GitHub Actions

概要

GitHub ActionsはGitHubが提供するCI/CD環境。 コードやプロジェクトに対するタスクを実行できる。

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スコープ

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 }}

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全体の変更を追うことができないので、コミットが分かれているとジョブが走らず、あたかもパスしているように見えて危険。

Tasks

実行時間の統計を取りたい

何で遅くなった、早くなったか把握したい。

Reference

release-drafter/release-drafter: Drafts your next release notes as pull requests are merged into master.

タグを自動で打ち、リリースを作成する便利なアクション。

Archives