🐡

Github actionの基礎をまとめてみた!

2023/02/12に公開

構成

自動したい処理は
.github/workflow配下に設置する

job: job一つに一つの仮想マシーンが割り当てられるイメージ
step: 処理の実態、なんの処理をするかを記載する

簡単な例
https://github.com/hirosi1900day/ecs-lesson-cicd/blob/main/.github/workflows/ci-workflow.yml

name: CI flow for Amazon ECS <=ワークフロー名
on: [push] <= トリガー
env:
  SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
jobs:
  ci:
    name: ci
    runs-on: ubuntu-latest <= 実行環境
    timeout-minutes: 10
    steps: <= 実際の処理
    - name: Checkout
      uses: actions/checkout@v2
    - name: Unit Test
      run: cd ${{ github.workspace }}
    - run: cd webapp && npm install && npm run test:unit
    - name: Success
      uses: rtCamp/action-slack-notify@v2.0.2
      if: success()
      env:
        SLACK_TITLE: CI flow / Success
        SLACK_COLOR: good
        SLACK_MESSAGE: Message for Success

    - name: Failure
      uses: rtCamp/action-slack-notify@v2.0.2
      if: failure()
      env:
        SLACK_TITLE: CI flow / Failure
        SLACK_COLOR: danger
        SLACK_MESSAGE: Message for Failure

    - name: Cancel
      uses: rtCamp/action-slack-notify@v2.0.2
      if: cancelled()
      env:
        SLACK_TITLE: CI flow / Cancel
        SLACK_COLOR: danger
        SLACK_MESSAGE: Message for Cancel

トリガーについて

イベント発生のきっかけになるのも主な種類

  • push: これはそのままでpushされたときに起動する。ブランチを限定したり、ファイルを限定またはタグ指定したりすることができる


もちろんpathとブランチを一緒に指定することも可能

  • pull_request: プルリクエストがマージされたときに実行する。ブランチ指定, pathなども可能

  • schedule: cron形式で指定し、定期的に実行する。デフォルトブランチでないと起動しないの注意

  • workflow_dispatch: githubのwebページからの手動実行、またはapiを叩くことでの実行

on:
  workflow_dispatch:

引数を使用する場合

on:
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level' <= 説明
        required: true <= 引数が必須かどうか
        default: 'warning' <=デフォルト値
        type: choice <= 引数の型
        options: <= choiceの時は選択肢 string, boolean, numberなどあり
        - info
        - warning
        - debug 
      print_tags:
        description: 'True to print to STDOUT'
        required: true 
        type: boolean 
      tags:
        description: 'Test scenario tags'
        required: true 
        type: string
      environment:
        description: 'Environment to run tests against'
        type: environment
        required: true 
  • workflow run: ワークフローの依存関係で実行するもの。ワークフローが要求または完了すると実行する

使い所としてはワークフローを再利用したい時で、ビルドは同じものを使いリリースのワークフローは分けたいなどが挙げられます。

on:
  workflow_run:
    workflows: ["Build"] <= 依存元のワークフロー名を指定
    types: [requested] <= requestかcompletedを指定し、requestなら要求されたら実行、completedなら完了したときに実行する
    branches:   <= ブランチしてもでき特定のブランチのみで実行するようにすることが可能
      - 'releases/**'
      - '!releases/**-alpha'

concurrencyについて

GitHub Actionsは、GitHubリポジトリ内で自動化されたワークフローを実行するためのツールで、一連のコマンドを定義してそれらを自動的に実行できます。ワークフローは、特定のイベント(例えば、プルリクエストの作成や新しいコミットのプッシュなど)が発生すると実行されます。

ここで「Concurrency」は、同時に実行できるタスクの数を指します。GitHub Actionsでは、無料アカウントと有料アカウントで同時に実行できるジョブの数に制限があります。例えば、無料アカウントでは一度に20のジョブを実行できます。これは、システムリソースの公平な利用を確保するためのものです。

