やる気パルスが回復するアニソン

40代のおっさんなので、新しいのは知りません。リンクは歌詞。

機動戦士ガンダム0083-STARDUST MEMORY-

THE WINNER
THE WINNER

銀河鉄道999

THE GALAXY EXPRESS 999
THE GALAXY EXPRESS 999

キン肉マン II世

愛のマッスル
愛のマッスル

真(チェンジ!!)ゲッターロボ 世界最後の日

今がその時だ
今がその時だ

六神合体ゴットマーズ

愛の金字塔
愛の金字塔


う。面倒になってきた。アニソンのリスト作るサービスくらいあってもよさそうなんだが…。

Mob Programming の体験ができる/事例発表があるイベント

気が向いたら更新。

これから

体験できる

事例発表

終わったもの

Mob Programming のエントリまとめ (リンクだけ)

いちいち探すの面倒なので、まとめておこう。 ひとまずリンクだけ。

(なんだろ?)

動画

やってみた

やってみた @ Agile Japan 2017

やってみた @ DevLove関西

ツール

【デンパ】 人間の業を肯定し、得体のしれないモチベーションを使ってアジャイルと付き合う

Joy,Inc.の強烈でまっすぐな「たーのしー!!」と、インフルエンザウィルス、けものフレンズに脳みそがやられた結果、貯めに貯め込んだ色んなものがスパークしまくって、いろいろつながったらしく、ずーっと追いかけてた答えみたいなものが出てきたので、忘れないために書いておく。

超個人的なものなので、適用範囲は狭い。というか、オレ専用。 傍流 of 傍流。光と闇のはざま。フツーの人は来ちゃいけないところのハズ。

後、いくつかの少ない経験と所詮本質の掴めないニワカが集めた情報から導き出された理屈なので、これでいいのか良く分かんない。 ついでに、ここに書いてるストーリ通りに物事が動いたかというと、かなり怪しい。自分の理屈のために事実を捻じ曲げてることは十分にありえる。記憶の改ざんなんてラクショーだもんね。

まぁ、こんなこと考える必要があるのはオレだけだし、すがるものも他に見つからないから、これを使って実験することにする。

スッキリしたこと

大きく2つ。これを続ければ、オレはうまくアジャイルと付き合える(ハズだ)。

  • 良く分かんないモチベーションを大事にする
  • 人間の業を肯定し、それを使って、人の役に立つロールを見つける

良く分かんないモチベーションを大事にする

続けるためにはモチベーションが必要だ。

ただ、オレには使命感みたいなのがない。会社が、組織が、お客様が。とか、そういうのがない。 危機感もない。かなりのんびりしている。あとで大事になって慌てるタイプだ。できないやつの典型。

どっちもない人はどうすればいいんだろう? オレは、良く分かんないモチベーションを使うことにした。なんかわかんないけど、夢中でやっちゃうやつ。 自分の中の理屈はわからないんけど、感じてることは分かる「たのしー」「すげー」「さすがー」

  • パイプライン作るのたのしー!!
  • ツール使ったら、こんなに簡単になるんだ、すげー!!
  • 達人ってこんな本読んでるんだ、さすがー!!

そういうの。(ちょっと強引?)

実は最後のは説明できる。達人に憧れるけど、近づけないので、せめて同じものに触れようとしてるのだ。涙ぐましい。 それやる時間があるなら、スキルを身に着ける訓練して、達人に近づけばいいんだけど、なにせ、オレなので、そんなことはしない。 しても続かない。ここに業がある。

業の話は置いといて、まぁそういう原初的な感情を使ってモチベーションを上げて、続けることにした。 これにはアップダウンが起きるという副作用があるんだけど、そこは人間だし仕方ないよねーってことにしてフタをする。 とあるマンガによれば、たゆまぬ鍛錬により「エンドルフィンどばどば」を常態化させることができるらしいので、そっちに行くのもありかもしれない。

人間の業を肯定し、それを使って、人の役に立てるロールを見つける

アジャイルは達人のノウハウが凝縮されている。これでもかってくらいギトギトに。 奴らは、マネジメント、エンジニアリング、マインドセット全方向で攻めてくる。さすが達人だ。逃げ場は用意されてない。

一方、オレは弱い人間だ。「気が散りやすい」「自分を中心に考える」「思慮が浅い」「苦手なことは後回し」「続けるの苦手」「危機感知能力が低い」辺りは標準装備。 売上? KPI? 何それ? 自分がやってることすら、意図を説明するのに一苦労、っていうより、上手く説明ができない。 説明できないから企画も立てられない、なので、必然的に予算も取れない。いつもスカンピンだ。(まぁそれで訓練されるものもあるんだけど)

こういう人間がアジャイラーを目指すと、間違いなく挫折する。能力を獲得するために必要な鍛錬ができないからだ。やってるうちに飽きちゃうし。

