AzurePipelinesUtils.psm1

#Region './Enum/LogMessageTypes.ps1' -1

Enum LogMessageTypes {
    Default
    Error
    Warning
    Information
    Section
}
#EndRegion './Enum/LogMessageTypes.ps1' 8
#Region './Private/Test-PipelineContext.ps1' -1

# Private helper function to validate Azure Pipelines context
function Test-PipelineContext {
    <#
    .SYNOPSIS
    Tests if the current session is running in an Azure DevOps Pipeline.
    
    .DESCRIPTION
    This private function checks for the presence of Azure DevOps environment variables
    to determine if the code is running within a pipeline context.
    
    .OUTPUTS
    [bool] Returns $true if running in Azure Pipelines, $false otherwise.
    #>

    [CmdletBinding()]
    [OutputType([bool])]
    param()
    
    $azureDevOpsVariables = @(
        'TF_BUILD',
        'AGENT_ID',
        'BUILD_BUILDID'
    )
    
    foreach ($variable in $azureDevOpsVariables) {
        if (Get-Item -Path "Env:$variable" -ErrorAction SilentlyContinue) {
            return $true
        }
    }
    
    return $false
}
#EndRegion './Private/Test-PipelineContext.ps1' 32
#Region './Private/Write-PipelineIssue.ps1' -1

<#
.SYNOPSIS
    Writes a log message to the Azure Pipelines log or console.

.DESCRIPTION
    This advanced function logs messages of type Warning, Error, Info, or Debug to Azure Pipelines or the console. It supports additional metadata such as source file, line, column, and issue code, and can optionally prevent updating the job status. The function is intended for use in CI/CD scenarios to provide rich, contextual logging.

.EXAMPLE
    Write-PipelineLog -Message "An error occurred." -LogType Error
    # Logs an error message to the Azure Pipelines log.

.EXAMPLE
    Write-PipelineLog -Message "File not found." -LogType Warning -SourcePath "src/app.ps1" -LineNumber 42
    # Logs a warning message with source file and line number metadata.

.EXAMPLE
    Write-PipelineLog -Message "Debugging info." -LogType Debug -DoNotUpdateJobStatus
    # Logs a debug message and does not update the job status.

.NOTES
    Author: igoravl
    Date: August 29, 2025
    This function is intended for use in Azure Pipelines and supports rich logging features for CI/CD automation.
#>

function Write-PipelineLog {
    [CmdletBinding()]
    param(
        # The message to log in the pipeline.
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Message,

        # The type of log message (Warning, Error, Info, Debug).
        [Parameter(Mandatory=$true)]
        [ValidateSet("Warning", "Error", "Info", "Debug", "Command")]
        [string]$LogType,

        # The source file path related to the log message (optional).
        [Parameter()]
        [string]$SourcePath,
        
        # The line number in the source file where the log message applies (optional).
        [Parameter()]
        [int]$LineNumber,

        # The column number in the source file where the log message applies (optional).
        [Parameter()]
        [int]$ColumnNumber,

        # The issue code associated with the log message (optional).
        [Parameter()]
        [Alias('Code')]
        [string]$IssueCode,

        # If set, does not update the job status (optional).
        [Parameter()]
        [switch] $DoNotUpdateJobStatus
    )

    $LogType = $LogType.ToLower()
    $color = 'White'

    if ((Test-PipelineContext)) {
        $prefix = "##[$LogType] "
    }
    else {
        switch($LogType) {
            "error" { $color = 'Red' }
            "warning" { $color = 'Yellow' }
            "info" { $color = 'LightGray' }
            "debug" { $color = 'DarkGray' }
            "command" { $color = 'Cyan' }
        }
    }

    $isIssue = ($LogType -eq 'error' -or $LogType -eq 'warning')

    if ($DoNotUpdateJobStatus.IsPresent -or (-not $isIssue)) {
        Write-Host "${prefix}$Message" -ForegroundColor $color
        return
    }
    
    $properties = ''

    if ($SourcePath) { $properties += ";sourcepath=$SourcePath" }
    if ($LineNumber) { $properties += ";linenumber=$LineNumber" }
    if ($ColumnNumber) { $properties += ";columnnumber=$ColumnNumber" }
    if ($IssueCode) { $properties += ";code=$IssueCode" }

    $global:_task_status = 'SucceededWithIssues'
    Write-Host "##vso[task.logissue type=$LogType$properties]$Message"
}
#EndRegion './Private/Write-PipelineIssue.ps1' 92
#Region './Public/Add-PipelineBuildTag.ps1' -1

