diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 270f2ef5e..ed7677cb0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,11 +5,11 @@ version: 2 updates: - - package-ecosystem: "github-actions" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: 'github-actions' # See documentation for possible values + directory: '/' # Location of package manifests schedule: - interval: "weekly" - - package-ecosystem: "nuget" # See documentation for possible values - directory: "/" # Location of package manifests + interval: 'weekly' + - package-ecosystem: 'nuget' # See documentation for possible values + directory: '/' # Location of package manifests schedule: - interval: "weekly" + interval: 'weekly' diff --git a/.vscode/settings.json b/.vscode/settings.json index d48c3e7ee..bee7d916e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -29,6 +29,10 @@ "editor.insertSpaces": true, "editor.tabSize": 2 }, + "editor.rulers": [ + 0, + 150 + ], "powershell.codeFormatting.autoCorrectAliases": true, "powershell.codeFormatting.newLineAfterCloseBrace": false, "powershell.codeFormatting.pipelineIndentationStyle": "IncreaseIndentationForFirstPipeline", diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 5620c53fc..1cd88506a 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -17,23 +17,23 @@ diverse, inclusive, and healthy community. Examples of behavior that contributes to a positive environment for our community include: -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -* Focusing on what is best not just for us as individuals, but for the +- Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: -* The use of sexualized language or imagery, and sexual attention or +- The use of sexualized language or imagery, and sexual attention or advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities @@ -106,7 +106,7 @@ Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an +standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within diff --git a/README.md b/README.md index 6b7b037dd..3efabbd92 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ Press Enter to open github.com in your browser...: ``` #### Personal access token + This is the least secure method of authentication, but it is also the simplest. Running the `Connect-GitHubAccount` command with the `-AccessToken` parameter will send you to the GitHub website where you can create a new personal access token. Give it the access you need and paste it into the terminal. @@ -100,6 +101,7 @@ Connect-GitHubAccount -AccessToken ``` #### System Access Token + The module also detects the presence of a system access token and uses that if it is present. This is useful if you are running the module in a CI/CD pipeline or in a scheduled task. The function looks for the `GH_TOKEN` and `GITHUB_TOKEN` environment variables (in order). @@ -110,6 +112,7 @@ Connect-GitHubAccount ``` ### Command Exploration + Familiarize yourself with the available cmdlets using the module's comprehensive documentation or inline help. ```powershell @@ -144,25 +147,31 @@ For a detailed understanding of the framework, [read more about PSModule here](h ## References ### Official GitHub Resources: + - [REST API Description](https://github.com/github/rest-api-description) - [GitHub CLI Manual](https://cli.github.com/manual/) - [GitHub Platform Samples](https://github.com/github/platform-samples) ### General Web References: + - [Generic HTTP Status Codes (MDN)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) ### Tools Planned for Development: + - [Azure AutoRest (OpenAPI Specification Code Generator)](https://github.com/Azure/autorest) ### Inspiration Behind the Project: + - [Microsoft's PowerShellForGitHub](https://github.com/microsoft/PowerShellForGitHub) - [PSGitHub by pcgeek86](https://github.com/pcgeek86/PSGitHub) - [PSSodium by TylerLeonhardt](https://github.com/TylerLeonhardt/PSSodium) - [libsodium NuGet Package](https://www.nuget.org/packages/Sodium.Core/) ### Authentication and Login: + - [PowerShell for GitHub on GitHub Marketplace](https://github.com/apps/powershell-for-github) - [Building a CLI with a GitHub App](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app) ### Module Configuration and Environment: + - [GH Environment for GitHub CLI](https://cli.github.com/manual/gh_help_environment) diff --git a/src/GitHub/GitHub.psd1 b/src/GitHub/GitHub.psd1 index f7d4ad99d..f73419373 100644 --- a/src/GitHub/GitHub.psd1 +++ b/src/GitHub/GitHub.psd1 @@ -1,15 +1,13 @@ @{ - # Author of this module - Author = 'Marius Storhaug' - # Version number of this module ModuleVersion = '0.3.0' # Description of the functionality provided by this module Description = 'GitHub PowerShell Module' - # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. - PrivateData = @{ + # Private data to pass to the module specified in RootModule/ModuleToProcess. + # This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ PSData = @{ diff --git a/src/GitHub/attributes.txt b/src/GitHub/attributes.txt new file mode 100644 index 000000000..750c3db8b --- /dev/null +++ b/src/GitHub/attributes.txt @@ -0,0 +1 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains long links.')] diff --git a/src/GitHub/data/Auth.psd1 b/src/GitHub/data/Auth.psd1 index 9a306d5c6..98d42943a 100644 --- a/src/GitHub/data/Auth.psd1 +++ b/src/GitHub/data/Auth.psd1 @@ -1,8 +1,8 @@ @{ - GitHubApp = @{ + GitHubApp = @{ ClientID = 'Iv1.f26b61bc99e69405' # $script:Auth.GitHubApp.ClientID } - OAuthApp = @{ + OAuthApp = @{ ClientID = '7204ae9b0580f2cb8288' # $script:Auth.OAuthApp.ClientID } AccessTokenGracePeriodInHours = 4 diff --git a/src/GitHub/private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 b/src/GitHub/private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 index 6bc64b2d6..1fc237268 100644 --- a/src/GitHub/private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 +++ b/src/GitHub/private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 @@ -18,6 +18,7 @@ https://docs.github.com/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#device-flow #> [OutputType([void])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Is the CLI part of the module.')] [CmdletBinding()] param( # The Client ID of the GitHub App. diff --git a/src/GitHub/private/Auth/DeviceFlow/Test-GitHubAccessTokenRefreshRequired.ps1 b/src/GitHub/private/Auth/DeviceFlow/Test-GitHubAccessTokenRefreshRequired.ps1 index 1606c6630..f9aa14138 100644 --- a/src/GitHub/private/Auth/DeviceFlow/Test-GitHubAccessTokenRefreshRequired.ps1 +++ b/src/GitHub/private/Auth/DeviceFlow/Test-GitHubAccessTokenRefreshRequired.ps1 @@ -11,12 +11,13 @@ This will test if the GitHub access token should be refreshed. #> + [OutputType([bool])] [CmdletBinding()] param() $tokenType = Get-GitHubConfig -Name 'AccessTokenType' -ErrorAction SilentlyContinue if ($tokenType -ne 'ghu_*') { - Write-Verbose "The access token is not a user token. No need to refresh." + Write-Verbose 'The access token is not a user token. No need to refresh.' return $false } diff --git a/src/GitHub/private/Config/Initialize-SecretVault.ps1 b/src/GitHub/private/Config/Initialize-SecretVault.ps1 index b17dee6f6..e39dd3d90 100644 --- a/src/GitHub/private/Config/Initialize-SecretVault.ps1 +++ b/src/GitHub/private/Config/Initialize-SecretVault.ps1 @@ -4,21 +4,21 @@ function Initialize-SecretVault { <# - .SYNOPSIS - Initialize a secret vault. + .SYNOPSIS + Initialize a secret vault. - .DESCRIPTION - Initialize a secret vault. If the vault does not exist, it will be created. + .DESCRIPTION + Initialize a secret vault. If the vault does not exist, it will be created. - .EXAMPLE - Initialize-SecretVault -Name 'SecretStore' -Type 'Microsoft.PowerShell.SecretStore' + .EXAMPLE + Initialize-SecretVault -Name 'SecretStore' -Type 'Microsoft.PowerShell.SecretStore' - Initializes a secret vault named 'SecretStore' using the 'Microsoft.PowerShell.SecretStore' module. + 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 + .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 ( diff --git a/src/GitHub/private/Config/Reset-GitHubConfig.ps1 b/src/GitHub/private/Config/Reset-GitHubConfig.ps1 index 54f0933bc..9586c2137 100644 --- a/src/GitHub/private/Config/Reset-GitHubConfig.ps1 +++ b/src/GitHub/private/Config/Reset-GitHubConfig.ps1 @@ -18,7 +18,7 @@ #> [Alias('Reset-GHConfig')] [OutputType([void])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param( # Reset the GitHub configuration for a specific scope. [Parameter()] @@ -58,5 +58,7 @@ } } } - Set-GitHubConfig @Settings + if ($PSCmdlet.ShouldProcess('Module config', 'Reset')) { + Set-GitHubConfig @Settings + } } diff --git a/src/GitHub/private/Gitignore/Get-GitHubGitignoreByName.ps1 b/src/GitHub/private/Gitignore/Get-GitHubGitignoreByName.ps1 new file mode 100644 index 000000000..f4259c994 --- /dev/null +++ b/src/GitHub/private/Gitignore/Get-GitHubGitignoreByName.ps1 @@ -0,0 +1,38 @@ +filter Get-GitHubGitignoreByName { + <# + .SYNOPSIS + Get a gitignore template + + .DESCRIPTION + The API also allows fetching the source of a single template. + Use the raw [media type](https://docs.github.com/rest/overview/media-types/) to get the raw contents. + + .EXAMPLE + Get-GitHubGitignoreList + + Get all gitignore templates + + .NOTES + https://docs.github.com/rest/gitignore/gitignore#get-a-gitignore-template + + #> + [CmdletBinding()] + param ( + [Parameter()] + [ValidateNotNullOrEmpty()] + [string] $Name + ) + + Process { + $inputObject = @{ + APIEndpoint = "/gitignore/templates/$Name" + Accept = 'application/vnd.github.raw+json' + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + + } +} diff --git a/src/GitHub/private/Gitignore/Get-GitHubGitignoreList.ps1 b/src/GitHub/private/Gitignore/Get-GitHubGitignoreList.ps1 new file mode 100644 index 000000000..d4a7e3ab5 --- /dev/null +++ b/src/GitHub/private/Gitignore/Get-GitHubGitignoreList.ps1 @@ -0,0 +1,32 @@ +filter Get-GitHubGitignoreList { + <# + .SYNOPSIS + Get all gitignore templates + + .DESCRIPTION + List all templates available to pass as an option when + [creating a repository](https://docs.github.com/rest/repos/repos#create-a-repository-for-the-authenticated-user). + + .EXAMPLE + Get-GitHubGitignoreList + + Get all gitignore templates + + .NOTES + https://docs.github.com/rest/gitignore/gitignore#get-all-gitignore-templates + + #> + [OutputType([string[]])] + [CmdletBinding()] + param () + + $inputObject = @{ + APIEndpoint = '/gitignore/templates' + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + +} diff --git a/src/GitHub/private/License/Get-GitHubLicenseByName.ps1 b/src/GitHub/private/License/Get-GitHubLicenseByName.ps1 new file mode 100644 index 000000000..77afc3d7a --- /dev/null +++ b/src/GitHub/private/License/Get-GitHubLicenseByName.ps1 @@ -0,0 +1,41 @@ +filter Get-GitHubLicenseByName { + <# + .SYNOPSIS + Get a license + + .DESCRIPTION + Gets information about a specific license. + For more information, see "[Licensing a repository ](https://docs.github.com/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository)." + + .EXAMPLE + Get-GitHubGitignoreList + + Get all gitignore templates + + .NOTES + https://docs.github.com/rest/licenses/licenses#get-a-license + + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] + [CmdletBinding()] + param ( + # The license keyword, license name, or license SPDX ID. For example, mit or mpl-2.0. + [Parameter()] + [ValidateNotNullOrEmpty()] + [Alias('license')] + [string] $Name + ) + + Process { + $inputObject = @{ + APIEndpoint = "/licenses/$Name" + Accept = 'application/vnd.github+json' + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + + } +} diff --git a/src/GitHub/private/License/Get-GitHubLicenseList.ps1 b/src/GitHub/private/License/Get-GitHubLicenseList.ps1 new file mode 100644 index 000000000..9caba4260 --- /dev/null +++ b/src/GitHub/private/License/Get-GitHubLicenseList.ps1 @@ -0,0 +1,33 @@ +filter Get-GitHubLicenseList { + <# + .SYNOPSIS + Get all commonly used licenses + + .DESCRIPTION + Lists the most commonly used licenses on GitHub. + For more information, see "[Licensing a repository ](https://docs.github.com/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/licensing-a-repository)." + + .EXAMPLE + Get-GitHubLicenseList + + Get all commonly used licenses. + + .NOTES + https://docs.github.com/rest/licenses/licenses#get-all-commonly-used-licenses + + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] + [OutputType([string[]])] + [CmdletBinding()] + param () + + $inputObject = @{ + APIEndpoint = '/licenses' + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + +} diff --git a/src/GitHub/private/License/Get-GitHubRepositoryLicense.ps1 b/src/GitHub/private/License/Get-GitHubRepositoryLicense.ps1 new file mode 100644 index 000000000..403c62a8f --- /dev/null +++ b/src/GitHub/private/License/Get-GitHubRepositoryLicense.ps1 @@ -0,0 +1,46 @@ +filter Get-GitHubRepositoryLicense { + <# + .SYNOPSIS + Get the license for a repository + + .DESCRIPTION + This method returns the contents of the repository's license file, if one is detected. + + Similar to [Get repository content](https://docs.github.com/rest/repos/contents#get-repository-content), this method also supports + [custom media types](https://docs.github.com/rest/overview/media-types) for retrieving the raw license content or rendered license HTML. + + .EXAMPLE + Get-GitHubRepositoryLicense -Owner 'octocat' -Repo 'Hello-World' + + Get the license for the Hello-World repository from the octocat account. + + .NOTES + https://docs.github.com/rest/licenses/licenses#get-the-license-for-a-repository + + #> + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + Process { + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/license" + Accept = 'application/vnd.github+json' + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + $Response = $_.Response + $rawContent = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Response.content)) + $Response | Add-Member -NotePropertyName 'raw_content' -NotePropertyValue $rawContent -Force + $Response + } + } +} diff --git a/src/GitHub/private/Menu/Invoke-DrawMenu.ps1 b/src/GitHub/private/Menu/Invoke-DrawMenu.ps1 deleted file mode 100644 index 4ca69a42e..000000000 --- a/src/GitHub/private/Menu/Invoke-DrawMenu.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -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-Menu.ps1 b/src/GitHub/private/Menu/Invoke-Menu.ps1 deleted file mode 100644 index 7059a10fd..000000000 --- a/src/GitHub/private/Menu/Invoke-Menu.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -function Invoke-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 - } - $($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/private/Organization/Blocking/Block-GitHubUserByOrganization.ps1 b/src/GitHub/private/Organization/Blocking/Block-GitHubUserByOrganization.ps1 index 14ffea29f..4097f4bf1 100644 --- a/src/GitHub/private/Organization/Blocking/Block-GitHubUserByOrganization.ps1 +++ b/src/GitHub/private/Organization/Blocking/Block-GitHubUserByOrganization.ps1 @@ -4,7 +4,8 @@ Block a user from an organization .DESCRIPTION - Blocks the given user on behalf of the specified organization and returns a 204. If the organization cannot block the given user a 422 is returned. + Blocks the given user on behalf of the specified organization and returns a 204. + If the organization cannot block the given user a 422 is returned. .EXAMPLE Block-GitHubUserByOrganization -OrganizationName 'github' -Username 'octocat' diff --git a/src/GitHub/private/Organization/Blocking/Get-GitHubBlockedUserByOrganization.ps1 b/src/GitHub/private/Organization/Blocking/Get-GitHubBlockedUserByOrganization.ps1 index 96d690692..6a9d2bbfd 100644 --- a/src/GitHub/private/Organization/Blocking/Get-GitHubBlockedUserByOrganization.ps1 +++ b/src/GitHub/private/Organization/Blocking/Get-GitHubBlockedUserByOrganization.ps1 @@ -26,6 +26,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -39,6 +40,7 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response - + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Organization/Blocking/Test-GitHubBlockedUserByOrganization.ps1 b/src/GitHub/private/Organization/Blocking/Test-GitHubBlockedUserByOrganization.ps1 index 231a29ea3..7f44bdc38 100644 --- a/src/GitHub/private/Organization/Blocking/Test-GitHubBlockedUserByOrganization.ps1 +++ b/src/GitHub/private/Organization/Blocking/Test-GitHubBlockedUserByOrganization.ps1 @@ -4,7 +4,8 @@ Check if a user is blocked by an organization .DESCRIPTION - Returns a 204 if the given user is blocked by the given organization. Returns a 404 if the organization is not blocking the user, or if the user account has been identified as spam by GitHub. + Returns a 204 if the given user is blocked by the given organization. + Returns a 404 if the organization is not blocking the user, or if the user account has been identified as spam by GitHub. .EXAMPLE Test-GitHubBlockedUserByOrganization -OrganizationName 'PSModule' -Username 'octocat' diff --git a/src/GitHub/private/Organization/Blocking/Unblock-GitHubUserByOrganization.ps1 b/src/GitHub/private/Organization/Blocking/Unblock-GitHubUserByOrganization.ps1 index 3e8d208cd..14637373a 100644 --- a/src/GitHub/private/Organization/Blocking/Unblock-GitHubUserByOrganization.ps1 +++ b/src/GitHub/private/Organization/Blocking/Unblock-GitHubUserByOrganization.ps1 @@ -40,7 +40,7 @@ ) $inputObject = @{ - APIEndpoint = "/user/blocks/$Username" + APIEndpoint = "/orgs/$OrganizationName/blocks/$Username" Method = 'DELETE' } diff --git a/src/GitHub/private/Organization/Get-GitHubAllOrganization.ps1 b/src/GitHub/private/Organization/Get-GitHubAllOrganization.ps1 index 9448116a1..630a82bfd 100644 --- a/src/GitHub/private/Organization/Get-GitHubAllOrganization.ps1 +++ b/src/GitHub/private/Organization/Get-GitHubAllOrganization.ps1 @@ -6,7 +6,8 @@ .DESCRIPTION Lists all organizations, in the order that they were created on GitHub. - **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 organizations. + **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 organizations. .EXAMPLE Get-GitHubAllOrganization -Since 142951047 @@ -18,6 +19,7 @@ #> [OutputType([pscustomobject])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] [CmdletBinding()] param ( # A organization ID. Only return organizations with an ID greater than this ID. @@ -26,6 +28,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -40,6 +43,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Organization/Get-GitHubMyOrganization.ps1 b/src/GitHub/private/Organization/Get-GitHubMyOrganization.ps1 index d90f84142..eeb373552 100644 --- a/src/GitHub/private/Organization/Get-GitHubMyOrganization.ps1 +++ b/src/GitHub/private/Organization/Get-GitHubMyOrganization.ps1 @@ -8,7 +8,11 @@ **OAuth scope requirements** - This only lists organizations that your authorization allows you to operate on in some way (e.g., you can list teams with `read:org` scope, you can publicize your organization membership with `user` scope, etc.). Therefore, this API requires at least `user` or `read:org` scope. OAuth requests with insufficient scope receive a `403 Forbidden` response. + This only lists organizations that your authorization allows you to operate on + in some way (e.g., you can list teams with `read:org` scope, you can publicize your + organization membership with `user` scope, etc.). Therefore, this API requires at + least `user` or `read:org` scope. OAuth requests with insufficient scope receive a + `403 Forbidden` response. .EXAMPLE Get-GitHubMyOrganization @@ -23,6 +27,7 @@ param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -36,6 +41,7 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response - + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Organization/Get-GitHubOrganizationByName.ps1 b/src/GitHub/private/Organization/Get-GitHubOrganizationByName.ps1 index 1e7c140fd..5b2a78681 100644 --- a/src/GitHub/private/Organization/Get-GitHubOrganizationByName.ps1 +++ b/src/GitHub/private/Organization/Get-GitHubOrganizationByName.ps1 @@ -4,9 +4,15 @@ Get an organization .DESCRIPTION - To see many of the organization response values, you need to be an authenticated organization owner with the `admin:org` scope. When the value of `two_factor_requirement_enabled` is `true`, the organization requires all members, billing managers, and outside collaborators to enable [two-factor authentication](https://docs.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/). + To see many of the organization response values, you need to be an authenticated organization + owner with the `admin:org` scope. When the value of `two_factor_requirement_enabled` is `true`, + the organization requires all members, billing managers, and outside collaborators to enable + [two-factor authentication](https://docs.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/). - GitHub Apps with the `Organization plan` permission can use this endpoint to retrieve information about an organization's GitHub plan. See "[Authenticating with GitHub Apps](https://docs.github.com/apps/building-github-apps/authenticating-with-github-apps/)" for details. For an example response, see 'Response with GitHub plan information' below." + GitHub Apps with the `Organization plan` permission can use this endpoint to retrieve information + about an organization's GitHub plan. See + "[Authenticating with GitHub Apps](https://docs.github.com/apps/building-github-apps/authenticating-with-github-apps/)" + for details. For an example response, see 'Response with GitHub plan information' below." .EXAMPLE Get-GitHubOrganizationByName -OrganizationName 'github' @@ -37,6 +43,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Organization/Get-GitHubUserOrganization.ps1 b/src/GitHub/private/Organization/Get-GitHubUserOrganization.ps1 index 1e815c218..cd2ea411d 100644 --- a/src/GitHub/private/Organization/Get-GitHubUserOrganization.ps1 +++ b/src/GitHub/private/Organization/Get-GitHubUserOrganization.ps1 @@ -4,9 +4,13 @@ List organizations for a user .DESCRIPTION - List [public organization memberships](https://docs.github.com/articles/publicizing-or-concealing-organization-membership) for the specified user. + List [public organization memberships](https://docs.github.com/articles/publicizing-or-concealing-organization-membership) + for the specified user. - This method only lists _public_ memberships, regardless of authentication. If you need to fetch all of the organization memberships (public and private) for the authenticated user, use the [List organizations for the authenticated user](https://docs.github.com/rest/orgs/orgs#list-organizations-for-the-authenticated-user) API instead. + This method only lists _public_ memberships, regardless of authentication. + If you need to fetch all of the organization memberships (public and private) for the authenticated user, use the + [List organizations for the authenticated user](https://docs.github.com/rest/orgs/orgs#list-organizations-for-the-authenticated-user) + API instead. .EXAMPLE Get-GitHubUserOrganization -Username 'octocat' @@ -25,6 +29,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -38,6 +43,7 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response - + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Releases/Assets/Get-GitHubReleaseAssetByID.ps1 b/src/GitHub/private/Releases/Assets/Get-GitHubReleaseAssetByID.ps1 index 98a405a4e..1ec06269f 100644 --- a/src/GitHub/private/Releases/Assets/Get-GitHubReleaseAssetByID.ps1 +++ b/src/GitHub/private/Releases/Assets/Get-GitHubReleaseAssetByID.ps1 @@ -4,8 +4,10 @@ Get a release asset .DESCRIPTION - To download the asset's binary content, set the `Accept` header of the request to [`application/octet-stream`](https://docs.github.com/rest/overview/media-types). - The API will either redirect the client to the location, or stream it directly if possible. API clients should handle both a `200` or `302` response. + To download the asset's binary content, set the `Accept` header of the request to + [`application/octet-stream`](https://docs.github.com/rest/overview/media-types). + The API will either redirect the client to the location, or stream it directly if + possible. API clients should handle both a `200` or `302` response. .EXAMPLE Get-GitHubReleaseAssetByID -Owner 'octocat' -Repo 'hello-world' -ID '1234567' @@ -37,6 +39,7 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response - + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Releases/Assets/Get-GitHubReleaseAssetByReleaseID.ps1 b/src/GitHub/private/Releases/Assets/Get-GitHubReleaseAssetByReleaseID.ps1 index 022f54b7d..cb3ac0b0d 100644 --- a/src/GitHub/private/Releases/Assets/Get-GitHubReleaseAssetByReleaseID.ps1 +++ b/src/GitHub/private/Releases/Assets/Get-GitHubReleaseAssetByReleaseID.ps1 @@ -35,11 +35,12 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'Owner', 'Repo', 'ID' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo', 'ID' $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/releases/$ID/assets" @@ -47,6 +48,7 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response - + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Releases/Releases/Get-GitHubReleaseAll.ps1 b/src/GitHub/private/Releases/Releases/Get-GitHubReleaseAll.ps1 index a29ed01ef..7ebd6982c 100644 --- a/src/GitHub/private/Releases/Releases/Get-GitHubReleaseAll.ps1 +++ b/src/GitHub/private/Releases/Releases/Get-GitHubReleaseAll.ps1 @@ -29,11 +29,12 @@ # The number of results per page (max 100). [Parameter(ParameterSetName = 'AllUsers')] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'Owner', 'Repo' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/releases" @@ -41,6 +42,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Releases/Releases/Get-GitHubReleaseByID.ps1 b/src/GitHub/private/Releases/Releases/Get-GitHubReleaseByID.ps1 index b5d57a318..73d98433d 100644 --- a/src/GitHub/private/Releases/Releases/Get-GitHubReleaseByID.ps1 +++ b/src/GitHub/private/Releases/Releases/Get-GitHubReleaseByID.ps1 @@ -39,6 +39,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Releases/Releases/Get-GitHubReleaseByTagName.ps1 b/src/GitHub/private/Releases/Releases/Get-GitHubReleaseByTagName.ps1 index 57c4b0dca..4ed7ccf35 100644 --- a/src/GitHub/private/Releases/Releases/Get-GitHubReleaseByTagName.ps1 +++ b/src/GitHub/private/Releases/Releases/Get-GitHubReleaseByTagName.ps1 @@ -38,6 +38,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Releases/Releases/Get-GitHubReleaseLatest.ps1 b/src/GitHub/private/Releases/Releases/Get-GitHubReleaseLatest.ps1 index 2391d72e2..8cc417614 100644 --- a/src/GitHub/private/Releases/Releases/Get-GitHubReleaseLatest.ps1 +++ b/src/GitHub/private/Releases/Releases/Get-GitHubReleaseLatest.ps1 @@ -34,6 +34,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Repositories/Autolinks/Get-GitHubRepositoryAutolinkById.ps1 b/src/GitHub/private/Repositories/Autolinks/Get-GitHubRepositoryAutolinkById.ps1 new file mode 100644 index 000000000..770cc1fc8 --- /dev/null +++ b/src/GitHub/private/Repositories/Autolinks/Get-GitHubRepositoryAutolinkById.ps1 @@ -0,0 +1,46 @@ +filter Get-GitHubRepositoryAutolinkById { + <# + .SYNOPSIS + Get an autolink reference of a repository + + .DESCRIPTION + This returns a single autolink reference by ID that was configured for the given repository. + + Information about autolinks are only available to repository administrators. + + .EXAMPLE + Get-GitHubRepositoryAutolinkById -Owner 'octocat' -Repo 'Hello-World' -Id 1 + + Gets the autolink with the id 1 for the repository 'Hello-World' owned by 'octocat'. + + .NOTES + https://docs.github.com/rest/repos/autolinks#get-an-autolink-reference-of-a-repository + + #> + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The unique identifier of the autolink. + [Parameter(Mandatory)] + [Alias('autolink_id')] + [Alias('Id')] + [int] $AutolinkId + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/autolinks/$AutolinkId" + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/private/Repositories/Autolinks/Get-GitHubRepositoryAutolinkList.ps1 b/src/GitHub/private/Repositories/Autolinks/Get-GitHubRepositoryAutolinkList.ps1 new file mode 100644 index 000000000..c3a49359e --- /dev/null +++ b/src/GitHub/private/Repositories/Autolinks/Get-GitHubRepositoryAutolinkList.ps1 @@ -0,0 +1,40 @@ +filter Get-GitHubRepositoryAutolinkList { + <# + .SYNOPSIS + List all autolinks of a repository + + .DESCRIPTION + This returns a list of autolinks configured for the given repository. + + Information about autolinks are only available to repository administrators. + + .EXAMPLE + Get-GitHubRepositoryAutolinkList -Owner 'octocat' -Repo 'Hello-World' + + Gets all autolinks for the repository 'Hello-World' owned by 'octocat'. + + .NOTES + https://docs.github.com/rest/repos/autolinks#list-all-autolinks-of-a-repository + + #> + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/autolinks" + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/private/Repositories/Fork/New-GitHubRepositoryAsFork.ps1 b/src/GitHub/private/Repositories/Fork/New-GitHubRepositoryAsFork.ps1 new file mode 100644 index 000000000..f8b3d881b --- /dev/null +++ b/src/GitHub/private/Repositories/Fork/New-GitHubRepositoryAsFork.ps1 @@ -0,0 +1,101 @@ +filter New-GitHubRepositoryAsFork { + <# + .SYNOPSIS + Create a fork + + .DESCRIPTION + Create a fork for the authenticated user. + + **Note**: Forking a Repository happens asynchronously. You may have to wait a short period of time before you can access the git objects. + If this takes longer than 5 minutes, be sure to contact [GitHub Support](https://support.github.com/contact?tags=dotcom-rest-api). + + **Note**: Although this endpoint works with GitHub Apps, the GitHub App must be installed on the destination account with access to all + repositories and on the source account with access to the source repository. + + .EXAMPLE + New-GitHubRepositoryAsFork -ForkOwner 'github' -ForkRepo 'Hello-World' + + Fork the repository `Hello-World` owned by `github` for the authenticated user. + Repo will be named `Hello-World`, and all branches and tags will be forked. + + .EXAMPLE + New-GitHubRepositoryAsFork -ForkOwner 'github' -ForkRepo 'Hello-World' -Name 'Hello-World-2' + + Fork the repository `Hello-World` owned by `github` for the authenticated user, naming the resulting repository `Hello-World-2`. + + .EXAMPLE + New-GitHubRepositoryAsFork -ForkOwner 'github' -ForkRepo 'Hello-World' -Organization 'octocat' + + Fork the repository `Hello-World` owned by `github` for the organization `octocat`, naming the resulting repository `Hello-World`. + + .EXAMPLE + New-GitHubRepositoryAsFork -ForkOwner 'github' -ForkRepo 'Hello-World' -DefaultBranchOnly + + Fork the repository `Hello-World` owned by `github` for the authenticated user, forking only the default branch. + + .NOTES + https://docs.github.com/rest/repos/forks#create-a-fork + + #> + [OutputType([pscustomobject])] + [CmdletBinding(SupportsShouldProcess)] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Repo, + + # The organization or person who will own the new repository. + # To create a new repository in an organization, the authenticated user must be a member of the specified organization. + [Parameter()] + [string] $Organization = (Get-GitHubConfig -Name Owner), + + # The name of the new repository. + [Parameter()] + [string] $Name, + + # When forking from an existing repository, fork with only the default branch. + [Parameter()] + [Alias('default_branch_only')] + [switch] $DefaultBranchOnly + ) + + if ([string]::IsNullorEmpty($Name)) { + $Name = $ForkRepo + } + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $body['default_branch_only'] = $DefaultBranchOnly + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/forks" + Method = 'POST' + Body = $body + } + + if ($PSCmdlet.ShouldProcess("Repository [$Organization/$Name] as fork of [$Owner/$Repo]", 'Create')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/private/Repositories/Repositories/Get-GitHubMyRepositories.ps1 b/src/GitHub/private/Repositories/Repositories/Get-GitHubMyRepositories.ps1 new file mode 100644 index 000000000..fa20d1326 --- /dev/null +++ b/src/GitHub/private/Repositories/Repositories/Get-GitHubMyRepositories.ps1 @@ -0,0 +1,144 @@ +filter Get-GitHubMyRepositories { + <# + .SYNOPSIS + List repositories for the authenticated user + + .DESCRIPTION + Lists repositories that the authenticated user has explicit permission (`:read`, `:write`, or `:admin`) to access. + The authenticated user has explicit permission to access repositories they own, repositories where + they are a collaborator, and repositories that they can access through an organization membership. + + .EXAMPLE + Get-GitHubMyRepositories + + Gets the repositories for the authenticated user. + + .EXAMPLE + Get-GitHubMyRepositories -Visibility 'private' + + Gets the private repositories for the authenticated user. + + .EXAMPLE + $param = @{ + Visibility = 'public' + Affiliation = 'owner','collaborator' + Sort = 'created' + Direction = 'asc' + PerPage = 100 + Since = (Get-Date).AddYears(-5) + Before = (Get-Date).AddDays(-1) + } + Get-GitHubMyRepositories @param + + Gets the public repositories for the authenticated user that are owned by the authenticated user + or that the authenticated user has been added to as a collaborator. The results are sorted by + creation date in ascending order and the results are limited to 100 repositories. The results + are limited to repositories created between 5 years ago and 1 day ago. + + .EXAMPLE + Get-GitHubMyRepositories -Type 'forks' + + Gets the forked repositories for the authenticated user. + + .EXAMPLE + Get-GitHubMyRepositories -Type 'sources' + + Gets the non-forked repositories for the authenticated user. + + .EXAMPLE + Get-GitHubMyRepositories -Type 'member' + + Gets the repositories for the authenticated user that are owned by an organization. + + .NOTES + https://docs.github.com/rest/repos/repos#list-repositories-for-the-authenticated-user + + #> + [CmdletBinding(DefaultParameterSetName = 'Type')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Private function, not exposed to user.')] + param ( + # Limit results to repositories with the specified visibility. + [Parameter( + ParameterSetName = 'Aff-Vis' + )] + [ValidateSet('all', 'public', 'private')] + [string] $Visibility = 'all', + + # Comma-separated list of values. Can include: + # - owner: Repositories that are owned by the authenticated user. + # - collaborator: Repositories that the user has been added to as a collaborator. + # - organization_member: Repositories that the user has access to through being a member of an organization. + # This includes every repository on every team that the user is on. + # Default: owner, collaborator, organization_member + [Parameter( + ParameterSetName = 'Aff-Vis' + )] + [ValidateSet('owner', 'collaborator', 'organization_member')] + [string[]] $Affiliation = @('owner', 'collaborator', 'organization_member'), + + # Specifies the types of repositories you want returned. + [Parameter( + ParameterSetName = 'Type' + )] + [ValidateSet('all', 'owner', 'public', 'private', 'member')] + [string] $Type = 'all', + + # The property to sort the results by. + [Parameter()] + [ValidateSet('created', 'updated', 'pushed', 'full_name')] + [string] $Sort = 'created', + + # The order to sort by. + # Default: asc when using full_name, otherwise desc. + [Parameter()] + [ValidateSet('asc', 'desc')] + [string] $Direction, + + # The number of results per page (max 100). + [Parameter()] + [ValidateRange(1, 100)] + [int] $PerPage = 30, + + # Only show repositories updated after the given time. + [Parameter()] + [datetime] $Since, + + # Only show repositories updated before the given time. + [Parameter()] + [datetime] $Before + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + Write-Verbose "Parameter: [$($_.Key)] = [$($_.Value)]" + $paramDefaultValue = Get-Variable -Name $_.Key -ValueOnly -ErrorAction SilentlyContinue + if (-not $PSBoundParameters.ContainsKey($_.Key) -and ($null -ne $paramDefaultValue)) { + Write-Verbose "Parameter: [$($_.Key)] = [$($_.Value)] - Adding default value" + $PSBoundParameters[$_.Key] = $paramDefaultValue + } + Write-Verbose " - $($PSBoundParameters[$_.Key])" + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Affiliation', 'Since', 'Before' + + if ($PSBoundParameters.ContainsKey('Affiliation')) { + $body['affiliation'] = $Affiliation -join ',' + } + if ($PSBoundParameters.ContainsKey('Since')) { + $body['since'] = $Since.ToString('yyyy-MM-ddTHH:mm:ssZ') + } + if ($PSBoundParameters.ContainsKey('Before')) { + $body['before'] = $Before.ToString('yyyy-MM-ddTHH:mm:ssZ') + } + + $inputObject = @{ + APIEndpoint = '/user/repos' + Method = 'GET' + body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + +} diff --git a/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryByName.ps1 b/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryByName.ps1 new file mode 100644 index 000000000..a37e81f12 --- /dev/null +++ b/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryByName.ps1 @@ -0,0 +1,44 @@ +filter Get-GitHubRepositoryByName { + <# + .SYNOPSIS + Get a repository + + .DESCRIPTION + The `parent` and `source` objects are present when the repository is a fork. + `parent` is the repository this repository was forked from, `source` is the ultimate source for the network. + **Note:** In order to see the `security_and_analysis` block for a repository you must have admin permissions + for the repository or be an owner or security manager for the organization that owns the repository. + For more information, see "[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization)." + + .EXAMPLE + Get-GitHubRepositoryByName -Owner 'octocat' -Repo 'Hello-World' + + Gets the repository 'Hello-World' for the organization 'octocat'. + + .NOTES + https://docs.github.com/rest/repos/repos#get-a-repository + + #> + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo" + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + +} diff --git a/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByID.ps1 b/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByID.ps1 new file mode 100644 index 000000000..ab2695799 --- /dev/null +++ b/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByID.ps1 @@ -0,0 +1,53 @@ +filter Get-GitHubRepositoryListByID { + <# + .SYNOPSIS + List public repositories + + .DESCRIPTION + Lists all public repositories in the order that they were created. + + Note: + - For GitHub Enterprise Server, this endpoint will only list repositories available to all users on the enterprise. + - 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 repositories. + + .EXAMPLE + Get-GitHubRepositoryListByID -Since '123456789 + + Gets the repositories with an ID equals and greater than 123456789. + + .NOTES + https://docs.github.com/rest/repos/repos#list-public-repositories + + #> + [CmdletBinding()] + param ( + # A repository ID. Only return repositories with an ID greater than this ID. + [Parameter()] + [int] $Since = 0 + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + Write-Verbose "Parameter: [$($_.Key)] = [$($_.Value)]" + $paramDefaultValue = Get-Variable -Name $_.Key -ValueOnly -ErrorAction SilentlyContinue + if (-not $PSBoundParameters.ContainsKey($_.Key) -and ($null -ne $paramDefaultValue)) { + Write-Verbose "Parameter: [$($_.Key)] = [$($_.Value)] - Adding default value" + $PSBoundParameters[$_.Key] = $paramDefaultValue + } + Write-Verbose " - $($PSBoundParameters[$_.Key])" + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + + $inputObject = @{ + APIEndpoint = '/repositories' + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + +} diff --git a/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByOrg.ps1 b/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByOrg.ps1 new file mode 100644 index 000000000..d6666f478 --- /dev/null +++ b/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByOrg.ps1 @@ -0,0 +1,83 @@ +filter Get-GitHubRepositoryListByOrg { + <# + .SYNOPSIS + List organization repositories + + .DESCRIPTION + Lists repositories for the specified organization. + **Note:** In order to see the `security_and_analysis` block for a repository you must have admin permissions for the repository + or be an owner or security manager for the organization that owns the repository. + For more information, see "[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization)." + + .EXAMPLE + Get-GitHubRepositoryListByOrg -Owner 'octocat' + + Gets the repositories for the organization 'octocat'. + + .EXAMPLE + Get-GitHubRepositoryListByOrg -Owner 'octocat' -Type 'public' + + Gets the public repositories for the organization 'octocat'. + + .EXAMPLE + Get-GitHubRepositoryListByOrg -Owner 'octocat' -Sort 'created' -Direction 'asc' + + Gets the repositories for the organization 'octocat' sorted by creation date in ascending order. + + .NOTES + https://docs.github.com/rest/repos/repos#list-organization-repositories + + #> + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # Specifies the types of repositories you want returned. + [Parameter()] + [validateSet('all', 'public', 'private', 'forks', 'sources', 'member')] + [string] $type = 'all', + + # The property to sort the results by. + [Parameter()] + [validateSet('created', 'updated', 'pushed', 'full_name')] + [string] $Sort = 'created', + + # The order to sort by. + # Default: asc when using full_name, otherwise desc. + [Parameter()] + [validateSet('asc', 'desc')] + [string] $Direction, + + # The number of results per page (max 100). + [Parameter()] + [ValidateRange(1, 100)] + [int] $PerPage = 30 + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + Write-Verbose "Parameter: [$($_.Key)] = [$($_.Value)]" + $paramDefaultValue = Get-Variable -Name $_.Key -ValueOnly -ErrorAction SilentlyContinue + if (-not $PSBoundParameters.ContainsKey($_.Key) -and ($null -ne $paramDefaultValue)) { + Write-Verbose "Parameter: [$($_.Key)] = [$($_.Value)] - Adding default value" + $PSBoundParameters[$_.Key] = $paramDefaultValue + } + Write-Verbose " - $($PSBoundParameters[$_.Key])" + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner' + + $inputObject = @{ + APIEndpoint = "/orgs/$Owner/repos" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + +} diff --git a/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByUser.ps1 b/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByUser.ps1 new file mode 100644 index 000000000..2b00538b1 --- /dev/null +++ b/src/GitHub/private/Repositories/Repositories/Get-GitHubRepositoryListByUser.ps1 @@ -0,0 +1,84 @@ +filter Get-GitHubRepositoryListByUser { + <# + .SYNOPSIS + List repositories for a user + + .DESCRIPTION + Lists public repositories for the specified user. + Note: For GitHub AE, this endpoint will list internal repositories for the specified user. + + .EXAMPLE + Get-GitHubRepositoryListByUser -Username 'octocat' + + Gets the repositories for the user 'octocat'. + + .EXAMPLE + Get-GitHubRepositoryListByUser -Username 'octocat' -Type 'member' + + Gets the repositories of organizations where the user 'octocat' is a member. + + .EXAMPLE + Get-GitHubRepositoryListByUser -Username 'octocat' -Sort 'created' -Direction 'asc' + + Gets the repositories for the user 'octocat' sorted by creation date in ascending order. + + .NOTES + https://docs.github.com/rest/repos/repos#list-repositories-for-a-user + + #> + [CmdletBinding()] + param ( + # The handle for the GitHub user account. + [Parameter( + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName + )] + [Alias('login')] + [string] $Username, + + # Specifies the types of repositories you want returned. + [Parameter()] + [validateSet('all', 'owner', 'member')] + [string] $Type = 'all', + + # The property to sort the results by. + [Parameter()] + [validateSet('created', 'updated', 'pushed', 'full_name')] + [string] $Sort = 'created', + + # The order to sort by. + # Default: asc when using full_name, otherwise desc. + [Parameter()] + [validateSet('asc', 'desc')] + [string] $Direction, + + # The number of results per page (max 100). + [Parameter()] + [ValidateRange(1, 100)] + [int] $PerPage = 30 + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + Write-Verbose "Parameter: [$($_.Key)] = [$($_.Value)]" + $paramDefaultValue = Get-Variable -Name $_.Key -ValueOnly -ErrorAction SilentlyContinue + if (-not $PSBoundParameters.ContainsKey($_.Key) -and ($null -ne $paramDefaultValue)) { + Write-Verbose "Parameter: [$($_.Key)] = [$($_.Value)] - Adding default value" + $PSBoundParameters[$_.Key] = $paramDefaultValue + } + Write-Verbose " - $($PSBoundParameters[$_.Key])" + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Username' + + $inputObject = @{ + APIEndpoint = "/users/$Username/repos" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryFromTemplate.ps1 b/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryFromTemplate.ps1 new file mode 100644 index 000000000..b7b240a0c --- /dev/null +++ b/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryFromTemplate.ps1 @@ -0,0 +1,105 @@ +filter New-GitHubRepositoryFromTemplate { + <# + .SYNOPSIS + Create a repository using a template + + .DESCRIPTION + Creates a new repository using a repository template. Use the `template_owner` and `template_repo` + route parameters to specify the repository to use as the template. If the repository is not public, + the authenticated user must own or be a member of an organization that owns the repository. + To check if a repository is available to use as a template, get the repository's information using the + [Get a repository](https://docs.github.com/rest/repos/repos#get-a-repository) endpoint and check that the `is_template` key is `true`. + + **OAuth scope requirements** + + When using [OAuth](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/), authorizations must include: + + * `public_repo` scope or `repo` scope to create a public repository. Note: For GitHub AE, use `repo` scope to create an internal repository. + * `repo` scope to create a private repository + + .EXAMPLE + $params = @{ + TemplateOwner = 'GitHub' + TemplateRepo = 'octocat' + Owner = 'PSModule' + Name = 'MyNewRepo' + IncludeAllBranches = $true + Description = 'My new repo' + Private = $true + } + New-GitHubRepositoryFromTemplate @params + + Creates a new private repository named `MyNewRepo` from the `octocat` template repository owned by `GitHub`. + + .NOTES + https://docs.github.com/rest/repos/repos#create-a-repository-using-a-template + + #> + [OutputType([pscustomobject])] + [CmdletBinding(SupportsShouldProcess)] + param ( + # The account owner of the template repository. The name is not case sensitive. + [Parameter(Mandatory)] + [Alias('template_owner')] + [string] $TemplateOwner, + + # The name of the template repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory)] + [Alias('template_repo')] + [string] $TemplateRepo, + + # The organization or person who will own the new repository. + # To create a new repository in an organization, the authenticated user must be a member of the specified organization. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the new repository. + [Parameter(Mandatory)] + [string] $Name, + + # A short description of the new repository. + [Parameter()] + [string] $Description, + + # Set to true to include the directory structure and files from all branches in the template repository, + # and not just the default branch. + [Parameter()] + [Alias('include_all_branches')] + [switch] $IncludeAllBranches, + + # Either true to create a new private repository or false to create a new public one. + [Parameter()] + [switch] $Private + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'TemplateOwner', 'TemplateRepo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$TemplateOwner/$TemplateRepo/generate" + Method = 'POST' + Body = $body + } + + if ($PSCmdlet.ShouldProcess("Repository [$Owner/$Name] from template [$TemplateOwner/$TemplateRepo]", 'Create')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryOrg.ps1 b/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryOrg.ps1 new file mode 100644 index 000000000..494c4ffc2 --- /dev/null +++ b/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryOrg.ps1 @@ -0,0 +1,258 @@ +filter New-GitHubRepositoryOrg { + <# + .SYNOPSIS + Create an organization repository + + .DESCRIPTION + Creates a new repository in the specified organization. The authenticated user must be a member of the organization. + + **OAuth scope requirements** + + When using [OAuth](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/), authorizations must include: + + * `public_repo` scope or `repo` scope to create a public repository. Note: For GitHub AE, use `repo` scope to create an internal repository. + * `repo` scope to create a private repository + + .EXAMPLE + $params = @{ + Owner = 'PSModule' + Name = 'Hello-World' + Description = 'This is your first repository' + Homepage = 'https://github.com' + HasIssues = $true + HasProjects = $true + HasWiki = $true + HasDownloads = $true + IsTemplate = $true + AutoInit = $true + AllowSquashMerge = $true + AllowAutoMerge = $true + DeleteBranchOnMerge = $true + SquashMergeCommitTitle = 'PR_TITLE' + SquashMergeCommitMessage = 'PR_BODY' + } + New-GitHubRepositoryOrg @params + + Creates a new public repository named "Hello-World" owned by the organization "PSModule". + + .PARAMETER GitignoreTemplate + Desired language or platform .gitignore template to apply. Use the name of the template without the extension. For example, "Haskell". + + .PARAMETER LicenseTemplate + Choose an open source license template that best suits your needs, and then use the license keyword as the license_template string. + For example, "mit" or "mpl-2.0". + + .NOTES + https://docs.github.com/rest/repos/repos#create-an-organization-repository + + #> + [OutputType([pscustomobject])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseDeclaredVarsMoreThanAssignments', + 'GitignoreTemplate', + Justification = 'Parameter is used in dynamic parameter validation.' + )] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseDeclaredVarsMoreThanAssignments', + 'LicenseTemplate', + Justification = 'Parameter is used in dynamic parameter validation.' + )] + [CmdletBinding(SupportsShouldProcess)] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository. + [Parameter(Mandatory)] + [string] $Name, + + # A short description of the repository. + [Parameter()] + [string] $Description, + + # A URL with more information about the repository. + [Parameter()] + [ValidateNotNullOrEmpty()] + [uri] $Homepage, + + # The visibility of the repository. + [Parameter()] + [ValidateSet('public', 'private')] + [string] $Visibility = 'public', + + # Either true to enable issues for this repository or false to disable them. + [Parameter()] + [Alias('has_issues')] + [switch] $HasIssues, + + # Either true to enable projects for this repository or false to disable them. + # Note: If you're creating a repository in an organization that has disabled repository projects, the default is false, + # and if you pass true, the API returns an error. + [Parameter()] + [Alias('has_projects')] + [switch] $HasProjects, + + # Either true to enable the wiki for this repository or false to disable it. + [Parameter()] + [Alias('has_wiki')] + [switch] $HasWiki, + + # Whether downloads are enabled. + [Parameter()] + [Alias('has_downloads')] + [switch] $HasDownloads, + + # Either true to make this repo available as a template repository or false to prevent it. + [Parameter()] + [Alias('is_template')] + [switch] $IsTemplate, + + # The id of the team that will be granted access to this repository. This is only valid when creating a repository in an organization. + [Parameter()] + [Alias('team_id')] + [int] $TeamId, + + # Pass true to create an initial commit with empty README. + [Parameter()] + [Alias('auto_init')] + [switch] $AutoInit, + + # Either true to allow squash-merging pull requests, or false to prevent squash-merging. + [Parameter()] + [Alias('allow_squash_merge')] + [switch] $AllowSquashMerge, + + # Either true to allow merging pull requests with a merge commit, or false to prevent merging pull requests with merge commits. + [Parameter()] + [Alias('allow_merge_commit')] + [switch] $AllowMergeCommit, + + # Either true to allow rebase-merging pull requests, or false to prevent rebase-merging. + [Parameter()] + [Alias('allow_rebase_merge')] + [switch] $AllowRebaseMerge, + + # Either true to allow auto-merge on pull requests, or false to disallow auto-merge. + [Parameter()] + [Alias('allow_auto_merge')] + [switch] $AllowAutoMerge, + + # Either true to allow automatically deleting head branches when pull requests are merged, or false to prevent automatic deletion. + # The authenticated user must be an organization owner to set this property to true. + [Parameter()] + [Alias('delete_branch_on_merge')] + [switch] $DeleteBranchOnMerge, + + # The default value for a squash merge commit title: + # - PR_TITLE - default to the pull request's title. + # - COMMIT_OR_PR_TITLE - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + [Parameter()] + [ValidateSet('PR_TITLE', 'COMMIT_OR_PR_TITLE')] + [Alias('squash_merge_commit_title')] + [string] $SquashMergeCommitTitle, + + # The default value for a squash merge commit message: + # - PR_BODY - default to the pull request's body. + # - COMMIT_MESSAGES - default to the branch's commit messages. + # - BLANK - default to a blank commit message. + [Parameter()] + [ValidateSet('PR_BODY', 'COMMIT_MESSAGES', 'BLANK')] + [Alias('squash_merge_commit_message')] + [string] $SquashMergeCommitMessage, + + # The default value for a merge commit title. + # - PR_TITLE - default to the pull request's title. + # - MERGE_MESSAGE - default to the classic title for a merge message (e.g.,Merge pull request #123 from branch-name). + [Parameter()] + [ValidateSet('PR_TITLE', 'MERGE_MESSAGE')] + [Alias('merge_commit_title')] + [string] $MergeCommitTitle, + + # The default value for a merge commit message. + # - PR_BODY - default to the pull request's body. + # - PR_TITLE - default to the pull request's title. + # - BLANK - default to a blank commit message. + [Parameter()] + [ValidateSet('PR_BODY', 'PR_TITLE', 'BLANK')] + [Alias('merge_commit_message')] + [string] $MergeCommitMessage + ) + + DynamicParam { + $DynamicParamDictionary = New-DynamicParamDictionary + + $dynParam = @{ + Name = 'GitignoreTemplate' + Alias = 'gitignore_template' + Type = [string] + ValidateSet = Get-GitHubGitignoreList + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam + + $dynParam2 = @{ + Name = 'LicenseTemplate' + Alias = 'license_template' + Type = [string] + ValidateSet = Get-GitHubLicenseList | Select-Object -ExpandProperty key + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam2 + + return $DynamicParamDictionary + } + + begin { + $GitignoreTemplate = $PSBoundParameters['GitignoreTemplate'] + $LicenseTemplate = $PSBoundParameters['LicenseTemplate'] + } + + Process { + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner' -RemoveTypes 'SwitchParameter' + + $body['private'] = $Visibility -eq 'private' + $body['has_issues'] = $HasIssues.IsPresent ? $HasIssues : $false + $body['has_wiki'] = $HasWiki.IsPresent ? $HasWiki : $false + $body['has_projects'] = $HasProjects.IsPresent ? $HasProjects : $false + $body['has_downloads'] = $HasDownloads.IsPresent ? $HasDownloads : $false + $body['is_template'] = $IsTemplate.IsPresent ? $IsTemplate : $false + $body['auto_init'] = $AutoInit.IsPresent ? $AutoInit : $false + $body['allow_squash_merge'] = $AllowSquashMerge.IsPresent ? $AllowSquashMerge : $false + $body['allow_merge_commit'] = $AllowMergeCommit.IsPresent ? $AllowMergeCommit : $false + $body['allow_rebase_merge'] = $AllowRebaseMerge.IsPresent ? $AllowRebaseMerge : $false + $body['allow_auto_merge'] = $AllowAutoMerge.IsPresent ? $AllowAutoMerge : $false + $body['delete_branch_on_merge'] = $DeleteBranchOnMerge.IsPresent ? $DeleteBranchOnMerge : $false + + Remove-HashtableEntry -Hashtable $body -NullOrEmptyValues + + $inputObject = @{ + APIEndpoint = "/orgs/$Owner/repos" + Method = 'POST' + Body = $body + } + + if ($PSCmdlet.ShouldProcess("Repository in organization $Owner", 'Create')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } + } +} diff --git a/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryUser.ps1 b/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryUser.ps1 new file mode 100644 index 000000000..eca573886 --- /dev/null +++ b/src/GitHub/private/Repositories/Repositories/New-GitHubRepositoryUser.ps1 @@ -0,0 +1,253 @@ +filter New-GitHubRepositoryUser { + <# + .SYNOPSIS + Create a repository for the authenticated user + + .DESCRIPTION + Creates a new repository for the authenticated user. + + **OAuth scope requirements** + + When using [OAuth](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/), authorizations must include: + + * `public_repo` scope or `repo` scope to create a public repository. Note: For GitHub AE, use `repo` scope to create an internal repository. + * `repo` scope to create a private repository. + + .EXAMPLE + $params = @{ + Name = 'Hello-World' + Description = 'This is your first repository' + Homepage = 'https://github.com' + HasIssues = $true + HasProjects = $true + HasWiki = $true + HasDownloads = $true + IsTemplate = $true + AutoInit = $true + AllowSquashMerge = $true + AllowAutoMerge = $true + DeleteBranchOnMerge = $true + SquashMergeCommitTitle = 'PR_TITLE' + SquashMergeCommitMessage = 'PR_BODY' + } + New-GitHubRepositoryUser @params + + Creates a new public repository named "Hello-World" owned by the authenticated user. + + .PARAMETER GitignoreTemplate + The desired language or platform to apply to the .gitignore. + + .PARAMETER LicenseTemplate + The license keyword of the open source license for this repository. + + .NOTES + https://docs.github.com/rest/repos/repos#create-a-repository-for-the-authenticated-user + + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseDeclaredVarsMoreThanAssignments', + 'GitignoreTemplate', + Justification = 'Parameter is used in dynamic parameter validation.' + )] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseDeclaredVarsMoreThanAssignments', + 'LicenseTemplate', + Justification = 'Parameter is used in dynamic parameter validation.' + )] + [CmdletBinding(SupportsShouldProcess)] + param ( + # The name of the repository. + [Parameter(Mandatory)] + [string] $Name, + + # A short description of the repository. + [Parameter()] + [string] $Description, + + # A URL with more information about the repository. + [Parameter()] + [ValidateNotNullOrEmpty()] + [uri] $Homepage, + + # The visibility of the repository. + [Parameter()] + [ValidateSet('public', 'private')] + [string] $Visibility = 'public', + + # Whether issues are enabled. + [Parameter()] + [Alias('has_issues')] + [switch] $HasIssues, + + # Whether projects are enabled. + [Parameter()] + [Alias('has_projects')] + [switch] $HasProjects, + + # Whether the wiki is enabled. + [Parameter()] + [Alias('has_wiki')] + [switch] $HasWiki, + + # Whether discussions are enabled. + [Parameter()] + [Alias('has_discussions')] + [switch] $HasDiscussions, + + # Whether downloads are enabled. + [Parameter()] + [Alias('has_downloads')] + [switch] $HasDownloads, + + # Whether this repository acts as a template that can be used to generate new repositories. + [Parameter()] + [Alias('is_template')] + [switch] $IsTemplate, + + # The id of the team that will be granted access to this repository. This is only valid when creating a repository in an organization. + [Parameter()] + [Alias('team_id')] + [int] $TeamId, + + # Pass true to create an initial commit with empty README. + [Parameter()] + [Alias('auto_init')] + [switch] $AutoInit, + + # Whether to allow squash merges for pull requests. + [Parameter()] + [Alias('allow_squash_merge')] + [switch] $AllowSquashMerge, + + # Whether to allow merge commits for pull requests. + [Parameter()] + [Alias('allow_merge_commit')] + [switch] $AllowMergeCommit, + + # Whether to allow rebase merges for pull requests. + [Parameter()] + [Alias('allow_rebase_merge')] + [switch] $AllowRebaseMerge, + + # Whether to allow Auto-merge to be used on pull requests. + [Parameter()] + [Alias('allow_auto_merge')] + [switch] $AllowAutoMerge, + + # Whether to delete head branches when pull requests are merged + [Parameter()] + [Alias('delete_branch_on_merge')] + [switch] $DeleteBranchOnMerge, + + # The default value for a squash merge commit title: + # - PR_TITLE - default to the pull request's title. + # - COMMIT_OR_PR_TITLE - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + [Parameter()] + [ValidateSet('PR_TITLE', 'COMMIT_OR_PR_TITLE')] + [Alias('squash_merge_commit_title')] + [string] $SquashMergeCommitTitle, + + # The default value for a squash merge commit message: + # - PR_BODY - default to the pull request's body. + # - COMMIT_MESSAGES - default to the branch's commit messages. + # - BLANK - default to a blank commit message. + [Parameter()] + [ValidateSet('PR_BODY', 'COMMIT_MESSAGES', 'BLANK')] + [Alias('squash_merge_commit_message')] + [string] $SquashMergeCommitMessage, + + # The default value for a merge commit title. + # - PR_TITLE - default to the pull request's title. + # - MERGE_MESSAGE - default to the classic title for a merge message (e.g.,Merge pull request #123 from branch-name). + [Parameter()] + [ValidateSet('PR_TITLE', 'MERGE_MESSAGE')] + [Alias('merge_commit_title')] + [string] $MergeCommitTitle, + + # The default value for a merge commit message. + # - PR_BODY - default to the pull request's body. + # - PR_TITLE - default to the pull request's title. + # - BLANK - default to a blank commit message. + [Parameter()] + [ValidateSet('PR_BODY', 'PR_TITLE', 'BLANK')] + [Alias('merge_commit_message')] + [string] $MergeCommitMessage + ) + + DynamicParam { + $DynamicParamDictionary = New-DynamicParamDictionary + + $dynParam = @{ + Name = 'GitignoreTemplate' + Alias = 'gitignore_template' + Type = [string] + ValidateSet = Get-GitHubGitignoreList + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam + + $dynParam2 = @{ + Name = 'LicenseTemplate' + Alias = 'license_template' + Type = [string] + ValidateSet = Get-GitHubLicenseList | Select-Object -ExpandProperty key + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam2 + + return $DynamicParamDictionary + } + + begin { + $GitignoreTemplate = $PSBoundParameters['GitignoreTemplate'] + $LicenseTemplate = $PSBoundParameters['LicenseTemplate'] + } + + Process { + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'visibility' -RemoveTypes 'SwitchParameter' + + $body['private'] = $Visibility -eq 'private' + $body['has_issues'] = $HasIssues.IsPresent ? $HasIssues : $false + $body['has_wiki'] = $HasWiki.IsPresent ? $HasWiki : $false + $body['has_projects'] = $HasProjects.IsPresent ? $HasProjects : $false + $body['has_downloads'] = $HasDownloads.IsPresent ? $HasDownloads : $false + $body['is_template'] = $IsTemplate.IsPresent ? $IsTemplate : $false + $body['auto_init'] = $AutoInit.IsPresent ? $AutoInit : $false + $body['allow_squash_merge'] = $AllowSquashMerge.IsPresent ? $AllowSquashMerge : $false + $body['allow_merge_commit'] = $AllowMergeCommit.IsPresent ? $AllowMergeCommit : $false + $body['allow_rebase_merge'] = $AllowRebaseMerge.IsPresent ? $AllowRebaseMerge : $false + $body['allow_auto_merge'] = $AllowAutoMerge.IsPresent ? $AllowAutoMerge : $false + $body['delete_branch_on_merge'] = $DeleteBranchOnMerge.IsPresent ? $DeleteBranchOnMerge : $false + + Remove-HashtableEntry -Hashtable $body -NullOrEmptyValues + + $inputObject = @{ + APIEndpoint = '/user/repos' + Method = 'POST' + Body = $body + } + + if ($PSCmdlet.ShouldProcess('Repository for user', 'Create')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } + } +} diff --git a/src/GitHub/private/Users/Blocking/Get-GitHubBlockedUserByUser.ps1 b/src/GitHub/private/Users/Blocking/Get-GitHubBlockedUserByUser.ps1 index e11fb208e..6cbae2096 100644 --- a/src/GitHub/private/Users/Blocking/Get-GitHubBlockedUserByUser.ps1 +++ b/src/GitHub/private/Users/Blocking/Get-GitHubBlockedUserByUser.ps1 @@ -19,17 +19,20 @@ param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/blocks" + APIEndpoint = '/user/blocks' Method = 'GET' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Blocking/Test-GitHubBlockedUserByUser.ps1 b/src/GitHub/private/Users/Blocking/Test-GitHubBlockedUserByUser.ps1 index 843905aab..5b7525e35 100644 --- a/src/GitHub/private/Users/Blocking/Test-GitHubBlockedUserByUser.ps1 +++ b/src/GitHub/private/Users/Blocking/Test-GitHubBlockedUserByUser.ps1 @@ -4,7 +4,9 @@ Check if a user is blocked by the authenticated user .DESCRIPTION - Returns a 204 if the given user is blocked by the authenticated user. Returns a 404 if the given user is not blocked by the authenticated user, or if the given user account has been identified as spam by GitHub. + Returns a 204 if the given user is blocked by the authenticated user. + Returns a 404 if the given user is not blocked by the authenticated user, + or if the given user account has been identified as spam by GitHub. .EXAMPLE Test-GitHubBlockedUserByUser -Username 'octocat' @@ -29,6 +31,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/private/Users/Emails/Get-GitHubUserAllEmail.ps1 b/src/GitHub/private/Users/Emails/Get-GitHubUserAllEmail.ps1 index 5ef211eba..fe6b37397 100644 --- a/src/GitHub/private/Users/Emails/Get-GitHubUserAllEmail.ps1 +++ b/src/GitHub/private/Users/Emails/Get-GitHubUserAllEmail.ps1 @@ -4,7 +4,8 @@ List email addresses for the authenticated user .DESCRIPTION - Lists all of your email addresses, and specifies which one is visible to the public. This endpoint is accessible with the `user:email` scope. + Lists all of your email addresses, and specifies which one is visible to the public. + This endpoint is accessible with the `user:email` scope. .EXAMPLE Get-GitHubUserAllEmail @@ -20,17 +21,20 @@ param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/emails" + APIEndpoint = '/user/emails' Method = 'GET' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Emails/Get-GitHubUserPublicEmail.ps1 b/src/GitHub/private/Users/Emails/Get-GitHubUserPublicEmail.ps1 index c264d5d83..fe3cd4d52 100644 --- a/src/GitHub/private/Users/Emails/Get-GitHubUserPublicEmail.ps1 +++ b/src/GitHub/private/Users/Emails/Get-GitHubUserPublicEmail.ps1 @@ -4,7 +4,9 @@ List public email addresses for the authenticated user .DESCRIPTION - Lists your publicly visible email address, which you can set with the [Set primary email visibility for the authenticated user](https://docs.github.com/rest/users/emails#set-primary-email-visibility-for-the-authenticated-user) endpoint. This endpoint is accessible with the `user:email` scope. + Lists your publicly visible email address, which you can set with the + [Set primary email visibility for the authenticated user](https://docs.github.com/rest/users/emails#set-primary-email-visibility-for-the-authenticated-user) + endpoint. This endpoint is accessible with the `user:email` scope. .EXAMPLE Get-GitHubUserPublicEmail @@ -16,21 +18,25 @@ #> [OutputType([pscustomobject])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Link to documentation.')] [CmdletBinding()] param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/public_emails" + APIEndpoint = '/user/public_emails' Method = 'GET' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Followers/Get-GitHubUserFollowersOfUser.ps1 b/src/GitHub/private/Users/Followers/Get-GitHubUserFollowersOfUser.ps1 index 7d6f50800..9c7af7cec 100644 --- a/src/GitHub/private/Users/Followers/Get-GitHubUserFollowersOfUser.ps1 +++ b/src/GitHub/private/Users/Followers/Get-GitHubUserFollowersOfUser.ps1 @@ -29,11 +29,12 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'username' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'username' $inputObject = @{ APIEndpoint = "/users/$Username/followers" @@ -41,6 +42,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Followers/Get-GitHubUserFollowingMe.ps1 b/src/GitHub/private/Users/Followers/Get-GitHubUserFollowingMe.ps1 index 0e250bfbf..7f60cde66 100644 --- a/src/GitHub/private/Users/Followers/Get-GitHubUserFollowingMe.ps1 +++ b/src/GitHub/private/Users/Followers/Get-GitHubUserFollowingMe.ps1 @@ -20,6 +20,7 @@ param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -31,6 +32,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Followers/Get-GitHubUserFollowingUser.ps1 b/src/GitHub/private/Users/Followers/Get-GitHubUserFollowingUser.ps1 index e73873a1a..a6a75fadc 100644 --- a/src/GitHub/private/Users/Followers/Get-GitHubUserFollowingUser.ps1 +++ b/src/GitHub/private/Users/Followers/Get-GitHubUserFollowingUser.ps1 @@ -29,11 +29,12 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'username' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'username' $inputObject = @{ APIEndpoint = "/users/$Username/following" @@ -41,6 +42,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Followers/Get-GitHubUserMyFollowers.ps1 b/src/GitHub/private/Users/Followers/Get-GitHubUserMyFollowers.ps1 index 0d100888c..8948c5e35 100644 --- a/src/GitHub/private/Users/Followers/Get-GitHubUserMyFollowers.ps1 +++ b/src/GitHub/private/Users/Followers/Get-GitHubUserMyFollowers.ps1 @@ -16,10 +16,12 @@ #> [OutputType([pscustomobject])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Private function, not exposed to user.')] [CmdletBinding()] param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -31,6 +33,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserGpgKeyForUser.ps1 b/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserGpgKeyForUser.ps1 index 035b0f7c4..458232ac4 100644 --- a/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserGpgKeyForUser.ps1 +++ b/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserGpgKeyForUser.ps1 @@ -27,11 +27,12 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'username' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'username' $inputObject = @{ APIEndpoint = "/users/$Username/gpg_keys" @@ -39,6 +40,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserMyGpgKey.ps1 b/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserMyGpgKey.ps1 index bacfe48ff..55c9e6094 100644 --- a/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserMyGpgKey.ps1 +++ b/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserMyGpgKey.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION Lists the current user's GPG keys. - Requires that you are authenticated via Basic Auth or via OAuth with at least `read:gpg_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + Requires that you are authenticated via Basic Auth or via OAuth with at least `read:gpg_key` + [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). .EXAMPLE Get-GitHubUserMyGpgKey @@ -21,6 +22,7 @@ param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -32,6 +34,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserMyGpgKeyById.ps1 b/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserMyGpgKeyById.ps1 index 37970f68c..670d5eb22 100644 --- a/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserMyGpgKeyById.ps1 +++ b/src/GitHub/private/Users/GPG-Keys/Get-GitHubUserMyGpgKeyById.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION View extended details for a single GPG key. - Requires that you are authenticated via Basic Auth or via OAuth with at least `read:gpg_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + Requires that you are authenticated via Basic Auth or via OAuth with at least `read:gpg_key` + [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). .EXAMPLE Get-GitHubUserMyGpgKeyById -ID '1234567' @@ -32,6 +33,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Get-GitHubAllUser.ps1 b/src/GitHub/private/Users/Get-GitHubAllUser.ps1 index a996a830e..5e86f7a4d 100644 --- a/src/GitHub/private/Users/Get-GitHubAllUser.ps1 +++ b/src/GitHub/private/Users/Get-GitHubAllUser.ps1 @@ -6,7 +6,9 @@ .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. + 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-GitHubAllUser -Since 17722253 @@ -25,17 +27,20 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/users" + APIEndpoint = '/users' Method = 'GET' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Get-GitHubMyUser.ps1 b/src/GitHub/private/Users/Get-GitHubMyUser.ps1 index 3bec059c4..88490d3b0 100644 --- a/src/GitHub/private/Users/Get-GitHubMyUser.ps1 +++ b/src/GitHub/private/Users/Get-GitHubMyUser.ps1 @@ -4,8 +4,10 @@ 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. + 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-GitHubMyUser @@ -25,6 +27,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Get-GitHubUserByName.ps1 b/src/GitHub/private/Users/Get-GitHubUserByName.ps1 index c4f008817..d60ca0d61 100644 --- a/src/GitHub/private/Users/Get-GitHubUserByName.ps1 +++ b/src/GitHub/private/Users/Get-GitHubUserByName.ps1 @@ -5,9 +5,17 @@ .DESCRIPTION Provides publicly available information about someone with a GitHub account. - GitHub Apps with the `Plan` user permission can use this endpoint to retrieve information about a user's GitHub plan. The GitHub App must be authenticated as a user. See "[Identifying and authorizing users for GitHub Apps](https://docs.github.com/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps/)" for details about authentication. For an example response, see 'Response with GitHub plan information' below" - The `email` key in the following response is the publicly visible email address from your GitHub [profile page](https://github.com/settings/profile). When setting up your profile, you can select a primary email address to be ΓÇ£publicΓÇ¥ which provides an email entry for this endpoint. If you do not set a public email address for `email`, then it will have a value of `null`. You only see publicly visible email addresses when authenticated with GitHub. For more information, see [Authentication](https://docs.github.com/rest/overview/resources-in-the-rest-api#authentication). - The Emails API enables you to list all of your email addresses, and toggle a primary email to be visible publicly. For more information, see "[Emails API](https://docs.github.com/rest/users/emails)". + GitHub Apps with the `Plan` user permission can use this endpoint to retrieve information about a user's GitHub plan. + The GitHub App must be authenticated as a user. See + "[Identifying and authorizing users for GitHub Apps](https://docs.github.com/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps/)" + for details about authentication. For an example response, see 'Response with GitHub plan information' below" + The `email` key in the following response is the publicly visible email address from your GitHub + [profile page](https://github.com/settings/profile). When setting up your profile, you can select a primary email + address to be ΓÇ£publicΓÇ¥ which provides an email entry for this endpoint. If you do not set a public email address for `email`, + then it will have a value of `null`. You only see publicly visible email addresses when authenticated with GitHub. + For more information, see [Authentication](https://docs.github.com/rest/overview/resources-in-the-rest-api#authentication). + The Emails API enables you to list all of your email addresses, and toggle a primary email to be visible publicly. + For more information, see "[Emails API](https://docs.github.com/rest/users/emails)". .EXAMPLE Get-GitHubUserByName -Username 'octocat' @@ -18,6 +26,7 @@ https://docs.github.com/rest/users/users#get-a-user #> [OutputType([pscustomobject])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] [CmdletBinding()] param ( # The handle for the GitHub user account. @@ -35,6 +44,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Keys/Get-GitHubUserKeyForUser.ps1 b/src/GitHub/private/Users/Keys/Get-GitHubUserKeyForUser.ps1 index feb8a8e31..9f035a1e3 100644 --- a/src/GitHub/private/Users/Keys/Get-GitHubUserKeyForUser.ps1 +++ b/src/GitHub/private/Users/Keys/Get-GitHubUserKeyForUser.ps1 @@ -27,11 +27,12 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'username' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'username' $inputObject = @{ APIEndpoint = "/users/$Username/keys" @@ -39,6 +40,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Keys/Get-GitHubUserMyKey.ps1 b/src/GitHub/private/Users/Keys/Get-GitHubUserMyKey.ps1 index cef244f18..3ab88f46c 100644 --- a/src/GitHub/private/Users/Keys/Get-GitHubUserMyKey.ps1 +++ b/src/GitHub/private/Users/Keys/Get-GitHubUserMyKey.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION Lists the public SSH keys for the authenticated user's GitHub account. - Requires that you are authenticated via Basic Auth or via OAuth with at least `read:public_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + Requires that you are authenticated via Basic Auth or via OAuth with at least `read:public_key` + [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). .EXAMPLE Get-GitHubUserMyKey @@ -21,6 +22,7 @@ param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -32,6 +34,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Keys/Get-GitHubUserMyKeyById.ps1 b/src/GitHub/private/Users/Keys/Get-GitHubUserMyKeyById.ps1 index a3728756f..6db617b4f 100644 --- a/src/GitHub/private/Users/Keys/Get-GitHubUserMyKeyById.ps1 +++ b/src/GitHub/private/Users/Keys/Get-GitHubUserMyKeyById.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION View extended details for a single public SSH key. - Requires that you are authenticated via Basic Auth or via OAuth with at least `read:public_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + Requires that you are authenticated via Basic Auth or via OAuth with at least `read:public_key` + [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). .EXAMPLE Get-GitHubUserMyKeyById -ID '1234567' @@ -32,6 +33,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserMySigningKey.ps1 b/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserMySigningKey.ps1 index ad6f7f7bf..2573b3424 100644 --- a/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserMySigningKey.ps1 +++ b/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserMySigningKey.ps1 @@ -4,8 +4,9 @@ List SSH signing keys for the authenticated user .DESCRIPTION - Lists the SSH signing keys for the authenticated user's GitHub account. - You must authenticate with Basic Authentication, or you must authenticate with OAuth with at least `read:ssh_signing_key` scope. For more information, see "[Understanding scopes for OAuth apps](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)." + Lists the SSH signing keys for the authenticated user's GitHub account. You must authenticate with + Basic Authentication, or you must authenticate with OAuth with at least `read:ssh_signing_key` scope. For more information, see + "[Understanding scopes for OAuth apps](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)." .EXAMPLE Get-GitHubUserMySigningKey @@ -21,6 +22,7 @@ param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -32,6 +34,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserMySigningKeyById.ps1 b/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserMySigningKeyById.ps1 index 677d197de..5620df3ed 100644 --- a/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserMySigningKeyById.ps1 +++ b/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserMySigningKeyById.ps1 @@ -5,7 +5,9 @@ .DESCRIPTION Gets extended details for an SSH signing key. - You must authenticate with Basic Authentication, or you must authenticate with OAuth with at least `read:ssh_signing_key` scope. For more information, see "[Understanding scopes for OAuth apps](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)." + You must authenticate with Basic Authentication, or you must authenticate with OAuth with at least `read:ssh_signing_key` scope. + For more information, see + "[Understanding scopes for OAuth apps](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)." .EXAMPLE Get-GitHubUserMySigningKeyById -ID '1234567' @@ -32,6 +34,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserSigningKeyForUser.ps1 b/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserSigningKeyForUser.ps1 index 78aa25598..87f0590f0 100644 --- a/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserSigningKeyForUser.ps1 +++ b/src/GitHub/private/Users/SSH-Signing-Keys/Get-GitHubUserSigningKeyForUser.ps1 @@ -27,11 +27,12 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'username' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'username' $inputObject = @{ APIEndpoint = "/users/$Username/ssh_signing_keys" @@ -39,6 +40,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Social-Accounts/Get-GitHubMyUserSocials.ps1 b/src/GitHub/private/Users/Social-Accounts/Get-GitHubMyUserSocials.ps1 index fde1e83c2..569e706f0 100644 --- a/src/GitHub/private/Users/Social-Accounts/Get-GitHubMyUserSocials.ps1 +++ b/src/GitHub/private/Users/Social-Accounts/Get-GitHubMyUserSocials.ps1 @@ -15,10 +15,12 @@ https://docs.github.com/rest/users/social-accounts#list-social-accounts-for-the-authenticated-user #> [OutputType([pscustomobject])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = 'Private function, not exposed to user.')] [CmdletBinding()] param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -30,6 +32,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Users/Social-Accounts/Get-GitHubUserSocialsByName.ps1 b/src/GitHub/private/Users/Social-Accounts/Get-GitHubUserSocialsByName.ps1 index aea79703d..12e0c421c 100644 --- a/src/GitHub/private/Users/Social-Accounts/Get-GitHubUserSocialsByName.ps1 +++ b/src/GitHub/private/Users/Social-Accounts/Get-GitHubUserSocialsByName.ps1 @@ -32,6 +32,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/private/Utilities/Casing/Convert-StringCasingStyle.ps1 b/src/GitHub/private/Utilities/Casing/Convert-StringCasingStyle.ps1 index 780ebbe75..25a659f77 100644 --- a/src/GitHub/private/Utilities/Casing/Convert-StringCasingStyle.ps1 +++ b/src/GitHub/private/Utilities/Casing/Convert-StringCasingStyle.ps1 @@ -62,7 +62,9 @@ 'kebab-case' { ($words -join '-').ToLower() } 'snake_case' { ($words -join '_').ToLower() } 'PascalCase' { ($words | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1).ToLower() }) -join '' } - 'camelCase' { $words[0].toLower() + (($words | Select-Object -Skip 1 | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1) }) -join '') } + 'camelCase' { + $words[0].toLower() + (($words | Select-Object -Skip 1 | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1) }) -join '') + } 'UPPER_SNAKE_CASE' { ($words -join '_').toUpper() } 'UPPER-KEBAB-CASE' { ($words -join '-').toUpper() } } diff --git a/src/GitHub/private/Utilities/DynamicParam/New-DynamicParam.ps1 b/src/GitHub/private/Utilities/DynamicParam/New-DynamicParam.ps1 new file mode 100644 index 000000000..2ce8a706b --- /dev/null +++ b/src/GitHub/private/Utilities/DynamicParam/New-DynamicParam.ps1 @@ -0,0 +1,200 @@ +function New-DynamicParam { + <# + .SYNOPSIS + Creates a new dynamic parameter for a function. + + .DESCRIPTION + Creates a new dynamic parameter for a function. + + .EXAMPLE + An example + + .NOTES + https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters?view=powershell-7.3#psdefaultvalue-attribute-arguments + + #Default Value + # https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_functions_advanced_parameters?view=powershell-7.3#psdefaultvalue-attribute-arguments + # https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.runtimedefinedparameter.value?view=powershellsdk-7.3.0 + #> + [OutputType([void])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Long links')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Function does not change state.')] + [CmdletBinding()] + param( + # Specifies the name of the parameter. + [Parameter(Mandatory)] + [string] $Name, + + # Specifies the aliases of the parameter. + [Parameter()] + [string[]] $Alias, + + # Specifies the data type of the parameter. + [Parameter()] + [type] $Type, + + # Specifies the parameter set name. + [Parameter()] + [string] $ParameterSetName = '__AllParameterSets', + + # Specifies if the parameter is mandatory. + # Parameter Set specific + [Parameter()] + [switch] $Mandatory, + + # Specifies the parameters positional binding. + # Parameter Set specific + [Parameter()] + [int] $Position, + + # Specifies if the parameter accepts values from the pipeline. + # Parameter Set specific + [Parameter()] + [switch] $ValueFromPipeline, + + # Specifies if the parameter accepts values from the pipeline by property name. + # Parameter Set specific + [Parameter()] + [switch] $ValueFromPipelineByPropertyName, + + # Specifies if the parameter accepts values from the remaining command line arguments that are not associated with another parameter. + # Parameter Set specific + [Parameter()] + [switch] $ValueFromRemainingArguments, + + # Specifies the help message of the parameter. + # Parameter Set specific + [Parameter()] + [string] $HelpMessage, + + # Specifies the comments of the parameter. + [Parameter()] + [string] $Comment, + + # Specifies the validate script of the parameter. + [Parameter()] + [scriptblock] $ValidateScript, + + # Specifies the validate regex pattern of the parameter. + [Parameter()] + [regex] $ValidatePattern, + + # Specifies the validate number of items for the parameter. + [Parameter()] + [ValidateCount(2, 2)] + [int[]] $ValidateCount, + + # Specifies the validate range of the parameter. + [Parameter()] + [object] $ValidateRange, + + # Specifies the validate set of the parameter. + [Parameter()] + [object] $ValidateSet, + + # Specifies the validate length of the parameter. + [Parameter()] + [ValidateCount(2, 2)] + [int[]] $ValidateLength, + + # Specifies if the parameter accepts null or empty values. + [Parameter()] + [switch] $ValidateNotNullOrEmpty, + + # Specifies if the parameter accepts wildcards. + [Parameter()] + [switch] $SupportsWildcards, + + # Specifies if the parameter accepts empty strings. + [Parameter()] + [switch] $AllowEmptyString, + + # Specifies if the parameter accepts null values. + [Parameter()] + [switch] $AllowNull, + + # Specifies if the parameter accepts empty collections. + [Parameter()] + [switch] $AllowEmptyCollection, + + # Specifies the dynamic parameter dictionary. + [Parameter()] + [System.Management.Automation.RuntimeDefinedParameterDictionary] $DynamicParamDictionary + ) + + $attributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + + # foreach ParameterSet in ParameterSets , Key = name, Value = Hashtable + $parameterAttribute = [System.Management.Automation.ParameterAttribute]::new() + + $parameterAttribute.ParameterSetName = $ParameterSetName + if ($PSBoundParameters.ContainsKey('HelpMessage')) { + $parameterAttribute.HelpMessage = $HelpMessage + } + if ($PSBoundParameters.ContainsKey('Position')) { + $parameterAttribute.Position = $Position + } + $parameterAttribute.Mandatory = $Mandatory + $parameterAttribute.ValueFromPipeline = $ValueFromPipeline + $parameterAttribute.ValueFromPipelineByPropertyName = $ValueFromPipelineByPropertyName + $parameterAttribute.ValueFromRemainingArguments = $ValueFromRemainingArguments + $attributeCollection.Add($parameterAttribute) + + if ($PSBoundParameters.ContainsKey('Alias')) { + $Alias | ForEach-Object { + $aliasAttribute = New-Object System.Management.Automation.AliasAttribute($_) + $attributeCollection.Add($aliasAttribute) + } + } + + # $Comment + + if ($PSBoundParameters.ContainsKey('ValidateSet')) { + $validateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute($ValidateSet) + $attributeCollection.Add($validateSetAttribute) + } + if ($PSBoundParameters.ContainsKey('ValidateNotNullOrEmpty')) { + $validateSetAttribute = New-Object System.Management.Automation.ValidateNotNullOrEmptyAttribute + $attributeCollection.Add($validateSetAttribute) + } + if ($PSBoundParameters.ContainsKey('ValidateLength')) { + $validateLengthAttribute = New-Object System.Management.Automation.ValidateLengthAttribute($ValidateLength[0], $ValidateLength[1]) + $attributeCollection.Add($validateLengthAttribute) + } + if ($PSBoundParameters.ContainsKey('ValidateCount')) { + $validateCountAttribute = New-Object System.Management.Automation.ValidateCountAttribute($ValidateCount[0], $ValidateCount[1]) + $attributeCollection.Add($validateCountAttribute) + } + if ($PSBoundParameters.ContainsKey('ValidateScript')) { + $validateScriptAttribute = New-Object System.Management.Automation.ValidateScriptAttribute($ValidateScript) + $attributeCollection.Add($validateScriptAttribute) + } + if ($PSBoundParameters.ContainsKey('ValidatePattern')) { + $validatePatternAttribute = New-Object System.Management.Automation.ValidatePatternAttribute($ValidatePattern) + $attributeCollection.Add($validatePatternAttribute) + } + if ($PSBoundParameters.ContainsKey('ValidateRange')) { + $validateRangeAttribute = New-Object System.Management.Automation.ValidateRangeAttribute($ValidateRange) + $attributeCollection.Add($validateRangeAttribute) + } + if ($PSBoundParameters.ContainsKey('SupportsWildcards')) { + $supportsWildcardsAttribute = New-Object System.Management.Automation.SupportsWildcardsAttribute + $attributeCollection.Add($supportsWildcardsAttribute) + } + if ($PSBoundParameters.ContainsKey('AllowEmptyString')) { + $allowEmptyStringAttribute = New-Object System.Management.Automation.AllowEmptyStringAttribute + $attributeCollection.Add($allowEmptyStringAttribute) + } + if ($PSBoundParameters.ContainsKey('AllowNull')) { + $allowNullAttribute = New-Object System.Management.Automation.AllowNullAttribute + $attributeCollection.Add($allowNullAttribute) + } + if ($PSBoundParameters.ContainsKey('AllowEmptyCollection')) { + $allowEmptyCollectionAttribute = New-Object System.Management.Automation.AllowEmptyCollectionAttribute + $attributeCollection.Add($allowEmptyCollectionAttribute) + } + + $runtimeDefinedParameter = New-Object System.Management.Automation.RuntimeDefinedParameter($Name, $Type, $attributeCollection) + $DynamicParamDictionary.Add($Name, $runtimeDefinedParameter) + +} diff --git a/src/GitHub/private/Utilities/DynamicParam/New-DynamicParamDictionary.ps1 b/src/GitHub/private/Utilities/DynamicParam/New-DynamicParamDictionary.ps1 new file mode 100644 index 000000000..78d11e2b5 --- /dev/null +++ b/src/GitHub/private/Utilities/DynamicParam/New-DynamicParamDictionary.ps1 @@ -0,0 +1,23 @@ +function New-DynamicParamDictionary { + <# + .SYNOPSIS + Creates a new RuntimeDefinedParameterDictionary + + .DESCRIPTION + Creates a new RuntimeDefinedParameterDictionary + + .EXAMPLE + New-DynamicParamDictionary + + Returns a new RuntimeDefinedParameterDictionary + #> + [OutputType([System.Management.Automation.RuntimeDefinedParameterDictionary])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', '', + Justification = 'Function does not change state.' + )] + [CmdletBinding()] + param() + + return [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() +} diff --git a/src/GitHub/private/Utilities/Hashtable/ConvertFrom-HashTable.ps1 b/src/GitHub/private/Utilities/Hashtable/ConvertFrom-HashTable.ps1 index 1db300f69..df8f4052b 100644 --- a/src/GitHub/private/Utilities/Hashtable/ConvertFrom-HashTable.ps1 +++ b/src/GitHub/private/Utilities/Hashtable/ConvertFrom-HashTable.ps1 @@ -38,7 +38,8 @@ Mandatory, ValueFromPipeline )] - [object]$InputObject + [AllowNull()] + [object] $InputObject ) $InputObject | ConvertTo-Json -Depth 100 | ConvertFrom-Json } diff --git a/src/GitHub/private/Utilities/Hashtable/Join-Object.ps1 b/src/GitHub/private/Utilities/Hashtable/Join-Object.ps1 index 9f4bb4355..7f93a32a6 100644 --- a/src/GitHub/private/Utilities/Hashtable/Join-Object.ps1 +++ b/src/GitHub/private/Utilities/Hashtable/Join-Object.ps1 @@ -4,7 +4,9 @@ Merges two or more objects into a single object .DESCRIPTION - Merges two or more objects into a single object. The first object is the main object, and the remaining objects are overrides. The overrides are applied in order, so the last object in the list will override any previous values. + Merges two or more objects into a single object. + The first object is the main object, and the remaining objects are overrides. + The overrides are applied in order, so the last object in the list will override any previous values. .EXAMPLE $main = [pscustomobject]@{a = 1; b = 2; c = 3} @@ -16,7 +18,8 @@ - - - - - 7 8 3 6 9 - Merges the three objects into a single object. The values from the last object override the values from the previous objects. + Merges the three objects into a single object. + The values from the last object override the values from the previous objects. .EXAMPLE $main = @{a = 1;b = 2} @@ -29,7 +32,8 @@ b 2 c 4 - Merges the two hashtables into a single hashtable. The values from the last hashtable override the values from the previous hashtables. + Merges the two hashtables into a single hashtable. + The values from the last hashtable override the values from the previous hashtables. Using the alias 'Merge-Object' instead of 'Join-Object'. .EXAMPLE diff --git a/src/GitHub/private/Utilities/Hashtable/Remove-HashTableEntries.ps1 b/src/GitHub/private/Utilities/Hashtable/Remove-HashtableEntry.ps1 similarity index 65% rename from src/GitHub/private/Utilities/Hashtable/Remove-HashTableEntries.ps1 rename to src/GitHub/private/Utilities/Hashtable/Remove-HashtableEntry.ps1 index 110bb3ed0..b35c7f79f 100644 --- a/src/GitHub/private/Utilities/Hashtable/Remove-HashTableEntries.ps1 +++ b/src/GitHub/private/Utilities/Hashtable/Remove-HashtableEntry.ps1 @@ -1,32 +1,62 @@ -filter Remove-HashtableEntries { +filter Remove-HashtableEntry { + <# + .SYNOPSIS + Remove entries from a hashtable. + + .DESCRIPTION + Remove different types of entries from a hashtable. + + .EXAMPLE + $Hashtable = @{ + 'Key1' = 'Value1' + 'Key2' = 'Value2' + 'Key3' = $null + 'Key4' = 'Value4' + 'Key5' = '' + } + $Hashtable | Remove-HashtableEntry -NullOrEmptyValues + + Remove keys with null or empty values + #> [OutputType([void])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', + '', + Justification = 'Function does not change state.' + )] [CmdletBinding()] param ( + # The hashtable to remove entries from. [Parameter( Mandatory, ValueFromPipeline )] [hashtable] $Hashtable, + # Remove keys with null or empty values. [Parameter()] [switch] $NullOrEmptyValues, + # Remove keys of type. [Parameter()] [string[]] $RemoveTypes, + # Remove keys with a given name. [Parameter()] [string[]] $RemoveNames, + # Remove keys NOT of type. [Parameter()] [string[]] $KeepTypes, + # Remove keys NOT with a given name. [Parameter()] [string[]] $KeepNames - ) + if ($NullOrEmptyValues) { Write-Verbose 'Remove keys with null or empty values' - ($Hashtable.GetEnumerator() | Where-Object { -not $_.Value }) | ForEach-Object { + ($Hashtable.GetEnumerator() | Where-Object { [string]::IsNullOrEmpty($_.Value) }) | ForEach-Object { Write-Verbose " - [$($_.Name)] - Value: [$($_.Value)] - Remove" $Hashtable.Remove($_.Name) } diff --git a/src/GitHub/private/Utilities/Web/ConvertTo-QueryString.ps1 b/src/GitHub/private/Utilities/Web/ConvertTo-QueryString.ps1 index fed644eef..6fce4ecba 100644 --- a/src/GitHub/private/Utilities/Web/ConvertTo-QueryString.ps1 +++ b/src/GitHub/private/Utilities/Web/ConvertTo-QueryString.ps1 @@ -39,9 +39,13 @@ } $parameters = if ($AsURLEncoded) { - ($InputObject.GetEnumerator() | ForEach-Object { "$([System.Web.HttpUtility]::UrlEncode($_.Key))=$([System.Web.HttpUtility]::UrlEncode($_.Value))" }) -join '&' + ($InputObject.GetEnumerator() | ForEach-Object { + "$([System.Web.HttpUtility]::UrlEncode($_.Key))=$([System.Web.HttpUtility]::UrlEncode($_.Value))" + }) -join '&' } else { - ($InputObject.GetEnumerator() | ForEach-Object { "$([System.Uri]::EscapeDataString($_.Key))=$([System.Uri]::EscapeDataString($_.Value))" }) -join '&' + ($InputObject.GetEnumerator() | ForEach-Object { + "$([System.Uri]::EscapeDataString($_.Key))=$([System.Uri]::EscapeDataString($_.Value))" + }) -join '&' } if ($parameters) { diff --git a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 index c37c5edf4..ff2c897fd 100644 --- a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 +++ b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 @@ -90,14 +90,12 @@ $AccessToken = (Get-GitHubConfig -Name AccessToken) } - $functionName = $MyInvocation.MyCommand.Name - $headers = @{ Accept = $Accept 'X-GitHub-Api-Version' = $Version } - Remove-HashTableEntries -Hashtable $headers -NullOrEmptyValues + Remove-HashtableEntry -Hashtable $headers -NullOrEmptyValues if (-not $URI) { $URI = ("$ApiBaseUri/" -replace '/$', '') + ("/$ApiEndpoint" -replace '^/', '') @@ -127,7 +125,6 @@ Authentication = 'Bearer' Token = $AccessToken ContentType = $ContentType - HttpVersion = $HttpVersion FollowRelLink = $FollowRelLink StatusCodeVariable = 'APICallStatusCode' ResponseHeadersVariable = 'APICallResponseHeaders' @@ -135,28 +132,69 @@ OutFile = $DownloadFilePath } - $APICall | Remove-HashTableEntries -NullOrEmptyValues + #If PSversion is higher than 7.1 use HttpVersion + if ($PSVersionTable.PSVersion -ge [version]'7.3') { + $APICall['HttpVersion'] = $HttpVersion + } + + $APICall | Remove-HashtableEntry -NullOrEmptyValues if ($Body) { # Use body to create the query string for certain situations if ($Method -eq 'GET') { $queryString = $Body | ConvertTo-QueryString $APICall.Uri = $APICall.Uri + $queryString - } elseif ($Body -is [string]) { # Use body to create the form data + } elseif ($Body -is [string]) { + # Use body to create the form data $APICall.Body = $Body } else { $APICall.Body = $Body | ConvertTo-Json -Depth 100 } } - Invoke-RestMethod @APICall | ForEach-Object { - $statusCode = $APICallStatusCode | ConvertTo-Json -Depth 100 | ConvertFrom-Json - $responseHeaders = $APICallResponseHeaders | ConvertTo-Json -Depth 100 | ConvertFrom-Json - [pscustomobject]@{ - Request = $APICall - Response = $_ - StatusCode = $statusCode - ResponseHeaders = $responseHeaders + try { + Invoke-RestMethod @APICall | ForEach-Object { + $statusCode = $APICallStatusCode | ConvertTo-Json -Depth 100 | ConvertFrom-Json + $responseHeaders = $APICallResponseHeaders | ConvertTo-Json -Depth 100 | ConvertFrom-Json + $verboseMessage = @" + +---------------------------------- +StatusCode: +$statusCode +---------------------------------- +Request: +$($APICall | ConvertFrom-HashTable | Format-List | Out-String) +---------------------------------- +ResponseHeaders: +$($responseHeaders.PSObject.Properties | Foreach-Object { $_ | Format-List | Out-String }) +---------------------------------- + +"@ + Write-Verbose $verboseMessage + [pscustomobject]@{ + Request = $APICall + Response = $_ + StatusCode = $statusCode + ResponseHeaders = $responseHeaders + } } + } catch { + $failure = $_ + $errorResult = @" + +----------------------------------`n`r +Request: +$($APICall | ConvertFrom-HashTable | Format-List | Out-String) +----------------------------------`n`r +Message: +$($failure.Exception.Message | ConvertFrom-HashTable | Format-List | Out-String) +----------------------------------`n`r +Response: +$($failure.Exception.Response | ConvertFrom-HashTable | Format-List | Out-String) +----------------------------------`n`r + +"@ + $errorResult.Split([System.Environment]::NewLine) | ForEach-Object { Write-Error $_ } + throw $failure.Exception.Message } } diff --git a/src/GitHub/public/Actions/Get-GitHubWorkflow.ps1 b/src/GitHub/public/Actions/Get-GitHubWorkflow.ps1 index 0be3d2b40..a568b78d8 100644 --- a/src/GitHub/public/Actions/Get-GitHubWorkflow.ps1 +++ b/src/GitHub/public/Actions/Get-GitHubWorkflow.ps1 @@ -29,13 +29,9 @@ [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), - [Parameter(ParameterSetName = 'ByName')] - [string] $Name, - - [Parameter(ParameterSetName = 'ByID')] - [string] $ID, - + # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -50,6 +46,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response.workflows + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response.workflows + } } diff --git a/src/GitHub/public/Actions/Get-GitHubWorkflowRun.ps1 b/src/GitHub/public/Actions/Get-GitHubWorkflowRun.ps1 index eaecf3997..882f58709 100644 --- a/src/GitHub/public/Actions/Get-GitHubWorkflowRun.ps1 +++ b/src/GitHub/public/Actions/Get-GitHubWorkflowRun.ps1 @@ -18,7 +18,9 @@ [Parameter(ParameterSetName = 'ByID')] [string] $ID, + # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -42,6 +44,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response.workflow_runs + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response.workflow_runs + } } diff --git a/src/GitHub/public/Actions/Get-GitHubWorkflowUsage.ps1 b/src/GitHub/public/Actions/Get-GitHubWorkflowUsage.ps1 index 2d541c094..ef0ca56fb 100644 --- a/src/GitHub/public/Actions/Get-GitHubWorkflowUsage.ps1 +++ b/src/GitHub/public/Actions/Get-GitHubWorkflowUsage.ps1 @@ -43,6 +43,8 @@ APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/timing" } - (Invoke-GitHubAPI @inputObject).Response.billable + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response.billable + } } diff --git a/src/GitHub/public/Actions/Remove-GitHubWorkflowRun.ps1 b/src/GitHub/public/Actions/Remove-GitHubWorkflowRun.ps1 index 88fd9d921..f833e225b 100644 --- a/src/GitHub/public/Actions/Remove-GitHubWorkflowRun.ps1 +++ b/src/GitHub/public/Actions/Remove-GitHubWorkflowRun.ps1 @@ -1,24 +1,49 @@ filter Remove-GitHubWorkflowRun { - [CmdletBinding()] + <# + .SYNOPSIS + Delete a workflow run + + .DESCRIPTION + Delete a specific workflow run. Anyone with write 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:write` permission to use + this endpoint. + + .EXAMPLE + Remove-GitHubWorkflowRun -Owner 'octocat' -Repo 'Hello-World' -ID 123456789 + + Deletes the workflow run with the ID 123456789 from the 'Hello-World' repository owned by 'octocat' + + .NOTES + https://docs.github.com/rest/actions/workflow-runs#delete-a-workflow-run + #> + [CmdletBinding(SupportsShouldProcess)] param ( + # The account owner of the repository. The name is not case sensitive. [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), + # The name of the repository without the .git extension. The name is not case sensitive. [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), + # The unique identifier of the workflow run. [Parameter( Mandatory, ValueFromPipelineByPropertyName )] - [string] $ID + [Alias('ID', 'run_id')] + [string] $RunID ) $inputObject = @{ - APIEndpoint = "repos/$Owner/$Repo/actions/runs/$ID" + APIEndpoint = "repos/$Owner/$Repo/actions/runs/$RunID" Method = 'DELETE' } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("workflow run with ID [$RunID] in [$Owner/$Repo]", 'Delete')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Actions/Start-GitHubWorkflow.ps1 b/src/GitHub/public/Actions/Start-GitHubWorkflow.ps1 index 1dc3a42a8..18099dfe6 100644 --- a/src/GitHub/public/Actions/Start-GitHubWorkflow.ps1 +++ b/src/GitHub/public/Actions/Start-GitHubWorkflow.ps1 @@ -18,14 +18,17 @@ # API Reference # https://docs.github.com/free-pro-team@latest/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( + # The account owner of the repository. The name is not case sensitive. [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), + # The name of the repository without the .git extension. The name is not case sensitive. [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), + # The ID of the workflow. [Alias('workflow_id')] [Parameter( Mandatory, @@ -33,12 +36,14 @@ )] [string] $ID, + # The reference of the workflow run. The reference can be a branch, tag, or a commit SHA. [Parameter( ValueFromPipelineByPropertyName )] [Alias('branch', 'tag')] [string] $Ref = 'main', + # Input parameters for the workflow run. You can use the inputs and payload keys to pass custom data to your workflow. [Parameter()] [hashtable] $Inputs = @{} ) @@ -54,6 +59,10 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("workflow with ID [$ID] in [$Owner/$Repo]", 'Start')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Actions/Start-GitHubWorkflowReRun.ps1 b/src/GitHub/public/Actions/Start-GitHubWorkflowReRun.ps1 index 3d4ae80b6..44015911b 100644 --- a/src/GitHub/public/Actions/Start-GitHubWorkflowReRun.ps1 +++ b/src/GitHub/public/Actions/Start-GitHubWorkflowReRun.ps1 @@ -1,34 +1,28 @@ filter Start-GitHubWorkflowReRun { <# .SYNOPSIS - Short description + Re-run a workflow .DESCRIPTION - Long description - - .PARAMETER Owner - Parameter description - - .PARAMETER Repo - Parameter description - - .PARAMETER ID - Parameter description + Re-runs your workflow run using its `run_id`. You can also specify a branch or tag name to re-run a workflow run from a branch .EXAMPLE - An example + Start-GitHubWorkflowReRun -Owner 'octocat' -Repo 'Hello-World' -ID 123456789 .NOTES https://docs.github.com/rest/reference/actions#re-run-a-workflow #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( + # The account owner of the repository. The name is not case sensitive. [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), + # The name of the repository without the .git extension. The name is not case sensitive. [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo), + # The unique identifier of the workflow run. [Alias('workflow_id')] [Parameter( Mandatory, @@ -42,6 +36,10 @@ APIEndpoint = "/repos/$Owner/$Repo/actions/runs/$ID/rerun" } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("workflow with ID [$ID] in [$Owner/$Repo]", 'Re-run')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Actions/Stop-GitHubWorkflowRun.ps1 b/src/GitHub/public/Actions/Stop-GitHubWorkflowRun.ps1 index 7b8eb8ecf..33df927fd 100644 --- a/src/GitHub/public/Actions/Stop-GitHubWorkflowRun.ps1 +++ b/src/GitHub/public/Actions/Stop-GitHubWorkflowRun.ps1 @@ -1,27 +1,20 @@ filter Stop-GitHubWorkflowRun { <# .SYNOPSIS - Short description + Cancel a workflow run .DESCRIPTION - Long description - - .PARAMETER Owner - Parameter description - - .PARAMETER Repo - Parameter description - - .PARAMETER ID - Parameter description + Cancels a workflow run using its `run_id`. You can use this endpoint to cancel a workflow run that is in progress or waiting .EXAMPLE - An example + Stop-GitHubWorkflowRun -Owner 'octocat' -Repo 'Hello-World' -ID 123456789 + + Cancels the workflow run with the ID 123456789 from the 'Hello-World' repository owned by 'octocat' .NOTES https://docs.github.com/rest/reference/actions#cancel-a-workflow-run #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] [alias('Cancel-GitHubWorkflowRun')] param ( [Parameter()] @@ -44,6 +37,10 @@ APIEndpoint = "/repos/$Owner/$Repo/actions/runs/$ID/cancel" } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("workflow run with ID [$ID] in [$Owner/$Repo]", 'Cancel/Stop')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 b/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 index 64b771674..dd1942c3f 100644 --- a/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 +++ b/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 @@ -41,6 +41,13 @@ [Alias('Login-GitHub')] [Alias('Login-GH')] [OutputType([void])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'AccessToken', Justification = 'Required for parameter set')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Is the CLI part of the module.')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSAvoidUsingConvertToSecureStringWithPlainText', + '', + Justification = 'The tokens are recieved as clear text. Mitigating exposure by removing variables and performing garbage collection.' + )] [CmdletBinding(DefaultParameterSetName = 'DeviceFlow')] param ( # Choose between authentication methods, either OAuthApp or GitHubApp. @@ -86,10 +93,14 @@ ) $envVars = Get-ChildItem -Path 'Env:' + Write-Verbose "Environment variables:" + Write-Verbose ($envVars | Format-Table -AutoSize | Out-String) $systemToken = $envVars | Where-Object Name -In 'GH_TOKEN', 'GITHUB_TOKEN' | Select-Object -First 1 + Write-Verbose "System token: [$systemToken]" $systemTokenPresent = $systemToken.count -gt 0 + Write-Verbose "System token present: [$systemTokenPresent]" $AuthType = $systemTokenPresent ? 'sPAT' : $PSCmdlet.ParameterSetName - + WRite-Verbose "AuthType: [$AuthType]" switch ($AuthType) { 'DeviceFlow' { Write-Verbose 'Logging in using device flow...' @@ -229,4 +240,9 @@ $repo = $systemRepo.Value.Split('/')[-1] Set-GitHubConfig -Repo $repo } + + Remove-Variable -Name tokenResponse -ErrorAction SilentlyContinue + Remove-Variable -Name settings -ErrorAction SilentlyContinue + [System.GC]::Collect() + } diff --git a/src/GitHub/public/Auth/Disconnect-GitHubAccount.ps1 b/src/GitHub/public/Auth/Disconnect-GitHubAccount.ps1 index 754786541..57afb45d7 100644 --- a/src/GitHub/public/Auth/Disconnect-GitHubAccount.ps1 +++ b/src/GitHub/public/Auth/Disconnect-GitHubAccount.ps1 @@ -23,6 +23,7 @@ [Alias('Logoff-GitHub')] [Alias('Logoff-GH')] [OutputType([void])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Is the CLI part of the module.')] [CmdletBinding()] param () diff --git a/src/GitHub/public/Branches/Get-GitHubRepoBranch.ps1 b/src/GitHub/public/Branches/Get-GitHubRepoBranch.ps1 index 7150c6dad..52b97d71a 100644 --- a/src/GitHub/public/Branches/Get-GitHubRepoBranch.ps1 +++ b/src/GitHub/public/Branches/Get-GitHubRepoBranch.ps1 @@ -1,9 +1,26 @@ filter Get-GitHubRepoBranch { + <# + .SYNOPSIS + List branches + + .DESCRIPTION + Lists all branches from a repository + + .EXAMPLE + Get-GitHubRepoBranch -Owner 'octocat' -Repo 'Hello-World' + + Gets all the branches from the 'Hello-World' repository owned by 'octocat' + + .NOTES + https://docs.github.com/rest/branches/branches#list-branches + #> [CmdletBinding()] param ( + # The account owner of the repository. The name is not case sensitive. [Parameter()] [string] $Owner = (Get-GitHubConfig -Name Owner), + # The name of the repository without the .git extension. The name is not case sensitive. [Parameter()] [string] $Repo = (Get-GitHubConfig -Name Repo) ) @@ -13,6 +30,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Config/Get-GitHubConfig.ps1 b/src/GitHub/public/Config/Get-GitHubConfig.ps1 index 76c0b5afe..ecb5394cc 100644 --- a/src/GitHub/public/Config/Get-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Get-GitHubConfig.ps1 @@ -38,11 +38,7 @@ $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-Object -Main $RefreshTokenData -Overrides $AccessTokenData -AsHashtable - - switch($Name) { + switch ($Name) { 'AccessToken' { Get-Secret -Name "$prefix`AccessToken" } @@ -50,6 +46,17 @@ Get-Secret -Name "$prefix`RefreshToken" } default { + $RefreshTokenSecretInfo = Get-SecretInfo -Name "$prefix`RefreshToken" + if ($null -ne $RefreshTokenSecretInfo.Metadata) { + $RefreshTokenMetadata = $RefreshTokenSecretInfo.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable + } + + $AccessTokenSecretInfo = Get-SecretInfo -Name "$prefix`AccessToken" + if ($null -ne $AccessTokenSecretInfo.Metadata) { + $AccessTokenMetadata = $AccessTokenSecretInfo.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable + } + $metadata = Join-Object -Main $RefreshTokenMetadata -Overrides $AccessTokenMetadata -AsHashtable + if ($Name) { $metadata.$Name } else { diff --git a/src/GitHub/public/Config/Set-GitHubConfig.ps1 b/src/GitHub/public/Config/Set-GitHubConfig.ps1 index 4f23a7b7a..ba389cd65 100644 --- a/src/GitHub/public/Config/Set-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Set-GitHubConfig.ps1 @@ -17,7 +17,7 @@ Sets a item called 'MyFavouriteRepo' in the GitHub configuration. #> [Alias('Set-GHConfig')] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # Set the access token type. [Parameter()] @@ -96,7 +96,7 @@ $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 + Remove-HashtableEntry -Hashtable $updateSecretMetadata -KeepTypes $keepTypes -RemoveNames $removeKeys Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" $newSecretMetadata = Join-Object -Main $newSecretMetadata -Overrides $updateSecretMetadata -AsHashtable @@ -109,7 +109,9 @@ Vault = $script:SecretVault.Name SecureStringSecret = $AccessToken } - Set-Secret @accessTokenSetParam + if ($PSCmdlet.ShouldProcess("secret [$secretName] in secret vault [$($script:SecretVault.Name)]", 'Set')) { + Set-Secret @accessTokenSetParam + } } if (Get-SecretInfo -Name $secretName) { @@ -118,7 +120,9 @@ Vault = $script:SecretVault.Name Metadata = $newSecretMetadata } - Set-SecretInfo @secretSetInfoParam + if ($PSCmdlet.ShouldProcess("secret [$secretName] in secret vault [$($script:SecretVault.Name)]", 'Set')) { + Set-SecretInfo @secretSetInfoParam + } } #endregion AccessToken @@ -143,7 +147,7 @@ $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 + Remove-HashtableEntry -Hashtable $updateSecretMetadata -KeepTypes $keepTypes -RemoveNames $removeKeys Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" $newSecretMetadata = Join-Object -Main $newSecretMetadata -Overrides $updateSecretMetadata -AsHashtable @@ -156,7 +160,9 @@ Vault = $script:SecretVault.Name SecureStringSecret = $RefreshToken } - Set-Secret @refreshTokenSetParam + if ($PSCmdlet.ShouldProcess("secret [$secretName] in secret vault [$($script:SecretVault.Name)]", 'Set')) { + Set-Secret @refreshTokenSetParam + } } if (Get-SecretInfo -Name $secretName) { @@ -165,7 +171,9 @@ Vault = $script:SecretVault.Name Metadata = $newSecretMetadata } - Set-SecretInfo @secretSetInfoParam + if ($PSCmdlet.ShouldProcess("secret [$secretName] in secret vault [$($script:SecretVault.Name)]", 'Set')) { + Set-SecretInfo @secretSetInfoParam + } } #endregion AccessToken } diff --git a/src/GitHub/public/Deployments/Get-GitHubEnvironment.ps1 b/src/GitHub/public/Deployments/Get-GitHubEnvironment.ps1 deleted file mode 100644 index 0cb07872f..000000000 --- a/src/GitHub/public/Deployments/Get-GitHubEnvironment.ps1 +++ /dev/null @@ -1,37 +0,0 @@ -filter 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/rest/reference/repos#get-all-environments - #> - [CmdletBinding()] - param ( - [Parameter()] - [string] $Owner = (Get-GitHubConfig -Name Owner), - - [Parameter()] - [string] $Repo = (Get-GitHubConfig -Name Repo) - ) - - $inputObject = @{ - APIEndpoint = "/repos/$Owner/$Repo/environments" - Method = 'GET' - } - - (Invoke-GitHubAPI @inputObject).Response - -} diff --git a/src/GitHub/public/Deployments/Get-GitHubEnvironmentSecrets.ps1 b/src/GitHub/public/Deployments/Get-GitHubEnvironmentSecrets.ps1 deleted file mode 100644 index 643eb7167..000000000 --- a/src/GitHub/public/Deployments/Get-GitHubEnvironmentSecrets.ps1 +++ /dev/null @@ -1,49 +0,0 @@ -filter 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/rest/reference/repos#get-all-environments - #> - [CmdletBinding()] - param ( - [Parameter()] - [string] $Owner = (Get-GitHubConfig -Name Owner), - - [Parameter()] - [string] $Repo = (Get-GitHubConfig -Name Repo), - - [Parameter( - Mandatory, - ValueFromPipelineByPropertyName - )] - [Alias('name')] - [string] $EnvironmentName - ) - - $RepoID = (Get-GitHubRepo).id - - $inputObject = @{ - APIEndpoint = "/repositories/$RepoID/environments/$EnvironmentName/secrets" - Method = 'GET' - } - - (Invoke-GitHubAPI @inputObject).Response - -} diff --git a/src/GitHub/public/Deployments/Update-GitHubEnvironment.ps1 b/src/GitHub/public/Deployments/Update-GitHubEnvironment.ps1 deleted file mode 100644 index c03cc78f2..000000000 --- a/src/GitHub/public/Deployments/Update-GitHubEnvironment.ps1 +++ /dev/null @@ -1,36 +0,0 @@ -filter Update-GitHubEnvironment { - <# - .NOTES - https://docs.github.com/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 - ) - - $body = @{ - owner = $Owner - repo = $Repo - environment_name = $Name - } - - $inputObject = @{ - APIEndpoint = "/repos/$Owner/$Repo/environments/$Name" - Method = 'PUT' - Body = $body - } - - (Invoke-GitHubAPI @inputObject).Response - -} diff --git a/src/GitHub/public/Emojis/Get-GitHubEmoji.ps1 b/src/GitHub/public/Emojis/Get-GitHubEmoji.ps1 new file mode 100644 index 000000000..33fba1287 --- /dev/null +++ b/src/GitHub/public/Emojis/Get-GitHubEmoji.ps1 @@ -0,0 +1,46 @@ +filter Get-GitHubEmoji { + <# + .SYNOPSIS + Get emojis + + .DESCRIPTION + Lists all the emojis available to use on GitHub. + If you pass the `Destination` parameter, the emojis will be downloaded to the specified destination. + + .EXAMPLE + Get-GitHubEmoji + + Gets all the emojis available to use on GitHub. + + .EXAMPLE + Get-GitHubEmoji -Destination 'C:\Users\user\Documents\GitHub\Emojis' + + Downloads all the emojis available to use on GitHub to the specified destination. + + .NOTES + https://docs.github.com/rest/reference/emojis#get-emojis + #> + [CmdletBinding()] + param ( + # The path to the directory where the emojis will be downloaded. + [Parameter()] + [string] $Destination + ) + + $inputObject = @{ + APIEndpoint = '/emojis' + Method = 'GET' + } + + $response = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + + 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/Emojis/Get-GitHubEmojis.ps1 b/src/GitHub/public/Emojis/Get-GitHubEmojis.ps1 deleted file mode 100644 index 5342ae458..000000000 --- a/src/GitHub/public/Emojis/Get-GitHubEmojis.ps1 +++ /dev/null @@ -1,26 +0,0 @@ -filter Get-GitHubEmojis { - <# - .NOTES - https://docs.github.com/rest/reference/emojis#get-emojis - #> - [CmdletBinding()] - param ( - [Parameter()] - [string] $Destination - ) - - $inputObject = @{ - APIEndpoint = '/emojis' - Method = 'GET' - } - - $response = (Invoke-GitHubAPI @inputObject).Response - - 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/Gitignore/Get-GitHubGitignore.ps1 b/src/GitHub/public/Gitignore/Get-GitHubGitignore.ps1 new file mode 100644 index 000000000..6fc19a794 --- /dev/null +++ b/src/GitHub/public/Gitignore/Get-GitHubGitignore.ps1 @@ -0,0 +1,55 @@ +filter Get-GitHubGitignore { + <# + .SYNOPSIS + Get a gitignore template or list of all gitignore templates names + + .DESCRIPTION + If no parameters are specified, the function will return a list of all gitignore templates names. + If the Name parameter is specified, the function will return the gitignore template for the specified name. + + .EXAMPLE + Get-GitHubGitignoreList + + Get all gitignore templates + + .EXAMPLE + Get-GitHubGitignore -Name 'VisualStudio' + + Get a gitignore template for VisualStudio + + .NOTES + https://docs.github.com/rest/gitignore/gitignore#get-a-gitignore-template + https://docs.github.com/rest/gitignore/gitignore#get-all-gitignore-templates + + #> + [CmdletBinding(DefaultParameterSetName = 'List')] + param () + + DynamicParam { + $DynamicParamDictionary = New-DynamicParamDictionary + + $dynParam = @{ + Name = 'Name' + ParameterSetName = 'Name' + Type = [string] + Mandatory = $true + ValidateSet = Get-GitHubGitignoreList + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam + + return $DynamicParamDictionary + } + + Process { + $Name = $PSBoundParameters['Name'] + switch ($PSCmdlet.ParameterSetName) { + 'List' { + Get-GitHubGitignoreList + } + 'Name' { + Get-GitHubGitignoreByName -Name $Name + } + } + } +} diff --git a/src/GitHub/public/License/Get-GitHubLicense.ps1 b/src/GitHub/public/License/Get-GitHubLicense.ps1 new file mode 100644 index 000000000..de1f90986 --- /dev/null +++ b/src/GitHub/public/License/Get-GitHubLicense.ps1 @@ -0,0 +1,76 @@ +filter Get-GitHubLicense { + <# + .SYNOPSIS + Get a license template, list of all popular license templates or a license for a repository + + .DESCRIPTION + If no parameters are specified, the function will return a list of all license templates. + If the Name parameter is specified, the function will return the license template for the specified name. + If the Owner and Repo parameters are specified, the function will return the license for the specified repository. + + .EXAMPLE + Get-GitHubLicense + + Get all license templates + + .EXAMPLE + Get-GitHubLicense -Name mit + + Get the mit license template + + .EXAMPLE + Get-GitHubLicense -Owner 'octocat' -Repo 'Hello-World' + + Get the license for the Hello-World repository from the octocat account. + + .PARAMETER Name + The license keyword, license name, or license SPDX ID. For example, mit or mpl-2.0. + + .NOTES + https://docs.github.com/rest/licenses/licenses#get-a-license + https://docs.github.com/rest/licenses/licenses#get-all-commonly-used-licenses + https://docs.github.com/rest/licenses/licenses#get-the-license-for-a-repository + + #> + [CmdletBinding(DefaultParameterSetName = 'List')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter(ParameterSetName = 'Repository')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(ParameterSetName = 'Repository')] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + DynamicParam { + $DynamicParamDictionary = New-DynamicParamDictionary + + $dynParam = @{ + Name = 'Name' + ParameterSetName = 'Name' + Type = [string] + Mandatory = $true + ValidateSet = Get-GitHubLicenseList | Select-Object -ExpandProperty Name + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam + + return $DynamicParamDictionary + } + + Process { + $Name = $PSBoundParameters['Name'] + switch ($PSCmdlet.ParameterSetName) { + 'List' { + Get-GitHubLicenseList + } + 'Name' { + Get-GitHubLicenseByName -Name $Name + } + 'Repository' { + Get-GitHubRepositoryLicense -Owner $Owner -Repo $Repo + } + } + } +} diff --git a/src/GitHub/public/Markdown/Get-GitHubMarkdown.ps1 b/src/GitHub/public/Markdown/Get-GitHubMarkdown.ps1 index 8070f9131..44b71d6f8 100644 --- a/src/GitHub/public/Markdown/Get-GitHubMarkdown.ps1 +++ b/src/GitHub/public/Markdown/Get-GitHubMarkdown.ps1 @@ -32,6 +32,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Markdown/Get-GitHubMarkdownRaw.ps1 b/src/GitHub/public/Markdown/Get-GitHubMarkdownRaw.ps1 index 053764516..8a9e18bef 100644 --- a/src/GitHub/public/Markdown/Get-GitHubMarkdownRaw.ps1 +++ b/src/GitHub/public/Markdown/Get-GitHubMarkdownRaw.ps1 @@ -16,6 +16,8 @@ Method = 'POST' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 b/src/GitHub/public/Meta/Get-GitHubApiVersion.ps1 similarity index 74% rename from src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 rename to src/GitHub/public/Meta/Get-GitHubApiVersion.ps1 index 20172b44e..e26969a66 100644 --- a/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubApiVersion.ps1 @@ -1,4 +1,4 @@ -filter Get-GitHubApiVersions { +filter Get-GitHubApiVersion { <# .SYNOPSIS Get all API versions. @@ -7,7 +7,7 @@ Get all supported GitHub API versions. .EXAMPLE - Get-GitHubApiVersions + Get-GitHubApiVersion Get all supported GitHub API versions. @@ -23,6 +23,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Meta/Get-GitHubMeta.ps1 b/src/GitHub/public/Meta/Get-GitHubMeta.ps1 index 0dd7b568e..c1b9e48ba 100644 --- a/src/GitHub/public/Meta/Get-GitHubMeta.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubMeta.ps1 @@ -4,13 +4,15 @@ 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/)." + 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. + **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 @@ -29,6 +31,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 b/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 index 49f2fd89c..1c18ea414 100644 --- a/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 @@ -39,6 +39,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Meta/Get-GitHubRoot.ps1 b/src/GitHub/public/Meta/Get-GitHubRoot.ps1 index 5637d66ee..55d8dff9d 100644 --- a/src/GitHub/public/Meta/Get-GitHubRoot.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubRoot.ps1 @@ -22,6 +22,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Meta/Get-GitHubZen.ps1 b/src/GitHub/public/Meta/Get-GitHubZen.ps1 index b4609085b..375cb9037 100644 --- a/src/GitHub/public/Meta/Get-GitHubZen.ps1 +++ b/src/GitHub/public/Meta/Get-GitHubZen.ps1 @@ -22,6 +22,8 @@ Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Organization/Get-GitHubOrganization.ps1 b/src/GitHub/public/Organization/Get-GitHubOrganization.ps1 index 054242e3e..cc2c2183d 100644 --- a/src/GitHub/public/Organization/Get-GitHubOrganization.ps1 +++ b/src/GitHub/public/Organization/Get-GitHubOrganization.ps1 @@ -34,6 +34,7 @@ #> [OutputType([pscustomobject])] [CmdletBinding(DefaultParameterSetName = '__DefaultSet')] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'All', Justification = 'Required for parameter set')] param ( # The organization name. The name is not case sensitive. [Parameter( @@ -69,6 +70,7 @@ [Parameter(ParameterSetName = 'AllOrg')] [Parameter(ParameterSetName = 'UserOrg')] [Parameter(ParameterSetName = '__DefaultSet')] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Organization/Get-GitHubOrganizationAppInstallation.ps1 b/src/GitHub/public/Organization/Get-GitHubOrganizationAppInstallation.ps1 index 48557d266..eaa30d69d 100644 --- a/src/GitHub/public/Organization/Get-GitHubOrganizationAppInstallation.ps1 +++ b/src/GitHub/public/Organization/Get-GitHubOrganizationAppInstallation.ps1 @@ -4,7 +4,8 @@ List app installations for an organization .DESCRIPTION - Lists all GitHub Apps in an organization. The installation count includes all GitHub Apps installed on repositories in the organization. You must be an organization owner with `admin:read` scope to use this endpoint. + Lists all GitHub Apps in an organization. The installation count includes all GitHub Apps installed on repositories in the organization. + You must be an organization owner with `admin:read` scope to use this endpoint. .EXAMPLE Get-GitHubOrganizationAppInstallation -OrganizationName 'github' @@ -31,6 +32,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) @@ -44,6 +46,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response.installations + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response.installations + } } diff --git a/src/GitHub/public/Organization/Remove-GitHubOrganization.ps1 b/src/GitHub/public/Organization/Remove-GitHubOrganization.ps1 index 7789ba0d6..cdc4093b0 100644 --- a/src/GitHub/public/Organization/Remove-GitHubOrganization.ps1 +++ b/src/GitHub/public/Organization/Remove-GitHubOrganization.ps1 @@ -18,7 +18,7 @@ https://docs.github.com/rest/orgs/orgs#delete-an-organization #> [OutputType([pscustomobject])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The organization name. The name is not case sensitive. [Parameter( @@ -37,6 +37,10 @@ Method = 'DELETE' } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("organization [$OrganizationName]", 'Delete')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Organization/Set-GitHubOrganization.ps1 b/src/GitHub/public/Organization/Set-GitHubOrganization.ps1 index 4f0e3e6b9..dcd883e64 100644 --- a/src/GitHub/public/Organization/Set-GitHubOrganization.ps1 +++ b/src/GitHub/public/Organization/Set-GitHubOrganization.ps1 @@ -4,9 +4,14 @@ Update an organization .DESCRIPTION - **Parameter Deprecation Notice:** GitHub will replace and discontinue `members_allowed_repository_creation_type` in favor of more granular permissions. The new input parameters are `members_can_create_public_repositories`, `members_can_create_private_repositories` for all organizations and `members_can_create_internal_repositories` for organizations associated with an enterprise account using GitHub Enterprise Cloud or GitHub Enterprise Server 2.20+. For more information, see the [blog post](https://developer.github.com/changes/2019-12-03-internal-visibility-changes). + **Parameter Deprecation Notice:** GitHub will replace and discontinue `members_allowed_repository_creation_type` + in favor of more granular permissions. The new input parameters are `members_can_create_public_repositories`, + `members_can_create_private_repositories` for all organizations and `members_can_create_internal_repositories` + for organizations associated with an enterprise account using GitHub Enterprise Cloud or GitHub Enterprise Server + 2.20+. For more information, see the [blog post](https://developer.github.com/changes/2019-12-03-internal-visibility-changes). - Enables an authenticated organization owner with the `admin:org` scope or the `repo` scope to update the organization's profile and member privileges. + Enables an authenticated organization owner with the `admin:org` scope or the `repo` scope to update the organization's + profile and member privileges. .EXAMPLE Set-GitHubOrganization -OrganizationName 'github' -Blog 'https://github.blog' @@ -22,14 +27,15 @@ } Set-GitHubOrganization @param - Sets the repository creation permissions for the organization 'github' to allow all members to create public, private, and internal repositories. + Sets the repository creation permissions for the organization 'github' to allow all members to create public, private, + and internal repositories. .NOTES https://docs.github.com/rest/orgs/orgs#update-an-organization #> [OutputType([pscustomobject])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The organization name. The name is not case sensitive. [Parameter( @@ -88,27 +94,36 @@ [ValidateSet('read', 'write', 'admin', 'none')] [string] $DefaultRepositoryPermission, - # Whether of non-admin organization members can create repositories. Note: A parameter can override this parameter. See members_allowed_repository_creation_type in this table for details. + # Whether of non-admin organization members can create repositories. + # Note: A parameter can override this parameter. See members_allowed_repository_creation_type in this table for details. [Parameter(ValueFromPipelineByPropertyName)] [Alias('members_can_create_repositories')] [bool] $MembersCanCreateRepositories = $true, - # Whether organization members can create internal repositories, which are visible to all enterprise members. You can only allow members to create internal repositories if your organization is associated with an enterprise account using GitHub Enterprise Cloud or GitHub Enterprise Server 2.20+. For more information, see "Restricting repository creation in your organization" in the GitHub Help documentation. + # Whether organization members can create internal repositories, which are visible to all enterprise members. + # You can only allow members to create internal repositories if your organization is associated with an enterprise + # account using GitHub Enterprise Cloud or GitHub Enterprise Server 2.20+. For more information, see + # "Restricting repository creation in your organization" in the GitHub Help documentation. [Parameter(ValueFromPipelineByPropertyName)] [Alias('members_can_create_internal_repositories')] [bool] $MembersCanCreateInternalRepositories, - # Whether organization members can create private repositories, which are visible to organization members with permission. For more information, see "Restricting repository creation in your organization" in the GitHub Help documentation. + # Whether organization members can create private repositories, which are visible to organization members with permission. + # For more information, see "Restricting repository creation in your organization" in the GitHub Help documentation. [Parameter(ValueFromPipelineByPropertyName)] [Alias('members_can_create_private_repositories')] [bool] $MembersCanCreatePrivateRepositories, - # Whether organization members can create public repositories, which are visible to anyone. For more information, see "Restricting repository creation in your organization" in the GitHub Help documentation. + # Whether organization members can create public repositories, which are visible to anyone. For more information, + # see 'Restricting repository creation in your organization' in the GitHub Help documentation. [Parameter(ValueFromPipelineByPropertyName)] [Alias('members_can_create_public_repositories')] [bool] $MembersCanCreatePublicRepositories, - # Specifies which types of repositories non-admin organization members can create. private is only available to repositories that are part of an organization on GitHub Enterprise Cloud. Note: This parameter is deprecated and will be removed in the future. Its return value ignores internal repositories. Using this parameter overrides values set in members_can_create_repositories. See the parameter deprecation notice in the operation description for details. + # Specifies which types of repositories non-admin organization members can create. private is only available to + # repositories that are part of an organization on GitHub Enterprise Cloud. Note: This parameter is deprecated and + # will be removed in the future. Its return value ignores internal repositories. Using this parameter overrides values + # set in members_can_create_repositories. See the parameter deprecation notice in the operation description for details. [Parameter(ValueFromPipelineByPropertyName)] [Alias('members_allowed_repository_creation_type')] [ValidateSet('all', 'private', 'none')] @@ -144,42 +159,48 @@ [string] $Blog, # Whether GitHub Advanced Security is automatically enabled for new repositories. - # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization." + # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for + # the organization that owns the repository. For more information, see "Managing security managers in your organization." # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request. [Parameter(ValueFromPipelineByPropertyName)] [Alias('advanced_security_enabled_for_new_repositories')] [bool] $AdvancedSecurityEnabledForNewRepositories = $false, # Whether Dependabot alerts is automatically enabled for new repositories. - # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization." + # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for + # the organization that owns the repository. For more information, see "Managing security managers in your organization." # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request. [Parameter(ValueFromPipelineByPropertyName)] [Alias('dependabot_alerts_enabled_for_new_repositories')] [bool] $DependabotAlertsEnabledForNewRepositories = $false, # Whether Dependabot security updates is automatically enabled for new repositories. - # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization." + # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for + # the organization that owns the repository. For more information, see "Managing security managers in your organization." # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request. [Parameter(ValueFromPipelineByPropertyName)] [Alias('dependabot_security_updates_enabled_for_new_repositories')] [bool] $DependabotSecurityUpdatesEnabledForNewRepositories = $false, # Whether dependency graph is automatically enabled for new repositories. - # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization." + # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for + # the organization that owns the repository. For more information, see "Managing security managers in your organization." # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request. [Parameter(ValueFromPipelineByPropertyName)] [Alias('dependency_graph_enabled_for_new_repositories')] [bool] $DependencyGraphEnabledForNewRepositories = $false, # Whether secret scanning is automatically enabled for new repositories. - # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization." + # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for + # the organization that owns the repository. For more information, see "Managing security managers in your organization." # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request. [Parameter(ValueFromPipelineByPropertyName)] [Alias('secret_scanning_enabled_for_new_repositories')] [bool] $SecretScanningEnabledForNewRepositories = $false, # Whether secret scanning push protection is automatically enabled for new repositories. - # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization." + # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for + # the organization that owns the repository. For more information, see "Managing security managers in your organization." # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request. [Parameter(ValueFromPipelineByPropertyName)] [Alias('secret_scanning_push_protection_enabled_for_new_repositories')] @@ -190,14 +211,15 @@ [Alias('secret_scanning_push_protection_custom_link_enabled')] [bool] $SecretScanningPushProtectionCustomLinkEnabled = $false, - # If secret_scanning_push_protection_custom_link_enabled is true, the URL that will be displayed to contributors who are blocked from pushing a secret. + # If secret_scanning_push_protection_custom_link_enabled is true, the URL that will be displayed to contributors who + # are blocked from pushing a secret. [Parameter(ValueFromPipelineByPropertyName)] [Alias('secret_scanning_push_protection_custom_link')] [string] $SecretScanningPushProtectionCustomLink ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashTableEntries -Hashtable $body -RemoveNames 'organization_name' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'organization_name' $inputObject = @{ APIEndpoint = "/orgs/$OrganizationName" @@ -205,6 +227,10 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("organization [$OrganizationName]", 'Set')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Organization/Set-GitHubOrganizationSecurityFeature.ps1 b/src/GitHub/public/Organization/Set-GitHubOrganizationSecurityFeature.ps1 index 7a7b88429..f8a491f0f 100644 --- a/src/GitHub/public/Organization/Set-GitHubOrganizationSecurityFeature.ps1 +++ b/src/GitHub/public/Organization/Set-GitHubOrganizationSecurityFeature.ps1 @@ -22,7 +22,8 @@ https://docs.github.com/rest/orgs/orgs#enable-or-disable-a-security-feature-for-an-organization #> [OutputType([pscustomobject])] - [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Long link in notes.')] + [CmdletBinding(SupportsShouldProcess)] param ( # The organization name. The name is not case sensitive. [Parameter(Mandatory)] @@ -34,19 +35,37 @@ # The security feature to enable or disable. [Parameter(Mandatory)] [Alias('security_product')] - [ValidateSet('dependency_graph', 'dependabot_alerts', 'dependabot_security_updates', 'advanced_security', 'code_scanning_default_setup', 'secret_scanning', 'secret_scanning_push_protection')] + [ValidateSet( + 'dependency_graph', + 'dependabot_alerts', + 'dependabot_security_updates', + 'advanced_security', + 'code_scanning_default_setup', + 'secret_scanning', + 'secret_scanning_push_protection' + )] [string] $SecurityProduct, # The action to take. - # enable_all means to enable the specified security feature for all repositories in the organization. disable_all means to disable the specified security feature for all repositories in the organization. + # enable_all means to enable the specified security feature for all repositories in the organization. disable_all + # means to disable the specified security feature for all repositories in the organization. [Parameter(Mandatory)] - [ValidateSet('enable_all', 'disable_all')] + [ValidateSet( + 'enable_all', + 'disable_all' + )] [string] $Enablement, - # CodeQL query suite to be used. If you specify the query_suite parameter, the default setup will be configured with this query suite only on all repositories that didn't have default setup already configured. It will not change the query suite on repositories that already have default setup configured. If you don't specify any query_suite in your request, the preferred query suite of the organization will be applied. + # CodeQL query suite to be used. If you specify the query_suite parameter, the default setup will be configured with + # this query suite only on all repositories that didn't have default setup already configured. It will not change the + # query suite on repositories that already have default setup configured. If you don't specify any query_suite in your + # request, the preferred query suite of the organization will be applied. [Parameter()] [Alias('query_suite')] - [ValidateSet('default', 'extended')] + [ValidateSet( + 'default', + 'extended' + )] [string] $QuerySuite ) @@ -60,6 +79,10 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("security feature [$SecurityProduct] on organization [$OrganizationName]", 'Set')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Rate-Limit/Get-GitHubRateLimit.ps1 b/src/GitHub/public/Rate-Limit/Get-GitHubRateLimit.ps1 index b326334d7..5fd6b9317 100644 --- a/src/GitHub/public/Rate-Limit/Get-GitHubRateLimit.ps1 +++ b/src/GitHub/public/Rate-Limit/Get-GitHubRateLimit.ps1 @@ -6,7 +6,8 @@ .DESCRIPTION **Note:** Accessing this endpoint does not count against your REST API rate limit. - Some categories of endpoints have custom rate limits that are separate from the rate limit governing the other REST API endpoints. For this reason, the API response categorizes your rate limit. Under `resources`, you'll see objects relating to different categories: + Some categories of endpoints have custom rate limits that are separate from the rate limit governing the other REST API endpoints. + For this reason, the API response categorizes your rate limit. Under `resources`, you'll see objects relating to different categories: * The `core` object provides your rate limit status for all non-search-related resources in the REST API. * The `search` object provides your rate limit status for the REST API for searching (excluding code searches). For more information, see "[Search](https://docs.github.com/rest/search)." * The `code_search` object provides your rate limit status for the REST API for searching code. For more information, see "[Search code](https://docs.github.com/rest/search/search#search-code)." @@ -17,7 +18,8 @@ * The `actions_runner_registration` object provides your rate limit status for registering self-hosted runners in GitHub Actions. For more information, see "[Self-hosted runners](https://docs.github.com/rest/actions/self-hosted-runners)." * The `source_import` object is no longer in use for any API endpoints, and it will be removed in the next API version. For more information about API versions, see "[API Versions](https://docs.github.com/rest/overview/api-versions)." - **Note:** The `rate` object is deprecated. If you're writing new API client code or updating existing code, you should use the `core` object instead of the `rate` object. The `core` object contains the same information that is present in the `rate` object. + **Note:** The `rate` object is deprecated. If you're writing new API client code or updating existing code, you should use the `core` object + instead of the `rate` object. The `core` object contains the same information that is present in the `rate` object. .EXAMPLE Get-GitHubRateLimit @@ -29,14 +31,17 @@ #> [OutputType([pscustomobject])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] [CmdletBinding()] param () $inputObject = @{ - APIEndpoint = "/rate_limit" + APIEndpoint = '/rate_limit' Method = 'GET' } - (Invoke-GitHubAPI @inputObject).Response.Resources + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response.Resources + } } diff --git a/src/GitHub/public/Releases/Assets/Add-GitHubReleaseAsset.ps1 b/src/GitHub/public/Releases/Assets/Add-GitHubReleaseAsset.ps1 index 35139229d..46119404b 100644 --- a/src/GitHub/public/Releases/Assets/Add-GitHubReleaseAsset.ps1 +++ b/src/GitHub/public/Releases/Assets/Add-GitHubReleaseAsset.ps1 @@ -4,25 +4,37 @@ Upload a release asset .DESCRIPTION - This endpoint makes use of [a Hypermedia relation](https://docs.github.com/rest/overview/resources-in-the-rest-api#hypermedia) to determine which URL to access. The endpoint you call to upload release assets is specific to your release. Use the `upload_url` returned in - the response of the [Create a release endpoint](https://docs.github.com/rest/releases/releases#create-a-release) to upload a release asset. + This endpoint makes use of [a Hypermedia relation](https://docs.github.com/rest/overview/resources-in-the-rest-api#hypermedia) + to determine which URL to access. The endpoint you call to upload release assets is specific to your release. Use the + `upload_url` returned in + the response of the [Create a release endpoint](https://docs.github.com/rest/releases/releases#create-a-release) to upload + a release asset. - You need to use an HTTP client which supports [SNI](http://en.wikipedia.org/wiki/Server_Name_Indication) to make calls to this endpoint. + You need to use an HTTP client which supports [SNI](http://en.wikipedia.org/wiki/Server_Name_Indication) to make calls to + this endpoint. - Most libraries will set the required `Content-Length` header automatically. Use the required `Content-Type` header to provide the media type of the asset. For a list of media types, see [Media Types](https://www.iana.org/assignments/media-types/media-types.xhtml). For example: + Most libraries will set the required `Content-Length` header automatically. Use the required `Content-Type` header to provide + the media type of the asset. For a list of media types, see + [Media Types](https://www.iana.org/assignments/media-types/media-types.xhtml). For example: `application/zip` - GitHub expects the asset data in its raw binary form, rather than JSON. You will send the raw binary content of the asset as the request body. Everything else about the endpoint is the same as the rest of the API. For example, + GitHub expects the asset data in its raw binary form, rather than JSON. You will send the raw binary content of the asset + as the request body. Everything else about the endpoint is the same as the rest of the API. For example, you'll still need to pass your authentication to be able to upload an asset. - When an upstream failure occurs, you will receive a `502 Bad Gateway` status. This may leave an empty asset with a state of `starter`. It can be safely deleted. + When an upstream failure occurs, you will receive a `502 Bad Gateway` status. This may leave an empty asset with a state + of `starter`. It can be safely deleted. **Notes:** - * GitHub renames asset filenames that have special characters, non-alphanumeric characters, and leading or trailing periods. The "[List release assets](https://docs.github.com/rest/releases/assets#list-release-assets)" - endpoint lists the renamed filenames. For more information and help, contact [GitHub Support](https://support.github.com/contact?tags=dotcom-rest-api). - * To find the `release_id` query the [`GET /repos/{owner}/{repo}/releases/latest` endpoint](https://docs.github.com/rest/releases/releases#get-the-latest-release). - * If you upload an asset with the same filename as another uploaded asset, you'll receive an error and must delete the old file before you can re-upload the new asset. + * GitHub renames asset filenames that have special characters, non-alphanumeric characters, and leading or trailing periods. + The "[List release assets](https://docs.github.com/rest/releases/assets#list-release-assets)" + endpoint lists the renamed filenames. For more information and help, contact + [GitHub Support](https://support.github.com/contact?tags=dotcom-rest-api). + * To find the `release_id` query the + [`GET /repos/{owner}/{repo}/releases/latest` endpoint](https://docs.github.com/rest/releases/releases#get-the-latest-release). + * If you upload an asset with the same filename as another uploaded asset, you'll receive an error and must delete + the old file before you can re-upload the new asset. .EXAMPLE Add-GitHubReleaseAsset -Owner 'octocat' -Repo 'hello-world' -ID '7654321' -FilePath 'C:\Users\octocat\Downloads\hello-world.zip' @@ -102,12 +114,12 @@ } $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'Owner', 'Repo', 'ID', 'FilePath' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo', 'ID', 'FilePath' $body['name'] = $Name $body['label'] = $Label - Remove-HashtableEntries -Hashtable $body -NullOrEmptyValues + Remove-HashtableEntry -Hashtable $body -NullOrEmptyValues $release = Get-GitHubRelease -Owner $Owner -Repo $Repo -ID $ID $uploadURI = $release.upload_url -replace '{\?name,label}', "?name=$($Name)&label=$($Label)" @@ -119,6 +131,8 @@ UploadFilePath = $FilePath } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Releases/Assets/Remove-GitHubReleaseAsset.ps1 b/src/GitHub/public/Releases/Assets/Remove-GitHubReleaseAsset.ps1 index d232ee047..70e61f0af 100644 --- a/src/GitHub/public/Releases/Assets/Remove-GitHubReleaseAsset.ps1 +++ b/src/GitHub/public/Releases/Assets/Remove-GitHubReleaseAsset.ps1 @@ -15,7 +15,7 @@ https://docs.github.com/rest/releases/assets#delete-a-release-asset #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The account owner of the repository. The name is not case sensitive. [Parameter()] @@ -36,6 +36,10 @@ Method = 'DELETE' } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("Asset with ID [$ID] in [$Owner/$Repo]", 'Delete')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Releases/Assets/Set-GitHubReleaseAsset.ps1 b/src/GitHub/public/Releases/Assets/Set-GitHubReleaseAsset.ps1 index 48ac2ec3a..e5daffd16 100644 --- a/src/GitHub/public/Releases/Assets/Set-GitHubReleaseAsset.ps1 +++ b/src/GitHub/public/Releases/Assets/Set-GitHubReleaseAsset.ps1 @@ -9,13 +9,13 @@ .EXAMPLE Set-GitHubReleaseAsset -Owner 'octocat' -Repo 'hello-world' -ID '1234567' -Name 'new_asset_name' -Label 'new_asset_label' - Updates the release asset with the ID '1234567' for the repository 'octocat/hello-world' with the new name 'new_asset_name' and label 'new_asset_label'. + Updates the release asset with the ID '1234567' for the repository 'octocat/hello-world' with the new name 'new_asset_name' and + label 'new_asset_label'. .NOTES https://docs.github.com/rest/releases/assets#update-a-release-asset - #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The account owner of the repository. The name is not case sensitive. [Parameter()] @@ -46,7 +46,7 @@ ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'Owner', 'Repo','ID' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo', 'ID' $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/releases/assets/$ID" @@ -54,6 +54,10 @@ Body = $requestBody } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("assets for release with ID [$ID] in [$Owner/$Repo]", 'Set')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Releases/Releases/Get-GitHubRelease.ps1 b/src/GitHub/public/Releases/Releases/Get-GitHubRelease.ps1 index 177f93ede..978b1a2d6 100644 --- a/src/GitHub/public/Releases/Releases/Get-GitHubRelease.ps1 +++ b/src/GitHub/public/Releases/Releases/Get-GitHubRelease.ps1 @@ -34,6 +34,7 @@ #> [CmdletBinding(DefaultParameterSetName = 'All')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Latest', Justification = 'Required for parameter set')] param ( # The account owner of the repository. The name is not case sensitive. [Parameter()] @@ -45,6 +46,7 @@ # The number of results per page (max 100). [Parameter(ParameterSetName = 'All')] + [ValidateRange(1, 100)] [int] $PerPage = 30, # Get the latest release only diff --git a/src/GitHub/public/Releases/Releases/New-GitHubRelease.ps1 b/src/GitHub/public/Releases/Releases/New-GitHubRelease.ps1 index bcc92f02e..5c1954afb 100644 --- a/src/GitHub/public/Releases/Releases/New-GitHubRelease.ps1 +++ b/src/GitHub/public/Releases/Releases/New-GitHubRelease.ps1 @@ -20,7 +20,8 @@ #> [OutputType([pscustomobject])] - [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] + [CmdletBinding(SupportsShouldProcess)] param ( # The account owner of the repository. The name is not case sensitive. [Parameter()] @@ -78,13 +79,13 @@ ) $requestBody = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $requestBody -RemoveNames 'Owner', 'Repo', 'GenerateReleaseNotes', 'Draft', 'Prerelease' - $requestBody = Join-Object -AsHashtable -Main $requestBody -Overrides @{ + Remove-HashtableEntry -Hashtable $requestBody -RemoveNames 'Owner', 'Repo', 'GenerateReleaseNotes', 'Draft', 'Prerelease' + $requestBody = Join-Object -AsHashtable -Main $requestBody -Overrides @{ generate_release_notes = $GenerateReleaseNotes.IsPresent draft = $Draft.IsPresent prerelease = $Prerelease.IsPresent } - Remove-HashtableEntries -Hashtable $requestBody -NullOrEmptyValues + Remove-HashtableEntry -Hashtable $requestBody -NullOrEmptyValues $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/releases" @@ -92,6 +93,10 @@ Body = $requestBody } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("$Owner/$Repo", 'Create a release')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Releases/Releases/New-GitHubReleaseNotes.ps1 b/src/GitHub/public/Releases/Releases/New-GitHubReleaseNote.ps1 similarity index 89% rename from src/GitHub/public/Releases/Releases/New-GitHubReleaseNotes.ps1 rename to src/GitHub/public/Releases/Releases/New-GitHubReleaseNote.ps1 index 841d53e1a..114293bc9 100644 --- a/src/GitHub/public/Releases/Releases/New-GitHubReleaseNotes.ps1 +++ b/src/GitHub/public/Releases/Releases/New-GitHubReleaseNote.ps1 @@ -1,4 +1,4 @@ -filter New-GitHubReleaseNotes { +filter New-GitHubReleaseNote { <# .SYNOPSIS List releases @@ -14,7 +14,7 @@ Repo = 'hello-world' TagName = 'v1.0.0' } - New-GitHubReleaseNotes @params + New-GitHubReleaseNote @params Creates a new release notes draft for the repository 'hello-world' owned by 'octocat' with the tag name 'v1.0.0'. In this example the tag 'v1.0.0' has to exist in the repository. @@ -27,7 +27,7 @@ TagName = 'v1.0.0' TargetCommitish = 'main' } - New-GitHubReleaseNotes @params + New-GitHubReleaseNote @params Creates a new release notes draft for the repository 'hello-world' owned by 'octocat' with the tag name 'v1.0.0'. In this example the tag 'v1.0.0' has to exist in the repository. @@ -42,7 +42,7 @@ PreviousTagName = 'v0.9.2' ConfigurationFilePath = '.github/custom_release_config.yml' } - New-GitHubReleaseNotes @params + New-GitHubReleaseNote @params Creates a new release notes draft for the repository 'hello-world' owned by 'octocat' with the tag name 'v1.0.0'. The release notes will be based on the changes between the tags 'v0.9.2' and 'v1.0.0' and generated based on the @@ -54,7 +54,8 @@ #> [OutputType([pscustomobject])] [Alias('Generate-GitHubReleaseNotes')] - [CmdletBinding()] + [Alias('New-GitHubReleaseNotes')] + [CmdletBinding(SupportsShouldProcess)] param ( # The account owner of the repository. The name is not case sensitive. [Parameter()] @@ -93,7 +94,7 @@ ) $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $body -RemoveNames 'Owner', 'Repo' + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' $inputObject = @{ APIEndpoint = "/repos/$Owner/$Repo/releases/generate-notes" @@ -101,6 +102,10 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("$Owner/$Repo", 'Create release notes')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Releases/Releases/Remove-GitHubRelease.ps1 b/src/GitHub/public/Releases/Releases/Remove-GitHubRelease.ps1 index 836fd519b..857e4663a 100644 --- a/src/GitHub/public/Releases/Releases/Remove-GitHubRelease.ps1 +++ b/src/GitHub/public/Releases/Releases/Remove-GitHubRelease.ps1 @@ -16,7 +16,7 @@ #> [OutputType([pscustomobject])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The account owner of the repository. The name is not case sensitive. [Parameter()] @@ -39,6 +39,10 @@ Method = 'DELETE' } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("Release with ID [$ID] in [$Owner/$Repo]", 'Delete')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Releases/Releases/Set-GitHubRelease.ps1 b/src/GitHub/public/Releases/Releases/Set-GitHubRelease.ps1 index e11478bc0..5af672e75 100644 --- a/src/GitHub/public/Releases/Releases/Set-GitHubRelease.ps1 +++ b/src/GitHub/public/Releases/Releases/Set-GitHubRelease.ps1 @@ -16,7 +16,8 @@ #> [OutputType([pscustomobject])] - [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] + [CmdletBinding(SupportsShouldProcess)] param ( # The account owner of the repository. The name is not case sensitive. [Parameter()] @@ -66,7 +67,9 @@ [Alias('discussion_category_name')] [string] $DiscussionCategoryName, - # Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Defaults to true for newly published releases. legacy specifies that the latest release should be determined based on the release creation date and higher semantic version. + # Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. + # Defaults to true for newly published releases. legacy specifies that the latest release should be determined based on the release creation + # date and higher semantic version. [Parameter()] [Alias('make_latest')] [ValidateSet('true', 'false', 'legacy')] @@ -74,10 +77,10 @@ ) $requestBody = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case - Remove-HashtableEntries -Hashtable $requestBody -RemoveNames 'Owner', 'Repo', 'Draft', 'Prerelease' - $requestBody = Join-Object -AsHashtable -Main $requestBody -Overrides @{ - draft = $Draft.IsPresent ? $Draft : $false - prerelease = $Prerelease.IsPresent ? $Prerelease : $false + Remove-HashtableEntry -Hashtable $requestBody -RemoveNames 'Owner', 'Repo', 'Draft', 'Prerelease' + $requestBody = Join-Object -AsHashtable -Main $requestBody -Overrides @{ + draft = $Draft.IsPresent ? $Draft : $false + prerelease = $Prerelease.IsPresent ? $Prerelease : $false } $inputObject = @{ @@ -86,6 +89,10 @@ Body = $requestBody } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("release with ID [$ID] in [$Owner/$Repo]", 'Update')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Repositories/Autolinks/Get-GitHubRepositoryAutolink.ps1 b/src/GitHub/public/Repositories/Autolinks/Get-GitHubRepositoryAutolink.ps1 new file mode 100644 index 000000000..18d936b7b --- /dev/null +++ b/src/GitHub/public/Repositories/Autolinks/Get-GitHubRepositoryAutolink.ps1 @@ -0,0 +1,55 @@ +filter Get-GitHubRepositoryAutolink { + <# + .SYNOPSIS + List all autolinks of a repository + + .DESCRIPTION + This returns a list of autolinks configured for the given repository. + + Information about autolinks are only available to repository administrators. + + .EXAMPLE + Get-GitHubRepositoryAutolink -Owner 'octocat' -Repo 'Hello-World' + + Gets all autolinks for the repository 'Hello-World' owned by 'octocat'. + + .EXAMPLE + Get-GitHubRepositoryAutolink -Owner 'octocat' -Repo 'Hello-World' -Id 1 + + Gets the autolink with the id 1 for the repository 'Hello-World' owned by 'octocat'. + + .NOTES + https://docs.github.com/rest/repos/autolinks#list-all-autolinks-of-a-repository + + #> + [Alias('Get-GitHubRepositoryAutolinks')] + [CmdletBinding(DefaultParameterSetName = 'Default')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The unique identifier of the autolink. + [Parameter( + Mandatory, + ParameterSetName = 'ById' + )] + [Alias('autolink_id')] + [Alias('Id')] + [int] $AutolinkId + ) + + switch ($PSCmdlet.ParameterSetName) { + 'ById' { + Get-GitHubRepositoryAutolinkById -Owner $Owner -Repo $Repo -Id $AutolinkId + } + default { + Get-GitHubRepositoryAutolinkList -Owner $Owner -Repo $Repo + } + } +} diff --git a/src/GitHub/public/Repositories/Autolinks/New-GitHubRepositoryAutolink.ps1 b/src/GitHub/public/Repositories/Autolinks/New-GitHubRepositoryAutolink.ps1 new file mode 100644 index 000000000..fe5ca1c59 --- /dev/null +++ b/src/GitHub/public/Repositories/Autolinks/New-GitHubRepositoryAutolink.ps1 @@ -0,0 +1,76 @@ +filter New-GitHubRepositoryAutolink { + <# + .SYNOPSIS + Create an autolink reference for a repository + + .DESCRIPTION + Users with admin access to the repository can create an autolink. + + .EXAMPLE + New-GitHubRepositoryAutolink -Owner 'octocat' -Repo 'Hello-World' -KeyPrefix 'GH-' -UrlTemplate 'https://www.example.com/issue/' + + Creates an autolink for the repository 'Hello-World' owned by 'octocat' that links to https://www.example.com/issue/ + when the prefix GH- is found in an issue, pull request, or commit. + + .NOTES + https://docs.github.com/rest/repos/autolinks#create-an-autolink-reference-for-a-repository + + #> + [OutputType([pscustomobject])] + [CmdletBinding(SupportsShouldProcess)] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Repo, + + # This prefix appended by certain characters will generate a link any time it is found in an issue, pull request, or commit. + [Parameter(Mandatory)] + [Alias('key_prefix')] + [string] $KeyPrefix, + + # The URL must contain for the reference number. matches different characters depending on the value of is_alphanumeric. + [Parameter(Mandatory)] + [Alias('url_template')] + [string] $UrlTemplate, + + # Whether this autolink reference matches alphanumeric characters. If true, the parameter of the url_template matches alphanumeric + # characters A-Z (case insensitive), 0-9, and -. If false, this autolink reference only matches numeric characters. + [Parameter()] + [Alias('is_alphanumeric')] + [bool] $IsAlphanumeric = $true + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/autolinks" + Method = 'POST' + Body = $body + } + + if ($PSCmdlet.ShouldProcess("Autolink for repository [$Owner/$Repo]", 'Create')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/Autolinks/Remove-GitHubRepositoryAutolink.ps1 b/src/GitHub/public/Repositories/Autolinks/Remove-GitHubRepositoryAutolink.ps1 new file mode 100644 index 000000000..5e430ca40 --- /dev/null +++ b/src/GitHub/public/Repositories/Autolinks/Remove-GitHubRepositoryAutolink.ps1 @@ -0,0 +1,49 @@ +filter Remove-GitHubRepositoryAutolink { + <# + .SYNOPSIS + Delete an autolink reference from a repository + + .DESCRIPTION + This deletes a single autolink reference by ID that was configured for the given repository. + + Information about autolinks are only available to repository administrators. + + .EXAMPLE + Remove-GitHubRepositoryAutolink -Owner 'octocat' -Repo 'Hello-World' -AutolinkId 1 + + Deletes the autolink with ID 1 for the repository 'Hello-World' owned by 'octocat'. + + .NOTES + https://docs.github.com/rest/repos/autolinks#delete-an-autolink-reference-from-a-repository + + #> + [OutputType([pscustomobject])] + [CmdletBinding(SupportsShouldProcess)] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Repo, + + # The unique identifier of the autolink. + [Parameter(Mandatory)] + [Alias('autolink_id')] + [Alias('Id')] + [int] $AutolinkId + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/autolinks/$AutolinkId" + Method = 'DELETE' + Body = $body + } + + if ($PSCmdlet.ShouldProcess("Autolink with ID [$AutolinkId] for repository [$Owner/$Repo]", 'Delete')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/CustomProperties/Get-GitHubRepositoryCustomProperty.ps1 b/src/GitHub/public/Repositories/CustomProperties/Get-GitHubRepositoryCustomProperty.ps1 new file mode 100644 index 000000000..0c53ad085 --- /dev/null +++ b/src/GitHub/public/Repositories/CustomProperties/Get-GitHubRepositoryCustomProperty.ps1 @@ -0,0 +1,41 @@ +filter Get-GitHubRepositoryCustomProperty { + <# + .SYNOPSIS + Get all custom property values for a repository + + .DESCRIPTION + Gets all custom property values that are set for a repository. + Users with read access to the repository can use this endpoint. + + .EXAMPLE + Get-GitHubRepositoryCustomProperty -Owner 'octocat' -Repo 'hello-world' + + Gets all custom property values that are set for the 'hello-world' repository. + + .NOTES + https://docs.github.com/rest/repos/custom-properties#get-all-custom-property-values-for-a-repository + + #> + [OutputType([pscustomobject])] + [Alias('Get-GitHubRepositoryCustomProperties')] + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/properties/values" + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositoryPrivateVulnerabilityReporting.ps1 b/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositoryPrivateVulnerabilityReporting.ps1 new file mode 100644 index 000000000..8615a4ec2 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositoryPrivateVulnerabilityReporting.ps1 @@ -0,0 +1,43 @@ +filter Disable-GitHubRepositoryPrivateVulnerabilityReporting { + <# + .SYNOPSIS + Disable private vulnerability reporting for a repository + + .DESCRIPTION + Disables private vulnerability reporting for a repository. The authenticated user must have admin access + to the repository. For more information, see + "[Privately reporting a security vulnerability](https://docs.github.com/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability)". + + .EXAMPLE + Disable-GitHubRepositoryPrivateVulnerabilityReporting -Owner 'PSModule' -Repo 'GitHub' + + Disables private vulnerability reporting for the PSModule/GitHub repository. + + .NOTES + https://docs.github.com/rest/repos/repos#disable-private-vulnerability-reporting-for-a-repository + + #> + [CmdletBinding(SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Long links')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/private-vulnerability-reporting" + Method = 'DELETE' + } + + if ($PSCmdlet.ShouldProcess("Private Vulnerability Reporting for [$Owner/$Repo]", 'Disable')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositorySecurityFix.ps1 b/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositorySecurityFix.ps1 new file mode 100644 index 000000000..fe967fa05 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositorySecurityFix.ps1 @@ -0,0 +1,43 @@ +filter Disable-GitHubRepositorySecurityFix { + <# + .SYNOPSIS + Disable automated security fixes + + .DESCRIPTION + Disables automated security fixes for a repository. The authenticated user must have admin access to the repository. + For more information, see + "[Configuring automated security fixes](https://docs.github.com/articles/configuring-automated-security-fixes)". + + .EXAMPLE + Disable-GitHubRepositorySecurityFix -Owner 'PSModule' -Repo 'GitHub' + + Disables automated security fixes for the repository. + + .NOTES + https://docs.github.com/rest/repos/repos#disable-automated-security-fixes + + #> + [CmdletBinding(SupportsShouldProcess)] + [Alias('Disable-GitHubRepositorySecurityFixes')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/automated-security-fixes" + Method = 'DELETE' + } + + if ($PSCmdlet.ShouldProcess("Security Fixes for [$Owner/$Repo]", 'Disable')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositoryVulnerabilityAlert.ps1 b/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositoryVulnerabilityAlert.ps1 new file mode 100644 index 000000000..cc76adfc4 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Disable-GitHubRepositoryVulnerabilityAlert.ps1 @@ -0,0 +1,42 @@ +filter Disable-GitHubRepositoryVulnerabilityAlert { + <# + .SYNOPSIS + Disable vulnerability alerts + + .DESCRIPTION + Disables dependency alerts and the dependency graph for a repository. + The authenticated user must have admin access to the repository. For more information, see + "[About security alerts for vulnerable dependencies](https://docs.github.com/articles/about-security-alerts-for-vulnerable-dependencies)". + + .EXAMPLE + Disable-GitHubRepositoryVulnerabilityAlert -Owner 'octocat' -Repo 'hello-world' + + Disables vulnerability alerts for the 'octocat/hello-world' repository. + + .NOTES + https://docs.github.com/rest/repos/repos#disable-vulnerability-alerts + #> + [CmdletBinding(SupportsShouldProcess)] + [Alias('Disable-GitHubRepositoryVulnerabilityAlerts')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/vulnerability-alerts" + Method = 'DELETE' + } + + if ($PSCmdlet.ShouldProcess("Vulnerability Alerts for [$Owner/$Repo]", 'Disable')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositoryPrivateVulnerabilityReporting.ps1 b/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositoryPrivateVulnerabilityReporting.ps1 new file mode 100644 index 000000000..c5b2058da --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositoryPrivateVulnerabilityReporting.ps1 @@ -0,0 +1,43 @@ +filter Enable-GitHubRepositoryPrivateVulnerabilityReporting { + <# + .SYNOPSIS + Enable private vulnerability reporting for a repository + + .DESCRIPTION + Enables private vulnerability reporting for a repository. The authenticated user must have admin access + to the repository. For more information, see + "[Privately reporting a security vulnerability](https://docs.github.com/code-security/security-advisories/guidance-on-reporting-and-writing/privately-reporting-a-security-vulnerability)." + + .EXAMPLE + Enable-GitHubRepositoryPrivateVulnerabilityReporting -Owner 'PSModule' -Repo 'GitHub' + + Enables private vulnerability reporting for the PSModule/GitHub repository. + + .NOTES + https://docs.github.com/rest/repos/repos#enable-private-vulnerability-reporting-for-a-repository + + #> + [CmdletBinding(SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Long links')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/private-vulnerability-reporting" + Method = 'PUT' + } + + if ($PSCmdlet.ShouldProcess("Private Vulnerability Reporting for [$Owner/$Repo]", 'Enable')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositorySecurityFix.ps1 b/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositorySecurityFix.ps1 new file mode 100644 index 000000000..e69b55d88 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositorySecurityFix.ps1 @@ -0,0 +1,43 @@ +filter Enable-GitHubRepositorySecurityFix { + <# + .SYNOPSIS + Enable automated security fixes + + .DESCRIPTION + Enables automated security fixes for a repository. The authenticated user must have admin access to the repository. + For more information, see + "[Configuring automated security fixes](https://docs.github.com/articles/configuring-automated-security-fixes)". + + .EXAMPLE + Enable-GitHubRepositorySecurityFix -Owner 'PSModule' -Repo 'GitHub' + + Enables automated security fixes for the repository. + + .NOTES + https://docs.github.com/rest/repos/repos#enable-automated-security-fixes + + #> + [CmdletBinding(SupportsShouldProcess)] + [Alias('Enable-GitHubRepositorySecurityFixes')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/automated-security-fixes" + Method = 'PUT' + } + + if ($PSCmdlet.ShouldProcess("Security Fixes for [$Owner/$Repo]", 'Enable')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositoryVulnerabilityAlert.ps1 b/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositoryVulnerabilityAlert.ps1 new file mode 100644 index 000000000..665820760 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Enable-GitHubRepositoryVulnerabilityAlert.ps1 @@ -0,0 +1,43 @@ +filter Enable-GitHubRepositoryVulnerabilityAlert { + <# + .SYNOPSIS + Enable vulnerability alerts + + .DESCRIPTION + Enables dependency alerts and the dependency graph for a repository. + The authenticated user must have admin access to the repository. + For more information, see + "[About security alerts for vulnerable dependencies](https://docs.github.com/articles/about-security-alerts-for-vulnerable-dependencies)". + + .EXAMPLE + Enable-GitHubRepositoryVulnerabilityAlert -Owner 'octocat' -Repo 'hello-world' + + Enables vulnerability alerts for the 'octocat/hello-world' repository. + + .NOTES + https://docs.github.com/rest/repos/repos#enable-vulnerability-alerts + #> + [CmdletBinding(SupportsShouldProcess)] + [Alias('Enable-GitHubRepositoryVulnerabilityAlerts')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/vulnerability-alerts" + Method = 'PUT' + } + + if ($PSCmdlet.ShouldProcess("Vulnerability Alerts for [$Owner/$Repo]", "Enable")) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepository.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepository.ps1 new file mode 100644 index 000000000..2c90839be --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepository.ps1 @@ -0,0 +1,229 @@ +filter Get-GitHubRepository { + <# + .SYNOPSIS + Gets a specific repository or list of repositories. + + .DESCRIPTION + Gets a specific repository or list of repositories based on parameter sets. + If no parameters are specified, the authenticated user's repositories are returned. + If a Username parameter is specified, the specified user's public repositories are returned. + If the SinceId parameter is specified, the repositories with an ID greater than the specified ID are returned. + If an Owner and Repo parameters are specified, the specified repository is returned. + If the Owner and Repo parameters are specified, the specified repository is returned. + + .PARAMETER Type + Specifies the types of repositories you want returned. + + .EXAMPLE + Get-GitHubRepository + + Gets the repositories for the authenticated user. + + .EXAMPLE + Get-GitHubRepository -Type 'owner' + + Gets the repositories owned by the authenticated user. + + .EXAMPLE + Get-GitHubRepository -Username 'octocat' + + Gets the repositories for the specified user. + + .EXAMPLE + Get-GitHubRepository -SinceID 123456789 + + Gets the repositories with an ID equals and greater than 123456789. + + .EXAMPLE + Get-GitHubRepository -Owner 'github' -Repo 'octocat' + + Gets the specified repository. + + .NOTES + https://docs.github.com/rest/repos/repos#list-repositories-for-the-authenticated-user + https://docs.github.com/rest/repos/repos#get-a-repository + https://docs.github.com/rest/repos/repos#list-public-repositories + https://docs.github.com/rest/repos/repos#list-organization-repositories + https://docs.github.com/rest/repos/repos#list-repositories-for-a-user + + #> + [CmdletBinding(DefaultParameterSetName = 'MyRepos_Type')] + param ( + #Limit results to repositories with the specified visibility. + [Parameter(ParameterSetName = 'MyRepos_Aff-Vis')] + [ValidateSet('all', 'public', 'private')] + [string] $Visibility = 'all', + + # Comma-separated list of values. Can include: + # - owner: Repositories that are owned by the authenticated user. + # - collaborator: Repositories that the user has been added to as a collaborator. + # - organization_member: Repositories that the user has access to through being a member of an organization. + # This includes every repository on every team that the user is on. + # Default: owner, collaborator, organization_member + [Parameter(ParameterSetName = 'MyRepos_Aff-Vis')] + [ValidateSet('owner', 'collaborator', 'organization_member')] + [string[]] $Affiliation = @('owner', 'collaborator', 'organization_member'), + + # A repository ID. Only return repositories with an ID greater than this ID. + [Parameter(ParameterSetName = 'ListByID')] + [int] $SinceID = 0, + + # Only show repositories updated after the given time. + [Parameter(ParameterSetName = 'MyRepos_Type')] + [Parameter(ParameterSetName = 'MyRepos_Aff-Vis')] + [datetime] $Since, + + # Only show repositories updated before the given time. + [Parameter(ParameterSetName = 'MyRepos_Type')] + [Parameter(ParameterSetName = 'MyRepos_Aff-Vis')] + [datetime] $Before, + + # The account owner of the repository. The name is not case sensitive. + [Parameter(ParameterSetName = 'ByName')] + [Parameter(ParameterSetName = 'ListByOrg')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter( + Mandatory, + ParameterSetName = 'ByName' + )] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The handle for the GitHub user account. + [Parameter( + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + ParameterSetName = 'ListByUser' + )] + [Alias('login')] + [string] $Username, + + # The property to sort the results by. + [Parameter(ParameterSetName = 'MyRepos_Type')] + [Parameter(ParameterSetName = 'MyRepos_Aff-Vis')] + [Parameter(ParameterSetName = 'ListByOrg')] + [Parameter(ParameterSetName = 'ListByUser')] + [ValidateSet('created', 'updated', 'pushed', 'full_name')] + [string] $Sort = 'created', + + # The order to sort by. + # Default: asc when using full_name, otherwise desc. + [Parameter(ParameterSetName = 'MyRepos')] + [Parameter(ParameterSetName = 'ListByOrg')] + [Parameter(ParameterSetName = 'ListByUser')] + [ValidateSet('asc', 'desc')] + [string] $Direction, + + # The number of results per page (max 100). + [Parameter(ParameterSetName = 'MyRepos')] + [Parameter(ParameterSetName = 'ListByOrg')] + [Parameter(ParameterSetName = 'ListByUser')] + [ValidateRange(1, 100)] + [int] $PerPage = 30 + + ) + + DynamicParam { + $DynamicParamDictionary = New-DynamicParamDictionary + + if ($PSCmdlet.ParameterSetName -in 'MyRepos_Type', 'ListByOrg', 'ListByUser') { + + switch ($PSCmdlet.ParameterSetName) { + 'MyRepos_Type' { + $ValidateSet = 'all', 'owner', 'public', 'private', 'member' + } + 'ListByOrg' { + $ValidateSet = 'all', 'public', 'private', 'forks', 'sources', 'member' + } + 'ListByUser' { + $ValidateSet = 'all', 'owner', 'member' + } + } + + $dynParam = @{ + Name = 'Type' + ParameterSetName = $PSCmdlet.ParameterSetName + Type = [string] + Mandatory = $false + ValidateSet = $ValidateSet + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam + } + + return $DynamicParamDictionary + } + + Begin { + $Type = $PSBoundParameters['Type'] + } + + Process { + switch ($PSCmdlet.ParameterSetName) { + 'MyRepos_Type' { + $params = @{ + Type = $Type + Sort = $Sort + Direction = $Direction + PerPage = $PerPage + Since = $Since + Before = $Before + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + Get-GitHubMyRepositories @params + } + 'MyRepos_Aff-Vis' { + $params = @{ + Visibility = $Visibility + Affiliation = $Affiliation + Sort = $Sort + Direction = $Direction + PerPage = $PerPage + Since = $Since + Before = $Before + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + Get-GitHubMyRepositories @params + } + 'ByName' { + $params = @{ + Owner = $Owner + Repo = $Repo + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + Get-GitHubRepositoryByName @params + } + 'ListByID' { + $params = @{ + Since = $SinceID + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + Get-GitHubRepositoryListByID @params + } + 'ListByOrg' { + $params = @{ + Owner = $Owner + Type = $Type + Sort = $Sort + Direction = $Direction + PerPage = $PerPage + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + Get-GitHubRepositoryListByOrg @params + } + 'ListByUser' { + $params = @{ + Username = $Username + Type = $Type + Sort = $Sort + Direction = $Direction + PerPage = $PerPage + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + Get-GitHubRepositoryListByUser @params + } + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryActivity.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryActivity.ps1 new file mode 100644 index 000000000..843ad2527 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryActivity.ps1 @@ -0,0 +1,135 @@ +filter Get-GitHubRepositoryActivity { + <# + .SYNOPSIS + List repository activities + + .DESCRIPTION + Lists a detailed history of changes to a repository, such as pushes, merges, force pushes, and branch changes, + and associates these changes with commits and users. + + For more information about viewing repository activity, + see "[Viewing activity and data for your repository](https://docs.github.com/repositories/viewing-activity-and-data-for-your-repository)." + + .EXAMPLE + Get-GitHubRepositoryActivity -Owner 'PSModule' -Repo 'GitHub' + + .EXAMPLE + Get-GitHubRepositoryActivity -Owner 'PSModule' -Repo 'GitHub' -Direction 'asc' + + .EXAMPLE + Get-GitHubRepositoryActivity -Owner 'PSModule' -Repo 'GitHub' -PerPage 100 + + .EXAMPLE + Get-GitHubRepositoryActivity -Owner 'PSModule' -Repo 'GitHub' -Before '2021-01-01T00:00:00Z' + + .EXAMPLE + Get-GitHubRepositoryActivity -Owner 'PSModule' -Repo 'GitHub' -After '2021-01-01T00:00:00Z' + + .EXAMPLE + Get-GitHubRepositoryActivity -Owner 'PSModule' -Repo 'GitHub' -Ref 'refs/heads/main' + + .EXAMPLE + Get-GitHubRepositoryActivity -Owner 'PSModule' -Repo 'GitHub' -Actor 'octocat' + + .EXAMPLE + $params = @{ + Owner = 'PSModule' + Repo = 'GitHub' + TimePeriod = 'day' + } + Get-GitHubRepositoryActivity @params | + Select-Object -Property @{n='actor';e={$_.actor.login}},activity_type,ref,timestamp + + Gets the activity for the past 24 hours and selects the actor, activity type, ref, and timestamp. + + .EXAMPLE + Get-GitHubRepositoryActivity -Owner 'PSModule' -Repo 'GitHub' -ActivityType 'push','force_push' + + .NOTES + https://docs.github.com/rest/repos/repos#list-repository-activities + + #> + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The direction to sort the results by. + [Parameter()] + [ValidateSet('asc', 'desc')] + [string] $Direction = 'desc', + + # The number of results per page (max 100). + # Default: 30 + [Parameter()] + [ValidateRange(1, 100)] + [Alias('per_page')] + [int] $PerPage = 30, + + # A cursor, as given in the Link header. If specified, the query only searches for results before this cursor. + [Parameter(ParameterSetName = 'BeforeAfter')] + [string] $Before, + + # A cursor, as given in the Link header. If specified, the query only searches for results after this cursor. + [Parameter(ParameterSetName = 'BeforeAfter')] + [string] $After, + + # The Git reference for the activities you want to list. + # The ref for a branch can be formatted either as refs/heads/BRANCH_NAME or BRANCH_NAME, where BRANCH_NAME is the name of your branch. + [Parameter()] + [string] $Ref, + + # The GitHub username to use to filter by the actor who performed the activity. + [Parameter()] + [string] $Actor, + + # The time period to filter by. + # For example,day will filter for activity that occurred in the past 24 hours, + # and week will filter for activity that occurred in the past 7 days (168 hours). + [Parameter()] + [ValidateSet('day', 'week', 'month', 'quarter', 'year')] + [Alias('time_period')] + [string] $TimePeriod, + + # The activity type to filter by. + # For example,you can choose to filter by 'force_push', to see all force pushes to the repository. + [Parameter()] + [ValidateSet('push', 'force_push', 'branch_creation', 'branch_deletion', 'pr_merge', 'merge_queue_merge')] + [Alias('activity_type')] + [string] $ActivityType + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/activity" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryCodeownersError.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryCodeownersError.ps1 new file mode 100644 index 000000000..656be4b29 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryCodeownersError.ps1 @@ -0,0 +1,66 @@ +filter Get-GitHubRepositoryCodeownersError { + <# + .SYNOPSIS + List CODEOWNERS errors + + .DESCRIPTION + List any syntax errors that are detected in the CODEOWNERS file. + + For more information about the correct CODEOWNERS syntax, + see "[About code owners](https://docs.github.com/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners)." + + .EXAMPLE + Get-GitHubRepositoryCodeownersError -Owner 'PSModule' -Repo 'GitHub' + + Gets the CODEOWNERS errors for the repository. + + .NOTES + https://docs.github.com/rest/repos/repos#list-codeowners-errors + + #> + [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # A branch, tag or commit name used to determine which version of the CODEOWNERS file to use. + # Default: the repository's default branch (e.g. main) + [Parameter()] + [string] $Ref + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/codeowners/errors" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryContributor.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryContributor.ps1 new file mode 100644 index 000000000..cce0d857e --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryContributor.ps1 @@ -0,0 +1,56 @@ +filter Get-GitHubRepositoryContributor { + <# + .SYNOPSIS + List repository contributors + + .DESCRIPTION + Lists contributors to the specified repository and sorts them by the number of commits per contributor in descending order. + This endpoint may return information that is a few hours old because the GitHub REST API caches contributor data to improve performance. + + GitHub identifies contributors by author email address. This endpoint groups contribution counts by GitHub user, + which includes all associated email addresses. To improve performance, only the first 500 author email addresses + in the repository link to GitHub users. The rest will appear as anonymous contributors without associated GitHub user information. + + .EXAMPLE + Get-GitHubRepositoryContributor -Owner 'PSModule' -Repo 'GitHub' + + Gets all contributors to the GitHub repository. + + .NOTES + https://docs.github.com/rest/repos/repos#list-repository-contributors + + #> + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # Wether to include anonymous contributors in results. + [Parameter()] + [switch] $Anon, + + # The number of results per page (max 100). + [Parameter()] + [ValidateRange(1, 100)] + [int] $PerPage = 30 + ) + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/contributors" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryFork.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryFork.ps1 new file mode 100644 index 000000000..6bd122670 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryFork.ps1 @@ -0,0 +1,68 @@ +filter Get-GitHubRepositoryFork { + <# + .SYNOPSIS + List forks + + .DESCRIPTION + List forks of a named repository. + + .EXAMPLE + Get-GitHubRepositoryFork -Owner 'octocat' -Repo 'Hello-World' + + List forks of the 'Hello-World' repository owned by 'octocat'. + + .NOTES + https://docs.github.com/rest/repos/forks#list-forks + + #> + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The direction to sort the results by. + [Parameter()] + [ValidateSet('newest', 'oldest', 'stargazers', 'watchers')] + [string] $Sort = 'newest', + + # The number of results per page. + [Parameter()] + [ValidateRange(1, 100)] + [Alias('per_page')] + [int] $PerPage = 30 + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/forks" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryLanguage.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryLanguage.ps1 new file mode 100644 index 000000000..e9b0ef81a --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryLanguage.ps1 @@ -0,0 +1,40 @@ +filter Get-GitHubRepositoryLanguage { + <# + .SYNOPSIS + List repository languages + + .DESCRIPTION + Lists languages for the specified repository. The value shown for each language is the number of + bytes of code written in that language. + + .EXAMPLE + Get-GitHubRepositoryLanguage -Owner 'octocat' -Repo 'hello-world' + + Gets the languages for the 'hello-world' repository owned by 'octocat'. + + .NOTES + https://docs.github.com/rest/repos/repos#list-repository-languages + + #> + [CmdletBinding()] + [Alias('Get-GitHubRepositoryLanguages')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/languages" + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositorySecurityFix.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositorySecurityFix.ps1 new file mode 100644 index 000000000..e2647fa3f --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositorySecurityFix.ps1 @@ -0,0 +1,41 @@ +filter Get-GitHubRepositorySecurityFix { + <# + .SYNOPSIS + Check if automated security fixes are enabled for a repository + + .DESCRIPTION + Shows whether automated security fixes are enabled, disabled or paused for a repository. + The authenticated user must have admin read access to the repository. For more information, see + "[Configuring automated security fixes](https://docs.github.com/articles/configuring-automated-security-fixes)". + + .EXAMPLE + Get-GitHubRepositorySecurityFix -Owner 'PSModule' -Repo 'GitHub' + + Gets the automated security fixes status for the GitHub repository. + + .NOTES + https://docs.github.com/rest/repos/repos#check-if-automated-security-fixes-are-enabled-for-a-repository + + #> + [CmdletBinding()] + [Alias('Get-GitHubRepoSecurityFixes')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/automated-security-fixes" + Method = 'GET' + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTag.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTag.ps1 new file mode 100644 index 000000000..8279c33bd --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTag.ps1 @@ -0,0 +1,48 @@ +filter Get-GitHubRepositoryTag { + <# + .SYNOPSIS + List repository tags + + .DESCRIPTION + List repository tags + + .EXAMPLE + Get-GitHubRepositoryTag -Owner 'PSModule' -Repo 'GitHub' + + Gets all tags of the GitHub repository. + + .NOTES + https://docs.github.com/rest/repos/repos#list-repository-tags + + #> + [CmdletBinding()] + [Alias('Get-GitHubRepositoryTags')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The number of results per page (max 100). + [Parameter()] + [ValidateRange(1, 100)] + [int] $PerPage = 30 + ) + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/tags" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTeam.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTeam.ps1 new file mode 100644 index 000000000..9b65bfcfa --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTeam.ps1 @@ -0,0 +1,56 @@ +filter Get-GitHubRepositoryTeam { + <# + .SYNOPSIS + List repository teams + + .DESCRIPTION + Lists the teams that have access to the specified repository and that are also visible to the authenticated user. + + For a public repository, a team is listed only if that team added the public repository explicitly. + + Personal access tokens require the following scopes: + * `public_repo` to call this endpoint on a public repository + * `repo` to call this endpoint on a private repository (this scope also includes public repositories) + + This endpoint is not compatible with fine-grained personal access tokens. + + .EXAMPLE + Get-GitHubRepositoryTeam -Owner 'PSModule' -Repo 'GitHub' + + Lists the teams that have access to the specified repository and that are also visible to the authenticated user. + + .NOTES + https://docs.github.com/rest/repos/repos#list-repository-teams + + #> + [CmdletBinding()] + [Alias('Get-GitHubRepositoryTeams')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The number of results per page (max 100). + [Parameter()] + [ValidateRange(1, 100)] + [int] $PerPage = 30 + ) + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/teams" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTopic.ps1 b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTopic.ps1 new file mode 100644 index 000000000..abeefb20a --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Get-GitHubRepositoryTopic.ps1 @@ -0,0 +1,44 @@ +filter Get-GitHubRepositoryTopic { + <# + .SYNOPSIS + Get all repository topics + + .DESCRIPTION + Get all repository topics + + .EXAMPLE + + .NOTES + https://docs.github.com/rest/repos/repos#get-all-repository-topics + + #> + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The number of results per page (max 100). + [Parameter()] + [ValidateRange(1, 100)] + [int] $PerPage = 30 + ) + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/topics" + Method = 'GET' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response.names + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Move-GitHubRepository.ps1 b/src/GitHub/public/Repositories/Repositories/Move-GitHubRepository.ps1 new file mode 100644 index 000000000..f5e61c61f --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Move-GitHubRepository.ps1 @@ -0,0 +1,77 @@ +filter Move-GitHubRepository { + <# + .SYNOPSIS + Transfer a repository + + .DESCRIPTION + A transfer request will need to be accepted by the new owner when transferring a personal repository to another user. + The response will contain the original `owner`, and the transfer will continue asynchronously. For more details on + the requirements to transfer personal and organization-owned repositories, see + [about repository transfers](https://docs.github.com/articles/about-repository-transfers/). + You must use a personal access token (classic) or an OAuth token for this endpoint. An installation access token or + a fine-grained personal access token cannot be used because they are only granted access to a single account. + + .EXAMPLE + Move-GitHubRepository -Owner 'PSModule' -Repo 'GitHub' -NewOwner 'GitHub' -NewName 'PowerShell' + + Moves the GitHub repository to the PSModule organization and renames it to GitHub. + + .NOTES + https://docs.github.com/rest/repos/repos#transfer-a-repository + + #> + [CmdletBinding()] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The username or organization name the repository will be transferred to. + [Parameter(Mandatory)] + [Alias('new_owner')] + [string] $NewOwner, + + # The new name to be given to the repository. + [Parameter()] + [Alias('new_name')] + [string] $NewName, + + # ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories. + [Parameter()] + [Alias('team_ids')] + [int[]] $TeamIds + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/transfer" + Method = 'POST' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/New-GitHubRepository.ps1 b/src/GitHub/public/Repositories/Repositories/New-GitHubRepository.ps1 new file mode 100644 index 000000000..16b9ead25 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/New-GitHubRepository.ps1 @@ -0,0 +1,403 @@ +filter New-GitHubRepository { + <# + .SYNOPSIS + Create a repository for a user or an organization. + + .DESCRIPTION + Creates a new repository for a user or in a specified organization. + + **OAuth scope requirements** + + When using [OAuth](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/), authorizations must include: + + * `public_repo` scope or `repo` scope to create a public repository. Note: For GitHub AE, use `repo` scope to create an internal repository. + * `repo` scope to create a private repository + + + .EXAMPLE + $params = @{ + Name = 'Hello-World' + Description = 'This is your first repository' + Homepage = 'https://github.com' + HasIssues = $true + HasProjects = $true + HasWiki = $true + HasDiscussions = $true + HasDownloads = $true + IsTemplate = $true + AutoInit = $true + AllowSquashMerge = $true + AllowAutoMerge = $true + DeleteBranchOnMerge = $true + SquashMergeCommitTitle = 'PR_TITLE' + SquashMergeCommitMessage = 'PR_BODY' + } + New-GitHubRepository @params + + Creates a new public repository named "Hello-World" owned by the authenticated user. + + .EXAMPLE + $params = @{ + Owner = 'PSModule' + Name = 'Hello-World' + Description = 'This is your first repository' + Homepage = 'https://github.com' + HasIssues = $true + HasProjects = $true + HasWiki = $true + HasDownloads = $true + IsTemplate = $true + AutoInit = $true + AllowSquashMerge = $true + AllowAutoMerge = $true + DeleteBranchOnMerge = $true + SquashMergeCommitTitle = 'PR_TITLE' + SquashMergeCommitMessage = 'PR_BODY' + } + New-GitHubRepository @params + + Creates a new public repository named "Hello-World" owned by the organization "PSModule". + + .EXAMPLE + $params = @{ + TemplateOwner = 'GitHub' + TemplateRepo = 'octocat' + Owner = 'PSModule' + Name = 'MyNewRepo' + IncludeAllBranches = $true + Description = 'My new repo' + Private = $true + } + New-GitHubRepository @params + + Creates a new private repository named `MyNewRepo` from the `octocat` template repository owned by `GitHub`. + + .EXAMPLE + $params = @{ + ForkOwner = 'octocat' + ForkRepo = 'Hello-World' + Owner = 'PSModule' + Name = 'MyNewRepo' + DefaultBranchOnly = $true + } + New-GitHubRepository @params + + Creates a new repository named `MyNewRepo` as a fork of `Hello-World` owned by `octocat`. + Only the default branch will be forked. + + .NOTES + https://docs.github.com/rest/repos/repos#create-a-repository-using-a-template + + + .PARAMETER GitignoreTemplate + Desired language or platform .gitignore template to apply. Use the name of the template without the extension. For example, "Haskell". + + .PARAMETER LicenseTemplate + Choose an open source license template that best suits your needs, and then use the license keyword as the license_template string. + For example, "mit" or "mpl-2.0". + + .NOTES + https://docs.github.com/rest/repos/repos#create-a-repository-for-the-authenticated-user + https://docs.github.com/rest/repos/repos#create-an-organization-repository + + #> + [OutputType([pscustomobject])] + [CmdletBinding( + SupportsShouldProcess, + DefaultParameterSetName = 'user' + )] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter(ParameterSetName = 'org')] + [Parameter(ParameterSetName = 'fork')] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository. + [Parameter(ParameterSetName = 'fork')] + [Parameter(Mandatory, ParameterSetName = 'user')] + [Parameter(Mandatory, ParameterSetName = 'org')] + [Parameter(Mandatory, ParameterSetName = 'template')] + [string] $Name, + + # The account owner of the template repository. The name is not case sensitive. + [Parameter( + Mandatory, + ParameterSetName = 'template' + )] + [Alias('template_owner')] + [string] $TemplateOwner, + + # The name of the template repository without the .git extension. The name is not case sensitive. + [Parameter( + Mandatory, + ParameterSetName = 'template' + )] + [Alias('template_repo')] + [string] $TemplateRepo, + + # The account owner of the repository. The name is not case sensitive. + [Parameter( + Mandatory, + ParameterSetName = 'fork' + )] + [string] $ForkOwner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter( + Mandatory, + ParameterSetName = 'fork' + )] + [string] $ForkRepo, + + # When forking from an existing repository, fork with only the default branch. + [Parameter(ParameterSetName = 'fork')] + [Alias('default_branch_only')] + [switch] $DefaultBranchOnly, + + # A short description of the new repository. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Parameter(ParameterSetName = 'template')] + [string] $Description, + + # Set to true to include the directory structure and files from all branches in the template repository, + # and not just the default branch. + [Parameter(ParameterSetName = 'template')] + [Alias('include_all_branches')] + [switch] $IncludeAllBranches, + + # A URL with more information about the repository. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [ValidateNotNullOrEmpty()] + [uri] $Homepage, + + # The visibility of the repository. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Parameter(ParameterSetName = 'template')] + [ValidateSet('public', 'private')] + [string] $Visibility = 'public', + + # Whether issues are enabled. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('has_issues')] + [switch] $HasIssues, + + # Whether projects are enabled. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('has_projects')] + [switch] $HasProjects, + + # Whether the wiki is enabled. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('has_wiki')] + [switch] $HasWiki, + + # Whether discussions are enabled. + [Parameter(ParameterSetName = 'user')] + [Alias('has_discussions')] + [switch] $HasDiscussions, + + # Whether downloads are enabled. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('has_downloads')] + [switch] $HasDownloads, + + # Whether this repository acts as a template that can be used to generate new repositories. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('is_template')] + [switch] $IsTemplate, + + # The id of the team that will be granted access to this repository. This is only valid when creating a repository in an organization. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('team_id')] + [int] $TeamId, + + # Pass true to create an initial commit with empty README. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('auto_init')] + [switch] $AutoInit, + + # Whether to allow squash merges for pull requests. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('allow_squash_merge')] + [switch] $AllowSquashMerge, + + # Whether to allow merge commits for pull requests. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('allow_merge_commit')] + [switch] $AllowMergeCommit, + + # Whether to allow rebase merges for pull requests. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('allow_rebase_merge')] + [switch] $AllowRebaseMerge, + + # Whether to allow Auto-merge to be used on pull requests. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('allow_auto_merge')] + [switch] $AllowAutoMerge, + + # Whether to delete head branches when pull requests are merged + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [Alias('delete_branch_on_merge')] + [switch] $DeleteBranchOnMerge, + + # The default value for a squash merge commit title: + # - PR_TITLE - default to the pull request's title. + # - COMMIT_OR_PR_TITLE - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [ValidateSet('PR_TITLE', 'COMMIT_OR_PR_TITLE')] + [Alias('squash_merge_commit_title')] + [string] $SquashMergeCommitTitle, + + # The default value for a squash merge commit message: + # - PR_BODY - default to the pull request's body. + # - COMMIT_MESSAGES - default to the branch's commit messages. + # - BLANK - default to a blank commit message. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [ValidateSet('PR_BODY', 'COMMIT_MESSAGES', 'BLANK')] + [Alias('squash_merge_commit_message')] + [string] $SquashMergeCommitMessage, + + # The default value for a merge commit title. + # - PR_TITLE - default to the pull request's title. + # - MERGE_MESSAGE - default to the classic title for a merge message (e.g.,Merge pull request #123 from branch-name). + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [ValidateSet('PR_TITLE', 'MERGE_MESSAGE')] + [Alias('merge_commit_title')] + [string] $MergeCommitTitle, + + # The default value for a merge commit message. + # - PR_BODY - default to the pull request's body. + # - PR_TITLE - default to the pull request's title. + # - BLANK - default to a blank commit message. + [Parameter(ParameterSetName = 'user')] + [Parameter(ParameterSetName = 'org')] + [ValidateSet('PR_BODY', 'PR_TITLE', 'BLANK')] + [Alias('merge_commit_message')] + [string] $MergeCommitMessage + ) + + DynamicParam { + $DynamicParamDictionary = New-DynamicParamDictionary + + $dynParam = @{ + Name = 'GitignoreTemplate' + Alias = 'gitignore_template' + Type = [string] + ValidateSet = Get-GitHubGitignoreList + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam + + $dynParam2 = @{ + Name = 'LicenseTemplate' + Alias = 'license_template' + Type = [string] + ValidateSet = Get-GitHubLicenseList | Select-Object -ExpandProperty key + DynamicParamDictionary = $DynamicParamDictionary + } + New-DynamicParam @dynParam2 + + return $DynamicParamDictionary + } + + begin { + $GitignoreTemplate = $PSBoundParameters['GitignoreTemplate'] + $LicenseTemplate = $PSBoundParameters['LicenseTemplate'] + } + + Process { + if ($PSCmdlet.ParameterSetName -in 'user', 'org') { + $params = @{ + Owner = $Owner + Name = $Name + Description = $Description + Homepage = $Homepage + Visibility = $Visibility + HasIssues = $HasIssues + HasProjects = $HasProjects + HasWiki = $HasWiki + HasDiscussions = $HasDiscussions + HasDownloads = $HasDownloads + IsTemplate = $IsTemplate + TeamId = $TeamId + AutoInit = $AutoInit + AllowSquashMerge = $AllowSquashMerge + AllowMergeCommit = $AllowMergeCommit + AllowRebaseMerge = $AllowRebaseMerge + AllowAutoMerge = $AllowAutoMerge + DeleteBranchOnMerge = $DeleteBranchOnMerge + SquashMergeCommitTitle = $SquashMergeCommitTitle + SquashMergeCommitMessage = $SquashMergeCommitMessage + MergeCommitTitle = $MergeCommitTitle + MergeCommitMessage = $MergeCommitMessage + GitignoreTemplate = $GitignoreTemplate + LicenseTemplate = $LicenseTemplate + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + } + + switch ($PSCmdlet.ParameterSetName) { + 'user' { + if ($PSCmdlet.ShouldProcess("repository for user [$Name]", 'Create')) { + New-GitHubRepositoryUser @params + } + } + 'org' { + if ($PSCmdlet.ShouldProcess("repository for organization [$Owner/$Name]", 'Create')) { + New-GitHubRepositoryOrg @params + } + } + 'template' { + if ($PSCmdlet.ShouldProcess("repository [$Owner/$Name] from template [$TemplateOwner/$TemplateRepo]", 'Create')) { + $params = @{ + TemplateOwner = $TemplateOwner + TemplateRepo = $TemplateRepo + Owner = $Owner + Name = $Name + IncludeAllBranches = $IncludeAllBranches + Description = $Description + Private = $Visibility -eq 'private' + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + New-GitHubRepositoryFromTemplate @params + } + } + 'fork' { + if ([string]::IsNullorEmpty($Name)) { + $Name = $ForkRepo + } + if ($PSCmdlet.ShouldProcess("repository [$Owner/$Name] as fork from [$ForkOwner/$ForkRepo]", 'Create')) { + $params = @{ + Owner = $ForkOwner + Repo = $ForkRepo + Organization = $Owner + Name = $Name + DefaultBranchOnly = $DefaultBranchOnly + } + Remove-HashtableEntry -Hashtable $params -NullOrEmptyValues + New-GitHubRepositoryAsFork @params + } + } + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Remove-GitHubRepository.ps1 b/src/GitHub/public/Repositories/Repositories/Remove-GitHubRepository.ps1 new file mode 100644 index 000000000..b993f0508 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Remove-GitHubRepository.ps1 @@ -0,0 +1,44 @@ +filter Remove-GitHubRepository { + <# + .SYNOPSIS + Delete a repository + + .DESCRIPTION + Deleting a repository requires admin access. If OAuth is used, the `delete_repo` scope is required. + + If an organization owner has configured the organization to prevent members from deleting organization-owned + repositories, you will get a `403 Forbidden` response. + + .EXAMPLE + Remove-GitHubRepository -Owner 'PSModule' -Repo 'Hello-World' + + Deletes the repository `Hello-World` in the `PSModule` organization. + + .NOTES + https://docs.github.com/rest/repos/repos#delete-a-repository + #> + [CmdletBinding(SupportsShouldProcess)] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter(Mandatory)] + [Alias('org')] + [Alias('login')] + [string] $Owner, + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter(Mandatory)] + [string] $Repo + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo" + Method = 'DELETE' + } + + if ($PSCmdlet.ShouldProcess("repo [$Owner/$Repo]", 'Delete')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } + +} diff --git a/src/GitHub/public/Repositories/Repositories/Set-GitHubRepositoryTopic.ps1 b/src/GitHub/public/Repositories/Repositories/Set-GitHubRepositoryTopic.ps1 new file mode 100644 index 000000000..58cd803be --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Set-GitHubRepositoryTopic.ps1 @@ -0,0 +1,50 @@ +filter Set-GitHubRepositoryTopic { + <# + .SYNOPSIS + Replace all repository topics + + .DESCRIPTION + Replace all repository topics + + .EXAMPLE + Set-GitHubRepositoryTopic -Owner 'octocat' -Repo 'hello-world' -Names 'octocat', 'octo', 'octocat/hello-world' + + Replaces all topics for the repository 'octocat/hello-world' with the topics 'octocat', 'octo', 'octocat/hello-world'. + + .NOTES + https://docs.github.com/rest/repos/repos#replace-all-repository-topics + #> + [CmdletBinding(SupportsShouldProcess)] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The number of results per page (max 100). + [Parameter()] + [Alias('Topics')] + [string[]] $Names = @() + ) + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $body.names = $body.names | ForEach-Object { $_.ToLower() } + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/topics" + Method = 'PUT' + Body = $body + } + + if ($PSCmdlet.ShouldProcess("topics for repo [$Owner/$Repo]", 'Set')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response.names + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Start-GitHubRepositoryEvent.ps1 b/src/GitHub/public/Repositories/Repositories/Start-GitHubRepositoryEvent.ps1 new file mode 100644 index 000000000..3cc74eb50 --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Start-GitHubRepositoryEvent.ps1 @@ -0,0 +1,94 @@ +filter Start-GitHubRepositoryEvent { + <# + .SYNOPSIS + Create a repository dispatch event + + .DESCRIPTION + You can use this endpoint to trigger a webhook event called `repository_dispatch` when you want activity + that happens outside of GitHub to trigger a GitHub Actions workflow or GitHub App webhook. You must configure + your GitHub Actions workflow or GitHub App to run when the `repository_dispatch` + event occurs. For an example `repository_dispatch` webhook payload, see + "[RepositoryDispatchEvent](https://docs.github.com/webhooks/event-payloads/#repository_dispatch)." + + The `client_payload` parameter is available for any extra information that your workflow might need. + This parameter is a JSON payload that will be passed on when the webhook event is dispatched. For example, + the `client_payload` can include a message that a user would like to send using a GitHub Actions workflow. + Or the `client_payload` can be used as a test to debug your workflow. + + This endpoint requires write access to the repository by providing either: + + - Personal access tokens with `repo` scope. For more information, see + "[Creating a personal access token for the command line](https://docs.github.com/articles/creating-a-personal-access-token-for-the-command-line)" + in the GitHub Help documentation. + - GitHub Apps with both `metadata:read` and `contents:read&write` permissions. + + This input example shows how you can use the `client_payload` as a test to debug your workflow. + + .EXAMPLE + $params = @{ + EventType = 'on-demand-test' + ClientPayload = @{ + unit = false + integration = true + } + } + Start-GitHubRepositoryEvent @params + + Starts a repository event with the name `on-demand-test` and a `client_payload` that includes `unit` and `integration`. + + .NOTES + https://docs.github.com/rest/repos/repos#create-a-repository-dispatch-event + + #> + [CmdletBinding(SupportsShouldProcess)] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Long links')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # A custom webhook event name. Must be 100 characters or fewer. + [Parameter(Mandatory)] + [Alias('event_type')] + [string] $EventType, + + # JSON payload with extra information about the webhook event that your action or workflow may use. + # The maximum number of top-level properties is 10. + [Parameter()] + [Alias('client_payload')] + [object] $ClientPayload + ) + + $PSCmdlet.MyInvocation.MyCommand.Parameters.GetEnumerator() | ForEach-Object { + $paramName = $_.Key + $paramDefaultValue = Get-Variable -Name $paramName -ValueOnly -ErrorAction SilentlyContinue + $providedValue = $PSBoundParameters[$paramName] + Write-Verbose "[$paramName]" + Write-Verbose " - Default: [$paramDefaultValue]" + Write-Verbose " - Provided: [$providedValue]" + if (-not $PSBoundParameters.ContainsKey($paramName) -and ($null -ne $paramDefaultValue)) { + Write-Verbose ' - Using default value' + $PSBoundParameters[$paramName] = $paramDefaultValue + } else { + Write-Verbose ' - Using provided value' + } + } + + $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case + Remove-HashtableEntry -Hashtable $body -RemoveNames 'Owner', 'Repo' -RemoveTypes 'SwitchParameter' + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/dispatches" + Method = 'POST' + Body = $body + } + + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Test-GitHubRepositoryVulnerabilityAlert.ps1 b/src/GitHub/public/Repositories/Repositories/Test-GitHubRepositoryVulnerabilityAlert.ps1 new file mode 100644 index 000000000..b9cca9ade --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Test-GitHubRepositoryVulnerabilityAlert.ps1 @@ -0,0 +1,49 @@ +filter Test-GitHubRepositoryVulnerabilityAlert { + <# + .SYNOPSIS + Check if vulnerability alerts are enabled for a repository + + .DESCRIPTION + Shows whether dependency alerts are enabled or disabled for a repository. + The authenticated user must have admin read access to the repository. + For more information, see + "[About security alerts for vulnerable dependencies](https://docs.github.com/articles/about-security-alerts-for-vulnerable-dependencies)". + + .EXAMPLE + Test-GitHubRepositoryVulnerabilityAlert -Owner 'PSModule' -Repo 'GitHub' + + Checks if vulnerability alerts are enabled for the PSModule/GitHub repository. + + .NOTES + https://docs.github.com/rest/repos/repos#list-repository-tags + + #> + [OutputType([bool])] + [CmdletBinding()] + [Alias('Test-GitHubRepositoryVulnerabilityAlerts')] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo) + ) + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo/vulnerability-alerts" + Method = 'GET' + } + + try { + (Invoke-GitHubAPI @inputObject).StatusCode -eq 204 + } catch { + if ($_.Exception.Response.StatusCode.Value__ -eq 404) { + return $false + } else { + throw $_ + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/Update-GitHubRepository.ps1 b/src/GitHub/public/Repositories/Repositories/Update-GitHubRepository.ps1 new file mode 100644 index 000000000..0f4e09f1b --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/Update-GitHubRepository.ps1 @@ -0,0 +1,225 @@ +filter Update-GitHubRepository { + <# + .SYNOPSIS + Update a repository + + .DESCRIPTION + **Note**: To edit a repository's topics, use the + [Replace all repository topics](https://docs.github.com/rest/repos/repos#replace-all-repository-topics) endpoint. + + .EXAMPLE + Update-GitHubRepository -Name 'octocat' -Description 'Hello-World' -Homepage 'https://github.com' + + .EXAMPLE + $params = @{ + Owner = 'octocat' + Repo = 'Hello-World' + name = 'Hello-World-Repo + description = 'This is your first repository' + homepage = 'https://github.com' + } + Update-GitHubRepository @params + + .NOTES + https://docs.github.com/rest/repos/repos#update-a-repository + + #> + [CmdletBinding(SupportsShouldProcess)] + param ( + # The account owner of the repository. The name is not case sensitive. + [Parameter()] + [Alias('org')] + [string] $Owner = (Get-GitHubConfig -Name Owner), + + # The name of the repository without the .git extension. The name is not case sensitive. + [Parameter()] + [string] $Repo = (Get-GitHubConfig -Name Repo), + + # The name of the repository. + [Parameter()] + [string] $Name, + + # A short description of the repository. + [Parameter()] + [string] $Description, + + # A URL with more information about the repository. + [Parameter()] + [uri] $Homepage, + + # The visibility of the repository. + [Parameter()] + [ValidateSet('public', 'private')] + [string] $Visibility, + + # Use the status property to enable or disable GitHub Advanced Security for this repository. + # For more information, see "About GitHub Advanced Security." + [Parameter()] + [switch] $EnableAdvancedSecurity, + + # Use the status property to enable or disable secret scanning for this repository. + # For more information, see "About secret scanning." + [Parameter()] + [switch] $EnableSecretScanning, + + # Use the status property to enable or disable secret scanning push protection for this repository. + # For more information, see "Protecting pushes with secret scanning." + [Parameter()] + [switch] $EnableSecretScanningPushProtection, + + # Whether issues are enabled. + [Parameter()] + [Alias('has_issues')] + [switch] $HasIssues, + + # Whether projects are enabled. + [Parameter()] + [Alias('has_projects')] + [switch] $HasProjects, + + # Whether the wiki is enabled. + [Parameter()] + [Alias('has_wiki')] + [switch] $HasWiki, + + # Whether this repository acts as a template that can be used to generate new repositories. + [Parameter()] + [Alias('is_template')] + [switch] $IsTemplate, + + # Updates the default branch for this repository. + [Parameter()] + [Alias('default_branch')] + [string] $DefaultBranch, + + # Whether to allow squash merges for pull requests. + [Parameter()] + [Alias('allow_squash_merge')] + [switch] $AllowSquashMerge, + + # Whether to allow merge commits for pull requests. + [Parameter()] + [Alias('allow_merge_commit')] + [switch] $AllowMergeCommit, + + # Whether to allow rebase merges for pull requests. + [Parameter()] + [Alias('allow_rebase_merge')] + [switch] $AllowRebaseMerge, + + # Whether to allow Auto-merge to be used on pull requests. + [Parameter()] + [Alias('allow_auto_merge')] + [switch] $AllowAutoMerge, + + # Whether to delete head branches when pull requests are merged + [Parameter()] + [Alias('delete_branch_on_merge')] + [switch] $DeleteBranchOnMerge, + + # Either true to always allow a pull request head branch that is behind its base branch + # to be updated even if it is not required to be up to date before merging, or false otherwise. + [Parameter()] + [Alias('allow_update_branch')] + [switch] $AllowUpdateMerge, + + # The default value for a squash merge commit title: + # - PR_TITLE - default to the pull request's title. + # - COMMIT_OR_PR_TITLE - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + [Parameter()] + [ValidateSet('PR_TITLE', 'COMMIT_OR_PR_TITLE')] + [Alias('squash_merge_commit_title')] + [string] $SquashMergeCommitTitle, + + # The default value for a squash merge commit message: + # - PR_BODY - default to the pull request's body. + # - COMMIT_MESSAGES - default to the branch's commit messages. + # - BLANK - default to a blank commit message. + [Parameter()] + [ValidateSet('PR_BODY', 'COMMIT_MESSAGES', 'BLANK')] + [Alias('squash_merge_commit_message')] + [string] $SquashMergeCommitMessage, + + # The default value for a merge commit title. + # - PR_TITLE - default to the pull request's title. + # - MERGE_MESSAGE - default to the classic title for a merge message (e.g.,Merge pull request #123 from branch-name). + [Parameter()] + [ValidateSet('PR_TITLE', 'MERGE_MESSAGE')] + [Alias('merge_commit_title')] + [string] $MergeCommitTitle, + + # The default value for a merge commit message. + # - PR_BODY - default to the pull request's body. + # - PR_TITLE - default to the pull request's title. + # - BLANK - default to a blank commit message. + [Parameter()] + [ValidateSet('PR_BODY', 'PR_TITLE', 'BLANK')] + [Alias('merge_commit_message')] + [string] $MergeCommitMessage, + + # Whether to archive this repository. false will unarchive a previously archived repository. + [Parameter()] + [switch] $Archived, + + # Either true to allow private forks, or false to prevent private forks. + [Parameter()] + [Alias('allow_forking')] + [switch] $AllowForking, + + # Either true to require contributors to sign off on web-based commits, + # or false to not require contributors to sign off on web-based commits. + [Parameter()] + [Alias('web_commit_signoff_required')] + [switch] $WebCommitSignoffRequired + ) + + $body = @{ + name = $Name + description = $Description + homepage = $Homepage + visibility = $Visibility + private = $Visibility -eq 'private' + default_branch = $DefaultBranch + squash_merge_commit_title = $SquashMergeCommitTitle + squash_merge_commit_message = $SquashMergeCommitMessage + merge_commit_title = $MergeCommitTitle + merge_commit_message = $MergeCommitMessage + + advanced_security = $EnableAdvancedSecurity.IsPresent ? @{ + status = $EnableAdvancedSecurity ? 'enabled' : 'disabled' + } : $null + secret_scanning = $EnableSecretScanning.IsPresent ? @{ + status = $EnableSecretScanning ? 'enabled' : 'disabled' + } : $null + secret_scanning_push_protection = $EnableSecretScanningPushProtection.IsPresent ? @{ + status = $EnableSecretScanningPushProtection ? 'enabled' : 'disabled' + } : $null + has_issues = $HasIssues.IsPresent ? $HasIssues : $null + has_projects = $HasProjects.IsPresent ? $HasProjects : $null + has_wiki = $HasWiki.IsPresent ? $HasWiki : $null + is_template = $IsTemplate.IsPresent ? $IsTemplate : $null + allow_squash_merge = $AllowSquashMerge.IsPresent ? $AllowSquashMerge : $null + allow_merge_commit = $AllowMergeCommit.IsPresent ? $AllowMergeCommit : $null + allow_rebase_merge = $AllowRebaseMerge.IsPresent ? $AllowRebaseMerge : $null + allow_auto_merge = $AllowAutoMerge.IsPresent ? $AllowAutoMerge : $null + allow_update_branch = $AllowUpdateMerge.IsPresent ? $AllowUpdateMerge : $null + delete_branch_on_merge = $DeleteBranchOnMerge.IsPresent ? $DeleteBranchOnMerge : $null + archived = $Archived.IsPresent ? $Archived : $null + allow_forking = $AllowForking.IsPresent ? $AllowForking : $null + web_commit_signoff_required = $WebCommitSignoffRequired.IsPresent ? $WebCommitSignoffRequired : $null + } + + Remove-HashtableEntry -Hashtable $body -NullOrEmptyValues + + $inputObject = @{ + APIEndpoint = "/repos/$Owner/$Repo" + Method = 'PATCH' + Body = $body + } + + if ($PSCmdlet.ShouldProcess("Repository [$Owner/$Repo]", 'Update')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } +} diff --git a/src/GitHub/public/Repositories/Repositories/remaining.txt b/src/GitHub/public/Repositories/Repositories/remaining.txt new file mode 100644 index 000000000..65b1d577b --- /dev/null +++ b/src/GitHub/public/Repositories/Repositories/remaining.txt @@ -0,0 +1 @@ +Create a repository dispatch event diff --git a/src/GitHub/public/Status/Get-GitHubStatus.ps1 b/src/GitHub/public/Status/Get-GitHubStatus.ps1 index 9b7f0e1d7..04c0088a4 100644 --- a/src/GitHub/public/Status/Get-GitHubStatus.ps1 +++ b/src/GitHub/public/Status/Get-GitHubStatus.ps1 @@ -4,8 +4,11 @@ Gets the status of GitHub services .DESCRIPTION - Get a summary of the status page, including a status indicator, component statuses, unresolved incidents, and any upcoming or in-progress scheduled maintenances. - Get the status rollup for the whole page. This endpoint includes an indicator - one of none, minor, major, or critical, as well as a human description of the blended component status. Examples of the blended status include "All Systems Operational", "Partial System Outage", and "Major Service Outage". + Get a summary of the status page, including a status indicator, component statuses, unresolved incidents, + and any upcoming or in-progress scheduled maintenances. Get the status rollup for the whole page. This endpoint + includes an indicator - one of none, minor, major, or critical, as well as a human description of the blended + component status. Examples of the blended status include "All Systems Operational", "Partial System Outage", + and "Major Service Outage". .EXAMPLE Get-GitHubStatus @@ -15,7 +18,8 @@ .EXAMPLE Get-GitHubStatus -Summary - Gets a summary of the status page, including a status indicator, component statuses, unresolved incidents, and any upcoming or in-progress scheduled maintenances. + Gets a summary of the status page, including a status indicator, component statuses, unresolved incidents, + and any upcoming or in-progress scheduled maintenances. .NOTES https://www.githubstatus.com/api#summary @@ -24,7 +28,8 @@ [OutputType([pscustomobject])] [CmdletBinding()] param( - # Gets a summary of the status page, including a status indicator, component statuses, unresolved incidents, and any upcoming or in-progress scheduled maintenances. + # Gets a summary of the status page, including a status indicator, component statuses, unresolved incidents, + # and any upcoming or in-progress scheduled maintenances. [Parameter()] [switch] $Summary ) diff --git a/src/GitHub/public/Status/Get-GitHubStatusComponents.ps1 b/src/GitHub/public/Status/Get-GitHubStatusComponent.ps1 similarity index 69% rename from src/GitHub/public/Status/Get-GitHubStatusComponents.ps1 rename to src/GitHub/public/Status/Get-GitHubStatusComponent.ps1 index 9da591488..c646aae66 100644 --- a/src/GitHub/public/Status/Get-GitHubStatusComponents.ps1 +++ b/src/GitHub/public/Status/Get-GitHubStatusComponent.ps1 @@ -1,13 +1,14 @@ -function Get-GitHubStatusComponents { +function Get-GitHubStatusComponent { <# .SYNOPSIS Gets the status of GitHub components .DESCRIPTION - Get the components for the page. Each component is listed along with its status - one of operational, degraded_performance, partial_outage, or major_outage. + Get the components for the page. Each component is listed along with its status - one of operational, + degraded_performance, partial_outage, or major_outage. .EXAMPLE - Get-GitHubStatusComponents + Get-GitHubStatusComponent Gets the status of GitHub components @@ -15,6 +16,7 @@ https://www.githubstatus.com/api#components #> [OutputType([pscustomobject[]])] + [Alias('Get-GitHubStatusComponents')] [CmdletBinding()] param() diff --git a/src/GitHub/public/Status/Get-GitHubStatusIncidents.ps1 b/src/GitHub/public/Status/Get-GitHubStatusIncident.ps1 similarity index 89% rename from src/GitHub/public/Status/Get-GitHubStatusIncidents.ps1 rename to src/GitHub/public/Status/Get-GitHubStatusIncident.ps1 index 3c5a5bf2f..ac2085ef4 100644 --- a/src/GitHub/public/Status/Get-GitHubStatusIncidents.ps1 +++ b/src/GitHub/public/Status/Get-GitHubStatusIncident.ps1 @@ -1,4 +1,4 @@ -function Get-GitHubStatusIncidents { +function Get-GitHubStatusIncident { <# .SYNOPSIS Gets the status of GitHub incidents @@ -12,12 +12,12 @@ Impact: None (black), Minor (yellow), Major (orange), or Critical (red) .EXAMPLE - Get-GitHubStatusIncidents + Get-GitHubStatusIncident Gets the status of GitHub incidents .EXAMPLE - Get-GitHubStatusIncidents -Unresolved + Get-GitHubStatusIncident -Unresolved Gets the status of GitHub incidents that are unresolved @@ -25,6 +25,7 @@ https://www.githubstatus.com/api#incidents #> [OutputType([pscustomobject[]])] + [Alias('Get-GitHubStatusIncidents')] [CmdletBinding()] param( # Gets the status of GitHub incidents that are unresolved diff --git a/src/GitHub/public/Teams/Get-GitHubRepoTeam.ps1 b/src/GitHub/public/Teams/Get-GitHubRepoTeam.ps1 index c07dd89f1..10b17a1df 100644 --- a/src/GitHub/public/Teams/Get-GitHubRepoTeam.ps1 +++ b/src/GitHub/public/Teams/Get-GitHubRepoTeam.ps1 @@ -17,6 +17,8 @@ filter Get-GitHubRepoTeam { APIEndpoint = "/repos/$Owner/$Repo/teams" } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Users/Blocking/Block-GitHubUser.ps1 b/src/GitHub/public/Users/Blocking/Block-GitHubUser.ps1 index 1a469cf4b..9e71bc02f 100644 --- a/src/GitHub/public/Users/Blocking/Block-GitHubUser.ps1 +++ b/src/GitHub/public/Users/Blocking/Block-GitHubUser.ps1 @@ -42,7 +42,6 @@ )] [Alias('org')] [Alias('owner')] - [Alias('login')] [string] $OrganizationName ) diff --git a/src/GitHub/public/Users/Blocking/Get-GitHubBlockedUser.ps1 b/src/GitHub/public/Users/Blocking/Get-GitHubBlockedUser.ps1 index 664fea731..59f0d3345 100644 --- a/src/GitHub/public/Users/Blocking/Get-GitHubBlockedUser.ps1 +++ b/src/GitHub/public/Users/Blocking/Get-GitHubBlockedUser.ps1 @@ -35,6 +35,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Users/Blocking/Test-GitHubBlockedUser.ps1 b/src/GitHub/public/Users/Blocking/Test-GitHubBlockedUser.ps1 index 7484d2be2..62dbd99d6 100644 --- a/src/GitHub/public/Users/Blocking/Test-GitHubBlockedUser.ps1 +++ b/src/GitHub/public/Users/Blocking/Test-GitHubBlockedUser.ps1 @@ -42,11 +42,11 @@ )] [Alias('org')] [Alias('owner')] - [Alias('login')] [string] $OrganizationName, # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Users/Blocking/Unblock-GitHubUser.ps1 b/src/GitHub/public/Users/Blocking/Unblock-GitHubUser.ps1 index 854a1ef70..440bb0ae3 100644 --- a/src/GitHub/public/Users/Blocking/Unblock-GitHubUser.ps1 +++ b/src/GitHub/public/Users/Blocking/Unblock-GitHubUser.ps1 @@ -41,7 +41,6 @@ )] [Alias('org')] [Alias('owner')] - [Alias('login')] [string] $OrganizationName ) diff --git a/src/GitHub/public/Users/Emails/Add-GitHubUserEmail.ps1 b/src/GitHub/public/Users/Emails/Add-GitHubUserEmail.ps1 index 6d7096598..1a1276fa1 100644 --- a/src/GitHub/public/Users/Emails/Add-GitHubUserEmail.ps1 +++ b/src/GitHub/public/Users/Emails/Add-GitHubUserEmail.ps1 @@ -33,11 +33,13 @@ $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/emails" + APIEndpoint = '/user/emails' Method = 'POST' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Users/Emails/Get-GitHubUserEmail.ps1 b/src/GitHub/public/Users/Emails/Get-GitHubUserEmail.ps1 index ae97b91c4..3d9530913 100644 --- a/src/GitHub/public/Users/Emails/Get-GitHubUserEmail.ps1 +++ b/src/GitHub/public/Users/Emails/Get-GitHubUserEmail.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION Lists all of your email addresses, and specifies which one is visible to the public. This endpoint is accessible with the `user:email` scope. - Specifying '-Public' will return only the publicly visible email address, which you can set with the [Set primary email visibility for the authenticated user](https://docs.github.com/rest/users/emails#set-primary-email-visibility-for-the-authenticated-user) endpoint. + Specifying '-Public' will return only the publicly visible email address, which you can set with the [Set primary email visibility for the + authenticated user](https://docs.github.com/rest/users/emails#set-primary-email-visibility-for-the-authenticated-user) endpoint. .EXAMPLE Get-GitHubUserEmail @@ -27,6 +28,7 @@ param ( # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30, [Parameter()] diff --git a/src/GitHub/public/Users/Emails/Remove-GitHubUserEmail.ps1 b/src/GitHub/public/Users/Emails/Remove-GitHubUserEmail.ps1 index 271090f22..9202fb247 100644 --- a/src/GitHub/public/Users/Emails/Remove-GitHubUserEmail.ps1 +++ b/src/GitHub/public/Users/Emails/Remove-GitHubUserEmail.ps1 @@ -16,7 +16,7 @@ #> [OutputType([pscustomobject])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # Email addresses associated with the GitHub user account. [Parameter( @@ -30,11 +30,15 @@ $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/emails" + APIEndpoint = '/user/emails' Method = 'DELETE' Body = $body } - $null = (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("Email addresses [$($Emails -join ', ')]", 'Delete')) { + $null = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Users/Emails/Set-GitHubUserEmailVisibility.ps1 b/src/GitHub/public/Users/Emails/Set-GitHubUserEmailVisibility.ps1 index 598a79522..d2da272b3 100644 --- a/src/GitHub/public/Users/Emails/Set-GitHubUserEmailVisibility.ps1 +++ b/src/GitHub/public/Users/Emails/Set-GitHubUserEmailVisibility.ps1 @@ -21,7 +21,7 @@ #> [OutputType([pscustomobject])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # Denotes whether an email is publicly visible. [Parameter( @@ -36,11 +36,15 @@ $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/email/visibility" + APIEndpoint = '/user/email/visibility' Method = 'PATCH' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("Email visibility [$Visibility]", 'Set')) { + $null = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Users/Followers/Add-GitHubUserFollowing.ps1 b/src/GitHub/public/Users/Followers/Add-GitHubUserFollowing.ps1 index 8bd70f467..3a9ed24ea 100644 --- a/src/GitHub/public/Users/Followers/Add-GitHubUserFollowing.ps1 +++ b/src/GitHub/public/Users/Followers/Add-GitHubUserFollowing.ps1 @@ -35,6 +35,8 @@ Method = 'PUT' } - $null = (Invoke-GitHubAPI @inputObject).Response + $null = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Users/Followers/Get-GitHubUserFollowers.ps1 b/src/GitHub/public/Users/Followers/Get-GitHubUserFollower.ps1 similarity index 84% rename from src/GitHub/public/Users/Followers/Get-GitHubUserFollowers.ps1 rename to src/GitHub/public/Users/Followers/Get-GitHubUserFollower.ps1 index b59ed7afd..780dadde0 100644 --- a/src/GitHub/public/Users/Followers/Get-GitHubUserFollowers.ps1 +++ b/src/GitHub/public/Users/Followers/Get-GitHubUserFollower.ps1 @@ -1,4 +1,4 @@ -filter Get-GitHubUserFollowers { +filter Get-GitHubUserFollower { <# .SYNOPSIS List followers of a given user or the authenticated user @@ -7,12 +7,12 @@ Lists the people following a given user or the authenticated user. .EXAMPLE - Get-GitHubUserFollowers + Get-GitHubUserFollower Gets all followers of the authenticated user. .EXAMPLE - Get-GitHubUserFollowers -Username 'octocat' + Get-GitHubUserFollower -Username 'octocat' Gets all followers of the user 'octocat'. @@ -21,6 +21,7 @@ #> [OutputType([pscustomobject])] + [Alias('Get-GitHubUserMyFollowers')] [CmdletBinding()] param ( # The handle for the GitHub user account. @@ -33,6 +34,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Users/Followers/Get-GitHubUserFollowing.ps1 b/src/GitHub/public/Users/Followers/Get-GitHubUserFollowing.ps1 index cdf12c54c..611b411aa 100644 --- a/src/GitHub/public/Users/Followers/Get-GitHubUserFollowing.ps1 +++ b/src/GitHub/public/Users/Followers/Get-GitHubUserFollowing.ps1 @@ -34,6 +34,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Users/Followers/Remove-GitHubUserFollowing.ps1 b/src/GitHub/public/Users/Followers/Remove-GitHubUserFollowing.ps1 index a601ba0b6..2bcaa62e5 100644 --- a/src/GitHub/public/Users/Followers/Remove-GitHubUserFollowing.ps1 +++ b/src/GitHub/public/Users/Followers/Remove-GitHubUserFollowing.ps1 @@ -17,7 +17,7 @@ #> [OutputType([pscustomobject])] [Alias('Unfollow-GitHubUser')] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The handle for the GitHub user account. [Parameter( @@ -33,6 +33,10 @@ Method = 'DELETE' } - $null = (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("User [$Username]", 'Unfollow')) { + $null = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Users/Followers/Test-GitHubUserFollows.ps1 b/src/GitHub/public/Users/Followers/Test-GitHubUserFollowing.ps1 similarity index 84% rename from src/GitHub/public/Users/Followers/Test-GitHubUserFollows.ps1 rename to src/GitHub/public/Users/Followers/Test-GitHubUserFollowing.ps1 index d8168159f..dbb950ba7 100644 --- a/src/GitHub/public/Users/Followers/Test-GitHubUserFollows.ps1 +++ b/src/GitHub/public/Users/Followers/Test-GitHubUserFollowing.ps1 @@ -1,4 +1,4 @@ -filter Test-GitHubUserFollows { +filter Test-GitHubUserFollowing { <# .SYNOPSIS Check if a given user or the authenticated user follows a person @@ -8,13 +8,13 @@ Returns a 404 if the user is not followed by a given user or the authenticated user. .EXAMPLE - Test-GitHubUserFollows -Follows 'octocat' - Test-GitHubUserFollows 'octocat' + Test-GitHubUserFollowing -Follows 'octocat' + Test-GitHubUserFollowing 'octocat' Checks if the authenticated user follows the user 'octocat'. .EXAMPLE - Test-GitHubUserFollows -Username 'octocat' -Follows 'ratstallion' + Test-GitHubUserFollowing -Username 'octocat' -Follows 'ratstallion' Checks if the user 'octocat' follows the user 'ratstallion'. @@ -24,6 +24,7 @@ #> [OutputType([bool])] + [Alias('Test-GitHubUserFollows')] [CmdletBinding()] param ( # The handle for the GitHub user account we want to check if is being followed. diff --git a/src/GitHub/public/Users/GPG-Keys/Add-GitHubUserGpgKey.ps1 b/src/GitHub/public/Users/GPG-Keys/Add-GitHubUserGpgKey.ps1 index fee17853e..597d618d0 100644 --- a/src/GitHub/public/Users/GPG-Keys/Add-GitHubUserGpgKey.ps1 +++ b/src/GitHub/public/Users/GPG-Keys/Add-GitHubUserGpgKey.ps1 @@ -5,10 +5,17 @@ .DESCRIPTION Adds a GPG key to the authenticated user's GitHub account. - Requires that you are authenticated via Basic Auth, or OAuth with at least `write:gpg_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + Requires that you are authenticated via Basic Auth, or OAuth with at least `write:gpg_key` + [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). .EXAMPLE - Add-GitHubUserGpgKey -Name 'GPG key for GitHub' -ArmoredPublicKey '-----BEGIN PGP PUBLIC KEY BLOCK-----\nVersion: GnuPG v1\n\nmQINBFnZ2ZIBEADQ2Z7Z7\n-----END PGP PUBLIC KEY BLOCK-----' + Add-GitHubUserGpgKey -Name 'GPG key for GitHub' -ArmoredPublicKey @' + -----BEGIN PGP PUBLIC KEY BLOCK----- + Version: GnuPG v1 + + mQINBFnZ2ZIBEADQ2Z7Z7 + -----END PGP PUBLIC KEY BLOCK----- + '@ Adds a GPG key to the authenticated user's GitHub account. @@ -40,11 +47,13 @@ $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/gpg_keys" + APIEndpoint = '/user/gpg_keys' Method = 'POST' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Users/GPG-Keys/Get-GitHubUserGpgKey.ps1 b/src/GitHub/public/Users/GPG-Keys/Get-GitHubUserGpgKey.ps1 index 0ccb50c2b..8cb551333 100644 --- a/src/GitHub/public/Users/GPG-Keys/Get-GitHubUserGpgKey.ps1 +++ b/src/GitHub/public/Users/GPG-Keys/Get-GitHubUserGpgKey.ps1 @@ -46,6 +46,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Users/GPG-Keys/Remove-GitHubUserGpgKey.ps1 b/src/GitHub/public/Users/GPG-Keys/Remove-GitHubUserGpgKey.ps1 index fac0d3ff2..648995db1 100644 --- a/src/GitHub/public/Users/GPG-Keys/Remove-GitHubUserGpgKey.ps1 +++ b/src/GitHub/public/Users/GPG-Keys/Remove-GitHubUserGpgKey.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION Removes a GPG key from the authenticated user's GitHub account. - Requires that you are authenticated via Basic Auth or via OAuth with at least `admin:gpg_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + Requires that you are authenticated via Basic Auth or via OAuth with at least `admin:gpg_key` + [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). .EXAMPLE Remove-GitHubUserGpgKey -ID '1234567' @@ -17,7 +18,7 @@ #> [OutputType([pscustomobject])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The ID of the GPG key. [Parameter( @@ -32,6 +33,10 @@ Method = 'DELETE' } - $null = (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("GPG key with ID [$ID]", 'Delete')) { + $null = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Users/Get-GitHubUser.ps1 b/src/GitHub/public/Users/Get-GitHubUser.ps1 index d505df4c1..34fd51c58 100644 --- a/src/GitHub/public/Users/Get-GitHubUser.ps1 +++ b/src/GitHub/public/Users/Get-GitHubUser.ps1 @@ -27,6 +27,11 @@ https://docs.github.com/rest/users/users #> [OutputType([pscustomobject])] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSReviewUnusedParameter', + 'All', + Justification = 'Parameter is used in dynamic parameter validation.' + )] [CmdletBinding(DefaultParameterSetName = '__DefaultSet')] param ( # The handle for the GitHub user account. @@ -50,6 +55,7 @@ # The number of results per page (max 100). [Parameter(ParameterSetName = 'AllUsers')] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Users/Get-GitHubUserCard.ps1 b/src/GitHub/public/Users/Get-GitHubUserCard.ps1 index ee7e7d427..1e72a909c 100644 --- a/src/GitHub/public/Users/Get-GitHubUserCard.ps1 +++ b/src/GitHub/public/Users/Get-GitHubUserCard.ps1 @@ -4,9 +4,12 @@ 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. + 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: + 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 @@ -46,6 +49,8 @@ Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Users/Keys/Add-GitHubUserKey.ps1 b/src/GitHub/public/Users/Keys/Add-GitHubUserKey.ps1 index 6d2670829..654681958 100644 --- a/src/GitHub/public/Users/Keys/Add-GitHubUserKey.ps1 +++ b/src/GitHub/public/Users/Keys/Add-GitHubUserKey.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION Adds a public SSH key to the authenticated user's GitHub account. - Requires that you are authenticated via Basic Auth, or OAuth with at least `write:public_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + Requires that you are authenticated via Basic Auth, or OAuth with at least `write:public_key` + [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). .EXAMPLE Add-GitHubUserKey -Title 'ssh-rsa AAAAB3NzaC1yc2EAAA' -Key '2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvv1234' @@ -39,11 +40,13 @@ $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/keys" + APIEndpoint = '/user/keys' Method = 'POST' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Users/Keys/Get-GitHubUserKey.ps1 b/src/GitHub/public/Users/Keys/Get-GitHubUserKey.ps1 index cdbfca733..6b59eb858 100644 --- a/src/GitHub/public/Users/Keys/Get-GitHubUserKey.ps1 +++ b/src/GitHub/public/Users/Keys/Get-GitHubUserKey.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION Lists a given user's or the current user's public SSH keys. - For the authenticated users keys, it requires that you are authenticated via Basic Auth or via OAuth with at least `read:public_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + For the authenticated users keys, it requires that you are authenticated via Basic Auth or via OAuth with + at least `read:public_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). Keys from a given user are accessible by anyone. .EXAMPLE @@ -48,6 +49,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Users/Keys/Remove-GitHubUserKey.ps1 b/src/GitHub/public/Users/Keys/Remove-GitHubUserKey.ps1 index 0c79573f6..725c35552 100644 --- a/src/GitHub/public/Users/Keys/Remove-GitHubUserKey.ps1 +++ b/src/GitHub/public/Users/Keys/Remove-GitHubUserKey.ps1 @@ -5,7 +5,8 @@ .DESCRIPTION Removes a public SSH key from the authenticated user's GitHub account. - Requires that you are authenticated via Basic Auth or via OAuth with at least `admin:public_key` [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). + Requires that you are authenticated via Basic Auth or via OAuth with at least `admin:public_key` + [scope](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/). .EXAMPLE Remove-GitHubUserKey -ID '1234567' @@ -17,7 +18,7 @@ #> [OutputType([pscustomobject])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The unique identifier of the key. [Parameter( @@ -32,6 +33,10 @@ Method = 'DELETE' } - $null = (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("Key with ID [$ID]", 'Delete')) { + $null = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Users/SSH-Signing-Keys/Add-GitHubUserSigningKey.ps1 b/src/GitHub/public/Users/SSH-Signing-Keys/Add-GitHubUserSigningKey.ps1 index cb55dc119..0a398a572 100644 --- a/src/GitHub/public/Users/SSH-Signing-Keys/Add-GitHubUserSigningKey.ps1 +++ b/src/GitHub/public/Users/SSH-Signing-Keys/Add-GitHubUserSigningKey.ps1 @@ -5,7 +5,9 @@ .DESCRIPTION Creates an SSH signing key for the authenticated user's GitHub account. - You must authenticate with Basic Authentication, or you must authenticate with OAuth with at least `write:ssh_signing_key` scope. For more information, see "[Understanding scopes for OAuth apps](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)." + You must authenticate with Basic Authentication, or you must authenticate with OAuth with at least `write:ssh_signing_key` scope. + For more information, see + "[Understanding scopes for OAuth apps](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)." .EXAMPLE Add-GitHubUserSigningKey -Title 'ssh-rsa AAAAB3NzaC1yc2EAAA' -Key '2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvv1234' @@ -27,7 +29,8 @@ [Alias('name')] [string] $Title, - # The public SSH key to add to your GitHub account. For more information, see [Checking for existing SSH keys](https://docs.github.com/authentication/connecting-to-github-with-ssh/checking-for-existing-ssh-keys)." + # The public SSH key to add to your GitHub account. For more information, see + # [Checking for existing SSH keys](https://docs.github.com/authentication/connecting-to-github-with-ssh/checking-for-existing-ssh-keys)." [Parameter( Mandatory, ValueFromPipelineByPropertyName @@ -39,11 +42,13 @@ $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case $inputObject = @{ - APIEndpoint = "/user/ssh_signing_keys" + APIEndpoint = '/user/ssh_signing_keys' Method = 'POST' Body = $body } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Users/SSH-Signing-Keys/Get-GitHubUserSigningKey.ps1 b/src/GitHub/public/Users/SSH-Signing-Keys/Get-GitHubUserSigningKey.ps1 index e7c60b53e..645dfb8da 100644 --- a/src/GitHub/public/Users/SSH-Signing-Keys/Get-GitHubUserSigningKey.ps1 +++ b/src/GitHub/public/Users/SSH-Signing-Keys/Get-GitHubUserSigningKey.ps1 @@ -48,6 +48,7 @@ # The number of results per page (max 100). [Parameter()] + [ValidateRange(1, 100)] [int] $PerPage = 30 ) diff --git a/src/GitHub/public/Users/SSH-Signing-Keys/Remove-GitHubUserSigningKey.ps1 b/src/GitHub/public/Users/SSH-Signing-Keys/Remove-GitHubUserSigningKey.ps1 index 48a283c3d..4ea9fca38 100644 --- a/src/GitHub/public/Users/SSH-Signing-Keys/Remove-GitHubUserSigningKey.ps1 +++ b/src/GitHub/public/Users/SSH-Signing-Keys/Remove-GitHubUserSigningKey.ps1 @@ -5,7 +5,9 @@ .DESCRIPTION Deletes an SSH signing key from the authenticated user's GitHub account. - You must authenticate with Basic Authentication, or you must authenticate with OAuth with at least `admin:ssh_signing_key` scope. For more information, see "[Understanding scopes for OAuth apps](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)." + You must authenticate with Basic Authentication, or you must authenticate with OAuth with at least + `admin:ssh_signing_key` scope. For more information, see + "[Understanding scopes for OAuth apps](https://docs.github.com/apps/building-oauth-apps/understanding-scopes-for-oauth-apps/)." .EXAMPLE Remove-GitHubUserSigningKey -ID '1234567' @@ -17,7 +19,7 @@ #> [OutputType([pscustomobject])] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The unique identifier of the SSH signing key. [Parameter( @@ -32,6 +34,10 @@ Method = 'DELETE' } - $null = (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("SSH signing key with ID [$ID]", 'Delete')) { + $null = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Users/Set-GitHubUser.ps1 b/src/GitHub/public/Users/Set-GitHubUser.ps1 index 99ceabf61..2a38756ec 100644 --- a/src/GitHub/public/Users/Set-GitHubUser.ps1 +++ b/src/GitHub/public/Users/Set-GitHubUser.ps1 @@ -28,7 +28,7 @@ #> [OutputType([void])] [Alias('Update-GitHubUser')] - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( # The new name of the user. [Parameter()] @@ -71,6 +71,10 @@ Method = 'PATCH' } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess('authenticated user', 'Set')) { + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/src/GitHub/public/Users/Social-Accounts/Add-GitHubUserSocials.ps1 b/src/GitHub/public/Users/Social-Accounts/Add-GitHubUserSocial.ps1 similarity index 76% rename from src/GitHub/public/Users/Social-Accounts/Add-GitHubUserSocials.ps1 rename to src/GitHub/public/Users/Social-Accounts/Add-GitHubUserSocial.ps1 index 89cfdcddf..aeca19aaa 100644 --- a/src/GitHub/public/Users/Social-Accounts/Add-GitHubUserSocials.ps1 +++ b/src/GitHub/public/Users/Social-Accounts/Add-GitHubUserSocial.ps1 @@ -1,4 +1,4 @@ -filter Add-GitHubUserSocials { +filter Add-GitHubUserSocial { <# .SYNOPSIS Add social accounts for the authenticated user @@ -7,7 +7,7 @@ Add one or more social accounts to the authenticated user's profile. This endpoint is accessible with the `user` scope. .EXAMPLE - Add-GitHubUserSocials -AccountUrls 'https://twitter.com/MyTwitterAccount', 'https://www.linkedin.com/company/MyCompany' + Add-GitHubUserSocial -AccountUrls 'https://twitter.com/MyTwitterAccount', 'https://www.linkedin.com/company/MyCompany' Adds the Twitter and LinkedIn accounts to the authenticated user's profile. @@ -15,6 +15,7 @@ https://docs.github.com/rest/users/social-accounts#add-social-accounts-for-the-authenticated-user #> [OutputType([void])] + [Alias('Add-GitHubUserSocials')] [CmdletBinding()] param ( # Full URLs for the social media profiles to add. @@ -31,6 +32,8 @@ Method = 'POST' } - (Invoke-GitHubAPI @inputObject).Response + Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } } diff --git a/src/GitHub/public/Users/Social-Accounts/Remove-GitHubUserSocials.ps1 b/src/GitHub/public/Users/Social-Accounts/Remove-GitHubUserSocial.ps1 similarity index 68% rename from src/GitHub/public/Users/Social-Accounts/Remove-GitHubUserSocials.ps1 rename to src/GitHub/public/Users/Social-Accounts/Remove-GitHubUserSocial.ps1 index c7ca4de98..c1b46603c 100644 --- a/src/GitHub/public/Users/Social-Accounts/Remove-GitHubUserSocials.ps1 +++ b/src/GitHub/public/Users/Social-Accounts/Remove-GitHubUserSocial.ps1 @@ -1,4 +1,4 @@ -filter Remove-GitHubUserSocials { +filter Remove-GitHubUserSocial { <# .SYNOPSIS Delete social accounts for the authenticated user @@ -10,13 +10,14 @@ Parameter description .EXAMPLE - Remove-GitHubUserSocials -AccountUrls 'https://twitter.com/MyTwitterAccount' + Remove-GitHubUserSocial -AccountUrls 'https://twitter.com/MyTwitterAccount' .NOTES https://docs.github.com/rest/users/social-accounts#delete-social-accounts-for-the-authenticated-user #> [OutputType([void])] - [CmdletBinding()] + [Alias('Remove-GitHubUserSocials')] + [CmdletBinding(SupportsShouldProcess)] param ( # Full URLs for the social media profiles to add. [Parameter(Mandatory)] @@ -32,6 +33,10 @@ Method = 'DELETE' } - (Invoke-GitHubAPI @inputObject).Response + if ($PSCmdlet.ShouldProcess("Social accounts [$($AccountUrls -join ', ')]", 'Delete')) { + $null = Invoke-GitHubAPI @inputObject | ForEach-Object { + Write-Output $_.Response + } + } } diff --git a/tests/DynamicParam.ps1 b/tests/DynamicParam.ps1 new file mode 100644 index 000000000..7be4f9ea5 --- /dev/null +++ b/tests/DynamicParam.ps1 @@ -0,0 +1,42 @@ +function Test-DynParam { + [CmdletBinding()] + param ( + [Parameter()] + [ValidateSet('A', 'B', 'C')] + [string]$Param1 + ) + + DynamicParam { + $ParamDictionary = New-ParamDictionary + + $dynParam2 = @{ + Name = 'Param2' + Type = [string] + ValidateSet = Get-Process | Select-Object -ExpandProperty Name + ParamDictionary = $ParamDictionary + } + New-DynamicParam @dynParam2 + + $dynParam3 = @{ + Name = 'Param3' + Type = [string] + ValidateSet = Get-ChildItem -Path C:\ | Select-Object -ExpandProperty Name + ParamDictionary = $ParamDictionary + } + New-DynamicParam @dynParam3 + + return $ParamDictionary + } + + process { + $Param1 = $PSBoundParameters['Param1'] + $Param2 = $PSBoundParameters['Param2'] + $Param3 = $PSBoundParameters['Param3'] + + Write-Host "Param1: $Param1" + Write-Host "Param2: $Param2" + Write-Host "Param3: $Param3" + } +} + +Test-DynParam -Param1 A -Param3 PerfLogs diff --git a/tests/GitHub/Auth/Connect-GitHubAccount.Tests.ps1 b/tests/GitHub/Auth/Connect-GitHubAccount.Tests.ps1 new file mode 100644 index 000000000..e7e06a3c6 --- /dev/null +++ b/tests/GitHub/Auth/Connect-GitHubAccount.Tests.ps1 @@ -0,0 +1,11 @@ +Describe 'Connect-GitHubAccount' { + It 'Function exists' { + Get-Command Connect-GitHubAccount | Should -Not -BeNullOrEmpty + } + + Context 'Parameter Set: sPAT' { + It 'Can be called with no parameters' { + { Connect-GitHubAccount } | Should -Not -Throw + } + } +} diff --git a/tests/GitHub/Auth/Disconnect-GitHubAccount.Tests.ps1 b/tests/GitHub/Auth/Disconnect-GitHubAccount.Tests.ps1 new file mode 100644 index 000000000..811bcd1f3 --- /dev/null +++ b/tests/GitHub/Auth/Disconnect-GitHubAccount.Tests.ps1 @@ -0,0 +1,13 @@ +Describe 'Disconnect-GitHubAccount' { + It 'Function exists' { + Get-Command Disconnect-GitHubAccount | Should -Not -BeNullOrEmpty + } + + It 'Can be called with no parameters' { + { Disconnect-GitHubAccount } | Should -Not -Throw + } + + It 'Can reconnect after disconnecting' { + { Connect-GitHubAccount } | Should -Not -Throw + } +} diff --git a/tests/GitHub/Get-GitHubRepository.Tests.ps1 b/tests/GitHub/Get-GitHubRepository.Tests.ps1 new file mode 100644 index 000000000..97ac96651 --- /dev/null +++ b/tests/GitHub/Get-GitHubRepository.Tests.ps1 @@ -0,0 +1,45 @@ +Describe 'Get-GitHubRepository' { + It 'Function exists' { + Get-Command Get-GitHubRepository | Should -Not -BeNullOrEmpty + } + + # Context 'Parameter Set: MyRepos_Type' { + # It 'Can be called with no parameters' { + # { Get-GitHubRepository - } | Should -Not -Throw + # } + + # It 'Can be called with Type parameter' { + # { Get-GitHubRepository -Type 'public' } | Should -Not -Throw + # } + # } + + # Context 'Parameter Set: MyRepos_Aff-Vis' { + # It 'Can be called with Visibility and Affiliation parameters' { + # { Get-GitHubRepository -Visibility 'public' -Affiliation 'owner' } | Should -Not -Throw + # } + # } + + Context 'Parameter Set: ByName' { + It 'Can be called with Owner and Repo parameters' { + { Get-GitHubRepository -Owner 'PSModule' -Repo 'GitHub' } | Should -Not -Throw + } + } + + # Context 'Parameter Set: ListByID' { + # It 'Can be called with SinceID parameter' { + # { Get-GitHubRepository -SinceID 123456789 } | Select-Object -First 10 | Should -Not -Throw + # } + # } + + Context 'Parameter Set: ListByOrg' { + It 'Can be called with Owner parameter' { + { Get-GitHubRepository -Owner 'PSModule' } | Should -Not -Throw + } + } + + Context 'Parameter Set: ListByUser' { + It 'Can be called with Username parameter' { + { Get-GitHubRepository -Username 'MariusStorhaug' } | Should -Not -Throw + } + } +} diff --git a/tests/GitHub/Status/Get-GitHubScheduledMaintenance.Tests.ps1 b/tests/GitHub/Status/Get-GitHubScheduledMaintenance.Tests.ps1 new file mode 100644 index 000000000..3e7601b65 --- /dev/null +++ b/tests/GitHub/Status/Get-GitHubScheduledMaintenance.Tests.ps1 @@ -0,0 +1,23 @@ +Describe 'Get-GitHubScheduledMaintenance' { + It 'Function exists' { + Get-Command Get-GitHubScheduledMaintenance | Should -Not -BeNullOrEmpty + } + + Context 'Parameter Set: Default' { + It 'Can be called with no parameters' { + { Get-GitHubScheduledMaintenance } | Should -Not -Throw + } + } + + Context 'Parameter Set: Active' { + It 'Can be called with Active parameter' { + { Get-GitHubScheduledMaintenance -Active } | Should -Not -Throw + } + } + + Context 'Parameter Set: Upcoming' { + It 'Can be called with Upcoming parameter' { + { Get-GitHubScheduledMaintenance -Upcoming } | Should -Not -Throw + } + } +} diff --git a/tests/GitHub/Status/Get-GitHubStatus.Tests.ps1 b/tests/GitHub/Status/Get-GitHubStatus.Tests.ps1 new file mode 100644 index 000000000..b1f34e700 --- /dev/null +++ b/tests/GitHub/Status/Get-GitHubStatus.Tests.ps1 @@ -0,0 +1,17 @@ +Describe 'Get-GitHubStatus' { + It 'Function exists' { + Get-Command Get-GitHubStatus | Should -Not -BeNullOrEmpty + } + + Context 'Parameter Set: Default' { + It 'Can be called with no parameters' { + { Get-GitHubStatus } | Should -Not -Throw + } + } + + Context 'Parameter Set: Summary' { + It 'Can be called with Summary parameter' { + { Get-GitHubStatus -Summary } | Should -Not -Throw + } + } +} diff --git a/tests/GitHub/Status/Get-GitHubStatusComponent.Tests.ps1 b/tests/GitHub/Status/Get-GitHubStatusComponent.Tests.ps1 new file mode 100644 index 000000000..7287968be --- /dev/null +++ b/tests/GitHub/Status/Get-GitHubStatusComponent.Tests.ps1 @@ -0,0 +1,9 @@ +Describe 'Get-GitHubStatusComponent' { + It 'Function exists' { + Get-Command Get-GitHubStatusComponent | Should -Not -BeNullOrEmpty + } + + It 'Can be called with no parameters' { + { Get-GitHubStatusComponent } | Should -Not -Throw + } +} diff --git a/tests/GitHub/Status/Get-GitHubStatusIncident.Tests.ps1 b/tests/GitHub/Status/Get-GitHubStatusIncident.Tests.ps1 new file mode 100644 index 000000000..d30058935 --- /dev/null +++ b/tests/GitHub/Status/Get-GitHubStatusIncident.Tests.ps1 @@ -0,0 +1,17 @@ +Describe 'Get-GitHubStatusIncident' { + It 'Function exists' { + Get-Command Get-GitHubStatusIncident | Should -Not -BeNullOrEmpty + } + + Context 'Parameter Set: Default' { + It 'Can be called with no parameters' { + { Get-GitHubStatusIncident } | Should -Not -Throw + } + } + + Context 'Parameter Set: Unresolved' { + It 'Can be called with Unresolved parameter' { + { Get-GitHubStatusIncident -Unresolved } | Should -Not -Throw + } + } +} diff --git a/tests/Rate-Limit/Get-GitHubRateLimit.Tests.ps1 b/tests/Rate-Limit/Get-GitHubRateLimit.Tests.ps1 new file mode 100644 index 000000000..0e698a5ad --- /dev/null +++ b/tests/Rate-Limit/Get-GitHubRateLimit.Tests.ps1 @@ -0,0 +1,9 @@ +Describe 'Get-GitHubRateLimit' { + It 'Function exists' { + Get-Command Get-GitHubRateLimit | Should -Not -BeNullOrEmpty + } + + It 'Can be called with no parameters' { + { Get-GitHubRateLimit } | Should -Not -Throw + } +} diff --git a/tools/utilities/GitHubAPI.ps1 b/tools/utilities/GitHubAPI.ps1 index 64aeedf58..559c09427 100644 --- a/tools/utilities/GitHubAPI.ps1 +++ b/tools/utilities/GitHubAPI.ps1 @@ -21,8 +21,8 @@ $response = Invoke-RestMethod -Uri $APIDocURI -Method Get # @{n = 'PUT'; e = { (($_.value.psobject.Properties.Name) -contains 'PUT') } }, ` # @{n = 'PATCH'; e = { (($_.value.psobject.Properties.Name) -contains 'PATCH') } } | Format-Table -$path = '/repos/{owner}/{repo}/releases/{release_id}/assets' -$method = 'post' +$path = '/repos/{owner}/{repo}/properties/values' +$method = 'get' $response.paths.$path.$method $response.paths.$path.$method.tags | clip # -> Namespace/foldername $response.paths.$path.$method.operationId | clip # -> FunctionName @@ -42,11 +42,11 @@ $response.paths.$path.$method.responses.'200'.content.'application/json'.schema. $response.components.schemas.PSobject.Properties | ForEach-Object { [pscustomobject]@{ - Name = $_.Name - Title = $_.Value.title - Type = $_.Value.type + Name = $_.Name + Title = $_.Value.title + Type = $_.Value.type Properties = $_.Value.properties - Required = $_.Value.required + Required = $_.Value.required } } diff --git a/tools/utilities/Local-Testing.ps1 b/tools/utilities/Local-Testing.ps1 index 0cf21d57c..9ede69b36 100644 --- a/tools/utilities/Local-Testing.ps1 +++ b/tools/utilities/Local-Testing.ps1 @@ -11,6 +11,7 @@ Get-SecretInfo Get-Module -Name GitHub -ListAvailable $VerbosePreference = 'Continue' +Find-Module -Name GitHub Install-Module -Name GitHub -Force -Verbose -AllowPrerelease Get-Module -Name GitHub -ListAvailable # $env:PSModulePath += ';C:\Repos\GitHub\PSModule\Modules\GitHub\outputs' @@ -80,3 +81,81 @@ $Release = Get-GitHubRelease -Owner PSModule -Repo Demo -Latest Add-GitHubReleaseAsset -Owner PSModule -Repo Demo -ID $Release.id -FilePath 'C:\Repos\GitHub\PSModule\Modules\GitHub\tools\utilities\Local-Testing.ps1' Get-GitHubReleaseAsset -Owner PSModule -Repo Demo -ReleaseID $Release.id + +Get-GitHubRepository | Select-Object full_name, id, visibility, created_at +Get-GitHubRepository -Type owner | Select-Object full_name, id, visibility, created_at +Get-GitHubRepository -Type private -Sort pushed | Select-Object full_name, id, visibility, created_at + +Get-GitHubRepository -Owner 'PSModule' -Repo 'Demo' | Select-Object full_name, id, visibility, created_at +Get-GitHubRepository -Owner 'Azure' -Repo 'ResourceModules' | Select-Object full_name, id, visibility, created_at + +Get-GitHubRepository -SinceID 702104693 -Verbose | Select-Object full_name, id, visibility, created_at + +Get-GitHubRepository -Username 'octocat' -Type all | Select-Object full_name, id, visibility, created_at +Get-GitHubRepository -Username 'octocat' -Type 'member' | Select-Object full_name, id, visibility, created_at +Get-GitHubRepository -Username 'octocat' -Sort 'created' -Direction 'asc' | Select-Object full_name, id, visibility, created_at + +Get-GitHubRepository -Owner 'PSModule' | Select-Object full_name, id, visibility, created_at +Get-GitHubRepository -Owner 'PSModule' -Type 'public' | Select-Object full_name, id, visibility, created_at +Get-GitHubRepository -Owner 'PSModule' -Sort 'created' -Direction 'asc' | Select-Object full_name, id, visibility, created_at + +$params = @{ + Verbose = $true + Owner = 'PSModule' + Name = 'Hello-world' + Description = 'This is a test repo.' + Homepage = 'https://github.com' + Visibility = 'public' + HasIssues = $true + HasProjects = $true + HasWiki = $true + HasDownloads = $true + IsTemplate = $true + # TeamID = 12345679 + AutoInit = $true + # GitignoreTemplate = 'VisualStudio' + # LicenseTemplate = 'MIT' + AllowSquashMerge = $true + SquashMergeCommitTitle = 'PR_TITLE' + SquashMergeCommitMessage = 'PR_BODY' + AllowMergeCommit = $true + MergeCommitTitle = 'PR_TITLE' + MergeCommitMessage = 'PR_BODY' + AllowRebaseMerge = $true + AllowAutoMerge = $true + DeleteBranchOnMerge = $true +} +New-GitHubRepositoryOrg @params -GitignoreTemplate VisualStudio -LicenseTemplate mit +Remove-GitHubRepository -Owner PSModule -Repo 'Hello-world' -Verbose + + +$params = @{ + Verbose = $true + Name = 'Hello-world' + Description = 'This is a test repo.' + Homepage = 'https://github.com' + Visibility = 'public' + HasIssues = $true + HasProjects = $true + HasWiki = $true + HasDownloads = $true + IsTemplate = $true + # TeamID = 12345679 + AutoInit = $true + # GitignoreTemplate = 'VisualStudio' + # LicenseTemplate = 'MIT' + AllowSquashMerge = $true + SquashMergeCommitTitle = 'PR_TITLE' + SquashMergeCommitMessage = 'PR_BODY' + AllowMergeCommit = $true + MergeCommitTitle = 'PR_TITLE' + MergeCommitMessage = 'PR_BODY' + AllowRebaseMerge = $true + AllowAutoMerge = $true + DeleteBranchOnMerge = $true +} +New-GitHubRepositoryUser @params -GitignoreTemplate VisualStudio -LicenseTemplate gpl-3.0 +Remove-GitHubRepository -Owner MariusStorhaug -Repo 'Hello-world' -Verbose + + +Get-GitHubRepositoryTopic -Owner 'PSModule' -Repo 'GitHub' diff --git a/tools/utilities/StopWorkflowsCustom.ps1 b/tools/utilities/StopWorkflowsCustom.ps1 index b73b89246..ea7c787e3 100644 --- a/tools/utilities/StopWorkflowsCustom.ps1 +++ b/tools/utilities/StopWorkflowsCustom.ps1 @@ -35,7 +35,7 @@ Get-GitHubRepoTeams (Get-GitHubWorkflow).count -Get-GitHubWorkflow | Select-Object -first 1 -Property * +Get-GitHubWorkflow | Select-Object -First 1 -Property * Get-GitHubWorkflow | Select-Object Name, state Get-GitHubWorkflow | Where-Object state -NE disabled_manually | Disable-GitHubWorkflow @@ -58,12 +58,12 @@ 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-GitHubWorkflowRun | Where-Object run_started_at -LE (Get-Date).AddDays(-1) | Remove-GitHubWorkflowRun Get-GitHubWorkflow | Where-Object name -NotLike '.*' | Start-GitHubWorkflow -Inputs @{ - staticValidation = $true + staticValidation = $true deploymentValidation = $false - removeDeployment = $true - prerelease = $false + removeDeployment = $true + prerelease = $false }