前回はこちら。

Power Platform ALM パイプラインを使用したソリューションのデプロイを解説|基本的なパイプライン構築
Power Platformの新しい管理ツール『パイプライン』を使う機会があったので、使い方をメモ。今回やること今回は開発環境で構築したソリューションを運用環境(別の環境)へ、『パイプライン』を使用してデプロイしてみる。まずは以下の環境を用...
GitHubへのコミット
前回作成したPower Platformのデプロイ用のパイプラインを拡張し、GitHubにソリューションをコミットしてみる。 基本的には以下の公式の手順と一緒だけど、一部変更が必要。公式

GitHub Actions を使用してパイプラインを拡張する - Power Platform
Power Automate フローから呼び出される GitHub ワークフローを使用して、ソリューションをダウンロード、展開、コミットします。
構築
手順は以下の通り
- EntraIDへのアプリ登録
- Power Platform環境にアプリケーションユーザーの登録
- GitHub:リポジトリ作成→Actionsの作成
- GitHub:アクセストークン作成
- Power Automate構築:GitHubのAPIコール
EntraIDへの登録
まずはEntra IDの登録から。この手順では以下3つの値をメモする。
- クライアントシークレット
- クライアントID(アプリID)
- テナントID
まずはAzure PortalでEntra IDを開き、


[アプリの登録]から[新規登録]を選ぶ。


適当な名前を付けて、シングルテナントで登録。


続いて登録したアプリの[APIのアクセス許可]から、[Dynamics CRM]を選んで、


「user_impersonation」をチェックし、[アクセス許可の追加]。


[証明書とシークレット]から[新しいクライアントシークレット]を選び、


生成された値をメモ。


最後に[概要]から[アプリID]と[テナントID]をメモすれば、この手順は終了。


Power Platform環境にアプリケーションユーザーの登録
続いて、Power Platformの環境にアプリケーションユーザーを作成し、GitHubへDataverseへのセキュリティロールを与える。Power Platform管理センターから、パイプラインを構築した環境を選び、[設定]を押す。


[アプリケーションユーザー]を選び、


[新規アプリユーザー]から、[アプリの追加]、


前の手順でEntra IDに追加したアプリを選択する。


部署(今回はサンプルなのでルート部署)と、セキュリティロールを設定し、[作成]。
※セキュリティロールはSystem Customizerで確実に動作するけど、権限を最低限にしたい場合はカスタムロールの作成を推奨。
以上でPower Platformへのアプリケーションユーザーの登録は完了。
※セキュリティロールはSystem Customizerで確実に動作するけど、権限を最低限にしたい場合はカスタムロールの作成を推奨。

GitHub:リポジトリ作成→Actionsの作成
リポジトリ作成
GitHubへ移動し、リポジトリを作成。


Actions設定
リポジトリを作成したら、Actionsから[set up a workflow yourself]を選択。


そしたら、公式のコードの一部を修正した以下のコードを貼り付け、[Commit changes]を押す。

コードの修正は以下の通り。

# 変更前 # Unpack the solution - name: unpack solution uses: microsoft/powerplatform-actions/unpack-solution@v0 with: solution-file: "${{ github.event.inputs.solution_name }}.zip" solution-folder: "${{ github.event.repository.name }}" solution-type: 'Both' process-canvas-apps: false overwrite-files: true # 変更後(unpack-solutionがv0だと動かなかったので、v1を使用) # Install PAC - name: Install Power Platform Tools uses: microsoft/powerplatform-actions/actions-install@v1 # Unpack the solution - name: unpack solution uses: microsoft/powerplatform-actions/unpack-solution@v1 with: solution-file: "${{ github.event.inputs.solution_name }}.zip" solution-folder: "${{ github.event.repository.name }}" solution-type: 'Both' process-canvas-apps: false overwrite-files: true以下全文。
name: Download, unpack and commit the solution to git run-name: Getting ${{ github.event.inputs.solution_name }} from pipelines host environment and committing on: workflow_dispatch: inputs: artifact_url: description: "The url of the Dataverse record ID for the artifact created by the pipelines (Example: https://[your-env].crm.dynamics.com/api/data/v9.0/deploymentartifacts([your-artifact-id])/artifactfile/$value)." required: true solution_name: description: "Name of the Solution in Dataverse environment" required: true user_name: description: "User name for the commit" required: true source_branch: description: "Branch for the solution commit" required: true target_branch: description: "Branch to create for the solution commit" required: false commit_message: description: "Message to provide for the commit" required: true permissions: contents: write jobs: export-unpack-commit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.inputs.source_branch }} # Commit changes to the existing or new branch - name: create new branch if specified shell: pwsh run: | if('${{ github.event.inputs.target_branch }}' -ne '') { git checkout -b ${{ github.event.inputs.target_branch }} ${{ github.event.inputs.source_branch }} } # Export the solution from the artifact created by pipelines - name: download solution from artifact env: CLIENT_ID: ${{secrets.CLIENT_ID}} TENANT_ID: ${{secrets.TENANT_ID}} CLIENT_SECRET: ${{secrets.CLIENT_SECRET}} shell: pwsh run: | $aadHost = "login.microsoftonline.com" $url = "${{ github.event.inputs.artifact_url }}" $options = [System.StringSplitOptions]::RemoveEmptyEntries $dataverseHost = $url.Split("://", $options)[1].Split("/")[0] $body = @{client_id = $env:CLIENT_ID; client_secret = $env:CLIENT_SECRET; grant_type = "client_credentials"; scope = "https://$dataverseHost/.default"; } $OAuthReq = Invoke-RestMethod -Method Post -Uri "https://$aadHost/$env:TENANT_ID/oauth2/v2.0/token" -Body $body $spnToken = $OAuthReq.access_token $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add("Authorization", "Bearer $spnToken") $headers.Add("Content-Type", "application/json") # Download the managed solution $response = Invoke-RestMethod "${{ github.event.inputs.artifact_url }}" -Method 'GET' -Headers $headers $bytes = [Convert]::FromBase64String($response.value) [IO.File]::WriteAllBytes("${{ github.event.inputs.solution_name }}_managed.zip", $bytes) # Download the unmanaged solution (for now we will need to use string manipulation to get the unmanaged solution URL, until the API provides this value) $unmanaged_artifact_url = "${{ github.event.inputs.artifact_url }}".Replace("artifactfile", "artifactfileunmanaged") $response = Invoke-RestMethod "$unmanaged_artifact_url" -Method 'GET' -Headers $headers $bytes = [Convert]::FromBase64String($response.value) [IO.File]::WriteAllBytes("${{ github.event.inputs.solution_name }}.zip", $bytes) # Install PAC - name: Install Power Platform Tools uses: microsoft/powerplatform-actions/actions-install@v1 # Unpack the solution - name: unpack solution uses: microsoft/powerplatform-actions/unpack-solution@v1 with: solution-file: "${{ github.event.inputs.solution_name }}.zip" solution-folder: "${{ github.event.repository.name }}" solution-type: 'Both' process-canvas-apps: false overwrite-files: true # Commit changes to the existing or new branch - name: commit changes shell: pwsh run: | rm -rf ${{ github.event.inputs.solution_name }}.zip rm -rf ${{ github.event.inputs.solution_name }}_managed.zip git config user.name ${{ github.event.inputs.user_name }} git pull git add --all git commit -am "${{ github.event.inputs.commit_message }}" --allow-empty # Push the committed changes to the source branch - name: push to branch shell: pwsh run: | if('${{ github.event.inputs.target_branch }}' -ne '') { git push origin ${{ github.event.inputs.target_branch }} } else { git push origin ${{ github.event.inputs.source_branch }} }
リポジトリにシークレットを登録
該当リポジトリの[Settings]を開いて、[Secrets and variables]の[Actions]を選択し、[New repository secret]を選択。