function Add-PipelineBuildTag {
    <#
    .SYNOPSIS
    Adds a tag to the current Azure DevOps Pipeline build.
    
    .DESCRIPTION
    This function adds a tag to the current build using Azure DevOps Pipelines logging commands.
    Tags can be used to categorize and filter builds.
    
    .PARAMETER Tag
    The tag to add to the build.
    
    .EXAMPLE
    Add-PipelineBuildTag -Tag "release"
    
    .EXAMPLE
    Add-PipelineBuildTag -Tag "hotfix"
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Tag
    )
    
    Write-Output "##vso[build.addbuildtag]$Tag"
}
#EndRegion './Public/Add-PipelineBuildTag.ps1' 27
#Region './Public/Add-PipelineLogFile.ps1' -1

<#
.SYNOPSIS
    Uploads a file to the current pipeline task log.

.DESCRIPTION
    The Add-PipelineTaskLogFile function uploads a specified file to the Azure DevOps pipeline task log.
    This allows you to attach log files or other output files to be visible in the pipeline run logs.

.PARAMETER Path
    The path to the file to be uploaded. This parameter accepts pipeline input.

.EXAMPLE
    Add-PipelineTaskLogFile -Path ".\build.log"
    
    Uploads build.log to the task logs with its original filename.

.EXAMPLE
    Get-ChildItem -Path ".\logs\*.log" | Add-PipelineTaskLogFile
    
    Uploads all log files from the logs directory to the task logs.

.NOTES
    This function requires to be run within an Azure Pipelines task execution context.
#>

Function Add-PipelineTaskLogFile {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $Path
    )

    Process {
        foreach ($filePath in $Path) {
            # Resolve the path to ensure it's absolute
            $resolvedPath = Resolve-Path -Path $filePath -ErrorAction Stop

            # Execute the Azure Pipelines task command
            Write-Host "##vso[task.uploadfile]$resolvedPath"
        }
    }
}
#EndRegion './Public/Add-PipelineLogFile.ps1' 44
#Region './Public/Add-PipelinePath.ps1' -1

<#
.SYNOPSIS
    Adds a path to the PATH environment variable in Azure Pipelines.

.DESCRIPTION
    The Add-PipelinePath function adds a specified path to the PATH environment variable
    in Azure Pipelines. It uses the task.prependpath command which is available in Azure Pipelines
    to ensure the path is properly set for subsequent tasks.

.PARAMETER Path
    The path to add to the PATH environment variable.

.EXAMPLE
    Add-PipelinePath -Path "C:\tools\bin"
    
    Adds the "C:\tools\bin" directory to the beginning of the PATH environment variable.

.EXAMPLE
    Add-PipelinePath "$(Build.SourcesDirectory)\tools"

    Adds the tools directory from the source repository to the beginning of the PATH environment variable.
#>

function Add-PipelinePath {
    [CmdletBinding()]
    param(
        [Parameter()]
        [string]$Path
    )
    
    $Path = (Resolve-Path -Path $Path).Path

    if (-not (Test-Path -Path $Path -PathType Container)) {
        Write-Error "The specified path '$Path' does not exist or is not a directory."
    }

    if ((Test-PipelineContext)) {
        Write-Host "##vso[task.prependpath]$Path"
    }
    else {
        $env:PATH = "$Path$([System.IO.Path]::PathSeparator)$env:PATH"
    }
}
#EndRegion './Public/Add-PipelinePath.ps1' 43
#Region './Public/Add-PipelineSummary.ps1' -1

<#
.SYNOPSIS
Adds a Markdown summary to Azure DevOps Pipelines.

.DESCRIPTION
This function adds a Markdown formatted summary to the pipeline run using Azure DevOps Pipelines logging commands.
Summaries appear in the pipeline run details and help provide additional information or context about the build.

.PARAMETER Content
The Markdown content to add as a summary.

.PARAMETER Path
Path to a Markdown file whose content will be added as a summary.

.EXAMPLE
Add-PipelineSummary -Content "## Build Completed Successfully"
# Adds a simple header as a summary to the pipeline

