VsoLoggingCommands.psm1

$Script:PSModuleRoot = $PSScriptRoot
# ./home/vsts/work/1/s/VsoLoggingCommands/Classes/VsoState.ps1
enum VsoState {
    Unknown
    Initialized
    InProgress
    Completed
}

# ./home/vsts/work/1/s/VsoLoggingCommands/Classes/VsoResult.ps1
enum VsoResult {
    Succeeded
    SucceededWithIssues
    Failed
    Cancelled
    Skipped
}

# Importing from [/home/vsts/work/1/s/VsoLoggingCommands\Private]
# ./VsoLoggingCommands/Private/Write-Vso.ps1
function Write-Vso
{
    <#
        .Synopsis
        Writes a VSO logging message to the host

        .Example
        Write-Vso -Action task.logissue -Text $Text -Attributes @{
            type = 'error'
        }

        .Example
        Write-Vso task.logissue $Text @{
            type = 'error'
        }

        .Notes

    #>

    [Alias('VSO')]
    [cmdletbinding()]
    param(

        # VsoTask or action
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName
        )]
        [ValidateSet(
            'task.logissue',
            'task.setprogress',
            'task.complete',
            'task.logdetail',
            'task.setvariable',
            'task.setendpoint',
            'task.addattachment',
            'task.uploadsummary',
            'task.uploadfile',
            'task.prependpath',
            'artifact.associate',
            'artifact.upload',
            'build.uploadlog',
            'build.updatebuildnumber',
            'build.addbuildtag',
            'release.updatereleasename'
        )]
        [String]
        $Task,

        # Message to log
        [Parameter(
            Position = 1,
            ValueFromPipeline
        )]
        [String[]]
        $Text,

        # Command attributes
        [Parameter(
            Position = 2,
            ValueFromPipelineByPropertyName
        )]
        [Hashtable]
        $Attributes
    )

    process
    {
        try
        {
            $stringBuilder = [System.Text.StringBuilder]::new()

            [void]$stringBuilder.Append("##vso[$Task")

            foreach($key in $Attributes.keys)
            {
                if ( ![string]::IsNullOrEmpty( $Attributes[$key] ) )
                {
                    [void]$stringBuilder.Append((" {0}={1};" -f $key.ToLower(), $Attributes[$key] ) )
                }
            }

            [void]$stringBuilder.Append("]")

            $prefix = $stringBuilder.ToString()
            foreach ( $message in $Text )
            {
                Write-Information -MessageData ("{0}{1}" -f $prefix, $message) -InformationAction Continue -Tags VSO
            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# Importing from [/home/vsts/work/1/s/VsoLoggingCommands\Public]
# ./VsoLoggingCommands/Public/Add-VsoArtifactFile.ps1
function Add-VsoArtifactFile
{
    <#
        .Synopsis
        Upload local file into a file container folder, create artifact if artifactname provided.

        .Example
        Add-VsoArtifactFile -Path $Path -Name $ArtifactName -Folder $ContainerFolder

        .Notes

    #>

    [Alias('VsoArtifactFile')]
    [cmdletbinding()]
    param(
        # Path to file to add to artifact
        [Alias('FullName')]
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $Path,

        # container folder to use
        [Alias('ContainerFolder')]
        [Parameter(
            Mandatory,
            Position = 1,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Folder,

        # Name of the artifact
        [Alias('ArtifactName')]
        [Parameter(
            Position = 2,
            ValueFromPipelineByPropertyName
        )]
        [String]
        $Name

    )

    process
    {
        try
        {
            $Attrbiutes = @{
                ArtifactName    = $Name
                ContainerFolder = $Folder
            }

            foreach ( $node in $Path )
            {
                Write-Vso -Task artifact.upload -Text $node -Attributes $Attrbiutes
            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Add-VsoArtifactLink.ps1
function Add-VsoArtifactLink
{
    <#
        .Synopsis
        Create an artifact link

        .Example
        Add-VsoArtifactLink -Path $Path

        .Notes
        Create an artifact link, artifact location is required to be a file container path, VC path or UNC share path.
    #>

    [cmdletbinding()]
    param(
        # Artifact location
        [Alias('Path', 'FullName', 'Container', 'FilePath', 'VersionControl', 'GitRef', 'TfvcLabel')]
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Location,

        # Name of artifact
        [Parameter(
            Mandatory,
            Position = 1,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Name,

        # type of link
        [Parameter(
            Mandatory,
            Position = 1,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('container', 'filepath', 'versioncontrol', 'gitref', 'tfvclabel')]
        [String]
        $Type
    )

    process
    {
        try
        {
            $Attrbiutes = @{
                ArtifactName = $Name
                Type         = $Type
            }

            Write-Vso -Task artifact.associate -Text $Location -Attributes $Attrbiutes

        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Add-VsoAttachment.ps1
function Add-VsoAttachment
{
    <#
        .Synopsis
        Upload and attach attachment to current timeline record.

        .Example
        Add-VsoAttachment -Path $Path

        .Notes
        These files are not available for download with logs. These can only be referred to by extensions using the type or name values.
    #>

    [Alias('VsoAttachment')]
    [cmdletbinding()]
    param(
        # Path
        [Alias('FullName')]
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Path,

        # Friendly name
        [Alias('BaseName')]
        [Parameter(
            Mandatory,
            Position = 1,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Name,

        # Attachment Type
        [Alias('Extension')]
        [Parameter(
            Mandatory,
            Position = 2,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Type

    )

    process
    {
        try
        {
            $Attrbiutes = @{
                Type = $Type
                Name = $Name
            }

            Write-Vso -Task task.addattachment -Text $Path -Attributes $Attrbiutes
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Add-VsoFile.ps1
function Add-VsoFile
{
    <#
        .Synopsis
        Upload user interested file as additional log information to the current timeline record.

        .Example
        Add-VsoFile -Path $Path

        .Notes
        The file shall be available for download along with task logs.
    #>

    [Alias('VsoFile')]
    [cmdletbinding()]
    param(
        # File to upload
        [Alias('FullName')]
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $Path
    )

    process
    {
        try
        {
            foreach ( $node in $Path )
            {
                Write-Vso -Task build.uploadlog -Text $node
            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Add-VsoLogFile.ps1
function Add-VsoLogFile
{
    <#
        .Synopsis
        Upload user interested log to build’s container “logs\tool” folder.

        .Example
        Add-VsoLogFile -Path $Path

        .Notes

    #>

    [Alias('VsoLogFile')]
    [cmdletbinding()]
    param(
        # Parameter help description
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $Path
    )

    process
    {
        try
        {
            foreach ( $node in $Path )
            {
                Write-Vso -Task build.uploadlog -Text $node

            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Add-VsoPath.ps1
function Add-VsoPath
{
    <#
        .Synopsis
        Instruction for the agent to update the PATH environment variable

        .Example
        Add-VsoPath -Path $Path

        .Notes
        The specified directory is prepended to the PATH. The updated environment variable will be reflected in subsequent tasks.
    #>

    [cmdletbinding()]
    param(
        # value to prepend to ENV:PATH
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Path
    )

    process
    {
        try
        {
            Write-Vso -Task task.prependpath -Text $Path
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Add-VsoSummary.ps1
function Add-VsoSummary
{
    <#
        .Synopsis
        Add summary to status page

        .Example
        Add-VsoSummaryFile -Path $Path

        .Notes
        This needs to be a path to a markdown file
    #>

    [Diagnostics.CodeAnalysis.SuppressMessageAttribute(
        "PSAvoidDefaultValueForMandatoryParameter","",
        Justification="There are multiple parameter sets"
    )]
    [Alias('VsoSummary','Add-VsoSummaryFile')]
    [cmdletbinding(DefaultParameterSetName = 'Markdown')]
    param(
        # Path to markdown page to use for summary
        [Alias('FullName')]
        [Parameter(
            ValueFromPipelineByPropertyName,
            ParameterSetName = 'Path'
        )]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName,
            ParameterSetName = 'Markdown'
        )]
        [String]
        $Path = ([System.IO.Path]::GetTempFileName()),

        # Markdown data to be displayed in the summary
        [Alias('Markdown','Data','InputObject')]
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipeline,
            ParameterSetName = 'Markdown'
        )]
        [String[]]
        $Summary
    )

    process
    {
        try
        {
            if($Summary)
            {
                $folder = Split-Path -Path $Path
                $null = New-Item -Path $folder -ItemType Directory -ErrorAction Ignore
                $Summary | Add-Content -Path $Path
            }
            Write-Vso -Task task.uploadsummary -Text $Path
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Add-VsoTag.ps1
function Add-VsoTag
{
    <#
        .Synopsis
        Add a tag for current build.

        .Example
        Add-VsoTag -Tag $Tag

        .Notes

    #>

    [Alias('VsoTag')]
    [cmdletbinding()]
    param(
        # Build ag to add to current build
        [Alias('BuildTag')]
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String[]]
        $Tag
    )

    process
    {
        try
        {
            foreach ( $node in $Tag )
            {
                Write-Vso -Task build.addbuildtag -Text $node
            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Set-VsoBuildNumber.ps1
function Set-VsoBuildNumber
{
    <#
        .Synopsis
        Sets the build number for the current build

        .Example
        Set-VsoBuildNumber -BuildNumber $BuildNumber

        .Notes

    #>

    [Alias('VsoBuildNumber')]
    [cmdletbinding()]
    param(
        # Build number to set
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $BuildNumber
    )

    process
    {
        try
        {
            Write-Vso -Task build.updatebuildnumber -Text $BuildNumber
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Set-VsoCompleteStatus.ps1

function Set-VsoCompleteStatus
{
    <#
        .Synopsis
        Finish timeline record for current task, set task result and current operation. When result not provide, set result to succeeded.

        .Example
        Set-VsoCompleteStatus -Message $Message

        .Notes

    #>

    [Alias('VsoStatus','Set-VsoStatus')]
    [cmdletbinding()]
    param(
        # Set the result of the task
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [VsoResult]
        $Status,

        # Task complete action message
        [Parameter(
            Position = 1,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [string]
        $Message
    )

    process
    {
        try
        {
            Write-Vso -Task task.complete -Text $Message @{
                Result = $Status
            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Set-VsoEndpoint.ps1
function Set-VsoEndpoint
{
    <#
        .Synopsis
        Set an endpoint field with given value.

        .Example
        Set-VsoEndpoint -Value $Value

        .Notes
        Value updated will be retained in the endpoint for the subsequent tasks that execute within the same job.
    #>

    [Alias('VsoEndpoint')]
    [cmdletbinding()]
    param(
        # Value to set
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Value,

        # Endpoint ID
        [Parameter(
            Mandatory,
            Position = 1,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Id,

        # Field Type
        [Parameter(
            Mandatory,
            Position = 2,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [ValidateSet('authParameter', 'dataParameter', 'url')]
        [String]
        $Field,

        # Endpoint ID
        [Parameter(
            Position = 3,
            ValueFromPipelineByPropertyName
        )]
        [String]
        $Key
    )

    process
    {
        try
        {
            $Attrbiutes = @{
                Key   = $Key
                Field = $Field
                ID    = $ID
            }

            Write-Vso -Task task.setendpoint -Text $Value -Attributes $Attrbiutes

        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Set-VsoProgress.ps1
function Set-VsoProgress
{
    <#
        .Synopsis
        Set progress and current operation for current task.

        .Example
        Set-VsoProgress -Message $Message

        .Notes

    #>

    [Alias('VsoProgress')]
    [cmdletbinding()]
    param(
        # Current task
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Message,

        # Percentage complete
        [Parameter(
            Position = 1,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [ValidateRange(0,100)]
        [int]
        $Value
    )

    process
    {
        try
        {
            Write-Vso -Task task.setprogress -Text $Message @{
                Value = $Value
            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Set-VsoReleaseName.ps1
function Set-VsoReleaseName
{
    <#
        .Synopsis
        Set release name

        .Example
        Set-VsoReleaseName -Name $Name

        .Notes

    #>

    [Alias('VsoReleaseName')]
    [cmdletbinding()]
    param(
        # Release name
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Name
    )

    process
    {
        try
        {
            Write-Vso -Task release.updatereleasename -Text $Name
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Set-VsoVariable.ps1
function Set-VsoVariable
{
    <#
        .Synopsis
        Sets a VSO variable

        .Example
        Set-VsoVariable -Name TestVar -Value TestValue

        .Notes
        Sets a variable in the variable service of taskcontext. The first task can set a variable, and following tasks in the same phase are able to use the variable. The variable is exposed to the following tasks as an environment variable. When issecret is set to true, the value of the variable will be saved as secret and masked out from log. Secret variables are not passed into tasks as environment variables and must be passed as inputs.

    #>

    [Alias('VsoVariable')]
    [cmdletbinding()]
    param(
        # Variable Name
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Name,

        # variable value
        [Parameter(
            Mandatory,
            Position = 1,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Value,

        # secures this value from logs
        [Parameter()]
        [switch]
        $IsSecret
    )

    process
    {
        try
        {
            $Attrbiutes = @{
                Variable = $Name
                issecret = $IsSecret
            }

            Write-Vso -Task task.setvariable -Text $Value -Attributes $Attrbiutes

        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Write-VsoError.ps1
function Write-VsoError
{
    <#
        .Synopsis
        Writes a VSO Error that shows on the summary screen

        .Example
        Write-VsoError -Message $message

        .Notes

    #>

    [Alias('VsoError')]
    [cmdletbinding()]
    param(
        # Parameter help description
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [String[]]
        $Message,

        # Source file path
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]
        $SourcePath,

        # Line number in the file
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]
        $LineNumber,

        # column number of the error
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]
        $ColumnNumber,

        # Error code
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]
        $Code
    )

    process
    {
        try
        {
            $Attributes = @{
                SourcePath   = $SourcePath
                LineNumber   = $LineNumber
                ColumnNumber = $ColumnNumber
                Code         = $Code
                Type         = 'error'
            }

            foreach ( $node in $Message )
            {
                $writeVsoLoggingCommandSplat = @{
                    Attributes = $Attributes
                    Task = 'task.logissue'
                    Text = $Message
                }
                Write-Vso @writeVsoLoggingCommandSplat
            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}

# ./VsoLoggingCommands/Public/Write-VsoLogDetail.ps1
function Write-VsoLogDetail
{
    <#
        .Synopsis
        Create and update detail timeline records.

        .Example
        Write-VsoLogDetail -Path $Path

        .Notes
        The first time a ##vso[task.detail] message is seen for a given task, a detailed timeline is created for that task.
        Nested timeline records are created and updated based on id and parentid.
        The task author needs to remember which Guid they used for each timeline record. The logging system tracks the Guid for each timeline record that has been created, so any new Guid results in a new timeline record

    #>

    [cmdletbinding()]
    param(
        # The message to log
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName
        )]
        [ValidateNotNullOrEmpty()]
        [String]
        $Message,

        # Timeline record Guid (Required)
        [String]
        $id = (New-Guid),

        # Parent timeline record Guid
        [String]
        $ParentId,

        # Record type (Required for first time, can't overwrite)
        [string]
        $Type,

        # Record name (Required for first time, can't overwrite)
        [string]
        $Name,

        # order of timeline record (Required for first time, can't overwrite)
        [string]
        $Order,

        # Datetime
        [DateTime]
        $StartTime,

        # Datetime
        [DateTime]
        $FinishTime,

        # percentage of completion
        [string]
        $Progress,

        # Unknown|Initialized|InProgress|Completed
        [VsoState]
        $State = 'Unknown',

        # Succeeded|SucceededWithIssues|Failed|Cancelled|Skipped
        [VsoResult]
        $Result
    )

    process
    {
        try
        {
            $Attrbiutes = @{
                id         = $id
                parentid   = $parentid
                type       = $type
                name       = $name
                order      = $order
                starttime  = $starttime
                finishtime = $finishtime
                progress   = $progress
                state      = $state
                result     = $result
            }

            Write-Vso -Task task.logdetail -Text $Message -Attributes $Attrbiutes
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }

    end
    {

    }
}

# ./VsoLoggingCommands/Public/Write-VsoWarning.ps1
function Write-VsoWarning
{
    <#
        .Synopsis
        Writes a VSO warning that shows on the summary screen

        .Example
        Write-VsoWarning -Message $message

        .Example
       VsoWarning $message

        .Notes

    #>

    [Alias('VsoWarning')]
    [cmdletbinding()]
    param(
        # Parameter help description
        [Parameter(
            Mandatory,
            Position = 0,
            ValueFromPipelineByPropertyName,
            ValueFromPipeline
        )]
        [String[]]
        $Message,

        # Source path of file
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]
        $SourcePath,

        # Line number in file
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]
        $LineNumber,

        # Column number in file
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]
        $ColumnNumber,

        # Error code
        [Parameter(ValueFromPipelineByPropertyName)]
        [string]
        $Code
    )

    process
    {
        try
        {
            $Attributes = @{
                SourcePath   = $SourcePath
                LineNumber   = $LineNumber
                ColumnNumber = $ColumnNumber
                Code         = $Code
                Type         = 'warning'
            }

            foreach ( $node in $Message )
            {
                $writeVsoLoggingCommandSplat = @{
                    Attributes = $Attributes
                    Task = 'task.logissue'
                    Text = $Message
                }
                Write-Vso @writeVsoLoggingCommandSplat
            }
        }
        catch
        {
            $PSCmdlet.ThrowTerminatingError( $PSItem )
        }
    }
}