※この情報は2021/12/17現在のものです。
はじめに
本記事は、これからGithub Actionsの導入を検討している方に向けて記載しております。
最近業務でGitHub Actionsを使うようになりましたので、その中で勉強してわかったことをつらつらとまとめます。
詳細な仕様につきましてはGitHub公式サイトのドキュメントが充実しておりますのでそちらをご確認ください。
背景
弊社スタンバイでは現在、CI/CDツールとしてJenkinsとAWS CodeBuildをメインに利用しており、JenkinsからCodeBuildをキックする構成としております。
しかし、この構成だと以下の問題点がございました。
- ビルドの設定がJenkinsとAWS CodeBuildで分かれるため、運用コストがかかる
- GitHubをトリガーとしてJenkinsジョブを起動する場合、Webhookを作成する必要がある
- Serverless FrameworkなどをJenkinsから実行するためには、JenkinsのslaveサーバにNode.js/pythonなどをインストールする必要があり、環境競合発生の可能性がある
これらの問題があるため、Github Actionsの導入を検討しておりました。
現在、Serverless Frameworkのデプロイ及び一部のサービスのビルドにつきましてはGithub Actionsを実際に導入しております。
GitHub Actionsとは
GIthub Actionsとは、GitHubが提供するCI/CDシステムです。
ランナーとして提供されるOSはLinuxだけでなく、Windows/macOSも提供されています。
セルフホストランナーを自前環境に構築してGitHub Actionsを実行できますのでオンプレ環境でも使えます。
料金
料金はGitHubのサイトに詳細が書かれています。
パブリックリポジトリ及びセルフホストランナーの場合は無料、プライベートリポジトリの場合でも契約しているプランに応じて無料枠があるため、GitHubを既に利用している場合使い始めやすいのではないでしょうか。
GitHub Actionsの始め方
リポジトリ直下の .github/workflows ディレクトリに任意の名称のymlファイルを作成することによって、ワークフローを作成できます。
サンプルのワークフローを定義して実行結果を確認してみます。
.github/workflows/learn-github-actions.yml
name: learn-github-actions on: [push] jobs: check-bats-version: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: node-version: '14' - run: npm install -g bats - run: bats -v
GitHubにpushします。
git add .github/workflows/learn-github-actions.yml git commit -m "first github actions workflow" git push origin main
Actionsのタブを見ると、pushしたワークフローを確認できます。
今回サンプルで追加したワークフローはリポジトリへのpushをトリガーとして動くため、既に動いていることが確認できます。
グリーンのチェックが実行成功のマークです
クリックして中身を確認すると、実行ログを確認できます。
例では全てのブランチに対してのpushをトリガーとして動くワークフローを作成してみましたが、他にも色々なトリガーがあります。
もちろん特定のブランチに対するpushで動くワークフローも作成可能です。
GitHubと高度に統合されており、様々な操作をトリガーとしてワークフローを起動できるのはGitHub Actionsの強みではないでしょうか。
AWSとの連携
Github Actionsのランナー環境にはAWS CLIなど主要なCLIやモジュールがインストールされているので、わざわざインストールするステップを入れることなくAWSの各種リソースを操作できます。
https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-README.md
クレデンシャルの設定やECRログインなども、AWS公式から提供されているGitHub Actions用テンプレートがあるため、1ステップで簡単に行う事ができます。
クレデンシャルはアクセスキーだけではなく、OIDCにも対応しています。
今回はアクセスキーでの設定例を書きます。
.github/workflows/aws-actions-sample.yml
name: aws-actions-sample on: workflow_dispatch: jobs: test: name: aws test runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: s3 list run: | aws s3 ls
Settings→Secretsで設定できるRepository secret
に入れておきます。
今回はトリガーをworkflow_dispatch
としているので、Actionsのタブから手動で実行します。
実行できていることが確認できます。(今回の例ではs3 lsコマンドが成功しています)
また、AWSアカウントが開発と本番で分かれているなど、環境が分かれているケースではEnvironment secretsが利用できます。
ymlにenvironment
の記述(とついでにワークフロー実行時引数)を追加します。
.github/workflows/aws-actions-sample-environment.yml
name: aws-actions-environment-sample on: workflow_dispatch: # ワークフロー実行時の引数 inputs: env: type: choice options: - dev - prod description: '環境' jobs: test: # environment設定を追加 # 値はワークフロー実行時の引数を設定 environment: ${{ github.event.inputs.env }} name: aws test runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: s3 list run: | aws s3 ls
Settings→Environmentsからenvironmentを作成し、その中にAWSのアクセスキーとシークレットキーを登録します。
今回はdevとprodのenvironmentを作成し、それぞれにAWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KEY
を設定しました。
なお、Repository secret
にも同名のキーが設定されていた場合、Environment secrets
が優先されます。
ワークフロー実行時にenvを指定すると、指定したenvironmentからシークレットを取得してAWS CLIを実行できます。
なお、workflow_dispatch
をトリガーとした場合、UIからの実行以外に、APIからも実行が可能です。
# OWNER: ワークフローを定義しているリポジトリのownerを指定 # REPO: ワークフローを定義しているリポジトリの名前を指定 curl -f \ -X POST \ -H "Accept: application/vnd.github.v3+json" \ -H "Authorization: Bearer ${GITHUB_TOKEN}" \ https://api.github.com/repos/${OWNER}/${REPO}/actions/workflows/aws-actions-sample-environment.yml/dispatches \ -d "{\"ref\": \"main\", \"inputs\": {\"env\": \"prod\"}}"
Composite Action
ワークフローを書いていると、セットアップなどで同一ステップを複数のワークフローに書くことが増えてきます。
複数のステップをまとめて再利用可能なActionに定義できる機能として、Composite Actionが提供されています。
Composite Actionのファイル名は action.yml である必要があります。
Composite Actionは利用する側と同じリポジトリに定義することも、別リポジトリに定義もできます。
今回の例では利用する側と同じリポジトリに定義しています。
composite-action/init/action.yml
name: "setup library" inputs: node-version: default: '14.x' required: false description: 'version of nodejs' runs: using: "composite" steps: - name: Set up Node.js uses: actions/setup-node@v1 with: node-version: ${{ inputs.node-version }}
Composite Action利用側はuses
で呼び出します。
.github/workflows/composite-action-sample.yml
name: composite-action-sample on: workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v2 - name: Initialize # Composite Actionを相対パスで指定 # Composite Actionが別リポジトリにある場合は{owner}/{repo}/{path}@{ref} # owner: Composite Actionを定義しているリポジトリのownerを指定 # repo: Composite Actionを定義しているリポジトリの名前を指定 # path: Composite Actionを定義しているパスを指定 # ref: Composite Actionのブランチまたはタグを指定(mainなど) uses: ./composite-action/init with: node-version: 16.x
注意点
- Composite Actionを利用側とは別リポジトリにする場合、そのリポジトリは パブリックリポジトリ にする必要があります。
プライベートリポジトリにする場合は、Composite Actionと利用側が同じリポジトリにいる必要があります。
(この点が不便で、プライベートリポジトリにComposite Actionを集めたいケースもありますが、今のところそれができないです) - Composite Action側のログは1つのステップにまとめられて表示されるため、地味に見づらいです。
- 利用側で設定した環境変数はComposite Action側でも参照できますが、シークレットは参照できないのでinputで渡す必要があります。
なお、Composite Actionにシークレットを渡した場合でも、Composite Action側のログはちゃんとマスクされます。
Reusable Workflow
ワークフロー内のステップを共通化する方法としてComposite Actionを紹介しましたが、もう1つ共通化する方法としてResuable Workflowがあります。
こちらはワークフロー自体を他のワークフローから呼び出せる機能となります。
Composite Actionは一部処理を共通化するものですが、ビルド→デプロイなど一連のフローを共通化する際に利用できます。
また、Composite Actionと比べて処理内でcheckoutを実行すると以下の違いがあります。
- Composite Action
- Composite Actionを定義している側のリポジトリのリソースをcheckout
- Reusable Workflow
- Reusable Workflowを利用している側のリポジトリのリソースをcheckout
なのでcheckoutも含めて共通化して別リポジトリに定義する場合はReusable Workflowの方が使いやすいです。
実際にResuable Workflowを書いてみます。
Resuable Workflowはワークフローの一種なので、 .github/workflows の中に作る必要があります。
.github/workflows/reusable-workflow.yml
name: Reusable workflow example on: # Reusable Workflowはworkflow_call workflow_call: inputs: command: required: true type: string env: required: true type: string # secretの設定 secrets: access_key_id: required: true secret_access_key: required: true jobs: example_job: # Environment Secretを使う場合はReusable Workflow側で設定 environment: ${{ inputs.env }} name: exec aws command runs-on: ubuntu-latest steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: ${{ secrets.access_key_id }} aws-secret-access-key: ${{ secrets.secret_access_key }} aws-region: ap-northeast-1 - name: aws ${{ inputs.command }} run: | aws ${{ inputs.command }}
.github/workflows/call-reusable-workflow.yml
name: Call a reusable workflow on: workflow_dispatch: inputs: env: type: choice options: - dev - prod description: '環境' jobs: call-workflow: # owner: Reusable Workflowを定義しているリポジトリのownerを指定 # repo: Reusable Workflowを定義しているリポジトリの名前を指定 # path: Reusable Workflowを定義しているパスを指定 # filename: Reusable Workflowのファイルの名称を指定 # ref: Reusable Workflowのブランチまたはタグを指定(mainなど) uses: {owner}/{repo}/{path}/{filename}@{ref} with: env: ${{ github.event.inputs.env }} command: s3 ls # Resuable Workflowで使うsecretを渡す secrets: access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
Reusable Workflow側のログはそれぞれのステップごとに分かれるので見やすいです。
注意点
- Composite Actionと同じく利用側とは別リポジトリにする場合、そのリポジトリは パブリックリポジトリ にする必要があります。
- Resuable Workflow呼び出し側で設定した環境変数はResuable Workflow側には反映されません。
なので引数でResuable Workflow側に渡してあげる必要があります。
ワークフローの配置戦略
Composite Action/Reusable Workflowの注意点に記載した通り、別リポジトリに定義する場合はパブリックリポジトリにする必要があります。
弊社では全てのリポジトリをプライベートリポジトリとして運用しているため、パブリックリポジトリとすることは許容できません。
なので、弊社では1つのリポジトリに主要なワークフローを集める方針としました。
- GitHub Actionsのワークフロー用リポジトリを作成
そこにデプロイなどのワークフローを作成 - ワークフロー用リポジトリに定義した各ワークフローで使う共通処理(ビルドなど)をComposite Actionとして同リポジトリに定義
- 各ワークフローでは各アプリケーションリポジトリをcheckoutしてビルドを実行
- 各アプリケーションのリポジトリには、必要に応じてPRのマージなどをトリガーとして起動するワークフローを作成 ワークフロー用リポジトリに定義されたワークフローをAPIでcall
これで各アプリケーションリポジトリに同じワークフローが分散することを防ぎつつ、Composite Actionで共通化ができます。
他にも、そもそも同じワークフローが必要なアプリケーションは1つのリポジトリにまとめてしまうなどの案もありましたが、移行工数などの観点から断念しました。
その他Tips
デバッグロギング
https://docs.github.com/ja/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging
Repository secret
にACTIONS_STEP_DEBUG
をtrueで設定すれば詳細なログを出力できます。
ローカルでワークフローを実行する
GitHubの公式ツールではありませんが、上記のようなツールがあります。
まとめ
GitHub Actionsはテンプレートも充実しており、簡単に、かつパブリックリポジトリなら無料で実装できるのでかなり便利だと思いました。
ただ、Composite Action/Reusable Workflowのパブリックリポジトリにしか配置できないなど、若干痒いところに手が届かない的な部分もまだまだあります。
どんどん新しい機能が追加されて使いやすくなっていってるようですので、是非皆さんも試してみてください。
本記事が、これからGitHub Actionsを始めようとされている方の理解の一助になれば幸いです。
スタンバイのプロダクトや組織について詳しく知りたい方は、気軽にご相談ください。