初めに
ども!最近はどんな検証をするときも最後のデプロイまで作るので、GitHub Actionsをセットで書くことが多い龍ちゃんです。今回はGitHub Actionsの再利用可能ワークフローについてお話ししたいと思います。最近、同じリポジトリ内でCIのワークフローからCDのワークフローを呼び出す際に、GitHubのシークレットがうまく渡せない問題に遭遇しました。
特に興味深いのが、公式ドキュメントでは「Environment Secretsは渡せない」とされているのに、実際にはなぜか渡ってしまうという現象です。この予想外の動作について検証した結果をご紹介します。
実際に試してみませんか?
この記事で紹介した検証は、皆さんのGitHubリポジトリでも再現できます。特に「公式ドキュメントでは不可能とされているが実際には動作する」という部分は、実際に動かしてみることで納得感が得られると思います。ぜひ検証してみて、結果をコメントで教えていただけると嬉しいです!
というか!GitHub公式のドキュメントにケチつける内容なんで自信がないんです!!
GitHub Secretsには3つのパターンがある
まずは基本から整理しましょう。GitHubのシークレットには3つの設定パターンがあります。
Secret種別 | 設定レベル | アクセス範囲 | 主な用途 | 特徴 |
---|---|---|---|---|
Repository Secrets | リポジトリ | 全てのワークフロー | APIキー、一般的な設定値 | 基本的なシークレット管理 |
Organization Secrets | 組織 | 複数リポジトリで共有 | 組織共通の認証情報 | 組織レベルでの統一管理 |
Environment Secrets | 環境 | 特定環境のみ | デプロイ先の機密情報 | 承認フロー、ブランチ制限と連携 |
それぞれセキュリティレベルと管理範囲が異なるため、プロジェクトの要件に応じて使い分ける必要があります。
再利用可能ワークフローについて
再利用可能ワークフローは、DRY原則でワークフローを共通化できる機能です。基本的な使い方はこんな感じです:
jobs:
deploy:
uses: ./.github/workflows/reusable.yml
メリットとしては、メンテナンス性向上、標準化、コード重複削減が挙げられます。2022年5月にsecrets: inherit
という機能も追加されて、より使いやすくなりました。
公式ドキュメントによる制限事項
公式ドキュメントでは、以下のような記載があります:
“Environment secrets cannot be passed from the caller workflow as on.workflow_call does not support the environment keyword”
つまり、想定される動作は:
- Repository/Organization Secrets → ✅ 継承可能
- Environment Secrets → ❌ 継承不可
これが開発者の困りごとでした。デプロイワークフローでEnvironment Secretsを使いたいし、環境ごとの承認フローも維持したい。しかし再利用可能ワークフローでは使えない、という状況です。
実際の検証: 段階的にSecret継承を確認
Repository/Organization Secrets の検証(期待通りの動作)
まず確実に動作するパターンから見ていきましょう。
name: ci-repo-org-secrets-tests
on:
workflow_dispatch:
jobs:
# API_KEYはrepoかorgにKEYが設定されている必要がある
call-secrets:
uses: ./.github/workflows/cd-secrets-mapped.yml
secrets:
API_KEY: ${{ secrets.API_KEY }}
call-secrets-inherit:
uses: ./.github/workflows/cd-secrets-mapped.yml
secrets: inherit
再利用可能ワークフロー側:
name: cd-secrets
on:
workflow_call:
secrets:
api_key:
required: true
jobs:
deploy-job:
runs-on: ubuntu-22.04
name: Get to GitHub Secret
steps:
- name: Check Validation Result
run: |
echo "🔍 デプロイ前検証を実行中..."
if [ -z "${{ secrets.api_key }}" ]; then
echo "::error title=Missing Deployment Target::api_key が必要です"
exit 1
fi
結果: 両パターンとも正常動作。公式ドキュメント通りの動作を確認できました。
Environment Secrets の検証(予想外の動作)
検証環境の準備として、Environment: production
を作成し、Environment Secret: API_KEY
を設定しました。再利用可能ワークフローはjobレベルでしか呼び出せないので、Secretで明示的に渡す方法がありません。
検証パターン2-A: secrets: inherit なし(動作しない)
name: ci-env-secrets-tests
on:
workflow_dispatch:
inputs:
env_name:
description: "Environment name to test (e.g. production, staging)"
required: true
default: "production"
type: environment
jobs:
# 失敗する(これは納得)
call-env-fixed-no-inherit:
uses: ./.github/workflows/cd-env-fixed.yml
# 成功する(なぜ!?)
call-env-fixed-inherit:
uses: ./.github/workflows/cd-env-fixed.yml
secrets: inherit
再利用可能ワークフロー側:
name: cd-env-fixed
on:
workflow_call:
jobs:
deploy:
runs-on: ubuntu-22.04
# 呼び出される側で環境を固定する例(ここでは production)
environment: production
steps:
- name: Mask and check environment secret
run: |
echo "🔍 Environment 'production' で環境シークレットを検証"
echo "::add-mask::${{ secrets.API_KEY }}"
if [ -z "${{ secrets.API_KEY }}" ]; then
echo "::error title=Missing API_KEY::Environment 'production' の API_KEY が未設定です"
exit 1
fi
echo "✅ Environment 'production' のシークレット(API_KEY)を参照できました(値はマスク済み)"
実行すると、inheritを付けたパターンは成功し、付けていないパターンは失敗します。
検証結果の整理
Secret種別 | 明示的指定 | secrets: inherit | 公式見解からの理解 | 実際の動作 |
---|---|---|---|---|
Repository | ✅ | ✅ | 渡せる | ✅ 動作 |
Organization | ✅ | ✅ | 渡せる | ✅ 動作 |
Environment | ❌ | ✅ | 渡せない | 🚨 動作する |
コミュニティでの議論状況
この問題は2021年から指摘されていますが、現在でも修正されていないようです。
主要なIssue
- Issue #1490 (2021年11月): 最初に問題が報告された「Environment Secrets are not available on Reusable Workflow」
- Issue #3379 (2024年7月): 現在も続く問題への要望「Enhancement: Streamlining secret inheritance to environment in reusable workflows」
3年間解決されていない状況で、バグなのか仕様なのかが不明です。多くの開発者が同様の問題で混乱しており、コミュニティではsecrets: inherit
+ 再利用可能ワークフロー側でのenvironment指定という回避策が使われています。
「使えるけど公式サポートではない」という微妙な状態が続いています。
実用的な活用方法
現在使える推奨パターンは以下の通りです:
# 呼び出し側
jobs:
deploy:
uses: ./.github/workflows/deploy.yml
secrets: inherit
# 再利用可能ワークフロー側
jobs:
deploy-job:
runs-on: ubuntu-latest
environment: production # ここで環境を指定(inputで渡すこともできるよ!)
steps:
- name: Deploy
run: echo "Deploy with ${{ secrets.DEPLOY_KEY }}"
セキュリティ考慮事項
- 意図しないSecretが渡されるリスクがある
- Environmentの承認フローは正常に機能する
- Repository/Organization Secretsも同時に渡される点に注意が必要
代替手法の比較
- Repository Secrets: 管理が簡単だがセキュリティレベルが低い
- Organization Secrets: スケールするがすべてのリポジトリからアクセス可能
- 専用キー管理サービス: 最もセキュアだが複雑性が増す
プロジェクトでの判断基準としては、環境ごとのデプロイ制御が必要な場合は現在の回避策を使用し、セキュリティ要件が厳しい場合は専用サービスを検討するのが良いでしょう。将来の公式サポートを見据えた設計にしておくことも重要です。
まとめと今後の展望
現状の整理をすると:
- Environment Secretsは
secrets: inherit
で実際には使える - 公式ドキュメントと実装に乖離があるように見える(公式の記載の理解ができていないのかも…)
- 3年間この状態が続いている
シークレットが意図せず渡せてしまう状況は便利に使えますが、個人的には、リポジトリ単位でのキー管理方法や、専用のキー管理サービス(キーボールトなど)を使うべきではないかと考えるようになってしまいました。
現在の方法を理解した上で慎重に活用し、セキュリティリスクを十分検討した上で、GitHubの動向を継続的にウォッチしていくことが重要ですね。この検証はマジで疲れました!
参考リンク
公式ドキュメント
- Reusing workflows
- Workflow syntax – jobs.<job_id>.uses
- Using environments for deployment
- GitHub Actions: Simplify using secrets with reusable workflows (2022年5月)