DevOps | MISO https://alb-owned-https-576747877.ap-northeast-1.elb.amazonaws.com 未来を創造するITのミソ Tue, 20 Jun 2023 04:37:40 +0000 ja hourly 1 https://wordpress.org/?v=6.7.2 https://alb-owned-https-576747877.ap-northeast-1.elb.amazonaws.com/wp-content/uploads/2017/09/tdi_300-300-300x280.png DevOps | MISO https://alb-owned-https-576747877.ap-northeast-1.elb.amazonaws.com 32 32 AWS認定試験を6冠するための受験順と勉強法 https://alb-owned-https-576747877.ap-northeast-1.elb.amazonaws.com/aws-certification-study Mon, 23 Mar 2020 00:00:26 +0000 https://alb-owned-https-576747877.ap-northeast-1.elb.amazonaws.com/?p=9181 以前、以下の「AWS認定ソリューションアーキテクトプロフェッショナルの新試験に合格した話」という記事を書きました。 その最後に「DevOps試験も合格したいと思っています」と書きましたが、その後無事DevOpsエンジニア…

The post AWS認定試験を6冠するための受験順と勉強法 first appeared on MISO.]]>
以前、以下の「AWS認定ソリューションアーキテクトプロフェッショナルの新試験に合格した話」という記事を書きました。

その最後に「DevOps試験も合格したいと思っています」と書きましたが、その後無事DevOpsエンジニア試験に合格し、合計6つの試験に合格することが出来ました。AWS界隈では6冠というそうです。以下の図はAWS認定のページから引用させていただいた試験の図です。ちょうどこの灰色の部分にある試験全部に受かったことになります。

そこで、今までの経験を踏まえて、これからAWS6冠を目指している人向けに、役立ちそうなことを書いてみたいと思います。前回の記事と若干重なる内容もありますがご容赦ください。

試験を受験する順番

試験を受ける順番は、個人的には以下の一択ではないかと思います。

  1. クラウドプラクティショナー
    • AWSの超基本を問われる試験なので、一番最初に受けます。
  2. ソリューションアーキテクトアソシエイト(SAA)
    • アソシエイト試験3種の中で、教材が一番豊富に存在するため、勉強しやすい試験です。これを2番目に受けます。
  3. SysOps
    • SAAと試験範囲が被っている範囲が多いので、これを3番目に受けます。
  4. ソリューションアーキテクトプロフェッショナル(SAP)
    • AWS資格の中で最難関と言われている試験です。アソシエイト試験3種のうち、まだDeveloperを取得していませんが、SAPとDeveloper試験は出題傾向が全く違うので、気にせずこれを4番目に受けましょう。
  5. Developer
    • Developerは出題傾向が今までに受けた試験と全く異なります。なので、SAPに合格したからといってすぐに合格できる試験ではなく、またイチから勉強します。これを5番目に受けます。
  6. DevOpsエンジニア
    • DeveloperとSysOpsの上級に当たる試験です。これを受ける時にはSysOpsの試験範囲を忘れかけているかもしれないので、復習から始めましょう。SAPと同じプロフェッショナル試験だけあって、これも難関。しかしSAPよりは少し易しいと思います。これを最後に受けます。

各試験の詳細と勉強方法

それでは、順番にそれぞれの試験と勉強方法を見ていきましょう。

1.クラウドプラクティショナー

AWS初心者用の試験で、これが一番簡単です。覚えていれば解ける問題中心なので、とにかく暗記、暗記です。

AWSが無料トレーニングを公開しているので、まずこれを読みましょう。また、試験対策本を一冊買って読みましょう。「AWSとは何?」「AWSのいいところは?」「何ができて、何ができないの?」「責任分界点は?」「代表的なサービスとその特徴は?」等が必要な視点です。

合格したら、次の試験を受けましょう。

2.ソリューションアーキテクトアソシエイト(SAA)

試験合格のための教材が多いので、勉強しやすい、合格しやすい試験だと言えます。

