-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🚀 [Feature]: Implement GitHub App creation and conversion functions
- Loading branch information
1 parent
e01341e
commit 6170aad
Showing
5 changed files
with
384 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
src/functions/private/Apps/GitHub Apps/Convert-GitHubAppManifest.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
function Convert-GitHubAppManifest { | ||
<# | ||
.SYNOPSIS | ||
Converts a GitHub App Manifest into a full GitHub App. | ||
.DESCRIPTION | ||
Converts a temporary GitHub App Manifest into a full GitHub App by exchanging the provided code for app credentials. | ||
This function requires authentication and will return key details such as the App ID, Client ID, Private Key, and Webhook Secret. | ||
.EXAMPLE | ||
Convert-GitHubAppManifest -Code 'example-code' -Context $GitHubContext | ||
Converts the GitHub App Manifest associated with 'example-code' using the specified context. | ||
Returns the App ID, Client ID, Private Key, and Webhook Secret. | ||
.NOTES | ||
[GitHub API Docs - Convert a GitHub App Manifest](https://docs.github.com/en/rest/apps/apps#create-a-github-app-from-a-manifest) | ||
#> | ||
|
||
[CmdletBinding()] | ||
param( | ||
# The code received from GitHub to convert the app manifest into an installation. | ||
[Parameter(Mandatory)] | ||
[string] $Code, | ||
|
||
# The context to run the command in. Used to get the details for the API call. | ||
[Parameter(Mandatory)] | ||
[object] $Context | ||
) | ||
|
||
begin { | ||
$stackPath = $MyInvocation.MyCommand.Name | ||
Write-Debug "[$stackPath] - Start" | ||
Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT | ||
} | ||
|
||
process { | ||
$inputObject = @{ | ||
Context = $Context | ||
APIEndpoint = "/app-manifests/$Code/conversions" | ||
Method = 'GET' | ||
} | ||
|
||
$response = Invoke-GitHubAPI @inputObject | Select-Object -ExpandProperty Response | ||
|
||
Write-Verbose 'GitHub App converted successfully.' | ||
Write-Verbose ($response | Format-List | Out-String) | ||
|
||
[PSCustomObject]@{ | ||
AppId = $response.id | ||
ClientId = $response.client_id | ||
PrivateKey = $response.pem | ||
WebhookSecret = $response.webhook_secret | ||
} | ||
} | ||
|
||
end { | ||
Write-Debug "[$stackPath] - End" | ||
} | ||
} |
189 changes: 189 additions & 0 deletions
189
src/functions/private/Apps/GitHub Apps/Invoke-GitHubAppCreationForm.ps1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
function Invoke-GitHubAppCreationForm { | ||
<# | ||
.SYNOPSIS | ||
Submits a GitHub App manifest to GitHub and returns a temporary creation code. | ||
.DESCRIPTION | ||
This function builds the manifest JSON payload from provided parameters and sends a POST request | ||
to the GitHub App creation endpoint (personal, organization, or enterprise). It then extracts the | ||
temporary code from the redirect URL. If something goes wrong, it writes an error. | ||
The function supports different parameter sets for creating apps under personal, organization, or | ||
enterprise accounts. | ||
.EXAMPLE | ||
$code = Invoke-GitHubAppCreationForm -Name "MyApp" -Url "https://example.com" -WebhookURL "https://example.com/webhook" | ||
Creates a GitHub App with the given name, homepage URL, and webhook URL, then returns a temporary | ||
creation code. | ||
.EXAMPLE | ||
$code = Invoke-GitHubAppCreationForm -Name "MyOrgApp" -Url "https://myorg.com" -Organization "MyOrg" | ||
Registers a GitHub App under the "MyOrg" organization and returns a temporary creation code. | ||
.NOTES | ||
[Registering a GitHub App from a manifest](https://docs.github.com/en/apps/sharing-github-apps/registering-a-github-app-from-a-manifest) | ||
#> | ||
|
||
[CmdletBinding(DefaultParameterSetName = 'Personal')] | ||
param( | ||
# The name of the GitHub App. | ||
[Parameter(Mandatory)] | ||
[string] $Name, | ||
|
||
# The homepage URL of the GitHub App. | ||
[Parameter(Mandatory)] | ||
[string] $Url, | ||
|
||
# Enables webhook support for the GitHub App. | ||
[Parameter()] | ||
[switch] $WebhookEnabled, | ||
|
||
# The webhook URL where GitHub will send event payloads. | ||
[Parameter()] | ||
[string] $WebhookURL, | ||
|
||
# The redirect URL after app creation. | ||
[Parameter()] | ||
[string] $RedirectUrl, | ||
|
||
# List of callback URLs for OAuth flows. | ||
[Parameter()] | ||
[string[]] $CallbackUrls, | ||
|
||
# The setup URL for the GitHub App. | ||
[Parameter()] | ||
[string] $SetupUrl, | ||
|
||
# A description of the GitHub App. | ||
[Parameter()] | ||
[string] $Description, | ||
|
||
# Indicates whether the app is public. | ||
[Parameter()] | ||
[switch] $Public, | ||
|
||
# List of default webhook events the GitHub App will subscribe to. | ||
[Parameter()] | ||
[string[]] $Events, | ||
|
||
# Permissions requested by the GitHub App. | ||
[Parameter()] | ||
[hashtable] $Permissions, | ||
|
||
# Determines if OAuth authorization should be requested upon installation. | ||
[Parameter()] | ||
[switch] $RequestOAuthOnInstall, | ||
|
||
# Determines if setup should be prompted when the app is updated. | ||
[Parameter()] | ||
[switch] $SetupOnUpdate, | ||
|
||
# The organization under which the app is being created (Organization parameter set). | ||
[Parameter(ParameterSetName = 'Organization', Mandatory)] | ||
[string] $Organization, | ||
|
||
# The enterprise under which the app is being created (Enterprise parameter set). | ||
[Parameter(ParameterSetName = 'Enterprise', Mandatory)] | ||
[string] $Enterprise, | ||
|
||
# Optional state parameter to pass during app creation. | ||
[Parameter()] | ||
[string] $State, | ||
|
||
# The context to run the command in. Used to get the details for the API call. | ||
[Parameter(Mandatory)] | ||
[object] $Context | ||
) | ||
|
||
begin { | ||
$stackPath = $MyInvocation.MyCommand.Name | ||
Write-Debug "[$stackPath] - Start" | ||
} | ||
|
||
process { | ||
Write-Verbose 'Building GitHub App manifest JSON payload...' | ||
# Build the manifest object | ||
$manifest = @{ | ||
name = $Name | ||
url = $Url | ||
hook_attributes = @{ | ||
url = $WebhookURL | ||
active = $WebhookEnabled | ||
} | ||
redirect_url = $RedirectUrl | ||
callback_urls = $CallbackUrls | ||
setup_url = $SetupUrl | ||
description = $Description | ||
public = $Public | ||
default_events = $Events | ||
default_permissions = $Permissions | ||
request_oauth_on_install = $RequestOAuthOnInstall | ||
setup_on_update = $SetupOnUpdate | ||
} | ConvertTo-Json -Depth 10 -Compress | ||
|
||
# Determine target URL based on Org value | ||
switch ($PSCmdlet.ParameterSetName) { | ||
'Enterprise' { | ||
$targetUrl = "$($Context.ApiBaseUri)/enterprises/$Enterprise/settings/apps/new" | ||
} | ||
'Organization' { | ||
$targetUrl = "$($Context.ApiBaseUri)/organizations/$Organization/settings/apps/new" | ||
} | ||
'Personal' { | ||
$targetUrl = "$($Context.ApiBaseUri)/settings/apps/new" | ||
} | ||
} | ||
|
||
if ($State) { | ||
if ($targetUrl -notlike '*?*') { | ||
$targetUrl = "$targetUrl?state=$State" | ||
} else { | ||
$targetUrl = "$targetUrl&state=$State" | ||
} | ||
} | ||
Write-Verbose "Sending manifest to GitHub App creation URL: $targetUrl" | ||
|
||
# Prepare the request body and headers | ||
$body = @{ manifest = $manifest } | ||
|
||
try { | ||
$inputObject = @{ | ||
Method = 'POST' | ||
Uri = $targetUrl | ||
Body = $body | ||
MaximumRedirection = 0 | ||
Authentication = 'Bearer' | ||
Token = $Context.Token | ||
ErrorAction = 'Stop' | ||
} | ||
$response = Invoke-WebRequest @inputObject | ||
} catch { | ||
Write-Error "Error sending manifest: $_" | ||
return | ||
} | ||
|
||
# Extract the 'code' from the redirect Location header | ||
$location = $response.Headers['Location'] | ||
Write-Verbose "Received redirect location: $location" | ||
if (-not $location) { | ||
Write-Error 'No redirect location found. The app may not have been created.' | ||
return | ||
} | ||
$code = $null | ||
if ($location -match 'code=([^&]+)') { | ||
$code = $matches[1] | ||
} | ||
if (-not $code) { | ||
Write-Error 'Failed to parse the app creation code from redirect URL.' | ||
return | ||
} | ||
Write-Verbose "Extracted temporary code: $code" | ||
return $code | ||
} | ||
|
||
end { | ||
Write-Debug "[$stackPath] - End" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
function New-GitHubApp { | ||
<# | ||
.SYNOPSIS | ||
Orchestrates the creation of a GitHub App. | ||
.DESCRIPTION | ||
This function ties together the manifest submission and conversion functions. | ||
It takes all the necessary app parameters, calls the function to send the manifest form, | ||
and then uses the temporary code to retrieve the final GitHub App configuration. | ||
.EXAMPLE | ||
$appDetails = New-GitHubApp -Name "MyApp" -Url "https://example.com" -WebhookURL "https://example.com/webhook" -Token "myToken" | ||
Creates a new GitHub App with the specified name, URL, webhook URL, and authentication token. | ||
.NOTES | ||
[GitHub Apps](https://docs.github.com/apps) | ||
#> | ||
[CmdletBinding(DefaultParameterSetName = 'Personal', SupportsShouldProcess)] | ||
param( | ||
# The name of the GitHub App. | ||
[Parameter()] | ||
[string] $Name, | ||
|
||
# The main URL of the GitHub App. | ||
[Parameter(Mandatory)] | ||
[string] $Url, | ||
|
||
# The webhook URL for event notifications. | ||
[Parameter()] | ||
[string] $WebhookURL, | ||
|
||
# Enables or disables webhooks. | ||
[Parameter()] | ||
[switch] $WebhookEnabled, | ||
|
||
# The redirect URL after authentication. | ||
[Parameter()] | ||
[string] $RedirectUrl, | ||
|
||
# List of callback URLs for OAuth authentication. | ||
[Parameter()] | ||
[string[]] $CallbackUrls, | ||
|
||
# The setup URL for the GitHub App. | ||
[Parameter()] | ||
[string] $SetupUrl, | ||
|
||
# A brief description of the GitHub App. | ||
[Parameter()] | ||
[string] $Description, | ||
|
||
# Specifies whether the app should be publicly visible. | ||
[Parameter()] | ||
[switch] $Public, | ||
|
||
# List of GitHub events the app subscribes to. | ||
[Parameter()] | ||
[string[]] $Events, | ||
|
||
# The permissions required by the GitHub App. | ||
[Parameter()] | ||
[hashtable] $Permissions, | ||
|
||
# Whether the app requests OAuth authorization on installation. | ||
[Parameter()] | ||
[switch] $RequestOAuthOnInstall, | ||
|
||
# Whether the setup process should run again when updating the app. | ||
[Parameter()] | ||
[switch] $SetupOnUpdate, | ||
|
||
# The organization under which the app is being created (Organization parameter set). | ||
[Parameter(ParameterSetName = 'Organization', Mandatory)] | ||
[string] $Organization, | ||
|
||
# The enterprise under which the app is being created (Enterprise parameter set). | ||
[Parameter(ParameterSetName = 'Enterprise', Mandatory)] | ||
[string] $Enterprise, | ||
|
||
# The state parameter for additional configuration. | ||
[Parameter()] | ||
[string] $State | ||
) | ||
begin { | ||
$stackPath = $MyInvocation.MyCommand.Name | ||
Write-Debug "[$stackPath] - Start" | ||
} | ||
process { | ||
Write-Verbose 'Initiating GitHub App creation process...' | ||
# Step 1: Send manifest and get the temporary code | ||
$params = @{ | ||
Name = $Name | ||
Url = $Url | ||
WebhookEnabled = $WebhookEnabled | ||
WebhookURL = $WebhookURL | ||
RedirectUrl = $RedirectUrl | ||
CallbackUrls = $CallbackUrls | ||
SetupUrl = $SetupUrl | ||
Description = $Description | ||
Public = $Public | ||
Events = $Events | ||
Permissions = $Permissions | ||
RequestOAuthOnInstall = $RequestOAuthOnInstall | ||
SetupOnUpdate = $SetupOnUpdate | ||
Enterprise = $Enterprise | ||
Org = $Organization | ||
State = $State | ||
} | ||
$code = Invoke-GitHubAppCreationForm @params | ||
|
||
if (-not $code) { | ||
Write-Error 'Failed to retrieve temporary code from GitHub App manifest submission.' | ||
return | ||
} | ||
|
||
# Step 2: Convert the temporary code into final app details | ||
if ($PSCmdlet.ShouldProcess("$Name", 'Create GitHub App')) { | ||
$appDetails = Convert-GitHubAppManifest -Code $code -Context $Context | ||
} | ||
if (-not $appDetails) { | ||
Write-Error 'Failed to convert GitHub App manifest into final configuration.' | ||
return | ||
} | ||
|
||
Write-Verbose 'GitHub App created successfully.' | ||
return $appDetails | ||
} | ||
end { | ||
Write-Debug "[$stackPath] - End" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters