Redmine を API 経由で操作する node-redmine
普段 Redmine を利用しているが、似たようなチケットをまとめて一括作成したり、チケット情報を抽出・整形したりしたい時に、GUI では限界があったので、何か良いやり方がないか調べてみた。
すると、Redmine も API が用意されており、JSON をぶん投げれば Issue の登録やら何やらができるみたいだった。
- 参考 : Rest api - Redmine
JSON を使うなら、シェルスクリプトで curl
したりするよりは、Node.js スクリプトで書いた方がオブジェクトとして扱いやすいかな…と思い、もう少し調べてみると、node-redmine という npm モジュールが公開されていた。
コードの中身を見ると、create_issue()
とか update_issue()
とかいったメソッドが用意されていて、内部で Redmine API 向けの URL に変換している、簡単な作り。でもコレがかなり助かる。
実際に使ってみよう。
目次
最もシンプルにチケット一覧を取得するまで
まずは適当な作業ディレクトリを作り、node-redmine をインストールしておく。
$ mkdir practice-redmine-api/ && cd $_
$ npm init -y
$ npm install -S node-redmine
$ touch list-issues.js
次に、list-issues.js
を以下のようにコーディングしていく。
const Redmine = require('node-redmine');
const hostName = 'http://my-redmine.com/'; // Redmine の URL
const config = {
apiKey: '【API キー】'
};
const redmine = new Redmine(hostName, config);
// Issue を5件取得する
redmine.issues({
limit: 5
}, (error, data) => {
if(error) throw error;
// JSON を2スペースで整形して表示する
data.issues.forEach((issue) => {
console.log(JSON.stringify(issue, null, ' '));
});
});
コレを実行すると以下のようになる。
$ node ./list-issues.js
{
"id": 99,
"project": {
"id": 1,
"name": "オレオレ Redmine"
},
// 中略……
"assigned_to": {
"id": 1,
"name": "Neo"
},
"subject": "あの問題を解決する",
"description": "h1. ほげほげ\r\nふがふが",
"start_date": "2018-01-01",
"due_date": "2018-12-31",
"created_on": "2018-01-01T00:00:00Z",
"updated_on": "2018-01-01T00:00:00Z"
}
{
// 2件目の Issue…
}
// 以下略…
こりゃ簡単だ!
API 認証部分を共通化する
Issue が取得できたので、Issue を登録したり更新したりする、別のスクリプトを書いてみようと思う。
ただその前に、先程のスクリプトの冒頭に書いた、API 認証部分を共通化しようと思う。
redmine-api-base.js
というファイルを作り、以下のように書く。
const Redmine = require('node-redmine');
const hostName = 'http://my-redmine.com/'; // Redmine の URL
const config = {
apiKey: '【API キー】'
};
const redmine = new Redmine(hostName, config);
module.exports = redmine;
先程の list-issues.js
は以下のように直す。
const redmine = require('./redmine-api-base');
redmine.issues({
limit: 5
}, (error, data) => { // 以下略…
このスクリプトのように1回しか使わないなら、イチイチ変数化しないで以下のように書いてしまっても良い。
require('./redmine-api-base').issues({
limit: 5
}, (error, data) => { // 以下略…
今後はこのノリで、やりたいことに合わせたスクリプトを作ってみる。
試してみた API
試しに使ってみた API は以下のとおり。callback
は、全て (error, data) => { }
という2つの仮引数を渡してくれる。
redmine.issues({ 【検索条件など】 }, callback)
redmine.get_issue_by_id(【Issue ID】, {}, callback)
redmine.create_issue({ 'issue': 【Issue オブジェクト】 }, callback)
redmine.update_issue(【Issue ID】, { 'issue': 【更新したいフィールドのみ書いた Issue オブジェクト】, callback)
redmine.get_user_by_id(【User ID】, {}, callback)
他にもあるので、ソースを見ながら使ってみよう。
複数チケットを一括登録する
複数のチケットを一括登録するには、API への POST 通信を順次実行するのが良いかと思う。色々試行錯誤して、以下のような bulk-create-issues.js
というスクリプトを作った。
const redmine = require('./redmine-api-base');
// 登録データの配列
const issues = [
{
'project_id' : 1, // プロジェクト ID
'tracker_id' : 10, // トラッカー ID
'subject' : 'ある課題 1', // チケット名
'description' : '説明', // 説明 : 改行は「\r\n\」で書ける
'assigned_to_id': 14, // 担当者 ID
'start_date' : '2018-05-01', // 開始日 : 文字列 'YYYY-MM-DD'
'due_date' : '2018-09-30' // 期日 : 文字列 'YYYY-MM-DD'
},
{
'project_id' : 1,
'tracker_id' : 10,
'subject' : 'ある課題 2',
'description' : '似たような説明',
'assigned_to_id': 18,
'start_date' : '2018-05-01',
'due_date' : '2018-09-30'
}
];
// 1件ずつ登録していく
issues.reduce((prevPromise, issue) => {
return prevPromise
.then(() => {
return new Promise((resolve, reject) => {
redmine.create_issue({
'issue': issue
}, (error, data) => {
if(error) {
console.error('登録失敗 : ', error);
return reject(error);
}
console.log('登録成功', data);
resolve();
});
});
});
}, Promise.resolve());
以前紹介した、配列データを直列で順次実行する Promise チェーンを作った。
実際は、登録データ (issues
) を作る方が大変。Redmine プロジェクトの設定に合わせて、色々指定しておかないといけないプロパティが多い。ココらへんは、既に作ってある Issue を issues()
か get_issue_by_id()
で取得してみて、「この項目はこの値にしておこう」というモノを控えておくと良い。
元データを Excel などで作ってあれば、CSV 形式で吐き出しておいて、CSV ファイルを読み込んだら JSON 形式の配列に変換する、という風にやれば良さそう。
以上
Redmine の一括操作もコレで楽チン!