この記事は公開されてから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を統合する必要は無いと考えています。その他、様々な実装方法があるのでドキュメント見ながら試してみてください。