GitHub.psm1

#region - From private/common.ps1
$script:APIBaseURI = 'https://api.github.com'
$script:Owner = ''
$script:Repo = ''
$script:Token = ''
#endregion - From private/common.ps1

#region - From private/Initialize-SecretVault.ps1
#Requires -Version 7.0
#Requires -Modules Microsoft.PowerShell.SecretManagement, Microsoft.PowerShell.SecretStore

function Initialize-SecretVault {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Name = 'SecretStore',

        [Parameter()]
        [Alias('ModuleName')]
        [string] $Type = 'Microsoft.PowerShell.SecretStore'
    )

    $secretVault = Get-SecretVault | Where-Object { $_.ModuleName -eq $Type }
    $secretVaultExists = $secretVault.count -ne 0
    Write-Verbose "$Name exists: $secretVaultExists"
    if (-not $secretVaultExists) {
        Write-Verbose "Registering [$Name]"
        $vaultParameters = @{
            Authentication  = 'None'
            PasswordTimeout = -1
            Interaction     = 'None'
            Scope           = 'CurrentUser'
            WarningAction   = 'SilentlyContinue'
            Confirm         = $false
            Force           = $true
        }
        Reset-SecretStore @vaultParameters

        $secretVault = @{
            Name         = $Name
            ModuleName   = $Type
            DefaultVault = $true
            Description  = 'SecretStore'
        }
        Register-SecretVault @secretVault
    }
    Get-SecretStoreConfiguration
}
#endregion - From private/Initialize-SecretVault.ps1

#region - From public/Connect-GitHubAccount.ps1
<#
.SYNOPSIS
Short description

.DESCRIPTION
Long description

.PARAMETER Owner
Parameter description

.PARAMETER Repo
Parameter description

.PARAMETER Token
Parameter description

.PARAMETER APIBaseURI
Parameter description

.EXAMPLE
An example

.NOTES
https://docs.github.com/en/rest/overview/other-authentication-methods#authenticating-for-saml-sso
#>

function Connect-GitHubAccount {
    [CmdletBinding()]
    param (
        [Parameter()]
        [String] $Owner,
        [Parameter()]
        [String] $Repo,
        [Parameter(Mandatory)]
        [String] $Token,
        [Parameter()]
        [String] $APIBaseURI = 'https://api.github.com'
    )

    $script:APIBaseURI = $APIBaseURI
    $script:Owner = $Owner
    $script:Repo = $Repo
    $script:Token = $Token

    Get-GitHubContext

}
#endregion - From public/Connect-GitHubAccount.ps1

#region - From public/Disable-GitHubWorkflow.ps1
<#
.SYNOPSIS
Short description

.DESCRIPTION
Long description

.PARAMETER Owner
Parameter description

.PARAMETER Repo
Parameter description

.PARAMETER Token
Parameter description

.PARAMETER ID
Parameter description

.EXAMPLE
An example

.NOTES
https://docs.github.com/en/rest/reference/actions#disable-a-workflow
#>

Function Disable-GitHubWorkflow {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = $script:Owner,

        [Parameter()]
        [string] $Repo = $script:Repo,

        [Parameter()]
        [string] $Token = $script:Token,

        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string[]] $ID
    )

    begin {}

    process {
        $InputObject = @{
            Owner       = $Owner
            Repo        = $Repo
            Token       = $Token
            Method      = 'PUT'
            APIEndpoint = "repos/$Owner/$Repo/actions/workflows/$ID/disable"
        }

        $Response = Invoke-GitHubAPI @InputObject

    }
    end {
        return $Response
    }
}
#endregion - From public/Disable-GitHubWorkflow.ps1

#region - From public/Enable-GitHubWorkflow.ps1
Function Enable-GitHubWorkflow {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = $script:Owner,

        [Parameter()]
        [string] $Repo = $script:Repo,

        [Parameter()]
        [string] $Token = $script:Token,

        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string[]] $ID
    )
    begin {}
    process {
        # API Reference
        # https://docs.github.com/en/rest/reference/actions#enable-a-workflow
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/actions/workflows/$ID/enable"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'PUT'
            Body    = @{} | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        return $Response
    }
    end {}
}
#endregion - From public/Enable-GitHubWorkflow.ps1

#region - From public/Get-GitHubContext.ps1
<#
.SYNOPSIS
Get the authenticated user

.DESCRIPTION
If the authenticated user is authenticated through basic authentication or OAuth with the user scope, then the response lists public and private profile information.
If the authenticated user is authenticated through OAuth without the user scope, then the response lists only public profile information.

.PARAMETER Token
Parameter description

.EXAMPLE
An example

.NOTES
https://docs.github.com/en/rest/reference/users#get-the-authenticated-user
#>

function Get-GitHubContext {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Token = $script:Token
    )

    $InputObject = @{
        Owner       = $Owner
        Repo        = $Repo
        Token       = $Token
        Method      = 'GET'
        APIEndpoint = 'user'
    }

    $Response = Invoke-GitHubAPI @InputObject

    return $Response
}
New-Alias -Name Get-GitHubUser -Value Get-GitHubContext -Force
#endregion - From public/Get-GitHubContext.ps1

#region - From public/Get-GitHubEmojis.ps1
<#
.SYNOPSIS
Short description

.DESCRIPTION
Long description

.PARAMETER Token
Parameter description

.EXAMPLE
An example

.NOTES
https://docs.github.com/en/rest/reference/emojis#get-emojis
#>

function Get-GitHubEmojis {
    [CmdletBinding()]
    param (
        $Destination
    )

    $Response = Invoke-GitHubAPI -Method Get -APIEndpoint emojis

    if (Test-Path -Path $Destination) {
        $Response.PSobject.Properties | ForEach-Object -Parallel {
            Invoke-WebRequest -Uri $_.Value -OutFile "$using:Destination/$($_.Name).png"
        }
    }

    return $Response
}
#endregion - From public/Get-GitHubEmojis.ps1

#region - From public/Get-GitHubEnvironment.ps1
function Get-GitHubEnvironment {
    [CmdletBinding()]
    param (
        $Owner = $script:Owner,
        $Repo = $script:Repo,
        $Token = $script:Token
    )
    begin {}
    process {
        # API Reference
        # https://docs.github.com/en/rest/reference/repos#get-all-environments
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/environments"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'GET'
            Body    = @{} | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        return $Response.Environments
    }
    end {}
}
#endregion - From public/Get-GitHubEnvironment.ps1

#region - From public/Get-GitHubEnvironmentSecrets.ps1
function Get-GitHubEnvironmentSecrets {
    [CmdletBinding()]
    param (
        $Owner = $script:Owner,
        $Repo = $script:Repo,
        $Token = $script:Token ,
        [Alias('name')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $EnvironmentName
    )
    begin {}
    process {
        $RepoID = (Get-GitHubRepo).id
        #/repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}
        #/repositories/{repository_id}/environments/{environment_name}/secrets
        # API Reference
        # https://docs.github.com/en/rest/reference/repos#get-all-environments
        $APICall = @{
            Uri     = "$APIBaseURI/repositories/$RepoID/environments/$EnvironmentName/secrets"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'GET'
            Body    = @{} | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        return $Response.secrets
    }
    end {}
}
#endregion - From public/Get-GitHubEnvironmentSecrets.ps1

#region - From public/Get-GitHubRepoBranch.ps1
function Get-GitHubRepoBranch {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = $script:Owner,

        [Parameter()]
        [string] $Repo = $script:Repo,

        [Parameter()]
        [string] $Token = $script:Token
    )

    $InputObject = @{
        Owner       = $Owner
        Repo        = $Repo
        Token       = $Token
        Method      = 'Get'
        APIEndpoint = "repos/$Owner/$Repo/branches"
    }

    $Response = Invoke-GitHubAPI @InputObject

    return $Response
}
#endregion - From public/Get-GitHubRepoBranch.ps1

#region - From public/Get-GitHubRepoTeams.ps1
<#
.SYNOPSIS
Short description

.DESCRIPTION
Long description

.PARAMETER Owner
Parameter description

.PARAMETER Repo
Parameter description

.PARAMETER Token
Parameter description

.EXAMPLE
An example

.NOTES
https://docs.github.com/en/rest/reference/repos#get-a-repository
#>

function Get-GitHubRepoTeams {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = $script:Owner,

        [Parameter()]
        [string] $Repo = $script:Repo,

        [Parameter()]
        [string] $Token = $script:Token
    )

    $InputObject = @{
        Owner       = $Owner
        Repo        = $Repo
        Token       = $Token
        Method      = 'Get'
        APIEndpoint = "repos/$Owner/$Repo/teams"
    }

    $Response = Invoke-GitHubAPI @InputObject

    return $Response
}
#endregion - From public/Get-GitHubRepoTeams.ps1

#region - From public/Get-GitHubRoot.ps1
<#
.SYNOPSIS
Short description

.DESCRIPTION
Long description

.PARAMETER Token
Parameter description

.EXAMPLE
An example

.NOTES
https://docs.github.com/en/rest/reference/meta#github-api-root
#>

function Get-GitHubRoot {
    [CmdletBinding()]
    param (
        $Token = $script:Token
    )

    Invoke-GitHubAPI -Token $Token

    return $Response
}
#endregion - From public/Get-GitHubRoot.ps1