試験対策本は数種出版されているので、自分に合う本を選び、何度も読みましょう。基礎的なサービス(EC2とかS3とかRDSとか)は触ってみると理解が深まるので、AWSアカウントを作成し、1年間の無料利用枠内で実際に使ってみましょう。あと、AWSのサンプル問題や模擬試験を解くことも忘れないようにしましょう。サンプル問題や模擬試験から出題されるケースもあるようです。

実はAWSの試験に合格すると、特典として「模擬試験を一度無料で受けられるバウチャー」が貰えます。クラウドプラクティショナーに合格しているのであれば、バウチャーを1つ持っているはずなので、それを使って模擬試験を受けましょう。模擬試験は何度受けても内容が変わらないので、一度受ければ十分です。模擬試験トークンはAWS training and certificationの「特典」から入手することができます。

試験の難易度については、クラウドプラクティショナー試験より上位の試験だけあり、暗記だけでは解けない問題となっております。しかしそれぞれのサービスの特徴を覚えていて、冷静に考えれば解ける問題ばかりです。

合格したら、すぐに次の試験を受けましょう。何故なら、SAAとSysOpsは試験範囲がかなり被っているのです。頭に今まで勉強したことが残っているうちにSysOpsにチャレンジしましょう。

3.SysOps

試験本で勉強するのに慣れきってしまった人はSysOpsの勉強がつらいと感じるかもしれません。このあたりから試験のための情報がガクッと減るためです。試験対策本がほとんどない!2020年1月現在、SysOps試験に対応している試験対策本が一冊あるのですが、これだけではちょっと足りないかなというのが本音です。(もちろん試験対策に役立つ本です。私は買いました。)しかし勉強しないとSysOps合格はできませんので、AWSのBlackBeltのサービス別資料を活用しましょう。これを読めばかなり得点力が上がります。というかBlackBeltはAWS試験を受けるのであれば必ず読みましょう。SysOpsとDeveloperはBlackBeltを読み込めば合格レベルに達します。

また、試験範囲のサービスの「よくある質問」にも目を通しておきましょう。絶対に試験に役立ちます。しかし、AWSのドキュメントはとにかく読みにくい。日本語訳がちょっと下手です。そんな時はキーワードでググって、たくさん出てくる技術ブログとか解説記事を読んだ方がいいと思います。

ドキュメントを読み漁った後は、問題を解く練習をしましょう。Udemyのコースを購入するのがいいと思います。有料ですが、頻繁に開催されるセール期間中は約半額になりますので、タイミングを見計らって買いましょう。また、コースによって質がかなり違うので、★の数やレビューを参照して高品質なものを選びましょう。★は4つ以上のものであれば安心です。

4.ソリューションアーキテクトプロフェッショナル(SAP)

ここでAWS試験の最難関、SAPを受けます。

SAPは本当に難しいです。大事な事なのでもう一度言います。SAPは本当に難しいです。詳細は以前私がSAPに合格した直後に書いたこちらの記事をご覧ください。

この試験は一度落ちたくらいで滅入ってはいけません。私の周りにSAPに一度で受かった人はいません。(どうやったらあの試験を一回で突破できるんでしょうね…?)何回か落ちるくらいの気持ちで試験に臨んで丁度良いと思います。

そうなると気になるのが受験料です。SAP試験の一回の受験料は3万円(プラス税)もするので、落ちるとお財布に大ダメージがいくこと必至。

そこで役に立つのが半額クーポンです。AWS認定試験に合格すると特典として、試験を半額で受けることができるクーポンが1枚発行されます。すでにクラウドプラクティショナー、SAA、SysOpsに合格しているのなら、半額クーポンを3枚持っているはずです。これをここで惜しみなく使いましょう。半額クーポンは模擬試験無料バウチャーと同じくAWS training and certificationの「特典」から入手することができます。見逃さないように!

5.Developer

