Skip to content

Instantly share code, notes, and snippets.

@rfennell
Last active February 7, 2025 11:19
Show Gist options
  • Save rfennell/374f4b5fea6e64f38743b9a9adf2b166 to your computer and use it in GitHub Desktop.
Save rfennell/374f4b5fea6e64f38743b9a9adf2b166 to your computer and use it in GitHub Desktop.
A sample Azure DevOps YAML Pipeline to update WI based on a WIQL query
# A pipeline to update a specific field in a work items that meeting a specific WIQL filter
# Do not trigger on a commit to the repo, but allow a manual run
trigger: none
# Run the pipeline at 1am every day
schedules:
- cron: '1 0 * * *'
displayName: Daily midnight build
always: true
branches:
include:
- main
# Parameters to allow overiding values on a manual run
parameters:
- name: TrialRun
displayName: Trial Run (Find the WI in scope but do not update)
type: boolean
default: false
- name: FieldName
displayName: Numeric WI Field to update
type: string
default: "Custom.PBIAge"
- name: WIQL
displayName: The WIQL Query to select the WI to update
type: string
default: "SELECT [System.Id] FROM workitems WHERE ([System.WorkItemType] = 'Bug' OR [System.WorkItemType] = 'Product Backlog Item' ) AND [System.State] IN ('Code Complete', 'Rework', 'Failed QA', 'Passed QA', 'Ready For Release QA', 'Failed Release QA', 'Passed Release QA', 'Ready To Deployed' )"
pool:
vmImage: ubuntu-latest
steps:
- checkout: none
- task: PowerShell@2
displayName: 'Increment PBI count'
inputs:
targetType: 'inline'
pwsh: true
script: |
# Set the values that would be passed in a parameters to a script
$org = '$(System.TeamFoundationCollectionUri)'
$project = "$(System.TeamProject)"
$fieldName = "${{ parameters.FieldName }}"
$query = "${{ parameters.WIQL}}"
$trialRun = [System.Convert]::ToBoolean("${{parameters.TrialRun}}")
# Append the project filter to the query so that only the required project is queried
# if this is not done then the query will return all work items in the organisation that the user has access too
# Note: On why this required
# - This has been done in this manner, as opposed to including it in the query string, as it was deemed this makes the query easier to understand
# - The --project parameter has not been used as this will not work with the --wiql parameter, the parameter overrides it.
$query += " AND [System.TeamProject] = '$project'"
write-host "Using the query '$query'"
# Get the work items that match the query, and force into an array as PS will not return an array for a single item
$workitems = @(az boards query --org $org --project $project --wiql $query | ConvertFrom-Json)
write-host "Found $($workitems.Count) work items that match the query"
# Loop across all the work items that match the query
foreach ($wi in $workitems) {
$id = $wi.id
# Get the current value of the fieldName
$currentWi = az boards work-item show --org $org --id $id | ConvertFrom-Json
$fieldValue = $currentWi.fields.$fieldName
Write-Host " Processing '$($currentWi.fields."System.WorkItemType")' WI #$id"
# Check the fieldName is numeric and if the value is null set to zero
if ($fieldValue -eq $null) {
$fieldValue = 0
} elseif ($fieldValue -isnot [double] -and $fieldValue -isnot [int64]) {
Write-Warning "The fieldName '$fieldName' does not contain numeric data'"
continue
}
if ($trialRun) {
write-host " TRIALRUN: The current value of the fieldName '$fieldName' would be updated from $fieldValue to $($fieldValue+1)"
} else {
write-host " The current value of the fieldName '$fieldName' will be updated from $fieldValue to $($fieldValue+1)"
$updatedWi = az boards work-item update --org $org --id $id --fields "$fieldName=$($fieldValue+1)" | ConvertFrom-Json
# error if the field was not updated
if ($updatedWi.fields.$fieldName -ne $fieldValue+1) {
Write-Host "The fieldName '$fieldName' was not updated to $($fieldValue+1) "
exit 1
}
}
}
Write-Host "All work items have been updated"
env:
AZURE_DEVOPS_EXT_PAT: $(System.AccessToken)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment