ขยายไปป์ไลน์โดยใช้ GitHub Actions

บทความนี้แสดงการใช้ GitHub Actions และโฟลว์ระบบคลาวด์ Power Automate สำหรับการขยายไปป์ไลน์ใน Power Platform เมื่อมีการส่งการปรับใช้งานไปป์ไลน์ โฟลว์คระบบลาวด์จะทริกเกอร์เวิร์กโฟลว์ GitHub เพื่อดาวน์โหลด แยกออก และยอมรับโค้ดต้นฉบับของอาร์ทิแฟกต์ไปยังสาขา GitHub

รายละเอียดเวิร์กโฟลว์

เวิร์กโฟลว์ถูกทริกเกอร์ผ่านเหตุการณ์ workflow_dispatch เวิร์กโฟลว์ทำงานบน ubuntu-latest และมีสิทธิ์ contents: write เพื่อให้สามารถยอมรับการเปลี่ยนแปลงกับสาขาที่เก็บ GitHub

เวิร์กโฟลว์ประกอบด้วยขั้นตอนต่อไปนี้:

  1. actions/checkout@v3: ตรวจสอบที่เก็บ
  2. create new branch if specified: สร้างสาขาใหม่หากมีการระบุ target_branch ในอินพุต
  3. download solution from artifact: ดาวน์โหลดโซลูชันจากอาร์ทิแฟกต์ที่สร้างขึ้นโดยไปป์ไลน์
  4. unpack solution: แยกโซลูชัน
  5. commit changes: ยอมรับการเปลี่ยนแปลงของสาขาที่มีอยู่หรือสาขาใหม่
  6. push to branch: ส่งการเปลี่ยนแปลงที่ยอมรับไปยังสาขาต้นทาง

อินพุตของเวิร์กโฟลว์

อินพุตของเวิร์กโฟลว์ต่อไปนี้จำเป็นหรือไม่บังคับ:

  • artifact_url (จำเป็น): URL ของรหัสแถว (เรกคอร์ด) Microsoft Dataverse สำหรับอาร์ทิแฟกต์ที่สร้างขึ้นโดยไปป์ไลน์
  • solution_name (จำเป็น): ชื่อของโซลูชันในสภาพแวดล้อม Dataverse
  • source_branch (จำเป็น): สาขาสำหรับการยอมรับโซลูชัน
  • target_branch (ไม่บังคับ): สาขาที่จะสร้างสำหรับการยอมรับโซลูชัน หากไม่ได้ระบุ จะมีการใช้ source_branch
  • commit_message (จำเป็น): ข้อความที่จะระบุสำหรับการยอมรับ

ข้อมูลลับของเวิร์กโฟลว์

ข้อมูลลับต่อไปนี้จำเป็นสำหรับการเชื่อมต่อกับ Dataverse โดยใช้ผู้ใช้แอปพลิเคชันที่กำหนดค่าใน Dataverse และใน Microsoft Entra ID (AD) กำหนดค่าข้อมูลลับเหล่านี้ในการตั้งค่าที่เก็บ GitHub

  • CLIENT_ID: รหัสไคลเอ็นต์ของแอปพลิเคชัน Microsoft Entra ที่ลงทะเบียนไว้
  • TENANT_ID: รหัสผู้เช่าของไดเรกทอรี Microsoft Entra ที่เชื่อมโยงกับแอปพลิเคชัน Microsoft Entra
  • CLIENT_SECRET: ข้อมูลลับของไคลเอ็นต์ของแอปพลิเคชัน Microsoft Entra ที่ลงทะเบียนไว้

สำหรับข้อมูลเพิ่มเติม ให้ไปที่ การสร้างและการใช้ข้อมูลลับที่เข้ารหัสลับ และ สร้างผู้ใช้แอปพลิเคชัน

โค้ดของเวิร์กโฟลว์

รายการด้านล่างคือโค้ดของเวิร์กโฟลว์ GitHub Actions

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)

      # 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

      # 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 }}
          }

หมายเหตุ

API เว็บสำหรับ Dataverse ที่ใช้ในการดาวน์โหลดอาร์ทิแฟกต์ของโซลูชันมีการจำกัดขนาดไฟล์สูงสุด 16 MB

ตัวอย่างโฟลว์ Power Automate

