RUANN - X★mas Eve2 Live 2018 (2018年12月23日@新宿ReNY)

8月のライブに続いての参戦です。

今回は小4の次女と一緒に行きました。位置としては2段目の先頭から見たので、どうにかRUANNちゃんの顔は見えるといった感じでした。中途半端に前のほうだと、背が低いとまったく見えないと思うので、整理番号200番くらいとしてはベストポジションだったのかなと思います。

f:id:onozaty:20190102224421j:plain

「X★mas Eve2 Live」ということで、クリスマスにちなんだ歌で始まり、いつもどおりの歌声(力強い歌声が大好きです)とアコギ、ダンスを披露してくれました。洋楽のカバーも、毎回違う曲を入れてくるので、今回は何かなーってのがとても楽しみです。(Loving youすごく良かった)

(以降の写真は、MIMI.RUNNDY(@MRunndy)さんが撮影した写真を許可をもらって利用させていただいています。すばらしい写真をありがとうございます!)

そして観客に楽しんでもらおうと、新しいこととしてDTMを使ったり(The Chainsmokers の Don't Let Me Down をアレンジ)、エレキ(いつもはアコギのLOVE & HOPEで)もみせてくれました。

アンコールでは、会場のみんなでREADY TO GOを歌って、とても盛り上がりました。ライブで盛り上がる定番の曲になりそうです。

自分が楽しかったのは当然ですが、スタンディングだし大丈夫かな、、と思っていた小4の娘もライブを楽しんでくれていました。手渡しでオリジナルCDを受け取ったときには、とても恥ずかしそうにRUANNちゃんに話しかけていて、その後すごく喜んでました。心に残るライブになったのではと思います。ありがとうございました。

RUANNちゃんのことを知ったのが、次女がアコギでテイラースイフトのWe Are Never Ever Getting Back Togetherを弾くってことで、参考動画をYouTubeで探していたときに下記の動画を見つけたのがきっかけだったので、いつか一緒にライブ行きたいと思っていて、今回それが叶いました。

RUANN (大山琉杏)「We Are Never Ever Getting Back Together (Taylor Swift)」2016/04/24 鶴見緑地公園

一番行きたがっていた三女(まだ幼稚園児のため、今回は参加できず)も、来年は小学校あがるのでもしかしたら次は娘2人連れての参戦になるかもしれません。(6歳児にスタンディングは無理だと思うのですが、本人は行く気まんまん...)

メジャーデビューして作曲や作詞に有名な加わって、曲の雰囲気が変わってきたのではと思います(There's No Ending、READY TO GOの2曲)。アーティスト本人も、聴いてくれる人を楽しませようと、いろいろなことにチャレンジしながら幅を広げているので、今後どんな曲を聞かせてくれるのか、どんなライブを魅せてくれるのか、とても楽しみです。

セットリスト

  1. サンタが街にやってくる
  2. Whishy Christmas
  3. Perfect life
  4. I AM STANDING
  5. Pinky World
  6. LOVE & HOPE
  7. TETOTE
  8. GET THE GLORY
  9. Don't Let Me Down (The Chainsmokers)
  10. There’s nothing holdin’ me back (Shawn Mendes)
  11. Loving you (Minnie Riperton)
  12. I’m just walking without you
  13. There’s No Ending
  14. (アンコール) READY TO GO
  15. (アンコール) The beautiful girl is about u

CSVを読み込んでRedmineのカスタムフィールドを更新するツール(redmine-issue-updater)を作りました

(この記事は Redmine Advent Calendar 2018 - Adventar の16日目の記事です。)

Redmineのチケットを更新するツールです。CSVファイルを読み込んで、チケットを更新します。現在更新対象としているのは、カスタムフィールドのみとなります。

チケットIDだけでなく、カスタムフィールドをキーとして更新できます。というか、これがやれるツールが無かったので、今回作りました。(チケットIDをキーとするものばかりなので)

利用方法

Java(JDK8以上)がインストールされた環境で、下記コマンドでアプリケーションをビルドします。

gradlew shadowJar

build/libs/redmine-issue-updater-all.jarというファイルが出来上がります。

下記のコマンドで、アプリケーションを実行します。

java -jar build/libs/redmine-issue-updater-1.0.0-all.jar config.json issues.csv

第1引数が設定ファイル、第2引数が更新する情報が書かれたCSVファイルとなります。

実行すると、下記のように更新されたチケットの情報が出力されます。

Processing start...
#1 is updated.
#2 is updated.
#3 is updated.
Processing is completed. 3 issues were updated.

以下は設定ファイルの例です。

{
  "readmineUrl": "http://localhost",
  "apyKey": "20d0779f947c3c9a7248332a078ff458644ed73d",
  "csvEncoding": "UTF-8",
  "fields": [
    {
      "headerName": "#",
      "type": "ISSUE_ID",
      "primaryKey": true
    },
    {
      "headerName": "Field1",
      "type": "CUSTOM_FIELD",
      "customFieldId": 1,
      "primaryKey": false
    },
    {
      "headerName": "Field2",
      "type": "CUSTOM_FIELD",
      "customFieldId": 2,
      "primaryKey": false
    }
  ]
}

各項目の内容は下記の通りです。

  • readmineUrl : Redmineの接続先URL。
  • apyKey : RedmineのAPIアクセスキー。
  • csvEncoding : CSVファイルのエンコーディング。
  • fields : CSVの各フィールド情報。CSV内の全てのフィールドを記載する必要は無く、利用するものだけ書いてあれば良い。
    • headerName : CSV内のヘッダ名。
    • type : 種別。(ISSUE_ID または CUSTOM_FIELD)
    • customFieldId : カスタムフィールドのID。種別がCUSTOM_FIELDの場合に設定します。
    • primaryKey : プライマリーキーか。trueとなっているフィールドの情報を使って、更新対象のチケットを検索。

カスタムフィールドのIDは、管理者画面のカスタムフィールドの設定画面で、対象のカスタムフィールドを選択した際のURLで確認できます。 以下のような場合、カスタムフィールドのIDは1となります。

または、チケット作成、編集画面でカスタムフィールドの入力欄に振られたIDでも確認できます。以下のような場合、カスタムフィールドのIDは2となります。

<input type="text" name="issue[custom_field_values][2]" id="issue_custom_field_values_2" value="A" class="string_cf">

以下はCSVファイルの例です。

#,Subject,Field1,Field2,Field3
1,xxxx,A,a,C
2,yyyy,B,b,B
3,zzzz,C,c,A

設定ファイルとCSVファイルのサンプルは、sampleフォルダ配下にあります。

注意事項

  • Redmine の REST API を利用しますので、REST APIが有効になっている必要があります。
  • カスタムフィールドをキーとする場合、対象のカスタムフィールドの設定として「フィルタとして使用」がONとなっている必要があります。

Redmine: View customize plugin の v2.0.0 をリリースしました

View customize plugin の v2.0.0 をリリースしました。Redmine 4.0(Rails5)への対応版となります。

v2.0.0からインストール時にbundle installが必要となります。注意ください。

今回のバージョンから対応するRedmineが3.1.x以上となります。3.0.x以下の方は、v1.2.2をご利用ください。

Redmineにおけるチケットの単位について

(この記事は Redmine Advent Calendar 2018 - Adventar の7日目の記事です。)

Redmineを運用していると「チケットをどういう単位で切るか」というところに悩む人も多いのではと思います。

何が適しているかは、Redmineの使い方や、そのプロジェクトのフローなどによって異なってくるので、これが正解だ!というものは無いのですが、目安の一つとして「同時に複数人が担当者になってしまわないようにチケットを分ける」といった方法があります。

同時に複数人が担当になってしまうようなチケットの切り方だと、

  • そのチケットを誰が担当しているのかが曖昧になり、結果、放置されてしまう
  • 複数の人の作業状況を加味しなければならないので、ステータスや進捗が設定しづらくなる

といったことがおこり、結果的にチケットから状況がわかりずらくなります。

これを避けるためにも、同時に複数人が担当者とならないような形でチケットを切っていくと良いと思います。

例1:一つのチケットを同時に複数人で担当するような場合

例として、クライアントサイドとサーバサイドを別々の担当者で製造する場合を考えて見ます。

この場合、1機能ということでクライアントとサーバまとめて1チケットにしてしまうと、1チケットを同時に複数人が担当することとなり、先ほど述べたような問題がおこりかねません。

こういったときには、クライアントとサーバで別々のチケットとするのが良いでしょう。また、それぞれのチケットが一つの機能であることをわかりやすくするため、親子チケットにするとわかりやすいと思います。

  • 機能
    • 製造: サーバサイド
    • 製造: クライアントサイト

Redmineの親子チケットは、使い方さえ間違えなければ、とても強力な仕組みだと思います。

例2:一つのチケットがステータスによって別々の担当者となる場合

作業とレビューを1つのチケットで行う場合、ステータスによって担当者が切り替わっていくと思いますが、同時に複数人が担当になるわけではないので、こういった場合は1チケットで十分です。

あくまで、同時に複数人が担当者になる(=同時に作業をする)場合のみ、別チケットにすれば十分となります。

ただ、担当者の切り替え忘れには注意が必要です。View customizeを使えば、ステータスに応じて担当者を自動設定することも可能なので、それでカバーするのも良いと思います。(View customizeでの設定方法は、また別の記事で)

終わりに

この考えに基づくようになってから、チケットの構成で悩むことは少なくなりました。チケットの構成に悩む方のヒントになればと思います。

なお、途中でチケットの構成変えたくなったら、そこで変えればよいので、最初にきっちり決めなくても良いと思っています。最初からうまくいくかどうかなんて、いくら時間かけて考えてもわかりません。まずは試してみて、やりづらいと思ったら、変えていくといったことをお勧めします。(自分のチームでも何度も変えていきました)

ShortcutKey2URL(Firefox版)の 4.0.2 をリリースしました

4.0.2 を先ほどリリースしました。Firefoxのテーマによっては、ポップアップの背景色が白以外となってしまう問題の対処となります。

自分の手元では再現できなかったのですが、報告していただいた方に試してもらいながら解決しました。

REST APIを利用して複数の子チケットをまとめて作成する(Redmine View Customize Plugin)

先週の第15回redmine.tokyoで紹介したスクリプトです。

REST APIを使って複数の子チケットをまとめて作成します。

作業を子チケットに分割して運用しているようなところだと、かなりうれしいのではと思います。 例えば、親として機能開発があって、その下に設計、製造、テストみたいな子チケットを作るような場合、これで1クリックで定型的な子チケットが作れるようになります。

設定内容

  • Path pattern: .*
  • Insertion position: Bottom of issue detail
$(function() {

  var projectId = $('#issue_project_id').val();
  var trackerId = $('#issue_tracker_id').val();
  var subject = $('#issue_subject').val();
  var priorityId = $('#issue_priority_id').val();
  var parentIssueId =  ViewCustomize.context.issue.id;

  // 子チケットとして作成する情報
  var issueChildren = [
    {
      'issue': {
        'project_id': projectId,
        'tracker_id': trackerId,
        'subject': subject + ' - 子チケット1',
        'priority_id': priorityId,
        'parent_issue_id': parentIssueId
      }
    },
    {
      'issue': {
        'project_id': projectId,
        'tracker_id': trackerId,
        'subject': subject + ' - 子チケット2',
        'priority_id': priorityId,
        'parent_issue_id': parentIssueId
      }
    },
    {
      'issue': {
        'project_id': projectId,
        'tracker_id': trackerId,
        'subject': subject + ' - 子チケット3',
        'priority_id': priorityId,
        'parent_issue_id': parentIssueId
      }
    }
  ];

  var link = $('<a title="子チケットの一括作成" class="icon icon-add" href="#">子チケットの一括作成</a>');
  $('#issue_tree').before($('<p>').append(link));

  link.on('click', function() {

    if (!confirm('子チケットをまとめて作成します。よろしいですか。')) {
      return;
    }

    // チケット作成処理(非同期)を順次実行し、最後にリロード
    var defer = $.Deferred();
    var promise = defer.promise();

    for (var i = 0; i < issueChildren.length; i++) {
      promise = promise.then(createIssue(issueChildren[i]));
    }

    promise
      .done(function() {
        // 成功したらリロード
        location.reload();
      })
      .fail(function() {
        alert('失敗しました');
      });

    defer.resolve();
  });

  function createIssue(issue) {

    return function() {

      return $.ajax({
        type: 'POST',
        url: '/issues.json',
        headers: {
          'X-Redmine-API-Key': ViewCustomize.context.user.apiKey
        },
        // 作成時はレスポンスのコンテンツが無く、jsonだとエラーとなるのでtextにしておく
        dataType: 'text',
        contentType: 'application/json',
        data: JSON.stringify(issue)
      });

    };
  }
})

画面イメージ

f:id:onozaty:20181117232408g:plain

第15回 redmine.tokyo勉強会で発表してきました

第15回 redmine.tokyo にて、View customize のバージョン1.2.0について発表してきました。

資料はこちら。

www.slideshare.net

発表中に、View cutomizeを知っている人に手を上げてもらったのですが、7、8割くらいの人が手をあげてくれました。うれしくて、ちょっと涙がでました。

他の方の発表も、いろいろ盛りだくさんで面白かったです。また、Twitterなどでやり取りしていた方と会うことが出来たのも良かったです。(ご挨拶しようと思っていて、タイミング逃してしまった方もいるので、また次回に、、)

声をかけていただいて、こうやって参加して発表できて、とても良い1日になりました。スタッフの皆様、ありがとうございました。