PipelineUtils.psm1

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

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

# Enum for supported pipeline types
enum PipelineType {
    Unknown = 0
    AzureDevOps = 1
    GitHubActions = 2
}
#EndRegion './Enum/PipelineTypes.ps1' 7
#Region './Private/Get-PipelineType.ps1' -1

# Private helper function to get the current pipeline type
function Get-PipelineType {
    <#
    .SYNOPSIS
    Determines the type of pipeline environment the code is running in.
    
    .DESCRIPTION
    This private function checks for environment variables specific to Azure DevOps
    and GitHub Actions to determine the pipeline type.
    
    .OUTPUTS
    [PipelineType] Returns the detected pipeline type (Unknown, AzureDevOps, or GitHubActions).
    #>

    [CmdletBinding()]
    [OutputType([PipelineType])]
    param()
    
    # Check for Azure DevOps environment variables
    $azureDevOpsVariables = @('TF_BUILD', 'AGENT_ID', 'BUILD_BUILDID')
    
    foreach ($variable in $azureDevOpsVariables) {
        if (Get-Item -Path "Env:$variable" -ErrorAction SilentlyContinue) {
            return [PipelineType]::AzureDevOps
        }
    }
    
    # Check for GitHub Actions environment variables
    $gitHubActionsVariables = @('GITHUB_ACTIONS', 'GITHUB_WORKFLOW', 'GITHUB_RUN_ID')
    
    foreach ($variable in $gitHubActionsVariables) {
        if (Get-Item -Path "Env:$variable" -ErrorAction SilentlyContinue) {
            return [PipelineType]::GitHubActions
        }
    }
    
    return [PipelineType]::Unknown
}
#EndRegion './Private/Get-PipelineType.ps1' 38
#Region './Private/Test-PipelineContext.ps1' -1

# Private helper function to validate pipeline context
function Test-PipelineContext {
    <#
    .SYNOPSIS
    Tests if the current session is running in a CI/CD pipeline (Azure DevOps or GitHub Actions).
    
    .DESCRIPTION
    This private function checks for the presence of environment variables specific to
    Azure DevOps or GitHub Actions to determine if the code is running within a pipeline context.
    
    .OUTPUTS
    [bool] Returns $true if running in a supported pipeline, $false otherwise.
    #>

    [CmdletBinding()]
    [OutputType([bool])]
    param()
    
    $pipelineType = Get-PipelineType
    return ($pipelineType -ne [PipelineType]::Unknown)
}
#EndRegion './Private/Test-PipelineContext.ps1' 21
#Region './Private/Write-PipelineLog.ps1' -1

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

.DESCRIPTION
    This advanced function logs messages of type Warning, Error, Info, or Debug to Azure Pipelines, GitHub Actions, 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 pipeline 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 CI/CD pipelines and supports rich logging features for 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 ending line number in the source file where the log message applies (optional). Appplies only to GitHub Actions.
        [Parameter()]
        [int]$EndLineNumber,

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

        # The ending line number in the source file where the log message applies (optional). Appplies only to GitHub Actions.
        [Parameter()]
        [int]$EndColumnNumber,

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

        # The issue code associated with the log message (optional). Applies only to GitHub Actions.
        [Parameter()]
        [Alias('Title')]
        [string]$IssueTitle,

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

    $LogType = $LogType.ToLower()
    $pipelineType = Get-PipelineType
    $color = 'White'

    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            switch ($LogType) {
                'error'   { $prefix = '##vso[task.logissue type=error'; $suffix = ';]'; $useVso = $true }
                'warning' { $prefix = '##vso[task.logissue type=warning'; $suffix = ';]'; $useVso = $true }
                'debug'   { $prefix = '##[debug]'; $suffix = '' }
                'command' { $prefix = '##[command]'; $suffix = '' }
                'info'    { $prefix = ''; $suffix = '' } # no official info command
            }
        }
        ([PipelineType]::GitHubActions) {
            switch ($LogType) {
                'error'   { $prefix = '::error'; $suffix = '::'; $ghaSupportsProps = $true }
                'warning' { $prefix = '::warning'; $suffix = '::'; $ghaSupportsProps = $true }
                'debug'   { $prefix = '::debug::'; $suffix = '' }
                'command' { $prefix = '##[command]'; $suffix = '' }
                'info'    { $prefix = '::notice'; $suffix = '::'; $ghaSupportsProps = $true }
            }
        }
        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 ((-not $DoNotUpdateJobStatus.IsPresent) -and $isIssue) {
        $global:_task_status = 'SucceededWithIssues'
    }

    if ($pipelineType -eq [PipelineType]::AzureDevOps -and $useVso) {
        $properties = ''
        if ($SourcePath) { $properties += ";sourcepath=$SourcePath" }
        if ($LineNumber) { $properties += ";linenumber=$LineNumber" }
        if ($ColumnNumber) { $properties += ";columnnumber=$ColumnNumber" }
        if ($IssueCode) { $properties += ";code=$IssueCode" }

        Write-Host "${prefix}${properties}${suffix}$Message"
        return
    }

    if ($pipelineType -eq [PipelineType]::GitHubActions -and $ghaSupportsProps) {
        # GitHub Actions supports properties only for error/warning/notice
        $props = [System.Collections.Generic.List[string]]::new()
        if ($SourcePath) { $props.Add("file=$SourcePath") }
        if ($LineNumber) { $props.Add("line=$LineNumber") }
        if ($EndLineNumber) { $props.Add("endLine=$EndLineNumber") }
        if ($ColumnNumber) { $props.Add("col=$ColumnNumber") }
        if ($EndColumnNumber) { $props.Add("endColumn=$EndColumnNumber") }
        if ($IssueTitle) { $props.Add("title=$IssueTitle$(if ($IssueCode) { " (code $IssueCode)" })") }
        elseif ($IssueCode) { $props.Add("title=$IssueCode") }
        $properties = if ($props.Count -gt 0) { " $($props -join ',')" } else { '' }

        Write-Host "${prefix}${properties}${suffix}$Message"
        return
    }

    Write-Host "${prefix}${Message}${suffix}" -ForegroundColor $color
}
#EndRegion './Private/Write-PipelineLog.ps1' 141
#Region './Public/Add-PipelineBuildTag.ps1' -1

