Perform CI/CD for Fabric apps with Azure DevOps

This post covers how you can perform CI/CD for Fabric apps with Azure DevOps. In order to deploy efficiently with a fully working YAML pipeline. Like in the below diagram.

Perform CI/CD for Fabric apps with Azure DevOps
Perform CICD for Fabric apps with Azure DevOps

Just to clarify, Fabric apps were announced at Microsoft Build two weeks ago. Idea is that you work with the developer toolkit called Rayfin to develop your application of choice locally, which you can then publish as a Fabric app in a Microsoft Fabric workspace.

There has been a lot of excitement online about this due to the many types of applications that you can develop with Rayfin projects and AI.

Microsoft has already released a guide that shows how to deploy Fabric apps with GitHub Actions. However, some changes need to be taken into consideration to orchestrate deployments with YAML pipelines in an efficient manner.

You can find an example that accompanies this post in the ado-fabric-app-cicd repository in GitHub. Which you can clone/download and work with. You can find the ‘deploy-app.yml‘ YAML pipeline in the ado-pipeline subfolder.

Perform CI/CD for Fabric apps with Azure DevOps

I got started by creating and developing a Rayfin package locally.

Performing CI/CD for Fabric apps with Azure DevOps is currently a two-step approach. First, you need to develop your proposed app with a Rayfin project locally and test your changes (CI). Afterwards, you need to deploy it to a Fabric workspace (CD).

Continuous Integration

One part that often gets overlooked when performing CI/CD is doing the Continuous Integration part. Options to perform Continuous Integration with this new offering include:

  • Preview deployment without changes with the –dry-run option. Which shows the planned operations.
  • Test changes locally with the npm run dev command. Once done, click on the Local URL returned. In Visual Studio Code this will cause the app to appear in a new tab.
  • Deploy to a development workspace with the ‘npx rayfin up –workspace {workspace name}‘ command.
  • Check your application is stable and secure with your AI offering of choice.

In addition, I strongly suggest you personally review your Fabric app before deploying to anything that resembles a production environment.

Note that when you create a new Rayfin project, Rayfin creates a populated ‘.gitignore’ file that excludes certain files from source control. As a result, Git does not push those files to remote repositories such as Azure DevOps. For example, the ‘.deployments’ log remains local to the project.

This does not mean that you do not need to check your Rayfin project for other potential issues though.

Anyway, after I had created my Rayfin package locally I tested it both locally and in a development workspace. I then pushed my changes into a Git repository in Azure DevOps. In order to create a YAML pipeline for deployment.

Deploying Fabric apps with Azure DevOps

Once my Git repository was in Azure DevOps, I started by adding the below to my YAML Pipeline.

variables:
- group: rayfin-ns
- group: rayfin-s

# Below are the parameters
parameters:
- name: force
  displayName: 'Allow destructive schema changes that may result in data loss'
  type: boolean
  default: false
  
trigger: none
# In this pipeline I use a Microsoft-hosted agent
# To reference a self-hosted agent instead swap around the commented and uncommented references
pool: 
  vmImage: 'windows-latest'

This was to reproduce the suggested parameter in the GitHub Actions guide. However, I propose you look into implementing an approvals process instead. Especially if intending to do a deployment to a production workspace.

Another key point I want to highlight is that I opted for a Windows Microsoft-hosted agent. This is because I found it was easier for my YAML pipeline to work with password management.

I then specified to checkout the repository and a version of node to work with. In order to Rayfin to work.

- checkout: self
  displayName: 'Checkout repository'

- task: UseNode@1
  displayName: 'Use Node.js 20'
  inputs:
    version: '20.x'

Afterwards I had to replicate the recommended concurrency option that is provided with the GitHub Actions alternative. There is not a native replacement for this in Azure DevOps. So, I got GitHub Copilot in Visual Studio Code to create the below PowerShell code for me.

- task: PowerShell@2
  displayName: 'Cancel older runs on this branch'
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)
  inputs:
    targetType: 'inline'
    script: |
      $orgUrl = "$(System.CollectionUri)"
      $project  = "$(System.TeamProject)"
      $definition = "$(System.DefinitionId)"
      $branch   = "$(Build.SourceBranch)"
      $currentId  = [int]"$(Build.BuildId)"

      $headers = @{
      Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
      }

      # Find running builds for this pipeline and branch
      $uri = "$($orgUrl)$project/_apis/build/builds" +
            "?definitions=$definition" +
            "&branchName=$([uri]::EscapeDataString($branch))" +
            "&statusFilter=inProgress,notStarted" +
            "&api-version=7.1"

      $builds = Invoke-RestMethod `
          -Uri $uri `
          -Headers $headers `
          -Method Get
          
      foreach ($build in $builds.value) {

        if ($build.id -lt $currentId) {

          Write-Host "Cancelling build $($build.id)"

          $cancelUri = "$($orgUrl)$project/_apis/build/builds/$($build.id)?api-version=7.1"

          $body = @{
            status = "Cancelling"
          } | ConvertTo-Json

          Invoke-RestMethod `
            -Uri $cancelUri `
            -Headers $headers `
            Method Patch `
            -ContentType "application/json" `
            -Body $body
        }
      }  

However, unless you are working with parallelism I recommend you comment this particular task out.

Next, I had to install Vite, TypeScript and Rayfin. I discovered that the Rayfin project already comes with a ‘package.json’ file. Which means I can install dependencies with the below task.

- task: PowerShell@2
  displayName: 'Install dependencies'
  inputs:
    targetType: 'inline'
    script: |
      npm ci

Installing the packages this way speeded up the process significantly.

Next task was to login to Rayfin with service principal credentials.

- task: PowerShell@2
  displayName: 'Login to Rayfin with service principal'
  inputs:
    targetType: 'inline'
    script: |
      npx rayfin login --service-principal --encryption-fallback-enabled -t '$(AZURE_TENANT_ID)' -u '$(AZURE_CLIENT_ID)' -p '$(AZURE_CLIENT_SECRET)'

Last task installs the Fabric app and related services into a Microsoft Fabric workspace.

- task: PowerShell@2
  displayName: 'Deploy to Fabric'
  inputs:
    targetType: 'inline'
    script:
      $extraArgs = ""

      if ("${{ parameters.force }}" -eq "true") {
          $extraArgs = "--force"
      }

      npx rayfin up `
        --workspace "$(fabric-workspace-name)" --yes $extraArgs

Testing deployed Fabric apps

Once completed I started my YAML pipeline. Once my YAML pipeline had completed I checked my Microsoft Fabric workspace and confirmed the fabric app and related items were there.

Afterwards, I created a different Fabric app with AI. Creating an focused session selector based on the Data Céilí schedule. Which I created by converting the ToDo project with a few AI prompts. This also worked and deployed the below Fabric app.

Focused Data Ceili session selector  deployed as a Fabric app
Focused Data Ceili session selector deployed as a Fabric app

Epilogue

As you can see, it is possible to Perform CI/CD for Fabric apps with Azure DevOps. However, CI/CD for Fabric apps in Microsoft Fabric does require a different approach.

Please remember that Fabric apps are still fairly new. When developing and deploying Fabric apps with Rayfin always check that they are both stable and secure.

Anyway, feel free to experiment with the YAML pipeline for yourselves.

2 thoughts on “Perform CI/CD for Fabric apps with Azure DevOps”

Leave a Comment