Backlogでチケットを管理していて、Gitbucketをリポジトリとして使っている場合に
GitbucketへのcommitをBacklogのチケットに反映する方法
@colorrabbitさんのこの記事の焼き直しです
Backlog APIのv2に対応させています
必要な手順
- backlog apiを使う為のapi keyを取得
- LambdaとAPI Gatewayを設置
- gitbucket側のwebhookにbacklogを追加
- コミットメッセージにbacklogのチケットIDを含める
backlog apiを使う為のapi keyを取得
backlogに入り、個人設定 -> APIを開く
適当なAPIのメモを入力し「登録」をするとAPIキーが発行されるのでメモしておく
LambdaとAPI Gatewayを設置
Lambda設定
gitbucketのwebhook -> lambda -> backlog となるようにlambdaを構成。
まずaws consoleからLambdaに入り、Node.jsの6.10を選択、Blank Functionを選択
トリガーはとりあえず作らないで次へ
コードをバリバリ書く。
基本はgitbucketからcommit/push等でhookされた情報を受取り、
いい感じに加工してbacklogのチケットのコメントとして追加してやればOK。
なお、環境変数は以下の感じに定義している
書きなぐりのコードだけれど参考までに貼っておきます
console.log('--- Gitbucket to Backlog api start');
const response = {
statusCode: 200,
headers: {},
body: ""
};
const querystring = require('querystring');
const http = require('https');
const url = require('url');
const backlog_endpoint = process.env.BACKLOG_ENDPOINT;
const backlog_api_key = process.env.BACKLOG_API_KEY;
const project_id = process.env.PROJECT_ID;
const makePushMessage = (json) => {
return `''Git Push通知''\n\n ${pushMessage(json)}`;
};
const pushMessage = (json) => {
return `
Pushed Repository
|~Repository|${json.repository.full_name}|
|~Branch|${json.ref}|
|~Compare|[[view:${json.compare}]]|
`;
};
const makeCommitMessage = (commit) => {
return `\n${commitMessage(json)}`;
};
const commitMessage = (commit) => {
return `
|~Commit ID|${commit.id}|
|~Commit Message|${commit.message.replace(/\r?\n/g,"")}|
|~Commiter|${commit.committer.name}|
|~Source|[[view:${commit.url}]]|
`;
};
const getTicketId = (message) => {
const filtered = message.split(' ').filter((element, index, array) => {
return (element.includes(project_id));
});
return filtered[0];
};
const isFix = (message) => {
return (
message.includes('#fix') ||
message.includes('#fixes') ||
message.includes('#fixed')
);
};
const isClose = (message) => {
return (
message.includes('#close') ||
message.includes('#closes') ||
message.includes('#closed')
);
};
const makeCommitInfo = (commit) => {
return {
ticketId: getTicketId(commit.message),
isFix: isFix(commit.message),
isClose: isClose(commit.message),
commitMessage: commitMessage(commit)
};
};
const postComment = (ticketId, content) => {
return new Promise((resolve, reject) => {
const endpoint = backlog_endpoint + '/issues/' + ticketId + '/comments' + '?apiKey=' + backlog_api_key;
const req_opts = url.parse(endpoint);
req_opts.method = 'POST';
req_opts.headers = {'Content-Type': 'application/x-www-form-urlencoded'};
const req =
http.request(
req_opts,
(res) => {
if (res.statusCode === 200 || res.statusCode === 201) {
return resolve();
} else {
console.log('error, status: ' + res.statusCode);
res.on('data', (chunk) => {
console.log('BODY: ' + chunk);
});
return resolve();
}
}
)
;
req.on('error', (error) => {
console.log('probrem with request: ' + error.message);
return resolve();
});
const postData = querystring.stringify({
content: content,
notifiedUserId: [],
attachmentId: []
});
req.write(postData);
req.end();
});
};
exports.handler = (event, context, callback) => {
const pushMessage = makePushMessage(event);
const commits = ((event) => {
if (!event.commits) return undefined;
return event.commits.map((commit, index, array) => {
return makeCommitInfo(commit);
});
})(event);
if (!commits) return;
// sequential execute
commits.reduce((current, args) => {
return current.then(() => {
return postComment.apply(null, [args.ticketId, pushMessage + args.commitMessage]);
});
}, Promise.resolve());
callback(null, response);
};
なお、gitbucketのsettings -> webhookで適当にtestしてみるとgitbucketからの
payloadが表示されるのでそれをテストデータにしてLambdaを動かしていくと早い
API Gateway
以前の記事を参考に立てればOK
今のところgitbucket側からいい感じに認証キーを送る方法がわからなくて
API Gateway側は無認証で動かしている(良くないので対処検討中)
gitbucket側のwebhookにbacklogを追加
gitbucket -> 対象のリポジトリ -> Settings -> Service Hooks
を開き、Add webhookをクリック
payload URLにapi gatewayで作成したurlを指定
コミットメッセージにbacklogのチケットIDを含める
以下のようにしてcommit/pushすればbacklog側にコメントが飛ぶ
git commit -m 'add readme [backlogのチケットID]'
TODO
- 今はcommitだけを拾ったが、issueとかpull requestとかも拾っていきたい
- gitbucket -> API Gatewayの認証(最悪IPで絞る)
- ちゃんとPromiseの非同期していないので対処したい(array分逐次実行にしないと)