diff --git a/README.md b/README.md index 293c5a4aa..988e606df 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -# GitHub Powershell Module - # GitHub PowerShell The **GitHub PowerShell** module serves as a convenient API wrapper around [GitHub's REST API](https://docs.github.com/en/rest), making the functionalities and data available on GitHub accessible through PowerShell commands. This module is tailored for developers, administrators, and GitHub enthusiasts who are familiar with PowerShell and want to integrate or manage their GitHub repositories seamlessly. diff --git a/src/GitHub/GitHub.ps1 b/src/GitHub/GitHub.ps1 index a0a45426b..79c1d6ddf 100644 --- a/src/GitHub/GitHub.ps1 +++ b/src/GitHub/GitHub.ps1 @@ -1,6 +1,6 @@ $scriptFilePath = $MyInvocation.MyCommand.Path -Write-Verbose "[$scriptFilePath] - Initializing GitHub module..." -Verbose +Write-Verbose "[$scriptFilePath] - Initializing GitHub module..." Initialize-SecretVault -Name $script:SecretVault.Name -Type $script:SecretVault.Type diff --git a/src/GitHub/GitHub.psd1 b/src/GitHub/GitHub.psd1 index 531b269f3..14bc32924 100644 --- a/src/GitHub/GitHub.psd1 +++ b/src/GitHub/GitHub.psd1 @@ -3,7 +3,7 @@ Author = 'Marius Storhaug' # Version number of this module - ModuleVersion = '0.0.1' + ModuleVersion = '0.1.1' # Description of the functionality provided by this module Description = 'GitHub PowerShell Module' diff --git a/src/GitHub/private/Menu/Invoke-DrawMenu.ps1 b/src/GitHub/private/Menu/Invoke-DrawMenu.ps1 new file mode 100644 index 000000000..4ca69a42e --- /dev/null +++ b/src/GitHub/private/Menu/Invoke-DrawMenu.ps1 @@ -0,0 +1,29 @@ +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 + } + } +} diff --git a/src/GitHub/private/Menu/Invoke-Meny.ps1 b/src/GitHub/private/Menu/Invoke-Meny.ps1 new file mode 100644 index 000000000..dcdbe6091 --- /dev/null +++ b/src/GitHub/private/Menu/Invoke-Meny.ps1 @@ -0,0 +1,29 @@ +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 +#> diff --git a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 index e3ec7793d..c8ab7a099 100644 --- a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 +++ b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 @@ -1,27 +1,27 @@ function Invoke-GitHubAPI { <# - .SYNOPSIS - Calls the GitHub API using the provided parameters. + .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. + .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 + .EXAMPLE + Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET - Gets all open pull requests for the specified repository. + Gets all open pull requests for the specified repository. - .EXAMPLE - Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET -Body @{ state = 'open' } + .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. + 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' + .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. -#> + 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. @@ -42,15 +42,15 @@ # The 'Accept' header for the API request. If not provided, the default will be used by GitHub's API. [Parameter()] - [string] $Accept, + [string] $Accept = 'application/vnd.github+json', # Specifies the HTTP version used for the request. [Parameter()] - $HttpVersion = '2.0', + [version] $HttpVersion = '2.0', # Support Pagination Relation Links per RFC5988. [Parameter()] - $FollowRelLink = $true, + [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()] @@ -76,6 +76,23 @@ $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 @@ -88,9 +105,19 @@ StatusCodeVariable = 'StatusCode' ResponseHeadersVariable = 'ResponseHeaders' } - Remove-HashTableEntries -Hashtable $APICall -NullOrEmptyValues + $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 { @@ -101,12 +128,11 @@ 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 $_ + Write-Verbose ($responseHeaders | ConvertTo-Json -Depth 100) } catch { - Write-Error "[$functionName] - GeneralException - $($_.Exception.Message)" - throw $_ + Write-Error "[$functionName] - Status code - [$StatusCode]" + $err = $_ | ConvertFrom-Json -Depth 10 + Write-Error "[$functionName] - $($err.Message)" + Write-Error "[$functionName] - For more info please see: [$($err.documentation_url)]" } } diff --git a/src/GitHub/public/Actions/Disable-GitHubWorkflow.ps1 b/src/GitHub/public/Actions/Disable-GitHubWorkflow.ps1 new file mode 100644 index 000000000..e430c3b64 --- /dev/null +++ b/src/GitHub/public/Actions/Disable-GitHubWorkflow.ps1 @@ -0,0 +1,34 @@ +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 | Out-Null + + } + + end {} +} diff --git a/src/GitHub/public/Actions/Enable-GitHubWorkflow.ps1 b/src/GitHub/public/Actions/Enable-GitHubWorkflow.ps1 new file mode 100644 index 000000000..d46c2e569 --- /dev/null +++ b/src/GitHub/public/Actions/Enable-GitHubWorkflow.ps1 @@ -0,0 +1,34 @@ +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 | Out-Null + + } + + end {} +} diff --git a/src/GitHub/public/Actions/Get-GitHubWorkflow.ps1 b/src/GitHub/public/Actions/Get-GitHubWorkflow.ps1 new file mode 100644 index 000000000..d5368fac7 --- /dev/null +++ b/src/GitHub/public/Actions/Get-GitHubWorkflow.ps1 @@ -0,0 +1,59 @@ +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 + + } +} diff --git a/src/GitHub/public/Actions/Get-GitHubWorkflowRun.ps1 b/src/GitHub/public/Actions/Get-GitHubWorkflowRun.ps1 new file mode 100644 index 000000000..15206b51c --- /dev/null +++ b/src/GitHub/public/Actions/Get-GitHubWorkflowRun.ps1 @@ -0,0 +1,55 @@ +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 | Select-Object -ExpandProperty workflow_runs | Write-Output + + } + + end {} + +} diff --git a/src/GitHub/public/Actions/Get-GitHubWorkflowUsage.ps1 b/src/GitHub/public/Actions/Get-GitHubWorkflowUsage.ps1 new file mode 100644 index 000000000..4ca08c6ec --- /dev/null +++ b/src/GitHub/public/Actions/Get-GitHubWorkflowUsage.ps1 @@ -0,0 +1,55 @@ +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 | Select-Object -ExpandProperty billable | Write-Output + + } + + end {} +} diff --git a/src/GitHub/public/Actions/Remove-GitHubWorkflowRun.ps1 b/src/GitHub/public/Actions/Remove-GitHubWorkflowRun.ps1 new file mode 100644 index 000000000..6e1438563 --- /dev/null +++ b/src/GitHub/public/Actions/Remove-GitHubWorkflowRun.ps1 @@ -0,0 +1,31 @@ +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 {} +} diff --git a/src/GitHub/public/Actions/Start-GitHubWorkflow.ps1 b/src/GitHub/public/Actions/Start-GitHubWorkflow.ps1 new file mode 100644 index 000000000..1d1ae9a6b --- /dev/null +++ b/src/GitHub/public/Actions/Start-GitHubWorkflow.ps1 @@ -0,0 +1,66 @@ +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 {} +} diff --git a/src/GitHub/public/Actions/Start-GitHubWorkflowReRun.ps1 b/src/GitHub/public/Actions/Start-GitHubWorkflowReRun.ps1 new file mode 100644 index 000000000..3c9ddd66a --- /dev/null +++ b/src/GitHub/public/Actions/Start-GitHubWorkflowReRun.ps1 @@ -0,0 +1,54 @@ +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 {} +} diff --git a/src/GitHub/public/Actions/Stop-GitHubWorkflowRun.ps1 b/src/GitHub/public/Actions/Stop-GitHubWorkflowRun.ps1 new file mode 100644 index 000000000..4821d0737 --- /dev/null +++ b/src/GitHub/public/Actions/Stop-GitHubWorkflowRun.ps1 @@ -0,0 +1,55 @@ +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 {} +} diff --git a/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 b/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 index a91cce1e3..4b57c307d 100644 --- a/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 +++ b/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 @@ -62,7 +62,15 @@ Mandatory, ParameterSetName = 'PAT' )] - [switch] $AccessToken + [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 @@ -172,4 +180,13 @@ Write-Host '✓ ' -ForegroundColor Green -NoNewline Write-Host 'Logged in to GitHub!' + + if ($Owner) { + Set-GitHubConfig -Owner $Owner + } + + if ($Repo) { + Set-GitHubConfig -Repo $Repo + } + } diff --git a/src/GitHub/public/Branches/Get-GitHubRepoBranch.ps1 b/src/GitHub/public/Branches/Get-GitHubRepoBranch.ps1 new file mode 100644 index 000000000..a8691d6af --- /dev/null +++ b/src/GitHub/public/Branches/Get-GitHubRepoBranch.ps1 @@ -0,0 +1,18 @@ +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 + +} diff --git a/src/GitHub/public/Config/Get-GitHubConfig.ps1 b/src/GitHub/public/Config/Get-GitHubConfig.ps1 index d872ed894..a279f7989 100644 --- a/src/GitHub/public/Config/Get-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Get-GitHubConfig.ps1 @@ -18,11 +18,30 @@ 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" @@ -30,13 +49,12 @@ 'RefreshToken' { Get-Secret -Name "$prefix`RefreshToken" } - 'RefreshTokenExpirationDate' { - $RefreshTokenData = Get-SecretInfo -Name "$prefix`RefreshToken" - $RefreshTokenData.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable | Select-Object -ExpandProperty $Name - } default { - $AccessTokenData = Get-SecretInfo -Name "$prefix`AccessToken" - $AccessTokenData.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable | Select-Object -ExpandProperty $Name + if ($Name) { + $metadata.$Name + } else { + $metadata + } } } } diff --git a/src/GitHub/public/Config/Set-GitHubConfig.ps1 b/src/GitHub/public/Config/Set-GitHubConfig.ps1 index e4432fa35..ab215ef15 100644 --- a/src/GitHub/public/Config/Set-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Set-GitHubConfig.ps1 @@ -165,7 +165,7 @@ Vault = $script:SecretVault.Name Metadata = $newSecretMetadata } - Set-SecretInfo @secretSetInfoParam -Verbose + Set-SecretInfo @secretSetInfoParam } #endregion AccessToken } diff --git a/src/GitHub/public/Deployments/Get-GitHubEnvironment.ps1 b/src/GitHub/public/Deployments/Get-GitHubEnvironment.ps1 new file mode 100644 index 000000000..15a39c62e --- /dev/null +++ b/src/GitHub/public/Deployments/Get-GitHubEnvironment.ps1 @@ -0,0 +1,44 @@ +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 {} +} diff --git a/src/GitHub/public/Deployments/Get-GitHubEnvironmentSecrets.ps1 b/src/GitHub/public/Deployments/Get-GitHubEnvironmentSecrets.ps1 new file mode 100644 index 000000000..602e2d922 --- /dev/null +++ b/src/GitHub/public/Deployments/Get-GitHubEnvironmentSecrets.ps1 @@ -0,0 +1,54 @@ +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 {} +} diff --git a/src/GitHub/public/Deployments/Update-GitHubEnvironment.ps1 b/src/GitHub/public/Deployments/Update-GitHubEnvironment.ps1 new file mode 100644 index 000000000..25da09436 --- /dev/null +++ b/src/GitHub/public/Deployments/Update-GitHubEnvironment.ps1 @@ -0,0 +1,42 @@ +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 {} +} diff --git a/src/GitHub/public/Emojis/Get-GitHubEmojis.ps1 b/src/GitHub/public/Emojis/Get-GitHubEmojis.ps1 new file mode 100644 index 000000000..b90763bc8 --- /dev/null +++ b/src/GitHub/public/Emojis/Get-GitHubEmojis.ps1 @@ -0,0 +1,26 @@ +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 + } +} diff --git a/src/GitHub/public/Markdown/Get-GitHubMarkdown.ps1 b/src/GitHub/public/Markdown/Get-GitHubMarkdown.ps1 new file mode 100644 index 000000000..ebcb6ed92 --- /dev/null +++ b/src/GitHub/public/Markdown/Get-GitHubMarkdown.ps1 @@ -0,0 +1,33 @@ +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 + +} diff --git a/src/GitHub/public/Markdown/Get-GitHubMarkdownRaw.ps1 b/src/GitHub/public/Markdown/Get-GitHubMarkdownRaw.ps1 new file mode 100644 index 000000000..4316e10a3 --- /dev/null +++ b/src/GitHub/public/Markdown/Get-GitHubMarkdownRaw.ps1 @@ -0,0 +1,21 @@ +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 + +} diff --git a/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 b/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 index ed1443291..cbb1bc3b6 100644 --- a/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 @@ -23,7 +23,6 @@ Method = 'GET' } - $response = Invoke-GitHubAPI @inputObject + Invoke-GitHubAPI @inputObject - $response } diff --git a/src/GitHub/public/Meta/Get-GitHubMeta.ps1 b/src/GitHub/public/Meta/Get-GitHubMeta.ps1 index cae684cf8..ccc4c9cbf 100644 --- a/src/GitHub/public/Meta/Get-GitHubMeta.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubMeta.ps1 @@ -29,7 +29,6 @@ Method = 'GET' } - $response = Invoke-GitHubAPI @inputObject + Invoke-GitHubAPI @inputObject - $response } diff --git a/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 b/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 index 946bfe86c..96ce2fa89 100644 --- a/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 @@ -27,23 +27,19 @@ [Alias('Say')] [Alias('Saying')] [string] - $S = "The glass is never half empty. Its just twice as big as it needs to be." + $S ) - # $query = [System.Web.HttpUtility]::UrlEncode($S) - # $query = [System.Uri]::EscapeDataString($S) - $body = @{ s = $S } $inputObject = @{ - APIEndpoint = "/octocat" + APIEndpoint = '/octocat' Method = 'GET' Body = $body } - $response = Invoke-GitHubAPI @inputObject + Invoke-GitHubAPI @inputObject - $response } diff --git a/src/GitHub/public/Meta/Get-GitHubRoot.ps1 b/src/GitHub/public/Meta/Get-GitHubRoot.ps1 index a08b507df..c4a52e16a 100644 --- a/src/GitHub/public/Meta/Get-GitHubRoot.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubRoot.ps1 @@ -17,12 +17,11 @@ [CmdletBinding()] param () - $InputObject = @{ + $inputObject = @{ APIEndpoint = '/' Method = 'GET' } - $response = Invoke-GitHubAPI @InputObject + Invoke-GitHubAPI @inputObject - $response } diff --git a/src/GitHub/public/Meta/Get-GitHubZen.ps1 b/src/GitHub/public/Meta/Get-GitHubZen.ps1 index 866265a06..8ddf4a7e7 100644 --- a/src/GitHub/public/Meta/Get-GitHubZen.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubZen.ps1 @@ -17,12 +17,11 @@ [CmdletBinding()] param () - $InputObject = @{ + $inputObject = @{ APIEndpoint = '/zen' Method = 'GET' } - $Response = Invoke-GitHubAPI @InputObject + Invoke-GitHubAPI @inputObject - $Response } diff --git a/src/GitHub/public/Teams/Get-GitHubRepoTeam.ps1 b/src/GitHub/public/Teams/Get-GitHubRepoTeam.ps1 new file mode 100644 index 000000000..cc3516f1b --- /dev/null +++ b/src/GitHub/public/Teams/Get-GitHubRepoTeam.ps1 @@ -0,0 +1,22 @@ +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 + +} diff --git a/src/GitHub/public/Users/Get-GitHubUser.ps1 b/src/GitHub/public/Users/Get-GitHubUser.ps1 new file mode 100644 index 000000000..c1632017c --- /dev/null +++ b/src/GitHub/public/Users/Get-GitHubUser.ps1 @@ -0,0 +1,30 @@ +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 + +} diff --git a/src/GitHub/public/Users/Get-GitHubUserCard.ps1 b/src/GitHub/public/Users/Get-GitHubUserCard.ps1 new file mode 100644 index 000000000..6617af34e --- /dev/null +++ b/src/GitHub/public/Users/Get-GitHubUserCard.ps1 @@ -0,0 +1,47 @@ +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 + +} diff --git a/src/GitHub/public/Users/Get-GitHubUserList.ps1 b/src/GitHub/public/Users/Get-GitHubUserList.ps1 new file mode 100644 index 000000000..960bfbe2c --- /dev/null +++ b/src/GitHub/public/Users/Get-GitHubUserList.ps1 @@ -0,0 +1,43 @@ +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 + +} diff --git a/src/GitHub/public/Users/Set-GitHubUser.ps1 b/src/GitHub/public/Users/Set-GitHubUser.ps1 new file mode 100644 index 000000000..8a388a937 --- /dev/null +++ b/src/GitHub/public/Users/Set-GitHubUser.ps1 @@ -0,0 +1,80 @@ +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 + +} diff --git a/tools/utilities/GHAPI.ps1 b/tools/utilities/GHAPI.ps1 new file mode 100644 index 000000000..3e9d36477 --- /dev/null +++ b/tools/utilities/GHAPI.ps1 @@ -0,0 +1,35 @@ +# API Authorization +# https://docs.github.com/en/rest/overview/other-authentication-methods + + +# https://docs.github.com/en/rest/overview/resources-in-the-rest-api +# https://docs.github.com/en/rest/reference + +$GHOwner = 'Org' +$GHRepo = 'RepoA' +$GHToken = 'ABC123' + +$GHAPIBaseURI = 'https://api.github.com' + +Function Get-GHActionRuns { + [CmdletBinding()] + param () + + # API Reference + # https://docs.github.com/en/rest/reference/actions#list-workflow-runs-for-a-repository + $APICall = @{ + Uri = "$GHRepoURI/repos/$GHOwner/$GHRepo/actions/runs" + Headers = @{ + Authorization = "token $GHToken" + 'Content-Type' = 'application/json' + } + Method = 'GET' + Body = @{} | ConvertTo-Json -Depth 100 + } + try { + $response = Invoke-RestMethod @APICall + } catch { + throw $_ + } + return $response.value +} diff --git a/tools/utilities/GitHubAPI.ps1 b/tools/utilities/GitHubAPI.ps1 index 9292af143..a5b3004e9 100644 --- a/tools/utilities/GitHubAPI.ps1 +++ b/tools/utilities/GitHubAPI.ps1 @@ -2,16 +2,38 @@ $APIDocURI = 'https://raw.githubusercontent.com/github/rest-api-description/main $Bundled = '/descriptions/api.github.com/api.github.com.json' $Dereferenced = 'descriptions/api.github.com/dereferenced/api.github.com.deref.json' $APIDocURI = $APIDocURI + $Bundled -$Response = Invoke-RestMethod -Uri $APIDocURI -Method Get +$response = Invoke-RestMethod -Uri $APIDocURI -Method Get -# $Response.info # API name = GitHub REST API -# $Response.openapi # Spec version = 3.0.3 -# $Response.servers # API URL = api.github.com -# $Response.externalDocs # API docs URL = docs.github.com/rest -# $Response.components # Type specs -# $Response.paths # API endpoints -# $Response.tags # API categories -# $Response.'x-webhooks' # Webhooks/event docs +$response.info # API name = GitHub REST API +$response.openapi # Spec version = 3.0.3 +$response.servers # API URL = api.github.com +$response.externalDocs # API docs URL = docs.github.com/rest +$response.components # Type specs +$response.paths # API endpoints # -> Namespaces, PascalCase! +$response.tags # API categories +$response.'x-webhooks' # Webhooks/event docs + +$response.paths.psobject.Properties | Select-Object ` + Name, ` + @{n = 'Get'; e = { (($_.value.psobject.Properties.Name) -contains 'Get') } }, ` + @{n = 'Post'; e = { (($_.value.psobject.Properties.Name) -contains 'Post') } }, ` + @{n = 'Delete'; e = { (($_.value.psobject.Properties.Name) -contains 'Delete') } }, ` + @{n = 'PUT'; e = { (($_.value.psobject.Properties.Name) -contains 'PUT') } }, ` + @{n = 'PATCH'; e = { (($_.value.psobject.Properties.Name) -contains 'PATCH') } } | format-table + +$path = '/users/{username}/hovercard' +$response.paths.$path.get.tags | clip # -> Namespace/foldername +$response.paths.$path.get.operationId | clip # -> FunctionName +$response.paths.$path.get.summary | clip # -> Synopsis +$response.paths.$path.get.description | clip # -> Description +$response.paths.$path.get.externalDocs.url | clip # -> Notes +$response.paths.$path.get.'x-github'.category | clip # -> Namespace/foldername +$response.paths.$path.get.'x-github'.subcategory | clip # -> Namespace/foldername +$response.paths.$path.get.'x-github'.enabledForGitHubApps | clip # -> Note + Warning if running as GitHub App +$response.paths.$path.get.'x-github'.githubCloudOnly | clip # -> Note +$response.paths.$path.get.parameters # -> Parameter list +$response.paths.$path.get.responses.'200'.content.'application/json'.schema # -> OutputType qualifyer +$response.paths.$path.get.responses.'200'.content.'application/json'.schema.items # -> OutputType +$response.paths.$path.get -$Response.paths.'/meta'.get diff --git a/tools/utilities/Local-Testing.ps1 b/tools/utilities/Local-Testing.ps1 index c99643b25..3157efdae 100644 --- a/tools/utilities/Local-Testing.ps1 +++ b/tools/utilities/Local-Testing.ps1 @@ -8,7 +8,7 @@ Get-SecretInfo Get-Module -Name GitHub -ListAvailable $VerbosePreference = 'Continue' -Install-Module -Name GitHub -Verbose -Force -AllowPrerelease +Install-Module -Name GitHub -Force -Verbose -AllowPrerelease # $env:PSModulePath += ';C:\Repos\GitHub\PSModule\Modules\GitHub\outputs' # Import-Module -Name 'C:\Repos\GitHub\PSModule\Modules\GitHub\src\GitHub\GitHub.psm1' -Verbose -Force @@ -24,8 +24,14 @@ Get-GitHubConfig -Name AccessTokenExpirationDate Get-GitHubConfig -Name RefreshToken Get-GitHubConfig -Name RefreshTokenExpirationDate Get-GitHubConfig -Name ApiBaseUri -Invoke-GitHubAPI -Method Get -ApiEndpoint / +Invoke-GitHubAPI -Method Get -ApiEndpoint /user Get-GitHubMeta Get-GitHubOctocat -S 'Hello, World!' Disconnect-GitHubAccount -Verbose $VerbosePreference = 'SIlentlyContinue' + + +$str = '2023-10-27 17:43:40 UTC' +$format = "yyyy-MM-dd HH:mm:ss 'UTC'" +$date = [datetime]::ParseExact($str, $format, $null) +$date diff --git a/tools/utilities/StopWorkflowsCustom.ps1 b/tools/utilities/StopWorkflowsCustom.ps1 new file mode 100644 index 000000000..b73b89246 --- /dev/null +++ b/tools/utilities/StopWorkflowsCustom.ps1 @@ -0,0 +1,69 @@ +$Owner = 'MariusStorhaug' +$Repo = 'ResourceModules' + +$Owner = 'PSModule' +$Repo = 'GitHub' + + +Install-Module -Name GitHub -Force -AllowClobber +Connect-GitHubAccount -Owner $Owner -Repo $Repo -Verbose + +Set-GitHubConfig -Owner $Owner -Repo $Repo -Verbose +Get-GitHubConfig +Get-GitHubWorkflow -Verbose + +# Disable all workflows +Get-GitHubWorkflow | Where-Object state -EQ 'active' | Disable-GitHubWorkflow + +# Enable all workflows +Get-GitHubWorkflow | Where-Object state -NE 'active' | Enable-GitHubWorkflow + +# Cancel all started workflows +Get-GitHubWorkflowRun | Where-Object status -NE Completed | Stop-GitHubWorkflowRun + +# Remove all completed workflows +Get-GitHubWorkflowRun | Where-Object status -EQ Completed | Remove-GitHubWorkflowRun + +# Disable all workflows +Get-GitHubWorkflow | Disable-GitHubWorkflow + +# Cancel all started workflows +Get-GitHubWorkflowRun | Where-Object status -NE completed | Stop-GitHubWorkflowRun + +Get-GitHubRepoTeams + + +(Get-GitHubWorkflow).count + +Get-GitHubWorkflow | Select-Object -first 1 -Property * + +Get-GitHubWorkflow | Select-Object Name, state +Get-GitHubWorkflow | Where-Object state -NE disabled_manually | Disable-GitHubWorkflow +Get-GitHubWorkflow | Disable-GitHubWorkflow +Get-GitHubWorkflow | Select-Object Name, state + +Get-GitHubWorkflow | Select-Object Name, state +Get-GitHubWorkflow | Where-Object name -NotLike '.*' | Enable-GitHubWorkflow +Get-GitHubWorkflow | Select-Object Name, state + +Get-GitHubWorkflow | Select-Object Name, state +Get-GitHubWorkflow | Enable-GitHubWorkflow +Get-GitHubWorkflow | Select-Object Name, state + +Get-GitHubWorkflow | Select-Object Name | Sort-Object Name -Unique +Get-GitHubWorkflow | Get-GitHubWorkflowUsage +(Get-GitHubWorkflow | Get-GitHubWorkflowRun).count +Get-GitHubWorkflowRun | Cancel-GitHubWorkflowRun +Get-GitHubWorkflowRun | Remove-GitHubWorkflowRun + +Get-GitHubWorkflowRun | Select-Object -Property name, display_title, created_at, run_started_at, updated_at, @{name = 'duration'; expression = { $_.updated_at - $_.run_started_at } }, @{name = 'wait_duration'; expression = { $_.updated_at - $_.created_at } } | Format-Table -AutoSize + +Get-GitHubWorkflowRun | Where-Object run_started_at -le (Get-Date).AddDays(-1) | Remove-GitHubWorkflowRun + + +Get-GitHubWorkflow | Where-Object name -NotLike '.*' | Start-GitHubWorkflow -Inputs @{ + staticValidation = $true + deploymentValidation = $false + removeDeployment = $true + prerelease = $false +}