最初は真面目にアジャイルなエンジニアになろうともがいてたんだけど、苦しいばっかで旨みがない。 それでも何かになりたくて、あっちこっちうろついてたんだけど、まぁ、訓練できない人は何にもなれない。 ひたすら情報だけが貯まっていくだけの日々。しかし、なれない人には使う機会もない。

バッドエンドまっしぐらだったんだけど、45歳になってとある教育を受けたとき、このまま情報ため込んで爆死はちと寂しいと考えるようになり、 長期間に渡り情シスさんのDevOpsの取り組みを手伝い、また、自分でも色んな助けを借りながら社内勉強会を長く続けてきたこと、 さらに会社でも共創というキーワードが流行り始め、アジャイルに興味がある人が増えてきたのもあって、オレのポジションがなんとなーく分かってきた。

自分自身がアジャイラーになることは一旦諦めて、そっちに向かう人に、自分が持ってる情報をパスする役 になればいいのである。

ロール「情報を渡す人」として自分を見れば、

  • 「気が散りやすい」は、「いろんなところに足を運び、情報を取って来る」
  • 「自分を中心に考える」は、「いろんなものを自分のこととして考えられるので、情報にオレなりの解釈を1つ加えて出すことができる (つっても無駄なのも多いんだろうけど)」
  • 「思慮が浅い」は、「ざっくり合えばいいやくらいで、情報をライトに送れる」
    • 相手にとって迷惑かどうかはオレにはわからんないのだ。マジ。当たらないと思ったことが当たったりするし、その逆もあるしで。

と、弱みがプラスに変わるのだ。 強引? だって、そう思い込まなきゃ、この先やってらんないだもん。 オレが動ければいいんだから、自分の脳みそをある程度の騙せる理屈と体験さえあればいいのだ。(この辺が自分中心)

そうそう。体験は大事。 社内でオレの雑な情報の渡し方でも喜んでくれる、返事を返してくれる人と出会えたのは、非常にありがたかった。

隣の人は聞き上手で、さらに、水どうと、デイリーポータルZが好きという、オレにとってヒジョーに話しやすい人だったのである。そーとー話聞いてもらった。マジ感謝。

コミュニティはチャットで会話をするようになったのがデカい。オレの思考の垂れ流しをスルーしてくれる人たちで助かった。(もちろん返事もしてもらった。沢山)

そういう人たちに情報を何回も渡すことで、こっちもだんだん情報の渡し方に慣れていくことができた。 感謝。感謝。感謝のメッセージ1万本とか言ったら怒られそうだし、オレもそんなに出せない。

情シスさんとは2年という、オレにとっては非常に長い期間お付き合いをさせていただいている。 長いから、たまに、前に出した情報が、時間が経った後にヒットするなんてことがある。 そういう経験を通じて、以前より待つこともできるようになった。犬でも「待て」ができるのに、なぜオレにはできなかったのか。犬以下。

まとめ

そんなこんなで、色んな意味で弱い人間のオレが、その業を克服することなく、なんとかアジャイルと付き合う方法は、

  • 良く分かんないモチベーションを大事にする
    • 「使命感、危機感」を感じないのを負い目にせず、「たのしー」「すげー」「さすがー」で動く
  • 人間の業を肯定し、それを使って、人の役に立つロールを見つける
    • オレのダラシない部分を「情報を渡す人」に必要な要素に変換して、少しでもいいので人の役に立つことをする

この辺らしい。

ただ、この先、このロールだけで生きていけるのか? というとちと疑問がある。 作る人には未練もあるし、何かしら方法を探したいなー。なー。なー。 言うだけならタダだし、言うとなれるっていう話もあるから、言うだけ言っておこうっと。

でも、みうらじゅんまで長じれば…あるいは…。でもあの人のスキルセットって、サブカルの中でもかなりレアらしいからなぁ。

構築に役立ったと思うもの

考え方やスタイル?

芯を外してるものも多い気がするけども。角さん、牛尾さん、川口さんにはいつも感謝しておりますです!!!

追いかけすぎて、ストーカーと化しているんじゃないか…と心配になるレベル…。ばれてるかなぁ。ばれてるだろうなぁ。

後、ここ最近の良く分からんデンパなツィートに反応していただいた皆様ありがとうございました。

練習

練習嫌いなので、知らず知らずのうちに練習させられてたんだと思う。

  • 分ける
    • 全部でまるっとまとめない
      • できてるところ、できてないところ
      • 合意できるところ、できないところ
      • イイところ、悪いところ
    • 褒めるのに使うし、アジャイルやる人探すのにもいるし、とにかくこれないと辛い
  • 捨てる
    • 全部自分でやりたい
      • 昼の勉強会を長く続けるためには、人の力を借りる必要があったので、自分でやりたいは捨てないとアカン
      • 捨てたおかげで、何が大事なんだっけ、オレ? を考えられるようになった
  • 説明する
    • 全部説明しなくていい
      • ポインタさえ示しておけば、ピンときたとこ抜き出すくらいのライトさでもヒットする人はいる
      • 逆にヒットしない人に、オレは上手に説明できないだろうから、そこはご縁がなかったことにして一旦忘れる
    • ピンと来たところを引用する via 川口 恭伸さん
      • オレが作った変な要約を渡すよりよっぽど良い
  • 待つ
    • 情報を渡した後、しばらくたってから様子を見にいく (今もせっかちなとこあるけど)
      • 情報渡してすぐ反応がないからといってダメだーって言ってると、せっかく出てきた芽が見のがしてしまう
      • しばらくたって芽が出ることもたまにあるから、渡した後忘れてしまうくらいでいい

