GitHub Actions完全に理解した。
— adachin👾SRE (@adachin0817) April 26, 2022
CircleCIを愛用している私ですが、最近GitHub Actionsに入門してみました。また、CI/CDツールは様々なメリットやデメリットなどエンジニアとして把握すべきです。ちなみに私はCircleCIの経験がある前提でGitHub Actionsを実装していたので、「この機能ないんかい!どうやるんだ!?」とハマることがありました。(脳の切り替えが遅い)
さて、以前CircleCIで個人のリポジトリがマージされるとgit pullによるSSHデプロイするように作りましたが、手っ取り早く、同様なことをAWSのEC2に対して高速にrsyncデプロイを実装してみました。
構成図
※例としてGitHub Flowによる開発方法、各EC2はPublicサブネット配下にあり、SSHができる環境です。アプリケーションはPHP7.4/Laravelとします。
・Stg
・ GitHub Actions
・リモートブランチにpush
・workflow_dispatchによる手動でリモートブランチを指定してrsyncデプロイ
・本番
・GitHub Actions
・masterマージによるrsyncデプロイ
GitHub Actionsのデバッグってどうやるのよ?
CircleCI同様と思いきや、デバッグ時にコンテナにSSHする場合はわざわざ action-tmate
を指定してpushしないといけません。結構手間なのでコメントアウトして書いておくといいですね。シンタックスチェックは actionlint
コマンドを使えばOK。早速書いていきましょう。
Setting GitHub Actions
https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions
- deploy/stg/deploy.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
## deploy stg-app01 echo -e "\ndeploy stg-app01" echo -e "\n" mkdir -p storage/logs chmod -R 777 storage chmod -R 777 storage/logs npm install npm install --prefix ./resources/frontend/xxx npm run build-deploy composer install --no-dev --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist composer dump-autoload ## rsync rsync --checksum --delete -av --exclude '.git' --include '.*' ./ \ -e "ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" -i ~/.ssh/private_key -p xxxxxx" \ hoge@xx.xx.xx.xxx:/var/www/hoge/ echo -e "Migration app01" ## Migration app01 ssh -o "StrictHostKeyChecking no" hoge@xx.xx.xx.xx -i ~/.ssh/private_key -p xxx 'cd ~/hoge' \ '&& php artisan config:clear' \ '&& php artisan cache:clear' \ '&& php artisan view:clear' \ '&& php artisan migrate --force' |
まず、Laravelをデプロイするためのレシピとしてシェルスクリプトを作りました。単純にcomposer install、rsyncしてマイグレーションするだけです。rsyncはchecksumで差分のみコピーと、デフォルトだと隠しファイルがコピーされないので–includeで明示的に指定しましょう。.gitディレクトリは増え続けるので–excludeで省きます。この流れをworkflows直に書こうとしていましたが、可読性が下がるので上記のように分けるのがベストだと思いました。
ちなみに–deleteオプションはによる転送元のディレクトリに存在せず、転送先のディレクトリに存在するファイルがあれば削除します。
※本番用のデプロイシェルはステージングと同様なので割愛します。
- .github/workflows/deploy-stg.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
name: Deploy-stg # デプロイ時のデバッグでpush時にデプロイできる #on: # pull_request: # CircleCIのWorkflowに近い on: workflow_dispatch: inputs: name: description: 'Name' required: true env: SLACK_WEBHOOK: ${{ secrets.STG_SLACK_WEBHOOK_URL }} SLACK_USERNAME: stg-deploy SLACK_CHANNEL: deploy SLACK_ICON: https://avatars.githubusercontent.com/u/44036562?s=280&v=4 jobs: deploy-aws: runs-on: ubuntu-latest steps: - uses: shivammathur/setup-php@v2 with: php-version: '7.4' - uses: actions/checkout@v3 #対象ブランチをcheckoutする with: fetch-depth: 0 #全タグ・全ブランチ・全履歴を取得する - name: echo key env: PRIVATE_KEY: ${{ secrets.SERVER_SECRET_KEY_AWS }} run: | mkdir ~/.ssh && echo "$PRIVATE_KEY" > ~/.ssh/private_key && chmod 600 ~/.ssh/private_key - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@main with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: Download file from S3 .env run: | aws s3 cp s3://stg-hoge/app/stg-env ./.env --quiet - name: Deploy App env: PRIVATE_KEY: ${{ secrets.SERVER_SECRET_KEY_AWS }} run: | sh ./deploy/stg/deploy.sh - name: Slack Success if: ${{ success() }} uses: rtCamp/action-slack-notify@v2 env: SLACK_TITLE: Stg deploy Success SLACK_COLOR: good - name: Slack Failure if: ${{ failure() }} uses: rtCamp/action-slack-notify@v2 env: SLACK_TITLE: Stg deploy Failure SLACK_COLOR: danger # sshデバッグのためコメントアウト # - name: Setup tmate session # uses: mxschmitt/action-tmate@v3 |
上記コメントしていますが、 actions/checkout
についてはCircleCIのcheckoutと挙動が違うので下記ドキュメントを見たほうが良さそうです。
https://github.com/actions/checkout
ステージング環境にテストするためには、push時やプルリクエスト時にステージング環境へリモートブランチのソースコードをデプロイできればOKということになります。そこで、CircleCI時では以下のようにCircleCIで定義されているブランチ名を変数として取ってきてAPI経由でデプロイするといったことをできないのかと路頭に迷っていたところ、 workflow_dispatch
を利用して手動でWebからブランチ名を指定、ブランチをcheckoutしてデプロイできるというのを知りました。これならわざわざステージング用にシェル芸する必要はないですし、本番環境と同等になります。非常に便利ですね。
https://docs.github.com/ja/actions/managing-workflow-runs/manually-running-a-workflow
ちなみにCircleCIでも manual pipeline run button
というのがあったのかい….!!(以下後でテストしてみます)
Trigger Pipelineでbooleanとstg用のworkflows名に対してtrueを指定すればリリースできました。
- .github/workflows/deploy-prd.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
name: Deploy-prd #デプロイ時のデバッグ #on: # pull_request: on: push: branches: [master] #masterマージで発動 env: SLACK_WEBHOOK: ${{ secrets.PRD_SLACK_WEBHOOK_URL }} SLACK_USERNAME: prd-deploy SLACK_CHANNEL: deploy SLACK_ICON: https://avatars.githubusercontent.com/u/44036562?s=280&v=4 jobs: deploy-aws: runs-on: ubuntu-latest steps: - uses: shivammathur/setup-php@v2 with: php-version: '7.4' - uses: actions/checkout@v3 with: fetch-depth: 0 - name: echo key env: PRIVATE_KEY: ${{ secrets.SERVER_SECRET_KEY_AWS }} run: | mkdir ~/.ssh && echo "$PRIVATE_KEY" > ~/.ssh/private_key && chmod 600 ~/.ssh/private_key - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@main with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ap-northeast-1 - name: Download file from S3 .env run: | aws s3 cp s3://prd-hoge/app/prd-env ./.env --quiet - name: Deploy App env: PRIVATE_KEY: ${{ secrets.SERVER_SECRET_KEY_AWS }} run: | sh ./deploy/prd/deploy.sh - name: Slack Success if: ${{ success() }} uses: rtCamp/action-slack-notify@v2 env: SLACK_TITLE: Prd deploy Success SLACK_COLOR: good - name: Slack Failure if: ${{ failure() }} uses: rtCamp/action-slack-notify@v2 env: SLACK_TITLE: Prd deploy Failure SLACK_COLOR: danger # sshデバッグのためコメントアウト # - name: Setup tmate session # uses: mxschmitt/action-tmate@v3 |
本番もコードはほとんど同じで、onのworkflowでbranchesはmasterを指定すればOK。CircleCIと似てる。
デプロイ確認とSlack通知
まとめ
さらにGitHub Actionsのノウハウが高まった
— adachin👾SRE (@adachin0817) May 8, 2022
CircleCIは1ファイル管理しますが複数のworkflowを書けるのがGithub Actionsのメリットと感じました。(個人的にはCircleCI推しだけど)Github Actionsは導入も簡単だし、気楽にCI/CDを実装できるのは良いと感じました。コンテナのデプロイもサクッとできそう。
ちなみに
SSMでもrunningしているインスタンスIDをタグで取得して、SSHが動いていればrsync可能です。マイグレーションは実行シェル分けたほうが分かりやすいですね。
- deploy/stg/deploy.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
~省略~ ## Deploy rsyn app for INSTANCE_ID in `aws ec2 describe-instances --output=text --filters "Name=tag:deploy,Values=stg-app" "Name=instance-state-name,Values=running" --query 'Reservations[].Instances[].{id:InstanceId}'` do echo -e "Deploy rsync app" echo ${INSTANCE_ID} rsync --checksum --delete -av --exclude '.git' --include '.*' ./ \ -e "ssh -o "StrictHostKeyChecking=no" -o "UserKnownHostsFile=/dev/null" -i ~/.ssh/private_key -p xxxxx" \ hoge@${INSTANCE_ID}:/var/www/hoge/ done ## Migration for INSTANCE_ID in `aws ec2 describe-instances --output=text --filters "Name=tag:deploy,Values=stg-app" ""Name=instance-state-name,Values=running"" --query 'Reservations[].Instances[].{id:InstanceId}'` do echo -e "Migration app" echo ${INSTANCE_ID} ssh -o "StrictHostKeyChecking no" hoge@${INSTANCE_ID} -i ~/.ssh/private_key -p xxxx 'sh ~/stg/deploy/migration/run.sh' done |
- deploy/stg/migration/run.sh
1 2 3 4 5 6 7 |
#!/bin/bash cd ~/hoge \ && php artisan config:clear \ && php artisan cache:clear \ && php artisan view:clear \ && php artisan migrate --force |
0件のコメント