Skip to content

Azure Pipelines

Azure Pipelines Tips🔗

Create a link to a pipeline for your chatops.

$button = "${ENV:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${ENV:SYSTEM_TEAMPROJECT}/_build/results?buildId=$($ENV:BUILD_BUILDID)&view=logs"

Helper Function for Reporting Progress on Task🔗

This is an ugly function, but hopefully useful as a jump start when in a hurry. 😁

This primarily allows you to quickly report:

  • ETA
  • Percent complete on a task
  • Log output on current task

Needs more refinement and probably should just be an invoke build function, but for now it's semi-useful for some long-running tasks

Setup up your variables like demonstrated. This doesn't handle nested task creation, so parentid won't be useful for anything other than local progress bar nesting.

$ProgressId =  [int]$RANDOM.Next(1, 1000)
$ProgressCounter = 0
$ProgressTotalToProcess = 1000
$ProgressStopwatch =  [diagnostics.stopwatch]::new()
$ProgressStopwatch.Start()
foreach ($i in $List.Items)
{
    $ProgressCounter++
        $ProgressSplat = @{
        Activity       =  '>>> Tacos'
        StatusMessage  =  "$($i.Foo).$($i.Bar)"
        ProgressId     =  $ProgressId
        Counter        =  $Counter
        TotalToProcess =  $ProgressTotalToProcess
        Stopwatch      =  $ProgressStopwatch
        # ParentId       =  $ParentProgressId
        BuildOutput    = $true # for write-host special commands to show task progress in pipelines
    }
    Write-BuildProgressInfo @ProgressSplat
}

Include this function in InvokeBuild job. If not using InvokeBuild, you'll need to change Write-Build to Write-Host and remove the color attribute.

function Write-BuildProgressInfo
{
    [cmdletbinding()]
    param(
        [string]$Activity='doing stuff',
        [string]$StatusMessage,
        [int]$ProgressId,
        [int]$Counter,
        [int]$TotalToProcess,
        $StopWatch,
        $ParentId,
        [switch]$Complete,
        [switch]$BuildOutput
    )
    [hashtable]$writeProgressSplat = @{}
    $writeProgressSplat.Add('Id', $ProgressId)
    $writeProgressSplat.Add('Activity'  , $Activity)
    if ($ParentId)
    {
        $writeProgressSplat.Add('ParentId', $ParentId )
    }

    # Write-Debug($PSBoundParameters.GetEnumerator() | Format-Table -AutoSize| Out-String)
    if ($Counter -lt $TotalToProcess -and $Complete -eq $false)
    {
        #still processing
        [int]$PercentComplete = [math]::Ceiling(($counter/$TotalToProcess)*100)
        try { [int]$AvgTimeMs = [math]::Ceiling(($StopWatch.ElapsedMilliseconds / $counter)) } catch { [int]$AvgTimeMs=0 } #StopWatch from beginning of process

        [int]$RemainingTimeSec = [math]::Ceiling( ($TotalToProcess - $counter) * $AvgTimeMs/1000)
        [string]$Elapsed = '{0:hh\:mm\:ss}' -f $StopWatch.Elapsed

        $writeProgressSplat.Add('Status', ("Batches: ($counter of $TotalToProcess) | Average MS: $($AvgTimeMs)ms | Elapsed Secs: $Elapsed | $($StatusMessage)"))
        $writeProgressSplat.Add('PercentComplete', $PercentComplete)
        $writeProgressSplat.Add('SecondsRemaining', $RemainingTimeSec)
        Write-Progress @writeProgressSplat
        if ($BuildOutput)
        {
            Write-Build DarkGray ("$Activity | $PercentComplete | ETA: $('{0:hh\:mm\:ss\.fff}' -f [timespan]::FromSeconds($RemainingTimeSec)) |  Batches: ($counter of $TotalToProcess) | Average MS: $($AvgTimeMs)ms | Elapsed Secs: $Elapsed | $($StatusMessage)")
            Write-Build DarkGray "##vso[task.setprogress value=$PercentComplete;]$Activity"
        }
    }
    else
    {
        [int]$PercentComplete = 100
        try { [int]$AvgTimeMs = [math]::Ceiling(($StopWatch.ElapsedMilliseconds / $TotalToProcess)) } catch { [int]$AvgTimeMs=0 } #StopWatch from beginning of process
        [string]$Elapsed = '{0:hh\:mm\:ss}' -f $StopWatch.Elapsed

        $writeProgressSplat.Add('Completed', $true)
        $writeProgressSplat.Add('Status', ("Percent Complete: 100% `nAverage MS: $($AvgTimeMs)ms`nElapsed: $Elapsed"))
        Write-Progress @writeProgressSplat
        if ($BuildOutput)
        {
            Write-Build DarkGray ("COMPLETED | $Activity | $PercentComplete | ETA: $('{0:hh\:mm\:ss\.fff}' -f $RemainingTimeSec) |  Batches: ($counter of $TotalToProcess) | Average MS: $($AvgTimeMs)ms | Elapsed Secs: $Elapsed | $($StatusMessage)")
        }
    }
}