オレを勘違いしてくれた皆様

最重要。オレという人間を勘違いして、色んなところで使おうとしてくれた/してくれてる人がいる。 名前出すと怒られそうなので、こういう感じでお茶を濁しておくけど、感謝しとりますー!!!

…って、実は仕掛けられてて、今も観察の対象だったりする??

Visual Studio Team Services と Rocket.Chat の連携 (プルリクエストだけ)

平間ソンでできたこと1つ目。

背景

  • 開発チームはVSTSを使っている
  • ちょっとした連絡にはRocket.Chatを使っている
  • VSTSでプルリクエストを作った後、いちいち手動でRocket.Chatに連絡しているので、面倒
  • Rocket.Chatのサーバは 社内イントラ にある

やりたいこと

  • VSTSでプルリクエストを作ったら、自動でRocket.Chatにメッセージを投げるようにしたい

実現案

a. VSTSのRoom使う (Service Hooks)

多分一番素直なやり方。今回は使えないけど。

連携方法

Roomを開いて、Manage Events -> Pull requestsを選択。 出てくるダイアログで、プロジェクトとリポジトリ、変更した人(チャットメンバーまたは誰でも)を選べば通知ができる。(チェックボックスをONにするのを忘れずに)

詳しくは https://msdn.microsoft.com/en-us/library/vs/alm/work/productivity/collaborate-in-a-team-room あたりを見ればわかる。

対応しているイベント

作成と、ステータス変更。タイトルなどの修正は対応してない。

連携イメージ

f:id:couger:20160503152620p:plain

b. Service Hooksを使う

Service Hooksについて

Service Hooksを使うと、外部ツールと連携ができる。 https://www.visualstudio.com/en-us/get-started/integrate/service-hooks/webhooks-and-vso-vs

連携可能なツール

一覧がどこにあるのかわからなかった。 https://www.visualstudio.com/en-us/integrate/explore/explore-vso-vsi.aspx で紹介されているアイコンでなんとなくわかるのでよし。

Rocket.Chatとの連携

Rocket.ChatのIncomming WebHookはSlackと互換性があるので、Service Hooksの設定で連携先にSlackを選択、URLにRocket.ChatのIncomming WebHookのURLを設定すれば良い。 ただし、https必須。

Rocket.Chatをhttps

独自ドメインも証明書も持ってないので、AzureのWeb Appsでも使おうかと思ったけど、はまりそうだったので、Herokuを利用。Herokuだと本家リポジトリにあるリンクから一発でデプロイできる。

https://github.com/RocketChat/Rocket.Chat

でも、ここまでするなら素直にSlack使ったほうがいいよなぁ...と思ったことは内緒にしておく。

連携方法

Rocket.Chat

管理 -> サービス連携 -> 新しいサービス連携 -> Incomming WebHookで作成。 作成したら、Webhook URLに表示されているURLをメモしておく。

VSTS

プロジェクトの設定 -> Service Hooks -> "+"ボタンでHookを追加する。

  • Serivice: Slack
  • Trigger: Pull request created
  • Action:
    • Slack Webhook URL: (Rocket.Chatで作成したWebhookのURLを設定)

Trigger "Pull request updated" についても同じようにHookを作る。

f:id:couger:20160503152221p:plain

対応しているイベント

Roomと同じ。 作成と、ステータス変更。タイトルなどの修正は対応してない。

連携イメージ

f:id:couger:20160503152822p:plain

URLのリンクがうまくいってないのは、SlackとRocket.Chatで書式が違うから。(だと思う)
Incommig WebHookの設定にScriptという項目があるので、そこでごにょごにょすれば直るかもしれない?

c. REST APIを使う

背景の Rocket.Chatのサーバは社内イントラにある のおかげで、a,b案は使えない。 ので、結局ここに落ち着くはず。

HubotでVSTSREST APIを叩き、拾ってきた情報をRocket.Chatに流す。

HubotとRocket.Chatの連携

Rocket.ChatもRocket.Chat連携用のHubotもコンテナが用意されてるのでそれを使うと楽。 RocketChat/hubot-rocketchat: Rocket.Chat Hubot adapter

VSTSREST API

Pull Requestに関しては以下のページを参照。 Git Pull Requests | REST API Reference for Visual Studio Team Services and Team Foundation Server

APIに必要な認証

