Skip to content

Instantly share code, notes, and snippets.

@rfennell
Last active May 16, 2025 13:41
Show Gist options
  • Save rfennell/45eef15772e0e676dc9e82cabd7d5ad0 to your computer and use it in GitHub Desktop.
Save rfennell/45eef15772e0e676dc9e82cabd7d5ad0 to your computer and use it in GitHub Desktop.
This script connects to an Azure DevOps organization and project using a Personal Access Token (PAT). It fetches all pipelines, gathers details about each pipeline (including type, source repository, branch, and latest run status), and exports the collected information to a CSV file.
<#
.SYNOPSIS
Retrieves Azure DevOps pipeline information and exports it to a CSV file.
.DESCRIPTION
This script connects to an Azure DevOps organization and project using a Personal Access Token (PAT).
It fetches all pipelines, gathers details about each pipeline (including type, source repository, branch, and latest run status),
and exports the collected information to a CSV file.
.PARAMETER organization
The name of the Azure DevOps organization. Default is "blackmarble-source".
.PARAMETER project
The name of the Azure DevOps project. Default is "bm".
.PARAMETER pat
The Personal Access Token (PAT) used for authentication with Azure DevOps REST API.
.PARAMETER outputCsv
The file path for the output CSV file. Default is "./azdo-pipelines.csv".
.NOTES
- Requires PowerShell and network access to Azure DevOps REST API.
- The PAT should have sufficient permissions to read pipelines and repositories.
- Handles both YAML and Classic pipelines.
- For YAML pipelines using Azure Repos Git, attempts to resolve the repository URL via the Azure DevOps API.
.EXAMPLE
.\get-azdo-builds.ps1 -organization "my-org" -project "my-project" -pat "my-pat" -outputCsv "./pipelines.csv"
Retrieves pipeline information from the specified Azure DevOps organization and project, and exports it to "pipelines.csv".
#>
# Azure DevOps organization and project details
param(
[string]$organization,
[string]$project,
[string]$pat,
[string]$outputCsv
)
# Base64-encode the PAT for authentication
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat"))
# Get all pipelines
$uri = "https://dev.azure.com/$organization/$project/_apis/pipelines?api-version=7.0"
Write-Host "Fetching list of pipelines from Azure DevOps..."
$pipelines = Invoke-RestMethod -Uri $uri -Headers @{Authorization = "Basic $base64AuthInfo"}
Write-Host ("Found {0} pipelines." -f $pipelines.count)
# Prepare an array to hold pipeline info
$pipelineInfoList = @()
foreach ($pipeline in $pipelines.value) {
$pipelineId = $pipeline.id
$pipelineName = $pipeline.name
Write-Host ("Processing pipeline: {0} (ID: {1})..." -f $pipelineName, $pipelineId)
# Get pipeline details (for repository info)
$pipelineDetailsUri = "https://dev.azure.com/$organization/$project/_apis/pipelines/$($pipelineId)?api-version=7.0"
$pipelineDetails = Invoke-RestMethod -Uri $pipelineDetailsUri -Headers @{Authorization = "Basic $base64AuthInfo"}
# Handle both YAML and Classic pipelines
$designerJsonRepo = $null
$repo = $null
$pipelineType = $null
if ($pipelineDetails.configuration.PSObject.Properties.Name -contains 'designerJson') {
$designerJson = $pipelineDetails.configuration.designerJson
if ($designerJson.PSObject.Properties.Name -contains 'repository') {
$designerJsonRepo = $designerJson.repository
$pipelineType = $designerJson.type
}
}
if ($pipelineDetails.configuration.PSObject.Properties.Name -contains 'repository') {
$repo = $pipelineDetails.configuration.repository
$pipelineType = 'yaml'
}
if ($designerJsonRepo) {
$sourceType = $designerJsonRepo.type
$sourceBranch = $designerJsonRepo.defaultBranch
$sourceUrl = $designerJsonRepo.url
} elseif ($repo) {
$sourceType = $repo.type
$sourceBranch = $repo.defaultBranch
# For YAML pipelines with Azure Repos Git, get the repo URL from the repo id
if ($sourceType -eq 'azurereposgit' -and $pipelineType -eq 'yaml') {
$repoId = $repo.id
# Call the Azure DevOps Repositories API to get the repo details
$repoApiUri = "https://dev.azure.com/$organization/$project/_apis/git/repositories/$($repoId)?api-version=7.0"
try {
$repoDetails = Invoke-RestMethod -Uri $repoApiUri -Headers @{Authorization = "Basic $base64AuthInfo"}
$sourceUrl = $repoDetails.webUrl
} catch {
$sourceUrl = 'Cannot resolve repo with ID ' + $repoId
}
} else {
$sourceUrl = $repo.url
}
} else {
$sourceType = ''
$sourceBranch = ''
$sourceUrl = ''
}
# Get latest run
$runsUri = "https://dev.azure.com/$organization/$project/_apis/pipelines/$($pipelineId)/runs?api-version=7.0&$top=1"
$runs = Invoke-RestMethod -Uri $runsUri -Headers @{Authorization = "Basic $base64AuthInfo"}
if ($runs.count -gt 0) {
$lastRun = $runs.value[0]
$lastRunTime = $lastRun.createdDate
$status = $lastRun.result
Write-Host (" Last run: {0} (Status: {1})" -f $lastRunTime, $status)
} else {
$lastRunTime = "Never"
$status = "N/A"
Write-Host " No runs found for this pipeline."
}
$pipelineInfo = [PSCustomObject]@{
"Pipeline Name" = $pipelineName
"Definition Id" = $pipelineId
"Pipeline Type" = $pipelineType
"Source Type" = $sourceType
"Source Branch" = $sourceBranch
"Source URL" = $sourceUrl
"Last Run Time" = $lastRunTime
"Status" = $status
}
$pipelineInfoList += $pipelineInfo
}
# Export to CSV
Write-Host "Exporting pipeline information to $outputCsv..."
$pipelineInfoList | Export-Csv -Path $outputCsv -NoTypeInformation -Encoding UTF8
Write-Host "Pipeline information exported to $outputCsv"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment