Configuring CI Using Azure Pipelines and Nx
Below is an example of an Azure Pipelines setup building and testing only what is affected.
1name: CI
2
3trigger:
4  - main
5pr:
6  - main
7
8variables:
9  CI: 'true'
10  ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
11    NX_BRANCH: $(System.PullRequest.PullRequestNumber)
12    TARGET_BRANCH: $[replace(variables['System.PullRequest.TargetBranch'],'refs/heads/','origin/')]
13    BASE_SHA: $(git merge-base $(TARGET_BRANCH) HEAD)
14  ${{ if ne(variables['Build.Reason'], 'PullRequest') }}:
15    NX_BRANCH: $(Build.SourceBranchName)
16    BASE_SHA: $(git rev-parse HEAD~1)
17  HEAD_SHA: $(git rev-parse HEAD)
18
19jobs:
20  - job: main
21    pool:
22      vmImage: 'ubuntu-latest'
23    steps:
24      - checkout: self
25        fetchDepth: 0
26        persistCredentials: true
27
28      # Set Azure Devops CLI default settings
29      - bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject)
30        displayName: 'Set default Azure DevOps organization and project'
31      # Get last successfull commit from Azure Devops CLI
32      - bash: |
33          LAST_SHA=$(az pipelines build list --branch $(Build.SourceBranchName) --definition-ids $(System.DefinitionId) --result succeeded --top 1 --query "[0].triggerInfo.\"ci.sourceSha\"")
34          if [ -z "$LAST_SHA" ]
35          then
36            echo "Last successful commit not found. Using fallback 'HEAD~1': $BASE_SHA"
37          else
38            echo "Last successful commit SHA: $LAST_SHA"
39            echo "##vso[task.setvariable variable=BASE_SHA]$LAST_SHA"
40          fi
41        displayName: 'Get last successful commit SHA'
42        condition: ne(variables['Build.Reason'], 'PullRequest')
43        env:
44          AZURE_DEVOPS_EXT_PAT: $(System.AccessToken)
45
46      # Connect your workspace on nx.app and uncomment this to enable task distribution.
47      # The "--stop-agents-after" is optional, but allows idle agents to shut down once the "e2e-ci" targets have been requested
48      # - script: yarn nx-cloud start-ci-run --distribute-on="3 linux-medium-js" --stop-agents-after="e2e-ci"
49
50      - script: yarn install --frozen-lockfile
51      - script: git branch --track main origin/main
52        condition: eq(variables['Build.Reason'], 'PullRequest')
53
54      # Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
55      # - script: yarn nx-cloud record -- echo Hello World
56      - script: yarn nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) --targets lint test build
57      - script: yarn nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) --parallel 1 e2e-ci
58Get the Commit of the Last Successful Build
In the example above, we ran a script to retrieve the commit of the last successful build. The idea is to use Azure Devops CLI directly in the Pipeline Yaml
First, we configure Devops CLI
1# Set Azure Devops CLI default settings
2- bash: az devops configure --defaults organization=$(System.TeamFoundationCollectionUri) project=$(System.TeamProject)
3  displayName: 'Set default Azure DevOps organization and project'
4Then we can query the pipelines API (providing the auth token)
1# Get last successfull commit from Azure Devops CLI
2- bash: |
3    LAST_SHA=$(az pipelines build list --branch $(Build.SourceBranchName) --definition-ids $(System.DefinitionId) --result succeeded --top 1 --query "[0].triggerInfo.\"ci.sourceSha\"")
4    if [ -z "$LAST_SHA" ]
5    then
6      echo "Last successful commit not found. Using fallback 'HEAD~1': $BASE_SHA"
7    else
8      echo "Last successful commit SHA: $LAST_SHA"
9      echo "##vso[task.setvariable variable=BASE_SHA]$LAST_SHA"
10    fi
11  displayName: 'Get last successful commit SHA'
12  condition: ne(variables['Build.Reason'], 'PullRequest')
13  env:
14    AZURE_DEVOPS_EXT_PAT: $(System.AccessToken)
15We can target a specific build; in this example, we specified:
- The branch (--branch)
- The result type (--result)
- The number of the result (--top)
The command returns an entire JSON object with all the information. But we can narrow it down to the desired result with the --query param that uses JMESPath format (more details)
Finally, we extract the result in a common custom variable named BASE_SHA used later by the nx format and nx affected commands.