mcpField
S
setup-pipeline

setup-pipeline

github.com/microsoftクラウド・DevOps1.1k162 回インストール今日更新
リポジトリ

setup-pipeline について

setup-pipelineは、DataverseでPower Platform Pipelinesを構成するPower Pages向けスキルです。プロジェクトや環境の確認、ALM計画のゲート、パイプライン作成を通じてデプロイを準備し、YAMLや外部CI/CD基盤を必要としません。

主な機能

  1. 01Dataverseでパイプライン構成を作成
  2. 02プロジェクトとソリューションの確認
  3. 03認証とAPIアクセスの検証
  4. 04Pipelinesホスト環境の特定
  5. 05ALM計画の確認を要求

活用シーン

  1. 01Power Pagesの自動デプロイ設定
  2. 02環境間のソリューション昇格の準備
  3. 03パイプライン作成前のALM準備状況確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/microsoft/power-platform-skills --skill setup-pipeline

インストール後、Claude Code で/setup-pipelineを入力して読み込まれたか確認します。

同梱ファイルscripts/validate-pipeline.js

詳細

翻訳後に原文が更新されています。最新の内容は原文をご確認ください。

プラグインの確認:node "${PLUGIN_ROOT}/scripts/check-version.js" を実行してください。メッセージが出力された場合は、続行する前にユーザーに表示してください。

setup-pipeline

Power Pages ソリューションを自動デプロイするための Power Platform パイプラインを設定します。PP Pipelines OData API を使用して、Dataverse にパイプライン構成を直接作成します。YAML ファイルや外部の CI/CD インフラストラクチャは必要ありません。

GitHub Actions と Azure DevOps Pipeline のオプションは、プラットフォームメニューで 近日公開として表示されます。

このスキルで使用する HAR で確認済みの API パターンについては、${PLUGIN_ROOT}/references/cicd-pipeline-patterns.md を参照してください。

前提条件

  • プロジェクトルートに powerpages.config.json が存在する
  • .solution-manifest.json が存在する(先に setup-solution でソリューションを作成しておく必要があります)
  • Azure CLI にログインしている(az account show が成功する)
  • PAC CLI にログインしている(pac env who が成功する)
  • Pipelines パッケージがインストールされた Power Platform 環境(「ホスト」環境)がある

フェーズ

フェーズ 0 — ALM プランゲート