普段の業務でCI/CDとか、Infrastracture as Codeとかに親しんでいる人には簡単かもしれませんが、そうでなければ苦戦すること確実なのがDeveloper試験。
いままでに試験に出たことがないサービスばかりが試験範囲になっていますので、気を引き締めて対策をしましょう。
勉強方法はSysOpsと同様で、BlackBeltと「よくある質問」の熟読、Udemyも活用しましょう。
SAPの試験をくぐり抜けてこれた人であれば「Developerは問題文短いし、聞かれていることは単純、楽勝!」と思えると思います。

6.DevOpsエンジニア

いよいよ専門知識を除くAWS試験の最後となるDevOpsエンジニアです。ここまで来たら後は分かると思います。DevOpsエンジニア試験は「DeveloperとSysOpsを合わせた試験範囲、SAPと同じ難易度」です。しかし、実際に受けてみた感じでは、SAPよりもDevOpsエンジニアの方が易しい印象です。問題文がSAPより短めだからでしょうか。試験範囲が狭いからでしょうか。(試験範囲が狭いというのは私の主観です。)
もうここまで来れたら大丈夫。今まで通り勉強して、受験して、そして合格しましょう。

以上が私が考える理想的なAWS資格取得方法です。

有効期限や更新は?――合格したその後

試験に合格したら、その日から3年間有効になります。つまり、3年経ったら失効します。失効する前に、再度試験を受けて合格すれば、延長されます。

アソシエイト試験とプロフェッショナル試験に合格している場合、プロフェッショナル試験に合格した段階でアソシエイト試験の有効期間が延長されます。つまり、SAAに合格してから1年後にSAPに受かったとします。そうするとSAPに合格した日から3年間、SAPの資格が有効になるのはもちろんですが、SAAの有効期間も同じく3年間延長されます。

DevOpsエンジニアの場合は下位試験がSysOpsとDeveloperなので、DevOpsエンジニアに合格すればSysOpsとDeveloperがどちらも3年間延長になります。

そして、クラウドプラクティショナーは、どのアソシエイト試験とプロフェッショナル試験に合格しても、その時点から3年間延長になります。

つまり、一度6冠したら、3年後にSAPとDevOpsエンジニアだけ再試験して合格すれば、残り4つも更新されます。6つの試験を全部受け直さなくていいのです。嬉しい…!

試験勉強から試験本番までに気をつけたこと

どの試験を受けるかに関係なく、私が心掛けたことを以下にまとめました。

  • 机に座った時に見えるところに目標を書いて貼りました。(SAP試験、8月までに合格!等。単純ですが、やる気が出ます。)
  • 勉強のために無理はせず、仕事で疲れた時とか体調が悪い時は休む。無理して仕事も勉強もダメになることがないよう気を付けました。
  • 快適な勉強環境を整えました。椅子は快適なものを使う。気が散らないよう、集中できる環境を整えました。
  • 間違えた問題や、忘れそうなことをまとめたノートを作り、まめに見直しました。試験直前には最初から最後まで見直し。かなり得点を上乗せすることができました。
  • 頭が疲れていない午前中に試験を受けました。頭がちゃんと回っている状態で試験を受ける作戦です。(その代わり、前日は早く寝る必要があります。)
  • 試験前には好きなものを食べました。お腹が空くと集中力がなくなるタイプなので、その対策です。気分が上がってノリノリで試験を受けることができました。単純ですね。
  • 協力してくれる家族にまめに感謝を伝え、たまにお土産を買って帰りました。意外と家族が気を遣ってくれてたりするので、ケアが必要です。

これからAWS試験を受けようとしてる方のお役に立てれば幸いです!

The post AWS認定試験を6冠するための受験順と勉強法 first appeared on MISO.]]>
Dockerで構築したRedmineとRocket.Chatを連携させてDevOpsっぽさを出す https://alb-owned-https-576747877.ap-northeast-1.elb.amazonaws.com/docker-redmine-rocket-chat Tue, 07 May 2019 00:00:51 +0000 https://alb-owned-https-576747877.ap-northeast-1.elb.amazonaws.com/?p=5305 はじめに 皆さんはバグ管理システムは何をお使いですか? 当社ではRedmineを使うケースがしばしばあります。Redmineはチケットが割り当てられたときなどに通知をメールで送信してくれますが、メールだとどこかスピード感…

