rust
CI
AzurePipelines

Azure Pipelines で Rust プロジェクトを CI する

知見をまとめていなかったのを思い出したので、アドベントカレンダーの小ネタとして放流しておきます。

Azure Pipelines について

Azure Pipelines は、Microsoft が提供している CI/CD サービスです。OSS プロジェクトの場合、ビルド時間無制限で10個までのジョブを並列に実行することが可能です。また、Linux, macOS および Windows の利用が可能であり、Travis CI と Appveyor とで分散しがちだった CI 周りの設定を集約させることが期待できます。また、ジョブ実行にコンテナを使用することが可能であるので、Docker Hub で公開されている Rust イメージなどを用いてインストール作業を簡略化することが出来ます。サービス開始からそれほど日が経っていないので情報が少ないなど難点もありますが、上手く行けば Rust プロジェクトの CI サービスとしての新たな選択肢となることが期待できます。

設定例

プロジェクトが GitHub にホストされていることを前提に話を進めます(GitLab など他のホスティングサービスについては今後の課題)。

設定ファイルはリポジトリ直下に azure-pipelines.yml という名前で配置します。細かい点を除けば、基本的な設定は他の CI サービスのものと同じように記述するすることが出来ます。本記事執筆時点 (2018/12/02) では Rust の公式サポートは無いため、コンテナを試用しない場合は手動で rustup をインストールする必要があります。

azure-pipelines.yml
# 使用するコンテナを列挙する
resources:
  containers:
    - container: rust
      image: rust:latest

jobs:
  - job: Linux
    pool:
      vmImage: 'ubuntu-16.04'
    # Travis CI でいう build matrix のようなもの
    # rust_toolchain の値は環境変数を介してスクリプト内で使用できる
    strategy:
      matrix:
        stable:
          rust_toolchain: stable
        beta:
          rust_toolchain: beta
        nightly:
          rust_toolchain: nightly
        minimum_supported:
          rust_toolchain: 1.30.0

    # 実行するスクリプトを列挙する
    steps:
      - script: |
          curl -sSf https://sh.rustup.rs | sh -s -- --default-toolchain $RUST_TOOLCHAIN -y
          echo "##vso[task.setvariable variable=PATH;]$PATH:$HOME/.cargo/bin"
        displayName: install rustup

      - script: cargo test --verbose
        displayName: run test

  # Windows を使用する例
  - job: Windows
    steps:
      - script: |
          curl -sSf -o rustup-init.exe https://win.rustup.rs
          rustup-init.exe -y --default-toolchain stable
          set PATH=%PATH%;%USERPROFILE%\.cargo\bin 
          echo '##vso[task.setvariable variable=PATH;]%PATH%;%USERPROFILE%\.cargo\bin'
        displayName: install rustup on Windows

      - script: cargo test --verbose
        displayName: run test

  # コンテナを使用する例
  # コンテナを使用する場合、vmImage は 'ubuntu-16.04' を指定する必要がある
  - job: Linux_container
    pool:
      vmImage: 'ubuntu-16.04'
    container: rust # 上に列挙したコンテナを指定する
    steps:
      - script: cargo test --verbose

Tarpaulin でのカバレッジ計測 + Codecov への送信例

cargo-tarpaulin を用いてカバレッジ計測を行い、その結果を Codecov に送信する例です。tarpaulin が Docker Hub にビルド済みのイメージを公開しているのでこれを使用します(数ヶ月前からイメージの更新が途絶えているので、可能であれば自前で作成したイメージを使ったほうが良いかもしれません…)。

azure-pipelines.yml
resources:
   containers:
     - container: tarpaulin
       image: xd009642/tarpaulin:latest-nightly
       options: --security-opt seccomp=unconfined

jobs:
  - job: tarpaulin
    pool:
      vmImage: 'ubuntu-16.04'
      container: tarpaulin
      steps:
      - script: |
          cargo tarpaulin -v --out Xml
          # 本記事執筆時点では Azure Pipelines に未対応なので直接指定する
          curl -s https://codecov.io/bash -o .codecov && chmod +x .codecov
          ./.codecov -B "${BUILD_SOURCEBRANCHNAME:-}" \
                     -C "${BUILD_SOURCEVERSION:-}" \
                     -P "${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER:-}" \
                     -b "${BUILD_BUILDID:-}" \
                     -K -n "report name"
        displayName: 'run tarpaulin'
        # secret variables は直接環境変数でアクセス出来ないのでマップする
        # https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=vsts&tabs=yaml%2Cbatch#secret-variables
        env:
          CODECOV_TOKEN: $(myCodecovToken)

現状の課題

使用例が少ない

出始めのサービスなのでしょうがないのですが、とにかく使用例が少ないので Rust を使用するための設定ファイルの書き方を調べるのに苦労しました。幸い、Juniper がちょうど Appveyor から Azure Pipelines に切り替えていたため、その設定と Azure Pipelines のドキュメントとを交互に眺めながら設定をすることが出来ました。Azure Pipelines 自体のドキュメントは割と整備されているので、他の言語 (Go など) のページを参考にすると良いと思います。

キャッシュが使えない

将来的に改善されるかもしれないですが、現時点ではキャッシュがサポートされていない1ため、依存関係のビルドに時間がかかるプロジェクトではビルド時間に難があるかもしれません。


  1. 調べた限りでは