Basicのみ対応。
GitHubにあるRailsアプリをVSTSでビルドして、Azureにデプロイする with Docker - cougerの日記 を見て、Alternate authentication credentials を有効にする。
Personal Access Tokenに対応しているので、そちらを使おう。ScopeはCode(Read)のみでOKっぽい。
指定する場合はこんな感じになる。ユーザ名はなんでもOK、パスワードにPersonal Access Tokenを指定すれば良いようだ。

http://[なんでもOK]:[Personal Access Token]@hogefuga.visualstudio.com/....

Personal Access Tokenの有効期間は180日なのでご注意をば。設定で1年間にすることも可能。

Personal Access Token、有効期間について @kkamegawa さんにアドバイスもらいました。ありがとーございます。

できたもの

だんだん疲れてきたので、できたものをペタペタ。

最初はActiveなものを全部出して、その後は、新規作成したものだけ表示。
vsts show pr [Active|Completed|Abandoned] のコマンドをhubotに投げると指定したステータスのプルリクを全部表示。
あと、チャーハン。

ごちゃごちゃしているのはなんとかならないものかなぁ。

Hubotスクリプト

Personal Access Tokenを使うように変更。

# Description:
#   VSTSのPull Requestが作成されたらメッセージを投下します
#
# Configuration
#   vsts... の変数を適宜変更してください
#
# Commands:
#   hubot vsts show pr [Active|Completed|Abandoned] - 指定したステータスのPull Requestを全部表示
#   hubot チャーハン - チャーハン作ります

cronJob = require('cron').CronJob
startDate = new Date

vstsAccount = "[VSTSアカウント名]"
vstsProject = "[VSTSプロジェクト名]"
vstsRepository = "[VSTSリポジトリ名]"
vstsPersonalAccessToken = "[VSTS Personal Access Token]"
vstsRemoteUrlBase4PR = "https://#{vstsAccount}.visualstudio.com/DefaultCollection/#{vstsProject}/_git/#{vstsRepository}/pullrequest"
vstsRestApiUrlBase4PR = "https://hubotvstsnotifier:#{vstsPersonalAccessToken}@#{vstsAccount}.visualstudio.com/defaultcollection/#{vstsProject}/_apis/git/repositories/#{vstsRepository}/pullrequests\?api-version\=1.0"

module.exports = (robot) ->
  createRestApiUrl4PR = (status, top) ->
    url = vstsRestApiUrlBase4PR
    if status?
      url = "#{url}\&status\=#{status}"
    if top?
      url = "#{url}\&$top=#{top}"
    url

  searchPullRequests = (status, top, callBack) ->
    url = createRestApiUrl4PR status, top
    robot.http(url)
      .get() (err, res, body) ->
        responseJson = JSON.parse body
        callBack responseJson.value

  createPRMessage = (pullReq) ->
    prUrl = "#{vstsRemoteUrlBase4PR}/#{pullReq.pullRequestId}"
    "[#{pullReq.pullRequestId}](#{prUrl}) #{pullReq.title} (#{pullReq.sourceRefName} -> #{pullReq.targetRefName})"

  showPullRequests = (status, top) ->
    callBack = (pullReqs) ->
      prMsgs = for pullReq in pullReqs
        createPRMessage pullReq
      if prMsgs.length is 0
        msg = "@all: プルリクエストはなかったよ"
      else
        msg = "@all: プルリクエストが#{prMsgs.length}個あるよ\n#{prMsgs.join('\n')}"
      robot.send {room: 'general'}, msg
    searchPullRequests status, top, callBack

  showRecentPullRequests = (status, top) ->
    callBack = (pullReqs) ->
      prMsgs = for pullReq in pullReqs
        creationDate = new Date pullReq.creationDate
        continue if startDate > creationDate
        createPRMessage pullReq
      startDate = new Date
      if prMsgs.length is 0
        return
      msg = "@all: 新しいプルリクエストが#{prMsgs.length}個あるよ\n#{prMsgs.join('\n')}"
      robot.send {room: 'general'}, msg
    searchPullRequests status, top, callBack

  robot.respond /vsts show pr (.*)/i, (msg) ->
    showPullRequests msg.match[1], null
    
  robot.respond /チャーハン/, (msg) ->
    msg.send """
```` <- 本当は3個
チャーハン作るよ!!
  ∧_∧
 (`・ω・)  。・゚・⌒)
 /  o━ヽニニフ))
 しーJ
```` <- 本当は3個
"""

  # 初回のみActiveなものを全部出す
  showPullRequests "Active"

  # 以降は新しいもののみ出す
  new cronJob('*/30 * * * * *', () ->
    showRecentPullRequests "Active"
  ).start()

実行環境

カレントディレクトリにscriptsフォルダを作成して、上記のCoffee Scriptを配置したあと docker-compose up -d でRocket.ChatとHubotが立ち上がり、VSTSの連携が始まります。

フォルダ構成

+ root
   + bot
       + Dockerfile
   + scrpts
      + hubot-vsts-notifier.coffee
   + docker-compose.yml

docker-compose.yml

