GitHub Actions
Memo
自動生成系はpull requestを作らせる
OpenAPIで何か生成しているときなどを想定する。生成を忘れないように、GitHub Actionsで実行するとよい。そのときPRを作らせると、チェックもできてよい。
デフォルト値をセットする
defaultsを使うと、共通のデフォルト値をセットできる。
defaults: run: working-directory: work jobs: hello: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 (略)
jobを共通化する
job間での共通部分はまとめて書くことですっきり書け、ジョブの高速化もできる。
- キャッシュ
- 言語環境
はどのタスクでも使うので、共通化できる。
name: Check on: push: jobs: # 共通処理で言語環境とキャッシュの用意をやる setup: runs-on: ubuntu-latest steps: - name: set up uses: actions/setup-go@v2 with: go-version: ^1.19 - name: check out uses: actions/checkout@v3 - name: Cache uses: actions/cache@main with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- build: needs: setup # 依存関係 runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: build run: go build . test: needs: setup # 依存関係 runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: test run: go test . -v
キャッシュ破棄ポリシーの落とし穴
毎回ビルドキャッシュ保存をしてるのに、あまりキャッシュヒットせず、毎回最初からになる現象に悩まされていた。デフォルトブランチでもマージするたびに行っていたので、キャッシュのブランチスコープの問題ではないように見えた。
問題の原因は、キャッシュ破棄ポリシーだった。1週間という期間と、リポジトリ合計で10GBという制限がある。
利用制限と退去のポリシー GitHubは、7日間以上アクセスされていないキャッシュエントリを削除します。 There is no limit on the number of caches you can store, but the total size of all caches in a repository is limited to 10 GB. この制限を超えた場合、GitHubは新しいキャッシュを保存しますが、合計サイズがリポジトリの制限以下になるまでキャッシュを退去させはじめます。
キャッシュサイズは2GBあったため、5回分しか保持されない計算。その回数のうちで、デフォルトブランチ以外のビルドでキャッシュが追い出されていくため、デフォルトブランチでのキャッシュがない状態になる。そのため、キャッシュヒットしない状態になる。妥協点はデフォルトブランチでのみキャッシュ保存し、別のブランチでは読み込みだけにすることだが、cacheアクションには保存だけするオプションがない。
cacheスコープ
- GitHub Actions の cache アクションでキャッシュヒットしない時はスコープを確認してみる
- Caching dependencies to speed up workflows - GitHub Docs
pushトリガーのジョブで、こんな感じにキャッシュを使っているとする。
- name: Cache Docker layers uses: actions/cache@v3 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx-
restore-keysはキャッシュ検索に使うkey。メインのkeyはgithub.shaによってすべてのコミットで別々にキャッシュ保存するので、完全一致でキャッシュ取得できることはない。ので、restore-keyが必要。キーが部分一致するので、後続のコミットで利用できる。
が、これだけではブランチが変わったとき、ブランチの最初ではキャッシュが利用されない。これがスコープ。スコープの探索は 同じブランチ → ベースブランチ → デフォルトブランチ のみで行われるので、ブランチの最初ではヒットしないということ。これを防ぐために、デフォルトブランチで定期的にpush保存を必要がある。
キャッシュキーのマッチング cache アクションは最初に、ワークフロー実行を含むブランチで key および restore-keys のキャッシュヒットを検索します。 現在のブランチにヒットがない場合、cache アクションは、親ブランチと上流のブランチで key および restore-keys を検索します。 restore-keys allows you to specify a list of alternate restore keys to use when there is a cache miss on key. 特定の度合いが強いものから弱いものへ並べて複数のリストアキーを作成できます。 The cache action searches the restore-keys in sequential order. キーが直接マッチしなかった場合、アクションはリストアキーでプレフィックスされたキーを検索します。 リストアキーに対して複数の部分一致があった場合、アクションは最も最近に作成されたキャッシュを返します。
reuseable actionにおけるsecretsの扱い方
jobs: called: uses: user/repo/.github/workflows/called.yml@main with: text: ${{ github.event.inputs.text }} secrets: # ←←← DUMMY: ${{ secrets.DUMMY }} # ←←← caller側ではとくになにもせずともsecretsが使える
on: workflow_call: inputs: text: type: string required: true secrets: # ←←← DUMMY: # ←←←called側ではここで定義されていて、かつ呼び出し側のsecretsで定義されてないとsecretsは参照不可 required: true jobs: called: runs-on: ubuntu-latest steps: - name: output secret run: | echo ${{ secrets.DUMMY }}
Stale Bot
動きがないIssueやPRを自動的にマークしたりcloseするGitHub bot。 probot/stale: A GitHub App built with Probot that closes abandoned Issues and Pull Requests after a period of inactivity.
設定の例(rubocop)。 https://github.com/rubocop/rubocop/blob/master/.github/stale.yml
PRの編集ファイルによって自動でラベルをつける
面倒なラベル付けを自動化する。
name: Pull Request Labeler on: - pull_request - pull_request_review jobs: triage: runs-on: ubuntu-latest steps: - name: Label all PRs uses: actions/labeler@master with: repo-token: "${{ secrets.GH_PAT }}" - name: Label approved PRs uses: koj-co/label-approved-action@master with: labels: "merge" env: GITHUB_TOKEN: "${{ secrets.GH_PAT }}"
config: - ./* tooling: - tooling/**/*.* assets: - static/**/*.* tests: - any: ["src/**/*.spec.js", "cypress/**/*"] package: - any: ["package.json", "package-lock.json"] source: - src/**/*
GitHub Actionsのトリガー
pathsで特定ファイルが変更されたときのみ実行するときの注意点。 pushは使わずに、pull_requestトリガーを使うべき。
on: pull_request: paths: - 'Dockerfile'
on: push: paths: - 'Dockerfile'
pushではpull_request全体の変更を追うことができないので、コミットが分かれているとジョブが走らず、あたかもパスしているように見えて危険。
Reference
release-drafter/release-drafter: Drafts your next release notes as pull requests are merged into master.
タグを自動で打ち、リリースを作成する便利なアクション。
GitHub Actions - 再利用可能ワークフローを使う | 豆蔵デベロッパーサイト
reuseable workflowの説明。