cancel
Showing results for 
Search instead for 
Did you mean: 
suparna-banerje

Detail Step-By-Step - Power Platform ALM with GitHub Actions

Introduction

  1. We can use GitHub Repositories as Source Control for Power Platform Solutions.
  2. To implement CI/CD process with GitHub, we can store the Power Platform solution in the source control. There are two main Paths –
    1. Export the unmanaged solution and place it as unpacked in the source control system. The build process imports the packed solution as unmanaged into a temporary build environment , then export the solution as managed and store it as a build artifact in your source control system.
    2. Export the solution as unmanaged and also export the solution as managed, and place both in the source control system.

We will follow Path B in this article.

 

We can create GitHub Workflows using yaml code for:

  1. Exporting the Solutions from Dev, unpack and store in a repository branch
  2. Generating Build Artifact and Import to Production

Steps:

1.    Setup source and Target environment

Create source and target environments. Both should have Dataverse database enabled. Create an unmanaged Solution in the source environment.

 

2.    Create Azure AD App Registration

  1.  Go to https://portal.azure.com
  2.  Search for App Registration, click New Registration
  3.  Provide the name, keep other fields with default value and click Register
  4.  Once the App is created, go to API Permissions, click Add a Permission>Select Dynamics CRM>Add Permission >Grant Admin Consent for <tenant>

suparnabanerje_0-1674124432371.png

     5. Go to Overview>Client credentials>New Secret. Copy the value into a notepad as this will be needed later and you won’t be able to get it once navigate away from this page.

    6. Come back to overview, and copy the Application (client) ID and Directory (tenant) ID in the same notepad. You will need these 3 values while creating GitHub workflows.

 

3.    Set up GitHub

  1.  Create GitHub Repository
  2.  Create new secret for Service Principal Authentication
  3.  Install GitHub Actions for Microsoft Power Platform from GitHub Marketplace for Actions

 

4.    Create GitHub Workflow – Export Solution

This workflow will export the Power Platform solution and keep both the managed and unmanaged version as unpacked in Github repository.

 

  1. Go to your Repository .Click on Actions and click set up a workflow yourself or click Configure in the Simple workflow box under the suggested for this repository section. This will start a new YAML file with a basic workflow to help you get started with GitHub actions. Update the name of the yaml file “Export Solution from Dev”
  2. Remove the content and paste below yaml code . Change the below values 

 

Solution Name - Provide your Solution Name (not the display name)

 

Environment Url - Go to make.powerapps.com> Select your Source environment >Go to Settings>Session details>copy the Instance url

 

Client ID and Tenant ID – Get it from the App registration created earlier

 

-----------------------------------------------------------------

 

name: export-and-branch-solution

# Export solution from DEV environment

#  unpack it and prepare, commit and push a git branch with the changes

 

on:

  workflow_dispatch:

    inputs:

      # Change this value

      solution_name:

        description: 'name of the solution to worked on from Power Platform'

        required: true

        default:  <SolutionName>

       #Do Not change these values

      solution_exported_folder:

        description: 'folder name for staging the exported solution *do not change*'

        required: true

        default: out/exported/

      solution_folder:

        description: 'staging the unpacked solution folder before check-in *do not change*'

        required: true

        default: out/solutions/

      solution_target_folder:

       description: 'folder name to be created and checked in *do not change*'

       required: true

       default: solutions/

env:

#edit your values here

  ENVIRONMENT_URL: '<Dev environment url>/'

  CLIENT_ID: ‘<clientId>’

  TENANT_ID: '<tenantID>'

 