chat:
  image: rocketchat/rocket.chat
  environment:
    - MONGO_URL=mongodb://db/rocketchat
  ports:
    - "3000:3000"
  links:
    - db

db:
  image: mongo
  ports:
    - 27017

bot:
  build: ./bot
  links:
    - chat
  environment:
    ROCKETCHAT_URL: http://chat:3000
    ROCKETCHAT_ROOM: ''
    LISTEN_ON_ALL_PUBLIC: true
    ROCKETCHAT_USER: [RocketChat認証ユーザ名]
    ROCKETCHAT_PASSWORD: [RocketChat認証パスワード]
    ROCKETCHAT_AUTH: password
    BOT_NAME: bot
  volumes:
    - ./scripts:/home/hubot/scripts

Dockerfile

FROM rocketchat/hubot-rocketchat

RUN npm install cron time

連携イメージ

f:id:couger:20160503182847p:plain

Vagrant 1.8.1@Windows でフォルダの同期に rsync を使う

この辺の記事を見て、やってみようと思ったまでは良かったんだけど、いろいろつまづいたのでメモ。

qiita.com

使ったソフトのバージョン

やったこと

Vagrantfile でフォルダ共有の設定を以下のようにした

config.vm.synced_folder "d:\\Development\\hoge", "/vagrant",
  owner: "vagrant", group: "www-data",
  type: "rsync", rsync__exclude: [".git/", ".otto/", "Appfile", "Vagrantfile"]

以下、つまづいたことと、解決または回避策。

つまづき1: sshが終わらない

以下のメッセージが出た後、反応がまったくなくなる。

default: SSH address: 127.0.0.1:2222
default: SSH username: vagrant
default: SSH auth method: private key

VirtualBoxGUIでログを確認したところ、DLLの読み込みに失敗しているようだった。

DLLを調べたところ、ネットワークドライバのものらしい。
どうしようもないのでネットワークドライバをアンインストール...orz
ので、現在有線LANが使えない。

ちなみにドライバは "Qualcomm Atheros Killer Network Manager"
あとから最新バージョン入れてみよう。

⇒ 最新版を入れたら解決した!!!

Killer Networking - Driver Downloads

つまづき2: rsync がない

chocolateyでrsyncをインストール。

つまづき3: rsyncで No such file or directory (2)

以下のようなエラーが出た。

There was an error when attempting to rsync a synced folder.
Please inspect the error message below for more info.
...(略)
rsync: change_dir "/d/Development/hoge" failed: No such file or directory (2)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) atmain.c(1165) [sender=3.1.1]

[Vagrantインストールフォルダ]\embedded\etc\fstab に以下を追加する。

 d:  /cygdrive/d

つまづき4: rsyncで良く分からんエラー(1)

以下のようなエラーがでる。

There was an error when attempting to rsync a synced folder.
Please inspect the error message below for more info.
...(略)
mm_receive_fd: no message header
process_mux_new_session: failed to receive fd 0 from slave
mux_client_request_session: read from master failed: Connection reset by peer
Failed to connect to new control master
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(235) [sender=3.1.1]

以下の回避策を適用。

github.com

つまづき3: rsyncで良く分からんエラー(2)

以下のようなエラーが出る。

C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.8.1/lib/vagrant/util/io.rb:32:in `encode': "\x8A" followed by "%" on Windows-31J (Encoding::InvalidByteSequenceError)
...(以下、スタックトレース)

外部エンコーディングWindows-31Jになっているのが問題らしい。 環境変数 RUBYOPT を設定する方向で回避できないか試行錯誤してみたものの、できなかった。 ので、以下を参考に io.rb を修正して回避。

Windows + Vagrant + Rails の比較的快適な環境を作る - みかづきメモ

embedでリンクが上手くできなかった...。

io.rb:32 修正前

data << io.readpartial(READ_CHUNK_SIZE).encode("UTF-8", Encoding.default_external)

io.rb:32 修正後

data << io.readpartial(READ_CHUNK_SIZE).force_encoding("UTF-8")

つまづき4: rsyncで良く分からんエラー(3)

以下のようなエラーが出る。

C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.8.1/plugins/providers/virtualbox/driver/version_5_0.rb:380:in `split': invalid byte sequence in UTF-8 (ArgumentError)
...(以下、スタックトレース)

上記と同じようなエラーっぽいので、 version_5_0.rb を修正して回避。

version_5_0.rb:380 修正前

execute("list", "bridgedifs").split("\n\n").collect do |block|

version_5_0.rb:380 修正後

execute("list", "bridgedifs").force_encoding('ASCII-8BIT').split("\n\n").collect do |block|

ということで動くようになりましたよ。

GitHubにあるRailsアプリをVSTSでビルドして、Azureにデプロイする with Docker

11/15に社内の人とハッカソン練習会をした。 Railsで作ったアプリを、VSTSでビルドして、AzureとDockerを使って動かすのに挑戦...したんだけど、上手くいかなかった。 ので、日を改めてチャレンジした記録。

目標

