GitHub.psm1
[Cmdletbinding()] param() $scriptName = $MyInvocation.MyCommand.Name Write-Verbose "[$scriptName] Importing subcomponents" #region - Data import Write-Verbose "[$scriptName] - [data] - Processing folder" $dataFolder = (Join-Path $PSScriptRoot 'data') Write-Verbose "[$scriptName] - [data] - [$dataFolder]" Get-ChildItem -Path "$dataFolder" -Recurse -Force -Include '*.psd1' -ErrorAction SilentlyContinue | ForEach-Object { Write-Verbose "[$scriptName] - [data] - [$($_.Name)] - Importing" New-Variable -Name $_.BaseName -Value (Import-PowerShellDataFile -Path $_.FullName) -Force Write-Verbose "[$scriptName] - [data] - [$($_.Name)] - Done" } Write-Verbose "[$scriptName] - [data] - Done" #endregion - Data import #region - From private Write-Verbose "[$scriptName] - [private] - Processing folder" #region - From private/Auth Write-Verbose "[$scriptName] - [private/Auth] - Processing folder" #region - From private/Auth/DeviceFlow Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow] - Processing folder" #region - From private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1] - Importing" function Invoke-GitHubDeviceFlowLogin { <# .SYNOPSIS Starts the GitHub Device Flow login process. .DESCRIPTION Starts the GitHub Device Flow login process. This will prompt the user to visit a URL and enter a code. .EXAMPLE Invoke-GitHubDeviceFlowLogin This will start the GitHub Device Flow login process. The user gets prompted to visit a URL and enter a code. .NOTES For more info about the Device Flow visit: https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#device-flow #> [OutputType([void])] [CmdletBinding()] param( # The Client ID of the GitHub App. [Parameter(Mandatory)] [string] $ClientID, # The scope of the access token, when using OAuth authentication. # Provide the list of scopes as space-separated values. # For more information on scopes visit: # https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps [Parameter()] [string] $Scope, # The refresh token to use for re-authentication. [Parameter()] [securestring] $RefreshToken ) do { if ($RefreshToken) { $tokenResponse = Wait-GitHubAccessToken -ClientID $ClientID -RefreshToken $RefreshToken } else { $deviceCodeResponse = Request-GitHubDeviceCode -ClientID $ClientID -Scope $Scope $deviceCode = $deviceCodeResponse.device_code $interval = $deviceCodeResponse.interval $userCode = $deviceCodeResponse.user_code $verificationUri = $deviceCodeResponse.verification_uri Write-Host '! ' -ForegroundColor DarkYellow -NoNewline Write-Host "We added the code to your clipboard: [$userCode]" $userCode | Set-Clipboard Read-Host 'Press Enter to open github.com in your browser...' Start-Process $verificationUri $tokenResponse = Wait-GitHubAccessToken -DeviceCode $deviceCode -ClientID $ClientID -Interval $interval } } while ($tokenResponse.error) $tokenResponse } Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1] - Done" #endregion - From private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 #region - From private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1 Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1] - Importing" function Request-GitHubAccessToken { <# .SYNOPSIS Request a GitHub token using the Device Flow. .DESCRIPTION Request a GitHub token using the Device Flow. This will poll the GitHub API until the user has entered the code. .EXAMPLE Request-GitHubAccessToken -DeviceCode $deviceCode -ClientID $ClientID This will poll the GitHub API until the user has entered the code. .NOTES For more info about the Device Flow visit: https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app #> [OutputType([PSCustomObject])] [CmdletBinding(DefaultParameterSetName = 'DeviceFlow')] param( # The Client ID of the GitHub App. [Parameter(Mandatory)] [string] $ClientID, # The 'device_code' used to request the access token. [Parameter( Mandatory, ParameterSetName = 'DeviceFlow' )] [string] $DeviceCode, # The refresh token used create a new access token. [Parameter( Mandatory, ParameterSetName = 'RefreshToken' )] [securestring] $RefreshToken ) $body = @{ 'client_id' = $ClientID } if ($PSBoundParameters.ContainsKey('RefreshToken')) { $body += @{ 'refresh_token' = (ConvertFrom-SecureString $RefreshToken -AsPlainText) 'grant_type' = 'refresh_token' } } if ($PSBoundParameters.ContainsKey('DeviceCode')) { $body += @{ 'device_code' = $DeviceCode 'grant_type' = 'urn:ietf:params:oauth:grant-type:device_code' } } $RESTParams = @{ Uri = 'https://github.com/login/oauth/access_token' Method = 'POST' Body = $body Headers = @{ 'Accept' = 'application/json' } } try { Write-Verbose ($RESTParams.GetEnumerator() | Out-String) $tokenResponse = Invoke-RestMethod @RESTParams -Verbose:$false Write-Verbose ($tokenResponse | ConvertTo-Json | Out-String) return $tokenResponse } catch { Write-Error $_ throw $_ } } Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1] - Done" #endregion - From private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1 #region - From private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1 Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1] - Importing" function Request-GitHubDeviceCode { <# .SYNOPSIS Request a GitHub Device Code. .DESCRIPTION Request a GitHub Device Code. .EXAMPLE Request-GitHubDeviceCode -ClientID $ClientID -Mode $Mode This will request a GitHub Device Code. .NOTES For more info about the Device Flow visit: https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app #> [OutputType([PSCustomObject])] [CmdletBinding()] param( # The Client ID of the GitHub App. [Parameter(Mandatory)] [string] $ClientID, # The scope of the access token, when using OAuth authentication. # Provide the list of scopes as space-separated values. # For more information on scopes visit: # https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps [Parameter()] [string] $Scope = 'gist, read:org, repo, workflow' ) $headers = @{ Accept = 'application/json' } $body = @{ client_id = $ClientID scope = $Scope } $RESTParams = @{ Uri = 'https://github.com/login/device/code' Method = 'POST' Body = $body Headers = $headers } try { Write-Verbose ($RESTParams.GetEnumerator() | Out-String) $deviceCodeResponse = Invoke-RestMethod @RESTParams -Verbose:$false return $deviceCodeResponse } catch { Write-Error $_ throw $_ } } Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1] - Done" #endregion - From private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1 #region - From private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1 Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1] - Importing" function Wait-GitHubAccessToken { <# .SYNOPSIS Waits for the GitHub Device Flow to complete. .DESCRIPTION Waits for the GitHub Device Flow to complete. This will poll the GitHub API until the user has entered the code. .EXAMPLE Wait-GitHubAccessToken -DeviceCode $deviceCode -ClientID $ClientID -Interval $interval This will poll the GitHub API until the user has entered the code. .EXAMPLE Wait-GitHubAccessToken -Refresh -ClientID $ClientID .NOTES For more info about the Device Flow visit: https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app #> [OutputType([PSCustomObject])] [CmdletBinding(DefaultParameterSetName = 'DeviceFlow')] param( # The Client ID of the GitHub App. [Parameter(Mandatory)] [string] $ClientID, # The device code used to request the access token. [Parameter( Mandatory, ParameterSetName = 'DeviceFlow' )] [string] $DeviceCode, # The refresh token used to request a new access token. [Parameter( Mandatory, ParameterSetName = 'RefreshToken' )] [securestring] $RefreshToken, # The interval to wait between polling for the token. [Parameter()] [int] $Interval = 5 ) do { if ($RefreshToken) { $response = Request-GitHubAccessToken -ClientID $ClientID -RefreshToken $RefreshToken } else { $response = Request-GitHubAccessToken -ClientID $ClientID -DeviceCode $DeviceCode } if ($response.error) { switch ($response.error) { 'authorization_pending' { # The user has not yet entered the code. # Wait, then poll again. Write-Verbose $response.error_description Start-Sleep -Seconds $interval continue } 'slow_down' { # The app polled too fast. # Wait for the interval plus 5 seconds, then poll again. Write-Verbose $response.error_description Start-Sleep -Seconds ($interval + 5) continue } 'expired_token' { # The 'device_code' expired, and the process needs to restart. Write-Error $response.error_description exit 1 } 'unsupported_grant_type' { # The 'grant_type' is not supported. Write-Error $response.error_description exit 1 } 'incorrect_client_credentials' { # The 'client_id' is not valid. Write-Error $response.error_description exit 1 } 'incorrect_device_code' { # The 'device_code' is not valid. Write-Error $response.error_description exit 2 } 'access_denied' { # The user cancelled the process. Stop polling. Write-Error $response.error_description exit 1 } 'device_flow_disabled' { # The GitHub App does not support the Device Flow. Write-Error $response.error_description exit 1 } default { # The response contains an access token. Stop polling. Write-Error 'Unknown error:' Write-Error $response.error Write-Error $response.error_description Write-Error $response.error_uri break } } } } until ($response.access_token) $response } Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1] - Done" #endregion - From private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1 Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow] - Done" #endregion - From private/Auth/DeviceFlow Write-Verbose "[$scriptName] - [private/Auth] - Done" #endregion - From private/Auth #region - From private/Config Write-Verbose "[$scriptName] - [private/Config] - Processing folder" #region - From private/Config/Initialize-SecretVault.ps1 Write-Verbose "[$scriptName] - [private/Config/Initialize-SecretVault.ps1] - Importing" #Requires -Version 7.0 #Requires -Modules Microsoft.PowerShell.SecretManagement #Requires -Modules Microsoft.PowerShell.SecretStore function Initialize-SecretVault { <# .SYNOPSIS Initialize a secret vault. .DESCRIPTION Initialize a secret vault. If the vault does not exist, it will be created. .EXAMPLE Initialize-SecretVault -Name 'SecretStore' -Type 'Microsoft.PowerShell.SecretStore' Initializes a secret vault named 'SecretStore' using the 'Microsoft.PowerShell.SecretStore' module. .NOTES For more information about secret vaults, see https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/overview?view=ps-modules #> [OutputType([void])] [CmdletBinding()] param ( # The name of the secret vault. [Parameter()] [string] $Name = 'SecretStore', # The type of the secret vault. [Parameter()] [Alias('ModuleName')] [string] $Type = 'Microsoft.PowerShell.SecretStore' ) $functionName = $MyInvocation.MyCommand.Name $vault = Get-SecretVault | Where-Object { $_.ModuleName -eq $Type } if (-not $vault) { Write-Verbose "[$functionName] - [$Type] - Registering" switch ($Type) { 'Microsoft.PowerShell.SecretStore' { $vaultParameters = @{ Authentication = 'None' PasswordTimeout = -1 Interaction = 'None' Scope = 'CurrentUser' WarningAction = 'SilentlyContinue' Confirm = $false Force = $true } Reset-SecretStore @vaultParameters } } Write-Verbose "[$functionName] - [$Type] - Done" } else { Write-Verbose "[$functionName] - [$Type] - already registered" } $secretStore = Get-SecretVault | Where-Object { $_.Name -eq $Name } if (-not $secretStore) { Write-Verbose "[$functionName] - [$Name] - Registering" $secretVault = @{ Name = $Name ModuleName = $Type DefaultVault = $true Description = 'SecretStore' } Register-SecretVault @secretVault Write-Verbose "[$functionName] - [$Name] - Done" } else { Write-Verbose "[$functionName] - [$Name] - already registered" } } Write-Verbose "[$scriptName] - [private/Config/Initialize-SecretVault.ps1] - Done" #endregion - From private/Config/Initialize-SecretVault.ps1 #region - From private/Config/Reset-GitHubConfig.ps1 Write-Verbose "[$scriptName] - [private/Config/Reset-GitHubConfig.ps1] - Importing" function Reset-GitHubConfig { <# .SYNOPSIS Reset the GitHub configuration. .DESCRIPTION Reset the GitHub configuration. Specific scopes can be reset by using the Scope parameter. .EXAMPLE Reset-GitHubConfig Resets the entire GitHub configuration. .EXAMPLE Reset-GitHubConfig -Scope 'Auth' Resets the Auth related variables of the GitHub configuration. #> [Alias('Reset-GHConfig')] [OutputType([void])] [CmdletBinding()] param( # Reset the GitHub configuration for a specific scope. [Parameter()] [ValidateSet('Auth', 'All')] [string] $Scope = 'All' ) Write-Verbose "Resetting GitHub configuration for scope '$Scope'..." switch ($Scope) { 'Auth' { $Settings = @{ AccessToken = [securestring]::new() AccessTokenExpirationDate = [datetime]::MinValue AccessTokenType = '' AuthType = '' DeviceFlowType = '' RefreshToken = [securestring]::new() RefreshTokenExpirationDate = [datetime]::MinValue Scope = '' } } 'All' { $Settings = @{ AccessToken = [securestring]::new() AccessTokenExpirationDate = [datetime]::MinValue AccessTokenType = '' ApiBaseUri = 'https://api.github.com' ApiVersion = '2022-11-28' AuthType = '' DeviceFlowType = '' Owner = '' RefreshToken = [securestring]::new() RefreshTokenExpirationDate = [datetime]::MinValue Repo = '' Scope = '' UserName = '' } } } Set-GitHubConfig @Settings } Write-Verbose "[$scriptName] - [private/Config/Reset-GitHubConfig.ps1] - Done" #endregion - From private/Config/Reset-GitHubConfig.ps1 Write-Verbose "[$scriptName] - [private/Config] - Done" #endregion - From private/Config #region - From private/Menu Write-Verbose "[$scriptName] - [private/Menu] - Processing folder" #region - From private/Menu/Invoke-DrawMenu.ps1 Write-Verbose "[$scriptName] - [private/Menu/Invoke-DrawMenu.ps1] - Importing" function Invoke-DrawMenu { ## supportfunction to the Menu function below param ( $menuItems, $menuPosition, $menuTitel ) $fcolor = $host.UI.RawUI.ForegroundColor $bcolor = $host.UI.RawUI.BackgroundColor $l = $menuItems.length + 1 Clear-Host $menuwidth = $menuTitel.length + 4 Write-Host "`t" -NoNewline Write-Host ('*' * $menuwidth) -fore $fcolor -back $bcolor Write-Host "`t" -NoNewline Write-Host "* $menuTitel *" -fore $fcolor -back $bcolor Write-Host "`t" -NoNewline Write-Host ('*' * $menuwidth) -fore $fcolor -back $bcolor Write-Host '' Write-Debug "L: $l MenuItems: $menuItems MenuPosition: $menuposition" for ($i = 0; $i -le $l; $i++) { Write-Host "`t" -NoNewline if ($i -eq $menuPosition) { Write-Host "$($menuItems[$i])" -fore $bcolor -back $fcolor } else { Write-Host "$($menuItems[$i])" -fore $fcolor -back $bcolor } } } Write-Verbose "[$scriptName] - [private/Menu/Invoke-DrawMenu.ps1] - Done" #endregion - From private/Menu/Invoke-DrawMenu.ps1 #region - From private/Menu/Invoke-Meny.ps1 Write-Verbose "[$scriptName] - [private/Menu/Invoke-Meny.ps1] - Importing" function Menu { ## Generate a small "DOS-like" menu. ## Choose a menuitem using up and down arrows, select by pressing ENTER param ( [array]$menuItems, $menuTitel = 'MENU' ) $vkeycode = 0 $pos = 0 Invoke-DrawMenu $menuItems $pos $menuTitel while ($vkeycode -ne 13) { $press = $host.ui.rawui.readkey('NoEcho,IncludeKeyDown') $vkeycode = $press.virtualkeycode Write-Host "$($press.character)" -NoNewline if ($vkeycode -eq 38) { $pos-- } if ($vkeycode -eq 40) { $pos++ } if ($pos -lt 0) { $pos = 0 } if ($pos -ge $menuItems.length) { $pos = $menuItems.length - 1 } Invoke-DrawMenu $menuItems $pos $menuTitel } Write-Output $($menuItems[$pos]) } <# ? What account do you want to log into? [Use arrows to move, type to filter] > GitHub.com GitHub Enterprise Server #> Write-Verbose "[$scriptName] - [private/Menu/Invoke-Meny.ps1] - Done" #endregion - From private/Menu/Invoke-Meny.ps1 Write-Verbose "[$scriptName] - [private/Menu] - Done" #endregion - From private/Menu #region - From private/Utilities Write-Verbose "[$scriptName] - [private/Utilities] - Processing folder" #region - From private/Utilities/ConvertFrom-HashTable.ps1 Write-Verbose "[$scriptName] - [private/Utilities/ConvertFrom-HashTable.ps1] - Importing" function ConvertFrom-HashTable { [CmdletBinding()] param ( [Parameter( Mandatory, ValueFromPipeline )] [object]$InputObject ) ([pscustomobject](@{} + $InputObject)) } Write-Verbose "[$scriptName] - [private/Utilities/ConvertFrom-HashTable.ps1] - Done" #endregion - From private/Utilities/ConvertFrom-HashTable.ps1 #region - From private/Utilities/ConvertTo-HashTable.ps1 Write-Verbose "[$scriptName] - [private/Utilities/ConvertTo-HashTable.ps1] - Importing" function ConvertTo-HashTable { [CmdletBinding()] param ( [Parameter( Mandatory, ValueFromPipeline )] [pscustomobject]$InputObject ) [hashtable]$hashtable = @{} foreach ($item in $InputObject.PSobject.Properties) { Write-Verbose "$($item.Name) : $($item.Value) : $($item.TypeNameOfValue)" $hashtable.$($item.Name) = $item.Value } $hashtable } Write-Verbose "[$scriptName] - [private/Utilities/ConvertTo-HashTable.ps1] - Done" #endregion - From private/Utilities/ConvertTo-HashTable.ps1 #region - From private/Utilities/Join-Hashtable.ps1 Write-Verbose "[$scriptName] - [private/Utilities/Join-Hashtable.ps1] - Importing" function Join-Hashtable { [OutputType([void])] [Alias('Merge-HashTable')] [CmdletBinding()] param ( [hashtable] $Main, [hashtable] $Overrides ) $hashtable = @{} $Main.Keys | ForEach-Object { $hashtable[$_] = $Main[$_] } $Overrides.Keys | ForEach-Object { $hashtable[$_] = $Overrides[$_] } $hashtable } Write-Verbose "[$scriptName] - [private/Utilities/Join-Hashtable.ps1] - Done" #endregion - From private/Utilities/Join-Hashtable.ps1 #region - From private/Utilities/Remove-HashTableEntries.ps1 Write-Verbose "[$scriptName] - [private/Utilities/Remove-HashTableEntries.ps1] - Importing" function Remove-HashtableEntries { [OutputType([void])] [CmdletBinding()] param ( [Parameter( Mandatory, ValueFromPipeline )] [hashtable] $Hashtable, [Parameter()] [switch] $NullOrEmptyValues, [Parameter()] [string[]] $RemoveTypes, [Parameter()] [string[]] $RemoveNames, [Parameter()] [string[]] $KeepTypes, [Parameter()] [string[]] $KeepNames ) if ($NullOrEmptyValues) { Write-Verbose 'Remove keys with null or empty values' ($Hashtable.GetEnumerator() | Where-Object { -not $_.Value }) | ForEach-Object { Write-Verbose " - [$($_.Name)] - Value: [$($_.Value)] - Remove" $Hashtable.Remove($_.Name) } } if ($RemoveTypes) { Write-Verbose "Remove keys of type: [$RemoveTypes]" ($Hashtable.GetEnumerator() | Where-Object { ($_.Value.GetType().Name -in $RemoveTypes) }) | ForEach-Object { Write-Verbose " - [$($_.Name)] - Type: [$($_.Value.GetType().Name)] - Remove" $Hashtable.Remove($_.Name) } } if ($KeepTypes) { Write-Verbose "Remove keys NOT of type: [$KeepTypes]" ($Hashtable.GetEnumerator() | Where-Object { ($_.Value.GetType().Name -notin $KeepTypes) }) | ForEach-Object { Write-Verbose " - [$($_.Name)] - Type: [$($_.Value.GetType().Name)] - Remove" $Hashtable.Remove($_.Name) } } if ($RemoveNames) { Write-Verbose "Remove keys named: [$RemoveNames]" ($Hashtable.GetEnumerator() | Where-Object { $_.Name -in $RemoveNames }) | ForEach-Object { Write-Verbose " - [$($_.Name)] - Remove" $Hashtable.Remove($_.Name) } } if ($KeepNames) { Write-Verbose "Remove keys NOT named: [$KeepNames]" ($Hashtable.GetEnumerator() | Where-Object { $_.Name -notin $KeepNames }) | ForEach-Object { Write-Verbose " - [$($_.Name)] - Remove" $Hashtable.Remove($_.Name) } } } Write-Verbose "[$scriptName] - [private/Utilities/Remove-HashTableEntries.ps1] - Done" #endregion - From private/Utilities/Remove-HashTableEntries.ps1 Write-Verbose "[$scriptName] - [private/Utilities] - Done" #endregion - From private/Utilities Write-Verbose "[$scriptName] - [private] - Done" #endregion - From private #region - From public Write-Verbose "[$scriptName] - [public] - Processing folder" #region - From public/Actions Write-Verbose "[$scriptName] - [public/Actions] - Processing folder" #region - From public/Actions/Disable-GitHubWorkflow.ps1 Write-Verbose "[$scriptName] - [public/Actions/Disable-GitHubWorkflow.ps1] - Importing" Function Disable-GitHubWorkflow { <# .NOTES https://docs.github.com/en/rest/reference/actions#disable-a-workflow #> [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string[]] $ID ) begin {} process { $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/disable" Method = 'PUT' } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Actions/Disable-GitHubWorkflow.ps1] - Done" #endregion - From public/Actions/Disable-GitHubWorkflow.ps1 #region - From public/Actions/Enable-GitHubWorkflow.ps1 Write-Verbose "[$scriptName] - [public/Actions/Enable-GitHubWorkflow.ps1] - Importing" Function Enable-GitHubWorkflow { <# .NOTES https://docs.github.com/en/rest/reference/actions#enable-a-workflow #> [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string[]] $ID ) begin {} process { $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/enable" Method = 'PUT' } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Actions/Enable-GitHubWorkflow.ps1] - Done" #endregion - From public/Actions/Enable-GitHubWorkflow.ps1 #region - From public/Actions/Get-GitHubWorkflow.ps1 Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflow.ps1] - Importing" function Get-GitHubWorkflow { <# .SYNOPSIS Lists the workflows in a repository. .DESCRIPTION Anyone with read access to the repository can use this endpoint. If the repository is private you must use an access token with the repo scope. GitHub Apps must have the actions:read permission to use this endpoint. .EXAMPLE Get-GitHubWorkflow -Owner 'octocat' -Repo 'hello-world' Gets all workflows in the 'octocat/hello-world' repository. .EXAMPLE Get-GitHubWorkflow -Owner 'octocat' -Repo 'hello-world' -Name 'hello-world.yml' Gets the 'hello-world.yml' workflow in the 'octocat/hello-world' repository. .NOTES https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#list-repository-workflows #> [CmdletBinding(DefaultParameterSetName = 'ByName')] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Parameter(ParameterSetName = 'ByName')] [string] $Name, [Parameter(ParameterSetName = 'ByID')] [string] $ID, [Parameter()] [int] $PerPage = 100 ) begin {} process { $body = @{ per_page = $PerPage } $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/actions/workflows" Method = 'GET' Body = $body } Invoke-GitHubAPI @inputObject | Select-Object -ExpandProperty workflows | Write-Output } } Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflow.ps1] - Done" #endregion - From public/Actions/Get-GitHubWorkflow.ps1 #region - From public/Actions/Get-GitHubWorkflowRun.ps1 Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflowRun.ps1] - Importing" Function Get-GitHubWorkflowRun { <# .NOTES https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository #> [CmdletBinding(DefaultParameterSetName = 'Repo')] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Parameter(ParameterSetName = 'ByName')] [string] $Name, [Parameter(ParameterSetName = 'ByID')] [string] $ID, [Parameter()] [int] $PerPage = 100 ) begin {} process { $body = @{ per_page = $PerPage } if ($Name) { $ID = (Get-GitHubWorkflow -Owner $Owner -Repo $Repo -Name $Name).id } if ($ID) { $Uri = "/repos/$Owner/$Repo/actions/workflows/$ID/runs" } else { $Uri = "/repos/$Owner/$Repo/actions/runs" } $inputObject = @{ APIEndpoint = $Uri Method = 'GET' Body = $body } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflowRun.ps1] - Done" #endregion - From public/Actions/Get-GitHubWorkflowRun.ps1 #region - From public/Actions/Get-GitHubWorkflowUsage.ps1 Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflowUsage.ps1] - Importing" Function Get-GitHubWorkflowUsage { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Owner Parameter description .PARAMETER Repo Parameter description .PARAMETER ID Parameter description .EXAMPLE An example .NOTES https://docs.github.com/en/rest/reference/actions#get-workflow-usage #> [CmdletBinding( DefaultParameterSetName = 'ByName' )] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string[]] $ID ) begin {} process { $inputObject = @{ Method = 'GET' APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/timing" } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflowUsage.ps1] - Done" #endregion - From public/Actions/Get-GitHubWorkflowUsage.ps1 #region - From public/Actions/Remove-GitHubWorkflowRun.ps1 Write-Verbose "[$scriptName] - [public/Actions/Remove-GitHubWorkflowRun.ps1] - Importing" function Remove-GitHubWorkflowRun { [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string] $ID ) begin {} process { $inputObject = @{ APIEndpoint = "repos/$Owner/$Repo/actions/runs/$ID" Method = 'DELETE' } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Actions/Remove-GitHubWorkflowRun.ps1] - Done" #endregion - From public/Actions/Remove-GitHubWorkflowRun.ps1 #region - From public/Actions/Start-GitHubWorkflow.ps1 Write-Verbose "[$scriptName] - [public/Actions/Start-GitHubWorkflow.ps1] - Importing" function Start-GitHubWorkflow { <# .SYNOPSIS Start a workflow run using the workflow's ID. .DESCRIPTION Start a workflow run using the workflow's ID. .EXAMPLE Get-GitHubWorkflow | Where-Object name -NotLike '.*' | Start-GitHubWorkflow -Inputs @{ staticValidation = $true deploymentValidation = $false removeDeployment = $true prerelease = $false } .NOTES # API Reference # https://docs.github.com/en/free-pro-team@latest/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event #> [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Alias('workflow_id')] [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string] $ID, [Parameter( ValueFromPipelineByPropertyName )] [Alias('branch', 'tag')] [string] $Ref = 'main', [Parameter()] [hashtable] $Inputs = @{} ) begin {} process { $body = @{ ref = $Ref inputs = $Inputs } $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/dispatches" Method = 'POST' Body = $body } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Actions/Start-GitHubWorkflow.ps1] - Done" #endregion - From public/Actions/Start-GitHubWorkflow.ps1 #region - From public/Actions/Start-GitHubWorkflowReRun.ps1 Write-Verbose "[$scriptName] - [public/Actions/Start-GitHubWorkflowReRun.ps1] - Importing" function Start-GitHubWorkflowReRun { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Owner Parameter description .PARAMETER Repo Parameter description .PARAMETER ID Parameter description .EXAMPLE An example .NOTES https://docs.github.com/en/rest/reference/actions#re-run-a-workflow #> [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Alias('workflow_id')] [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string] $ID ) begin {} process { $inputObject = @{ Method = 'POST' APIEndpoint = "/repos/$Owner/$Repo/actions/runs/$ID/rerun" } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Actions/Start-GitHubWorkflowReRun.ps1] - Done" #endregion - From public/Actions/Start-GitHubWorkflowReRun.ps1 #region - From public/Actions/Stop-GitHubWorkflowRun.ps1 Write-Verbose "[$scriptName] - [public/Actions/Stop-GitHubWorkflowRun.ps1] - Importing" function Stop-GitHubWorkflowRun { <# .SYNOPSIS Short description .DESCRIPTION Long description .PARAMETER Owner Parameter description .PARAMETER Repo Parameter description .PARAMETER ID Parameter description .EXAMPLE An example .NOTES https://docs.github.com/en/rest/reference/actions#cancel-a-workflow-run #> [CmdletBinding()] [alias('Cancel-GitHubWorkflowRun')] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Alias('workflow_id')] [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string] $ID ) begin {} process { $inputObject = @{ Method = 'POST' APIEndpoint = "/repos/$Owner/$Repo/actions/runs/$ID/cancel" } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Actions/Stop-GitHubWorkflowRun.ps1] - Done" #endregion - From public/Actions/Stop-GitHubWorkflowRun.ps1 Write-Verbose "[$scriptName] - [public/Actions] - Done" #endregion - From public/Actions #region - From public/API Write-Verbose "[$scriptName] - [public/API] - Processing folder" #region - From public/API/Invoke-GitHubAPI.ps1 Write-Verbose "[$scriptName] - [public/API/Invoke-GitHubAPI.ps1] - Importing" function Invoke-GitHubAPI { <# .SYNOPSIS Calls the GitHub API using the provided parameters. .DESCRIPTION This function is a wrapper around Invoke-RestMethod tailored for calling GitHub's API. It automatically handles the endpoint URI construction, headers, and token authentication. .EXAMPLE Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET Gets all open pull requests for the specified repository. .EXAMPLE Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET -Body @{ state = 'open' } Gets all open pull requests for the specified repository, filtered by the 'state' parameter. .EXAMPLE Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET -Body @{ state = 'open' } -Accept 'application/vnd.github.v3+json' Gets all open pull requests for the specified repository, filtered by the 'state' parameter, and using the specified 'Accept' header. #> [CmdletBinding()] param ( # The HTTP method to be used for the API request. It can be one of the following: GET, POST, PUT, DELETE, or PATCH. [Parameter()] [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = 'GET', # The base URI for the GitHub API. This is usually 'https://api.github.com', but can be adjusted if necessary. [Parameter()] [string] $ApiBaseUri = (Get-GitHubConfig -Name ApiBaseUri), # The specific endpoint for the API call, e.g., '/repos/user/repo/pulls'. [Parameter(Mandatory)] [string] $ApiEndpoint, # The body of the API request. This can be a hashtable or a string. If a hashtable is provided, it will be converted to JSON. [Parameter()] [Object] $Body, # The 'Accept' header for the API request. If not provided, the default will be used by GitHub's API. [Parameter()] [string] $Accept = 'application/vnd.github+json', # Specifies the HTTP version used for the request. [Parameter()] [version] $HttpVersion = '2.0', # Support Pagination Relation Links per RFC5988. [Parameter()] [bool] $FollowRelLink = $true, # The secure token used for authentication in the GitHub API. It should be stored as a SecureString to ensure it's kept safe in memory. [Parameter()] [SecureString] $AccessToken = (Get-GitHubConfig -Name AccessToken), # The 'Content-Type' header for the API request. The default is 'application/vnd.github+json'. [Parameter()] [string] $ContentType = 'application/vnd.github+json', # The GitHub API version to be used. By default, it pulls from a configuration script variable. [Parameter()] [string] $Version = (Get-GitHubConfig -Name ApiVersion) ) $functionName = $MyInvocation.MyCommand.Name $headers = @{ Accept = $Accept 'X-GitHub-Api-Version' = $Version } Remove-HashTableEntries -Hashtable $headers -NullOrEmptyValues $URI = ("$ApiBaseUri/" -replace '/$', '') + ("/$ApiEndpoint" -replace '^/', '') # $AccessTokenAsPlainText = ConvertFrom-SecureString $AccessToken -AsPlainText # # Swap out this by using the -Authentication Bearer -Token $AccessToken # switch -Regex ($AccessTokenAsPlainText) { # '^ghp_|^github_pat_' { # $headers.authorization = "token $AccessTokenAsPlainText" # } # '^ghu_|^gho_' { # $headers.authorization = "Bearer $AccessTokenAsPlainText" # } # default { # $tokenPrefix = $AccessTokenAsPlainText -replace '_.*$', '_*' # $errorMessage = "Unexpected AccessToken format: $tokenPrefix" # Write-Error $errorMessage # throw $errorMessage # } # } $APICall = @{ Uri = $URI Method = $Method Headers = $Headers Authentication = 'Bearer' Token = $AccessToken ContentType = $ContentType HttpVersion = $HttpVersion FollowRelLink = $FollowRelLink StatusCodeVariable = 'StatusCode' ResponseHeadersVariable = 'ResponseHeaders' } $APICall | Remove-HashTableEntries -NullOrEmptyValues if ($Body) { $Body | Remove-HashTableEntries -NullOrEmptyValues # Use body to create the query string for GET requests if ($Method -eq 'GET') { $queryParams = ($Body.GetEnumerator() | ForEach-Object { "$([System.Web.HttpUtility]::UrlEncode($_.Key))=$([System.Web.HttpUtility]::UrlEncode($_.Value))" }) -join '&' if ($queryParams) { $APICall.Uri = $APICall.Uri + '?' + $queryParams } } if ($Body -is [string]) { $APICall.Body = $Body } else { $APICall.Body = $Body | ConvertTo-Json -Depth 100 } } try { Invoke-RestMethod @APICall | Write-Output Write-Verbose ($StatusCode | ConvertTo-Json -Depth 100) Write-Verbose ($responseHeaders | ConvertTo-Json -Depth 100) } catch [System.Net.WebException] { Write-Error "[$functionName] - WebException - $($_.Exception.Message)" throw $_ } catch { Write-Error "[$functionName] - GeneralException - $_" $err = $_ | ConvertFrom-Json -Depth 10 Write-Error "[$functionName] - $($err.Message)" Write-Error "[$functionName] - For more info please see: [$($err.documentation_url)]" throw $_ } } Write-Verbose "[$scriptName] - [public/API/Invoke-GitHubAPI.ps1] - Done" #endregion - From public/API/Invoke-GitHubAPI.ps1 Write-Verbose "[$scriptName] - [public/API] - Done" #endregion - From public/API #region - From public/Auth Write-Verbose "[$scriptName] - [public/Auth] - Processing folder" #region - From public/Auth/Connect-GitHubAccount.ps1 Write-Verbose "[$scriptName] - [public/Auth/Connect-GitHubAccount.ps1] - Importing" function Connect-GitHubAccount { <# .SYNOPSIS Connects to GitHub using a personal access token or device code login. .DESCRIPTION Connects to GitHub using a personal access token or device code login. For device flow / device code login: PowerShell requests device and user verification codes and gets the authorization URL where you will enter the user verification code. In GitHub you will be asked to enter a user verification code at https://github.com/login/device. PowerShell will keep polling GitHub for the user authentication status. Once you have authorized the device, the app will be able to make API calls with a new access token. .EXAMPLE Connect-GitHubAccount Connects to GitHub using a device flow login. If the user has already logged in, the access token will be refreshed. .EXAMPLE Connect-GitHubAccount -AccessToken ! Enter your personal access token: ************* User gets prompted for the access token and stores it in the secret store. The token is used when connecting to GitHub. .EXAMPLE Connect-GitHubAccount -Mode 'OAuthApp' -Scope 'gist read:org repo workflow' Connects to GitHub using a device flow login and sets the scope of the access token. .NOTES https://docs.github.com/en/rest/overview/other-authentication-methods#authenticating-for-saml-sso #> [Alias('Connect-GHAccount')] [Alias('Connect-GitHub')] [Alias('Connect-GH')] [Alias('Login-GitHubAccount')] [Alias('Login-GHAccount')] [Alias('Login-GitHub')] [Alias('Login-GH')] [OutputType([void])] [CmdletBinding(DefaultParameterSetName = 'DeviceFlow')] param ( # Choose between authentication methods, either OAuthApp or GitHubApp. # For more info about the types of authentication visit: # https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps [Parameter(ParameterSetName = 'DeviceFlow')] [ValidateSet('OAuthApp', 'GitHubApp')] [string] $Mode = 'GitHubApp', # The scope of the access token, when using OAuth authentication. # Provide the list of scopes as space-separated values. # For more information on scopes visit: # https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps [Parameter(ParameterSetName = 'DeviceFlow')] [string] $Scope = 'gist read:org repo workflow', # The personal access token to use for authentication. [Parameter( Mandatory, ParameterSetName = 'PAT' )] [switch] $AccessToken, # Set the default owner to use in commands. [Parameter()] [string] $Owner, # Set the default repository to use in commands. [Parameter()] [string] $Repo ) $envVar = Get-ChildItem -Path 'Env:' | Where-Object Name -In 'GH_TOKEN', 'GITHUB_TOKEN' | Select-Object -First 1 $envVarPresent = $envVar.count -gt 0 $AuthType = $envVarPresent ? 'sPAT' : $PSCmdlet.ParameterSetName switch ($AuthType) { 'DeviceFlow' { Write-Verbose 'Logging in using device flow...' $clientID = $script:Auth.$Mode.ClientID if ($Mode -ne (Get-GitHubConfig -Name DeviceFlowType -ErrorAction SilentlyContinue)) { Write-Verbose "Using $Mode authentication..." $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -Scope $Scope } else { $accessTokenValidity = [datetime](Get-GitHubConfig -Name 'AccessTokenExpirationDate') - (Get-Date) $accessTokenIsValid = $accessTokenValidity.Seconds -gt 0 $accessTokenValidityText = "$($accessTokenValidity.Hours):$($accessTokenValidity.Minutes):$($accessTokenValidity.Seconds)" if ($accessTokenIsValid) { if ($accessTokenValidity -gt 4) { Write-Host '✓ ' -ForegroundColor Green -NoNewline Write-Host "Access token is still valid for $accessTokenValidityText ..." return } else { Write-Host '⚠' -ForegroundColor Yellow -NoNewline Write-Host "Access token remaining validity $accessTokenValidityText. Refreshing access token..." $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -RefreshToken (Get-GitHubConfig -Name RefreshToken) } } else { $refreshTokenValidity = [datetime](Get-GitHubConfig -Name 'RefreshTokenExpirationDate') - (Get-Date) $refreshTokenIsValid = $refreshTokenValidity.Seconds -gt 0 if ($refreshTokenIsValid) { Write-Host '⚠' -ForegroundColor Yellow -NoNewline Write-Verbose 'Access token expired. Refreshing access token...' $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -RefreshToken (Get-GitHubConfig -Name RefreshToken) } else { Write-Verbose "Using $Mode authentication..." $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -Scope $Scope } } } Reset-GitHubConfig -Scope 'Auth' switch ($Mode) { 'GitHubApp' { $settings = @{ AccessToken = ConvertTo-SecureString -AsPlainText $tokenResponse.access_token AccessTokenExpirationDate = (Get-Date).AddSeconds($tokenResponse.expires_in) AccessTokenType = $tokenResponse.access_token -replace '_.*$', '_*' ApiBaseUri = 'https://api.github.com' ApiVersion = '2022-11-28' AuthType = $AuthType DeviceFlowType = $Mode RefreshToken = ConvertTo-SecureString -AsPlainText $tokenResponse.refresh_token RefreshTokenExpirationDate = (Get-Date).AddSeconds($tokenResponse.refresh_token_expires_in) Scope = $tokenResponse.scope } } 'OAuthApp' { $settings = @{ AccessToken = ConvertTo-SecureString -AsPlainText $tokenResponse.access_token AccessTokenType = $tokenResponse.access_token -replace '_.*$', '_*' ApiBaseUri = 'https://api.github.com' ApiVersion = '2022-11-28' AuthType = $AuthType DeviceFlowType = $Mode Scope = $tokenResponse.scope } } } Set-GitHubConfig @settings break } 'PAT' { Write-Verbose 'Logging in using personal access token...' Reset-GitHubConfig -Scope 'Auth' Write-Host '! ' -ForegroundColor DarkYellow -NoNewline Start-Process 'https://github.com/settings/tokens' $accessTokenValue = Read-Host -Prompt 'Enter your personal access token' -AsSecureString $accessTokenType = (ConvertFrom-SecureString $accessTokenValue -AsPlainText) -replace '_.*$', '_*' if ($accessTokenType -notmatch '^ghp_|^github_pat_') { Write-Host '⚠' -ForegroundColor Yellow -NoNewline Write-Host "Unexpected access token format: $accessTokenType" } $settings = @{ AccessToken = $accessTokenValue AccessTokenType = $accessTokenType ApiBaseUri = 'https://api.github.com' ApiVersion = '2022-11-28' AuthType = $AuthType } Set-GitHubConfig @settings break } 'sPAT' { Write-Verbose 'Logging in using system access token...' Reset-GitHubConfig -Scope 'Auth' $prefix = $envVar.Value -replace '_.*$', '_*' $settings = @{ AccessToken = ConvertTo-SecureString -AsPlainText $envVar.Value AccessTokenType = $prefix ApiBaseUri = 'https://api.github.com' ApiVersion = '2022-11-28' AuthType = 'sPAT' } Set-GitHubConfig @settings } } Write-Host '✓ ' -ForegroundColor Green -NoNewline Write-Host 'Logged in to GitHub!' if ($Owner) { Set-GitHubConfig -Owner $Owner } if ($Repo) { Set-GitHubConfig -Repo $Repo } } Write-Verbose "[$scriptName] - [public/Auth/Connect-GitHubAccount.ps1] - Done" #endregion - From public/Auth/Connect-GitHubAccount.ps1 #region - From public/Auth/Disconnect-GitHubAccount.ps1 Write-Verbose "[$scriptName] - [public/Auth/Disconnect-GitHubAccount.ps1] - Importing" function Disconnect-GitHubAccount { <# .SYNOPSIS Disconnects from GitHub and removes the current GitHub configuration. .DESCRIPTION Disconnects from GitHub and removes the current GitHub configuration. .EXAMPLE Disconnect-GitHubAccount Disconnects from GitHub and removes the current GitHub configuration. #> [Alias('Disconnect-GHAccount')] [Alias('Disconnect-GitHub')] [Alias('Disconnect-GH')] [Alias('Logout-GitHubAccount')] [Alias('Logout-GHAccount')] [Alias('Logout-GitHub')] [Alias('Logout-GH')] [Alias('Logoff-GitHubAccount')] [Alias('Logoff-GHAccount')] [Alias('Logoff-GitHub')] [Alias('Logoff-GH')] [OutputType([void])] [CmdletBinding()] param () Reset-GitHubConfig -Scope 'All' Write-Host '✓ ' -ForegroundColor Green -NoNewline Write-Host 'Logged out of GitHub!' } Write-Verbose "[$scriptName] - [public/Auth/Disconnect-GitHubAccount.ps1] - Done" #endregion - From public/Auth/Disconnect-GitHubAccount.ps1 Write-Verbose "[$scriptName] - [public/Auth] - Done" #endregion - From public/Auth #region - From public/Branches Write-Verbose "[$scriptName] - [public/Branches] - Processing folder" #region - From public/Branches/Get-GitHubRepoBranch.ps1 Write-Verbose "[$scriptName] - [public/Branches/Get-GitHubRepoBranch.ps1] - Importing" function Get-GitHubRepoBranch { [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo) ) $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/branches" Method = 'GET' } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Branches/Get-GitHubRepoBranch.ps1] - Done" #endregion - From public/Branches/Get-GitHubRepoBranch.ps1 Write-Verbose "[$scriptName] - [public/Branches] - Done" #endregion - From public/Branches #region - From public/Config Write-Verbose "[$scriptName] - [public/Config] - Processing folder" #region - From public/Config/Get-GitHubConfig.ps1 Write-Verbose "[$scriptName] - [public/Config/Get-GitHubConfig.ps1] - Importing" function Get-GitHubConfig { <# .SYNOPSIS Get configuration value. .DESCRIPTION Get a named configuration value from the GitHub configuration file. .EXAMPLE Get-GitHubConfig -Name ApiBaseUri Get the current GitHub configuration for the ApiBaseUri. #> [Alias('Get-GHConfig')] [Alias('GGHC')] [OutputType([object])] [CmdletBinding()] param ( # Choose a configuration name to get. [Parameter()] [ValidateSet( 'AccessToken', 'AccessTokenExpirationDate', 'AccessTokenType', 'ApiBaseUri', 'ApiVersion', 'AuthType', 'DeviceFlowType', 'Owner', 'RefreshToken', 'RefreshTokenExpirationDate', 'Repo', 'Scope', 'UserName' )] [string] $Name ) $prefix = $script:SecretVault.Prefix $RefreshTokenData = (Get-SecretInfo -Name "$prefix`RefreshToken").Metadata | ConvertFrom-HashTable | ConvertTo-HashTable $AccessTokenData = (Get-SecretInfo -Name "$prefix`AccessToken").Metadata | ConvertFrom-HashTable | ConvertTo-HashTable $metadata = Join-Hashtable -Main $RefreshTokenData -Overrides $AccessTokenData switch($Name) { 'AccessToken' { Get-Secret -Name "$prefix`AccessToken" } 'RefreshToken' { Get-Secret -Name "$prefix`RefreshToken" } default { if ($Name) { $metadata.$Name } else { $metadata } } } } Write-Verbose "[$scriptName] - [public/Config/Get-GitHubConfig.ps1] - Done" #endregion - From public/Config/Get-GitHubConfig.ps1 #region - From public/Config/Set-GitHubConfig.ps1 Write-Verbose "[$scriptName] - [public/Config/Set-GitHubConfig.ps1] - Importing" function Set-GitHubConfig { <# .SYNOPSIS Set the GitHub configuration. .DESCRIPTION Set the GitHub configuration. Specific scopes can be set by using the parameters. .EXAMPLE Set-GitHubConfig -APIBaseURI 'https://api.github.com" -APIVersion '2022-11-28' Sets the App.API scope of the GitHub configuration. .EXAMPLE Set-GitHubConfig -Name "MyFavouriteRepo" -Value 'https://github.com/PSModule/GitHub' Sets a item called 'MyFavouriteRepo' in the GitHub configuration. #> [Alias('Set-GHConfig')] [CmdletBinding()] param ( # Set the access token type. [Parameter()] [string] $AccessTokenType, # Set the access token. [Parameter()] [securestring] $AccessToken, # Set the access token expiration date. [Parameter()] [datetime] $AccessTokenExpirationDate, # Set the API Base URI. [Parameter()] [string] $ApiBaseUri, # Set the GitHub API Version. [Parameter()] [string] $ApiVersion, # Set the authentication type. [Parameter()] [string] $AuthType, # Set the device flow type. [Parameter()] [string] $DeviceFlowType, # Set the default for the Owner parameter. [Parameter()] [string] $Owner, # Set the refresh token. [Parameter()] [securestring] $RefreshToken, # Set the refresh token expiration date. [Parameter()] [datetime] $RefreshTokenExpirationDate, # Set the default for the Repo parameter. [Parameter()] [string] $Repo, # Set the scope. [Parameter()] [string] $Scope, # Set the GitHub username. [Parameter()] [string] $UserName ) $prefix = $script:SecretVault.Prefix #region AccessToken $secretName = "$prefix`AccessToken" $removeKeys = 'AccessToken', 'RefreshToken', 'RefreshTokenExpirationDate' $keepTypes = 'String', 'Int', 'DateTime' # Get existing metadata if it exists $newSecretMetadata = @{} if (Get-SecretInfo -Name $secretName) { $secretGetInfoParam = @{ Name = $secretName Vault = $script:SecretVault.Name } $secretInfo = Get-SecretInfo @secretGetInfoParam Write-Verbose "$secretName - secretInfo : $($secretInfo | Out-String)" $secretMetadata = $secretInfo.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable $newSecretMetadata = Join-Hashtable -Main $newSecretMetadata -Overrides $secretMetadata } # Get metadata updates from parameters and clean up unwanted data $updateSecretMetadata = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" Write-Verbose "updateSecretMetadataType : $($updateSecretMetadata.GetType())" Remove-HashTableEntries -Hashtable $updateSecretMetadata -KeepTypes $keepTypes -RemoveNames $removeKeys Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" $newSecretMetadata = Join-HashTable -Main $newSecretMetadata -Overrides $updateSecretMetadata Write-Verbose "newSecretMetadata : $($newSecretMetadata | Out-String)" Write-Verbose "newSecretMetadataType : $($newSecretMetadata.GetType())" if ($AccessToken) { $accessTokenSetParam = @{ Name = $secretName Vault = $script:SecretVault.Name SecureStringSecret = $AccessToken } Set-Secret @accessTokenSetParam } if (Get-SecretInfo -Name $secretName) { $secretSetInfoParam = @{ Name = $secretName Vault = $script:SecretVault.Name Metadata = $newSecretMetadata } Set-SecretInfo @secretSetInfoParam } #endregion AccessToken #region RefreshToken $secretName = "$prefix`RefreshToken" $removeKeys = 'AccessToken', 'RefreshToken', 'AccessTokenExpirationDate' # Get existing metadata if it exists $newSecretMetadata = @{} if (Get-SecretInfo -Name $secretName) { $secretGetInfoParam = @{ Name = $secretName Vault = $script:SecretVault.Name } $secretInfo = Get-SecretInfo @secretGetInfoParam Write-Verbose "$secretName - secretInfo : $($secretInfo | Out-String)" $secretMetadata = $secretInfo.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable $newSecretMetadata = Join-Hashtable -Main $newSecretMetadata -Overrides $secretMetadata } # Get metadata updates from parameters and clean up unwanted data $updateSecretMetadata = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" Write-Verbose "updateSecretMetadataType : $($updateSecretMetadata.GetType())" Remove-HashTableEntries -Hashtable $updateSecretMetadata -KeepTypes $keepTypes -RemoveNames $removeKeys Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" $newSecretMetadata = Join-HashTable -Main $newSecretMetadata -Overrides $updateSecretMetadata Write-Verbose "newSecretMetadata : $($newSecretMetadata | Out-String)" Write-Verbose "newSecretMetadataType : $($newSecretMetadata.GetType())" if ($RefreshToken) { $refreshTokenSetParam = @{ Name = $secretName Vault = $script:SecretVault.Name SecureStringSecret = $RefreshToken } Set-Secret @refreshTokenSetParam } if (Get-SecretInfo -Name $secretName) { $secretSetInfoParam = @{ Name = $secretName Vault = $script:SecretVault.Name Metadata = $newSecretMetadata } Set-SecretInfo @secretSetInfoParam } #endregion AccessToken } Write-Verbose "[$scriptName] - [public/Config/Set-GitHubConfig.ps1] - Done" #endregion - From public/Config/Set-GitHubConfig.ps1 Write-Verbose "[$scriptName] - [public/Config] - Done" #endregion - From public/Config #region - From public/Deployments Write-Verbose "[$scriptName] - [public/Deployments] - Processing folder" #region - From public/Deployments/Get-GitHubEnvironment.ps1 Write-Verbose "[$scriptName] - [public/Deployments/Get-GitHubEnvironment.ps1] - Importing" function Get-GitHubEnvironment { <# .SYNOPSIS Get GitHub environment .DESCRIPTION Long description .PARAMETER Owner Parameter description .PARAMETER Repo Parameter description .EXAMPLE An example .NOTES https://docs.github.com/en/rest/reference/repos#get-all-environments #> [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo) ) begin {} process { $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/environments" Method = 'GET' } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Deployments/Get-GitHubEnvironment.ps1] - Done" #endregion - From public/Deployments/Get-GitHubEnvironment.ps1 #region - From public/Deployments/Get-GitHubEnvironmentSecrets.ps1 Write-Verbose "[$scriptName] - [public/Deployments/Get-GitHubEnvironmentSecrets.ps1] - Importing" function Get-GitHubEnvironmentSecrets { <# .SYNOPSIS Get GitHub environment secrets .DESCRIPTION Long description .PARAMETER Owner Parameter description .PARAMETER Repo Parameter description .PARAMETER EnvironmentName Parameter description .EXAMPLE An example .NOTES https://docs.github.com/en/rest/reference/repos#get-all-environments #> [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Alias('name')] [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string] $EnvironmentName ) begin {} process { $RepoID = (Get-GitHubRepo).id $inputObject = @{ APIEndpoint = "/repositories/$RepoID/environments/$EnvironmentName/secrets" Method = 'GET' } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Deployments/Get-GitHubEnvironmentSecrets.ps1] - Done" #endregion - From public/Deployments/Get-GitHubEnvironmentSecrets.ps1 #region - From public/Deployments/Update-GitHubEnvironment.ps1 Write-Verbose "[$scriptName] - [public/Deployments/Update-GitHubEnvironment.ps1] - Importing" function Update-GitHubEnvironment { <# .NOTES https://docs.github.com/en/rest/reference/repos#create-or-update-an-environment #> [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), [Alias('environment_name')] [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [string] $Name ) begin {} process { $body = @{ owner = $Owner repo = $Repo environment_name = $Name } $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/environments/$Name" Method = 'PUT' Body = $body } Invoke-GitHubAPI @inputObject } end {} } Write-Verbose "[$scriptName] - [public/Deployments/Update-GitHubEnvironment.ps1] - Done" #endregion - From public/Deployments/Update-GitHubEnvironment.ps1 Write-Verbose "[$scriptName] - [public/Deployments] - Done" #endregion - From public/Deployments #region - From public/Emojis Write-Verbose "[$scriptName] - [public/Emojis] - Processing folder" #region - From public/Emojis/Get-GitHubEmojis.ps1 Write-Verbose "[$scriptName] - [public/Emojis/Get-GitHubEmojis.ps1] - Importing" function Get-GitHubEmojis { <# .NOTES https://docs.github.com/en/rest/reference/emojis#get-emojis #> [CmdletBinding()] param ( [Parameter()] [string] $Destination ) $inputObject = @{ APIEndpoint = '/emojis' Method = 'GET' } $response = Invoke-GitHubAPI @inputObject if (Test-Path -Path $Destination) { $response.PSobject.Properties | ForEach-Object -Parallel { Invoke-WebRequest -Uri $_.Value -OutFile "$using:Destination/$($_.Name).png" } } else { $response } } Write-Verbose "[$scriptName] - [public/Emojis/Get-GitHubEmojis.ps1] - Done" #endregion - From public/Emojis/Get-GitHubEmojis.ps1 Write-Verbose "[$scriptName] - [public/Emojis] - Done" #endregion - From public/Emojis #region - From public/Markdown Write-Verbose "[$scriptName] - [public/Markdown] - Processing folder" #region - From public/Markdown/Get-GitHubMarkdown.ps1 Write-Verbose "[$scriptName] - [public/Markdown/Get-GitHubMarkdown.ps1] - Importing" function Get-GitHubMarkdown { <# .NOTES https://docs.github.com/en/rest/reference/meta#github-api-root #> [CmdletBinding()] param ( [Parameter()] [switch] $Text, [Parameter()] [ValidateSet('markdown', 'gfm')] [string] $Mode, [Parameter()] [string] $Context ) $body = @{ context = $Context mode = $Mode text = $Text } $inputObject = @{ APIEndpoint = '/markdown' Method = 'POST' Body = $body } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Markdown/Get-GitHubMarkdown.ps1] - Done" #endregion - From public/Markdown/Get-GitHubMarkdown.ps1 #region - From public/Markdown/Get-GitHubMarkdownRaw.ps1 Write-Verbose "[$scriptName] - [public/Markdown/Get-GitHubMarkdownRaw.ps1] - Importing" function Get-GitHubMarkdownRaw { <# .NOTES https://docs.github.com/en/rest/reference/meta#github-api-root #> [CmdletBinding()] param ( [Parameter()] [switch] $Text ) $inputObject = @{ APIEndpoint = '/markdown/raw' ContentType = 'text/plain' Body = $Text Method = 'POST' } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Markdown/Get-GitHubMarkdownRaw.ps1] - Done" #endregion - From public/Markdown/Get-GitHubMarkdownRaw.ps1 Write-Verbose "[$scriptName] - [public/Markdown] - Done" #endregion - From public/Markdown #region - From public/Meta Write-Verbose "[$scriptName] - [public/Meta] - Processing folder" #region - From public/Meta/Get-GitHubApiVersions.ps1 Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubApiVersions.ps1] - Importing" function Get-GitHubApiVersions { <# .SYNOPSIS Get all API versions. .DESCRIPTION Get all supported GitHub API versions. .EXAMPLE Get-GitHubApiVersions Get all supported GitHub API versions. .NOTES https://docs.github.com/rest/meta/meta#get-all-api-versions #> [OutputType([string[]])] [CmdletBinding()] param () $inputObject = @{ ApiEndpoint = '/versions' Method = 'GET' } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubApiVersions.ps1] - Done" #endregion - From public/Meta/Get-GitHubApiVersions.ps1 #region - From public/Meta/Get-GitHubMeta.ps1 Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubMeta.ps1] - Importing" function Get-GitHubMeta { <# .SYNOPSIS Get GitHub meta information. .DESCRIPTION Returns meta information about GitHub, including a list of GitHub's IP addresses. For more information, see "[About GitHub's IP addresses](https://docs.github.com/articles/about-github-s-ip-addresses/)." The API's response also includes a list of GitHub's domain names. The values shown in the documentation's response are example values. You must always query the API directly to get the latest values. **Note:** This endpoint returns both IPv4 and IPv6 addresses. However, not all features support IPv6. You should refer to the specific documentation for each feature to determine if IPv6 is supported. .EXAMPLE Get-GitHubMeta Returns meta information about GitHub, including a list of GitHub's IP addresses. .NOTES https://docs.github.com/rest/meta/meta#get-apiname-meta-information #> [OutputType([object])] [CmdletBinding()] param () $inputObject = @{ ApiEndpoint = '/meta' Method = 'GET' } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubMeta.ps1] - Done" #endregion - From public/Meta/Get-GitHubMeta.ps1 #region - From public/Meta/Get-GitHubOctocat.ps1 Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubOctocat.ps1] - Importing" function Get-GitHubOctocat { <# .SYNOPSIS Get Octocat. .DESCRIPTION Get the octocat as ASCII art. .EXAMPLE Get-GitHubOctocat Get the octocat as ASCII art .EXAMPLE Get-GitHubOctocat -S 'The glass is never half empty. It's just twice as big as it needs to be.' Get the octocat as ASCII art with a custom saying .NOTES https://docs.github.com/rest/meta/meta#get-octocat #> [OutputType([string])] [CmdletBinding()] param ( # The words to show in Octocat's speech bubble [Parameter()] [Alias('Say')] [Alias('Saying')] [string] $S ) $body = @{ s = $S } $inputObject = @{ APIEndpoint = '/octocat' Method = 'GET' Body = $body } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubOctocat.ps1] - Done" #endregion - From public/Meta/Get-GitHubOctocat.ps1 #region - From public/Meta/Get-GitHubRoot.ps1 Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubRoot.ps1] - Importing" function Get-GitHubRoot { <# .SYNOPSIS GitHub API Root. .DESCRIPTION Get Hypermedia links to resources accessible in GitHub's REST API. .EXAMPLE Get-GitHubRoot Get the root endpoint for the GitHub API. .NOTES https://docs.github.com/rest/meta/meta#github-api-root #> [CmdletBinding()] param () $inputObject = @{ APIEndpoint = '/' Method = 'GET' } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubRoot.ps1] - Done" #endregion - From public/Meta/Get-GitHubRoot.ps1 #region - From public/Meta/Get-GitHubZen.ps1 Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubZen.ps1] - Importing" function Get-GitHubZen { <# .SYNOPSIS Get the Zen of GitHub. .DESCRIPTION Get a random sentence from the Zen of GitHub. .EXAMPLE Get-GitHubZen Get a random sentence from the Zen of GitHub. .NOTES https://docs.github.com/rest/meta/meta#get-the-zen-of-github #> [CmdletBinding()] param () $inputObject = @{ APIEndpoint = '/zen' Method = 'GET' } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubZen.ps1] - Done" #endregion - From public/Meta/Get-GitHubZen.ps1 Write-Verbose "[$scriptName] - [public/Meta] - Done" #endregion - From public/Meta #region - From public/Teams Write-Verbose "[$scriptName] - [public/Teams] - Processing folder" #region - From public/Teams/Get-GitHubRepoTeam.ps1 Write-Verbose "[$scriptName] - [public/Teams/Get-GitHubRepoTeam.ps1] - Importing" function Get-GitHubRepoTeam { <# .NOTES https://docs.github.com/en/rest/reference/repos#get-a-repository #> [CmdletBinding()] param ( [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo) ) $inputObject = @{ Method = 'Get' APIEndpoint = "/repos/$Owner/$Repo/teams" } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Teams/Get-GitHubRepoTeam.ps1] - Done" #endregion - From public/Teams/Get-GitHubRepoTeam.ps1 Write-Verbose "[$scriptName] - [public/Teams] - Done" #endregion - From public/Teams #region - From public/Users Write-Verbose "[$scriptName] - [public/Users] - Processing folder" #region - From public/Users/Get-GitHubUser.ps1 Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUser.ps1] - Importing" function Get-GitHubUser { <# .SYNOPSIS Get the authenticated user .DESCRIPTION If the authenticated user is authenticated with an OAuth token 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. .EXAMPLE Get-GitHubUser Get the authenticated user .NOTES https://docs.github.com/rest/users/users#get-the-authenticated-user #> [OutputType([pscustomobject])] [Alias('Get-GitHubContext')] [CmdletBinding()] param () $inputObject = @{ APIEndpoint = '/user' Method = 'GET' } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUser.ps1] - Done" #endregion - From public/Users/Get-GitHubUser.ps1 #region - From public/Users/Get-GitHubUserCard.ps1 Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUserCard.ps1] - Importing" function Get-GitHubUserCard { <# .SYNOPSIS Get contextual information for a user .DESCRIPTION Provides hovercard information when authenticated through basic auth or OAuth with the `repo` scope. You can find out more about someone in relation to their pull requests, issues, repositories, and organizations. The `subject_type` and `subject_id` parameters provide context for the person's hovercard, which returns more information than without the parameters. For example, if you wanted to find out more about `octocat` who owns the `Spoon-Knife` repository via cURL, it would look like this: ```shell curl -u username:token https://api.github.com/users/octocat/hovercard?subject_type=repository&subject_id=1300192 ``` .EXAMPLE .NOTES https://docs.github.com/rest/users/users#get-contextual-information-for-a-user #> [OutputType([pscustomobject])] [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $Username, [Parameter()] [ValidateSet('organization', 'repository', 'issue', 'pull_request')] [string] $SubjectType, [Parameter()] [int] $SubjectID = '' ) $body = @{ subject_type = $SubjectType subject_id = $SubjectID } $inputObject = @{ APIEndpoint = "/users/$Username/hovercard" Method = 'GET' Body = $body } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUserCard.ps1] - Done" #endregion - From public/Users/Get-GitHubUserCard.ps1 #region - From public/Users/Get-GitHubUserList.ps1 Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUserList.ps1] - Importing" function Get-GitHubUserList { <# .SYNOPSIS List users .DESCRIPTION Lists all users, in the order that they signed up on GitHub. This list includes personal user accounts and organization accounts. Note: Pagination is powered exclusively by the `since` parameter. Use the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers) to get the URL for the next page of users. .EXAMPLE Get-GitHubUserList -Since 17722253 Get the authenticated user .NOTES https://docs.github.com/rest/users/users#list-users #> [OutputType([pscustomobject])] [CmdletBinding()] param ( # A user ID. Only return users with an ID greater than this ID. [Parameter()] [int] $Since = 0, # The number of results per page (max 100). [Parameter()] [int] $PerPage = 100 ) $body = @{ since = $Since per_page = $PerPage } $inputObject = @{ APIEndpoint = "/users" Method = 'GET' Body = $body } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUserList.ps1] - Done" #endregion - From public/Users/Get-GitHubUserList.ps1 #region - From public/Users/Set-GitHubUser.ps1 Write-Verbose "[$scriptName] - [public/Users/Set-GitHubUser.ps1] - Importing" function Set-GitHubUser { <# .SYNOPSIS Update the authenticated user .DESCRIPTION **Note:** If your email is set to private and you send an `email` parameter as part of this request to update your profile, your privacy settings are still enforced: the email address will not be displayed on your public profile or via the API. .EXAMPLE Set-GitHubUser -Name 'octocat' Update the authenticated user's name to 'octocat' .EXAMPLE Set-GitHubUser -Location 'San Francisco' Update the authenticated user's location to 'San Francisco' .EXAMPLE Set-GitHubUser -Hireable $true -Bio 'I love programming' Update the authenticated user's hiring availability to 'true' and their biography to 'I love programming' .NOTES https://docs.github.com/rest/users/users#update-the-authenticated-user #> [OutputType([void])] [Alias('Update-GitHubUser')] [CmdletBinding()] param ( # The new name of the user. [Parameter()] [string] $Name, # The publicly visible email address of the user. [Parameter()] [string] $Email, # The new blog URL of the user. [Parameter()] [string] $Blog, # The new Twitter username of the user. [Parameter()] [string] $TwitterUsername, # The new company of the user. [Parameter()] [string] $Company, # The new location of the user. [Parameter()] [string] $Location, # The new hiring availability of the user. [Parameter()] [boolean] $Hireable, # The new short biography of the user. [Parameter()] [string] $Bio ) $body = @{} $PSBoundParameters.GetEnumerator() | ForEach-Object { $body.($_.Key) = $_.Value } $inputObject = @{ APIEndpoint = '/user' Body = $body Method = 'PATCH' } Invoke-GitHubAPI @inputObject } Write-Verbose "[$scriptName] - [public/Users/Set-GitHubUser.ps1] - Done" #endregion - From public/Users/Set-GitHubUser.ps1 Write-Verbose "[$scriptName] - [public/Users] - Done" #endregion - From public/Users Write-Verbose "[$scriptName] - [public] - Done" #endregion - From public #region - From GitHub.ps1 Write-Verbose "[$scriptName] - [GitHub.ps1] - Importing" $scriptFilePath = $MyInvocation.MyCommand.Path Write-Verbose "[$scriptFilePath] - Initializing GitHub module..." Initialize-SecretVault -Name $script:SecretVault.Name -Type $script:SecretVault.Type # Autologon if a token is present in environment variables $envVar = Get-ChildItem -Path 'Env:' | Where-Object Name -In 'GH_TOKEN', 'GITHUB_TOKEN' | Select-Object -First 1 $envVarPresent = $envVar.count -gt 0 if ($envVarPresent) { Connect-GitHubAccount } Write-Verbose "[$scriptName] - [GitHub.ps1] - Done" #endregion - From GitHub.ps1 Export-ModuleMember -Function 'Disable-GitHubWorkflow','Enable-GitHubWorkflow','Get-GitHubWorkflow','Get-GitHubWorkflowRun','Get-GitHubWorkflowUsage','Remove-GitHubWorkflowRun','Start-GitHubWorkflow','Start-GitHubWorkflowReRun','Stop-GitHubWorkflowRun','Invoke-GitHubAPI','Connect-GitHubAccount','Disconnect-GitHubAccount','Get-GitHubRepoBranch','Get-GitHubConfig','Set-GitHubConfig','Get-GitHubEnvironment','Get-GitHubEnvironmentSecrets','Update-GitHubEnvironment','Get-GitHubEmojis','Get-GitHubMarkdown','Get-GitHubMarkdownRaw','Get-GitHubApiVersions','Get-GitHubMeta','Get-GitHubOctocat','Get-GitHubRoot','Get-GitHubZen','Get-GitHubRepoTeam','Get-GitHubUser','Get-GitHubUserCard','Get-GitHubUserList','Set-GitHubUser' -Cmdlet '' -Variable '' -Alias '*' |