The post Dockerで構築したRedmineとRocket.Chatを連携させてDevOpsっぽさを出す first appeared on MISO.]]>
はじめに

皆さんはバグ管理システムは何をお使いですか?

当社ではRedmineを使うケースがしばしばあります。Redmineはチケットが割り当てられたときなどに通知をメールで送信してくれますが、メールだとどこかスピード感に欠けると感じたことがあるのではないでしょうか。

昨今、「DevOps」という単語がトレンドとして上がってきていることもあってか、チャットを採用している開発チームが増えてきていますし、Redmineの通知もチャットを通じて送信してくれないかな、と感じることもあると思います。しかし、チャットを導入しようにも、セキュリティの都合などからクラウドサービスは採用できないというケースもあるでしょう。

そこで今回は、DockerによるRedmineとRocket.Chat(*1)の構築と、RedmineとRocket.Chatの連携の設定をしていきます(*2)。

*1 オープンソースソフトウェアのウェブチャットサーバ。インターネット上で提供されているSlackのようなチャットサービスを、プライベートな独自のプラットフォーム上で構築することができます。

*2 前提として、AWSのEC2インスタンス(CentOS)上に構築します。別環境の場合は適宜読み替える箇所が出てくると思いますが、ご了承ください。AWSマネジメントコンソールの画面は2019/02/26時点のものです。

CentOSにDockerでRedmineを構築する

それではまず、CentOSにDockerでRedmineを構築します。念の為インスタンスの作成から手順を載せておきます。

インスタンスの作成

1.AWSマネジメントコンソールにログインし、「EC2」→サイドメニューの「インスタンス」→「インスタンスの作成」の順に選択する。

2.「コミュニティ AMI」の「Cent OS」にチェックを入れ、検索窓に「CentOS 7.6.1810 x86_64 with cloud-init (HVM) – ami-00fff3eb6cfbbc19f」と入力し、出てきたAMIの「選択」をクリックする

 3.「インスタンスの詳細の設定」→「ストレージの追加」→「タグの追加」→「セキュリティグループの設定」を適宜行い、インスタンスを作成する

DockerによるRedmineのインストール

Tera Termにて、作成したインスタンスに接続して、Dockerのインストールと、DockerによるRedmineのインストールをします。
1.rootユーザに変更する

sudo su

2.Dockerをインストールする

yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce

3.起動時の設定をする

systemctl start docker
systemctl enable docker

4.docker-composeをインストールする

curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

5. SELinuxを無効にする。

vi /etc/sysconfig/selinux
setenforce 0

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
#SELINUX=enforcing
SELINUX=disabled
# SELINUXTYPE= can take one of three values:
#     targeted - Targeted processes are protected,
#     minimum - Modification of targeted policy. Only selected processes are protected.
#     mls - Multi Level Security protection.
SELINUXTYPE=targeted

6.Redmine用のディレクトリを作成し、docker-compose.ymlファイルを作成する

mkdir -p /var/www/redmine
cd /var/www/redmine
vi docker-compose.yml

version: '3.5'

services:
  redmine:
    image: redmine:passenger
    container_name: redmine
    ports:
      - 3000:3000
    environment:
      TZ: Asia/Tokyo
      REDMINE_DB_MYSQL: mysql
      REDMINE_DB_DATABASE: redmine
      REDMINE_DB_USERNAME: redmine
      REDMINE_DB_PASSWORD: redmine
      REDMINE_DB_ENCODING: utf8
    depends_on:
      - mysql
    restart: always
    volumes:
      - /var/www/redmine/files:/usr/src/redmine/files
      - /var/www/redmine/log:/usr/src/redmine/log
      - /var/www/redmine/plugins:/usr/src/redmine/plugins
      - /var/www/redmine/public/themes:/usr/src/redmine/public/themes

  mysql:
     image: mysql:5.7
     container_name: mysql
     restart: always
     environment:
       TZ: Asia/Tokyo
       MYSQL_ROOT_PASSWORD: devops
       MYSQL_DATABASE: redmine
       MYSQL_USER: redmine
       MYSQL_PASSWORD: redmine
     volumes:
       - mysql-data:/var/lib/mysql
     command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci

volumes:
  mysql-data:
    name: mysql-redmine

7.ユーザ権限を変更する

sudo gpasswd -a $USER docker
sudo systemctl restart docker
exit
sudo su -
cd /var/www/redmine

8.docker-composeでRedmineを立ち上げる

docker-compose up -d
docker ps

9.RedmineとMySQLの設定をする

docker exec redmine bundle exec rake redmine:load_default_data RAILS_ENV=production REDMINE_LANG=ja
docker exec -it mysql mysql_config_editor set --host=localhost --user=redmine --password

10.下記URLにアクセスし、Redmineのホーム画面が表示されることを確認する
 http://[インスタンスのパブリックIPアドレス]:3000/

Rocket.Chatとの連携プラグインのインストール

次に、Rocket.Chatとの連携プラグインをインストールします。
1.必要なライブラリをインストールする

docker exec redmine gem install 'slim-rails'
docker exec redmine gem install 'validate_url'

2.Chatとの連携プラグインをインストールする

docker exec redmine git clone git://github.com/alphanodes/redmine_messenger.git plugins/redmine_messenger
docker exec redmine bundle exec rake redmine:plugins:migrate RAILS_ENV=production

3.コンテナを再起動する

docker restart redmine

4.Redmineの管理者ユーザでログインし、ヘッダーメニューの「管理」→「プラグイン」にアクセスし、「Redmine Messenger」プラグインが表示されていることを確認する
 ※管理者ユーザは最初、下記情報でログインすることができます。
  ユーザID : admin
  パスワード : admin

CentOSにDockerでRocket.Chatを構築する

次に別のCentOSにDockerでRocket.Chatを構築します。
CentOSのインスタンス作成手順はRedmineのものとほぼ(追加したタグ「Name」の値以外)同じなので、割愛します。

DockerによるRocket.Chatのインストール

Tera Termにて、作成したインスタンスに接続して、Dockerのインストールと、DockerによるRocket.Chatのインストールをします。
1.rootユーザに変更する

sudo su

2.Dockerをインストールする

yum install -y yum-utils
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y docker-ce

3.起動時の設定をする

systemctl start docker
systemctl enable docker

4.docker-composeをインストールする

curl -L https://github.com/docker/compose/releases/download/1.23.2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

5.MongoDBのコンテナイメージを取得する

docker pull mongo

6.Rocket.Chatのコンテナイメージを取得する

docker pull rocketchat/rocket.chat

7.Rocket.Chat用のディレクトリを作成し、docker-compose.ymlファイルを作成する

mkdir -p /var/www/rocket.chat/data/runtime/db
mkdir -p /var/www/rocket.chat/data/dump
cd /var/www/rocket.chat
vi docker-compose.yml

version: '3'

services:
  db:
    image: mongo:latest
    volumes:
     - ./data/runtime/db:/data/db
     - ./data/dump:/dump
    command: mongod --smallfiles

  rocketchat:
    image: rocketchat/rocket.chat:latest
    environment:
      MONGO_URL: mongodb://db:27017/rocketchat
      ROOT_URL: http://localhost:3000
      Accounts_UseDNSDomainCheck: 1
    links:
      - db:db
    volumes:
      - ./uploads:/app/uploads
    depends_on:
      - db
    ports:
      - 3000:3000

8.ユーザ権限を変更する

sudo gpasswd -a $USER docker
sudo systemctl restart docker
exit
sudo su -
cd /var/www/rocket.chat

9.docker-composeでRocket.Chatを立ち上げる

docker-compose up -d
docker ps