考えていること

  • 以下を自動化したい。
    • Dockerイメージのビルド
    • プライベートレジストリへのPush
    • デモ用サーバへのデプロイ
  • Docker Machine使いたい
    • Docker Machineでプライベートレジストリや、デモ用サーバを作りたい。(楽だったから)

ビルドエージェントの構築

VSTSからビルドエージェント上でDockerコマンドを実行できるようにする。

VSTSプロジェクトの作成

Azure Portal にアクセス

新規 -> 開発者向けサービス -> Team Project から作成。 いろいろ聞かれるので適当に入れる。

VSTSプロジェクトの設定変更

ユーザとパスワードを使ってVSTSに接続できるようにする。

Alternate authentication credentials を有効にする

  1. VSTSにアクセス
  2. 鍵マーク -> Settings をクリック
  3. Application Connections にある Alternate authentication credentials を Allow に変更

認証するユーザと、パスワードを指定する

  1. 名前 -> My Profile
  2. Security -> Alternate authentication credentials をクリック
  3. Enable alternate authentication credentials をチェック
  4. Password, Confirm Password を入力して、Save をクリック

Passwordは以下の条件を満たす必要がある。

Passwords must be between 8 and 32 characters long, and must include 3 or more of the following: numbers, uppercase letters, lowercase letters, and special symbols.

ちなみに Alternate authentication credentials を使うと、VSTSからツッコミがある。

Personal access tokens are a more convenient and secure replacement for Alternate authentication credentials. Please use personal access tokens instead.

ので、Personal access tokenを使いたいんだけど、後回しにする。

Agent Poolの作成

  1. VSTSにアクセス
  2. 鍵マーク -> Settings をクリック
  3. Agent pool -> New pool をクリック

名前を入れて、OKをクリックする。

プロジェクトの作成

  1. VSTSにアクセス
  2. Recent Projects & Terms にある New をクリック
  3. パラメータ設定して、Create project をクリック

ビルドエージェント用サーバの作成

VMの作成

AzureからUbuntu Server 14.04 LTSでVMを作成する。

  1. 参照 -> 仮想マシン -> 追加をクリック

ビルドが早くなるかもということで、Standard_D1にした。

適当にパラメータを設定。

ランゲージパックの更新

ログインするとやれと言われたので。

sudo apt-get -y install language-pack-ja

Dockerのインストール

http://docs.docker.com/engine/installation/ubuntulinux/ を見ながらインストール。 sudo 必要ないようにdockerグループにユーザを追加する。

sudo usermod -aG docker [ユーザ名]

VSTS Agentのインストール

Node.jsのインストール

nvmでインストールするので、まずはnvmのインストール。 https://github.com/creationix/nvm を見ながら。

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.29.0/install.sh | bash
source ~/.bashrc

バージョンを指定してインストール。

nvm install v4.2.3

azure-cliのインストール

npm install -g azure-cli

azure-cliでAzureにログインする

azure login

標準出力に出てくるガイドに沿ってログインプロセスを進める。 サブスクリプションが適用されているかどうか確認する。

azure account list

利用したいサブスクリプションがカレントではない場合は、以下のコマンドでカレントにする。

azure account set [サブスクリプションID]

VSTS Agentのインストール

https://github.com/Microsoft/vso-agent を見ながら。

npm install vsoagent-installer -g
mkdir myagent; cd myagent
vsoagent-installer

VSTS Agentの起動

node agent/vsoagent

ユーザ名、パスワードを聞かれるので、上の方で設定したユーザ名とパスワードを入力する。 パラメータを幾つか聞かれるので入力。 無事接続すると、以下のようなメッセージが表示される。(最後にAgent Started.が出れば多分OK)

...
...
2015-12-11T15:45:09.233Z: Agent Started.

VSTSのAgent Poolでビルドエージェントが起動していることを確認する。

動作確認

テスト用ビルド定義を作成、Dockerが動作するかどうか確認する。

テスト用スクリプトの作成

ビルド定義からはバイナリファイルを直接呼び出すことができない。 ので、ビルドエージェントに以下の内容のシェルスクリプトを用意する。 (test.shとした)

docker run hello-world

vsoagentを再起動(ログインからやり直し)しないと、以下のようなエラーが出るかも。

2015-12-11T16:11:06.376Z: Cannot connect to the Docker daemon. Is the docker daemon running on this host?

テスト用ビルド定義の作成

  1. プロジェクトにアクセス
  2. BUILD -> "+" をクリック
  3. Empty を選択して、Next をクリック
  4. Create をクリック

ビルドができたので、ステップを追加する。

  1. Add Build Step をクリック
  2. Utility -> Shell script -> Add をクリック
  3. Close をクリック
  4. Script path にテスト用スクリプトのパスを入力して Save をクリック
  5. 名前を聞かれるので、適当に名前をつけて保存

実行するビルドエージェントを変更する。 さっき作ったビルド定義を開いていると思うので、以下の手順を流す。

  1. General -> Default agent queue をビルドエージェント名にする
  2. Save -> OK をクリックする

ビルドの実行

  1. プロジェクトにアクセス
  2. BUILD -> Build definition -> [ビルドの名前] をクリック
  3. 右ペインの queue build... をクリック
  4. OKをクリック

ビルドが成功して、以下のようなログが出力されたらOK。

レジストリ、デモ用サーバを作成する

Docker Machineを使ってサーバを作ってみる。

準備

Docker Machineのインストールと、証明書の作成。

Docker Machineのインストール

unzipないと怒られるので先に入れる。

sudo apt-get -y install unzip

後は https://docs.docker.com/machine/install-machine/ 見ながらインストール。

curl -L https://github.com/docker/machine/releases/download/v0.5.0/docker-machine_linux-amd64.zip >machine.zip && \
unzip machine.zip && \
rm machine.zip && \
sudo mv docker-machine* /usr/local/bin

一応、動作確認。

docker-machine --version

証明書の作成

AzureでDocker Machine使うのに必要。

mkdir ~/azure-cert; cd ~/azure-cert
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout azure.pem -out azure.pem

いろいろ聞かれるので、入力。

openssl pkcs12 -export -out azure.pfx -in azure.pem -name "Azure Certificate"
openssl x509 -inform pem -in azure.pem -outform der -out azure.cer
chmod 600 azure.pem

証明書の登録

  1. https://manage.windowsazure.com/ にアクセス。
  2. 設定 -> 管理証明書 をクリック
  3. アップロードをクリック
  4. azure.cer をアップロード

レジストリサーバの構築

サブスクリプションIDが必要なので確認。

azure account list

docker-machineでサーバを作る。

docker-machine create -d azure \
--azure-subscription-id "[サブスクリプションID]" \
--azure-subscription-cert "[azure.pemのパス]" \
--azure-location 'Japan West' \
--azure-username '[ユーザ名]'  \
--azure-password '[パスワード]' \
--azure-ssh-port 10022 \
--azure-size 'Small' \
--azure-docker-port 52376 \
[レジストリサーバ名]

エンドポイントを設定。

azure vm endpoint create \
--name docker-registry \
[レジストリサーバ名] \
5000 \
5000

デモサーバの構築

レジストリサーバの構築と同じ手順で、サーバを作成する。楽チンだ。 エンドポイントも設定。

azure vm endpoint create \
--name rails \
[デモサーバ名] \
3000 \
3000

動作確認

サーバの確認

docker-machine ls

レジストリサーバ

eval $(docker-machine env [レジストリサーバ名])
docker run -d -p 5000:5000 registry

リクエストを送ってみる。

curl http://[レジストリサーバ]:5000/v1/search

以下のような結果が返ってくればOK。

{"num_results": 0, "query": "", "results": []}

デモサーバ

GitHubRailsアプリをビルド、レジストリに登録、評価サーバへのデプロイまでやってみる。 ビルドには、Railsアプリ用のDockerイメージ rails:onbuild を使う。 rails:onbuildを使うと、任意のRailsアプリをDockerイメージにできる。

コード: https://github.com/agilecommunity/home_kpt

プライベートレジストリにhttpでアクセスさせる

httpでアクセスするようにビルドエージェント上のDockerサービスにinsecure-registryのオプションを指定する。 ビルドエージェントと、デモ用サーバで、/etc/default/dockerのDOCKER_OPTを変更し、サービスを再起動する。

/etc/default/dockerを変更する。

DOCKER_OPTS=--insecure-registry [レジストリサーバ]:5000

サービスを再起動する。

service docker restart

念のため、デモ用サーバでも実行するのを忘れないこと。(忘れててPullに失敗した...)

Dockerイメージのビルド

リポジトリをクローン。

git clone https://github.com/agilecommunity/home_kpt.git

直下のディレクトリにDockerfileを作成。

FROM rails:onbuild

ビルド。

cd home_kpt
docker build -t ajako/home_kpt .

Dockerイメージの動作確認

Railsが上がればOKとする。

docker run -it --rm ajako/home_kpt

プライベートレジストリに登録

プライベートレジストリに登録するので、タグつける。

docker build -t [レジストリサーバ]:5000/ajako/home_kpt

レジストリに登録

docker push [レジストリサーバ]:5000/ajako/home_kpt

レジストリの内容を確認。

curl http://[レジストリサーバ]:5000/v1/search

レジストリにイメージが登録されていたら、以下のような結果が返ってくる。

{"num_results": 1, "query": "", "results": [{"description": "", "name": "ajako/home_kpt"}]}

デモ用サーバにデプロイ

Railsが動けばOKとする。

eval $(docker-machine env [デモ用サーバ名])
docker run -it --rm [レジストリサーバ]:5000/ajako/home_kpt

VSTSからビルド、デプロイを実行

シェルスクリプトの作成

ビルドと、デプロイで分ける。 ビルド用。カレントディレクトリでビルドをする想定。

