前のエントリではバイナリを GitHub のリリースとして配布しているけれど、これは GitHub Actions でビルドとリリースのアップロードを行っている。いろいろ試行錯誤した結果なのでメモを残しておく。
ビルドに成功してからリリースを作成する、とした違いはあるけど、基本的に以下のエントリを参考にしている。
【GitHub Actions】Go言語の自動テストからリリースまでを作ってみた - Qiita
できあがりの workflow はこういう感じ。
一度 CI をセットアップしてしまうと、そのあと触ることは全然ないので、時間をあけて完全に忘れてしまった状態でも、問題なくメンテできるようになっていてほしい。そういう観点では、公式っぽいアクションだけで構成できたのはよかった。
ジョブはこういう流れになっている。
- Build (matrix)
- Create-release
- Upload-release (matrix)
Build
build: strategy: matrix: target: - x86_64-unknown-linux-gnu - x86_64-pc-windows-gnu - x86_64-apple-darwin include: - target: x86_64-unknown-linux-gnu os: ubuntu-latest - target: x86_64-pc-windows-gnu os: ubuntu-latest - target: x86_64-apple-darwin os: macos-latest runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v1 # https://github.com/actions/cache/blob/master/examples.md#rust---cargo - name: Cache cargo registry uses: actions/cache@v1 with: path: ~/.cargo/registry key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }} - name: Cache cargo index uses: actions/cache@v1 with: path: ~/.cargo/git key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }} - name: Cache cargo build uses: actions/cache@v1 with: path: target key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }} - uses: actions-rs/toolchain@v1 with: toolchain: stable override: true - uses: actions-rs/cargo@v1.0.1 with: command: build args: --release --target=${{ matrix.target }} use-cross: true - run: | zip --junk-paths slack-stream-json-${{ matrix.target }} target/${{ matrix.target }}/release/slack-stream-json{,.exe} - uses: actions/upload-artifact@v1 with: name: build-${{ matrix.target }} path: slack-stream-json-${{ matrix.target }}.zip
Linux、macOS、Windows それぞれでビルドしたいので、matrix を使う。なんか cross というのを使えば(actions-rs/cargo のオプションにある)1ホスト上で全部クロスビルドできそうだったんだけど、x86_64-apple-darwin 向けのビルドで "error: failed to run custom build command for backtrace-sys v0.1.32
" などと言われてしまい簡単にはできなそうだった。このへんの仕組みは何も知らないので、OSごと切り替えられるのであればそちらのほうがシンプルだろうと、そのようにした。
x86_64-pc-windows-gnu 向けは Linux でビルドできた。ここが Windows でしかビルドできなかったら、zip
コマンドを使い変えないといけなくて大変だったのではないだろうか……。
actions/cache も Rust/Cargo に対応している。
ビルドしたバイナリは、あとでリリースに上げたいので actions/upload-artifact しておく。
Create-release
create-release: needs: [build] runs-on: ubuntu-latest steps: - id: create-release uses: actions/create-release@v1.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} release_name: Release ${{ github.ref }} draft: false prerelease: false - run: | echo '${{ steps.create-release.outputs.upload_url }}' > release_upload_url.txt - uses: actions/upload-artifact@v1 with: name: create-release path: release_upload_url.txt
actions/create-release でタグに対応するリリースを作成する。リリースを作るのは一度しかできない(エラーになる。ここでちょっとハマった)ので、matrix から外して、build とは別のジョブとして立てる。
リリースのアップロード用 URL を、これも後で使うので upload-artifact しておく。
Upload-release
upload-release: strategy: matrix: target: - x86_64-unknown-linux-gnu - x86_64-pc-windows-gnu - x86_64-apple-darwin needs: [create-release] runs-on: ubuntu-latest steps: - uses: actions/download-artifact@v1 with: name: create-release - id: upload-url run: | echo "::set-output name=url::$(cat create-release/release_upload_url.txt)" - uses: actions/download-artifact@v1 with: name: build-${{ matrix.target }} - uses: actions/upload-release-asset@v1.0.1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.upload-url.outputs.url }} asset_path: ./build-${{ matrix.target }}/slack-stream-json-${{ matrix.target }}.zip asset_name: slack-stream-json-${{ matrix.target }}.zip asset_content_type: application/zip
これが最後のフェーズ。あまりそうする必要もないけど、build と合わせるため matrix を使う。actions/download-artifact で前の2つのジョブの結果を受け取って、actions/upload-release-asset する。これで各 OS 分のファイルをリリースに添付できる。
標準出力に ::set-output
と送ることで、ステップの output を設定できるらしい。おおう。ステップ名には -
も使えるので、今回はケバブケースを採用してみた。