GitHub Actions テンプレート書いて、プッシュ
→ 実行
→ 失敗
→ 修正
→ プッシュ
、今までずっとこういう繰り返してきたが、とても時間かかってしまいます。 最近いいもの見つかったので、簡単で紹介します。
nektos/act
GitHub Actions
をローカルで実行できるツールです。Windows
、Linux
、Mac
、メジャーなプラットフォームは全てサポートされてます。
簡単なサンプル
インストール方法
# Mac
brew install act
# Linux
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
# Windows Chocolatey
choco install act-cli
# Windows Scoop
scoop install act
環境変数
GitHub Actions
のデフォルト 環境変数 はパラメータで渡すことができます。
act --env-file .env
MY_ENV_VAR=MY_ENV_VAR_VALUE
MY_2ND_ENV_VAR="my 2nd env var value"
シークレット変数
GitHub Actions
用のシークレット変数はパラメータで渡すことができます。
# シークレットファイル
act --secret-file .secrets
# シークレットパラメータ
act -s AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE -s AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
完全な例
まず GitHub Actions
用のテンプレートを用意します。今回は AWS ECS
へのデプロイ用のテンプレートとなります。
name: Build and Deploy to ECS Backend Service
on:
push:
paths:
- backend/private/**
- .github/workflows/backend.yml
env:
ECR_REPOSITORY: fargate-backend
TAKS_DEFINITION_FILE: task-def/backend.json
SERVICE_NAME: backend
CLUSTER_NAME: fargate-microservice
jobs:
build:
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@master
# AWS Credentials
- 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
# ECR Login
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# docker build and push
- name: Build, tag, and push image to Amazon ECR
working-directory: backend/private
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
# update task definition
- name: Fill in the new image ID in the Amazon ECS task definition
id: render-web-container
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.TAKS_DEFINITION_FILE }}
container-name: ${{ env.ECR_REPOSITORY }}
image: ${{ steps.build-image.outputs.image }}
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.render-web-container.outputs.task-definition }}
service: ${{ env.SERVICE_NAME }}
cluster: ${{ env.CLUSTER_NAME }}
wait-for-service-stability: true
act push --secret-file .secrets
AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
[Build .../build] 🚀 Start image=nektos/act-environments-ubuntu:18.04
[Build .../build] 🐳 docker run image=nektos/act-environments-ubuntu:18.04 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[Build .../build] 🐳 docker cp src=/usr/local/src/fargate-microservice-architecture/. dst=/github/workspace
[Build .../build] ⭐ Run Checkout
[Build .../build] ✅ Success - Checkout
[Build .../build] ⭐ Run Configure AWS credentials
[Build .../build] ☁ git clone 'https://github.com/aws-actions/configure-aws-credentials' # ref=v1
[Build .../build] 🐳 docker cp src=/home/ec2-user/.cache/act/aws-actions-configure-aws-credentials@v1 dst=/actions/
[Build .../build] ⚙ ::add-mask::***
[Build .../build] ⚙ ::add-mask::***
[Build .../build] ⚙ ::add-mask::999999999999
[Build .../build] ⚙ ::set-output:: aws-account-id=999999999999
[Build .../build] ✅ Success - Configure AWS credentials
[Build .../build] ⭐ Run Login to Amazon ECR
[Build .../build] ☁ git clone 'https://github.com/aws-actions/amazon-ecr-login' # ref=v1
[Build .../build] 🐳 docker cp src=/home/ec2-user/.cache/act/aws-actions-amazon-ecr-login@v1 dst=/actions/
[Build .../build] ⚙ ::set-output:: registry=999999999999.dkr.ecr.ap-northeast-1.amazonaws.com
[Build .../build] ❓ ::save-state name=registries::999999999999.dkr.ecr.ap-northeast-1.amazonaws.com
[Build .../build] 💬 ::debug::'skip-logout' is for 1 registries.
[Build .../build] ✅ Success - Login to Amazon ECR
[Build .../build] ⭐ Run Build, tag, and push image to Amazon ECR
| Sending build context to Docker daemon 11.26kB
| Step 1/12 : FROM node:14-alpine as build
| ---> 471e8b4eb0b2
| Step 2/12 : WORKDIR /app
| ---> Using cache
| ---> 99cdc798e7f7
| Step 3/12 : COPY . .
| ---> 6ad23c2907e9
| Step 4/12 : RUN yarn install
| ---> Running in c4952859c6d8
| yarn install v1.22.5
| warning package.json: No license field
| info No lockfile found.
| warning No license field
| [1/4] Resolving packages...
| [2/4] Fetching packages...
| [3/4] Linking dependencies...
| [4/4] Building fresh packages...
| success Saved lockfile.
| Done in 2.88s.
| Removing intermediate container c4952859c6d8
| ---> 7d59270a7da3
| Step 5/12 : RUN yarn build
| ---> Running in 7dd9e30c6be5
| yarn run v1.22.5
| warning package.json: No license field
| $ tsc
| Done in 2.40s.
| Removing intermediate container 7dd9e30c6be5
| ---> 25d360ba037f
| Step 6/12 : FROM node:14-alpine
| ---> 471e8b4eb0b2
| Step 7/12 : WORKDIR /app
| ---> Using cache
| ---> 99cdc798e7f7
| Step 8/12 : COPY --from=build /app/build .
| ---> 481979ef9c8c
| Step 9/12 : COPY package.json .
| ---> e2f9100ebeae
| Step 10/12 : RUN yarn install --production --no-lockfile
| ---> Running in 3fec184a0e87
| yarn install v1.22.5
| warning package.json: No license field
| warning No license field
| [1/4] Resolving packages...
| [2/4] Fetching packages...
| [3/4] Linking dependencies...
| [4/4] Building fresh packages...
| Done in 2.84s.
| Removing intermediate container 3fec184a0e87
| ---> cad29e95c4bb
| Step 11/12 : EXPOSE 8090
| ---> Running in 57c67c1ea88b
| Removing intermediate container 57c67c1ea88b
| ---> ff75e6a21c15
| Step 12/12 : CMD [ "yarn", "start"]
| ---> Running in 3ae8cfe11af5
| Removing intermediate container 3ae8cfe11af5
| ---> df3e4e5d1a05
| Successfully built df3e4e5d1a05
| Successfully tagged 999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/fargate-backend:f8a3efce5d67ff5ebe5b083334a79ba1651d7cb9
| The push refers to repository [999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/fargate-backend]
8ae25a3d281b: Pushed
7c35cc8ea3b9: Pushed
232cca45d3ab: Pushed
2bd9c1c800cb: Layer already exists
e5312594675f: Layer already exists
e8ab0f5d941e: Layer already exists
42e6ad646250: Layer already exists
0fcbbeeeb0d7: Layer already exists
f8a3efce5d67ff5ebe5b083334a79ba1651d7cb9: digest: sha256:cfb60be4df7f147425e809c745eec8ca0a3660c16b989832accd973a16e905fd size: 1991
[Build .../build] ⚙ ::set-output:: image=999999999999.dkr.ecr.ap-northeast-1.amazonaws.com/fargate-backend:f8a3efce5d67ff5ebe5b083334a79ba1651d7cb9
[Build .../build] ✅ Success - Build, tag, and push image to Amazon ECR
[Build .../build] ⭐ Run Fill in the new image ID in the Amazon ECS task definition
[Build .../build] ☁ git clone 'https://github.com/aws-actions/amazon-ecs-render-task-definition' # ref=v1
[Build .../build] 🐳 docker cp src=/home/ec2-user/.cache/act/aws-actions-amazon-ecs-render-task-definition@v1 dst=/actions/
[Build .../build] ⚙ ::set-output:: task-definition=/tmp/task-definition--86-Ixb7NQkEVcwv-.json
[Build .../build] ✅ Success - Fill in the new image ID in the Amazon ECS task definition
[Build .../build] ⭐ Run Deploy Amazon ECS task definition
[Build .../build] ☁ git clone 'https://github.com/aws-actions/amazon-ecs-deploy-task-definition' # ref=v1
[Build .../build] 🐳 docker cp src=/home/ec2-user/.cache/act/aws-actions-amazon-ecs-deploy-task-definition@v1 dst=/actions/
[Build .../build] 💬 ::debug::Registering the task definition
[Build .../build] ⚙ ::set-output:: task-definition-arn=arn:aws:ecs:ap-northeast-1:999999999999:task-definition/fargate-backend:21
[Build .../build] 💬 ::debug::Updating the service
| Deployment started. Watch this deployment's progress in the Amazon ECS console: https://console.aws.amazon.com/ecs/home?region=ap-northeast-1#/clusters/fargate-microservice/services/Backend/events
[Build .../build] 💬 ::debug::Waiting for the service to become stable. Will wait for 30 minutes
[Build .../build] ✅ Success - Deploy Amazon ECS task definition
よくある問題
Dockerコマンドが見つからない
::error::Unable to locate executable file: docker
[Build .../build] 🐳 docker cp src=/home/ec2-user/.cache/act/aws-actions-amazon-ecr-login@v1 dst=/actions/
[Build .../build] ⚙ ::set-output:: registry=999999999999.dkr.ecr.ap-northeast-1.amazonaws.com
[Build .../build] ❗ ::error::Unable to locate executable file: docker. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.
解決策
Default Runner は node:12.6-buster-slim
のDocker image
を使ってるため、OS に Docker Command
が使えません。下記はデフォルトの設定です。
GitHub Runner | Docker Image |
---|---|
ubuntu-latest | node:12.6-buster-slim |
ubuntu-20.04 | node:12.6-buster-slim |
ubuntu-18.04 | node:12.6-buster-slim |
ubuntu-16.04 | node:12.6-stretch-slim |
windows-latest | unsupported |
windows-2019 | unsupported |
macos-latest | unsupported |
macos-10.15 | unsupported |
実行用の Docker image
を置き換えれば、解決できます。ただ、イメージファイルは 18 GB
以上ありますので、最初のダウンロードは時間かかります。
act push --secret-file .secrets --platform ubuntu-18.04=nektos/act-environments-ubuntu:18.04
最後に
他のコマンドも色々ありますので、act --help
で確認してください。