#region - From public/Get-GitHubWorkflow.ps1
<#
.SYNOPSIS
Short description

.DESCRIPTION
Long description

.PARAMETER Owner
Parameter description

.PARAMETER Repo
Parameter description

.PARAMETER Token
Parameter description

.PARAMETER Name
Parameter description

.PARAMETER ID
Parameter description

.PARAMETER PageSize
Parameter description

.EXAMPLE
An example

.NOTES
https://docs.github.com/en/rest/reference/actions#list-repository-workflows
#>

Function Get-GitHubWorkflow {
    [CmdletBinding(DefaultParameterSetName = 'ByName')]
    param (
        [Parameter()]
        [string] $Owner = $script:Owner,

        [Parameter()]
        [string] $Repo = $script:Repo,

        [Parameter()]
        [string] $Token = $script:Token,

        [Parameter(ParameterSetName = 'ByName')]
        [string] $Name,

        [Parameter(ParameterSetName = 'ByID')]
        [string] $ID,

        [Parameter()]
        [int] $PageSize = 30
    )

    $processedPages = 0
    $workflows = @()
    do {
        $processedPages += 1
        $Response = Invoke-GitHubAPI -Method GET -APIEndpoint "repos/$Owner/$Repo/actions/workflows?per_page=$PageSize&page=$processedPages"
        $workflows += $Response.workflows | Where-Object name -Match $name | Where-Object id -Match $id
    } while ($workflows.count -ne $Response.total_count)

    return $workflows
}
#endregion - From public/Get-GitHubWorkflow.ps1

#region - From public/Get-GitHubWorkflowRun.ps1
Function Get-GitHubWorkflowRun {
    [CmdletBinding()]
    param (
        $Owner = $script:Owner,
        $Repo = $script:Repo,
        $Token = $script:Token ,
        $Name,
        $ID
    )

    $Results = @()
    $i = 0
    # API Reference
    # https://docs.github.com/en/rest/reference/actions#list-workflow-runs-for-a-repository
    do {
        $i++
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/actions/runs?per_page=100&page=$i"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'GET'
            Body    = @{} | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        $WorkflowRuns = $Response.workflow_runs
        $Results += $WorkflowRuns
    } while ($WorkflowRuns.count -eq 100)
    return $Results | Where-Object Name -Match $Name | Where-Object workflow_id -Match $ID
}
#endregion - From public/Get-GitHubWorkflowRun.ps1

#region - From public/Get-GitHubWorkflowUsage.ps1
Function Get-GitHubWorkflowUsage {
    [CmdletBinding(
        DefaultParameterSetName = 'ByName'
    )]
    param (
        $Owner = $script:Owner,
        $Repo = $script:Repo,
        $Token = $script:Token ,
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string[]] $ID
    )

    begin {}
    process {
        # API Reference
        # https://docs.github.com/en/rest/reference/actions#get-workflow-usage
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/actions/workflows/$ID/timing"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'GET'
            Body    = @{} | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        return $Response.billable
    }
    end {}
}
#endregion - From public/Get-GitHubWorkflowUsage.ps1

#region - From public/Invoke-GitHubAPI.ps1
function Invoke-GitHubAPI {
    [CmdletBinding()]
    param (
        [Parameter()]
        [ValidateSet('GET', 'POST', 'PATCH', 'DELETE')]
        [String] $Method = 'GET',

        [Parameter()]
        [string] $APIEndpoint,

        [Parameter()]
        [hashtable] $Body = @{},

        [Parameter()]
        [string] $Owner = $script:Owner,

        [Parameter()]
        [string] $Repo = $script:Repo,

        [Parameter()]
        [string] $Token = $script:Token
    )
    $APICall = @{
        Uri     = ("$script:APIBaseURI/$APIEndpoint").Replace('\', '/').Replace('//', '/')
        Headers = @{
            Authorization  = "token $Token"
            'Content-Type' = 'application/vnd.github.v3+json' #'application/json'
        }
        Method  = $Method
        Body    = $Body | ConvertTo-Json -Depth 100
    }
    try {
        $Response = Invoke-RestMethod @APICall
    } catch {
        throw $_
    }
    return $Response
}
#endregion - From public/Invoke-GitHubAPI.ps1

#region - From public/Remove-GitHubWorkflowRun.ps1
function Remove-GitHubWorkflowRun {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = $script:Owner,

        [Parameter()]
        [string] $Repo = $script:Repo,

        [Parameter()]
        [string] $Token = $script:Token,

        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $ID
    )

    begin {}
    process {
        # API Reference
        # https://docs.github.com/en/rest/reference/actions#delete-a-workflow-run
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/actions/runs/$ID"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'DELETE'
            Body    = @{} | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        return $Response
    }
    end {}
}
#endregion - From public/Remove-GitHubWorkflowRun.ps1