.EXAMPLE
Add-PipelineSummary -Path ".\build-report.md"
# Adds the content of build-report.md file as a summary to the pipeline

.EXAMPLE
"## Test Results: Passed" | Add-PipelineSummary
# Adds summary from pipeline input
#>

function Add-PipelineSummary {
    [CmdletBinding(DefaultParameterSetName = 'Content')]
    param(
        # The Markdown content to add as a summary
        [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'Content', ValueFromPipeline = $true)]
        [string]$Content,

        # Path to a Markdown file whose content will be added as a summary
        [Parameter(Mandatory = $true, ParameterSetName = 'Path')]
        [string]$Path
    )

    Process {
        if ($PSCmdlet.ParameterSetName -eq 'Path') {
            if (-not (Test-Path -Path $Path)) {
                throw "The specified path '$Path' does not exist."
            }
        }
        else {
            # Write the content to a temporary file
            $Path = [System.IO.Path]::GetTempFileName() + ".md"
            Set-Content -Path $Path -Value $Content -Encoding UTF8
        }

        if ((Test-PipelineContext)) {
            Write-Host "##vso[task.uploadsummary]$Path"
        }
        else {
            Write-PipelineSection "Pipeline Summary"
            Get-Content -Path $Path | Write-Host
        }
    }
}
#EndRegion './Public/Add-PipelineSummary.ps1' 60
#Region './Public/Complete-PipelineTask.ps1' -1

Function Complete-PipelineTask {
    Param(
        [Parameter()]
        [string] $Status = 'Succeeded'
    )

    if(-not (Test-PipelineContext)) {
        return
    }

    if($Status -eq 'Succeeded' -and ($Global:_task_status -ne 'Succeeded')) {
        $Status = $Global:_task_status
    }

    if ($Status -ne 'Succeeded') {
        Write-Host "##vso[task.complete result=$Status;]"
    }
}
#EndRegion './Public/Complete-PipelineTask.ps1' 19
#Region './Public/Set-PipelineBuildNumber.ps1' -1

<#
.SYNOPSIS
Sets the build number in Azure DevOps Pipelines.

.DESCRIPTION
This function sets the build number using Azure DevOps Pipelines logging commands.
The build number can be modified during a pipeline run to provide custom versioning.

.PARAMETER BuildNumber
The build number to set for the current pipeline run.

.EXAMPLE
Set-PipelineBuildNumber -BuildNumber "1.0.42"
# Sets the build number to 1.0.42

.EXAMPLE
Set-PipelineBuildNumber -BuildNumber "$(Get-Date -Format 'yyyy.MM.dd').$env:BUILD_BUILDID"
# Sets the build number using a date-based format with the build ID
#>

function Set-PipelineBuildNumber {
    [CmdletBinding()]
    param(
        # The build number to set for the current pipeline
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$BuildNumber
    )

    if ((Test-PipelineContext)) {
        $prefix = '##vso[build.updatebuildnumber]'
    }
    else {
        $prefix = 'Build number: '
    }

    Write-Output "$prefix$BuildNumber"
}
#EndRegion './Public/Set-PipelineBuildNumber.ps1' 37
#Region './Public/Set-PipelineReleaseNumber.ps1' -1

<#
.SYNOPSIS
Sets the release name in Azure DevOps classic releases.

.DESCRIPTION
This function sets the release name using Azure DevOps Pipelines logging commands.
The release name can be modified during a release run to provide custom naming.

.EXAMPLE
Set-PipelineReleaseNumber -ReleaseName "1.0.42"
# Sets the release name to 1.0.42

.EXAMPLE
Set-PipelineReleaseNumber -ReleaseName "$(Get-Date -Format 'yyyy.MM.dd').$env:RELEASE_RELEASEID"
# Sets the release name using a date-based format with the release ID
#>

function Set-PipelineReleaseNumber {
    [CmdletBinding()]
    param(
        # The release number to set for the current release
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$ReleaseNumber
    )

    if ((Test-PipelineContext)) {
        $prefix = '##vso[release.updatereleasename]'
    }
    else {
        $prefix = 'Release name: '
    }

    Write-Output "$prefix$ReleaseNumber"
}
#EndRegion './Public/Set-PipelineReleaseNumber.ps1' 34
#Region './Public/Set-PipelineSecretValue.ps1' -1

<#
.SYNOPSIS
Marks a value as secret in Azure DevOps Pipelines.