10.下記URLにアクセスし、Rocket.Chatのセットアップウィザード画面が表示されることを確認する
 ※セットアップウィザード画面は初期表示時のみで、それ以外の場合はホーム画面が表示される
 http://[インスタンスのパブリックIPアドレス]:3000/

Rocket.Chatの初期設定をする

1.下記の通りに管理者情報を入力し、「次へ」をクリックする
 名前      : 任意の名前
 ユーザ名    : [姓]-[名] ※姓と名は先頭のみ大文字のアルファベット
 組織の電子メール: 任意のメールアドレス
 パスワード   : 任意のパスワード

2.組織情報はスキップできるので、今回はそのまま「次へ」をクリックする
 ※任意で設定してください。

3.サーバ情報もスキップできるので、今回はそのまま「次へ」をクリックする
 ※任意で設定してください。

4.今回は、サーバーを登録する項目で「次を自分で実施し、スタンドアローン利用する」を選択し、「次へ」をクリックする

5.「ワークスペースを開く」をクリックする

6.Rocket.Chatのユーザホーム画面が表示されることを確認する

RedmineとRocket.Chatの連携設定をする

以上でインストールが完了したので、ついにRedmineとRocket.Chatの連携設定をします。

Rocket.Chatの設定

1.サイドメニューの[新しいチャンネルを作成]をクリックする

2.下記の通りにチャンネル情報を入力し、「作成」をクリック
 プライベートグループ : 任意(デフォルトはオン)
 読み取り専用チャンネル: デフォルト
 放送チャンネル    : デフォルト
 チャンネル名     : 任意
 ユーザを招待     : 任意(自分以外に招待したい人を追加する。後で追加することもできる。)

3.チャンネルが作成されていることを確認する

4.サイドメニューの「オプション」→「管理」→「サービス連携」の順にクリックする

5.「新しいサービス連携」をクリックする

6.「着信WebHook」をクリックする

7.下記の通りに項目を設定し、「変更を保存」をクリックする
 有効       : 「はい」を選択
 名前(オプション): 任意の名前
 投稿先チャンネル : 投稿先のチャンネルを指定
 ※上記以外はデフォルトでもOKです。

8.「WebHook URL」をコピーする

Redmineの設定

1.ヘッダーメニューの「管理」→「プラグイン」の順にクリックし、「Redmine Messenger」の「設定」をクリックする
 ※ここで設定した内容が、各Redmine上のプロジェクトでデフォルトとなります。

2.下記の通りに項目を設定し、「適用」をクリックする
 メッセンジャーのURL    : コピーしたWebHook URL(ホスト名がlocalhostになっている場合は、適宜置き換える)
 メッセンジャーのチャンネル : 通知先のRocket.Chatのチャンネル名
 ウォッチャーを表示する   : チェックを入れる(有効にする)
 ※上記以外はデフォルトでもOKです。

動作確認をする

動作確認のため、Redmineでプロジェクトとチケットを作成してみます。

Rocket.Chatを見てみると、作成したチャンネルに投稿が来ている!


しかし、少し味気ないような気がします。せめて担当者やウォッチャーにメンション(通知)を飛ばしたいですね。ということで、スクリプトを少しいじってみましょう。

Redmine Messengerで担当者とウォッチャーに通知が来るようにカスタマイズする

Redmine Adminユーザだけではわかりづらいので、RedmineとRocket.Chatにそれぞれ下記のユーザを追加しました。

【Redmine】
 1人目
  ログインID: yamauchi
  名    : Kentaro
  姓    : Yamauchi
 2人目
  ログインID: mirai
  名    : Sou
  姓    : Mirai

【Rocket.Chat】
 1人目
  名前  : 未来 創
  ユーザ名: Mirai-Sou

 

Redmineの設定の変更

