functions/Publish-CodeOpsResultsToBlobStorage.ps1

function Publish-CodeOpsResultsToBlobStorage {
    [CmdletBinding(DefaultParameterSetName="sastoken")]
    param (
        [Parameter(Mandatory=$true)]
        [AllowEmptyString()]
        [string] $StorageAccountName,

        [Parameter(Mandatory=$true)]
        [AllowEmptyString()]
        [string] $ContainerName,

        [Parameter(Mandatory=$true)]
        [AllowEmptyString()]
        [string] $BlobPath,

        [Parameter(Mandatory=$true, ParameterSetName="sastoken")]
        [AllowEmptyString()]
        [string] $SasToken,

        [Parameter(Mandatory=$true)]
        [string] $JsonFilePath,

        [Parameter(Mandatory=$true)]
        [string] $Timestamp,

        [Parameter(ParameterSetName="aadauth")]
        [switch] $UseConnectedAccount,

        [Parameter(ParameterSetName="aadauth")]
        [int] $GeneratedSasTokenLifetimeMinutes = 5,

        [Parameter()]
        [switch] $WhatIf
    )

    # validate the JSON in the source file
    $jsonData = Get-Content -Raw $JsonFilePath | ConvertFrom-Json -Depth 100

    if ($PSCmdlet.ParameterSetName -eq "aadauth" -and $StorageAccountName -and $ContainerName) {
        Write-Host "Generating short-lived SAS storage token using current credentials [StorageAccount=$StorageAccountName] [Container=$ContainerName]"
        $ctx = New-AzStorageContext -StorageAccountName $StorageAccountName -UseConnectedAccount
        $SasToken = (New-AzStorageContainerSASToken -Context $ctx `
                        -Container $ContainerName `
                        -ExpiryTime (Get-Date).AddMinutes($GeneratedSasTokenLifetimeMinutes) `
                        -Permission rw)
    }

    if ($StorageAccountName -and $SasToken -and $ContainerName -and $BlobPath) {
        # name the file differently for real runs and dry runs
        $filename = $WhatIf ? "dryrun-$Timestamp.json" : "run-$Timestamp.json"

        Write-Information @"
Publishing storage account:
    Source File: $JsonFilePath
    Account: $StorageAccountName
    Blob Path: "$ContainerName/$BlobPath/$filename"
"@


        # The tooling that generates the SAS token is due to change such that it will no longer include
        # the leading '?' character in the returned SAS token. The use of TrimStart() will handle
        # either scenario and be more forgiving when the $SasToken parameter is supplied explicitly.
        $uri = "https://{0}.blob.core.windows.net/{1}/{2}/{3}?{4}" -f $StorageAccountName,
                                                                    $ContainerName,
                                                                    $BlobPath,
                                                                    $filename,
                                                                    $SasToken.TrimStart("?")
        $headers = @{
            "x-ms-date" = [System.DateTime]::UtcNow.ToString("R")
            "x-ms-blob-type" = "BlockBlob"
        }
        Invoke-RestMethod -Headers $headers `
                          -Uri $uri `
                          -Method PUT `
                          -Body ($jsonData | ConvertTo-Json -Depth 100 -Compress) `
                          -Verbose:$false | Out-Null
    }
    else {
        Write-Information "Publishing skipped, due to absent configuration"
    }
}