.DESCRIPTION
This function marks a value as secret using Azure DevOps Pipelines logging commands.
Secret values are masked in the pipeline logs to prevent sensitive information from being exposed.

.PARAMETER Value
The value to be marked as secret in the pipeline logs.

.EXAMPLE
Set-PipelineSecretValue -Value "myPassword123"
# Marks "myPassword123" as a secret that will be masked in pipeline logs

.EXAMPLE
$apiKey = "abcd1234efgh5678"
Set-PipelineSecretValue -Value $apiKey
# Marks the API key as a secret that will be masked in pipeline logs
#>

function Set-PipelineSecretValue {
    [CmdletBinding()]
    param(
        # The value to be marked as secret in the pipeline logs
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Value
    )

    if ((Test-PipelineContext)) {
        Write-Output "##vso[task.setsecret]$Value"
    }
    else {
        Write-Output "Secret value has been masked in logs: ********"
    }
}
#EndRegion './Public/Set-PipelineSecretValue.ps1' 36
#Region './Public/Set-PipelineVariable.ps1' -1

function Set-PipelineVariable {
    <#
    .SYNOPSIS
    Sets a variable in Azure DevOps Pipelines.
    
    .DESCRIPTION
    This function sets a pipeline variable using Azure DevOps Pipelines logging commands.
    The variable can be used in subsequent tasks and jobs.
    
    .PARAMETER Name
    The name of the variable to set.
    
    .PARAMETER Value
    The value to assign to the variable.
    
    .PARAMETER Secret
    Indicates whether the variable should be treated as a secret.
    
    .PARAMETER Output
    Indicates whether the variable should be available to subsequent jobs.
    
    .EXAMPLE
    Set-PipelineVariable -Name "BuildNumber" -Value "1.0.42"
    
    .EXAMPLE
    Set-PipelineVariable -Name "ApiKey" -Value "secret123" -Secret
    
    .EXAMPLE
    Set-PipelineVariable -Name "DeploymentTarget" -Value "Production" -Output
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Name,
        
        [Parameter(Mandatory = $true)]
        [string]$Value,
        
        [Parameter(Mandatory = $false)]
        [switch]$Secret,
        
        [Parameter(Mandatory = $false)]
        [switch]$Output,
        
        [Parameter(Mandatory = $false)]
        [switch]$ReadOnly
    )
    
    $properties = ''

    if ($Secret) {
        $properties += ";issecret=true"
    }
    if ($Output) {
        $properties += ";isoutput=true"
    }
    if ($ReadOnly) {
        $properties += ";isreadonly=true"
    }

    Write-Output "##vso[task.setvariable variable=$Name$properties]$Value"
}
#EndRegion './Public/Set-PipelineVariable.ps1' 63
#Region './Public/Write-PipelineCommand.ps1' -1

<#
.SYNOPSIS
Writes a command message to the Azure Pipelines log.

.DESCRIPTION
The Write-PipelineCommand function outputs a command message to the Azure Pipelines log using the appropriate logging command. This helps in troubleshooting and provides additional context during pipeline execution.

.EXAMPLE
Write-PipelineCommand -Message "This is a command message."
Writes the specified command message to the Azure Pipelines log.
#>

Function Write-PipelineCommand {
    Param (
        # Specifies the command message to write to the Azure Pipelines log.
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [string]$Message
    )
    
    Write-PipelineLog -Message $Message -LogType Command
}
#EndRegion './Public/Write-PipelineCommand.ps1' 21
#Region './Public/Write-PipelineDebug.ps1' -1

<#
.SYNOPSIS
Writes a debug message to the Azure Pipelines log.

.DESCRIPTION
The Write-PipelineDebug function outputs a debug message to the Azure Pipelines log using the appropriate logging command. This helps in troubleshooting and provides additional context during pipeline execution.

.EXAMPLE
Write-PipelineDebug -Message "This is a debug message."
Writes the specified debug message to the Azure Pipelines log.

.NOTES
Requires execution within an Azure Pipelines environment to have effect.
#>

Function Write-PipelineDebug {
    Param (
        # Specifies the debug message to write to the Azure Pipelines log.
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true)]
        [string]$Message
    )

    Write-PipelineLog -Message $Message -LogType Debug
}

