1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Github Actions - 構成要素の概要と要点

Last updated at Posted at 2024-12-30

内容

GitHub Actionsを構成するコンポーネントの概要と要点について記載する

イベント

ワークフローをトリガーするイベント

各イベント説明に記載されているGITHUB_REFGITHUB_SHAは、ブランチ名、コミットIDで、
workflowはそのソースコードの状態で実行される
actions/checkoutでソースコードをcheckoutする際にデフォルトではこのブランチ名、コミットIDが使用される(パラメータrefで変更可能)

Noteに「このイベントは、ワークフローファイルがデフォルト ブランチにある場合にのみワークフローの実行をトリガーします。」とあるイベントは、
デフォルトブランチにworkflowの実装がマージされたあとでしか実行・動作確認できないため注意

pull_request

PRの各種操作をトリガーにworkflowを起動する
以下のようにブランチやファイルパスでイベントのフィルターも可能

on:
  pull_request:
    types:
      - opened
      - synchronize
    branches:
      - 'releases/**'
    paths:
      - '**.js'

使用頻度の高いtypesとしてはopened, closed, synchronize等、
PRのマージ時にworkflowを実行する場合は以下のようにgithub.event.pull_request.mergedと合わせて判定する

on:
  pull_request:
    types:
      - closed

jobs:
  if_merged:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    steps:
    - run: |
        echo The PR was merged

typesopened, synchronizeでPR発行時、PRに対してコミットpush時にテストworkflowを実行、
typesclosedでPRマージ時に実環境にデプロイする等の使い分けが考えられる
synchronizeを入れるとコミット頻度が高い場合や、workflowが重い場合にActionsの実行時間が増加して料金への影響もあるため要検討

pull_requestイベントはGITHUB_REFGITHUB_SHAが特殊で、
PRマージブランチ(PRがマージされた後の状態のソースコード)になる
pull requestのheadブランチへの最後のコミットのコミットIDを取得する場合は、
代わりにgithub.event.pull_request.head.shaを使用する

「このイベントは、ワークフローファイルがデフォルト ブランチにある場合にのみワークフローの実行をトリガーします。」の記載がないため、
pull_requestトリガーのworkflowを新規追加したPRを発行すると、そのPRに対してworkflowがトリガーされる

workflow_dispatch

workflowを手動実行する際に使用する
「このイベントは、ワークフローファイルがデフォルト ブランチにある場合にのみワークフローの実行をトリガーします。」の記載があるが、
デフォルトブランチにdispatch workflowがあり、他ブランチでそのworkflowを変更、pushした場合は、
以下のように他ブランチを選択して実行することで変更が反映された状態で実行することができる

2024-12-29-11-18-24.png

workflow_call

他のworkflowからworkflowを呼び出す際に使用する
他イベントとは用途が違って、workflowの共通化や、冗長性の解消等に使用する
reusable-workflowsで後述

workflows

workflowのトリガーとなるイベントとjob,stepから構成される

name: Run CI
on: [push, pull_request]

jobs:
  normal_ci:
    runs-on: ubuntu-latest
    steps:
      - name: Run normal CI
        run: echo "Running normal CI"

  pull_request_ci:
    runs-on: ubuntu-latest
    if: ${{ github.event_name == 'pull_request' }}  # イベント名を参照
    steps:
      - name: Run PR CI
        run: echo "Running PR only CI"

上記github.event_nameのようにワークフローの実行、変数、ランナーの環境、ジョブ、ステップに関する情報にはコンテキストを使ってアクセスする

github コンテキストのevent

