ブランチ毎に作成したGitHub Actions workflowを1つにまとめる
はじめに
GitHub Actions,公式アナウンスされていませんが、AssumeRoleができるようになって積極的に利用しています。今回は、GitHubリポジトリのブランチ毎にAWSアカウントのデプロイ先を変更するworkflowを1つにまとめてみました。
構成図
前回の記事をベースとしています。dev,stg,prd環境毎にAWSアカウントを分離したワークロードでpush先のブランチ毎にworkflowを作成していました。
.github/workflows/dev-deploy.yml
name: cfn deploy on: push: branches: - dev workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read env: ENV: dev SYSNAME: example BILLINGTAG: example CIDR: 10.255.0.0/16 DOMAIN_NAME: dev.example.com HOSTED_ZONE_ID: Z10116024XXXXXXXXXXX INSTANCE_TYPE: t3.micro INSTANCE_CLASS: db.t3.small MASTERPASSWORD: ${{ secrets.MASTERPASSWORD }} steps: - name: setup run: | brew install rain echo "rain -v" rain -v - name: there's still a race condition for now run: sleep 5 - name: Configure AWS run: | export AWS_ROLE_ARN=arn:aws:iam::123456789012:role/GithubActionRole export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds export AWS_DEFAULT_REGION=ap-northeast-1 echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE - uses: actions/checkout@v2 with: ref: dev - name: Check the Format of the CloudFormation template. run: | echo Returns an error if not formatted. rain fmt -v ./template/*yml - name: Template deploy. run: | rain deploy -y ./system.yml $ENV-stack --params \ env=$ENV,\ sysName=$SYSNAME,\ billingTag=$BILLINGTAG,\ vpcCidr=$CIDR,\ domainName=$DOMAIN_NAME,\ hostedZoneId=$HOSTED_ZONE_ID,\ instanceType=$INSTANCE_TYPE,\ instanceClass=$INSTANCE_CLASS,\ masterPassword=$MASTERPASSWORD,\
.github/workflows/stg-deploy.yml
name: cfn deploy on: push: branches: - stg workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read env: ENV: stg SYSNAME: example BILLINGTAG: example CIDR: 10.254.0.0/16 DOMAIN_NAME: stg.example.com HOSTED_ZONE_ID: Z10116024XXXXXXXXXXX INSTANCE_TYPE: t3.micro INSTANCE_CLASS: db.t3.small MASTERPASSWORD: ${{ secrets.MASTERPASSWORD }} steps: - name: setup run: | brew install rain echo "rain -v" rain -v - name: there's still a race condition for now run: sleep 5 - name: Configure AWS run: | export AWS_ROLE_ARN=arn:aws:iam::123456789012:role/GithubActionRole export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds export AWS_DEFAULT_REGION=ap-northeast-1 echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE - uses: actions/checkout@v2 with: ref: stg - name: Check the Format of the CloudFormation template. run: | echo Returns an error if not formatted. rain fmt -v ./template/*yml - name: Template deploy. run: | rain deploy -y ./system.yml $ENV-stack --params \ env=$ENV,\ sysName=$SYSNAME,\ billingTag=$BILLINGTAG,\ vpcCidr=$CIDR,\ domainName=$DOMAIN_NAME,\ hostedZoneId=$HOSTED_ZONE_ID,\ instanceType=$INSTANCE_TYPE,\ instanceClass=$INSTANCE_CLASS,\ masterPassword=$MASTERPASSWORD,\
.github/workflows/prd-deploy.yml
name: cfn deploy on: push: branches: - main workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read env: ENV: prd SYSNAME: example BILLINGTAG: example CIDR: 10.0.0.0/16 DOMAIN_NAME: example.com HOSTED_ZONE_ID: Z10116024ZZZZZZZZZZ INSTANCE_TYPE: m5.large INSTANCE_CLASS: db.m5.large MASTERPASSWORD: ${{ secrets.MASTERPASSWORD }} steps: - name: setup run: | brew install rain echo "rain -v" rain -v - name: there's still a race condition for now run: sleep 5 - name: Configure AWS run: | export AWS_ROLE_ARN=arn:aws:iam::123456789012:role/GithubActionRole export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds export AWS_DEFAULT_REGION=ap-northeast-1 echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE - uses: actions/checkout@v2 with: ref: main - name: Check the Format of the CloudFormation template. run: | echo Returns an error if not formatted. rain fmt -v ./template/*yml - name: Template deploy. run: | rain deploy -y ./system.yml $ENV-stack --params \ env=$ENV,\ sysName=$SYSNAME,\ billingTag=$BILLINGTAG,\ vpcCidr=$CIDR,\ domainName=$DOMAIN_NAME,\ hostedZoneId=$HOSTED_ZONE_ID,\ instanceType=$INSTANCE_TYPE,\ instanceClass=$INSTANCE_CLASS,\ masterPassword=$MASTERPASSWORD,\
それぞれの差異は、push先ブランチ(dev or stg or prd)、env、AWS_ROLE_ARNが異なりますがそれ以外は重複しています。例えばCloudFormationスタックをデプロイする rain deploy
のパラメータの修正があるとすべてのworkflowを修正する必要があります。重複する処理を共通action、push先ブランチで環境変数を変更する1つのworkflowを作成しました。
1つのworkflow
name: cfn deploy on: push: workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Checkout code uses: actions/checkout@v2 - name: IAM Role for dev account if: contains(toJSON(github.ref), 'dev') run: | echo ENV=dev >> $GITHUB_ENV echo SYSNAME=example >> $GITHUB_ENV echo BILLINGTAG=example >> $GITHUB_ENV echo CIDR=10.255.0.0/16 >> $GITHUB_ENV echo DOMAIN_NAME=dev.example.com >> $GITHUB_ENV echo HOSTED_ZONE_ID=Z01774222TMXXXXXXXXXX >> $GITHUB_ENV echo INSTANCE_TYPE=t3.micro >> $GITHUB_ENV echo INSTANCEINSTANCE_CLASS_TYPE=db.t3.small >> $GITHUB_ENV echo MASTERPASSWORD=${{ secrets.DEV_MASTERPASSWORD }} >> $GITHUB_ENV echo AWS_ROLE_ARN=arn:aws:iam::123456789010:role/githubrole >> $GITHUB_ENV - name: env exportIAM Role for stg account if: contains(toJSON(github.ref), 'stg') run: | echo ENV=stg >> $GITHUB_ENV echo SYSNAME=example >> $GITHUB_ENV echo BILLINGTAG=example >> $GITHUB_ENV echo CIDR=10.254.0.0/16 >> $GITHUB_ENV echo DOMAIN_NAME=stg.example.com >> $GITHUB_ENV echo HOSTED_ZONE_ID=Z01774222TMYYYYYYYYYY >> $GITHUB_ENV echo INSTANCE_TYPE=t3.micro >> $GITHUB_ENV echo INSTANCEINSTANCE_CLASS_TYPE=db.t3.small >> $GITHUB_ENV echo MASTERPASSWORD=${{ secrets.STG_MASTERPASSWORD }} >> $GITHUB_ENV echo AWS_ROLE_ARN=arn:aws:iam::123456789011:role/githubrole >> $GITHUB_ENV - name: IAM Role for prd account if: contains(toJSON(github.ref), 'main') run: | echo ENV=prd >> $GITHUB_ENV echo SYSNAME=example >> $GITHUB_ENV echo BILLINGTAG=example >> $GITHUB_ENV echo CIDR=10.0.0.0/16 >> $GITHUB_ENV echo DOMAIN_NAME=stg.example.com >> $GITHUB_ENV echo HOSTED_ZONE_ID=Z01774222TMYYYYYYYYYY >> $GITHUB_ENV echo INSTANCE_TYPE=t3.micro >> $GITHUB_ENV echo INSTANCEINSTANCE_CLASS_TYPE=db.t3.small >> $GITHUB_ENV echo MASTERPASSWORD=${{ secrets.PRD_MASTERPASSWORD }} >> $GITHUB_ENV echo AWS_ROLE_ARN=arn:aws:iam::123456789012:role/githubrole >> $GITHUB_ENV - name: Configure AWS run: | export AWS_ROLE_ARN=$AWS_ROLE_ARN export AWS_WEB_IDENTITY_TOKEN_FILE=/tmp/awscreds export AWS_DEFAULT_REGION=ap-northeast-1 echo AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE >> $GITHUB_ENV echo AWS_ROLE_ARN=$AWS_ROLE_ARN >> $GITHUB_ENV echo AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION >> $GITHUB_ENV curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -r '.value' > $AWS_WEB_IDENTITY_TOKEN_FILE - name: setup common run: | brew install rain echo "rain -v" rain -v - name: Check the Format of the CloudFormation template run: | echo Returns an error if not formatted rain fmt -v ./template/*yml - name: Template deploy. run: | rain deploy -y ./system.yml $ENV-stack --params \ env=$ENV,\ sysName=$SYSNAME,\ billingTag=$BILLINGTAG,\ vpcCidr=$CIDR,\ domainName=$DOMAIN_NAME,\ hostedZoneId=$HOSTED_ZONE_ID,\ instanceType=$INSTANCE_TYPE,\ instanceClass=$INSTANCE_CLASS,\ masterPassword=$MASTERPASSWORD
変更ポイント1
すべてのpushをトリガーとするように修正しました。これまで特定ブランチで制御していましたが、dev,stg,mainブランチのpushをトリガーとしてGitHub Actionsが起動します。
on: push:
変更ポイント2
if: contains(toJSON(github.ref), 'ブランチ名')
でpushブランチを特定してactionを実行します。併せて環境毎に異なるenv,AWS_ROLE_ARNを環境変数に設定します。ここで環境変数を設定する意図は、steps内のenvが次のアクションに引き継がれませんが、$GITHUB_ENV
環境変数に格納しておくと他のアクションでも利用できるようになるので設定してます。
- name: IAM Role for dev account if: contains(toJSON(github.ref), 'dev') run: | echo ENV=dev >> $GITHUB_ENV echo SYSNAME=example >> $GITHUB_ENV echo BILLINGTAG=example >> $GITHUB_ENV echo CIDR=10.255.0.0/16 >> $GITHUB_ENV echo DOMAIN_NAME=dev.example.com >> $GITHUB_ENV echo HOSTED_ZONE_ID=Z01774222TMXXXXXXXXXX >> $GITHUB_ENV echo INSTANCE_TYPE=t3.micro >> $GITHUB_ENV echo INSTANCEINSTANCE_CLASS_TYPE=db.t3.small >> $GITHUB_ENV echo MASTERPASSWORD=${{ secrets.DEV_MASTERPASSWORD }} >> $GITHUB_ENV echo AWS_ROLE_ARN=arn:aws:iam::123456789010:role/githubrole >> $GITHUB_ENV - name: env exportIAM Role for stg account if: contains(toJSON(github.ref), 'stg') run: | echo ENV=stg >> $GITHUB_ENV echo SYSNAME=example >> $GITHUB_ENV echo BILLINGTAG=example >> $GITHUB_ENV echo CIDR=10.254.0.0/16 >> $GITHUB_ENV echo DOMAIN_NAME=stg.example.com >> $GITHUB_ENV echo HOSTED_ZONE_ID=Z01774222TMYYYYYYYYYY >> $GITHUB_ENV echo INSTANCE_TYPE=t3.micro >> $GITHUB_ENV echo INSTANCEINSTANCE_CLASS_TYPE=db.t3.small >> $GITHUB_ENV echo MASTERPASSWORD=${{ secrets.STG_MASTERPASSWORD }} >> $GITHUB_ENV echo AWS_ROLE_ARN=arn:aws:iam::123456789011:role/githubrole >> $GITHUB_ENV - name: IAM Role for prd account if: contains(toJSON(github.ref), 'main') run: | echo ENV=prd >> $GITHUB_ENV echo SYSNAME=example >> $GITHUB_ENV echo BILLINGTAG=example >> $GITHUB_ENV echo CIDR=10.0.0.0/16 >> $GITHUB_ENV echo DOMAIN_NAME=stg.example.com >> $GITHUB_ENV echo HOSTED_ZONE_ID=Z01774222TMYYYYYYYYYY >> $GITHUB_ENV echo INSTANCE_TYPE=t3.micro >> $GITHUB_ENV echo INSTANCEINSTANCE_CLASS_TYPE=db.t3.small >> $GITHUB_ENV echo MASTERPASSWORD=${{ secrets.PRD_MASTERPASSWORD }} >> $GITHUB_ENV echo AWS_ROLE_ARN=arn:aws:iam::123456789012:role/githubrole >> $GITHUB_ENV
変更ポイント3
name: Configure AWS
、name: Check the Format of the CloudFormation template
、name: Template deploy.
は共通アクションです。環境変数AWS_ROLE_ARN
からIAMロールのARNを参照してexportするように修正しています。rain deploy
の--paramsも同様に環境変数から呼び出しています。
まとめ
1つのworkflowで重複する処理とブランチ毎のデプロイ先を変更することができました。環境毎(例えば本番だけ)に処理が異なる場合は無理してworkflowを統合する必要は無いと考えています。その他、様々な実装方法があるのでドキュメント見ながら試してみてください。