こんにちは、かつコーチです。
テストの自動化までできるようになると、次に欲しくなるのが「mainにマージしたら自動で本番に反映される」仕組みです。
手動デプロイには、手順の抜け漏れや、担当者しか作業できないという属人化のリスクが常につきまといます。
この記事では、GitHub Actionsを使ったデプロイ自動化の基本設計と、安全に運用するための考え方を解説します。
ワークフローの書き方やテスト自動化は前提知識として進めます。
デプロイ自動化とは?
ベルトコンベアで完成品を出荷まで運ぶ仕組み
デプロイ自動化とは、コードの変更がmainブランチに取り込まれた後、ビルド・検証・本番反映までの一連の工程を、人手を介さず自動で実行する仕組みです。
イメージとしては、工場のベルトコンベアが完成品を検品ラインから梱包、出荷まで自動で運んでいく様子を思い浮かべてください。
人が1工程ずつ台車で運んでいた頃は、運搬中に落として壊す、違うラインに置いてしまうといったミスが起こり得ました。
ベルトコンベアに乗せてしまえば、決まったルートを、決まった速度で、同じ品質のまま出荷口まで運んでくれます。
デプロイ自動化も同様に、「ビルド」「テスト」「本番反映」という工程をパイプラインに乗せ、人の手を介さずに一貫した手順で実行させる考え方です。
なぜデプロイの自動化が重要なのか
手動デプロイには、以下のようなリスクがあります。
- デプロイ手順書のバージョンが古く、実際の手順とズレている
- 特定の担当者しか本番反映の作業ができず、その人が休むと止まる
- 手順の一部を飛ばしてしまい、キャッシュのクリア漏れなどの事故につながる
自動化されたパイプラインは、誰が実行しても同じ手順・同じ順序で処理されるため、属人化とヒューマンエラーの両方を同時に解消できます。
実装手順:デプロイワークフローの構築
ここでは、mainへのマージをトリガーに、AWS S3への静的サイトデプロイを行う例で解説します。
手順1:デプロイ専用ワークフローを作成する
$ touch .github/workflows/deploy.yml
テスト用ワークフローとデプロイ用ワークフローは、責務を分けて別ファイルにするのが定石です。
手順2:mainマージ後のみ反応するよう設定する
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
environment: productionを指定すると、後述するEnvironment secretsや承認フローと連携できます。
手順3:ビルドからデプロイまでの工程を定義する
steps:
- name: リポジトリを取得
uses: actions/checkout@v4
- name: Node.jsをセットアップ
uses: actions/setup-node@v4
with:
node-version: "20"
- name: 依存パッケージをインストール
run: npm ci
- name: プロダクションビルド
run: npm run build
- name: AWS認証情報を設定
uses: aws-actions/configure-aws-credentials@v4
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: S3へデプロイ
run: aws s3 sync ./dist s3://your-bucket-name --delete
--deleteオプションは、ローカルのビルド成果物に存在しないファイルをS3側からも削除する設定です。
ベルトコンベアの終着点で、古い在庫を残さず最新の完成品だけを棚に並べ直しているイメージです。
手順4:本番反映前に承認ステップを挟む
重要な環境には、GitHubのEnvironment機能で「Required reviewers」を設定できます。
これにより、environment: productionのjobは、指定したレビュアーが承認するまで実行されずに一時停止します。
ベルトコンベアの途中に、最終検品担当者が目視でチェックするゲートを設けるようなイメージです。
自動化しつつも、本番反映という重大な工程だけは人の目を挟むという設計が、安全性とスピードのバランスとして現実的です。
よくあるつまずきポイント・エラー対処
secretsの参照ミスで認証エラーが出た話
私が実際にはまったのが、Environment secretsとRepository secretsの区別を誤り、認証エラーでデプロイが失敗し続けたケースです。
❌ Before:Repository secretsにしか登録していないのにEnvironmentを指定
jobs:
deploy:
environment: production
steps:
- run: aws s3 sync ./dist s3://your-bucket-name
An error occurred (InvalidAccessKeyId) when calling the PutObject operation
Environmentを指定したjobは、そのEnvironmentに紐づくsecretsを優先的に参照する仕組みになっており、production用のsecretsを別途登録していなかったため、空の認証情報で失敗していました。
出荷ラインに正しいラベルシールを供給し忘れていたようなものです。
✅ After:Settings > Environments > productionにsecretsを登録する
GitHubリポジトリの Settings > Environments からproduction環境を作成し、そこにAWS_ACCESS_KEY_IDなどを個別登録しました。
これにより、production環境専用の認証情報として正しく参照されるようになり、デプロイが成功しました。
以降、Environmentごとにsecretsを分離することで、ステージングと本番で誤って同じ認証情報を使い回すリスクも避けられるようにしています。
応用・一歩先の使い方
ロールバックも自動化パイプラインの一部として設計する
デプロイの自動化を突き詰めると、次に重要になるのが「失敗したときにどう戻すか」です。
前回成功したデプロイのアーティファクトを保持しておき、手動トリガー(workflow_dispatch)で以前のバージョンを再デプロイできるワークフローを用意しておくと、障害発生時の復旧が格段に速くなります。
on:
workflow_dispatch:
inputs:
version:
description: "ロールバック対象のバージョンタグ"
required: true
ベルトコンベアには、不良品を検知したら前の工程に押し戻す仕組みもセットで設計しておくべきだ、という発想です。
まとめ
この記事のポイント
- デプロイ自動化は、ベルトコンベアのようにビルドから本番反映までを一貫した手順で自動実行する仕組み
environmentとRequired reviewersを組み合わせ、本番反映前に人の承認を挟める- Environment secretsとRepository secretsは別物であり、参照先を誤ると認証エラーになる
- ロールバック手段も自動化パイプラインの一部としてあらかじめ設計しておく
次に読むべき記事
デプロイまで自動化できたら、日々の運用で遭遇しがちなトラブルは「よくあるGitHubのつまずきポイントまとめ」で振り返りとして確認しておくと安心です。