Create standard tasks
Because it is useful to create standard (DoD) tasks for a User Story so that you do not forget anything, this script checks all User Stories in the current Iteration and creates the necessary tasks for these stories.
Supplies
- PAT token from your DevOps project
- Project and organization name.
- A way to automate your powershell script, this can be done through a scheduled task, scheduled pipeline or, for example, a webhook.
Script
The script uses the DevOps API to create tasks, the tasks are defined in a json file, make sure this file is in the same location as the script.
workitems.json |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 | [
{
"Title": "Documentation",
"Description": "Describe the changes or new functionality on https://docs.loevencloud.nl"
},
{
"Title": "Step-by-step plan",
"Description": "define a step-by-step plan."
},
{
"Title": "The Test",
"Description": "Describe tests and implement them where possible."
},
{
"Title": "Research",
"Description": "Go out and do some research."
},
{
"Title": "Automatiseer",
"Description": "Can it be done automatically?."
},
{
"Title": "Integrate",
"Description": "integrates it into the current setup (https://docs.loevencloud.nl"
}
]
|
automateTasks.ps1 |
---|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 | <#
.SYNOPSIS
Automation script for common devops tasks
#>
[CmdletBinding()]
param (
[Parameter()]
[string]$org = "DEVOPSORG",
[Parameter()]
[string]$project = "DEVOPSPROJECT",
[Parameter()]
[string]$pat = "DEVOPSPAT"
)
#Global Variables
$B64Pat = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("`:$Pat"))
$header = @{
Authorization = "Basic $B64pat"
}
$iterationBaseUri = 'https://dev.azure.com/ORG/PROJECT/_apis/work/teamsettings/iterations?$timeframe=current
$iterationUri = $iterationBaseUri.replace("ORG/PROJECT","$org/$project")
$workItemBasePostUri = 'https://dev.azure.com/ORG/PROJECT/_apis/wit/workitems/$Task?api-version=6.1-preview.3'
$workItemPostUri = $workItemBasePostUri.replace("ORG/PROJECT", "$org/$project")
$currentIteration = Invoke-RestMethod -Method GET -Headers $header -Uri $iterationUri -ContentType "application/json"
$workitemsUri = "https://dev.azure.com/$org/$project/_apis/work/teamsettings/iterations/$($currentIteration.value.id)/workitems?api-version=7.0"
$allWorkitems = Invoke-RestMethod -Method GET -Headers $header -Uri $workitemsUri -ContentType "application/json"
$defaultWorkItems = Get-Content -Raw -Path /scripts/workitems.json | ConvertFrom-Json
$userStories = $allWorkitems.workItemRelations | Where-Object { $_.source -eq $null }
$excludedStories = @("OPS", "OOTS")
#Functions
function Add-devOpsWorkItem {
[CmdletBinding()]
param (
[Parameter()]
[string]$Title,
[Parameter()]
[string]$userStoryId,
[Parameter()]
[string]$description,
[Parameter()]
[string]$iterationPath
)
$body = @(
@{
op = "add"
path = "/fields/System.IterationPath"
value = "$iterationPath"
},
@{
op = "add"
path = "/fields/System.Title"
value = "$title"
},
@{
op = "add"
path = "/fields/System.Description"
value = "$description"
},
@{
op = "add"
path = "/relations/-"
value = @{
rel = "System.LinkTypes.Hierarchy-Reverse"
url = "https://dev.azure.com/$org/$project/_apis/wit/workitems/$userStoryId"
}
}
) | ConvertTo-Json -Depth 10
$response = Invoke-RestMethod -Uri $workItemPostUri -Headers $header -Method POST -Body $body -ContentType "application/json-patch json"
if ($response.id) {
Write-Host "`tTask $title created and linked"
}
else {
Write-Host "Error creating task and linking to user story: $($response | ConvertTo-Json -Depth 10)"
}
}
# Main script
foreach ($userStory in $userStories) {
$storyProperties = Invoke-RestMethod -Method get -Headers $header -Uri $userstory.target.url -ContentType "application/json"
$iteration = $($storyProperties.fields.'System.IterationPath')
Write-Output "$iteration - $($storyProperties.fields.'System.Title')"
if ($excludedStories -contains $($storyProperties.fields.'System.Title')) {
Write-Output "$($storyProperties.fields.'System.Title') is excluded for default work process."
}
else {
$childItems = $allWorkitems.workItemRelations | Where-Object { $_.source.id -eq $userstory.target.id }
$activeTasks = @()
foreach ($child in $childItems) {
$taskMeta = @{} | Select-Object Title
$childProperties = Invoke-RestMethod -Method get -Headers $header -Uri $child.target.url -ContentType "application/json"
$taskMeta.Title = "`t$($childProperties.fields.'System.Title')"
$activeTasks = $taskMeta
}
foreach ($defaultTask in $defaultWorkItems) {
if (!($activeTasks.Title -match $defaultTask.Title)) {
Add-devOpsWorkItem -Title $defaultTask.Title -userStoryId $userstory.target.id -iterationPath $iteration -description $defaultTask.Description
}
}
}
}
|