😀

MackefileとactでGHAワークフローのaws-cliをローカルでテストする

2024/12/28に公開

はじめに

GitHub Actionsは、CI/CD環境を簡単に構築できる便利なツールですが、実際にワークフローを開発する際、GitHub上で動かしながらテストするのは少し手間がかかりますよね。

そこでおすすめなのが、ローカル環境でGitHub Actionsをシミュレートできるツール「act」です。このツールを使えば、ローカルで素早くワークフローを確認でき、作業効率が大幅にアップします。

たとえば、actを使えばaws-cliを利用したテストも可能です。また、Makefileを活用することで、テストの実行をさらに効率化できます。

この記事では、actとMakefileを組み合わせてワークフローのaws-cliをテストする方法をご紹介します!

サンプルのワークフローとMakefile

以下のサンプルを使用して解説していきます。

1.ワークフロー

このワークフローではAWS CLIを使用してS3バケットにファイルを同期します。

deploy.yml
name: deploy

on:
  pull_request:
    types: [opened, reopened, synchronize]

permissions:
  contents: read
  id-token: write

env:
  AWS_ROLE_ARN: ${{ secrets.AWS_ROLE_ARN }}
  AWS_REGION: us-east-1
  BUCKET: dummy-bucket

jobs:
  job1:
    runs-on: ubuntu-latest
    steps:
      - name: Setup for act
        # actで実行した場合は、処理を行います。
        if: github.actor == 'nektos/act'
        run: |
          curl -s "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
          unzip -q awscliv2.zip
          sudo ./aws/install
          rm -fr awscliv2.zip ./aws
          aws --version

      - name: Checkout
        uses: actions/checkout@v4

      - name: Configure AWS Credentials
        # actで実行した場合は、処理を行いません。
        if: github.actor != 'nektos/act'
        id: aws-credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ env.AWS_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}

      - name: Sync html
        run: |
          aws s3 sync --delete ./html/ s3://${{ env.BUCKET }}/

      - name: List bucket for debug
        # actで実行した場合は、処理を行います。
        if: github.actor == 'nektos/act'
        run: |
          echo "**** local"
          ls -al html/
          echo "**** remote"
          aws s3 ls s3://${{ env.BUCKET }}/

Setup for act

  • actの場合に実行する。
  • actのDockerイメージに含まれていないaws-cliをインストールしている。

Cofigure AWS Credentials

  • actの場合は実行しません。
  • かわりに、環境変数に設定したAWSクレデンシャルを使用。

2.Makefile

actを実行するために以下のようなMakefileを使用します。
AWS CLIのsts assume-roleコマンドを使い、一時的なAWSクレデンシャルを生成してactを実行します。

Makefile
PROFILE          := dummy
REGION           := us-east-1
IAM_ROLE_FOR_ACT := arn:aws:iam::000000000000:role/dummy

ACT_MICRO_IMAGE  := node:16-buster-slim
ACT_MEDIUM_IMAGE := catthehacker/ubuntu:act-latest

# act実行
act: aws_creds
	-act -P ubuntu-latest=$(ACT_MEDIUM_IMAGE) \
	--container-architecture linux/amd64 \
	-s AWS_ROLE_ARN="dummy" \
	--env-file .act_env \
	-W .github/workflows/deploy.yml
	rm -f .act_env

# 一時的なAWSクレデンシャルの生成
aws_creds:
	@echo "create temporaly aws credentials"
	@aws sts assume-role \
	--role-arn $(IAM_ROLE_FOR_ACT) \
	--role-session-name act \
	--duration-second 900 \
	--profile $(PROFILE) \
	--query 'Credentials' \
	| jq -r '.|[.AccessKeyId,.SecretAccessKey,.SessionToken]|@csv' \
	| awk -F, '{printf("AWS_ACCESS_KEY_ID=%s\nAWS_SECRET_ACCESS_KEY=%s\nAWS_SESSION_TOKEN=%s\nAWS_REGION=$(REGION)\n",$$1,$$2,$$3)}' \
	> .act_env
  • actはMEDIUMイメージを使っています。MICROはコマンドが色々不足しており、LARGEはイメージサイズが大きすぎるため。
  • act実行時にはsecret.AWS_ROLE_ARNは使用しないので、"dummy"としている。
  • act実行時に--env-file .act_envを使用して、環境変数にAWSクレデンシャルを設定。

ローカルでのテスト手順

私のローカル環境は、Lubuntu22.04です。

1. IAMロールの作成

actで使用するクレデンシャルを作成するためのIAMロールを作成します。