メンションを送る際にRedmineが送信する名前の情報がデフォルトだと「名 姓」になっているので、変更します。
「名 姓」のままがいい場合はRocket.Chatのユーザ名を「名-姓」にすれば問題なく設定できます。
1.ヘッダーメニューの「管理」→「設定」→「表示」タブにアクセスし、下記項目の設定を変更し、「保存」をクリックする
 デフォルト言語  : 「Japanese(日本語)」
 ユーザ名の表示形式: 「姓 名」

Redmine Messengerのカスタマイズ

Redmine Messengerはチケットの更新時などにウォッチャーを送信しないようになっているようです。そこで、Redmine Messengerのソースコード(Ruby)を少しカスタマイズします。
1.「/usr/src/redmine/plugins/redmine_messenger/lib/redmine_messenger/patches/issue_patch.rb」をコンテナ内からホストにコピーしてくる

docker cp redmine:/usr/src/redmine/plugins/redmine_messenger/lib/redmine_messenger/patches/issue_patch.rb issue_patch.rb

2.ホストで「issue_patch.rb」を編集

vi issue_patch.rb

module RedmineMessenger
  module Patches
    module IssuePatch
      def self.included(base)
        base.send(:include, InstanceMethods)
        base.class_eval do
          after_create :send_messenger_create
          after_update :send_messenger_update
        end
      end

      module InstanceMethods
        def send_messenger_create
          channels = Messenger.channels_for_project project
          url = Messenger.url_for_project project

          return unless channels.present? && url
          return if is_private? && !Messenger.setting_for_project(project, :post_private_issues)

          set_language_if_valid Setting.default_language

          attachment = {}
          if description.present? && Messenger.setting_for_project(project, :new_include_description)
            attachment[:text] = Messenger.markup_format(description)
          end
          attachment[:fields] = [{ title: I18n.t(:field_status),
                                   value: ERB::Util.html_escape(status.to_s),
                                   short: true },
                                 { title: I18n.t(:field_priority),
                                   value: ERB::Util.html_escape(priority.to_s),
                                   short: true }]
          if assigned_to.present?
            attachment[:fields] << { title: I18n.t(:field_assigned_to),
                                     value: ERB::Util.html_escape(assigned_to.to_s),
                                     short: true }
          end

          if RedmineMessenger.setting?(:display_watchers) && watcher_users.count > 0
            attachment[:fields] << {
              title: I18n.t(:field_watcher),
              value: ERB::Util.html_escape(watcher_users.join(', ')),
              short: true
            }
          end

          Messenger.speak(l(:label_messenger_issue_created,
                            project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
                            url: send_messenger_mention_url(project, description),
                            user: author),
                          channels, url, attachment: attachment, project: project)
        end

        def send_messenger_update
          return if current_journal.nil?

          channels = Messenger.channels_for_project project
          url = Messenger.url_for_project project

          return unless channels.present? && url && Messenger.setting_for_project(project, :post_updates)
          return if is_private? && !Messenger.setting_for_project(project, :post_private_issues)
          return if current_journal.private_notes? && !Messenger.setting_for_project(project, :post_private_notes)

          set_language_if_valid Setting.default_language

          attachment = {}
          if current_journal.notes.present? && Messenger.setting_for_project(project, :updated_include_description)
            attachment[:text] = Messenger.markup_format(current_journal.notes)
          end

          fields = current_journal.details.map { |d| Messenger.detail_to_field d }
          if status_id != status_id_was
            fields << { title: I18n.t(:field_status),
                        value: ERB::Util.html_escape(status.to_s),
                        short: true }
          end
          if priority_id != priority_id_was
            fields << { title: I18n.t(:field_priority),
                        value: ERB::Util.html_escape(priority.to_s),
                        short: true }
          end
          if assigned_to.present?
            fields << { title: I18n.t(:field_assigned_to),
                        value: ERB::Util.html_escape(assigned_to.to_s),
                        short: true }
          end
          attachment[:fields] = fields if fields.any?

          # 20190204 Yamauchi added start
          if RedmineMessenger.setting?(:display_watchers) && watcher_users.count > 0
            attachment[:fields] << {
              title: I18n.t(:field_watcher),
              value: ERB::Util.html_escape(watcher_users.join(', ')),
              short: true
            }
          end
          # 20190204 Yamauchi added end

          Messenger.speak(l(:label_messenger_issue_updated,
                            project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
                            url: send_messenger_mention_url(project, current_journal.notes),
                            user: current_journal.user),
                          channels, url, attachment: attachment, project: project)
        end

        private

        def send_messenger_mention_url(project, text)
          mention_to = ''
          if Messenger.setting_for_project(project, :auto_mentions) ||
             Messenger.textfield_for_project(project, :default_mentions).present?
            mention_to = Messenger.mentions(project, text)
          end
          "<#{Messenger.object_url(self)}|#{ERB::Util.html_escape(self)}>#{mention_to}"
        end
      end
    end
  end
end

3.ホストからコンテナ内に「issue_patch.rb」をコピー

docker cp issue_patch.rb redmine:/usr/src/redmine/plugins/redmine_messenger/lib/redmine_messenger/patches/issue_patch.rb

4.コンテナを再起動する

docker restart redmine

Rocket.Chatのカスタムスクリプト

最後に、Rocket.Chat側に送信されたメッセージを通知させるようにカスタマイズします。
1.サイドメニューの「オプション」→「管理」→「サービス連携」の順にクリックする
2.先程作成した「着信WebHook – [任意の名前]」をクリックする

3.下記の通りに項目を設定し、「変更を保存」をクリックする
 スクリプトを有効にする: はい
 Script: 次の内容

class Script {
  /**
   * @params {object} request
   */
  process_incoming_request({ request }) {

    var responseText = request.content.text;
    var fields = request.content.attachments[0].fields;

    // 担当者をチャット向けに変換
    var assignedField = fields.filter(function(value, index) {
      return value.title == "担当者"
    });
    if (assignedField.length != 0) {
      var assignedValue = assignedField[0].value;
      responseText += "\n担当者: @" + assignedValue.split(" ").join("-");
    }

    // ウォッチャーをチャット向けに変換
    var watcherField = fields.filter(function(value, index) {
      return value.title == "ウォッチャー"
    });

    if (watcherField.length != 0) {
      responseText += "\nウォッチャー: ";
      var watchers = watcherField[0].value.split(", ");
      watchers.forEach(function(value, index, array) {     
        responseText += "@" + value.split(" ").join("-");

        if (index != array.length - 1) {
          responseText += ", "
        }
      });
    }

    // メッセージを設定
    request.content.text = responseText;

    return {
      content : request.content
    };
  }
}

 

動作確認をする

再度動作確認のため、Redmineでチケットの更新をしてみます。

Rocket.Chatを見てみると、作成したチャンネルに今度は通知が来ている!デスクトップ通知も来てほしかったのですが、証明書がない場合はChromeだとブロックされてしまうようです。Firefoxやデスクトップアプリの場合は、デスクトップ通知も問題なく来ました。担当者とウォッチャーにメンションが飛んでいることも確認できました!

 

ちなみに、Rocket.Chatでは、自分宛てにメンションがついている投稿だけを表示する機能があるので、埋もれても問題なく表示することができます。

おわりに

いかがでしたでしょうか。今回はRedmineとRocket.Chatの構築と連携の設定に加えて、少しプラグインをカスタマイズしてみました。RedmineのプラグインはRuby、Rocket.ChatのカスタムスクリプトはJavaScript(Meteor)で書くことができるので、比較的ネットでも記事を見つけやすく、意外と簡単にカスタマイズできると思います。複数環境を用意する場合も、docker-compose.ymlがあれば構築は簡単ですし、Dockerイメージファイルを作成すれば環境の複製も比較的容易になります。今後は、これらの環境の構築や連携の設定などを自動化し、GUIベースで簡単に環境構築できるようにしていきたいと考えています。

The post Dockerで構築したRedmineとRocket.Chatを連携させてDevOpsっぽさを出す first appeared on MISO.]]>