ここで、Entra ID設定時にメモした3つの値を設定する

以上で、リポジトリとActionsの設定は完了。
- CLIENT_ID : クライアントID
- CLIENT_SECRET:シークレット
- TENANT_ID:テナントID



GitHub:アクセストークンの作成
GitHubのテナント(ユーザー)の設定を開き、[Developer Settings]から[Personal access tokens]の[Fine-grained tokens]を選択。[Generate new token]を押す。


適当な名前と、トークンの有効期限を設定、


Repository accessを先ほど作成したリポジトリに限定し、


Permissionsで[Actions]と[Contents]を「Read and Write」にする。


[Generate]を押下し、出力されるGitHubのアクセストークンをメモする。

以上でアクセストークンの作成は完了。

Power Automate構築:GitHubのAPIコール
最後にGitHubで作成したActionsを呼び出すPower Automateの構築。全体図はこんな感じ。


まずトリガーは、以下のように設定。
※公式リファレンスに記載のある「OnDeploymentRequested」だと問題が発生する場合があるけど、ひとまずこれで。

※公式リファレンスに記載のある「OnDeploymentRequested」だと問題が発生する場合があるけど、ひとまずこれで。

続いて「IDで行を取得する」アクションで、テーブル「展開ステージの実行」から行を取得。


最後にHTTPアクションで、以下のURLにPOSTする。
URL:~~~/repos/【テナント(ユーザー)名】/【リポジトリ名】/actions/workflows/【ワークフローファイル名】/dispatches
ヘッダ:Authorization : Bearer 【Githubアクセストークン】
Bodyは以下の通り。 ※source_branchとtarget_branchは必要に応じて設定を変えてください。
ちょっと長かったけど、以上で設定は完了。
URL:~~~/repos/【テナント(ユーザー)名】/【リポジトリ名】/actions/workflows/【ワークフローファイル名】/dispatches
ヘッダ:Authorization : Bearer 【Githubアクセストークン】

Bodyは以下の通り。 ※source_branchとtarget_branchは必要に応じて設定を変えてください。
{ "ref": "main", "inputs": { "artifact_url": "@{triggerOutputs()?['body/OutputParameters/ArtifactFileDownloadLink']}", "solution_name": "@{triggerOutputs()?['body/OutputParameters/ArtifactName']}", "user_name": "@{triggerOutputs()?['body/OutputParameters/DeployAsUser']}", "source_branch": "main", "commit_message": "@{outputs('ID_で行を取得する')?['body/deploymentnotes']}" } }




動作確認
前回の記事で作成したソリューション内のキャンバスアプリのラベルの内容をv1.0.0.4に変更し、保存→公開する。


公開後、設定したパイプラインを起動すると、



Power Automateが動き、GitHubのActionsをコール。


少し待つとGitHubのアクションが成功し、


ソリューションの中身がGitHubに入る。


今回はキャンバスアプリの中身を変えたので、.msappの内容が無事更新されている。


Actionsが失敗することもある
全く同じ手順でパイプラインを動かし、


Power Automateまで無事動くけど、


GitHubのActionsが失敗することがある。

エラーメッセージ「No file attachment found for attribute」とある通り、これはGitHubのアクションでマネージドソリューションのzipを持ってこようとしたときに、まだパイプラインのソリューションのzip化が完了していないため、起きていると思われる。
ちょっと長くなってしまったので、もしこれが起きた場合の対処方法については次回。
コメント