Githubのリポジトリ設定にて整理する機会があったので、備忘。
- Environments 設定箇所
- Environments 利用シーン
- Environments で何ができるのか
- 「Required reviewers」
- 「Wait timer」
- Github契約プランによるEnvironments設定の違いについて
- ワークフローでenvironmentsを指定した際に、Environmentsシークレット/変数が見つからなかったとき
- ワークフローでenvironmentsを指定した際に、各箇所で同一名のEnvironmentsシークレット/変数を登録していた場合
- Environmentsを使ったワークフロー例
- サンプルコード
Environments 設定箇所
リポジトリ > Settings > Code and automation > Environments
Environments 利用シーン
Environments ワークフローとの連携以外 に用いられるケースはほぼありません。(Deployments REST API 経由での利用も可能)
ワークフロー内でjobs.<job_id>.environment: <env>
を付けると、そのジョブが実行される前に環境保護ルール(Required reviewers、Wait timer)を必ず通過しないと先に進めなくなります。
さらに、Environment に定義したシークレット(Environmentsシークレット)・変数(Environments変数)は、そのジョブからしか読み込めません。
それ以外、たとえばプルリク上でのブランチ制御やコードレビュー、Packages/Codespaces/Dependabot など他の GitHub 機能で Environment を直接参照したり制御したりする仕組みは提供されていません。
Environments で何ができるのか
Environments を使うことで、リポジトリ全体のシークレット(Settings -> Security -> Secrets and variables)とは別に、より細かいアクセス制御や承認フローをシークレット利用時に挟むことができます。
主なメリットは以下のとおりです:
環境ごとのシークレット分離
- 通常のリポジトリシークレットは、ワークフロー内のどのジョブからでも
${{ secrets.NAME }}
で取得可能です。※ 重要 - 一方、Environment に登録したシークレットは、その環境を参照したジョブ(
environment: staging
など)でしか読み込めません。 - たとえば、本番用の AWS 認証情報を
production
環境にのみ置き、それ以外のブランチ/ワークフローでは一切参照できないようにできます。
- 通常のリポジトリシークレットは、ワークフロー内のどのジョブからでも
デプロイ前の保護(承認)ルール適用
- Environment には「Required reviewers」や「Wait timer」を設定でき、ジョブが実際に環境シークレットへアクセスする前に人による承認や一定時間の待機を挟めます。
- たとえば、
production
環境のシークレットを取得する前に必ず 2 名以上のレビュアー承認を通す、といった運用が可能です。
ブランチやタグの制限
- 環境保護ルールで、どのブランチ/タグからのジョブだけが環境を利用できるかを指定できます。
- これにより、
dev
ブランチではstaging
環境のシークレットは使えても、staging
環境の承認を通したジョブだけがproduction
のシークレットを読める、という段階的アクセスコントロールが実現できます。
監査ログとの連携
- 環境を介して実行されたジョブは、誰がいつ承認したかを GitHub の監査ログで追跡できます。
- 機密情報へのアクセス記録を残すことで、セキュリティ要件への対応やインシデント時の調査に役立ちます。
「Required reviewers」
Required reviewers(必須レビューアー)
- 何をするか 環境(Environment)に対して「このジョブを実行する前に、特定のユーザー/チームの承認を必須にする」機能です。
主な挙動
- ワークフロー上で
jobs.<job_id>.environment: <env-name>
を指定したジョブは、開始直後に“保護ゲート”に入ります。 - ジョブは「Waiting」ステータスとなり、実際のステップ(
run:
等)は実行されません。 - 必須レビュアーとして設定したユーザーまたはチームのうち いずれか1名 が「Approve & deploy」を行うと、ジョブは保護ゲートを通過し、続きのステップを実行します。
- 承認が 30日以内 に行われない場合、自動的に失敗扱いとなります。
- ワークフロー上で
設定のポイント
- レビュアーは最大 6 名(ユーザー/チームの組み合わせ)まで指定可能。
- レビュアーには少なくともリポジトリの「Read」権限が必要。
- 必要に応じて「自己承認を防ぐ(prevent self-review)」オプションで、ジョブ実行者自身による承認を禁止できます。
プラン制限
- パブリックリポジトリ:Free/Pro/Team でも利用可
- プライベート/内部リポジトリ:GitHub Enterprise プランが必要
「Wait timer」
Wait timer(待機タイマー)
- 何をするか ジョブ実行開始直後に指定分数だけ “一時停止” し、その後で次の保護ルール(Required reviewers など)へ進ませる機能です。
主な挙動
- ジョブがトリガーされると即座にタイマーを開始し、指定分数の間ジョブ実体を保留(保護ゲート内)にします。
- タイマーが切れると、ジョブは「タイマー待機完了」となり、次の承認ステップや実際の処理へ移行します。
設定のポイント
- タイマーは 1 分~43,200 分(30 日) の整数で設定可能。
- タイマー中の時間は 課金対象外 です。
プラン制限
- パブリックリポジトリ:Free/Pro/Team でも利用可
- プライベート/内部リポジトリ:GitHub Enterprise プランが必要
両者を同時に使う場合の流れ
- ジョブがトリガー → Wait timer が動き出し、指定時間だけ保留
- タイマー切れ → 「承認待ち(Required reviewers)」の状態に移行
- 必須レビュアーのいずれかが承認 → ジョブ本体ステップが実行
- 未承認状態が 30日 継続すると失敗扱い
つまり、 * まず「最低限の待機時間」を確保し、 * その後「人による承認」を通過させて * 初めてデプロイ用スクリプトや機密シークレットへのアクセスを許可
ということができます。
Github契約プランによるEnvironments設定の違いについて
プライベートリポジトリでは Required reviewers や Wait timer といったデプロイ保護ルールは使えません。
GitHub Free/Pro/Team プランでは、環境 (Environments) 自体や「環境シークレット」「デプロイ対象ブランチ制限」はプライベートリポジトリでも利用できますが、 Required reviewers/Wait timer をはじめとする「その他のデプロイ保護ルール」は パブリックリポジトリでのみ 有効です 。
- プライベートリポジトリでこれらを利用するには、GitHub Enterprise プランへのアップグレードが必要になります 。
ワークフローでenvironmentsを指定した際に、Environmentsシークレット/変数が見つからなかったとき
GitHub Actions の secrets
および vars
(変数)コンテキストは、ジョブがアクセス可能な全レベルの値をまとめて提供します。つまり、ジョブで environment: production
を指定すると、
- Environment シークレット
- Repository シークレット
- Organization シークレット
のすべてが secrets
コンテキストにロードされ、同一キー名があれば Environment シークレットが優先 されます。
- もし
production
環境側にAPI_KEY
が定義されていなくても、リポジトリ側に同じキー (API_KEY
) があればsecrets.API_KEY
で取得できます 。 - どちらにも定義がなく参照しようとすると、戻り値は空文字列になります 。
同様に、変数 (vars
) も
- Environment 変数
- Repository 変数
- Organization 変数 をまとめて読み込み、同名キーは Environment 側が上書きします。定義がなければ Repository 側の変数が使われます 。
まとめ
environment: production
を指定したジョブでは、Environment→Repository→Organization の順でシークレット/変数を参照。- Environment に値がなければ、リポジトリの値をそのまま利用。
- どこにも存在しないキーを参照すると、空文字列が返ります。
ワークフローでenvironmentsを指定した際に、各箇所で同一名のEnvironmentsシークレット/変数を登録していた場合
Environment に secret1: A Repository に secret1: B Organization に secret1: C
であれば、最終的にはEnvironmentsのA
が採用されます。
つまり優先順位は、Environments > Repository > Organizations。(範囲が狭いほうが優先されます。)
Environmentsを使ったワークフロー例
environment
は ワークフローのトップレベルや ステップレベルではなく、必ず各ジョブ (jobs.<job_id>
) の中に定義する必要があります。
jobs: deploy: runs-on: ubuntu-latest environment: production # ← ここでのみ指定可能 steps: - uses: actions/checkout@v4 - name: Deploy run: ./deploy.sh
- ジョブ外 (workflow ルート) に書くと構文エラー になります。
- ステップ毎に environment を切り替えることもできず、あくまでジョブ単位で “このジョブはどの Environment の保護ルール・シークレットを使うか” を指定する用途です。
したがって、環境ゲートを使いたいジョブごとに必ず environment: <env-name>
を書いてください。
サンプルコード
- Environmentsに
production
として登録済みとする。
name: Deploy with Environment Secrets on: push: branches: [ main ] jobs: deploy: name: Deploy to Production runs-on: ubuntu-latest environment: production # production 環境を参照 defaults: run: working-directory: ./deploy-scripts # デプロイスクリプトの場所 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Use production secrets # production 環境のシークレットを読み込む run: echo "ACCESS_KEY=${{ secrets.PROD_ACCESS_KEY }}" && \ echo "SECRET=${{ secrets.PROD_SECRET_KEY }}" - name: Run deployment script run: ./deploy.sh
# environment設定値を手動ワークフロー実行時に指定するパターン name: Terraform CI/CD on: workflow_dispatch: inputs: environment: description: 'Deployment environment' required: true default: 'production' jobs: terraform: runs-on: ubuntu-latest environment: ${{ github.event.inputs.environment }} # 実行時に指定された environment を参照 defaults: run: working-directory: ./infra # 必要に応じてパスを調整してください steps: - name: Checkout repository uses: actions/checkout@v4 - name: Configure AWS Credentials (Assume Role) uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} # Assume Role 用の ARN aws-region: ${{ secrets.AWS_REGION }} role-session-name: github-actions-session # 任意のセッション名 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: 1.7.2 # お好みのバージョンを指定可能 - name: Terraform Init run: terraform init - name: Terraform Validate run: terraform validate - name: Terraform Format Check run: terraform fmt -check - name: Terraform Plan run: terraform plan -out=tfplan
以上です。