jobs:

  export-from-dev:

    runs-on: windows-latest

    # or you can say runs-on: ubuntu-latest

    env:

      RUNNER_DEBUG: 1

 

    steps:

    - uses: actions/checkout@v2

      with:

        lfs: true

 

  

    - name: export-solution action -unmanaged

      uses: microsoft/powerplatform-actions/export-solution@v0

      with:

        environment-url: ${{env.ENVIRONMENT_URL}}

        app-id: ${{env.CLIENT_ID}}

        client-secret: ${{ secrets.PowerPlatformSPN }}

        tenant-id: ${{env.TENANT_ID}}

        solution-name: ${{ github.event.inputs.solution_name }}

        solution-output-file: ${{ github.event.inputs.solution_exported_folder}}/${{ github.event.inputs.solution_name }}.zip

       

    - name: export-solution action -managed

      uses: microsoft/powerplatform-actions/export-solution@v0

      with:

        environment-url: ${{env.ENVIRONMENT_URL}}

        app-id: ${{env.CLIENT_ID}}

        client-secret: ${{ secrets.PowerPlatformSPN }}

        tenant-id: ${{env.TENANT_ID}}

        solution-name: ${{ github.event.inputs.solution_name }}

        managed: true

        solution-output-file: ${{ github.event.inputs.solution_exported_folder}}/${{ github.event.inputs.solution_name }}_managed.zip

 

    - name: unpack-solution action

      uses: microsoft/powerplatform-actions/unpack-solution@v0

      with:

        solution-file: ${{ github.event.inputs.solution_exported_folder}}/${{ github.event.inputs.solution_name }}.zip

        solution-folder: ${{ github.event.inputs.solution_folder}}/${{ github.event.inputs.solution_name }}

        solution-type: 'Both'

        overwrite-files: true

 

    - name: branch-solution, prepare it for a PullRequest

      uses: microsoft/powerplatform-actions/branch-solution@v0

      with:

        solution-folder: ${{ github.event.inputs.solution_folder}}/${{ github.event.inputs.solution_name }}

        solution-target-folder: ${{ github.event.inputs.solution_target_folder}}/${{ github.event.inputs.solution_name }}

        repo-token: ${{ secrets.GITHUB_TOKEN }}

        allow-empty-commit: true

 

------------------------------------------------------------------------------------------

  1.  You are now ready to commit your changes. Select Start commit, type Create export yml in the title field, and then add a description (optional). Next, click Commit new file.
  2.  Navigate to Actions, Run workflow, and choose Run workflow.
  3.  After the workflow has completed, validate that a new branch has been created

suparnabanerje_1-1674124432376.png

4.  Go to Pull Requests, select the Branch and click Create Pull Request.

5.  On the Open a Pull request screen, add a title and description, as desired, then click Create pull request.

 

suparnabanerje_2-1674124432382.png

6.  The screen will update showing the newly create pull request. As the pull request is created confirmation will be provided showing that our branch has no conflict with the main branch. This confirmation means that the changes can be merged into the main branch automatically. Click Merge pull request and then click Confirm merge.

7.  Navigate back to the default (main) branch and validate the solution is now available there as well.

 

5. Create GitHub Workflow -  Generate a build artifact and import to production

 

This workflow will generate build artifact for managed solution and import it to Production environment.

Create another workflow file following the same process above, paste the below yaml code . Update the values following the same steps as above

-------------------------------------------------------------------------------------

name: release-solution-to-prod

# Reusable workflow

# upload the solution to the GitHub artifacts and deploy to the PROD environment

on:

  workflow_dispatch:

    inputs:

      #Do Not change these values

      #Values are set by the caller

      #caller sample: release-action-call.ymnl

      solution_name:

        description: 'The solution name.'

        type: string

        default: '<SolutionName> '  

      solution_shipping_folder:

        description: 'folder name for staging the exported solution *do not change*'       

        type: string

        default: out/ship/

      solution_outbound_folder:

        description: 'staging the unpacked solution folder before check-in *do not change*'

        type: string

        default: out/solutions/

      solution_source_folder:

       description: 'folder name to be created and checked in *do not change*'

       type: string

       default: solutions/

      solution_release_folder:

       description: 'folder where the released binaries are going to be hosted *do not change*'

       type: string

       default: out/release

         

      PRODUCTION_ENVIRONMENT_URL:

        description: 'Production environment url.'

        type: string

        required: true

        default: ‘<Production Environment Url>’

       

      CLIENT_ID:

        description: 'The client id'

        type: string

        required: true

        default: ‘<ClientID>’

      TENANT_ID:

        description: 'The tenant id'

        type: string

        required: true

        default: ‘<TenantID>’ 

 

