Skip to content

Instantly share code, notes, and snippets.

@wsmelton
Last active October 14, 2023 01:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wsmelton/975bd3dd2cc97f8d8b55d3d559d4485e to your computer and use it in GitHub Desktop.
Save wsmelton/975bd3dd2cc97f8d8b55d3d559d4485e to your computer and use it in GitHub Desktop.
PowerShell script to find code in Azure DevOps service
#requires -Version 7.2
<#
.SYNOPSIS
Azure DevOps REST API to get a results across an organization based on provided search text, just as you would in the web UI
.NOTES
https://learn.microsoft.com/en-us/rest/api/azure/devops/search/code-search-results/fetch-code-search-results?view=azure-devops-rest-7.1&tabs=HTTP#coderesult
Based on provided answer from SO: https://stackoverflow.com/a/64973447/12974596
.EXAMPLE
./Search-AzureDevOpsCode.ps1 -OrganizationName Company -Project Enterprise -SearchFilter "ext:yml AND somestringvalue" -AzAccessToken (Get-AzAccessToken)
Return results from Enterprise project in the Company organization
.EXAMPLE
./Search-AzureDevOpsCode.ps1 -OrganizationName Company -SearchFilter "ext:yml AND somestringvalue" -AzAccessToken (Get-AzAccessToken)
Return results from the Company organization, considering all projects
#>
[CmdletBinding()]
param (
# Organization Name for Azure DevOps tenant
[Parameter(Mandatory, Position = 0)]
[string]
$OrganizationName,
# Search filter, based on same filters allowed in the Web UI
# e.g., ext:yml AND somestringValue
[Parameter(Mandatory, Position = 2)]
$SearchFilter,
# Token object from Get-AzAccessToken
[Parameter(Mandatory, Position = 3)]
[Microsoft.Azure.Commands.Profile.Models.PSAccessToken]
$AzAccessToken,
# Project to search, optional.
# If not provided will perform search at the organization level
[string]
$Project
)
process {
$body = @{
searchText = $SearchFilter
'$top' = 1000
} | ConvertTo-Json
$header = @{
'Authorization' = "Bearer $($AzAccessToken.Token)"
}
$ProjectNames = if ([string]::IsNullOrEmpty($Project)) {
$irmParams = @{
Uri = "https://dev.azure.com/" + $OrganizationName + "/_apis/projects?api-version=5.1"
Method = 'GET'
ContentType = 'application/json'
Headers = $header
}
(Invoke-RestMethod @irmParams | Select-Object -ExpandProperty value).name
} else {
$Project
}
Write-Verbose "Projects to process: $($ProjectNames)"
$collection = @()
$ProjectNames | ForEach-Object {
Write-Verbose "Project: $($_)"
$currentProject = $_
$irmSearchParams = @{
Uri = "https://almsearch.dev.azure.com/$($OrganizationName)/$($currentProject)/_apis/search/codesearchresults?api-version=7.1-preview.1"
Method = 'POST'
ContentType = 'application/json'
Headers = $header
Body = $body
}
try {
(Invoke-RestMethod @irmSearchParams -ErrorAction Stop).results | ForEach-Object {
$collection += [pscustomobject]@{
project = $_.project.name
repository = $_.repository.name
repositoryType = $_.repository.type
version = $_.versions.branchName -join ','
fileName = $_.fileName
filePath = $_.path
}
}
} catch {
Write-Warning "Error occurred processing project: $($_.Exception.Message)"
}
}
}
end {
$collection
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment