2018年12月20日木曜日

[Azure Pipelines] ビルドをスキップするコミットメッセージコマンド

この記事は Azure DevOps Advent Calendar 2018 20日目の記事です。

今回の内容は非常に短いのですが、Azure Pipelines でビルドをスキップするコミットメッセージコマンドを紹介したいと思います。
前回、前々回の記事はこちら

コミットメッセージコマンド
多くの CI サービスで使われている機能で、コミットメッセージに特定の文字列を入れておくと、CI 上の機能を呼び出せるものになります。
その定番がビルドのスキップです。

ドキュメントの更新だけのときなど、CI が実行されなくても問題ないようなケースで役に立ちます。
筆者が使用している CI サービスの各スキップコマンドを以下のリポジトリでまとめていますので、Azure Pipelines 以外のサービスで気になるものがあれば見ていただければと思います。
https://github.com/srz-zumix/ci-skip/tree/master

Azure Pipelines でビルドスキップするコミットメッセージコマンド
さて、肝心の Azure Pipelines のスキップメッセージですが、
***NO_CI***
になります。

多くの CI サービスで使われている [ci skip] や [skip ci] は対応していないようです。
ちょっと残念ですが、 issue もあるようなので対応されることを期待して待ってます。
https://github.com/Microsoft/azure-pipelines-agent/issues/858


実際にスキップメッセージを入れたときの挙動は先に紹介した ci-skip リポジトリで見ることができます。
exsample commit: add Azure Pipelines ***NO_CI***

今回は以上です。
では。

2018年12月11日火曜日

Azure Pipelines でマトリックスを組んでみた

この記事はAzure DevOps Advent Calendar 2018 11日目の記事です。
4日目に投稿した「ブログズミ: Azure Pipelines 始めました」の続きになります。


早速ですが、上のスクリーンショットは 31 個のジョブを実行している様子です。
いやホント10 並列は素晴らしいですね!

では、今回はマトリックスを組んでみた流れを紹介したいと思います。
テンプレートを作る
まずは、パラメータで処理パターンを増やすためのベースとなるテンプレート部分を作ります。
ドキュメントを見た感じですと、ジョブ、もしくはステップをテンプレートにできるようです。
Job and step templates - Azure Pipelines & TFS | Microsoft Docs

テンプレートの記述と利用
テンプレートは azure-pipelines.yml とは 別の yaml ファイルに記述します。
そして、azure-pipelines.yml もしくは別のテンプレートから下記のように参照します。
steps:
  - template: templates/sample.yml  # Template reference
jobs:
  - template: templates/jobs.yml  # Template reference

サンプルがドキュメントに載ってますので、そちらを見ていただくとわかりやすいと思います。
テンプレートは別のリポジトリのファイルを参照することもできるようですが、今回は使わないので省略します。 > Using other repositories

テンプレートにパラメータを渡す
テンプレートにパラメータとして任意の要素を渡し、パラメータに応じて処理内容を変えたいと思います。
Passing parameters
(ドキュメントを見ていると、単純の値や配列だけでなく、ジョブをパラメータとして扱うこともできるようですが、まだ実践してないので今回は省略)

まずは、パラメータのやり方から。

template 側の yaml
parameters:
  name: ''
  options: ''
  vmImage: 'ubuntu 16.04' # デフォルト値

jobs:
  - job: ${{ parameters.name }}
    pool:
      vmImage: ${{ parameters.vmImage }}
parameters にパラメータを定義します。ここでセットした値はデフォルト値になります。
パラメータの値を使用する場合は、${{ parameters.hogehoge }} のようにします。

azure-pipelines.yml 側
jobs:
  - template: .ci/azure_pipelines/template-make-test.yml
    parameters:
      name: default
 
パラメータを渡す場合も、parameters に記述します。
これでパラメータの受け渡しができるようになりました。

パラメータに応じて処理を変える
さて、中核に迫ってまいりました。
パラメータの内容によって、処理を変える方法はいろいろ考えられます。
ドキュメントを見ていると、高度なことができそうな感じがしているのですが・・・
まだ使いこなせてないので、省略。
* Template expression functions
   Expressions
