LoginSignup
7
2

More than 3 years have passed since last update.

お手軽に Github Actions を解ったつもりになるための Tips

Last updated at Posted at 2020-12-17

mediba Advent Calendar 2020 の18日目担当の @h-sugawara です。
担当している各種プロジェクトでは、CI/CD に CircleCI というサービスを使わせて頂いています。
しかし、最近、諸事情により CircleCI から Github Actions への移行を検討していて、Github Actions の導入検証を行いました。
今回は、Github Actions で頻出して使うことが多くて調べたものを、毎度調べ直すのが面倒だったため、情報を集約する Tips を作成しました。

Workflow Tips

コミットにソースコードを含む開発用ブランチをプッシュした時に実行する

開発用ブランチfeature/hogehogeにソースコードbatch/foobar/main.goを含むファイルをコミットして、Github へプッシュした時に、テストや構文チェックを行う Workflow を実行させたいとします。
このような場合、次の例のようにプッシュイベントのトリガーを設定します。

on:
  push:
    branches:
      - 'feature/*'
    paths:
      - '**.go'

on.push.branches'feature/*'は、feature/から始まるブランチが対象です。
しかし、*/を除く0文字以上の文字列を示すフィルタであるため、feature/issue-1234/hogehogeのようなブランチは対象外となることに注意が必要です。
これらの対象外となるブランチも含める場合は、0文字以上のすべての文字列を対象とする**を用いて'feature/**'とします。

on.push.pathsも同様のルールで、上述の例の場合はすべての.goファイルがコミットに含まれているかが対象となります。
これを、'*.go'と書き換えた場合は、レポジトリのルートにある.goファイルだけが対象となります。

指定ブランチ以外をプッシュした時に実行する

特定のブランチのプッシュを無視する場合は、on.push.branches-ignoreで指定します。
ただし、これをトリガーに設定すると Github Actions の仕様上、タグのプッシュはすべて無視されることに留意しておきましょう。
タグのプッシュも含めるには、次のようにon.push.tags'*'または'**'を、トリガーに設定します。

on:
  push:
    branches-ignore:
      - 'develop'
      - 'release/**'
    tags:
      - '*'

このようにすると、例えば、feature/から始まるブランチをプッシュしたり、v1.0.0のようなタグをプッシュしたりすると Workflow が実行されます。
反対に、developブランチやrelease/から始まるブランチをプッシュしても Workflow は実行されません。
なお、タグのプッシュが無視されても構わない場合は、on.push.tagsの指定は不要です。

指定タグ以外をプッシュした時に実行する

特定のタグのプッシュを無視する場合は、on.push.tags-ignoreで指定します。
前述のbranches-ignoreと同様に GitHub Actions の仕様により、ブランチのプッシュはすべて無視されます。
ブランチのプッシュも含めるには、下記のようにon.push.branches'**'を、トリガーに設定します。
'*'を指定した場合、ブランチ名に/が含まれるとうまく動かないため、'**'の利用を推奨。

on:
  push:
    branches:
      - '**'
    tags-ignore:
      - 'dev-*'
      - 'stg-*'

この設定例では、developブランチや、feature/またはrelease/などから始まるブランチをプッシュしたり、v1.0.0のようなタグをプッシュしたりすると Workflow が実行されます。
反対に、dev-stg-で始まるタグがプッシュされた場合は、Workflow は実行されません。
もちろん、特定のタグ以外のタグのプッシュを対象とするだけなら、on.push.branchesは不要です。

プルリクエストがマージされた時に実行する

プルリクエストのマージをトリガーとする Workflow を作成する時は、次の2点に注意が必要です。

  1. compare ブランチ(マージ元)ではなく、base ブランチ(マージ先)が対象である
  2. プルリクエストイベントのアクティビティタイプにはマージされたことを示すものはない

そのため、以下の例のように、on.pull_request.typesclosedであり、jobなどでgithub.event.pull_request.mergedtrueであることを確かめる必要があります。

on:
  pull_request:
    branches:
      - my_base_branch
    types:
      - closed

jobs:
  my_job_name:
    runs-on: ubuntu-latest
    if: github.event.pull_request.merged == true
    steps:
      - name: my_step_name
        run: echo "Hello world!"

renovate などのツールやプルリクエストの作成などを定期的に実行する

on:
  schedule:
    - cron: '*/15 * * * *'

Job Tips

2つ以上前に実行された Job の出力値を参照する

例えば、first_jobsecond_joblast_jobの順で Job を実行するとします。
この時、last_jobneedsに、直前に実行されることを意図してsecond_jobだけを指定すると、Job の実行順はその通りになります。
しかし、second_jobの前に実行されたfirst_jobの出力値は参照できません。
なぜなら、Job が参照できる出力値は、依存関係によって以前に実行したすべての Job ではなく、needsで指定した Job のみだからです。
そのため、実行する Job から見て依存関係にあるすべての Jobを needsに指定する必要があります。

jobs:
  first_job:
    runs-on: ubuntu-latest
    outputs:
      first_val: ${{ steps.echo_step.outputs.first }}
    steps:
      name: set output
      id: echo_step
      run: echo "::set-output name=first::hogehoge"

  second_job:
    runs-on: ubuntu-latest
    needs: [first_job]
    outputs:
      second_val: ${{ steps.echo_step.outputs.second }}
    steps:
      name: set output
      id: echo_step
      run: echo "::set-output name=second::foobar"

  last_job:
    runs-on: ubuntu-latest
    needs: [first_job, second_job]
    steps:
      name: echo before job output
      run: |
        echo "${{ needs.first_job.outputs.first_val }}"
        echo "${{ needs.second_job.outputs.second_val }}"   

直前の Job の結果が success 以外でも必ず実行する

Job の実行条件は、if: success()(成功時のみ実行)がデフォルトで設定されています。
そのため、jobs.<job_id>.needsで指定した Job のいずれか一つでも実行結果がsuccess以外になった場合、<job_id>の実行はスキップされます。
必ず実行させる必要がある Job には、下記のようにif: always()を指定しましょう。

jobs:
  first_job:
    runs-on: ubuntu-latest
    steps:
      name: failure job
      run: exit 1

  second_job:
    runs-on: ubuntu-latest
    steps:
      name: success job
      run: exit 0

  last_job:
    runs-on: ubuntu-latest
    needs: [first_job, second_job]
    if: always()
    steps:
      name: echo
      run: echo "running second_job."   

この方法は、テストやビルド、デプロイなどの Job の後に、Slack などでそれらの実行結果を通知する Job を実行する場合に活用できます。

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2