こんにちは!日々のデプロイ作業やパイプラインの構築、本当にお疲れ様です。
今回は、GitHub Actionsを使った開発で誰もが一度は頭を悩ませる「多環境(ステージング、本番など)の複雑な設定値管理」について、現場で即座に使える超実践的な裏技をご紹介します。
これをマスターすれば、「環境ごとにシークレットを何個も手動で登録し直す」という苦行から解放され、スマートで拡張性の高いCI/CDパイプラインが手に入りますよ。毎日の開発が劇的に楽になりますので、ぜひ最後までついてきてくださいね!
—
1. GitHub Actionsと「環境変数・シークレット」の基本
まずは、今回の主役であるGitHub Actionsと、変数を安全に扱う仕組みについておさらいしておきましょう。
GitHub Actionsとは?
GitHub Actionsは、コードのプッシュやプルリクエスト作成などのイベントをトリガーにして、テスト、ビルド、デプロイなどのタスクを自動化(CI/CD)するための強力なエンジンです。
暗号化されたシークレット(Encrypted Secrets)の役割
パスワード、APIキー、データベースの接続情報など、ソースコードに絶対に含めたくない機密情報は、GitHubの「Secrets」という機能を使って暗号化して保存します。
アクションの実行時に、環境変数(`secrets.API_KEY` のように)として安全に呼び出すことができるのが特徴です。
—
2. なぜ「標準のEnvironment機能」だけでは足りなくなるのか?
GitHubには「Environments(環境)」という、ステージングやプロダクションごとに承認フローやシークレットを分ける素晴らしい機能があります。
しかし、プロジェクトが大きくなり、以下のような要件が出てくると、標準機能だけでは限界が来ます。
- 変数の数が多すぎる: 接続先URL、タイムアウト値、機能フラグなど、環境ごとに数十個の設定値がある。
- 動的に切り替えたい: ブランチ名やプルリクエストのラベルに応じて、動的に設定の組み合わせを変えたい。
「シークレットの登録画面を何度もポチポチして管理するのは、ヒューマンエラーの元だし面倒くさい……!」
そんなときに役立つのが、「設定値をJSONで一元管理し、ワークフローから動的にマッピングする裏技」です。
—
3. 【実践】JSONファイルとマッピングで多環境を華麗にさばく裏技
ここからが本題です。
今回は、`staging` と `production` という2つの環境に向けて、設定値をJSONファイルで管理し、GitHub Actions側で動的に読み込んで切り替える仕組みを作ってみましょう。
ステップ1:設定ファイル(JSON)を用意する
リポジトリのルートに、設定値をまとめた `config/environments.json` を作成します。
(※ここに機密情報は含めず、あくまで「環境ごとのパラメータ構造」を定義します)
{
“staging”: {
“api_endpoint”: “https://api-stg.example.com”,
“log_level”: “debug”,
“enable_cache”: false
},
“production”: {
“api_endpoint”: “https://api.example.com”,
“log_level”: “error”,
“enable_cache”: true
}
}
ステップ2:機密情報はGitHub Secretsにまとめる
機密情報(例:APIトークンなど)だけは、これまで通りGitHubの「Secrets」に登録します。
今回は例として、キーを環境ごとに分けるのではなく、以下のようにサフィックス(接尾辞)をつけて登録しておきます。
- `STAGING_API_TOKEN`
- `PRODUCTION_API_TOKEN`
ステップ3:動的マッピングを行うワークフローを書く
ここが一番のキモです!GitHub Actionsのワークフローファイル(`.github/workflows/deploy.yml`)を以下のように記述します。
name: Dynamic Multi-Environment Deploy
on:
push:
branches:
- main
- develop
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# 1. リポジトリのコードをチェックアウト
- name: Checkout Code
uses: actions/checkout@v4
# 2. ブランチ名からターゲット環境を自動判定する
- name: Determine Environment
id: env-set
run: |
if [[ “${{ github.ref }}” == “refs/heads/main” ]]; then
echo “env_name=production” >> $GITHUB_OUTPUT
echo “secret_prefix=PRODUCTION” >> $GITHUB_OUTPUT
else
echo “env_name=staging” >> $GITHUB_OUTPUT
echo “secret_prefix=STAGING” >> $GITHUB_OUTPUT
fi
# 3. jqコマンドを使ってJSONから該当環境の設定値を抜き出して動的に環境変数にセット!
- name: Load Config from JSON
id: load-config
run: |
ENV_NAME=”${{ steps.env-set.outputs.env_name }}”
# jqでJSONをパースし、GitHub Actionsの環境変数に出力する
API_ENDPOINT=$(jq -r –arg env “$ENV_NAME” ‘.[$env].api_endpoint’ config/environments.json)
LOG_LEVEL=$(jq -r –arg env “$ENV_NAME” ‘.[$env].log_level’ config/environments.json)
ENABLE_CACHE=$(jq -r –arg env “$ENV_NAME” ‘.[$env].enable_cache’ config/environments.json)
echo “API_ENDPOINT=$API_ENDPOINT” >> $GITHUB_ENV
echo “LOG_LEVEL=$LOG_LEVEL” >> $GITHUB_ENV
echo “ENABLE_CACHE=$ENABLE_CACHE” >> $GITHUB_ENV
echo “Loaded config for: $ENV_NAME”
# 4. 機密情報(Secret)を動的なプレフィックスを使って安全にロード
- name: Load Secret
id: load-secret
run: |
PREFIX=”${{ steps.env-set.outputs.secret_prefix }}”
# インダイレクトにシークレットを環境変数に割り当てる
# ※GitHubの仕様上、secretsオブジェクトは動的キーを指定できないため、パターンマッチや条件分岐を使います
if [ “$PREFIX” == “PRODUCTION” ]; then
echo “API_TOKEN=${{ secrets.PRODUCTION_API_TOKEN }}” >> $GITHUB_ENV
else
echo “API_TOKEN=${{ secrets.STAGING_API_TOKEN }}” >> $GITHUB_ENV
fi
# 5. 動作確認(HelloWorld的ステップ)
- name: Verify Dynamic Configuration
run: |
echo “=== デプロイ設定の確認 ===”
echo “Target Environment: ${{ steps.env-set.outputs.env_name }}”
echo “API Endpoint: $API_ENDPOINT”
echo “Log Level: $LOG_LEVEL”
echo “Cache Enabled: $ENABLE_CACHE”
# セキュリティのため、シークレットの中身はマスクして存在確認だけにする
if [ -n “$API_TOKEN” ]; then
echo “API Token: [LOADED SUCCESSFULLY]”
else
echo “API Token: [MISSING]”
fi
—
このアプローチの素晴らしいメリット
1. 設定の見通しが圧倒的に良くなる:
環境ごとのパラメータがひとつのJSONファイル(`environments.json`)に集約されているため、コードレビューの際に「ステージングと本番で設定の差異がどうなっているか」が一目で分かります。
2. スクリプトの再利用性が上がる:
ブランチやトリガーに応じて読み込むキーを動的に切り替えているため、環境ごとにワークフローファイルを複製する必要がありません(DRY原則の維持)。
3. 安全性の担保:
機密情報はしっかりとGitHub Secretsの暗号化領域に守られつつ、非機密のパラメータ構造はリポジトリでバージョン管理できるという、セキュリティと利便性のいいとこ取りができます。
—
おわりに
今回は、GitHub Actionsにおける「多環境向け設定値の動的マッピング」という少し踏み込んだ裏技をご紹介しました。
最初は少し難しく感じるかもしれませんが、Linuxの標準ツール(`jq` など)とGitHub Actionsの出力機構(`$GITHUB_OUTPUT` / `$GITHUB_ENV`)を組み合わせることで、パイプラインの表現力は無限に広がります。
「毎日の面倒な手作業を、スマートな自動化で置き換える」――これこそがエンジニアの醍醐味です。ぜひあなたのプロジェクトでも試してみてくださいね。あなたの開発ライフがより快適になることを応援しています!