plan-alm が最初の窓口です。 ユーザーが ALM に関する意図(プロモート/リリース/デプロイ/CI-CD の設定/ステージングへの移行/本番環境へのプッシュ)を示した場合、オーケストレーター(/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 "." \
  --envUrl "{devEnvUrl}" \
  --token "{token}" \
  --solutionId "{solutionId from .solution-manifest.json, if available}"

ヘルパーは { exists, stale, staleness: { reason, detail }, generatedAt, planStatus, ... } を含む JSON を返します。鮮度チェックには環境の認証情報と 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 を実行しますか?」

🚦 ゲート(意図 · setup-pipeline: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 はプランナーであり、デプロイは行いません。このスキルは続いて Phase 0 のチェックを再実行し(この時点では exists:true)、Phase 1 に進みます。
  • 計画なしで続行 → BYPASSED_PLAN_GATE = true を設定し、Phase 1 に進みます。
  • キャンセル → 正常に終了します。

Step 4 — 古い計画。 ユーザーに次のように伝えます。

「{generatedAt} に作成された ALM 計画がありますが、その後({solution.modifiedon} に)ソースソリューションが変更されています。コンポーネントが変更されている可能性があります。plan-alm を再実行すると、分析とレンダリング済み HTML が更新されます。」

🚦 ゲート(意図 · setup-pipeline:0.stale-plan): check-alm-plan.js が stale:true を返した場合に適用する、フェイルクローズ方式の開始ゲートです。ヘルパースクリプトに基づきます。

AskUserQuestion:

質問ヘッダー選択肢
先に計画を更新しますか?ALM 計画の鮮度更新 — /power-pages:plan-alm を再実行(推奨)、既存の計画で続行、キャンセル
  • 更新(推奨) → /power-pages:plan-alm を実行します。完了後、Phase 0 のヘルパーを再実行して鮮度を確認します。それでも古い場合は詳細を示したうえで、Phase 1 に進みます(無限ループにはしません)。
  • 続行 → STALE_PLAN_ACK = true を設定し、Phase 1 に進みます。
  • キャンセル → 正常に終了します。

このゲートがある理由。 このスキルを直接実行すると、オーケストレーターによるデプロイ前の完全性チェック、ホスト解決の判断、デプロイ戦略の選択、レンダリング済み HTML 計画が省略されます。setup-pipeline を直接実行するユーザーは、ソリューションに追加すべきコンポーネントの見落とし、大きな Web ファイルに関するアセットの注意事項の見落とし、誤ったホスト環境に対するパイプラインの構築をしがちです。このゲートにより、plan-alm が実行されて(これらすべての判断が提示・記録されている)か、ユーザーが明示的にスキップを選択したことが保証されます。

Phase 1 — プロジェクトコンテキストの検出

このフェーズの開始時に、すべてのタスクを先に作成します。

作成するタスク:

  1. 「プロジェクトコンテキストを検出」
  2. 「CI/CD プラットフォームを選択」
  3. 「パイプライン構成を確認」
  4. 「事前チェックを実行」
  5. 「デプロイ環境を作成」
  6. 「パイプラインとステージを作成」
  7. 「検証して成果物を書き込む」

手順:

  1. detect-project-context.js を使用してプロジェクトコンテキストを読み取ります。

    node "${PLUGIN_ROOT}/scripts/lib/detect-project-context.js"
    

    出力を JSON として取得し、.siteName(siteName として保存)、.websiteRecordId、.environmentUrl(devEnvUrl として保存)、.solutionManifest(solutionManifest として保存)を抽出します。宣言型サイト/データモデル(EDM)サイトでは、devEnvUrl は null になります。detect-project-context.js は powerpages.config.json からのみ環境 URL を読み取りますが、これらのサイトにはそのファイルがないためです。ここで devEnvUrl が null であることをエラーとして扱わないでください。手順 2 で pac env who から正規の開発環境 URL を解決します。siteName がない場合は処理を停止し、最初に /power-pages:create-site を実行するよう案内してください。ダウンロードまたはデプロイ済みのサイト(コードサイトまたは宣言型サイト)では、常に siteName が解決されます(powerpages.config.json または .powerpages-site/website.yml から取得)。そのため、siteName がない場合は、ここにサイトがチェックアウトされていないことを意味し、単に「powerpages.config.json がない」ということではありません。.solution-manifest.json がなく solutionManifest が null の場合は、処理を停止し、最初に /power-pages:setup-solution を実行するよう案内してください。

    マニフェストのバージョン確認:

    • solutionManifest.schemaVersion === 2(複数ソリューションレイアウト)の場合は、MULTI_SOLUTION_MODE = true を設定し、solutionManifest.solutions[] を SOLUTIONS_LIST として保存します。Phase 6b を参照してください。1 つのパイプラインですべてのソリューションを、ソリューションごとのステージ実行を通じてデプロイします(「ソリューションごとに 1 つのパイプライン」という v1.3.x より前のレイアウトは、Pipelines UI が煩雑になるため元に戻されました)。
    • schemaVersion がないか 1(単一ソリューション)の場合は、solutionManifest.solution.uniqueName と solutionManifest.solution.solutionId を読み取ります。1 つのパイプラインを作成します(既存のフロー)。
  2. verify-alm-prerequisites.js を実行して、PAC CLI の認証を確認し、トークンを取得して、API へのアクセスを検証します。devEnvUrl が null でない場合に限り、--envUrl を渡してください(コードサイト)。Step 1 の宣言型サイト/データモデルサイトのように devEnvUrl が null の場合は、--envUrl を完全に省略してください。--envUrl "null" や空の値を渡してはいけません。

    # Code sites — devEnvUrl resolved from powerpages.config.json in Step 1:
    node "${PLUGIN_ROOT}/scripts/lib/verify-alm-prerequisites.js" --envUrl "{devEnvUrl}"
    
    # Declarative / data-model (EDM) sites — devEnvUrl is null, omit the flag:
    node "${PLUGIN_ROOT}/scripts/lib/verify-alm-prerequisites.js"
    

    verify-alm-prerequisites.js では --envUrl は省略可能で、省略時には pac env who から環境を解決します(このフラグは PAC CLI の環境を 上書きする場合にのみ 使用します)。出力を JSON として取得し、.envUrl と .token(DEV_TOKEN として保存)を抽出したら、devEnvUrl = .envUrl に設定してください。この検証済みの値(pac env who から取得)は、後続のすべての手順で使用する正式な開発環境 URL です。宣言型サイトでは null を補完し、コードサイトでは値を確認します。それでも .envUrl が空の場合は停止し、再試行する前に pac auth create を実行して認証するか、環境を選択(pac org select)するようユーザーに案内してください。

  3. サイレントモードで実行します。

    node "${PLUGIN_ROOT}/scripts/lib/list-environments.js"
    

    JSON 配列を ENV_LIST として保存します(各エントリは { displayName, environmentId, environmentUrl, uniqueName, active })。このヘルパーは pac env list を解析します。現在の PAC CLI では従来の pac env list --output json は無効です(pac env list が受け付けるのは --filter のみです)。PAC が未認証の場合、このヘルパーは [] を出力して終了コード 0 で終了するため、この手順は問題なく続行できます。

  4. ensure-pipelines-host-detect.js を使用して Pipelines ホストを解決します(内部では /power-pages:ensure-pipelines-host と同じフローが実行されます。docs/alm/last-host-check.json にキャッシュされた情報があれば読み込み、解決順序に従って調査します:組織設定のバインド → BAP 環境 GET → テナントの既定カスタムホスト → テナント全体の列挙。読み取り専用で、ユーザーへのプロンプトは表示しません)。

    BAP_TOKEN=$(az account get-access-token --resource "https://service.powerapps.com/" --query accessToken -o tsv)
    node "${PLUGIN_ROOT}/scripts/lib/ensure-pipelines-host-detect.js" \
      --envUrl "{devEnvUrl}" \
      --token "{DEV_TOKEN}" \
      --userId "{userId}" \
      --bapToken "{BAP_TOKEN}" \
      --projectRoot "."
    

    標準出力を JSON として取得します:const hostResult = JSON.parse(output)。hostResult.resolutionStatus、hostResult.finalHostEnvUrl、hostResult.ready を読み取ります。

    resolutionStatus に応じて分岐します。

    • AvailableUsingPlatformHost / AvailableUsingCustomHost / AvailableUsingCustomHostByAdminDefault — ホストはすでに確立されており、ready: true です。HOST_ENV_URL = hostResult.finalHostEnvUrl として保存し、続行します。フェーズ 3 でユーザーに確認します。
    • AvailableUnboundCustomHost / MultipleUnboundCustomHosts / PlatformHostExistsUnbound / NoHost — 開発環境にバインドされたホストがありません。/power-pages:ensure-pipelines-host に処理を委任し、既存のホストを再利用するか、新しいカスタムホスト(D365_ProjectHost テンプレート)をプロビジョニングできるようにします。ユーザーには次のように伝えます:「{devEnvUrl} にバインドされた Pipelines ホストがありません。ホストを設定するために /power-pages:ensure-pipelines-host を実行します。テナント全体で既存のホストを検索し、見つからない場合は新しいカスタムホストのプロビジョニングを提案します。」 サブスキルの完了後、docs/alm/last-host-check.json を再読み込みします。新しいマーカーの ready: true が確認できた場合に限り、HOST_ENV_URL = finalHostEnvUrl を取得します。ユーザーがサブスキルをキャンセルした場合は、このスキルを停止します。ホストがなければパイプラインを作成できません。
    • CannotRedirect — 停止し、hostResult.warnings[0] にある具体的なテナント設定エラーを伝えます。ユーザーには次のように伝えます:「このテナントの DefaultCustomPipelinesHostEnvForTenant 設定と、ソース環境の ProjectHostEnvironmentId 組織設定の内容が一致しません。解決できるのは Power Platform 管理者のみです。」
    • OrgSettingStale — 停止し、警告を表示します:「{devEnvUrl} の ProjectHostEnvironmentId が、現在確認できないホスト環境(削除済み、無効、またはアクセス権がない環境)を参照しています。PPAC で組織設定をクリアするか、環境の所有者に連絡してください。」
    • PermissionDenied — 停止し、警告を表示します:「呼び出し元には、環境 {devEnvUrl} がバインドされている環境に対する BAP 読み取りアクセス権がありません。ホスト環境の所有者に連絡し、少なくとも Deployment Pipeline User アクセス権を付与してもらってください。」

    これが旧 discover-pipelines-host.js の呼び出しに取って代わる理由: このヘルパーが確認していたのは、テナントレベルの DefaultCustomPipelinesHostEnvForTenant 設定のみ(4 つある解決シグナルのうち 1 つ)でした。ensure-pipelines-host-detect.js は、Power Apps UI が使用する解決順序全体(ProjectHostProvider.tsx を反映)を確認するため、テナントにカスタムホストが存在するもののソース環境がまだバインドされていない場合など、これまで検出できなかった AvailableUnboundCustomHost のケースも含め、すべてのケースで UI と一致します。状態の完全な一覧については、references/cicd-pipeline-patterns.md を参照してください。

  5. 既存の docs/alm/last-pipeline.json を確認します。見つかった場合は、その内容を読み取ります。

  6. 調査結果を報告します:「プロジェクト:{siteName}。ソリューション:{uniqueName}。開発環境:{devEnvUrl}。ホスト環境:{HOST_ENV_URL ?? '次の手順で確保します'}({hostResult.resolutionStatus})。既存のパイプライン:あり/なし。」

🚦 ゲート(plan · setup-pipeline:1.existing-pipeline): 既存の docs/alm/last-pipeline.json が見つかりました — 上書きするか、先に確認するか、キャンセルしてください。Dataverse への書き込みはまだありません。

既存の docs/alm/last-pipeline.json が見つかった場合は、AskUserQuestion を使用して尋ねます:

「{pipelineName} のパイプライン設定(作成日時:{createdAt})がすでに存在します。どのように進めますか?

  1. 上書き — 新しいパイプラインを作成し、マーカーを置き換える
  2. 既存の設定を先に確認してから決める
  3. キャンセル」
  • 確認の場合:既存の docs/alm/last-pipeline.json の内容を表示してから、同じ 3 つの選択肢を再度尋ねます。
  • キャンセルの場合:スキルを停止し、変更は行われなかったことをユーザーに伝えます。
  • 上書きの場合:続行します。
フェーズ 1.5 — 最新の Pipelines ドキュメントを確認する

参照先:${PLUGIN_ROOT}/references/alm-docs-grounding.md

この手順は約 30 秒以内に完了させてください。MCP の検索/取得でエラーが発生した場合は、1 行のメモを記録して続行します。このスキルはオフラインでも実行できる必要があります。

  1. microsoft_docs_search を次のクエリで実行します:Power Platform Pipelines setup OData API host environment deploymentenvironments
  2. microsoft_docs_fetch を使用して、https://learn.microsoft.com/en-us/power-platform/alm/pipelines(およびホスト設定またはパイプライン作成に関する関連ページを最大 1 件)を並行して取得します。
  3. Microsoft Learn の現在の記述に基づき、Pipelines のホスト解決、deploymentenvironments/deploymentpipelines/deploymentstages のスキーマ、パイプラインのライフサイクルについて、1 段落の要約を作成します。${PLUGIN_ROOT}/references/cicd-pipeline-patterns.md と比較し、相違点(新しいフィールド、非推奨の API、変更された検証ステータスコード)にフラグを立てます。
  4. 要約をフェーズ 2 以降の判断に活用します。スキルの動作を黙って変更しないでください。相違点があれば、フェーズ 5(Pipelines ホストへの環境の登録)の前に、ソフト警告としてユーザーに伝えます。
フェーズ 2 — CI/CD プラットフォームを選択する

🚦 ゲート(plan · setup-pipeline:2.platform): CI/CD プラットフォームを選択 — PP Pipelines(完全対応)か、GitHub Actions/ADO(近日対応予定のスタブ)か。

AskUserQuestion を使用してユーザーに尋ねます:

「使用する CI/CD プラットフォームを選択してください。

  1. Power Platform Pipelines — Microsoft 標準のデプロイメントパイプラインです。外部インフラストラクチャは不要です。(推奨)
  2. GitHub Actions — 近日対応予定
  3. Azure DevOps Pipeline — 近日対応予定」

ユーザーが引数として power-platform、github、または ado を渡した場合は、この質問を省略し、指定された値を使用します。

選択内容を PLATFORM として保存します。

github または ado が選択された場合 → 近日対応予定のパスを表示して停止します。


Power Platform Pipelines のパス

フェーズ 3 — パイプライン構成の確認

質問する前に、自動検出された情報をまとめます。

設定自動検出された値
サイト名powerpages.config.json の {siteName}
ソリューションの一意の名前.solution-manifest.json の {uniqueName}
開発環境の URLpac env who の {devEnvUrl}
ホスト環境の URLensure-pipelines-host-detect.js の {HOST_ENV_URL}(フェーズ 1 のステップ 4 で解決済み)
BAP 環境 ID(開発)pac env list から取得

🚦 ゲート(plan · setup-pipeline:3.config): 自動検出されたパイプライン構成(パイプライン名、ホスト環境、ターゲット環境)を確認します。キャンセルすると、ホストへの Dataverse 書き込みを行う前に終了します。

値を事前入力して、AskUserQuestion でユーザーに尋ねます。

「次のパイプライン構成をまとめました。確認または修正してください。

  • パイプライン名:{siteName} Pipeline(変更できます)
  • ソース(開発)環境:{devEnvUrl}
  • ホスト環境(Pipelines がインストールされている場所):{HOST_ENV_URL} (フェーズ 1 で解決済み — この時点では必ず値が存在します。そうでなければ ensure-pipelines-host によってスキルが停止されています)
  • デプロイするソリューション:{uniqueName}
  • ターゲット環境:いくつですか?(開発 → ステージング/開発 → ステージング → 本番)」

ユーザーから次の情報を収集します。

  • PIPELINE_NAME(デフォルト:{siteName} Pipeline)
  • HOST_ENV_URL(確認 — フェーズ 1 ですでに解決済みです。ユーザーが管理する別のホストを指定する場合に限り、上書きできます。その場合は、まず /power-pages:ensure-pipelines-host を再実行して検証してください)
  • ターゲット環境の数と URL(該当する場合は STAGING_ENV_URL、PROD_ENV_URL)
  • 各ターゲットの BAP 環境 ID(pac env list から取得 — 見つかった場合は事前入力し、見つからない場合は確認します)

次を実行して HOST_TOKEN を保存します。

az account get-access-token --resource "{hostEnvOrigin}" --query accessToken -o tsv

最終確認の概要を提示し、続行する前にユーザーの承認を求めます。

フェーズ 4 — 事前チェック

すべての Dataverse 呼び出しには Node.js の https モジュールを使用してください(Windows では curl にエンコードの問題があります)。

4.1 ホスト環境に Pipelines がインストールされていることを確認します:

GET {hostEnvUrl}/api/data/v9.1/deploymentpipelines?$top=0
Authorization: Bearer {HOST_TOKEN}

応答が 404 の場合、または「unknown entity」エラーが返された場合は、処理を中止し、次のようにユーザーに伝えます:「選択したホスト環境には Power Platform Pipelines がインストールされていません。別の環境を選択するか、Pipelines パッケージをインストールしてください。」

4.2 verify-solution-exists.js を使用して、開発環境にソリューションが存在することを確認します:

node "${PLUGIN_ROOT}/scripts/lib/verify-solution-exists.js" \
  --envUrl "{devEnvUrl}" \
  --uniqueName "{uniqueName}" \
  --token "{DEV_TOKEN}"

出力を JSON として取得し、.found を確認します。false の場合は、デプロイする前に開発環境からソリューションをエクスポートする必要があることをユーザーに伝えます。

4.3 同じ名前の既存のパイプラインがないか確認します:

GET {hostEnvUrl}/api/data/v9.1/deploymentpipelines?$filter=name eq '{PIPELINE_NAME}'&$select=deploymentpipelineid&$top=1
Authorization: Bearer {HOST_TOKEN}

🚦 ゲート(計画 · setup-pipeline:4.3.name-conflict): ホスト環境に同じ名前のパイプラインがすでに存在します。既存のパイプライン ID を再利用するか、別の名前で新しいパイプラインを作成するかを選択してください。自動再利用すると他のユーザーが所有するパイプラインに紐づけてしまうおそれがあり、自動上書きするとそのユーザーのステージ履歴が失われます。

トリガー: フェーズ 4.3 のクエリで該当するパイプラインが見つかりました。 確認が必要な理由: 他のユーザーのパイプラインのステージが上書きされるか、ホスト環境のパイプライン一覧を乱す重複パイプラインが作成されるためです。 キャンセルした場合: 何も起こりません。Dataverse への書き込みはまだありません。

見つかった場合は、AskUserQuestion を使って、既存のパイプライン ID を使用するか、別の名前で新しいパイプラインを作成するかを尋ねます。

4.4 ソース環境とすべてのターゲット環境で blockedattachments を確認します:

Power Pages のコードサイトには、コンパイル後の出力に .js ファイルが含まれます。環境の blockedattachments 設定で .js が指定されている場合、(ソース環境での)pac pages upload-code-site と、(ターゲット環境での)deploy-pipeline は、どちらも AttachmentBlocked エラーで失敗します。ソース環境とすべてのターゲット環境で次を実行します:

node "${PLUGIN_ROOT}/scripts/lib/fix-blocked-attachments.js" \
  --envUrl "{envUrl}" \
  --extensions js \
  --dry-run

いずれかの環境で wasBlocked が空でない場合は、ユーザーに次のように伝えます:

「{envUrl} では .js ファイルがブロックされています。これにより、Power Pages コードサイトのアップロードやデプロイが失敗します。ブロックを解除しますか?環境レベルのセキュリティ設定が変更されます。」

🚦 ゲート(同意 · setup-pipeline:4.4.blocked-attachments): 環境レベルの blockedattachments セキュリティ設定を変更します(テナント全体に影響します)。このスキルだけでなく、その環境のすべてのユーザーに影響します。PPAC から元に戻せます。ブロックがある環境ごとに発生します。 フェーズ 4.4 ではソース環境とすべてのターゲット環境を確認します。N 個の環境のうち M 個で .js(またはほかのメディア拡張子)がブロックリストに含まれている場合、環境ごとに 1 回、ゲートが M 回発生します。各環境には、それぞれ独自のセキュリティ設定と、影響を受けるメーカーのグループがあります。ソース環境での「はい」はステージング環境には適用されません。ステージング環境での「はい」は本番環境には適用されません。環境をまたいで同意をまとめて取得しないでください。

AskUserQuestion を使って尋ねます:1. はい、ブロックを解除する(推奨)/2. スキップする(手動で修正します)。

承認された場合は、変更を適用するために --dry-run なしで再実行します。ユーザーが拒否した場合は警告として記録します。デプロイを成功させるには、ユーザーが手動で修正する必要があります。

事前チェックの結果を報告します。重大なチェックに失敗した場合は、明確な手順を示して処理を中止します。警告のみの場合は、続行する前にユーザーに確認します。

フェーズ 5 — Pipelines ホストに環境を登録する

各環境(ソース+ターゲット)について、ホストの Dataverse に deploymentenvironments 行を作成し、Pipelines ホストに登録します。これはメタデータのみの登録です。この行は既存の BAP 環境への参照であり、プロビジョニングの呼び出しではありません。環境自体は、あらかじめ BAP に存在している必要があります。ホストは、参照先の環境に到達でき、呼び出し元に適切なアクセス権があることを検証します(validationstatus は Pending → Succeeded に変わります)。ソース環境を先に処理し、その後にターゲット環境を処理します。

各環境(開発用ソース+各ターゲット)に対して create-deployment-environment.js を使用します。

node "${PLUGIN_ROOT}/scripts/lib/create-deployment-environment.js" \
  --hostEnvUrl "{HOST_ENV_URL}" \
  --token "{HOST_TOKEN}" \
  --name "{siteName} {label}" \
  --bapEnvId "{BAP_ENV_GUID}" \
  --environmentType 200000000 \
  [--environmentUrl "{environmentUrl}"]

必須の引数(scripts/lib/create-deployment-environment.js ごと):

  • --bapEnvId — 追加する環境の BAP 環境 GUID です。pac env list(列 Environment ID)または、現在のソース環境では pac env who を使用して解決します。組織/Dataverse の URL ではありません。
  • --environmentType — 開発用/ソース環境には 200000000、各ターゲット環境には 200000001 を指定します。
  • --environmentUrl は任意です。出力マーカーにそのまま含めるためだけに使用され、Dataverse には送信されません。

標準出力を JSON として取得します:const envResult = JSON.parse(output)。 envResult.deploymentEnvironmentId を、開発用ソース環境では SOURCE_DEPLOYMENT_ENV_ID として保存し、各ターゲットでは TARGET_DEPLOYMENT_ENV_IDs に追加します。また、各呼び出しで使用した bapEnvId の値も保持してください。作成結果が Failed になった場合、フェーズ 5a の強制リンクによる自動修正でこの値が必要になります。

注:このスクリプトは、プレフィックスのないフィールド(name、environmentid、environmenttype)を使用して deploymentenvironments に POST し、OData-EntityId ヘッダーから deploymentenvironmentid GUID を抽出した後、ステータスが 200000001(Succeeded)または 200000002(Failed)になるまで、3 秒ごとに(最大 20 回)validationstatus をポーリングします。失敗した場合、スクリプトはエラーの詳細を標準エラー出力に書き込み、終了コード 1 で終了します。その場合は処理を停止し、エラーをユーザーに報告してください。(以前の msdyn_ プレフィックス付きフィールド形式と 192350001/192350002 のステータスコードは初期プレビュー版 HAR のものであり、リリース済みの Pipelines スキーマでは msdyn_ プレフィックス付きプロパティは拒否され、2000000XX コードが使用されます。)

失敗した場合は、エラーを示して停止してください。デプロイ環境の作成は必須です。

5a — 「別の Pipelines ホストにすでに関連付けられている」を検出する(パターン 15)

スクリプトの標準エラー出力に以下のいずれかの文字列が含まれている場合(大文字と小文字を区別しません)、BAP 環境には現在、別の Pipelines ホストが記録されています。

  • already associated with another pipelines host
  • associated with another pipelines host
  • environment is already linked to a different host
  • environment is already bound to
  • linked to another host
  • claimed by another host

Pipelines パッケージのバージョン間でバックエンドの文言が変わっても検出がひそかに機能しなくなることのないよう、これらはすべて大文字と小文字を区別せずに照合してください(.includes() の前に String.prototype.toLowerCase() を使用します)。いずれにも一致しない場合でも、スクリプトが Dataverse のエラーコード 0x80048d18(またはこの 16 進コードを含むラップされた errormessage)で終了した場合は、同じパターンとして扱ってください。メッセージの文言が変わっても、これが安定したシグナルです。

🚦 ゲート(同意 · setup-pipeline:5a.pattern-15): 対象環境には別の Pipelines ホストが記録されています。文書化された自動修正として強制リンクを提示してください。これは破壊的な操作です。以前のホストはこの環境へのパイプラインアクセスを失います。ここでキャンセルすると、setup-pipeline は正常に終了します。パターン 15 が発生した環境ごとに実行されます。 フェーズ 5 では、ホストへの登録時にソース環境と各対象環境をループ処理します。2 つの対象環境がどちらも別のホストを記録している場合、このゲートは環境ごとに 1 回、合計 2 回実行されます。環境をまたいで同意をまとめないでください。破壊的な影響範囲は環境ごとに異なります(各環境にはそれぞれ以前のホストの記録があり、そのホストに属する独自のメーカーグループがアクセスを失います)。

これは ${PLUGIN_ROOT}/references/deployment-error-catalog.md のパターン 15です。ひそかに再試行しないでください。生の errormessage をそのままユーザーに提示し、文書化された自動修正を AskUserQuestion で提示してください。

question: "<envLabel> is already linked to a different Pipelines host. The /power-pages:force-link-environment skill can take over the association (DESTRUCTIVE to the previous host — makers there lose pipeline access for this env). Run it now?"
header: "Force Link?"
options:
  - "Run /power-pages:force-link-environment now (Recommended)" — auto-fix per the deployment error catalog
  - "Cancel setup-pipeline" — investigate the previous host first

重要なガードレール:

  • このプロンプトを通じてユーザーから明示的な同意を得ずに、/power-pages:force-link-environment を絶対に呼び出さないでください。この操作を元に戻すには、以前のホストから再度 Force Link を実行する必要があります。
  • ユーザーが「実行…」を選択した場合は、--host <HOST_ENV_URL> と --dev-env <bapEnvId>(フェーズ 5 でこの環境について取得した BAP 環境 GUID。前述の「bapEnvId の値も保持する」注記を参照)を指定して /power-pages:force-link-environment を呼び出し、サブスキル内でホストや環境について再度質問されないようにしてください。
  • サブスキルが成功を返したら、失敗した環境だけを対象に、同じ引数で create-deployment-environment.js を再実行してください。フェーズ 5 全体を再起動しないでください。作成スクリプトは冪等です。すでに作成済みの環境は findExistingByBapId によって処理を早期終了し(reused: true を返します)、先ほど失敗した環境もホストの記録が移動したことで Succeeded になります。
  • ユーザーが「キャンセル」を選択した場合は、パイプラインのセットアップを停止し、再試行する前に /power-pages:ensure-pipelines-host detect-only で現在のホストの関連付けを確認するよう勧めてください。

create-deployment-environment のその他の失敗については、上記の一般的な「エラーで停止する」処理に進んでください。

検証が完了したら、環境ごとに進捗を報告してください。

フェーズ 6 — パイプラインの作成、ソースの関連付け、ステージの作成

create-deployment-pipeline.js を使用して、1 回の呼び出しでパイプラインを作成し、ソース環境を関連付け、すべてのステージレコードを作成します。

node "${PLUGIN_ROOT}/scripts/lib/create-deployment-pipeline.js" \
  --hostEnvUrl "{HOST_ENV_URL}" \
  --token "{HOST_TOKEN}" \
  --pipelineName "{PIPELINE_NAME}" \
  --description "Power Pages deployment pipeline for {siteName}" \
  --sourceDeploymentEnvironmentId "{SOURCE_DEPLOYMENT_ENV_ID}" \
  --stagesJson '[{"name":"Deploy to {targetLabel}","targetDeploymentEnvironmentId":"{TARGET_DEPLOYMENT_ENV_ID}","order":1}]'

標準出力を JSON として取得します:const pipelineResult = JSON.parse(output)。 次の値を抽出します:

  • pipelineResult.pipelineId → PIPELINE_ID として保存します
  • pipelineResult.stages → { stageId, name, targetDeploymentEnvironmentId } の配列

スクリプト内部で行う処理(プレフィックスなしのフィールドスキーマを使用します。先ほどの msdyn_ プレフィックス付きのボディは、提供された Pipelines スキーマで拒否されました。移行マップの全内容については、create-deployment-pipeline.js の先頭にあるコメントブロックを参照してください):

  1. { name, description } を deploymentpipelines(v9.1)に POST します — OData-EntityId ヘッダーから deploymentpipelineid を抽出します
  2. ソース環境を関連付けるため、相対パスの @odata.id ボディを deploymentpipelines({pipelineId})/deploymentpipeline_deploymentenvironment/$ref に POST します(HAR で確認済み。先頭に / を付けたり、完全な URL を指定したりしません)
  3. 各ステージについて、{ name, [email protected], [email protected] } を deploymentstages に POST します — OData-EntityId ヘッダーから deploymentstagesid を抽出します

失敗した場合:スクリプトはエラーを標準エラー出力に書き込み、終了コード 1 で終了します。処理を停止し、エラーをユーザーに報告してください。

フェーズ 6b — 複数ソリューションの deploymentOrder(MULTI_SOLUTION_MODE = true の場合のみ)

設計上の注意(v1.3.x 更新): 1 つの Power Platform Pipeline で、別々のステージ実行を通じて複数のソリューションをデプロイできます。各実行では、同じ deploymentstages レコードに異なる artifactname と solutionid を指定します。ソリューションごとにパイプラインを作成する方法は無駄が多く、Pipelines の UI も煩雑になっていました。現在は、ターゲット環境ごとにパイプラインを 1 つ、ステージを 1 つ作成し、ソリューションごとのデプロイ順序を docs/alm/last-pipeline.json に記録します。 その後、deploy-pipeline は順序に従ってループし、同じステージに対してソリューションごとにステージ実行を作成します。

マニフェストが schemaVersion: 2 の場合、create-deployment-pipeline.js を複数回呼び出してはいけません。代わりに、次の手順を実行します。

  1. 次の内容で create-deployment-pipeline.js を1 回だけ呼び出します。
    • pipelineName = "{siteName}-Pipeline"(例:IdeaSphere-Pipeline)。
    • デプロイするソリューションを列挙した description(例:"Deploys IdeaSphere_Core → IdeaSphere_WebAssets → IdeaSphere_Future in order")。
    • ターゲット環境ごとに 1 つの deploymentstages レコード(ソリューションごとではありません)。
  2. order でソートした SOLUTIONS_LIST から deploymentOrder 配列を作成します。各エントリは { solutionUniqueName, solutionId, order } です。isFutureBuffer: true かつ components.length === 0 のエントリはスキップします。空の Future ソリューションにはデプロイ対象がありません。これは setup-solution で作成されますが、コンテンツが追加されるまでデプロイループには参加しません。レンダラーに意図を表示できるよう、status: "SkippedEmpty" を付けて順序配列には残してください。
  3. 単一の pipelineId とその stages[] を収集します。deploymentOrder を docs/alm/last-pipeline.json に保存します(フェーズ 7 を参照)。
フェーズ 7 — 検証、アーティファクトの書き込み、コミット

7.1 パイプラインが作成されたことを確認します:

GET {hostEnvUrl}/api/data/v9.1/deploymentpipelines({PIPELINE_ID})?$select=name,statecode
Authorization: Bearer {HOST_TOKEN}

statecode = 0(アクティブ)であることを確認します。クエリが失敗した場合は、「検証不能 — パイプラインは有効なままの可能性があります」と報告してください。

7.2 docs/alm/last-pipeline.json を書き込みます(存在しない場合は、先に docs/alm/ ディレクトリを作成します — node -e "require('fs').mkdirSync('docs/alm',{recursive:true})")。

{
  "pipelineId": "{PIPELINE_ID}",
  "pipelineName": "{PIPELINE_NAME}",
  "hostEnvUrl": "{HOST_ENV_URL}",
  "sourceDeploymentEnvironmentId": "{SOURCE_DEPLOYMENT_ENV_ID}",
  "sourceEnvironmentUrl": "{devEnvUrl}",
  "solutionName": "{uniqueName}",
  "createdAt": "{ISO timestamp}",
  "stages": [
    {
      "stageId": "{deploymentstagesid}",
      "name": "Deploy to {targetLabel}",
      "rank": 1,
      "targetDeploymentEnvironmentId": "{TARGET_DEPLOYMENT_ENV_ID}",
      "targetEnvironmentUrl": "{targetEnvUrl}"
    }
  ]
}

複数ソリューションのマーカー(マニフェスト v2): MULTI_SOLUTION_MODE = true の場合、docs/alm/last-pipeline.json は schemaVersion: 3 を使用し、単一のパイプラインと、どのソリューションをどの順序でデプロイするかを示す deploymentOrder[] を含みます。

{
  "schemaVersion": 3,
  "pipelineId": "...",
  "pipelineName": "IdeaSphere-Pipeline",
  "hostEnvUrl": "{HOST_ENV_URL}",
  "sourceDeploymentEnvironmentId": "{SOURCE_DEPLOYMENT_ENV_ID}",
  "sourceEnvironmentUrl": "{devEnvUrl}",
  "createdAt": "{ISO timestamp}",
  "stages": [
    {
      "stageId": "...",
      "name": "Deploy to Staging",
      "rank": 1,
      "targetDeploymentEnvironmentId": "...",
      "targetEnvironmentUrl": "https://staging.crm.dynamics.com"
    }
  ],
  "deploymentOrder": [
    { "solutionUniqueName": "IdeaSphere_Core", "solutionId": "...", "order": 1 },
    { "solutionUniqueName": "IdeaSphere_WebAssets", "solutionId": "...", "order": 2 },
    { "solutionUniqueName": "IdeaSphere_Future", "solutionId": "...", "order": 3, "status": "SkippedEmpty", "isFutureBuffer": true }
  ]
}

🚦 ゲート(plan · setup-pipeline:6b.v2-migration): 再実行時に v2 の pipelines[] マニフェストが検出されました。次のいずれかを選択してください:v3 に移行する(N-1 個の追加パイプラインを削除し、1 つにまとめる)か、レガシーの構成を維持する。

トリガー: docs/alm/last-pipeline.json が schemaVersion: 2 のプロジェクトで、setup-pipeline を再実行する場合。 確認する理由: 自動移行では Dataverse のパイプラインレコードが削除されます。これはホスト環境の状態に対する破壊的な変更であり、setup-pipeline を再実行しない限り元に戻せません。 キャンセルした場合: 変更はありません。パイプラインレコードはまだ削除されていません。

移行に関する注意: このスキルの以前のバージョンでは、schemaVersion: 2 と pipelines[] 配列(ソリューションごとに Dataverse のパイプラインレコードを 1 つ)を使用していました。v2 に固定されているプロジェクトは、従来の deploy-pipeline の MULTI_PIPELINE_MODE パスで引き続き動作します。新しいセットアップではすべて v3 形式を使用してください。v2 のプロジェクトで setup-pipeline を再実行するときは、移行する(N-1 個の追加パイプラインを削除し、1 つにまとめる)か、レガシーの構成を維持するかを AskUserQuestion で確認してください。

7.3 docs/pipeline-setup.md を作成(または再レンダリング)する(必要に応じて docs/ ディレクトリを作成)。

内容:

  1. 作成したパイプライン — 名前、ホスト環境の URL、パイプライン ID
  2. 構成した環境 — ソース環境と、各ターゲット環境のデプロイ環境 ID
  3. デプロイ順のソリューション(マルチソリューションモードのみ) — solutionManifest.solutions[] の各エントリについて、{uniqueName, version, componentCount} を列挙します。マニフェストで追跡している場合は各エントリの components.length から componentCount を読み取ります。そうでない場合は、Dataverse にライブクエリ(solutioncomponents?$filter=_solutionid_value eq '{solutionId}' and componenttype ne 380&$count=true)を実行して取得します。以前の呼び出しで取得した古い値をハードコードしたり、引き継いだりしないでください。
  4. デプロイのトリガー方法 — /power-pages:deploy-pipeline を実行するか、Power Platform make.powerapps.com → Solutions → Pipelines を開きます
  5. 承認ゲート(該当する場合) — Power Platform Admin Center での構成方法
  6. トラブルシューティング — よくある検証エラーとその解決方法

同期モードでの再レンダリング: docs/alm/last-pipeline.json がすでに存在するプロジェクトで setup-pipeline が呼び出された場合(configure-env-variables、setup-solution の同期後、またはコンポーネント数を増加させる環境変数の追加後の再実行)、現在の Dataverse の状態からこのファイル全体を再生成してください。その場で一部だけを修正しないでください。確認された不具合では、Citizens ポータルの pipeline-setup.md に Foundation のコンポーネント数が 13 と記載されていましたが、configure-env-variables によってそのソリューションに環境変数定義が 2 つ追加された後、Dataverse では 15 になっていました。Markdown は更新されませんでした。最も簡単で安全な動作は「Phase 7.3 では常に再レンダリングする」ことです。この処理では現在の状態を直接読み取り、ファイルには保持する価値のあるユーザー編集セクションがないためです。

7.4 コミット:

git add docs/alm/last-pipeline.json docs/pipeline-setup.md
git commit -m "Add Power Platform Pipeline configuration for {siteName}"

7.5 スキルの使用状況を記録する:

参照:${PLUGIN_ROOT}/references/skill-tracking-reference.md

参照先のスキル追跡手順に従って、このスキルの使用状況を記録してください。--skillName "SetupPipeline" を使用してください。

7.5b ALM プランを更新する(存在する場合):

node "${PLUGIN_ROOT}/scripts/lib/refresh-alm-plan-data.js" \
  --projectRoot "." \
  --phase setup-pipeline \
  --render

このヘルパーは docs/alm/last-host-check.json と docs/alm/last-pipeline.json を読み取り、planData.hostResolution と planData.pipelineMeta を更新し、セットアップ前の「ホストが検出されない」リスクを削除して、docs/alm-plan.html を再レンダリングします。docs/.alm-plan-data.json が存在しない場合(ALM プランの一部ではない単独の呼び出し)は、ヘルパーは ok:false を返して何もせずに終了します。無条件に実行しても安全です。 ユーザーを次のステップへ案内します(ユーザー主導で進行)。 ヘルパーの標準出力 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 を返した場合(プランなし)は、次のステップについて何も伝えません。次のスキルを自動で呼び出してはいけません。実行するかどうかはユーザーが決めます。

7.6 概要を提示します:

リソースID / URL
パイプライン{PIPELINE_NAME}({PIPELINE_ID})
ホスト環境{HOST_ENV_URL}
ソースデプロイ環境{SOURCE_DEPLOYMENT_ENV_ID}
ステージ:{name}{stageId} → {targetEnvUrl}

書き込まれたファイル:

  • docs/alm/last-pipeline.json — パイプライン設定マーカー
  • docs/pipeline-setup.md — セットアップドキュメント

次のステップ:

/power-pages:deploy-pipeline を実行して、最初のデプロイを開始します。


近日対応予定のパス

GitHub Actions または Azure DevOps が選択された場合:

ユーザーに次のように伝えます。

「このスキルでは、GitHub Actions と Azure DevOps Pipeline のサポートは近日対応予定です。

現時点では、次の 2 つの方法があります:

  1. Power Platform Pipelines を使用する — オプション 1 を選択して、Microsoft のネイティブなデプロイパイプラインを設定します(推奨)
  2. 終了する — ドキュメントを使って GitHub Actions/Azure DevOps を手動で設定します」

🚦 ゲート(plan · setup-pipeline:coming-soon.exit): ユーザーが GitHub/ADO(近日対応予定のスタブ)を選択した場合、PP Pipelines に切り替えるか、正常に終了するかを選択できるようにします。

AskUserQuestion を使って質問します:

  1. Power Platform Pipelines に切り替える — フェーズ 2 に戻る
  2. 終了する — 手動で設定する

GitHub/ADO が引数として渡された場合:上記のメッセージを表示し、問題なく終了します。


重要な判断ポイント(ユーザーの応答を待つ)

  1. フェーズ 1:既存のパイプラインファイル — 上書き、確認、またはキャンセル(docs/alm/last-pipeline.json が見つかった場合のみ)
  2. フェーズ 2:プラットフォームの選択(Power Platform Pipelines/GitHub は近日対応予定/ADO は近日対応予定)
  3. フェーズ 3:パイプライン設定の確認 — パイプライン名、ホスト環境 URL、ターゲット環境
  4. フェーズ 4:事前確認の警告 — 続行またはキャンセル
  5. フェーズ 3:パイプライン作成前のパラメーター確認

エラー処理

  • powerpages.config.json がない:停止し、/power-pages:create-site を案内します
  • .solution-manifest.json がない:停止し、/power-pages:setup-solution を案内します
  • RetrieveSetting が空を返す:ホスト環境 URL を手動で入力するようユーザーに求めます
  • デプロイ環境の statecode = 1 かつ errormessage が null 以外(検証失敗):エラーの詳細を示して停止します
  • パイプラインの $ref 呼び出しが失敗:ステージの作成前にこの関連付けが必要なため、停止します
  • ステージの作成が失敗:失敗を記録し、残りのステージの処理を続けます — 部分的な成功は有効です

進捗管理テーブル

タスクの内容実行中の状態説明
プロジェクトのコンテキストを検出するプロジェクトのコンテキストを検出していますpowerpages.config.json と .solution-manifest.json を読み取り、pac env who と pac env list を実行し、RetrieveSetting を呼び出してホスト環境を特定し、既存の docs/alm/last-pipeline.json があるか確認します
CI/CD プラットフォームを選択するCI/CD プラットフォームを選択していますユーザーに Power Platform Pipelines(完全版)または GitHub/ADO(近日公開)を確認します
パイプラインの設定を確認するパイプラインの設定を確認しています自動検出した値からパイプライン名、ソース環境、ホスト環境、ソリューション名を事前入力し、ターゲット環境を尋ねて、ユーザーの確認を得ます
事前チェックを実行する事前チェックを実行していますホスト環境に Pipelines がインストールされていること、開発環境にソリューションが存在することを確認し、パイプライン名の競合をチェックします
デプロイ環境を作成するデプロイ環境を作成していますソース環境と各ターゲット環境について deploymentenvironments を POST し、それぞれの validationstatus が Succeeded になるまでポーリングします
パイプラインとステージを作成するパイプラインとステージを作成していますdeploymentpipelines を POST し、$ref でソース環境を関連付け、各ターゲットについて(previousdeploymentstageid でリンクされた)deploymentstages を POST します
アーティファクトを検証して書き込むアーティファクトを検証して書き込んでいますパイプラインをクエリしてアクティブであることを確認し、docs/alm/last-pipeline.json と docs/pipeline-setup.md を書き込み、コミットして、次の手順を含む概要を提示します

コメント