function Add-PipelineBuildTag {
    <#
    .SYNOPSIS
    Adds a tag to the current pipeline build/run.
    
    .DESCRIPTION
    This function adds a tag to the current build in Azure DevOps. GitHub Actions does not
    support adding build/run tags via workflow commands; in that environment the function
    emits a warning and returns.
    
    .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
    )
    
    $pipelineType = Get-PipelineType
    
    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            Write-Output "##vso[build.addbuildtag]$Tag"
        }
        ([PipelineType]::GitHubActions) {
            Write-Warning "Add-PipelineBuildTag is only supported in Azure DevOps pipelines."
            return
        }
        default {
            Write-Output "Build tag: $Tag"
        }
    }
}
#EndRegion './Public/Add-PipelineBuildTag.ps1' 41
#Region './Public/Add-PipelinePath.ps1' -1

<#
.SYNOPSIS
    Adds a path to the PATH environment variable in CI/CD pipelines.

.DESCRIPTION
    The Add-PipelinePath function adds a specified path to the PATH environment variable
    in Azure DevOps or GitHub Actions. It uses the appropriate command for each platform
    to ensure the path is properly set for subsequent tasks/steps.

.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."
        return
    }

    $pipelineType = Get-PipelineType
    
    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            Write-Host "##vso[task.prependpath]$Path"
        }
        ([PipelineType]::GitHubActions) {
            Add-Content -Path $env:GITHUB_PATH -Value $Path
        }
    }
    $env:PATH = "$Path$([System.IO.Path]::PathSeparator)$env:PATH"
}
#EndRegion './Public/Add-PipelinePath.ps1' 49
#Region './Public/Add-PipelineSummary.ps1' -1

<#
.SYNOPSIS
Adds a Markdown summary to CI/CD pipelines.

.DESCRIPTION
This function adds a Markdown formatted summary to the pipeline run using Azure DevOps or GitHub Actions 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."
            }
            $summaryPath = $Path
        }
        else {
            # Write the content to a temporary file
            $summaryPath = [System.IO.Path]::GetTempFileName() + ".md"
            Set-Content -Path $summaryPath -Value $Content -Encoding UTF8
        }

        $pipelineType = Get-PipelineType
        
        switch ($pipelineType) {
            ([PipelineType]::AzureDevOps) {
                Write-Host "##vso[task.uploadsummary]$summaryPath"
            }
            ([PipelineType]::GitHubActions) {
                # Append to the GitHub Actions step summary
                Get-Content -Path $summaryPath | Add-Content -Path $env:GITHUB_STEP_SUMMARY
            }
            default {
                Get-Content -Path $summaryPath | Write-Host
            }
        }
    }
}
#EndRegion './Public/Add-PipelineSummary.ps1' 68
#Region './Public/Add-PipelineTaskLogFile.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
    )

    Begin {
        $pipelineType = Get-PipelineType
        
        if($pipelineType -ne [PipelineType]::AzureDevOps) {
            Write-Warning "Add-PipelineTaskLogFile is only supported in Azure DevOps pipelines."
            return
        }
    }

    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-PipelineTaskLogFile.ps1' 53
#Region './Public/Complete-PipelineTask.ps1' -1

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

    $pipelineType = Get-PipelineType
    
    if($pipelineType -ne [PipelineType]::AzureDevOps) {
        Write-Warning "Complete-PipelineTask is only supported in Azure DevOps pipelines."
        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' 22
#Region './Public/Set-PipelineBuildNumber.ps1' -1

<#
.SYNOPSIS
Sets the build/run number in CI/CD pipelines.

.DESCRIPTION
This function sets the build number in Azure DevOps. GitHub Actions does not support
changing the run name during execution; in that environment the function emits a warning.

.PARAMETER BuildNumber
The build number/run name 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
    )

    $pipelineType = Get-PipelineType
    
    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            Write-Output "##vso[build.updatebuildnumber]$BuildNumber"
        }
        ([PipelineType]::GitHubActions) {
            Write-Warning "Set-PipelineBuildNumber is only supported in Azure DevOps pipelines."
            return
        }
        default {
            Write-Output "Build number: $BuildNumber"
        }
    }
}
#EndRegion './Public/Set-PipelineBuildNumber.ps1' 43
#Region './Public/Set-PipelineReleaseNumber.ps1' -1

<#
.SYNOPSIS
Sets the release name in CI/CD pipelines.

.DESCRIPTION
This function sets the release name using the appropriate logging commands for the detected pipeline.
The release name can be modified during a release run to provide custom naming.

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

.EXAMPLE
Set-PipelineReleaseNumber -ReleaseNumber "$(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
    )

    $pipelineType = Get-PipelineType
    
    if($pipelineType -ne [PipelineType]::AzureDevOps) {
        Write-Warning "Set-PipelineReleaseNumber is only supported in Azure DevOps pipelines."
        return
    }
    
    # Check if we're in a Release pipeline (not a Build pipeline)
    if (-not $Env:RELEASE_RELEASEID) {
        Write-Warning "Set-PipelineReleaseNumber is only supported in Azure DevOps Release pipelines. Setting the build number instead."
        Set-PipelineBuildNumber -BuildNumber $ReleaseNumber
        return
    }
    
    Write-Output "##vso[release.updatereleasename]$ReleaseNumber"
}
#EndRegion './Public/Set-PipelineReleaseNumber.ps1' 41
#Region './Public/Set-PipelineSecretValue.ps1' -1

<#
.SYNOPSIS
Marks a value as secret in CI/CD pipelines.

.DESCRIPTION
This function marks a value as secret using Azure DevOps or GitHub Actions 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
    )

    $pipelineType = Get-PipelineType
    
    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            Write-Output "##vso[task.setsecret]$Value"
        }
        ([PipelineType]::GitHubActions) {
            Write-Output "::add-mask::$Value"
        }
        default {
            Write-Output "Secret value has been masked in logs: ********"
        }
    }
}
#EndRegion './Public/Set-PipelineSecretValue.ps1' 43
#Region './Public/Set-PipelineVariable.ps1' -1

