0

I would like to identify the build policy for a build that was run by clicking the Queue (or Re-queue) button against a required/optional check from within a pull request. I wish to identify the policy programmatically from within a pipeline; e.g. a script task. Open to any approach, been exploring the az CLI but no luck thus far.

I've setup two build policies against a branch that both target the same build definition - Policy A and Policy B. Both are setup to be run manually - A is required, B is optional. Both will surface in the UI for a pull request as checks - A being required, B being optional. When a build is run by clicking the Queue (or Re-queue) button against either check, I would like to be able to identify which of the two policies the run was initiated from, (which policy provided the Queue or Re-queue button that was clicked).

Screenshot of Required & Optional Checks in Pull Request in Azure DevOps

EDIT: A bit more background on what I'm doing ...

  • I've got a single pipeline for building an application.
  • I've recently got a request to update the pipeline to support publishing to Chromatic.
  • I've added a Publish to Chromatic parameter to the pipeline and a task to push to Chromatic when the parameter is set to true.
  • I received a subsequent request to make it easier to publish changes from a feature branch to Chromatic. One engineer threw out the idea of having an optional check available in pull requests to give a single button click experience.

While researching my options, I was wondering if it would be possible to enhance the existing pipeline to set the Publish to Chromatic parameter to true during a run. I found this comment on Reddit which ultimately led to me posting here ...

set a default for your parameter (I like to use 'auto') add a script >task near the beginning that reads the pull request comment and sets a variable for you to use in later logic if the parameter is auto . you can even condition this to only run on a PR.

I am aware that I could create a separate pipeline for publishing to Chromatic instead of updating the existing one; that's one of a few options I have. At this point, I'm more-so curious whether or not this particular approach is technically feasible even if I opt not to go forward with it.

Hope that adds some clarity!

cookbr
  • 125
  • 2
  • 9

1 Answers1

0

The policy that queued the pipeline isn't something that is visible to the pipeline as a pipeline variable. In fact, there doesn't seem to be any indication if the PullRequest was queued manually or automatically.

There might be a few other ways to approach this...

I would start by putting a publishChromatic parameter in the pipeline and then building up conditions in the pipeline execution around this variable. By default, let's assume that the value is false so that if you're manually queueing a pipeline run you can opt-in.

triggers:
- include:
    branches:
    - develop

parameters:

- name: publishChromatic
  displayName: 'Publish build to Chromatic'
  type: boolean
  default: false

jobs:
- job: Build
  variables:
    publishChromatic: ${{ parameters.publishChromatic }}
 
  steps:
  ... pre-execution steps

  - task: CmdLine@2
    displayName: Publish to Chromatic
    condition: and(succeeded(), eq(variables['publishChromatic'], 'true'))
    inputs:
      script: npx chromatic --project-token=$(CHROMATIC_PROJECT_TOKEN) --branch=$(Build.SourceBranch)

  ... post execution steps

Option 1: Pull Request Labels

One option might be to inspect the pull request for the presence of a label as outlined in this answer. As a pre-execution step, a simple script could flip the flag when the label is present:

- pwsh: |
    $urlFormat = "{0}/{1}/_apis/git/repositories/{1}/pullRequests/{2}/labels?api-version=6.0-preview.1"
    $url = $urlFormat -f `
              $env:SYSTEM_TEAMFOUNDATIONSERVERURI, `
              $env:SYSTEM_TEAMPROJECTID, `
              $env:BUILD_REPOSITORY_NAME, `
              $env:SYSTEM_PULLREQUEST_PULLREQUESTID
    $headers = @{
       Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
    }

    $response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers
    $labels = $response.value.name

    Write-Host "##vso[task.setvariable variable=PullRequestTag]$labels"                        
    
  displayName: 'Fetch Pull Request Labels'
  condition: and( succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)

- pwsh: |
    if ("$(PullRequestLabels)" -like "*chromatic*") {
       Write-Host "##vso[task.setvariable variable=publishChromatic]true"
    }
  condition: and( succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
  displayName: 'Check for Chromatic label'
    

I like this option in that it provides a bit of traceability for which Pull Requests were deployed. Unfortunately, there's no way to queue a build automatically when the PR labels are modified so you'd need to have the tag on the PR before triggering the pipeline.

You could also establish a different pattern such as triggering based on a convention like a value that appears in the name of the Pull Request, etc.

Option 2: Pipeline to Trigger Chromatic

If you'd rather have a Build Validation option labeled 'Deploy to Chromatic' to automate triggering your deployment to Chromatic, a simple option would be to create a pipeline that triggers your pipeline with the publishChromatic parameter.

trigger: none

steps:
- checkout: none
- pwsh: |
    $pipelineId = 1234
    $urlFormat = "{0}/{1}/_apis/pipelines/{2}/runs?api-version=6.0-preview.1
    $url = $urlFormat -f `
              $env:SYSTEM_TEAMFOUNDATIONSERVERURI, `
              $env:SYSTEM_TEAMPROJECTID `
              $pipelineId
    $headers = @{
       Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
    }
    $body = @{
       resources = @{ repositories = @{ self = @{ refName = "$(Build.SourceBranch)" } } }
       variables = @{
         originalPrId = @{
            value = "$(System.PullRequest.PullRequestId)
         }
       }
       templateParameters = @{
          publishChromatic = $true
       }
    }

    Invoke-RestMethod -Uri $url -Method Post -Body $body -Headers $headers

  displayName: 'Trigger Chromatic Pipeline'
  condition: eq(variables['Build.Reason'],'PullRequest')
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)

This simple script performs a fire-and-forget approach to triggering your original pipeline.

If you need to have a successful deployment to Chromatic as part of your PR, you could adjust the original pipeline to report a pull-request status.

In your original pipeline, add the following as a post-execution step:

- pwsh: |
    $urlFormat = "{0}/{1}/_apis/git/repositories/{2}/pullRequests/{3}/statuses?api-version=6.0-preview.1
    $url = $urlFormat -f `
              $env:SYSTEM_TEAMFOUNDATIONSERVERURI, `
              $env:SYSTEM_TEAMPROJECTID, `
              $env:BUILD_REPOSITORY_NAME, `
              "$(originalPrId)"
    $headers = @{
       Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
    }
    $body = @{
       status = "succeeded"
       description = "completed chromatic regression"
       context = @{
          name = "qualitygate/chromatic"
       }
       targetUrl = "http://chromatic.com/your/buildid"
    }
    
    Invoke-RestMethod -Uri $url -Method POST -Body $body -Headers $headers
    
  displayName: Report status to PR
  condition: and( succeeded(), ne(variables['originalPrId'],''))
  env:
    SYSTEM_ACCESSTOKEN: $(System.AccessToken)
  

To require a successful chromatic quality gate, add a Status Check to your Branch Policy with the same name mentioned above qualitygate/chromatic.

Option 3: Further down the Rabbit hole

You can establish even deeper integration with Chromatic by building a custom extension that allows you to add specialized menus to the Pull Request checks menu. The custom menu could include javascript-enabled buttons to trigger your pipeline without the need for a custom pipeline mentioned in Option 2.

While not necessarily dependent on writing a custom extension, you could also create an Azure Function App that listens for webhooks from Chromatic and posts status updates back to your PR with the a custom UI that links back to the Chromatic build. You'd simply need to query the Azure DevOps API to map the branch name in the Chromatic payload to the corresponding PR.

bryanbcook
  • 16,210
  • 2
  • 40
  • 69