github.eventにはGitHubのWebhookペイロードが含まれる(例:pull_request

github.eventは、トリガーのイベントによって内容が異なる
そのため、共通処理のreusable-workflowやcomposite-action内でgithub.event.pull_request.head.shaのようなイベント依存の値を参照すると、
pull_request以外のイベントでは参照できないため注意が必要

env

以下のように各階層で環境変数envを定義することができる(変数に情報を格納する抜粋)

name: Greeting on variable day

on:
  workflow_dispatch

env:  # workflowレベルの環境変数
  DAY_OF_WEEK: Monday

jobs:
  greeting_job:
    runs-on: ubuntu-latest
    env:  # jobレベルの環境変数
      Greeting: Hello
    steps:
      - name: "Say Hello Mona it's Monday"
        run: echo "$Greeting $First_Name. Today is $DAY_OF_WEEK!"
        env:  # stepレベルの環境変数
          First_Name: Mona

ただし、workflow_callイベントの場合はトップ階層のenvが使用できない(issues: https://github.com/actions/runner/issues/2372)

on:
  workflow_call:
env:
  env_1: 123
jobs:
  job_1:
    runs-on: ubuntu-latest
    env:
      env_2: ${{ env.env_1 }}  # ERROR (Unrecognized named-value: 'env', Available expression contexts: github, inputs, vars, needs, strategy, matrix, secrets)
    steps:
      - run: echo "hello"

解決方法として、inputsのdefaultで代用することができる

on:
  workflow_call:
    inputs:
      param_1:
        required: false  # 呼び出し元から指定されない前提
        type: string
        default: 123
jobs:
  job_1:
    runs-on: ubuntu-latest
    env:
      env_2: ${{ inputs.param_1 }}
    steps:
      - run: echo "hello"

reusable-workflows

reusable-workflowsworkflow_callイベントによって実行される
以下、reusable-workflowstest_1.ymlworkflowはusesで呼び出す例
secrets: inheritを指定することで、organization、repository、environmentレベルのシークレットを継承できる
ただし、github.tokensecrets.GITHUB_TOKENへのアクセス権は自動的に呼び出し先workflowに付与される(GITHUB_TOKENについてはpermissions参照)

./.github/workflows/test_1.yml
name: 適当なreusable-workflows
on:
  workflow_call:
jobs:
  job_1:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
jobs:
  test_1:
    secrets: inherit # reusable-workflowsへのシークレットの継承
    uses: ./.github/workflows/test_1.yml  # reusable-workflows呼び出し

workflow_dispatch, workflow_callは、workflowに対するパラメータ(inputs)が指定できる
指定できるinputsのtypeはそれぞれ異なり、
workflow_dispatchでinputsに指定できるtype(on.workflow_dispatch.inputs..type)は、boolean、choice、number、environmentまたはstring
workflow_callでinputsに指定できるtype(on.workflow_call.inputs..type)は、boolean、number、または string
また、workflowの出力(outputs)も指定できる
stepの出力をworkflowの出力にする場合、以下のようにsteps → jobs → workflowの順で出力を連携する必要がある

name: Test output

on:
  workflow_call:
    inputs:
      param_1:
        required: true
        type: string
    outputs:
      workflow_output:  # jobsのoutputをworkflowのoutputに連携
        value: ${{ jobs.job_1.outputs.job_output }}

jobs:
  job_1:
    runs-on: ubuntu-latest
    outputs:
      job_output: ${{ steps.output_step.outputs.output_1 }}  # stepsのoutputをjobsのoutputに連携
    steps:
      - uses: actions/checkout@v4
      - id: output_step
        run: |
          output="hello"
          echo "output_1=${output}" >> $GITHUB_OUTPUT

呼び出し元では以下のようにinputsを指定、outputsを参照する

jobs:
  test_1:
    secrets: inherit
    uses: ./.github/workflows/test_1.yml
    with:
      param_1: "test"  # reusable-workflowsのinputs指定
  test_2:
    runs-on: ubuntu-latest
    env:
      test_1_output: ${{ jobs.test_1.outputs.workflow_output }}  # reusable-workflowsのoutputsを参照
    steps:
      - run: |
          echo $test_1_output

job

jobには以下のようにruns-on, permissions, environment, needs, env, steps等を指定できる

jobs:
  test_1:
    ...

  test_2:
    name: Test 2
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write
      pull-requests: write
    environment:
      name: dev
    needs: [test_1]
    env:
      env_1: "abc"
    steps:
      - uses: actions/checkout@v4
      - name: Build Python
        id: build_python
        ...

各Jobはそれぞれ異なる環境のため、
Jobでcheckoutしたソースコード、インストールしたツール、作成したファイル等は他Jobに引き継がれない
そのため、Jobを分けすぎると無駄に環境構築処理が複数回発生し、処理時間の増加につながる
cache(actions/cache)や、artifact(actions/upload-artifact) を使うことでJob間でファイルを共有することができる
cache、artifactについてはGitHub Actions - cacheとartifact参照

runs-on

runs-onにはランナー(jobの実行に使用するimage)を指定する
ubuntu-latestwindows-latest等、基本的には標準のGitHubでホストされたランナーにある中から選択する
各ランナーのリンクから、該当のランナーにインストールされているツールの情報が確認できる(例: ubuntu-latest
ユーザが管理するセルフホステッドランナーを使用することもできる(GitHub Actions - セルフホステッド ランナー(AWS CodeBuild)にて使用方法を記載)

permissions

GitHubの操作を行うActionに使用されるGITHUB_TOKENの権限の変更に使用する
permissionsにある中から選択する
githubコンテキストのtokengithub.tokenGITHUB_TOKENは同じものである
actions/checkoutもGitHub操作であるため、デフォルトでGITHUB_TOKENを使用している(パラメータtokenで変更可能)
GitHub CLI等でGitHub操作をする場合は、以下のように環境変数でGITHUB_TOKENを渡す必要がある(GITHUB_TOKEN シークレットについて抜粋)

name: Open new issue
on: workflow_dispatch

jobs:
  open-issue:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      issues: write
    steps:
      - run: |
          gh issue --repo ${{ github.repository }} \
            create --title "Issue title" --body "Issue body"
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

environment

GitHub Actions - environment と Deployment protection rules参照

needs

workflow内に複数のJobが存在する場合、既定では全Jobは並列実行される
Jobの実行順番を制御するためにはneedsを使用してJobの依存関係を指定する
needsに指定されたJobが成功した場合のみJobが実行される

jobs:
  job1:
  job2:
    needs: job1
  job3:
    needs: [job1, job2]

needsに指定したJobの成功/失敗問わずJobを実行したい場合は以下のようにalways()を使用する

jobs:
  job1:
  job2:
    needs: job1
  job3:
    if: ${{ always() }}
    needs: [job1, job2]

needsに指定したJobの出力(jobs..outputs)は以下のようにアクセスできる

jobs:
  job1:
    runs-on: ubuntu-latest
    # Map a step output to a job output
    outputs:
      output1: ${{ steps.step1.outputs.test }}
      output2: ${{ steps.step2.outputs.test }}
    steps:
      - id: step1
        run: echo "test=hello" >> "$GITHUB_OUTPUT"
      - id: step2
        run: echo "test=world" >> "$GITHUB_OUTPUT"
  job2:
    runs-on: ubuntu-latest
    needs: job1
    steps:
      - env:
          OUTPUT1: ${{needs.job1.outputs.output1}}
          OUTPUT2: ${{needs.job1.outputs.output2}}
        run: echo "$OUTPUT1 $OUTPUT2"

step

ステップでは、コマンドを実行する、設定タスクを実行する、
あるいはactions/checkoutのような公開されたアクションを実行することができる

composite-action

複数stepからなる処理を共通化したい場合等に使用する
実装したcomposite-actionは、.github/actions/{任意の名前}/action.ymlに格納しておく
以下、AWS認証を行うcomposite-actionと実行例

.github/actions/aws-credential/action.yml
name: AWS Credentials Setting
description: Configure AWS credentials

inputs:
  region:
    description: AWS region
    required: true
  account_id:
    description: AWS account
    required: true
  role_name:
    description: Role to assume
    required: true
runs:
  using: "composite"  # composite-action指定
  steps:
    - uses: aws-actions/configure-aws-credentials@v4
      with:
        aws-region: ${{ inputs.region }}
        role-to-assume: arn:aws:iam::${{ inputs.account_id }}:role/${{ inputs.role_name }}
        role-duration-seconds: 3600
jobs:
  aws_:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    environment:
      name: dev
    steps:
      - uses: actions/checkout@v4  # composite-action実行前にcheckoutが必須
      - uses: ./.github/actions/aws-credential
        with:
          account_id: ${{ vars.ACCOUNT_ID }}
          region: ${{ vars.REGION }}
          role_name: ${{ secrets.ASSUME_ROLE_NAME }}

composite-action実行前にcheckoutが必須となる

composite-action内ではsecretsが参照できない、そのためsecretsを使用する場合はinputsで渡す必要がある

composite-action内ではコマンド実行(run)を行う際に、shell: bashのようにshell指定が必須となる

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?