configure-env-variables について
Dataverse の環境変数を作成し、Power Pages のサイト設定に関連付けるスキルです。環境ごとに異なる値を設定でき、`deploy-pipeline` 用の `deployment-settings.json` も生成します。
主な機能
- 01Dataverse 環境変数定義の作成
- 02サイト設定と環境変数の関連付け
- 03デプロイ段階ごとの値の収集
- 04`deployment-settings.json` の生成
活用シーン
- 01開発・ステージング・本番で異なる値を設定
- 02静的なサイト設定を環境変数ベースに変更
- 03デプロイパイプライン向けに段階別の値を準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill configure-env-variablesインストール後、Claude Code で/configure-env-variablesを入力して読み込まれたか確認します。
同梱ファイルscripts/validate-env-variables.js
詳細
プラグインチェック:
node "${PLUGIN_ROOT}/scripts/check-version.js"を実行します。メッセージが出力された場合は、続行する前にユーザーに表示してください。
configure-env-variables
Dataverse 環境変数を作成し、Power Pages サイト設定にリンクします。これにより、デプロイ環境(dev、staging、prod)ごとに異なる構成値を設定できます。deploy-pipeline で使用する deployment-settings.json を生成します。
背景
Power Pages のサイト設定では、環境変数を使用できます(2025年3月に GA、拡張データモデルのみ)。リンクすると、次のようになります。
- サイト設定の
mspp_sourceが0(静的)から1(環境変数)に変わります - ランタイムは静的な
mspp_valueではなく、現在の環境の環境変数値を読み取ります - パイプラインのデプロイ時に、ターゲット環境の値が
deploymentsettingsjson経由で注入されます
API に関する注意:サイト設定から環境変数へのリンクは、HAR で確認された OData PATCH パターン(v9.0、EnvironmentValue ナビゲーションプロパティ、if-match: * および clienthost: Browser ヘッダーが必須)を使って設定します。この処理は scripts/lib/link-site-setting-to-env-var.js が行います。すべての手順は完全に自動化されています。
前提条件
- PAC CLI で認証済み:
pac auth who - Azure CLI トークンを利用可能:
az account get-access-token - プロジェクトルートに
.solution-manifest.jsonが存在する(先にsetup-solutionを実行してください) - dev 環境に Power Pages サイトがデプロイ済み(
.powerpages-site/フォルダーが存在する)
フェーズ 0 — ALM 計画のゲート
plan-almが最初の窓口です。 ユーザーが ALM の意図(プロモート/リリース/デプロイ/CI-CD のセットアップ/staging への移行/prod へのプッシュ)を示した場合、オーケストレーター(/power-pages:plan-alm)を最初に実行する必要があります。このフェーズ 0 はそれを徹底するものであり、ユーザーが一度無視すれば以後ずっと省略できる一度限りのチェックではなく、計画がない場合に処理を安全側で停止させることを目的としています。
スキップ規則。 このスキルが実行中の plan-alm オーケストレーションの一部として呼び出された場合は、フェーズ 0 全体をスキップし、フェーズ 1 に進みます。ゲートヘルパーは inExecution ブロックを通じてこれを示します。次の場合は何も表示せず、フェーズ 1 に進みます。
inExecution.status === "active"
ヘルパーは docs/.alm-plan-data.json からこの状態を計算します。PLAN_STATUS === "In Execution" かつ LAST_INVOCATION_AT が過去 60 分以内であることが条件です。check-alm-plan.js は、計画が実行中であることを検出するたびに LAST_INVOCATION_AT を自動更新します。そのため、チェーン内の各スキルが次のスキルまでチェーンを維持します。deploy-pipeline はステージごとに 60 分かかる場合があるため、複数時間に及ぶデプロイでも、チェーンが誤って実行中ではないと判定されることなく、この時間枠内で継続できます。ハートビートが 60 分以上ない停滞したチェーンは stale-heartbeat として再分類され、フェーズ 0 のゲートが通常どおり動作します。これにより、放置された計画によってユーザー確認がひそかに回避されることを防ぎます。
inExecution.status が "active" 以外("not-running"、"stale-heartbeat"、"no-plan")の場合は、以下のフェーズ 0 のゲートフローを実行します。残りのヘルパーフィールドに応じて分岐します。
ステップ 1 — ゲートヘルパーを実行します。
node "${PLUGIN_ROOT}/scripts/lib/check-alm-plan.js" --projectRoot "."
ヘルパーは { exists, deferred, stale, staleness: { reason, detail }, generatedAt, planStatus, ... } を含む JSON を返します。最新状態を確認する場合は、フェーズ 1 で取得した後に --envUrl、--token、--solutionId を渡してください。指定しない場合、ヘルパーは存在確認のみを行います。これは、以下のゲート判定には十分です。
ステップ 2 — 結果に応じて分岐します。
| 結果 | 動作 |
|---|---|
deferred: true | ユーザーがこのプロジェクトの ALM を明示的に延期しています(.alm-deferred マーカーが存在します)。警告せずにフェーズ 1 へ進みます。 |
exists: false | ユーザーはまだ plan-alm を実行していません。ステップ 3 を参照してください。 |
exists: true, stale: false | 計画は最新です。何も表示せず、フェーズ 1 へ進みます。 |
exists: true, stale: true(理由:solution-modified) | 計画の生成後にソリューションが変更されました。ステップ 4 を参照してください。 |
ステップ 3 — 計画がありません。 ユーザーに次のように伝えます。
「このプロジェクトには ALM プランがありません。
/power-pages:plan-almを実行すると、プロジェクトの状態を検出し、昇格戦略(PP Pipelines と手動のエクスポート/インポート)について確認したうえで、どのサイト設定を環境変数にするかを分類し、適切なスキル(このスキルを含む)を適切な順序で実行します。今すぐ plan-alm を実行しますか?」
🚦 ゲート(intent · configure-env-variables:0.no-plan):
check-alm-plan.jsがexists:falseを返した場合のフェイルクローズ方式の開始ゲートです。ヘルパースクリプトに基づいています。
AskUserQuestion:
| 質問 | ヘッダー | 選択肢 |
|---|---|---|
先に /power-pages:plan-alm を実行しますか? | ALM プランゲート | はい — 今すぐ /power-pages:plan-alm を実行(推奨)、プランなしで続行(上級者向け — 理解したうえで実行します)、キャンセル |
- はい(推奨) →
/power-pages:plan-almを実行します。プランを作成して終了します。plan-almはプランナーであり、デプロイは行いません。このスキルはその後、フェーズ 0 のチェックを再実行し(exists:trueになった状態)、フェーズ 1 に進み、事前に分類されたsiteSettingsをdocs/alm/alm-plan-context.jsonから取得します。 - プランなしで続行 →
BYPASSED_PLAN_GATE = trueに設定し、フェーズ 1 に進みます。 - キャンセル → 正常に終了します。
手順 4 — 古いプラン。 ユーザーに次のように伝えます:
「ALM プランは
{generatedAt}に作成されていますが、その後ソースソリューションが変更されています({solution.modifiedon})。コンポーネントが変更されている可能性があります。plan-almを再実行すると、分析とレンダリング済み HTML が更新されます。」
🚦 ゲート(intent · configure-env-variables:0.stale-plan):
check-alm-plan.jsがstale:true(プラン作成後にソリューションが変更された状態)を返した場合のフェイルクローズ方式の開始ゲートです。ヘルパースクリプトに基づいています。
AskUserQuestion:
| 質問 | ヘッダー | 選択肢 |
|---|---|---|
| 先にプランを更新しますか? | ALM プランの鮮度 | 更新 — /power-pages:plan-alm を再実行(推奨)、既存のプランで続行、キャンセル |
- 更新(推奨) →
/power-pages:plan-almを実行します。完了後、フェーズ 0 のヘルパーを再実行して鮮度を確認します。それでも古い場合は、詳細を提示してからフェーズ 1 に進みます(無限ループはさせません)。 - 続行 →
STALE_PLAN_ACK = trueに設定し、フェーズ 1 に進みます。 - キャンセル → 正常に終了します。
このゲートがある理由。 configure-env-variables を直接実行すると、オーケストレーターによるステージごとの値の収集、サイト設定の分類(keepAsIs / promoteToEnvVar / authNoValue / excluded)、パイプライン戦略との整合が行われないまま、環境変数の定義と deployment-settings.json が作成されます。このスキルを単独で実行するユーザーは、プランのソリューション分割と整合しない環境変数スキーマ名を選んだり、プランで追加対象に分類された authNoValue 設定を見落としたり、後で setup-pipeline が構成するパイプラインと一致しないステージ名を生成したりすることがよくあります。このゲートにより、plan-alm が実行済みで(環境変数の決定がデプロイプラン全体と整合している)、またはユーザーが明示的に実行を省略することを選択した、いずれかの状態が確保されます。
フェーズ 1 — 既存の状態を確認する
プロジェクトのコンテキストを読み取り、Dataverse にクエリを実行して、すでに構成されている内容を確認します。
1.1 プロジェクトファイルを読み取る:
cat .solution-manifest.json # get solutionUniqueName, environmentUrl, publisher.prefix
cat docs/alm/last-pipeline.json # get hostEnvUrl, stages[].name
ls .powerpages-site/site-settings/ # list all site setting YAML files
1.2 トークンを取得して前提条件を確認する:
node "${PLUGIN_ROOT}/scripts/lib/verify-alm-prerequisites.js" \
--envUrl "{devEnvUrl}" \
--require-manifest
出力を JSON として取得し、.envUrl(devEnvUrl として保存)および .token(TOKEN として保存)を抽出します。
1.3 環境内の既存の環境変数をクエリする:
GET {devEnvUrl}/api/data/v9.2/environmentvariabledefinitions?$select=schemaname,displayname,type,defaultvalue,environmentvariabledefinitionid&$orderby=schemaname
1.4 環境変数がすでに関連付けられているサイト設定(mspp_source = 1)をクエリする:
GET {devEnvUrl}/api/data/v9.2/mspp_sitesettings?$filter=mspp_source eq 1 and _mspp_websiteid_value eq {WEBSITE_ID}&$select=mspp_name,mspp_source,_mspp_environmentvariable_value,mspp_envvar_schema
.powerpages-site/website.yml の id フィールドから WEBSITE_ID を取得します。
1.5 サイト設定の YAML ファイルを解析し、すべての設定と現在のソースを一覧表示します:
source: 1のファイルは、すでに環境変数を使用していますsource: 0または source フィールドがないファイルは静的です
次の要約表をユーザーに提示します:
Current site settings (static): 48
Already env-var-backed: 3
Existing env var definitions: 2
Phase 2 — サイト設定を選択し、環境変数を計画する
どのサイト設定を環境変数で管理するか、ユーザーに尋ねます。静的なサイト設定の一覧を候補として提示します。環境ごとに異なる可能性が高い設定を推奨します。
一般的な候補:
Authentication/OpenIdConnect/AzureAD/ClientId— Entra ID のアプリ登録は環境ごとに異なりますAuthentication/OpenAuth/Microsoft/ClientId— OAuth アプリ IDAuthentication/OpenAuth/Microsoft/ClientSecret— OAuth シークレット(Secret 型を使用)Authentication/Registration/LocalLoginEnabled— 開発環境と本番環境で異なる場合がありますAuthentication/Registration/OpenRegistrationEnabled— オープンサインアップのポリシー- ユーザーが追加したカスタムサイト設定
🚦 ゲート(計画 · configure-env-variables:2.selection): ユーザーが環境変数に昇格させるサイト設定を選択します。複数選択できます。キャンセルすると、環境変数の定義を作成する前に終了します。
AskUserQuestion で尋ねます:
「どのサイト設定を環境変数で管理しますか?それぞれに環境変数を作成し、リンクする手順をご案内します。
候補は次のとおりです(番号をカンマ区切りで入力してください):
- Authentication/Registration/LocalLoginEnabled(現在:true)
- Authentication/OpenIdConnect/AzureAD/ClientId(現在:空)
- [その他の設定...] N. 独自の設定名を入力する」
選択した設定ごとに、次の項目を尋ねます。
- 環境変数のスキーマ名 —
${PLUGIN_ROOT}/scripts/lib/generate-env-var-schema-name.jsを使って生成します(setup-solutionと共有する唯一の情報源です):
出力:node "${PLUGIN_ROOT}/scripts/lib/generate-env-var-schema-name.js" \ --publisherPrefix "{publisherPrefix}" --settingName "{settingName}"{ schemaName, sanitized }。標準ルールは{prefix}_{settingName.replace(/[^A-Za-z0-9]+/g,'_').toLowerCase()}です。たとえば、Authentication/Registration/LocalLoginEnabledはids_authentication_registration_localloginenabledになります。ここに独自のルールを直接記述しないでください。setup-solution はこのヘルパーからスキーマ名を生成するため、configure-env-variables も setup-solution がすでに作成した名前と一致させる必要があります。一致しないと、既存のサイト設定へのリンクに失敗します。ユーザーに理由があれば候補を上書きできますが、既定値は必ずヘルパーから取得してください。 - 表示名(人が読んで理解できる名前)
- 型:String(既定値)、Boolean、Number、Secret
- 開発環境/ソースの値(既定値 = YAML の現在の
mspp_value) - ステージごとの値 —
docs/alm/last-pipeline.json内の各ステージについて、どの値にするか
例:
Setting: Authentication/Registration/LocalLoginEnabled
Schema name: ids_authentication_registration_localloginenabled
Display name: IdeaSphere Local Login Enabled
Type: String (site settings always resolve as strings)
Dev value: true
Staging value: false
Production value: false
Phase 3 — 環境変数の定義を作成する
計画した環境変数ごとに、typeCode に応じて分岐します。
{displayName}の置換ルール — スキーマ名ではなく、人が読んで理解できるラベルを選びます。environmentvariabledefinitionの Dataverse のdisplayname列は、PPAC、レンダリングされた ALM 計画の Env Variables タブ、last-env-vars.jsonに表示されます。スキーマ名(例:c311_api_secret)を--displayNameに指定すると、計画と PPAC の両方に生のトークンが表示されてしまいます。元のサイト設定にあるわかりやすいラベルを選んでください(例:c311/api_secretのDescription、または planData 内の人が読めるタイトルからAPI Secretを選びます)。わかりやすいラベルがない場合は、スキーマ名のプレフィックスを除いた末尾をタイトルケースにして作成します(例:c311_api_secret→Api Secret→ 手作業でAPI Secretに整えます)。displayNameとschemaNameは意図的に異なる値にします。それぞれ対象とするユーザーが異なります。
3.A — 文字列型の環境変数(typeCode = 100000000)
定義のみを作成するフローです。各ステージの値は、デプロイ時に deployment-settings.json から deploymentsettingsjson PATCH を介して後から設定します。
3.A.1 確認し、必要に応じて作成するには、create-env-var-definition.js を使用します(スクリプトは POST の前に schemaName で既存の定義を確認します)。
node "${PLUGIN_ROOT}/scripts/lib/create-env-var-definition.js" \
--envUrl "{devEnvUrl}" \
--token "{TOKEN}" \
--schemaName "{schemaName}" \
--displayName "{displayName}" \
--type 100000000 \
--defaultValue "{devValue}"
出力を JSON として取得し、.definitionId(envVarDefId として保存)を抽出し、.created を確認します(true = 新規作成、false = 既存)。すでに存在する場合は、続行する前に既存の定義が想定どおりであることを確認してください。
3.A.2 現在の環境の値を作成する(defaultvalue とは別の、現在使用中の開発環境の値です)。
POST {devEnvUrl}/api/data/v9.2/environmentvariablevalues
Content-Type: application/json
{
"[email protected]": "/environmentvariabledefinitions({envVarDefId})",
"value": "true"
}
応答:HTTP 204。
3.B — Key Vault Secret URI が利用可能な場合のシークレット型環境変数(typeCode = 100000005)
許可されるシークレット参照形式
Dataverse と Power Platform Pipelines のハンドラーが、シークレット型環境変数の値として受け付ける形式は、正確に3種類です。それ以外はインポート時に "ImportAsHolding failed: The value provided as a secret reference does not match a valid secret reference format" というエラーで拒否されます。ホストはインポートを直列化するため、デプロイがキューに入ってから数時間後に拒否されることもあります。デプロイ前バリデーター(deploy-pipeline Phase 5.1b、ヘルパーは scripts/lib/validate-deployment-settings.js)がこれらの形式を事前に検出しますが、SKILL.md の作成者が deployment-settings.json に最初から適切な形式を指定できるよう、ここに記載します。
許可される形式:
-
Key Vault シークレット識別子 URI —
store-keyvault-secret.jsのsecretUri出力に含まれる形式です。https://<vault>.vault.azure.net/secrets/<name> https://<vault>.vault.azure.net/secrets/<name>/<32-char-hex-version>Vault 名は3~24文字で、小文字の英数字とハイフンのみを使用できます。先頭は英字、末尾は英字または数字にしてください。これは標準形式であり、
add-server-logicPhase 7.2a が、ユーザーに表示される「secretUri の出力を共有する」手順で返す形式です。 -
Azure リソース ID — Maker が URI 形式をすぐに用意できない場合に使う、ARM 形式の完全なパスです。
/subscriptions/<subscriptionId>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault>/secrets/<name>resourceGroupsとresourcegroupsのどちらの大文字・小文字の組み合わせも Dataverse で受け付けられます。 -
空文字列
""— 環境変数の定義に妥当な既定値が設定されている場合に使用できます。deployment-settings.jsonのステージごとのValue: ""は、「このステージでは定義の既定値を使用する」という意味です。
拒否される形式(バリデーターが警告します):
@KeyVault(vaultName=<vault>;secretName=<name>)— テンプレート形式のプレースホルダーです。Dataverse では認識されません。 実際のセッションで、この形式を使った結果、4時間41分のキュー待ちの後に ImportAsHolding エラーが発生しました。形式 (1) または (2) に置き換えてください。<TODO>、<KEY_VAULT_URI>、<PLACEHOLDER>、${ENV_VAR}— 山括弧形式またはシェル形式のプレースホルダーです。同様に、これらは Maker 独自の表記であり、Dataverse では解析されません。- 平文のシークレット値 — ファイルが git にコミットされるため安全でないうえ、環境変数の型が Secret の場合は Dataverse にも拒否されます。意図した値が平文の場合、環境変数の型は Secret(
100000005)ではなく String(100000000)にしてください。 - Key Vault URI に見えるものの標準形式に合致しない HTTPS URL(ホストの末尾が
.netではなく.com、/secrets/セグメントがない、バージョンの接尾辞が短いなど)。バリデーターはこれらにinvalid-uriの警告を個別に表示するため、値を再作成せずに誤記を修正できます。
実装
ユーザーがすでにシークレットを Azure Key Vault に保存しており、正規形式のシークレット識別子 URI を持っている場合は、アトミックなディープインサートパスを使用します。これは add-server-logic の Phase 7.2a が使用するのと同じフローです:
node "${PLUGIN_ROOT}/scripts/create-environment-variable.js" "{devEnvUrl}" \
--schemaName "{schemaName}" \
--displayName "{displayName}" \
--type secret \
--value "{secretUri}"
このスクリプトは単一のディープインサートを POST し、environmentvariabledefinition (type 100000005) と、Key Vault URI を value に持つ environmentvariablevalues 行の両方を作成します。Dataverse は実行時に URI を参照解除してシークレットを解決します。このスクリプトは ALM を認識しており、AddSolutionComponent を介して新しい定義をターゲットソリューションに追加します (ファミリーの他の部分と同じ resolve-target-solution.js の解決順序を使用します)。
相互参照: 完全な Key Vault のエンドツーエンド (Vault の選択 (
list-azure-keyvaults.js/create-azure-keyvault.js)、シークレットの保存 (会話からシークレットを排除するために stdin を使用するstore-keyvault-secret.js)、および環境変数の作成への URI の受け渡し) については、${PLUGIN_ROOT}/skills/add-server-logic/SKILL.mdの Phase 7.2a を参照してください。 実装は同一であり、同じヘルパースクリプトを再利用します。
3.C — Key Vault URI のないシークレット環境変数 (レガシー / 保留)
ユーザーがまだ Key Vault を選択していない、またはシークレットを保存していない場合は、空の値のプレースホルダーで定義を作成し、インポート後に Power Platform Admin Center を介して値を設定するようユーザーに指示します:
node "${PLUGIN_ROOT}/scripts/lib/create-env-var-definition.js" \
--envUrl "{devEnvUrl}" \
--token "{TOKEN}" \
--schemaName "{schemaName}" \
--displayName "{displayName}" \
--type 100000005
(--defaultValue を省略します — Dataverse は environmentvariablevalues 行が追加されるまで、デフォルトなしで Secret タイプの定義を保存します)。値は PPAC → Solutions → Environment Variables → 選択 → 値の設定 を介して、ターゲット環境ごとに設定する必要があることをユーザーに伝えます。このパスはレガシーのフォールバックです。専用の configure-secrets スキル (フォローアップ PR で予定) は、最終的に資格情報スタイルの設定に対して 3.B をエンドツーエンドでオーケストレーションする予定です。
型コードのリファレンス
100000000= String — パス 3.A を経由します。100000005= Secret — パス 3.B (Key Vault URI が利用可能な場合に推奨) または 3.C (保留 / レガシー) を経由します。
その他の正規の型 (100000001 Number、100000002 Boolean、100000003 JSON、100000004 DataSource) は、適切な --type コードを指定してパス 3.A に従います。
作成した環境変数 ID を追跡します: { schemaName, envVarDefId, siteSettingName, devValue, stageValues: { stageName: value } }。
Phase 4 — サイト設定を環境変数にリンクする
リンクする各サイト設定について、link-site-setting-to-env-var.js を実行します (HAR で確認済みの v9.0 API を介した PATCH — UI ステップは不要):
node "${PLUGIN_ROOT}/scripts/lib/link-site-setting-to-env-var.js" \
--envUrl "{devEnvUrl}" \
--token "{TOKEN}" \
--siteSettingId "{siteSettingId}" \
--definitionId "{envVarDefId}" \
--schemaName "{schemaName}"
出力を JSON としてキャプチャし、.ok と .verified が両方とも true であることを確認します。スクリプトは必須の if-match: * および clienthost: Browser ヘッダーを付けて PATCH を適用し、その後 mspp_source === 1 および _mspp_environmentvariable_value が定義 ID と一致することを検証します。
.ok が false または .verified が false の場合は、エラーを報告してユーザーに尋ねます:
「
{settingName}を環境変数{schemaName}にリンクできませんでした。どのように進めますか?
- 再試行
- この設定をスキップ — 静的のままにする
- キャンセル」
Phase 5 — 環境変数をソリューションに追加する
各環境変数の定義について、ソリューションに追加します:
POST {devEnvUrl}/api/data/v9.2/AddSolutionComponent
Content-Type: application/json
{
"ComponentId": "{envVarDefId}",
"ComponentType": 380,
"SolutionUniqueName": "IdeaSphereSolution",
"AddRequiredComponents": false,
"DoNotIncludeSubcomponents": false
}
応答: HTTP 200 と { "id": "..." }。
注意:
environmentvariablevaluesレコードをソリューションに追加しないでください — これらは環境固有であり、各環境にローカルなままにしておく必要があります。ソリューションに入るのは定義 (type 380) のみです。
環境変数がソリューションコンポーネントに表示されることを確認します:
GET {devEnvUrl}/api/data/v9.2/solutioncomponents?$filter=_solutionid_value eq {solutionId} and componenttype eq 380&$select=objectid
Phase 6 — deployment-settings.json を生成する
deployment-settings.json をプロジェクトルートに書き込みます。このファイルはステージごとの環境変数オーバーライド値を保存し、deploy-pipeline によって読み取られます。
{
"$schema": "https://schemas.microsoft.com/power-platform/deployment-settings/2024",
"description": "Per-stage environment variable values for IdeaSphereSolution pipeline deployments. Commit this file. Do not store secrets here — use Secret type env vars backed by Key Vault instead.",
"stages": {
"Deploy to Staging": {
"EnvironmentVariables": [
{
"SchemaName": "ids_LocalLoginEnabled",
"Value": "false"
}
],
"ConnectionReferences": []
}
}
}
ステージ名は docs/alm/last-pipeline.json の stages[].name の値と完全に一致する必要があります。
Secret タイプの環境変数の場合: "Value": "" を書き込み、Azure Key Vault またはパイプラインシークレットを介して値を設定するようユーザーに指示するコメントを追加します — 生のシークレットをこのファイルに保存しないでください。
フェーズ 6.1 — 書き込み前の検証(必須、省略しないでください)
deployment-settings.json をディスクに保存する前に、すべてのエントリが正規の Secret 参照形式に準拠しているか検証してください。Power Platform Pipelines ハンドラーは、ステージの実行がキューに登録され、シリアル化されたインポートの後ろで何時間も待機した後、インポート時に deploymentsettingsjson PATCH を検証します。ここに不正な値(例:テンプレート形式の @KeyVault(vaultName=...;secretName=...) プレースホルダー、シークレットの生の内容、不正な URI)があると、インポートは "ImportAsHolding failed: The value provided as a secret reference does not match a valid secret reference format" で失敗し、ユーザーがそれを知るのは数時間後です。実際の証拠(2026-05-21 Citizens ポータルのデプロイ):deployment-settings.json 内の @KeyVault(...) プレースホルダーがホストに送られ、他のインポートの後ろでキューに入り、4 時間 41 分待機した後に拒否されました。
無効な値を書き込み時に検出するかどうかで、1 秒未満で確実に停止できるか、何時間も手詰まりになるかが決まります。
node "${PLUGIN_ROOT}/scripts/lib/validate-deployment-settings.js" \
--settingsFile "./deployment-settings.json" \
--envUrl "{devEnvUrl}" \
--token "{token}"
このヘルパーは、書き込んだばかりのファイルを読み取り、valueFormat(kv-uri / kv-resource-id / kv-placeholder / empty / plain-text / invalid-uri)で各 EnvironmentVariables[] エントリを分類し、--envUrl が指定されている場合は Secret 型のエントリを Dataverse の型の参照情報と照合して、{ summary: { valid, invalid, "unknown-type", skipped }, findings[] } を出力します。summary.invalid に応じて分岐します。
summary.invalid === 0→ フェーズ 7 に進みます。summary.invalid > 0→ 停止します。無効なfindings[]エントリをそれぞれ、schemaName、valueFormat、value、messageとともにユーザーに提示します。よくある問題:@KeyVault(vaultName=...;secretName=...)→kv-placeholder(テンプレート形式で、Dataverse では決して認識されません)。修正方法:Key Vault Secret Identifier URIhttps://<vault>.vault.azure.net/secrets/<name>[/<version>]、または Azure リソース ID の完全な形式/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.KeyVault/vaults/<vault>/secrets/<name>に置き換えるか、空文字列を指定して環境変数定義の既定値にフォールバックします。- シークレットの生の内容(URI またはリソース ID のパターンに一致しない通常の文字列)→
plain-text。修正方法:シークレットを生のままコミットしないでください。Key Vault URI/リソース ID に切り替えるか、空文字列を指定し、ステージごとにパイプラインシークレットを通じて値を設定します。 - 不正な URI →
invalid-uri。修正方法:上記の正規パターンと照らし合わせて形式を再確認します。
ユーザーから修正後の値が提供されたら、検証を再実行してください。summary.invalid === 0 の場合にのみ、フェーズ 7 に進みます。
🚦 ゲート(同意 · configure-env-variables:6.1.invalid-secret-values): 書き込み前の検証で、形式が無効な Secret 参照が見つかりました。これらの値を含むファイルの出荷を拒否してください。修正するか、中止してください。呼び出し元が回避することはできません。記録された無効な値はすべて、インポート時に失敗します。
このゲートが「そのまま進む」ではなく、確実に停止する理由:不正だと分かっている Secret 参照を「強制的に書き込む」ことに意味はありません。Pipelines ハンドラーはインポート時に必ず拒否します。そのまま書き込んでも、キューでの待ち時間が無駄になるだけです。ユーザーが正規の Key Vault URI をまだ用意できていない場合は、
Value: ""(定義の既定値)を残し、シークレット参照の準備ができたら改めて対応するのが正しい手順です。
フェーズ 7 — 検証とコミット
7.1 サイト設定 YAML を同期する — pac pages upload-code-site を実行して、更新されたサイト設定(Dataverse で source: 1 が確認できる状態になったもの)を YAML に反映します。
pac pages upload-code-site --rootPath "." --environment {devEnvUrl}
アップロード後、更新された YAML ファイルを確認してください。source: 1 が含まれ、環境変数のスキーマ名を参照しているはずです。
7.2 ソリューションに環境変数が含まれていることを確認する:
GET {devEnvUrl}/api/data/v9.2/solutioncomponents?$filter=_solutionid_value eq {solutionId} and componenttype eq 380
7.2b 開発環境に値が反映されていることを確認する。 定義と値を作成した後、開発環境をクエリして、各 environmentvariablevalues 行が存在することを確認します。共有ヘルパー scripts/lib/verify-env-var-values.js を使用すると、この読み取り専用の確認を行えます。
node "${PLUGIN_ROOT}/scripts/lib/verify-env-var-values.js" \
--envUrl "{devEnvUrl}" \
--schemaNames "{comma-separated schema names just created}"
stdout を JSON として取得します。summary.landed === summary.total の場合、ローカルの定義と値の連鎖は正常であり、deploy-pipeline Phase 5.2 の deploymentsettingsjson PATCH に必要な情報がそろっています。summary.missing > 0 の場合は、1 行の警告をログに記録し、configure-env-variables の再実行を推奨します。最も可能性の高い原因は、一時的な OData 書き込みエラーにより、対応する値のない定義が残ったことです。同じヘルパーはデプロイ時にも(deploy-pipeline Phase 7.6.5)、ターゲット環境に対して実行されます。チェックを一元化することで、開発側の書き込みとターゲット側への反映で診断の形式を統一できます。
7.2b.bump ソースソリューションのバージョンを更新し、マニフェストを同期します。 新しい環境変数の定義を作成し、AddSolutionComponent を使ってソリューションに追加すると、solutions.modifiedon が変更されます。下流のスキルで常に増加するバージョンラベルが認識されるようパッチバージョンを更新し、ローカルの .solution-manifest.json にも変更を反映します。
node "${PLUGIN_ROOT}/scripts/lib/bump-solution-version.js" \
--envUrl "{devEnvUrl}" \
--token "{token}" \
--uniqueName "{solutionUniqueName}" \
--projectRoot "."
ヘルパーは { previous, next, bumped: true, manifestUpdated, manifestUpdateReason } を返します。--projectRoot "." を指定すると、.solution-manifest.json の solution.version(複数ソリューションモードでは、一致する solutions[].version)がアトミックに更新されます。この更新を行わないと、.solution-manifest.json が Dataverse より古い状態になります。これは、実際の Citizens ポータルでの実行でも確認されています。configure-env-variables と deploy-pipeline のそれぞれでソースが変更された後、Dataverse のバージョンが 1.0.0.4 に達していた一方で、マニフェストのバージョンは 1.0.0.2 のままでした。
7.2c 構成後の環境変数スナップショットを更新します。 検出ヘルパーを再実行して、新しく作成した定義を含む docs/alm/last-env-vars.json を書き込みます。これを行わないと、レンダリングされた ALM プランの「Env Variables」タブには、最後に setup-solution が書き込んだ内容が残ります。新しく作成された定義は、plan-alm を再実行するまで表示されません。このフェーズの最後に呼び出される更新ヘルパーは、このサイドカーを planData.envVars[] に取り込み、docs/alm/alm-env-vars.json にも反映して、両方のスナップショットを最新の状態に保ちます。
node "${PLUGIN_ROOT}/scripts/lib/discover-env-var-definitions.js" \
--envUrl "{devEnvUrl}" \
--publisherPrefix "{publisherPrefix}" \
--websiteRecordId "{websiteRecordId}" \
--token "{token}" \
--solutionId "{solutionId}" > docs/alm/last-env-vars.json.tmp \
&& mv docs/alm/last-env-vars.json.tmp docs/alm/last-env-vars.json
一時ファイルへの書き込みパターンにより、検出が一時的に失敗した場合も、正常なスナップショットが保持されます。結果をターゲットソリューションに限定するには、--solutionId を指定します。指定しない場合、汎用の発行元プレフィックスによって、同じテナント内の無関係なプロジェクトの環境変数も返されます。
7.3 コミット:
git add .powerpages-site/site-settings/ deployment-settings.json
git commit -m "Configure env vars: {list of schema names} — link {setting names} to env vars for ALM"
7.4 概要を提示します:
✅ Environment variables configured
Env vars created/confirmed:
ids_LocalLoginEnabled → Authentication/Registration/LocalLoginEnabled
Dev value: true
Staging: false
Added to solution: IdeaSphereSolution (1 env var component)
deployment-settings.json written with:
Stage "Deploy to Staging": ids_LocalLoginEnabled = false
Next steps:
1. Run /power-pages:export-solution to export the updated solution
2. Run /power-pages:deploy-pipeline — it will automatically read deployment-settings.json
and inject the env var values during deployment
3. After deployment, verify in staging: the Sign In button should be hidden
(Authentication/Registration/LocalLoginEnabled = false)
7.5 スキルの使用状況を記録します:
参照:
${PLUGIN_ROOT}/references/skill-tracking-reference.md
参照先のスキル追跡手順に従い、このスキルの使用状況を記録します。--skillName "ConfigureEnvVariables" を使用してください。
7.5b ALM プランを更新します(存在する場合):
node "${PLUGIN_ROOT}/scripts/lib/refresh-alm-plan-data.js" \
--projectRoot "." \
--phase configure-env-variables \
--live \
--render
ヘルパーは docs/alm/last-env-vars.json を再読み込みし、新しく作成された定義を planData.envVars[] に反映します。また、deployment-settings.json のステージごとの値を「Values by Environment」マトリックスに補完します(--live を指定すると、各プランステージのライブ environmentvariablevalues テーブルから読み取った値もマージされるため、Power Platform Admin Center で設定した値が表示されます。deployment-settings.json の値が優先され、クエリに失敗したステージは出力の liveEnvVars.errors に記載され、変更されません)。さらに、plannedEnvVarCount をゼロにし、LAST_SYNC_AT を記録して、docs/alm-plan.html を再レンダリングします。docs/.alm-plan-data.json が存在しない場合(ALM プランの一部ではなく、単独で実行された場合)、ヘルパーは ok:false を返して何もせずに終了します。無条件で実行しても安全です。
ライブクエリの失敗を通知します。 ヘルパーの標準出力 JSON に空ではない liveEnvVars.errors[] が含まれている場合、読み取りに失敗したステージを、1 行ずつユーザーに伝えます。"{stage} のライブ環境変数値を読み取れませんでした:{error}。Values by Environment マトリックスのその列は変更されていないため、Power Platform Admin Center で設定された値が欠落していたり、古い可能性があります。" エラーが HTTP 401/403 の場合、またはトークンを取得できなかったと記されている場合、Azure CLI がその環境とは異なるテナントにサインインしている可能性が最も高いです(az は既定のサブスクリプションのテナント用トークンを発行しますが、このテナントは PAC CLI プロファイルのテナントと異なることがあります)。そのため、az login --tenant <environment tenant id>(または az account set --subscription <a subscription in that tenant>)を実行し、上記の更新コマンドを再実行するよう提案します。これは情報提供のみです。スキルを失敗させたり、概要の提示を妨げたりしないでください。liveEnvVars がない場合や、errors が空の場合は何も伝えません。
次のステップをユーザーに提示します(ユーザー主導の実行順序)。 ヘルパーの標準出力 JSON には、nextStep: { name, skill: string | null } | null が含まれています。null でない場合は、skill に応じて分岐します。skill が null でない場合、ユーザーに "計画を更新しました。計画の次のステップ:{nextStep.name} → 準備ができたら {nextStep.skill} を実行してください。" と伝えます。skill が null(Finalize などの内部ステップで、ユーザーが実行するコマンドがない場合)は、ステップ名のみを伝えます。"計画を更新しました。計画の次のステップ:{nextStep.name}。" とし、run null は絶対に表示しないでください。null の場合、またはヘルパーが ok:false を返した場合は、次のステップについて何も伝えません。次のスキルを自動的に呼び出さないでください。実行はユーザー主導です。
重要な判断ポイント(ユーザーの回答を待つ)
| フェーズ | 判断 | 選択肢 |
|---|---|---|
| フェーズ 2 | 環境変数で管理するサイト設定 | リストから選択 |
| フェーズ 2 | 環境変数のスキーマ名、型、ステージごとの値 | それぞれ入力 |
| フェーズ 4 | リンク失敗時の再試行/スキップ/キャンセル | 再試行/スキップ/キャンセル |
| フェーズ 7 | コミットと次のステップの確認 | 続行/調整 |
タスクの進捗表
| タスクの内容 | activeForm | 説明 |
|---|---|---|
| 既存の状態を確認 | 既存の状態を確認中 | マニフェストを読み取り、既存の環境変数とすでにリンクされているサイト設定を Dataverse に問い合わせて、候補を一覧表示します |
| 環境変数を計画 | 環境変数を計画中 | 環境変数で管理するサイト設定をユーザーに尋ね、スキーマ名、型、開発環境および各ステージの値を収集します |
| 環境変数の定義を作成 | 環境変数の定義を作成中 | 計画した各環境変数について、environmentvariabledefinitions と environmentvariablevalues に POST します |
| サイト設定を環境変数にリンク | サイト設定をリンク中 | 各設定について link-site-setting-to-env-var.js を実行し、出力の .ok と .verified を確認します |
| 環境変数をソリューションに追加 | 環境変数をソリューションに追加中 | 各環境変数の定義について AddSolutionComponent(type 380)を実行します |
| deployment-settings.json を生成 | デプロイ設定を生成中 | ステージごとの環境変数値を含む deployment-settings.json を書き込みます |
| 検証してコミット | 検証してコミット中 | YAML を同期し、ソリューションコンポーネントを検証してコミットし、概要を提示します |