หากต้องการเรียกเวิร์กโฟลว์ GitHub คุณสามารถสร้างโฟลว์ Power Automate ที่จะทริกเกอร์เมื่อมีการร้องขอการปรับใช้งานใน Dataverse โฟลว์สามารถกำหนดค่าให้ส่งผ่านอินพุตที่จำเป็นไปยังเวิร์กโฟลว์ GitHub ได้ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการสร้างโฟลว์ของ Power Automate ให้ไปที่ สร้างโฟลว์

ข้อมูลโฟลว์

โฟลว์จะทริกเกอร์เมื่อมีการเรียกใช้การดำเนินการ OnDeploymentRequested ใน Dataverse โฟลว์เรียกตัวเชื่อมต่อ HTTP เพื่อทริกเกอร์เวิร์กโฟลว์ GitHub โฟลว์ส่งผ่านอินพุตที่จำเป็นไปยังเวิร์กโฟลว์ GitHub ได้ รวมอินพุตต่อไปนี้ในเนื้อความของคำขอ:

  • artifact_url: URL ของอาร์ทิแฟกต์โซลูชัน Dataverse ที่สร้างขึ้นโดยไปป์ไลน์
  • solution_name: ชื่อของโซลูชันในสภาพแวดล้อม Dataverse
  • user_name: ชื่อผู้ใช้สำหรับการคอมมิต
  • source_branch: สาขาต้นทางสำหรับการคอมมิตโซลูชัน
  • target_branch: สาขาที่จะสร้างสำหรับการคอมมิตโซลูชัน
  • commit_message: ข้อความที่จะระบุสำหรับการคอมมิต

ค่าที่ส่งผ่านไปยัง artifact_url, solution_name และ user_name จะถูกดึงมาจากเอาต์พุตของการดำเนินการที่ทริกเกอร์ไปป์ไลน์ commit_message ถูกดึงมาจากแถวการเรียกใช้ลำดับขั้นการปรับใช้งานใน Dataverse

  • artifact_url: @{triggerOutputs()?['body/OutputParameters/ArtifactFileDownloadLink']}
  • solution_name: @{triggerOutputs()?['body/OutputParameters/ArtifactName']}
  • user_name: @{triggerOutputs()?['body/OutputParameters/DeployAsUser']}
  • commit_message: @{outputs('Retrieve_the_Deployment_Stage_Run')?['body/deploymentnotes']}

โฟลว์ยังใช้โทเค็นการเข้าใช้ส่วนบุคคล (PAT) เพื่อรับรองความถูกต้องกับ GitHub ด้วย สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการสร้างโทเค็นการเข้าถึงส่วนตัวของ GitHub ให้ไปที่ การสร้างโทเค็นการเข้าถึงส่วนตัว PAT ถูกส่งในส่วนหัว Authorization ของคำขอ HTTP

อัปเดตค่าต่อไปนี้ในโฟลว์:

  • [GitHub Personal Access Token] - แทนที่ด้วยโทเค็นการเข้าถึงส่วนตัวของ GitHub ของคุณ
  • [GitHub Organization] - แทนที่ด้วยชื่อองค์กร GitHub ของคุณ
  • [GitHub Repository] - แทนที่ด้วยชื่อที่เก็บ GitHub ของคุณ
  • [GitHub Workflow YAML File] - แทนที่ด้วยชื่อไฟล์ YAML ของเวิร์กโฟลว์ GitHub ของคุณ
  • [Source Branch] - แทนที่ด้วยสาขา Git เพื่อคอมมิตโซลูชัน
  • [Target Branch] - แทนที่ด้วยสาขา Git เพื่อสร้างการคอมมิตโซลูชัน Target Branch เป็นแบบไม่บังคับ หากคุณไม่ระบุสาขาเป้าหมาย แสดงว่าโซลูชันของคุณยอมรับ Source Branch

โฟลว์ Power Automate ที่แสดงทริกเกอร์ OnDeploymentRequested พร้อมขั้นตอนเพื่อดึงการเรียกใช้ลำดับขั้นการปรับใช้งานที่เกี่ยวข้องและเรียกเวิร์กโฟลว์ GitHub โดยใช้ตัวเชื่อมต่อ HTTP

ขั้นตอนถัดไป

เรียกใช้ไปป์ไลน์ใน Power Platform

ดูเพิ่มเติม

เริ่มต้นใช้งานด่วนสำหรับ GitHub Actions
ขยายไปป์ไลน์ใน Power Platform
โฟลว์ระบบคลาวด์คืออะไร