GitHub Actions を AWS CodeBuild で実行する

| 4 min read
Author: noboru-kudo noboru-kudoの画像

代表的なCI/CDサービスの1つになったGitHub Actionsですが、その大きな強みの1つにエコシステムの充実度があげられます。
GitHub マーケットプレイスを覗くと、数多くのActionsが公開されており、様々なツール・サービスとの統合が簡単にできるようになっています。

AWSにもCodeBuildやCodePipeline、CodeDeployといったCI/CDのマネージドサービスがあります。
これらはAWSが提供するサービスだけに、AWSリソースと高度に統合されてます。これはAWS中心のプロジェクトでは効率が良いですが、AWS外のツールやサービスを使う場合はシェルで頑張るというケースが多いのかなと思います。

そんな中、AWSからCodeBuildでGitHub Actionsの実行をサポートすると発表がありました。

最初は、GitHub ActionsのセルフホステッドランナーとしてCodeBuildが使えるようになったのかなくらいに思っていましたが、そうではなくジョブはCodeBuildとして動作するようです。
さらに、VCSとしてGitHub以外も利用可能だったり、制限はありますがGitHub Actionsのマーケットプレイスで公開されているActionsも利用可能です[1]

これは。。と思いましたので早速試してみました。

GitHubとの接続設定

#

GitHub以外のVCSで動かすのになぜ必要なのかと思いましたが、公式ドキュメントを見ると以下のように記載がありました。

Why do I need to connect to GitHub as a source provider in order to use GitHub Actions?

In order to use GitHub Actions, the source must be downloaded on a build compute. Anonymous downloads will be rate limited, so by connecting to GitHub, it can help ensure consistent access.

ActionsをGitHubからダウンロードする際のRateリミットを回避するために、GitHubとの接続設定が必要なようです。

この方法として、公式ドキュメントでは管理コンソール経由(OAuth)またはCLIでアクセストークンをCodeBuildに設定する方式が説明されています。
今回はCLIの方で実施しました。

事前にGitHubからパーソナルアクセストークンを発行し、以下AWS CLIで登録します。

# アクセストークンをGITHUB_TOKENに設定
aws codebuild import-source-credentials --token ${GITHUB_TOKEN} \
--server-type GITHUB --auth-type PERSONAL_ACCESS_TOKEN

登録したアクセストークンは、以下コマンドから確認できます。

aws codebuild list-source-credentials
{
"sourceCredentialsInfos": [
{
"arn": "arn:aws:codebuild:ap-northeast-1:xxxxxxxxxxxx:token/github",
"serverType": "GITHUB",
"authType": "PERSONAL_ACCESS_TOKEN"
}
]
}

GitHub Actionsを利用する準備はこれで完了です。

CodeBuildプロジェクト

#

CodeBuildの作成は、GitHub Actionsを使わない場合と基本変わりません。

今回はAmazon Linux2で最新のイメージをセットアップしました。
また、VCS(ソース)にはGitHubでなくCodeCommitを指定し、Serverless FrameworkベースのLambdaソースコードをコミットしておきました。

唯一の注意点として、利用予定のActionsでコンテナを使う場合は特権モードを設定する必要があります。

CodeBuild - enable privilege mode

今回利用予定のServerless FrameworkのActionsは、コンテナベースのため特権モードを有効にしました。

BuildSpec

#

作成したCodeBuildプロジェクトには、以下のBuildSpecを登録しました。

version: 0.2

env:
variables:
STAGE: "prod"
parameter-store:
DOCKER_PASS: /dockerhub/password

phases:
pre_build:
commands:
# Actionsが登録されているDockerHubのRateリミット回避
- echo ${DOCKER_PASS} | docker login --username <docker-username> --password-stdin
build:
# GitHub Actions
steps:
- uses: actions/setup-node@v3
with:
node-version: 20
- run: npm ci
- run: npm run test
- if: ${{ env.STAGE == 'prod' && success() }}
name: serverless deploy
uses: serverless/github-action@v3
with:
args: deploy
- if: ${{ failure() }}
run: echo "github action failed!!"

一見すると通常のCodeBuildのBuildSpecですが、buildフェーズ配下がcommandsではなく、stepsとなっています。
この部分の記述がGitHub Actionsのものとなっています。
ここでactions/setup-nodeserverless/github-actionsといったGitHub Actionsのマーケットプレイスに登録されているものを使っています。
iffailure()等の関数もGitHub Actionsの仕様と同じです。環境変数の参照などはCodeBuildのものも使えます(この例だとenv.STAGE)。
詳細な仕様は以下公式ドキュメントを参照してください。

もちろん、GitHubの外で実行されますので、利用可能なActionsには制約があります。
github contextに依存するものや、プルリクエストやIssue等、GitHub自体を操作するものは利用できません。
制約の詳細は公式ドキュメントを参照してください。

なお、ここではbuildフェーズ配下に記述していますが、stepsは任意のフェーズで記述可能です。ただし、commandsとの併用はできないようです。

CodeBuildジョブ実行

#

CodeBuildの実行方法は、GitHub Actions利用有無で変わりません。
スクショ等は省略しますが、steps配下に記述した通りv20系のNode.jsがセットアップされ、インストール・テスト後に、Serverless FrameworkでLambda関数がデプロイされている様子が確認できました。

ちなみに、GitHub接続をしていない場合は以下のエラーが出ました。

GitHub接続設定をしない状態だとstepsは有効にならないようです。

最後に

#

使えるActionsに制限はありますが、成熟したエコシステムを持つGitHub ActionsをCodeBuildで利用することで、両者のいいとこ取りができるようになりました。

個人的には、GitHub Actionsのエコシステムをそのまま取り込む戦略には違和感はありましたが、今後の動向に注目していきたいと思いました。


  1. GitHub Actionsのエコシステムにタダ乗りな感じですが、GitHub側の承諾は取っているんでしょうかね。。。 ↩︎

豆蔵デベロッパーサイト - 先週のアクセスランキング
  1. 基本から理解するJWTとJWT認証の仕組み (2022-12-08)
  2. AWS認定資格を12個すべて取得したので勉強したことなどをまとめます (2022-12-12)
  3. Nuxt3入門(第4回) - Nuxtのルーティングを理解する (2022-10-09)
  4. Backstageで開発者ポータルサイトを構築する - 導入編 (2022-04-29)
  5. Nuxt3入門(第8回) - Nuxt3のuseStateでコンポーネント間で状態を共有する (2022-10-28)
  6. Viteベースの高速テスティングフレームワークVitestを使ってみる (2022-12-28)
  7. ORマッパーのTypeORMをTypeScriptで使う (2022-07-27)
  8. Nuxt3入門(第1回) - Nuxtがサポートするレンダリングモードを理解する (2022-09-25)
  9. GitHub Actions - 構成変数(環境変数)が外部設定できるようになったので用途を整理する (2023-01-16)
  10. Jest再入門 - 関数・モジュールモック編 (2022-07-03)