docker build -t [レジストリサーバ]:5000/ajako/home_kpt .
docker push [レジストリサーバ]:5000/ajako/home_kpt

デプロイ用。Docker Composeで実行する。

eval $(docker-machine env [デモ用サーバ])
docker stop ajako_home_kpt
docker rm ajako_home_kpt
docker run -d -p 3000:3000 [レジストリサーバ]:5000/ajako/home_kpt --name ajako_home_kpt

初回失敗するのだよなぁ。これだと。

ビルド定義の作成

外部サービスの登録

GitHubにアクセスするために外部サービスの登録をする。

GitHub personal access tokenの作成

  1. GitHubにログイン
  2. 自分のアイコン -> Settingsをクリック
  3. Personal access tokens -> Generate access tokenをクリック
  4. 名前と、scopeを指定し、Generate tokenをクリック VSTSによると repo, user, admin:repo_hook がいいらしい

access tokensの画面にアクセストークンが表示されてると思うので、それをメモ。

コネクションの作成

  1. プロジェクトを表示
  2. 鍵マーク -> Services をクリック
  3. New Service Endpoint -> GitHub をクリック
  4. RepositoryタグでRepository typeにGitHubを指定
  5. ConnectionのところのManageをクリック
  6. New Service Endpoint -> GitHubを選択
  7. 名前と、Personal access token -> トークンを指定してOKをクリック

ビルド定義の作成

新しいビルド定義をEmptyテンプレートで作成する。

リポジトリの指定

  1. Repository をクリック
  2. Repository typeを、GitHubにする
  3. Connectionで、作成したコネクションを選択
  4. Repositoryに選択できるリポジトリが表示されるので、対象のリポジトリを選択

ステップと、エージェントプールの指定

  1. Buildで、上記で作ったビルドとデプロイのシェルスクリプトをそれぞれ指定する。
  2. Generalで、Default agent queueにUbuntuを指定する

Saveで、保存。

動作確認

ブラウザからアクセスして、画面が出たらOK。 なんだけど、実はこのアプリ、DBにPostgreSQL使ってるので、エラー画面が出るのだなぁ...orz まぁ、なんとかDockerイメージ作って、レジストリにPush、デプロイまではできたということで、ここまでに...いや、やろう。

デモサーバでPostgreSQLを実行して、Railsアプリと連携させる

Docker Composeでやるのが面倒なくていいので、そっちでやる。

ビルドエージェントにDocker Composeをインストールする

https://docs.docker.com/engine/installation/ubuntulinux/ を見ながら。 rootで以下を実行

curl -L https://github.com/docker/compose/releases/download/1.5.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

動作確認

docker-compose --version

データベースの起動と初期化

設定ファイルの作成

以下の内容で docker-compose.yml を作成する。 説明はごめんなさい。はしょります。 Rails環境変数 DATABASE_URLを指定すると、設定ファイルを無視して、環境変数の内容で接続してくれるらしい。ありがたい。

DBは永続化するデータをDockerホスト側に出した。

web:
  image:[レジストリサーバ]:5000/ajako/home_kpt
  ports:
    - "3000:3000"
  links:
    - db
  environment:
    - DATABASE_URL=postgresql://[DBユーザ]:[DBパスワード]@db/home_kpt_db
db:
  image: postgres:9.4
  environment:
    - POSTGRES_PASSWORD=[postgresのパスワード]
  volumes:
    - [デモサーバのどこか]/home_kpt_db:/var/lib/postgresql/data

起動確認

docker-compose.ymlのあるディレクトリで以下を実行。

docker-compose up

ブラウザからアクセスすると、DBに接続しようとしてエラー。ユーザ作ってないからね。

DBユーザとデータベースの作成

コンテナの中に入ってDBユーザと、データベースを作成する。 docker ps で名前確認して、以下のコマンドでシェルを実行。

docker exec -it [名前] /bin/bash

DBを初期化する

su - postgres
cd /usr/lib/postgresql/9.4/bin
./createuser -P [DBユーザ名]

パスワード聞かれるので入れよう。 オーナーを指定してDBを作成。

./createdb -O home_kpt home_kpt_db

次にあるマイグレーションのように docker-compose で実行できればいいのに...。

マイグレーション

ビルドエージェントから実行。

docker-compose run web rake db:migrate    

デプロイスクリプトの修正

eval $(docker-machine env ajakohackathonDockerDemo)
cd [docker-compose.ymlのある場所]
docker-compose pull web
docker-compose up -d web

動作確認

無事画面が出た!!!

ということで、GitHubRailsアプリをVSTSを使ってDockerイメージにして、Azureにデプロイするまでが完了。 長かったなぁ。

今後やりたいこと

  • エージェントをサービス化する
  • Personal access tokenを使ってビルドエージェントを接続する
  • Docker Machineでリソースグループを指定してVMを作る方法を調べて見る
    • Docker Machineで作ると、クラッシックタイプになるので、そこも変えたい
  • そもそもこの手順が長いので、もっと楽にできる方法はないのか探してみたい