Set-Alias -Name 'Write-Debug' -Value 'Write-PipelineDebug' -Force -Scope Global
#EndRegion './Public/Write-PipelineDebug.ps1' 26
#Region './Public/Write-PipelineError.ps1' -1

function Write-PipelineError {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Message,
        
        [Parameter(Mandatory = $false)]
        [string]$SourcePath,
        
        [Parameter(Mandatory = $false)]
        [int]$LineNumber
    )
    
    if ((Test-PipelineContext)) {
        $prefix = '##[warning] ' 
    }
    
    if ($DoNotUpdateJobStatus.IsPresent) {
        Write-Host "${prefix}$Message" -ForegroundColor Yellow
        return
    }
    
    $properties = ''

    if ($SourcePath) { $properties += ";sourcepath=$SourcePath" }
    if ($LineNumber) { $properties += ";linenumber=$LineNumber" }

    Write-Host "##vso[task.logissue type=error$properties]$Message"
}

# Alias
Set-Alias -Name 'Write-Error' -Value 'Write-PipelineError' -Force -Scope Global
#EndRegion './Public/Write-PipelineError.ps1' 33
#Region './Public/Write-PipelineGroup.ps1' -1

Function Write-PipelineGroup {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        $Header,

        [Parameter(Mandatory = $true)]
        [scriptblock]$Body
    )

    Write-PipelineGroupBegin $Header

    (& $Body) | ForEach-Object { Write-Log $_ }

    Write-PipelineGroupEnd
}
#EndRegion './Public/Write-PipelineGroup.ps1' 17
#Region './Public/Write-PipelineGroupEnd.ps1' -1

Function Write-PipelineGroupEnd() {
    Write-Host "##[endgroup]"
}

#EndRegion './Public/Write-PipelineGroupEnd.ps1' 5
#Region './Public/Write-PipelineGroupStart.ps1' -1

Function Write-PipelineGroupStart($Text) {
    if (-not [string]::IsNullOrWhiteSpace($Text)) {
        $timestamp = "[$(Get-Date -Format 'HH:mm:ss.fff')] "
    }
    
    Write-Host "##[group]${timestamp}$Text"
}
#EndRegion './Public/Write-PipelineGroupStart.ps1' 8
#Region './Public/Write-PipelineProgress.ps1' -1

<#
.SYNOPSIS
Writes a progress message in Azure DevOps Pipelines.

.DESCRIPTION
This function writes a progress message using Azure DevOps Pipelines logging commands.
It can be used to show progress status during pipeline execution, including
percentage completion values.

.PARAMETER PercentComplete
The percentage of completion (0-100) for the current operation.

.PARAMETER Activity
The name of the activity for which progress is being reported.

.PARAMETER Status
The current status message for the activity.

.PARAMETER Id
A unique identifier for the progress bar. Useful when tracking multiple
concurrent operations.

.EXAMPLE
Write-PipelineProgress -PercentComplete 50 -Activity "Deployment" -Status "Installing components"
# Reports 50% completion for the "Deployment" activity

.EXAMPLE
Write-PipelineProgress -PercentComplete 75 -Activity "Build" -Status "Compiling sources" -Id 1
# Reports 75% completion for the "Build" activity with ID 1
#>

function Write-PipelineProgress {
    [CmdletBinding()]
    param(
        # The percentage of completion (0-100)
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateRange(0, 100)]
        [int]$PercentComplete,

        # The name of the activity for which progress is being reported
        [Parameter(Mandatory = $true, Position = 1)]
        [string]$Activity
    )

    if ((Test-PipelineContext)) {
        # Using Azure DevOps Pipelines task progress command
        Write-Output "##vso[task.setprogress value=$PercentComplete;]$Activity - $PercentComplete%"
    }
    else {
        # If not in a pipeline, use standard PowerShell Write-Progress
        Write-Progress -Activity $Activity -PercentComplete $PercentComplete
    }
}
#EndRegion './Public/Write-PipelineProgress.ps1' 53
#Region './Public/Write-PipelineSection.ps1' -1


<#
.SYNOPSIS
Writes a section header to the Azure Pipelines log output.

.DESCRIPTION
This function emits a formatted section header in the Azure Pipelines log, optionally boxed, using the special logging command for sections. It is useful for visually grouping related log output in pipeline runs.

.EXAMPLE
Write-PipelineSection -Text "Build started"
Writes a section header labeled "Build started" to the pipeline log.