jobs:

  convert-to-managed:

    runs-on: windows-latest

    # or you can say runs-on: ubuntu-latest

    env:

      RUNNER_DEBUG: 1

 

    steps:

    - uses: actions/checkout@v2

      with:

        lfs: true

 

    - name: Pack solution

      uses: microsoft/powerplatform-actions/pack-solution@v0

      with:

        solution-folder: ${{ inputs.solution_source_folder}}/${{ inputs.solution_name }}

        solution-file: ${{ inputs.solution_outbound_folder}}/${{ inputs.solution_name }}_managed.zip

        solution-type: Managed

 

 

    - name: Upload the ready to ship solution to GH artifact store

      uses: actions/upload-artifact@v2

      with:

        name: managedSolutions

        path: ${{ inputs.solution_outbound_folder}}

 

  release-to-staging:

    needs: [ convert-to-managed ]

    runs-on: windows-latest

    env:

      RUNNER_DEBUG: 1

 

    steps:

    - uses: actions/checkout@v2

      with:

        lfs: true

 

    - name: Fetch the ready to ship solution from GH artifact store

      uses: actions/download-artifact@v2

      with:

        name: managedSolutions

        path: ${{ inputs.solution_release_folder}}

    - name: Import solution to prod env

      uses: microsoft/powerplatform-actions/import-solution@v0

      with:

        environment-url: ${{inputs.PRODUCTION_ENVIRONMENT_URL}}

        app-id: ${{inputs.CLIENT_ID}}

        client-secret: ${{ secrets.PowerPlatformSPN }}

        tenant-id: ${{inputs.TENANT_ID}}

        solution-file: ${{ inputs.solution_release_folder}}/${{ inputs.solution_name }}_managed.zip

        force-overwrite: true

        publish-changes: true

 

-----------------------------------------------------------------------------------------------

Run the workflow and validate that the solution has been deployed to Production.

Comments

Hi!   Thanks for this.  One question -- I can't see anything here that updates the solution version number?   Is that possible?

@matmeredith You can add the task Set Solution version in your Azure DevOps pipeline, GitHub has some limitation as of now

Thanks.  But I'm using GitHub pipelines, so is this not possible currently?   I'd looked at the equivalent GitHub action but was struggling to get it to work.... 

 

Nice article @suparna-banerje .

 

@matmeredith Apologies for the late response. I had exactly the same question when I first started working with Power Platform Github Actions as there was no such action available. However, it looks like this action is now available to set the version of a solution. See here: https://github.com/microsoft/powerplatform-actions/blob/main/set-online-solution-version/action.yml. According to the file history it only became available less than 1 month ago.

@suparna-banerje I am getting an error when running the Import workflow into the destination environment.  It is stating the following,

"Error: CanvasApp import: FAILURE: No file with that name found

CanvasApp import: FAILURE: No file with that name found"
 
The solution has a model driven app, not canvas.  I reviewed your code and it does not specify the app type, so unsure where this error is coming from.  The export workflow worked just fine with exporting.
 
Please advise as to your conclusion.

 

@bei_mf Are you still facing this issue? There were some issues with a release of GitHub actions, which should have been fixed now. 

@bei_mf The error might be being raised because you have Custom Pages in your solution - these are similar to Canvas Apps.

 

Please ensure you are using the latest version of the Github Actions though in your workflow as the issue was resolved a while ago. You will need to re-export/unpack and commit your solution and re-build it again using the latest version of the Github Actions for the fix to take effect