* Insertion
* Conditional insertion
* Iterative insertion

今回はとてもシンプルにパラメータをスクリプトの引数として使いました。
(Azure Pipelines 側の書き方や制約に縛られず、自分の好きな書き方をできるので、まずはこの方法で良いと思います。)

iutest では以下のようにしました。
parameters:
  options: ''
  package_name: 'default'

steps:
- script: make -C test -j4 OUTPUTXML=junit ${{ parameters.options }}
  displayName: 'make'
- script: make -C test -j4 OUTPUTXML=junit ${{ parameters.options }} ${run_option} test
  displayName: 'test'
  env:
    run_option: RUN_OPTION="--iutest_default_package_name=${{ parameters.package_name }}"

make にオプションを渡せるようにしたのと、テスト実行時のオプションを指定するようにしました。

azure-pipelines.ym > job template > step template
さて、ここまででほぼほぼテンプレートを作ることができるようになっていると思いますが、最後にテンプレートを2段構成にしてみました。
テンプレートをテンプレートで使うことも問題なくできるのです!

iutest では、make test とテスト結果を集計するステップテンプレート、
そして、それをある程度の粒度でパラメタライズドしたジョブテンプレートにしました。



azrue-pipelines.yml は以下のように、ジョブテンプレートを利用するだけの非常にシンプルな内容になりました。
jobs:
  - template: .ci/azure_pipelines/template-make-test.yml
    parameters:
      name: default
  - template: .ci/azure_pipelines/template-make-disabled-test.yml
    parameters:
      name: disabled

テンプレート側の yaml は長いので、GitHub を見てくださいmm
iutest/azure-pipelines.yml at master · srz-zumix/iutest
iutest/.ci/azure_pipelines at master · srz-zumix/iutest

マトリックスを書く

これが、ちょっと長いのですが・・・こんな感じになりました。


ステップテンプレートに make のオプションを生成して流しているジョブテンプレートになるのですが、
やっていることは1つのマクロを定義して config を変えて、ビルド・テストをさせています。
そのマクロ部分をマトリックスにしたのですが、いちいち名前をつけないといけないのが面倒・・・
DISABLED_CONFIG 配列に定義できると楽なんですが・・・

たぶん、もっとキレイに書けるんだろうなーという感触はありますが、今後の課題としたいと思いますmm

10並列の効果はどんなもんよ?
iutest の現時点で、1 pipeline で 57 ジョブが実行しています。
各ジョブでやっていることは、ほぼほぼ同等でマクロ定義が1つ異なるだけのビルド・テストです。
1ジョブの実行時間が約5分。

直列に行った場合は、5 x 57 分で約5時間です・・・

が、これが、


なんと!


およそ 35分 !!
10並列のパワー素晴らしい

テスト失敗してますよ?
はい。
今まで config 変更のテストは、ローカルの Jenkins もしくは今はなき SnapCI でやっていたのですが(それかローカル実行)、とにかく時間がかかって辛かった!のでやってませんでした。すみませんmm
今回、Azure Pipelines の力によってメンテナンスできてなかった部分が炙り出された感じです。
本当、ありがとうございます!!って感じです。
(FAIL はちゃんと直します。ごめんなさい)

今後やりたいこと
さて、今回はこれで以上となりますが、
まだまだ Azure Pipelines でやりたいこと・できることは多そうです。
また進展あったらまとめたいと思います。ではでは。

* [ci skip]
* auto cancel
* 簡易テスト後に、マトリックスが走るようにする(dependsOn の挿入?)
* 条件分岐(xml 出力がされないことを期待する場合に、集計をしない)
* yaml に書く量を減らしたい
* 本当のマトリックス( N x M )で爆発させたい

2018年12月4日火曜日

Azure Pipelines 始めました

この記事は(ちょうど公開するタイミングで空きがあったので)
Azure DevOps Advent Calendar 2018 4日目の記事になりました。