以下は、AWS STSを使用して一時的なクレデンシャルを作成する際に使用するIAMロールのポリシーを記載した例です。このロールには、aws s3 syncコマンドを実行するために必要な最小限の権限が含まれています。

IAMロールの信頼ポリシー

このポリシーを設定することで、STSがロールを引き受けることを許可します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "sts.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

IAMロールのポリシー (S3 Sync 用)

以下のポリシーでは、特定のS3バケットへのsync操作に必要な権限を指定しています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::example-bucket",
                "arn:aws:s3:::example-bucket/*"
            ]
        }
    ]
}

2. ディレクトリ構成

以下のようなディレクトリ構成であることとします。

.
├── .github
│   └── workflows
│       └── deploy.yml
├── .gitignore
├── Makefile
└── html
    └── index.html

3. テストの実行

make actを実行するだけで、以下の一連の操作が行われます。

(1) 一時的なAWSクレデンシャルの生成
make aws_credsターゲットが実行され、.act_envファイルにクレデンシャルが保存されます。

(2) GitHub Actionsワークフローの実行
actが実行され、ワークフローがローカル環境で実行されます。

(3) クレデンシャルの削除
.act_envファイルが削除され、セキュリティが保たれます。

実行結果は以下のようになります。

実行例
$ make act
create temporaly aws credentials
act -P ubuntu-latest=catthehacker/ubuntu:act-latest \
--container-architecture linux/amd64 \
-s AWS_ROLE_ARN="dummy" \
--env-file .act_env \
-W .github/workflows/deploy.yml
INFO[0000] Using docker host 'unix:///var/run/docker.sock', and daemon socket 'unix:///var/run/docker.sock'
[deploy/job1] 🚀  Start image=catthehacker/ubuntu:act-latest
[deploy/job1]   🐳  docker pull image=catthehacker/ubuntu:act-latest platform=linux/amd64 username= forcePull=true
[deploy/job1]   🐳  docker create image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["tail" "-f" "/dev/null"] cmd=[] network="host"
[deploy/job1]   🐳  docker run image=catthehacker/ubuntu:act-latest platform=linux/amd64 entrypoint=["tail" "-f" "/dev/null"] cmd=[] network="host"
[deploy/job1]   🐳  docker exec cmd=[node --no-warnings -e console.log(process.execPath)] user= workdir=
[deploy/job1]   ☁  git clone 'https://github.com/aws-actions/configure-aws-credentials' # ref=v4
[deploy/job1] Non-terminating error while running 'git clone': some refs were not updated
[deploy/job1] ⭐ Run Main Setup for act
[deploy/job1]   🐳  docker exec cmd=[bash -e /var/run/act/workflow/0] user= workdir=
| You can now run: /usr/local/bin/aws --version
| aws-cli/2.22.26 Python/3.12.6 Linux/6.8.0-50-generic exe/x86_64.ubuntu.22
[deploy/job1]   ✅  Success - Main Setup for act
[deploy/job1] ⭐ Run Main Checkout
[deploy/job1]   🐳  docker cp src=/home/blog/act_awscli/. dst=/home/blog/act_awscli
[deploy/job1]   ✅  Success - Main Checkout
[deploy/job1] ⭐ Run Main Sync html
[deploy/job1]   🐳  docker exec cmd=[bash -e /var/run/act/workflow/3] user= workdir=
[deploy/job1]   ✅  Success - Main Sync html
[deploy/job1] ⭐ Run Main List bucket for debug
[deploy/job1]   🐳  docker exec cmd=[bash -e /var/run/act/workflow/4] user= workdir=
| **** local
| total 12
| drwxr-xr-x 2 root root 4096 Dec 28 08:17 .
| drwxr-xr-x 4 root root 4096 Dec 28 08:17 ..
| -rw-rw-r-- 1 root root    3 Dec 22 02:26 index.html
| **** remote
| 2024-12-22 02:26:23          3 index.html
[deploy/job1]   ✅  Success - Main List bucket for debug
[deploy/job1] Cleaning up container for job job1
[deploy/job1] 🏁  Job succeeded
rm -f .act_env

まとめ

今回紹介したMakefileとactを活用することで、以下のメリットが得られます。

  1. 効率的なローカルテスト
    Githubに依存せず、ローカルで素早くテストが実行可能。

  2. セキュリティの確保
    一時的なクレデンシャルを使用し、セキュリティリスクを最小限に抑える。

  3. 再利用可能な仕組み
    Makefileにより、複雑な手順を簡潔に再現できる。

Discussion