mirror of
https://dev.azure.com/effectory/Survey%20Software/_git/Cloud%20Engineering
synced 2026-02-27 18:52:18 +01:00
added documetation
This commit is contained in:
@@ -1,41 +1,144 @@
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Analyzes Azure DevOps repositories to identify which have 'test' and 'accept' branches and their last activity.
|
||||
|
||||
.DESCRIPTION
|
||||
This script retrieves all repositories from an Azure DevOps project and analyzes each one to determine:
|
||||
- Basic repository information (ID, name, default branch, status, URL)
|
||||
- Last commit activity on the default branch
|
||||
- Whether a 'test' branch exists and its last commit activity
|
||||
- Whether an 'accept' branch exists and its last commit activity
|
||||
|
||||
This is commonly used in development workflows where 'test' and 'accept' branches represent
|
||||
specific deployment environments or approval stages in the development pipeline.
|
||||
|
||||
.PARAMETER Token
|
||||
The Azure DevOps Personal Access Token (PAT) used for authentication. This token must have
|
||||
'Code (Read)' permissions to access repository and commit information.
|
||||
|
||||
.PARAMETER Organization
|
||||
The Azure DevOps organization name. Defaults to "effectory" if not specified.
|
||||
|
||||
.PARAMETER Project
|
||||
The Azure DevOps project name. Defaults to "Survey Software" if not specified.
|
||||
|
||||
.EXAMPLE
|
||||
.\RepositoriesWithTestAccept.ps1 -Token "your-personal-access-token"
|
||||
|
||||
Analyzes repositories using the default organization and project settings.
|
||||
|
||||
.EXAMPLE
|
||||
.\RepositoriesWithTestAccept.ps1 -Token "your-pat-token" -Organization "myorg" -Project "MyProject"
|
||||
|
||||
Analyzes repositories for a specific organization and project.
|
||||
|
||||
.OUTPUTS
|
||||
Creates a timestamped CSV file in the current directory with the format: "yyyy-MM-dd HHmm repositories with test and accept.csv"
|
||||
The CSV contains the following columns:
|
||||
- Id: Repository unique identifier
|
||||
- Name: Repository name
|
||||
- DefaultBranch: Repository default branch (e.g., main, master)
|
||||
- IsDisabled: Boolean indicating if the repository is disabled
|
||||
- WebUrl: Repository web URL in Azure DevOps
|
||||
- LastDefaultChange: Date of last commit on the default branch
|
||||
- HasTest: Boolean indicating if a 'test' branch exists (True/False)
|
||||
- LastTestChange: Date of last commit on the 'test' branch (empty if branch doesn't exist)
|
||||
- HasAccept: Boolean indicating if an 'accept' branch exists (True/False)
|
||||
- LastAcceptChange: Date of last commit on the 'accept' branch (empty if branch doesn't exist)
|
||||
|
||||
.NOTES
|
||||
Author: Cloud Engineering Team
|
||||
Created: 2025
|
||||
Requires: PowerShell 5.1 or later, Azure CLI installed and authenticated
|
||||
Dependencies: Azure CLI (az) for repository listing, Azure DevOps REST API for commit information
|
||||
|
||||
Prerequisites:
|
||||
- Install Azure CLI: https://docs.microsoft.com/en-us/cli/azure/install-azure-cli
|
||||
- Authenticate: az login
|
||||
- Azure DevOps Personal Access Token with Code (Read) permissions
|
||||
|
||||
The script uses both Azure CLI commands and REST API calls:
|
||||
- Azure CLI for listing repositories
|
||||
- REST API for checking branch existence and commit history
|
||||
|
||||
Branch Analysis:
|
||||
- 'test' branch: Often used for testing environment deployments
|
||||
- 'accept' branch: Often used for acceptance testing or staging environments
|
||||
- Default branch: Usually 'main' or 'master', represents the primary development branch
|
||||
|
||||
Error Handling:
|
||||
- If a branch doesn't exist, the API call will fail and the branch is marked as non-existent
|
||||
- Disabled repositories are processed but branch analysis is skipped
|
||||
- Network or authentication errors are handled gracefully
|
||||
|
||||
.LINK
|
||||
https://docs.microsoft.com/en-us/rest/api/azure/devops/git/commits/get-commits
|
||||
#>
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory = $true, HelpMessage = "Azure DevOps Personal Access Token with Code (Read) permissions")]
|
||||
[string]$Token,
|
||||
|
||||
[Parameter(Mandatory = $false, HelpMessage = "Azure DevOps organization name")]
|
||||
[string]$Organization = "effectory",
|
||||
|
||||
[Parameter(Mandatory = $false, HelpMessage = "Azure DevOps project name")]
|
||||
[string]$Project = "Survey Software"
|
||||
)
|
||||
|
||||
# Define a class to structure repository information with branch analysis
|
||||
class Repository {
|
||||
[string] $Id = ""
|
||||
[string] $Name = ""
|
||||
[string] $DefaultBranch = ""
|
||||
[string] $IsDisabled = ""
|
||||
[string] $WebUrl = ""
|
||||
[string] $LastDefaultChange = ""
|
||||
[string] $HasTest = ""
|
||||
[string] $LastTestChange = ""
|
||||
[string] $HasAccept = ""
|
||||
[string] $LastAcceptChange = ""
|
||||
[string] $Id = "" # Repository unique identifier
|
||||
[string] $Name = "" # Repository display name
|
||||
[string] $DefaultBranch = "" # Repository default branch (e.g., main, master)
|
||||
[string] $IsDisabled = "" # Whether the repository is disabled (True/False)
|
||||
[string] $WebUrl = "" # Repository web URL in Azure DevOps
|
||||
[string] $LastDefaultChange = "" # Date of last commit on default branch
|
||||
[string] $HasTest = "" # Whether 'test' branch exists (True/False)
|
||||
[string] $LastTestChange = "" # Date of last commit on 'test' branch
|
||||
[string] $HasAccept = "" # Whether 'accept' branch exists (True/False)
|
||||
[string] $LastAcceptChange = "" # Date of last commit on 'accept' branch
|
||||
}
|
||||
|
||||
# Initialize variables for API calls
|
||||
[string] $url = ""
|
||||
[string] $repositoryId = ""
|
||||
[string] $branchName = ""
|
||||
|
||||
# Generate timestamped filename for the output CSV
|
||||
[string] $date = Get-Date -Format "yyyy-MM-dd HHmm"
|
||||
$fileName = ".\$date repositories with test and accept.csv"
|
||||
|
||||
[string] $token = "yixqmupncd3b72zij4y5lfsenepak5rtvlba3sj33tvxvc4s7a6q" #"{INSERT_PERSONAL_ACCESS_TOKEN}"
|
||||
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($token)"))
|
||||
$head = @{ Authorization =" Basic $token" }
|
||||
[string] $organization = "effectory"
|
||||
[string] $project = "Survey%20Software"
|
||||
# Prepare authentication for Azure DevOps REST API calls
|
||||
# Personal Access Token must be base64 encoded with a colon prefix
|
||||
$encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($Token)"))
|
||||
$head = @{ Authorization =" Basic $encodedToken" }
|
||||
|
||||
# URL-encode the project name for API calls
|
||||
$projectEncoded = $Project -replace " ", "%20"
|
||||
|
||||
# Display script execution banner
|
||||
Write-Host "========================================================================================================================================================================"
|
||||
Write-Host "Creating repository overview."
|
||||
Write-Host "Analyzing repositories for 'test' and 'accept' branches"
|
||||
Write-Host "Organization: $Organization, Project: $Project"
|
||||
Write-Host "Output file: $fileName"
|
||||
Write-Host "========================================================================================================================================================================"
|
||||
|
||||
$repos = az repos list --organization "https://dev.azure.com/$organization/" --project "survey software" | ConvertFrom-Json | Select-Object
|
||||
# Retrieve all repositories from the Azure DevOps project
|
||||
Write-Host "Fetching repositories from project '$Project'..." -ForegroundColor Yellow
|
||||
$repos = az repos list --organization "https://dev.azure.com/$Organization/" --project "$Project" | ConvertFrom-Json | Select-Object
|
||||
Write-Host "Found $($repos.Count) repositories" -ForegroundColor Green
|
||||
|
||||
# Initialize array to store repository analysis results
|
||||
[Repository[]]$Result = @()
|
||||
|
||||
# Process each repository to analyze branch structure and activity
|
||||
foreach ($repo in $repos)
|
||||
{
|
||||
Write-Host $repo.name
|
||||
Write-Host "Analyzing repository: $($repo.name)" -ForegroundColor Cyan
|
||||
|
||||
# Create new repository object and populate basic information
|
||||
[Repository] $repository = [Repository]::new()
|
||||
$repository.Id = $repo.id
|
||||
$repository.Name = $repo.name
|
||||
@@ -43,50 +146,96 @@ foreach ($repo in $repos)
|
||||
$repository.IsDisabled = $repo.isDisabled
|
||||
$repository.WebUrl = $repo.webUrl
|
||||
|
||||
# Only analyze branches for active repositories
|
||||
if ($true -ne $repo.isDisabled)
|
||||
{
|
||||
$repositoryId = $repo.id
|
||||
|
||||
# Analyze default branch activity
|
||||
$branchName = $repo.defaultBranch
|
||||
$branchName = $branchName.Replace("refs/heads/", "")
|
||||
Write-Host " Checking default branch: $branchName" -ForegroundColor Gray
|
||||
|
||||
try {
|
||||
$url="https://dev.azure.com/$organization/$project/_apis/git/repositories/$repositoryId/commits?searchCriteria.itemVersion.version=$branchName&searchCriteria.`$top=1&api-version=6.0"
|
||||
$url="https://dev.azure.com/$Organization/$projectEncoded/_apis/git/repositories/$repositoryId/commits?searchCriteria.itemVersion.version=$branchName&searchCriteria.`$top=1&api-version=6.0"
|
||||
$response = Invoke-RestMethod -Uri $url -Method GET -Headers $head
|
||||
$repository.LastDefaultChange = $response.value[0].committer.date
|
||||
Write-Host " Last commit: $(Get-Date $response.value[0].committer.date -Format 'yyyy-MM-dd HH:mm')" -ForegroundColor Gray
|
||||
}
|
||||
catch {
|
||||
Write-Host " No commits found or branch inaccessible" -ForegroundColor Yellow
|
||||
$repository.LastDefaultChange = ""
|
||||
}
|
||||
|
||||
# Check for 'test' branch existence and activity
|
||||
Write-Host " Checking for 'test' branch..." -ForegroundColor Gray
|
||||
try {
|
||||
$branchName = "test"
|
||||
$url="https://dev.azure.com/$organization/$project/_apis/git/repositories/$repositoryId/commits?searchCriteria.itemVersion.version=$branchName&searchCriteria.`$top=1&api-version=6.0"
|
||||
$url="https://dev.azure.com/$Organization/$projectEncoded/_apis/git/repositories/$repositoryId/commits?searchCriteria.itemVersion.version=$branchName&searchCriteria.`$top=1&api-version=6.0"
|
||||
$response = Invoke-RestMethod -Uri $url -Method GET -Headers $head
|
||||
$repository.HasTest = "True"
|
||||
$repository.LastTestChange = $response.value[0].committer.date
|
||||
Write-Host " 'test' branch found - Last commit: $(Get-Date $response.value[0].committer.date -Format 'yyyy-MM-dd HH:mm')" -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
$repository.HasTest = "False"
|
||||
$repository.LastTestChange = ""
|
||||
Write-Host " 'test' branch not found" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Check for 'accept' branch existence and activity
|
||||
Write-Host " Checking for 'accept' branch..." -ForegroundColor Gray
|
||||
try {
|
||||
$branchName = "accept"
|
||||
$url="https://dev.azure.com/$organization/$project/_apis/git/repositories/$repositoryId/commits?searchCriteria.itemVersion.version=$branchName&searchCriteria.`$top=1&api-version=6.0"
|
||||
$url="https://dev.azure.com/$Organization/$projectEncoded/_apis/git/repositories/$repositoryId/commits?searchCriteria.itemVersion.version=$branchName&searchCriteria.`$top=1&api-version=6.0"
|
||||
$response = Invoke-RestMethod -Uri $url -Method GET -Headers $head
|
||||
$repository.HasAccept = "True"
|
||||
$repository.LastAcceptChange = $response.value[0].committer.date
|
||||
Write-Host " 'accept' branch found - Last commit: $(Get-Date $response.value[0].committer.date -Format 'yyyy-MM-dd HH:mm')" -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
$repository.HasAccept = "False"
|
||||
$repository.LastAcceptChange = ""
|
||||
Write-Host " 'accept' branch not found" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host " Repository is disabled - skipping branch analysis" -ForegroundColor Yellow
|
||||
# Set default values for disabled repositories
|
||||
$repository.LastDefaultChange = ""
|
||||
$repository.HasTest = "N/A"
|
||||
$repository.LastTestChange = ""
|
||||
$repository.HasAccept = "N/A"
|
||||
$repository.LastAcceptChange = ""
|
||||
}
|
||||
|
||||
# Add repository to results array
|
||||
$Result += $repository
|
||||
}
|
||||
|
||||
$Result | Export-Csv -Path $fileName -Append -NoTypeInformation
|
||||
# Export results to CSV file
|
||||
$Result | Export-Csv -Path $fileName -NoTypeInformation
|
||||
|
||||
# Calculate and display summary statistics
|
||||
$totalRepos = $Result.Count
|
||||
$activeRepos = ($Result | Where-Object { $_.IsDisabled -ne "True" }).Count
|
||||
$disabledRepos = ($Result | Where-Object { $_.IsDisabled -eq "True" }).Count
|
||||
$reposWithTest = ($Result | Where-Object { $_.HasTest -eq "True" }).Count
|
||||
$reposWithAccept = ($Result | Where-Object { $_.HasAccept -eq "True" }).Count
|
||||
$reposWithBoth = ($Result | Where-Object { $_.HasTest -eq "True" -and $_.HasAccept -eq "True" }).Count
|
||||
|
||||
# Display completion summary
|
||||
Write-Host "========================================================================================================================================================================"
|
||||
Write-Host "Done."
|
||||
Write-Host "Branch analysis completed successfully!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "SUMMARY STATISTICS:" -ForegroundColor Cyan
|
||||
Write-Host "Total repositories: $totalRepos" -ForegroundColor Yellow
|
||||
Write-Host "Active repositories: $activeRepos" -ForegroundColor Yellow
|
||||
Write-Host "Disabled repositories: $disabledRepos" -ForegroundColor Yellow
|
||||
Write-Host "Repositories with 'test' branch: $reposWithTest" -ForegroundColor Yellow
|
||||
Write-Host "Repositories with 'accept' branch: $reposWithAccept" -ForegroundColor Yellow
|
||||
Write-Host "Repositories with both 'test' and 'accept' branches: $reposWithBoth" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host "Output file: $fileName" -ForegroundColor Yellow
|
||||
Write-Host "========================================================================================================================================================================"
|
||||
Reference in New Issue
Block a user