特定のワークフローまたはジョブの「Concurrency」を設定することにより、そのワークフローまたはジョブの同時実行インスタンスの数を制限することができます。これは特に、順序に敏感なタスクやリソースに対する競合を防ぐために有用です。

たとえば、次のようなワークフロー定義では、同じブランチからのプッシュに対して同時に1つのワークフローのみが実行され、新しいワークフローが開始されると前のワークフローがキャンセルされます:

concurrency: 
  group: ${{ github.head_ref }}
  cancel-in-progress: true

上記の定義では、groupキーで一意の識別子を設定し(この場合はブランチ名)、cancel-in-progressをtrueに設定することで、同じグループの新しい実行が開始されると進行中の実行がキャンセルされることを指定しています。

jobについて

job毎にランナーと呼ばれる実行環境が用意される

jobs:
  ci: <= ジョブのid このidを使ってjobを指定することもできる
    name: ci <= job名
    runs-on: ubuntu-latest <= 実行環境
    timeout-minutes: 10
    steps: <= 実際の処理
    - name: Checkout
      uses: actions/checkout@v2
    - name: Unit Test
      run: cd ${{ github.workspace }}

ランナーとは
job単位で作成され実際に実行されるサーバーのイメージ
gtihubのランナーを使うことも可能ですし、自前のサーバーをランナーとして扱うことも可能
githubから提供されるlinuxの種類

  • linux
  • windows
  • macOS

代表的なlinux ubuntに含まれるパッケージの紹介

stepについて

実際に処理を記載する部分
runちusesがある
run: shell scriptを書く
uses: マーケットプレイスに公開されているものを指定または自分で作成して使うことも可能

jobs:
  ci: <= ジョブのid このidを使ってjobを指定することもできる
    name: ci <= job名
    runs-on: ubuntu-latest <= 実行環境
    timeout-minutes: 10
    steps: <= 実際の処理
    - name: Checkout <= step名
      id: test <= stepのid(必要に応じて書く)
      run: |  <= shell script記載
        echo "test${NAME}" 
	echo 'test'
      env: <= 環境変数指定 run内で使用
        NAME: hogehoge
            shell: bash  <= シェルを指定可能
            working-directory: tmp <=シェルを実行する場所を指定できる
    - name: Unit Test
      run: cd ${{ github.workspace }}

ディレクトリーやshellなど毎回条件を指定するのは面倒なのでデフォルト環境が設定できるようになっている

usesについて

jobs:
  ci:
    name: ci
    runs-on: ubuntu-latest <= 実行環境
    timeout-minutes: 10
    steps: <= 実際の処理
    - name: Checkout
      uses: actions/checkout@v2 <= 使うアクション指定
      with:
        fetch-depth: 0 <= アクションの引数

環境変数

これはご存じのとおり、サーバー内の同一環境であればどこからでも参照できる変数のこと
github actionが事前に登録している環境変数もあるので記載します。
実行している実行環境の値を取得することができます。

利用例

  • GITHUB_SERVER_URL, GITHUB_REPOSITORY, GUTHUB_RUN_ID
    これら3つの情報を組み合わせるとワークフローURLが取得できる
$GITHUB_SERCER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID

slackで実行して結果を送信したいなどがあればこれで作成したURLを送信すればOK

  • GITHUB_ENVの使い方
    実はgithub actionではstepごとにシェルを起動させ、初期化、スクリプト実行します。
    初期化の際にGITHUB_ENVの値を読み込んで起動するので、job間, step間で共有したい値があればGITHUB_ENVに書き込めばOK!

  • GITHUB_STEP_SUMMARY
    下記の部分に表示されるようになる

シークレット

秘密情報などは直接workflowには書かずgithubのシークレットを使って利用します。登録された情報は***に置き換えられる。

外部から見られたくない情報などは
${{ secrets.HOST }}などのようにして使用します。

式とコンテキスト

式: ワークフローの中でコンテキストを参照,または演算を行うもの
コンテキスト: ワークフロー実行状態, 実行環境など各種環境情報を保存したデータ

代表的にコンテキスト

job間の依存関係を明示する方法

下記のようにneedsを使うことでjob2はjob1の次に実行されるようになる

jobs:
  job1:
  ....
  job2:
    needs: job1

複数も指定できる
下記のようにするとjob1とjob2が正常終了してからjob3を実行するようになる

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

エラー処理方法

github actionではstepでエラーが発生すると、そのstepの後続のコマンドや後続のstep、jobすべて実行されなくなります。
しかしエラーが発生した際に何かしらの処理をする方法をgithub actionはいくつか準備しているので紹介します。

  • bash +e {0}
    下記のようにすることでstepでエラーが発生してもそこで止まらず後続処理も実行されるようになる

注意点としては後続処理は実行されるが、実行の結果は失敗となるので後続のstepやjobは実行されないようになる

step:
  name: sample
  shell: bash +e {0}
  run: echo "test"
  • continue-on-error: true

エラーが発生しても無視したい時に使用する

利用したいケースとしてはそもそも失敗する可能性がある
静的解析や単体テストなどを実行する際に使用します。

注意点としては実行結果は必ず成功になるので後続のstepやjobも実行される

step:
  name: sample
  continue-on-error: true
  run: echo "test"

jobで使用する場合は

jobs:
  job1:
    name: test
    run-on: ubuntu-latest
    continue-on-errors: true
    step:.......

利用シーンとしてはstepとほぼ同じですが、jobでcontinue-on-errors: trueを使うと
job内のstepで失敗した際にはjob内の後続のstepは実行されないがjobは成功扱いになることを注意しないといけない

実行環境出力, 取得方法

  • stepの結果確認方法
jobs:
  job1:
    name: test
    run-on: ubuntu-latest
    continue-on-errors: true
    step:
      - id: step1 <= idを設定する
        name: test
        run: echo "hollow world"
      - run: echo "step1 resul: ${{steps.step1.conclusion}}" 
      - run: echo "step1 resul: ${{steps.step1.outcome}}" 
      

steps.step1.conclusionはcontinue-on-errorsで無効化された結果を取得(すなわちからず成功が得られる)
steps.step1.outcomeはcontinue-on-errorsで無効化される前の結果を取得

  • step間での情報共有方法

set-outputがあるがこれは2023の6月から使えなくなるようなので記載を省略します。

1,環境変数を使った受け渡す方法
GITHUB_ENVにデータを受け渡すことでstep間で値の共有が可能になる
stepでプロセス起動時にGITHUB_ENVの情報を読み込みシェルを立ち上げるため

jobs:
  job1:
    name: test
    run-on: ubuntu-latest
    continue-on-errors: true
    step:
      - id: step1 <= idを設定する
        name: test
        run: echo "test=world" >> $GITHUB_ENV
	
	別ステップ
	run: echo "message: ${test}"
	run: echo "message: ${{ env.test }}"

2, ローカルファイルに保存してしまう

jobs:
  job1:
    name: test
    run-on: ubuntu-latest
    continue-on-errors: true
    step:
      - id: step1 <= idを設定する
        name: test
        run: echo "test" > message.txt
	
	別ステップ
	run: cat message.txt
  • job間での情報共有方法

1, jobの実行結果を表示する
needを使いjob間の依存関係を定義し、needs.job名.resultで取得することができる

1-1, jobで情報を共有する

条件分岐

if always()
if failure()
if success()
if canceled()
がある

stepでの例

jobs:
  job1:
    name: test
    run-on: ubuntu-latest
    continue-on-errors: true
    step:
      - id: step1 <= idを設定する
        name: test
	if always()
        run: echo "test" > message.txt

jobでの例

jobs:
  job1:
    name: test
    if always()
    run-on: ubuntu-latest
    continue-on-errors: true
    step:
      - id: step1 <= idを設定する
        name: test
        run: echo "test" > message.txt

Discussion