.EXAMPLE
Write-PipelineSection -Text "Tests" -Boxed
Writes a boxed section header labeled "Tests" to the pipeline log.

.NOTES
Requires execution within an Azure Pipelines agent environment to have effect in the log output.
#>

Function Write-PipelineSection {
    [CmdletBinding()]
    Param (
        # The text to display as the section header in the pipeline log.
        [Parameter(Mandatory = $true)]
        [string]$Text,

        # If specified, draws a box around the section header.
        [Parameter(Mandatory = $false)]
        [switch]$Boxed
    )

    $msg = "== $Text =="
    $box = "`n"

    if ((Test-PipelineContext)) {
        $prefix = '##[section]'
    }

    if ($Boxed) {
        $box += ("${prefix}$('=' * $msg.Length)`n")
    }    

    Write-Host "${box}${prefix}$msg${box}" -ForegroundColor Cyan
}
#EndRegion './Public/Write-PipelineSection.ps1' 45
#Region './Public/Write-PipelineTaskProgress.ps1' -1

function Write-PipelineTaskProgress {
    <#
    .SYNOPSIS
    Updates the progress of the current Azure DevOps Pipeline task.
    
    .DESCRIPTION
    This function updates the progress indicator for the current task using Azure DevOps Pipelines logging commands.
    
    .PARAMETER CurrentOperation
    The current operation being performed.
    
    .PARAMETER PercentComplete
    The percentage of completion (0-100).
    
    .EXAMPLE
    Write-PipelineTaskProgress -CurrentOperation "Installing dependencies" -PercentComplete 25
    
    .EXAMPLE
    Write-PipelineTaskProgress -CurrentOperation "Running tests" -PercentComplete 75
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$CurrentOperation,
        
        [Parameter(Mandatory = $false)]
        [ValidateRange(0, 100)]
        [int]$PercentComplete
    )
    
    $properties = "currentoperation=$CurrentOperation"
    if ($PSBoundParameters.ContainsKey('PercentComplete')) {
        $properties += ";percentcomplete=$PercentComplete"
    }
    
    Write-Output "##vso[task.setprogress $properties]"
}
#EndRegion './Public/Write-PipelineTaskProgress.ps1' 38
#Region './Public/Write-PipelineWarning.ps1' -1

function Write-PipelineWarning {
    <#
    .SYNOPSIS
    Writes a warning message to Azure DevOps Pipelines output.
    
    .DESCRIPTION
    This function writes a warning message using Azure DevOps Pipelines logging commands.
    The message will appear as a warning in the pipeline logs.
    
    .PARAMETER Message
    The warning message to display.
    
    .PARAMETER SourcePath
    Optional source file path where the warning occurred.
    
    .PARAMETER LineNumber
    Optional line number where the warning occurred.
    
    .EXAMPLE
    Write-PipelineWarning -Message "This is a warning"
    
    .EXAMPLE
    Write-PipelineWarning -Message "Deprecated function used" -SourcePath "script.ps1" -LineNumber 42
    #>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0)]
        [string]$Message,
        
        [Parameter()]
        [string]$SourcePath,
        
        [Parameter()]
        [int]$LineNumber,

        [Parameter()]
        [int]$ColumnNumber,

        [Parameter()]
        [Alias('Code')]
        [string]$IssueCode,

        [Parameter()]
        [switch] $DoNotUpdateJobStatus
    )
    
    if ((Test-PipelineContext)) {
        $prefix = '##[warning] ' 
    }
    
    if ($DoNotUpdateJobStatus.IsPresent) {
        Write-Host "${prefix}$Message" -ForegroundColor Yellow
        return
    }
    
    $properties = ''

    if ($SourcePath) { $properties += ";sourcepath=$SourcePath" }
    if ($LineNumber) { $properties += ";linenumber=$LineNumber" }
    if ($ColumnNumber) { $properties += ";columnnumber=$ColumnNumber" }
    if ($IssueCode) { $properties += ";code=$IssueCode" }

    $global:_task_status = 'SucceededWithIssues'
    Write-Host "##vso[task.logissue type=warning$properties]$Message"
}

# Alias
Set-Alias -Name 'Write-Warning' -Value 'Write-PipelineWarning' -Force -Scope Global
#EndRegion './Public/Write-PipelineWarning.ps1' 69