#region - From public/Start-GitHubWorkflow.ps1


<#
.SYNOPSIS
#

.DESCRIPTION
Long description

.PARAMETER Owner
Parameter description

.PARAMETER Repo
Parameter description

.PARAMETER Token
Parameter description

.PARAMETER ID
Parameter description

.PARAMETER Ref
Parameter description

.PARAMETER Inputs
Parameter description

.EXAMPLE
Get-GitHubWorkflow | Where-Object name -NotLike '.*' | Start-GitHubWorkflow -Inputs @{
    staticValidation = $true
    deploymentValidation = $false
    removeDeployment = $true
    prerelease = $false
}



.NOTES
General notes
#>

function Start-GitHubWorkflow {
    [CmdletBinding()]
    param (
        $Owner = $script:Owner,
        $Repo = $script:Repo,
        $Token = $script:Token ,
        [Alias('workflow_id')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $ID,

        [Parameter(
            ValueFromPipelineByPropertyName
        )]
        [Alias('branch', 'tag')]
        [string] $Ref = 'main',

        [Parameter()]
        [hashtable] $Inputs = @{}
    )
    begin {}
    process {
        # API Reference
        # https://docs.github.com/en/free-pro-team@latest/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/actions/workflows/$ID/dispatches"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'POST'
            Body    = @{
                ref    = $Ref
                inputs = $Inputs
            } | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        return $Response
    }
    end {}
}
#endregion - From public/Start-GitHubWorkflow.ps1

#region - From public/Start-GitHubWorkflowReRun.ps1
function Start-GitHubWorkflowReRun {
    [CmdletBinding()]
    param (
        $Owner = $script:Owner,
        $Repo = $script:Repo,
        $Token = $script:Token ,
        [Alias('workflow_id')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $ID
    )
    begin {}
    process {
        # API Reference
        # https://docs.github.com/en/rest/reference/actions#re-run-a-workflow
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/actions/runs/$ID/rerun"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'POST'
            Body    = @{} | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        return $Response
    }
    end {}
}
#endregion - From public/Start-GitHubWorkflowReRun.ps1

#region - From public/Stop-GitHubWorkflowRun.ps1
function Stop-GitHubWorkflowRun {
    [CmdletBinding()]
    [alias('Cancel-GitHubWorkflowRun')]
    param (
        $Owner = $script:Owner,
        $Repo = $script:Repo,
        $Token = $script:Token ,
        [Alias('workflow_id')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $ID
    )
    begin {}
    process {
        # API Reference
        # https://docs.github.com/en/rest/reference/actions#cancel-a-workflow-run
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/actions/runs/$ID/cancel"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'POST'
            Body    = @{} | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        return $Response
    }
    end {}
}
#endregion - From public/Stop-GitHubWorkflowRun.ps1

#region - From public/Update-GitHubEnvironment.ps1
function Update-GitHubEnvironment {
    [CmdletBinding()]
    param (
        $Owner = $script:Owner,
        $Repo = $script:Repo,
        $Token = $script:Token ,
        [Alias('environment_name')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $Name
    )
    begin {}
    process {
        # API Reference
        # https://docs.github.com/en/rest/reference/repos#create-or-update-an-environment
        $APICall = @{
            Uri     = "$APIBaseURI/repos/$Owner/$Repo/environments/$Name"
            Headers = @{
                Authorization  = "token $Token"
                'Content-Type' = 'application/json'
            }
            Method  = 'PUT'
            Body    = @{
                owner            = $Owner
                repo             = $Repo
                environment_name = $Name
            } | ConvertTo-Json -Depth 100
        }
        try {
            if ($PSBoundParameters.ContainsKey('Verbose')) {
                $APICall
            }
            $Response = Invoke-RestMethod @APICall
        } catch {
            throw $_
        }
        $Response
    }
    end {}
}
#endregion - From public/Update-GitHubEnvironment.ps1

Export-ModuleMember -Function 'Connect-GitHubAccount','Disable-GitHubWorkflow','Enable-GitHubWorkflow','Get-GitHubContext','Get-GitHubEmojis','Get-GitHubEnvironment','Get-GitHubEnvironmentSecrets','Get-GitHubRepoBranch','Get-GitHubRepoTeams','Get-GitHubRoot','Get-GitHubWorkflow','Get-GitHubWorkflowRun','Get-GitHubWorkflowUsage','Invoke-GitHubAPI','Remove-GitHubWorkflowRun','Start-GitHubWorkflow','Start-GitHubWorkflowReRun','Stop-GitHubWorkflowRun','Update-GitHubEnvironment' -Cmdlet '*' -Variable '*' -Alias '*'