Skip to content

Commit 925b555

Browse files
authored
Utility: Script for listing task versions and searching for a version (#21084)
* Adding Script for List Task Version * Get the release the version is part of * Added support for inline parameter * Updated Documentation * Updated documentation
1 parent 6f96b30 commit 925b555

File tree

2 files changed

+298
-0
lines changed

2 files changed

+298
-0
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# TasksVersions.ps1 Documentation
2+
3+
## Overview
4+
`ListTasksVersions.ps1` is a PowerShell script designed to list all unique versions of an Azure Pipelines task and show the commit link for each version. It also allows searching for a specific version based on `Major`, `Minor`, and `Patch` parameters.
5+
6+
## Features
7+
- List all versions of a task.
8+
- Search for a specific version using `Major`, `Minor`, and `Patch` parameters.
9+
- Displays error messages for invalid or missing inputs.
10+
## How to Run the Script
11+
12+
There are two ways to run the script:
13+
14+
### 1. Parameterized (Non-Interactive) Mode
15+
You provide all required parameters directly on the command line. This is useful for automation or scripting.
16+
17+
**Examples:**
18+
- List all versions of a task:
19+
```powershell
20+
pwsh ./ListTasksVersions.ps1 -TaskName CopyFilesV2
21+
```
22+
- Search for a specific version:
23+
```powershell
24+
pwsh ./ListTasksVersions.ps1 -TaskName CopyFilesV2 -Version 2.238.0
25+
```
26+
27+
- Search for a specific version and show release info:
28+
```powershell
29+
pwsh ./ListTasksVersions.ps1 -TaskName CopyFilesV2 -Version 2.238.0 -ShowRelease
30+
```
31+
32+
### 2. Interactive Mode
33+
If you do not provide required parameters, the script will prompt you for input. This is user-friendly for manual use.
34+
35+
**Example:**
36+
- Run the script without parameters:
37+
```powershell
38+
pwsh ./ListTasksVersions.ps1
39+
```
40+
- The script will prompt you to:
41+
1. Choose to view all versions or search for a specific version.
42+
2. Enter the task name.
43+
3. (If searching) Enter the version numbers.
44+
4. Choose whether to display release information (y/n).
45+
46+
Each case is handled automatically based on your input.
47+
## Usage
48+
49+
### Parameters
50+
- **TaskName**: The name of the task (e.g., `CopyFilesV2`).
51+
- **Major**: The major version number.
52+
- **Minor**: The minor version number.
53+
- **Patch**: The patch version number.
54+
- **ShowRelease**: Switch. If specified, displays release (Git tag) information for each version. If not provided, the script will prompt you in interactive mode.
55+
56+
### Behaviors
57+
#### View All Versions
58+
1. Run the script.
59+
2. Select the option to view all versions.
60+
3. Enter the task name.
61+
4. When prompted, choose whether to display release information (enter 'y' or 'n').
62+
5. The script lists all versions of the task, including release info if selected.
63+
64+
#### Search for a Specific Version
65+
1. Run the script.
66+
2. Select the option to search for a specific version.
67+
3. Enter the task name.
68+
4. Provide values for `Major`, `Minor`, and `Patch`.
69+
5. When prompted, choose whether to display release information (enter 'y' or 'n').
70+
6. If any parameter is missing, the script displays an error and exits.
71+
7. If all parameters are provided, the script searches for the exact version and displays the result, including release info if selected.
72+
73+
#### Error Handling
74+
- If the task name is empty, the script displays an error:
75+
```
76+
Task name cannot be empty. Please provide a valid task name.
77+
```
78+
79+
- If the task does not exist, the script displays an error:
80+
```
81+
Task not found: <TaskName>. Please check the task name and try again.
82+
```
83+
84+
- If any version parameter (`Major`, `Minor`, or `Patch`) is missing during a search, the script displays an error:
85+
```
86+
All parameters (Major, Minor, Patch) are required for search. Please provide valid values.
87+
```
88+
89+
## Notes
90+
- Ensure the `task.json` file exists in the `Tasks/<TaskName>/` directory.
91+
- The script requires PowerShell to run.
92+
- Release Information is only available in search mode.
93+
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
param(
2+
[string]$TaskName,
3+
[string]$Version,
4+
[switch]$ShowRelease
5+
)
6+
7+
<#
8+
.SYNOPSIS
9+
List all unique versions of an Azure Pipelines task and show the commit link for each version, or search for a particular version.
10+
.DESCRIPTION
11+
This script scans the git history of a task's task.json file and outputs all unique versions found, sorted in version order.
12+
It provides clickable commit links if a remote is set, or commit hashes otherwise.
13+
You can choose to see all versions or search for a particular version.
14+
Output is shown as a table for easy reading.
15+
.PARAMETER TaskName
16+
The name of the task (e.g., CopyFilesV2)
17+
.EXAMPLE
18+
pwsh ./Find-FirstTaskVersionCommit.ps1
19+
#>
20+
function Show-ErrorAndExit($msg) {
21+
Write-Host "[ERROR] $msg" -ForegroundColor Red
22+
exit 1
23+
}
24+
25+
# Only prompt for parameters if not provided
26+
if (-not $TaskName) {
27+
Write-Host "" # Add spacing
28+
Write-Host "View (A)ll versions of a task, or (S)earch for a particular version" -ForegroundColor Cyan
29+
$action = Read-Host 'Enter "A" for all, or "S" for search'
30+
if ($action -notin @('A', 'a', 'S', 's')) {
31+
Show-ErrorAndExit "Invalid action. Please enter 'A' for all versions or 'S' for search."
32+
}
33+
$TaskName = Read-Host 'Enter the task name (e.g CopyFilesV2)'
34+
if($TaskName -eq '') {
35+
Show-ErrorAndExit "Task name cannot be empty. Please provide a valid task name."
36+
}
37+
$searchMode = $action -eq 's'
38+
if ($searchMode) {
39+
Write-Host "" # Add spacing
40+
$Major = Read-Host 'Enter the Major version number'
41+
$Minor = Read-Host 'Enter the Minor version number'
42+
$Patch = Read-Host 'Enter the Patch version number'
43+
$showReleaseInput = Read-Host 'Do you want to show the release tag? (Y/N)'
44+
if ($showReleaseInput -match '^(y|yes)$') {
45+
$ShowRelease = $true
46+
} else {
47+
$ShowRelease = $false
48+
}
49+
}
50+
} else {
51+
$searchMode = $false
52+
if ($Version) {
53+
$searchMode = $true
54+
$versionParts = $Version -split '\.'
55+
if ($versionParts.Length -eq 3) {
56+
$Major = $versionParts[0]
57+
$Minor = $versionParts[1]
58+
$Patch = $versionParts[2]
59+
} else {
60+
Show-ErrorAndExit "Version must be in the format Major.Minor.Patch (e.g., 2.252.0)"
61+
}
62+
}
63+
}
64+
65+
$TaskJsonPath = "../../Tasks/${TaskName}/task.json"
66+
if (-not (Test-Path $TaskJsonPath)) {
67+
Show-ErrorAndExit "Task not found: $TaskName. Please check the task name and try again."
68+
}
69+
70+
# Try to get the remote URL for link generation
71+
$remoteUrl = git remote get-url origin 2>$null
72+
if ($remoteUrl) {
73+
if ($remoteUrl -like 'git@*') {
74+
$remoteUrl = $remoteUrl -replace ':', '/' -replace 'git@', 'https://'
75+
$remoteUrl = $remoteUrl -replace '.git$', ''
76+
} elseif ($remoteUrl -like 'http*') {
77+
$remoteUrl = $remoteUrl -replace '.git$', ''
78+
}
79+
}
80+
81+
$commits = git log --format="%H" -- $TaskJsonPath
82+
if (-not $commits) {
83+
Show-ErrorAndExit "No git history found for $TaskJsonPath. Please ensure Task exists"
84+
}
85+
86+
$versions = @{}
87+
foreach ($commit in $commits) {
88+
$content = git show "${commit}:$TaskJsonPath" 2>$null
89+
if ($content) {
90+
try {
91+
$json = $content | ConvertFrom-Json
92+
$ver = "$($json.version.Major).$($json.version.Minor).$($json.version.Patch)"
93+
if (-not $versions.ContainsKey($ver)) {
94+
$commitInfo = git show -s --format="%an" $commit
95+
$commitDateRaw = git show -s --format="%ad" --date=iso $commit
96+
$commitDate = (Get-Date $commitDateRaw).ToString('dd-MM-yyyy')
97+
$commitUrl = $remoteUrl ? "$remoteUrl/commit/$commit" : $commit
98+
$versions[$ver] = [PSCustomObject]@{
99+
Version = $ver
100+
LinkOrCommit = $commitUrl
101+
Date = $commitDate
102+
Author = $commitInfo
103+
CommitHash = $commit
104+
}
105+
}
106+
} catch {
107+
Write-Host "[WARN] Could not parse JSON for commit $commit. Skipping." -ForegroundColor DarkYellow
108+
}
109+
}
110+
}
111+
112+
# Function to get the release tag(s) for a given commit
113+
function Get-ReleaseTagsForCommit($commitHash) {
114+
$tags = git tag --contains $commitHash 2>$null
115+
if ($tags) {
116+
$sortedTags = $tags | Sort-Object { [int]$_ } -ErrorAction SilentlyContinue
117+
return $sortedTags[0]
118+
} else {
119+
return $null
120+
}
121+
}
122+
123+
if ($versions.Count -eq 0) {
124+
Show-ErrorAndExit "No valid versions found for ${TaskName}."
125+
}
126+
127+
# Build $table in commit order (latest first, no need to sort)
128+
$table = @()
129+
foreach ($commit in $commits) {
130+
$ver = $null
131+
if ($versions.ContainsKey($commit)) {
132+
# Should never happen, but skip if duplicate
133+
continue
134+
}
135+
# Find the version for this commit
136+
foreach ($v in $versions.Keys) {
137+
if ($versions[$v].LinkOrCommit -like "*${commit}") {
138+
$ver = $v
139+
break
140+
}
141+
}
142+
if ($ver) {
143+
$row = $versions[$ver].PSObject.Copy()
144+
# If LinkOrCommit is a URL, make it a clickable hyperlink with text as the full commit hash
145+
if ($row.LinkOrCommit -match '^https?://') {
146+
$commitHash = $row.LinkOrCommit -replace '^.*\/([^\/]+)$', '$1'
147+
$row.LinkOrCommit = "`e]8;;$($row.LinkOrCommit)`e\$commitHash`e]8;;`e\"
148+
}
149+
$table += $row
150+
}
151+
}
152+
153+
# If user provided a version, check if it ever existed
154+
if ($searchMode) {
155+
# Enforce all parameters for search
156+
if (-not $Major -or -not $Minor -or -not $Patch) {
157+
Show-ErrorAndExit "All parameters (Major, Minor, Patch) are required for search. Please provide valid values."
158+
}
159+
160+
# If Major, Minor, and Patch are provided, search for that specific version
161+
if ($Major -and $Minor -and $Patch) {
162+
Write-Host "" # Add spacing
163+
Write-Host "[INFO] Searching for version $Major.$Minor.$Patch..." -ForegroundColor Yellow
164+
Write-Host "" # Add spacing
165+
$inputVersion = "$Major.$Minor.$Patch"
166+
if ($versions.ContainsKey($inputVersion)) {
167+
$row = $versions[$inputVersion].PSObject.Copy()
168+
# If LinkOrCommit is a URL, make it a clickable hyperlink with text as the full commit hash
169+
if ($row.LinkOrCommit -match '^https?://') {
170+
$commitHash = $row.LinkOrCommit -replace '^.*\/([^\/]+)$', '$1'
171+
$row.LinkOrCommit = "`e]8;;$($row.LinkOrCommit)`e\$commitHash`e]8;;`e\"
172+
}
173+
Write-Host "[SUCCESS] Version $inputVersion existed." -ForegroundColor Green
174+
Write-Host "" # Add spacing
175+
$row | Format-Table Version, LinkOrCommit, Date, Author
176+
if ($ShowRelease) {
177+
$commitHash = $row.CommitHash
178+
$releaseTag = Get-ReleaseTagsForCommit $commitHash
179+
if ($releaseTag) {
180+
if ($remoteUrl) {
181+
$releaseUrl = "$remoteUrl/releases/tag/$releaseTag"
182+
Write-Host "This version is part of release: $releaseTag" -ForegroundColor Green
183+
Write-Host "Release link: $releaseUrl" -ForegroundColor Cyan
184+
} else {
185+
Write-Host "This version is part of release: $releaseTag" -ForegroundColor Green
186+
}
187+
} else {
188+
Write-Host "No release tag found for this version." -ForegroundColor Yellow
189+
}
190+
}
191+
} else {
192+
Write-Host "Version $inputVersion does not exist for ${TaskName}." -ForegroundColor Red
193+
Write-Host "" # Add spacing
194+
Write-Host "[INFO] Valid versions for ${TaskName}:" -ForegroundColor Cyan
195+
$table | Format-Table Version, LinkOrCommit, Date, Author
196+
}
197+
}
198+
}
199+
# If no search mode, just show all unique versions
200+
else
201+
{
202+
Write-Host "" # Add spacing
203+
Write-Host "[INFO] All unique versions found for ${TaskName} (latest first):" -ForegroundColor Cyan
204+
$table | Format-Table Version, LinkOrCommit, Date, Author
205+
}

0 commit comments

Comments
 (0)