EmotionTechテックブログ

株式会社エモーションテックのProduct Teamのメンバーが、日々の取り組みや技術的なことを発信していくブログです。

GitHub Actions ワークフローの手引きの手引き

はじめに

こんにちは、バックエンドエンジニアのよしかわです。

今回の記事は弊社内でも CI/CD で便利に活用している GitHub Actions についてのものです。GitHub Actions の既存ワークフローの手入れやレビューをしたいが勝手が分からないという方向けに、簡単なワークフローを題材とした公式ドキュメントの紹介をしてみようと思います。

なお本稿が日本語のため、参照するドキュメントも日本語版にしています。より正確な情報が求められる場合などは必要に応じて英語版もご参照ください。

題材

公式ドキュメントの例よりさらに簡単な下記のワークフローを題材にします。GitHub を使ったことがあれば動作は概ね想像がつくのではないかと思います。

YAML

name: Test

run-name: "Test: ${{ github.event.pull_request.title }}"

on:
  pull_request:

jobs:
  test:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v3
      - run: make test
      - run: echo '::notice::finished'
  on_failure:
    needs: test
    if: ${{ failure() }}
    permissions:
      contents: read
      pull-requests: write
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v3
      - name: Comment on PR
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
        run: |
          cat <<EOF | gh pr comment "$PR_NUMBER" --body-file -
          Something wrong.
          Please check $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID
          EOF

このワークフローの詳細を確認する際とくに役立つドキュメントの一覧が下記です。

場所 ドキュメント
青色の実線で囲まれた部分 GitHub Actions のワークフロー構文
シェルスクリプト(run部分)の実行環境: サポートされているソフトウェア, 既定の環境変数
赤色の細線で囲まれた部分 ワークフローをトリガーするイベント
黄色の実線が下に引かれた部分 文法、関数:
変数の中身: コンテキスト
注意: スクリプトインジェクションのリスクを理解する
緑色の破線が下に引かれた部分 GitHub Actions のワークフロー コマンド

以降はこれらのドキュメントを参照しながら、題材のワークフローのいくつかの部分について挙動を確認していきます。

ワークフロー構文

まずは左側の青い実線で囲まれた部分、つまりワークフローの骨格部分です。これは GitHub Actions のワークフロー構文というページに詳しく、namerun-name などの項目ごとに説明が記載されています。runuses について少しだけ見てみます。

例: シェルスクリプトの呼び出し (run)

jobs.<job_id>.steps[*].run を見ると、シェルスクリプトの実行に使うシェルコマンドを jobs.<job_id>.steps[*].shell で指定可能なことやそのデフォルト値などが分かります。

なおシェルスクリプトからデフォルトで利用可能なソフトウェアや環境変数は下記に記載されています。題材のワークフローで使っている GitHub CLI (gh コマンド) も載っています。

例: ワークフローやアクションの呼び出し (uses)

実は uses には次の2種類があり使い方が異なるので少し注意が必要です。題材のワークフローで使っているのは後者の方です。

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

次に赤い細線で囲まれた pull_request: の部分、より正確に言えば on: の中身の部分です。これはワークフローをトリガーするイベントというページにまとめられています。

例: プルリクエス

今回の例では pull_request: にとくにパラメータを与えず利用していますが、説明を見るとそのような場合の動作も記載されています。

このイベントは、2つ以上の種類のアクティビティで起動されます。それぞれのアクティビティの種類については、「Webhook のイベントとペイロード」をご覧ください。 既定では、ワークフローは、pull_request イベントのアクティビティの種類が openedsynchronize、または reopened の場合にのみ実行されます。

説明にしたがって Webhook のイベントとペイロードを見ると、例えば syncrhonize は(2023/8/15時点では未訳のようですが)ベースブランチを変更したり新しいコミットをプッシュしたりしたときを表していることが分かります。

A pull request's head branch was updated. For example, the head branch was updated from the base branch or new commits were pushed to the head branch.

ところで冒頭の例のワークフローを変更するプルリクエストを作成した場合、そのプルリクエストでは変更前と変更後のどちらのワークフローが実行されるでしょうか。

手掛かりはワークフローのトリガーの下記の記述にあります。

各ワークフロー実行では、そのイベントに関連付けられたコミット SHA または Git ref に存在するワークフローのバージョンが使用されます。 ワークフローが実行されると、GitHub によってランナー環境の GITHUB_SHA (コミット SHA) と GITHUB_REF (Git ref) の環境変数が設定されます。

つまり GITHUB_SHA が指すコミットが何か分かればよいことが分かります。実はこれもワークフローをトリガーするイベントの各項目に記載されています。気になる方は確かめてみてください。ついでに pull_requestpull_request_target を比べてみてもいいかもしれません。

式とコンテキスト

今度は黄色の下線が引かれた部分、すなわち ${{}} で囲まれた部分です。次の2ページが参考になります。

    • ${{}} の間に書ける式の構文や型、利用可能な関数などが説明されています。
  • コンテキスト
    • 式の中で参照可能な各オブジェクトが説明されています。
    • ただしワークフロー中の全ての式で全てのオブジェクトを参照できるわけではありません。どの部分の式でどのオブジェクトを参照可能かは GitHub Actions のワークフロー構文の中で述べられています。

ただしこの機能は注意して使わないとコマンドインジェクションの温床になってしまいます。公式ブログの Four tips to keep your GitHub Actions workflows secure という記事では、悪い例として下記のような書き方が挙げられています。 run${{ }} の組み合わせは要注意と思っておくのが良いでしょう。

- name: print title
  run: echo "${{ github.event.issue.title }}"

公式ドキュメントの GitHub Actions のセキュリティ強化というページには様々なセキュリティ強化策が説明されており、インジェクション攻撃についても下記の項で解説されていて参考になります。

例: github コンテキスト

題材のワークフローでは、例えば run-name の部分であれば下記のように github コンテキストを参照可能です。

この値には式を含めることができ、github および inputs コンテキストを参照することもできます。

さらにリンクを辿ると github.event にはイベントの種類に応じたオブジェクトが格納されていることや、プルリクエストの場合には .pull_request.title が存在することも分かります。

ワークフローコマンド

最後は緑色の破線が引かれた部分です。このように特定の形式で echo したり(今回の例では割愛してしまいましたが)特別なファイルに書き込んだりすると、ワークフローコマンドという機能を利用できます。GitHub Actions のワークフロー コマンドというページに説明がある通り下記のようなことが可能です。

  • 実行結果を分かりやすく表示する
  • 秘匿情報をマスクする
  • あるステップ(steps の要素)から後続のステップに環境変数を引き継ぐ

例: notice

題材のワークフローでは通知メッセージの設定を利用しています。この方法で出力したメッセージは下記画像の下線部のようにワークフローの実行ログとは別に表示されます。実行結果のうち注意が必要な部分の出力に用いると便利かもしれません。

おわりに

簡単なワークフローを題材に GitHub Actions のドキュメントの一部を紹介いたしました。既存のワークフローに少し手を入れてみようかなと思う方のお役に立てば幸いです。

エモーションテックでは顧客体験、従業員体験の改善をサポートし、世の中の体験を変えるプロダクトを開発しています。この記事や他の記事を見て少しでも弊社に興味をもっていただけましたら、ぜひ採用ページからご応募をお願いいたします。

hrmos.co hrmos.co hrmos.co