Azure Pipelines が9月にリリースされたようですが、最近知りました。
なんと! OSS なら 10 並列・時間制限なし!!
これは組み合わせ爆発させざるをえない!!!(マテ



Sign Up
脊髄反射で SignUp しましょう。

MS アカウントでサインインして、名前決めたら完了です。


あれ?すでに Organization がありますね?


どうやら、昔作った Visual Studio Online のが残ってたみたいです。
新規作成した Organization は削除。
Overview で「組織のURL」を更新し、プロジェクトもすべて削除しました。


ともあれ、これでサインナップ完了です。

パイプラインを作る
では、パイプライン作っていきましょう。
Azure Dev Ops のダッシュボードからプロジェクト作成しても良かったのですが、 GitHub からやったほうが楽かなーと思ったのでそっちにしました。

GitHub から登録
GitHub Marketplace に Azrue Pipeline があるので、インストールします。


フリープランで Order


リポジトリを選択(全部もしくは任意のリポジトリを選べます)


Organization を選択(SignUp 時に作成したもの)
プロジェクト名は任意で(すでにあれば選択)


認証したら・・・


プロジェクトの出来上がり!


ここまでで、プロジェクト作成が完了してパイプライン作成の第一ステップのロケーション(GitHub)の選択が終わっている状態になっています。
ここから、パイプラインを設定していきます。

リポジトリの選択
つづいて、リポジトリの選択をします。今回の場合は iutest を選択します。

テンプレートの選択
Choose a template でパイプラインのテンプレートを選びます。
c++ のテンプレートがあったので、「C/C++ with GCC」を選択しました。(リポジトリの内容によってオススメが出てくるみたいですね)


YAML
テンプレートから azure-pipelines.yml が生成されます。
ルートディレクトリで make するだけですが、iutest はそれではビルドされないので、ビルドとテストの実行をするように少し書き換えました。


Save and Run2
最後に保存して、最初のビルドを実行してみましょう!
生成した azure-pipelines.yml を commit/push するので、master に入れるかブランチ切るかを選択し、(必要であればコメントも)「Save and run」ボタンを押します。


今回はブランチを作成しました。
https://github.com/srz-zumix/iutest/pull/120

はじめてのビルド
「Save and run」を押すとビルドがキューに積まれて、処理が始まります。






しばらく待つと・・・無事成功!
ここまでは簡単でしたね!


テストの集計タスクを追加してみる
まだまだ、Azure Pipelines のことで把握していないことばかりではありますが、この流れのままテストの集計までしてしまいましょう。

テストができるようになったので、テストの集計をします。
テストの集計は「タスク」になっているようなので、タスクを追加します。

Publish Test Results task - Azure Pipelines & TFS | Microsoft Docs
先程作成した azure-pipelines.yml に以下を追加します。
- task: PublishTestResults@2
  inputs:
    testResultsFiles: 'test/*.xml'
変更を最初に作ったブランチに push しましょう。


集計できました!簡単!!
さて、これで GitHub に push するとテストが実行され、結果が集計されるところまで確認できました。
(失敗すべきテストまで集計されてしまっているのは make のオプションミスです・・・)
CI をするにあたっての基本的なことができるようになったので、ここからやりたいことを組み込んでいこうと思いますが、そのへんはまた次回で・・・

バッジを付ける
次回に行く前に・・・やっぱりバッジはつけておきましょう!
バッジはパイプラインのダッシュボードページの右上メニューの中にあります。

バッジのブランチは「?branchName=develop」をつけると指定できます。
※ ビルドページの URL のブランチ指定がうまくできなかったので、方法があれば知りたいですmm

最後に
OSS プロジェクトなら 10 並列が無料で使えるのは、個人的にすごくありがたいです。
まだ、10 並列を使い切ってはないのですが、これから使っていこうと思ってます。

また、導入してしばらく経っているのですが、GitHub に push してからビルドが走るまでの時間も早いので、そこも嬉しい。
YAML の書き方は・・・ちょっと四苦八苦しながらも書いてるので、もう少しドキュメントがわかりやすいと嬉しいな、とも思いました。(圧倒的英語力不足ともいう・・・)

OS も Windows だけでなく、macOS/Linux も使えるようなです。
(最近は、この辺での優位性がなくなりつつありますが・・・)

Azure Pipelines は非常に強力なサービスなのは間違いなさそうなので、これからもお世話になると思います。よろしくお願いしますmm

今回は以上です。