function Set-PipelineVariable {
    <#
    .SYNOPSIS
    Sets a variable in CI/CD pipelines (Azure DevOps or GitHub Actions).
    
    .DESCRIPTION
    This function sets a pipeline variable using the appropriate syntax for the detected pipeline environment.
    For Azure DevOps, it uses logging commands. For GitHub Actions, it writes to $env:GITHUB_ENV.
    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. (Azure DevOps only)
    
    .PARAMETER Output
    Indicates whether the variable should be available to subsequent jobs or steps.
    For GitHub Actions, writes to $env:GITHUB_OUTPUT instead of $env:GITHUB_ENV.
    
    .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
    )
    
    $pipelineType = Get-PipelineType
    
    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            $propList = @()

            if ($Secret) { $propList += 'issecret=true' }
            if ($Output) { $propList += 'isoutput=true' }
            if ($ReadOnly) { $propList += 'isreadonly=true' }

            $properties = if ($propList.Count -gt 0) { ';' + ($propList -join ';') + ';' } else { ';' }

            Write-Output "##vso[task.setvariable variable=$Name$properties]$Value"
        }
        ([PipelineType]::GitHubActions) {
            if ($Output) {
                # For outputs, write to GITHUB_OUTPUT
                Add-Content -Path $env:GITHUB_OUTPUT -Value "$Name=$Value"
            }
            else {
                # For environment variables, write to GITHUB_ENV
                # Support multiline values using delimiter
                if ($Value -match '\r?\n') {
                    $delimiter = "EOF_$(Get-Random)"
                    Add-Content -Path $env:GITHUB_ENV -Value "$Name<<$delimiter"
                    Add-Content -Path $env:GITHUB_ENV -Value $Value
                    Add-Content -Path $env:GITHUB_ENV -Value $delimiter
                }
                else {
                    Add-Content -Path $env:GITHUB_ENV -Value "$Name=$Value"
                }
            }
            
            # Note: GitHub Actions handles secrets differently - they must be defined in repository/organization settings
            if ($Secret) {
                Write-PipelineWarning -Message "Secret flag is not applicable in GitHub Actions. Secrets must be configured in repository settings. Value will be masked in logs, though." 
                Set-PipelineSecretValue -Value $Value
            }
            if ($ReadOnly) {
                Write-PipelineWarning -Message "ReadOnly flag is not applicable in GitHub Actions." 
            }
        }
    }

    Set-Item -Path "env:$Name" -Value $Value
}
#EndRegion './Public/Set-PipelineVariable.ps1' 97
#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,

        [Parameter()]
        [int]$ColumnNumber,

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

        [Parameter()]
        [switch] $DoNotUpdateJobStatus
    )
    
    Write-PipelineLog -Message $Message -LogType 'Error' -SourcePath $SourcePath -LineNumber $LineNumber -ColumnNumber $ColumnNumber -IssueCode $IssueCode -DoNotUpdateJobStatus:$DoNotUpdateJobStatus
}

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

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

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

    Write-PipelineGroupStart $Header

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

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

Function Write-PipelineGroupEnd() {
    $pipelineType = Get-PipelineType
    
    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            Write-Host "##[endgroup]"
        }
        ([PipelineType]::GitHubActions) {
            Write-Host "::endgroup::"
        }
        default {
            # No special handling needed for non-pipeline environments
        }
    }
}

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

Function Write-PipelineGroupStart($Text) {
    $pipelineType = Get-PipelineType
    
    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            Write-Host "##[group]$Text"
        }
        ([PipelineType]::GitHubActions) {
            Write-Host "::group::$Text"
        }
        default {
            Write-Host "$Text" -ForegroundColor Cyan
        }
    }
}
#EndRegion './Public/Write-PipelineGroupStart.ps1' 16
#Region './Public/Write-PipelineProgress.ps1' -1

<#
.SYNOPSIS
Writes a progress message in CI/CD pipelines.

.DESCRIPTION
This function writes a progress message using the appropriate logging commands for the detected pipeline.
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
    )

    $pipelineType = Get-PipelineType
    
    switch ($pipelineType) {
        ([PipelineType]::AzureDevOps) {
            Write-Output "##vso[task.setprogress value=$PercentComplete;]$Activity - $PercentComplete%"
        }
        ([PipelineType]::GitHubActions) {
            # GitHub Actions doesn't have native progress bars, use notice
            Write-Output "::notice::$Activity - $PercentComplete% complete"
        }
        default {
            # If not in a pipeline, use standard PowerShell Write-Progress
            Write-Progress -Activity $Activity -PercentComplete $PercentComplete
        }
    }
}
#EndRegion './Public/Write-PipelineProgress.ps1' 60
#Region './Public/Write-PipelineSection.ps1' -1


<#
.SYNOPSIS
Writes a section header to the CI/CD pipeline log output.

.DESCRIPTION
This function emits a formatted section header in the pipeline log, optionally boxed, using the appropriate logging command for the detected pipeline. 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 a supported CI/CD pipeline environment (Azure DevOps or GitHub Actions).
#>

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"
    $pipelineType = Get-PipelineType

    if ($pipelineType -ne [PipelineType]::Unknown) {
        $prefix = '##[section]'
    }

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

    Write-Host "${box}${prefix}$msg${box}" -ForegroundColor Cyan

    if ($pipelineType -eq [PipelineType]::GitHubActions) {
        Write-Host "" -ForegroundColor Cyan
    }
}
#EndRegion './Public/Write-PipelineSection.ps1' 50
#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
    )
    
    Write-PipelineLog -Message $Message -LogType 'Warning' -SourcePath $SourcePath -LineNumber $LineNumber -ColumnNumber $ColumnNumber -IssueCode $IssueCode -DoNotUpdateJobStatus:$DoNotUpdateJobStatus
}

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