Azure DevOps PowerShell Scripts - List all release definitions and dependant builds

Thursday, 17 June 2021

Azure Pipelines logo It’s easy to open a specific release definition in the Azure DevOps web UI to find out what builds it references, but you can’t do the opposite - open a build to see which release definitions rely on it.

Last time we got a list of Azure Pipelines Release Definitions. Let’s go the next step and match up the builds that are being consumed by each release definition. With this list, we can now filter down to a build and find which releases use it.

See Personal access tokens for instructions on how to create the personal access token.

param (
    [string] $organisation,
    [string] $personalAccessToken
)

$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))
$headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$result = Invoke-RestMethod -Uri "https://dev.azure.com/$organisation/_apis/projects?api-version=6.0" -Method Get -Headers $headers

$projectNames = $result.value.name

$projectNames | ForEach-Object {
    $project = $_

    $result = Invoke-RestMethod -Uri "https://vsrm.dev.azure.com/$organisation/$project/_apis/release/definitions?api-version=6.1-preview.4&`$expand=artifacts" -Method Get -Headers $headers

    $result.value | Select-Object name, 
        @{ Name = "Url"; Expression = { $_._links.web.href }},
        @{ Name="Artifacts"; Expression= { $_.artifacts.alias }}, 
        @{ Name="artifactSourceDefinitionUrl"; Expression= { $_.artifacts.definitionReference.artifactSourceDefinitionUrl.id }}
}

This script also makes use of the Definitions - List REST API. This time we’re requesting the artifacts property to be included in the results. It is this property that contains information about builds and their artifacts that are being consumed by the release definition.

Azure DevOps PowerShell Scripts - List all release definitions

Friday, 11 June 2021

Azure Pipelines logo If you want to list all the Azure Pipelines Release Definitions for all projects in an Azure DevOps organisation, this script will return a list of their names, the date of the latest release and a link to view the definition within the web UI.

Note that Release definitions are part of the “classic” release pipelines. If you’re using YAML-based deployments then those will be viewable via the Pipelines script.

See Personal access tokens for instructions on how to create the personal access token.

param (
    [string] $organisation,
    [string] $personalAccessToken
)

$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))
$headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$result = Invoke-RestMethod -Uri "https://dev.azure.com/$organisation/_apis/projects?api-version=6.0" -Method Get -Headers $headers

$projectNames = $result.value.name

$projectNames | ForEach-Object {
    $project = $_

    $result = Invoke-RestMethod -Uri "https://vsrm.dev.azure.com/$organisation/$project/_apis/release/definitions?api-version=6.1-preview.4&`$expand=lastRelease" -Method Get -Headers $headers

    $result.value | Select-Object name, @{ Name="CreatedOn"; Expression= { $_.lastRelease.createdOn }}, @{ Name = "Url"; Expression = { $_._links.web.href }}
} | Sort-Object 

It makes use of the Definitions - List REST API. Note that the documentation for that API is slightly misleading in the examples. You do need to pass in $expand=lastRelease to get the lastRelease property populated.

Azure DevOps PowerShell Scripts - List all Azure Pipelines

Thursday, 10 June 2021

Azure Pipelines logo If you want to list all the Azure Pipelines for all projects in an Azure DevOps organisation, this script will return a list of their names.

See Personal access tokens for instructions on how to create the personal access token.

param (
    [string] $organisation,
    [string] $personalAccessToken
)

$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))
$headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$result = Invoke-RestMethod -Uri "https://dev.azure.com/$organisation/_apis/projects?api-version=6.0" -Method Get -Headers $headers

$projectNames = $result.value.name

$projectNames | ForEach-Object {
    $project = $_

    $result = Invoke-RestMethod -Uri "https://dev.azure.com/$organisation/$project/_apis/pipelines?api-version=6.0-preview.1" -Method Get -Headers $headers

    $result.value.name
} | Sort-Object

It makes use of the Pipelines - List REST API, so you could ask for any of the other properties instead of or in addition to name as well.

Azure DevOps PowerShell Scripts - List all Git repositories

Wednesday, 9 June 2021

Azure Repos logo If you want to list all the Git repositories for all projects in an Azure DevOps organisation, this script will return all the remote URLs.

See Personal access tokens for instructions on how to create the personal access token.

param (
    [string] $organisation,
    [string] $personalAccessToken
)

$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($personalAccessToken)"))
$headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)}

$result = Invoke-RestMethod -Uri "https://dev.azure.com/$organisation/_apis/projects?api-version=6.0" -Method Get -Headers $headers

$projectNames = $result.value.name

$projectNames | ForEach-Object {
    $project = $_

    $result = Invoke-RestMethod -Uri "https://dev.azure.com/$organisation/$project/_apis/git/repositories?api-version=6.0" -Method Get -Headers $headers

    $result.value.remoteUrl
} | Sort-Object

It makes use of the Repositories - List REST API, so you could ask for any of the other properties instead of or in addition to remoteUrl as well.

Using GitHub Actions to update packages.lock.json for Dependabot PRs

Thursday, 27 May 2021

I like using Dependabot to keep my package dependencies up to date. But it does have one problem if you’re using packages.lock.json files with NuGet packages - it doesn’t update them. So your csproj will be modified but the packages.lock.json file won’t, which can lead to broken failing.

Build failure

Here’s one approach to working around this. Hopefully GitHub will fix this properly in the future.

ChatOps

I’m going to make use of Peter Evans’ Slash Command Dispatch GitHub Action to enable triggering by entering /lockfiles as a comment on the pull request. This action is extensible and can be used to create all kinds of ‘slash’ commands.

First up, I created a new workflow that uses this action:

name: Slash Command Dispatch
on:
  issue_comment:
    types: [created]
jobs:
  slashCommandDispatch:
    runs-on: ubuntu-latest
    steps:

      - uses: xt0rted/[email protected]
        id: comment-branch

      - name: Slash Command Dispatch
        uses: peter-evans/[email protected]
        id: slash-command
        with:
          token: $
          commands: |
            lockfiles
          permission: write
          issue-type: pull-request
          dispatch-type: workflow
          static-args: ref=$

Things to note:

The second workflow is named lockfiles-command.yml. It needs to follow the convention of commandname-command.yml.

name: Update lockfiles
on:
  workflow_dispatch:

jobs:
  lockfiles:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/[email protected]
        with:
          fetch-depth: 0
          token: $

      - name: Setup .NET 5
        uses: actions/[email protected]
        with:
          dotnet-version: 5.0.x

      - name: Restore dependencies
        run: dotnet restore --force-evaluate

      - uses: stefanzweifel/[email protected]
        with:
          commit_message: Update lockfiles

Things to note:

To trigger the workflow, add a new comment to a pull request with /lockfiles. eg.

GitHub pull request comment

You can see a complete repo with example pull request over at https://github.com/flcdrg/dependabot-lockfiles/pull/1

Future ideas

It could be possible to have this workflow trigger automatically after Dependabot creates the pull request if you wanted to completely automate this approach, rather than needing to add the comment manually.