Skip to content

Commit 924cf38

Browse files
🚀 [Feature]: Enhance Connect-GitHubApp to support parallel connections and improve examples
1 parent e66d934 commit 924cf38

File tree

1 file changed

+123
-70
lines changed

1 file changed

+123
-70
lines changed

‎src/functions/public/Auth/Connect-GitHubApp.ps1‎

Lines changed: 123 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
66
.DESCRIPTION
77
Connects to GitHub using a GitHub App to generate installation access tokens and create contexts for targets.
8+
This function supports recursive processing and parallel connections to multiple installations.
89
910
Available target types:
1011
- User
@@ -14,7 +15,7 @@
1415
.EXAMPLE
1516
Connect-GitHubApp
1617
17-
Connects to GitHub as all available targets using the logged in GitHub App.
18+
Connects to GitHub as all available targets using the logged in GitHub App in parallel.
1819
1920
.EXAMPLE
2021
Connect-GitHubApp -User 'octocat'
@@ -31,6 +32,16 @@
3132
3233
Connects to GitHub as the enterprise 'msx' using the logged in GitHub App.
3334
35+
.EXAMPLE
36+
Get-GitHubAppInstallation | Connect-GitHubApp -ThrottleLimit 4
37+
38+
Gets all app installations and connects to them in parallel with a maximum of 4 concurrent connections.
39+
40+
.EXAMPLE
41+
Connect-GitHubApp -User '*', -Organization 'psmodule', 'github' -ThrottleLimit 8
42+
43+
Connects to all users and the specified organizations in parallel with a maximum of 8 concurrent connections.
44+
3445
.NOTES
3546
[Authenticating to the REST API](https://docs.github.com/rest/overview/other-authentication-methods#authenticating-for-saml-sso)
3647
@@ -41,23 +52,32 @@
4152
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Is the CLI part of the module.')]
4253
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '',
4354
Justification = 'The tokens are received as clear text. Mitigating exposure by removing variables and performing garbage collection.')]
44-
[CmdletBinding(DefaultParameterSetName = '__AllParameterSets')]
55+
[CmdletBinding(DefaultParameterSetName = 'All Installations')]
4556
param(
4657
# The user account to connect to.
47-
[Parameter(ParameterSetName = 'Filtered')]
58+
[Parameter(ParameterSetName = 'Filtered', ValueFromPipelineByPropertyName)]
4859
[SupportsWildcards()]
4960
[string[]] $User,
5061

5162
# The organization to connect to.
52-
[Parameter(ParameterSetName = 'Filtered')]
63+
[Parameter(ParameterSetName = 'Filtered', ValueFromPipelineByPropertyName)]
5364
[SupportsWildcards()]
5465
[string[]] $Organization,
5566

5667
# The enterprise to connect to.
57-
[Parameter(ParameterSetName = 'Filtered')]
68+
[Parameter(ParameterSetName = 'Filtered', ValueFromPipelineByPropertyName)]
5869
[SupportsWildcards()]
5970
[string[]] $Enterprise,
6071

72+
# Installation objects from pipeline for parallel processing.
73+
[Parameter(Mandatory, ParameterSetName = 'Installation', ValueFromPipeline)]
74+
[GitHubAppInstallation[]] $Installation,
75+
76+
# The maximum number of parallel operations to run at once.
77+
[Parameter(ParameterSetName = 'Filtered')]
78+
[Parameter(ParameterSetName = 'Installation')]
79+
[uint] $ThrottleLimit = ([Environment]::ProcessorCount * 2),
80+
6181
# Passes the context object to the pipeline.
6282
[Parameter()]
6383
[switch] $PassThru,
@@ -82,14 +102,86 @@
82102
Write-Debug "[$stackPath] - Start"
83103
$Context = Resolve-GitHubContext -Context $Context
84104
Assert-GitHubContext -Context $Context -AuthType App
105+
$selectedInstallations = @()
85106
}
86107

87108
process {
88-
$installations = Get-GitHubAppInstallation -Context $Context
89-
$selectedInstallations = @()
90-
Write-Verbose "Found [$($installations.Count)] installations."
91109
switch ($PSCmdlet.ParameterSetName) {
110+
'Installation' {
111+
if ($Installation.Count -eq 1) {
112+
Write-Verbose "Processing installation [$($Installation.Target.Name)] [$($Installation.ID)]"
113+
$token = New-GitHubAppInstallationAccessToken -Context $Context -ID $Installation.ID
114+
115+
$contextParams = @{
116+
AuthType = [string]'IAT'
117+
TokenType = [string]'ghs'
118+
DisplayName = [string]$Context.DisplayName
119+
ApiBaseUri = [string]$Context.ApiBaseUri
120+
ApiVersion = [string]$Context.ApiVersion
121+
HostName = [string]$Context.HostName
122+
HttpVersion = [string]$Context.HttpVersion
123+
PerPage = [int]$Context.PerPage
124+
ClientID = [string]$Context.ClientID
125+
InstallationID = [string]$installation.ID
126+
Permissions = [GitHubPermission[]]$installation.Permissions
127+
Events = [string[]]$installation.Events
128+
InstallationType = [string]$installation.Type
129+
Token = [securestring]$token.Token
130+
TokenExpiresAt = [datetime]$token.ExpiresAt
131+
}
132+
133+
switch ($installation.Type) {
134+
'User' {
135+
$contextParams['InstallationName'] = [string]$installation.Target.Name
136+
$contextParams['Owner'] = [string]$installation.Target.Name
137+
}
138+
'Organization' {
139+
$contextParams['InstallationName'] = [string]$installation.Target.Name
140+
$contextParams['Owner'] = [string]$installation.Target.Name
141+
}
142+
'Enterprise' {
143+
$contextParams['InstallationName'] = [string]$installation.Target.Name
144+
$contextParams['Enterprise'] = [string]$installation.Target.Name
145+
}
146+
}
147+
Write-Verbose 'Logging in using a managed installation access token...'
148+
$contextParams | Format-Table | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
149+
$contextObj = [GitHubAppInstallationContext]::new((Set-GitHubContext -Context $contextParams.Clone() -PassThru -Default:$Default))
150+
$contextObj | Format-List | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
151+
if (-not $Silent) {
152+
$name = $contextObj.Name
153+
if ($script:IsGitHubActions) {
154+
$green = $PSStyle.Foreground.Green
155+
$reset = $PSStyle.Reset
156+
Write-Host "$green✓$reset Connected $name!"
157+
} else {
158+
Write-Host '✓ ' -ForegroundColor Green -NoNewline
159+
Write-Host "Connected $name!"
160+
}
161+
}
162+
if ($PassThru) {
163+
Write-Debug "Passing context [$contextObj] to the pipeline."
164+
Write-Output $contextObj
165+
}
166+
return
167+
}
168+
169+
$Installation | ForEach-Object -ThrottleLimit $ThrottleLimit -Parallel {
170+
$params = @{
171+
ID = $_.ID
172+
Context = $using:Context
173+
PassThru = $using:PassThru
174+
Silent = $using:Silent
175+
Default = $using:Default
176+
}
177+
Connect-GitHubApp @params
178+
}
179+
return
180+
}
92181
'Filtered' {
182+
$installations = Get-GitHubAppInstallation -Context $Context
183+
Write-Verbose "Found [$($installations.Count)] installations."
184+
93185
$User | ForEach-Object {
94186
$userItem = $_
95187
Write-Verbose "User filter: [$userItem]."
@@ -111,73 +203,34 @@
111203
$_.Type -eq 'Enterprise' -and $_.Target.Name -like $enterpriseItem
112204
}
113205
}
114-
}
115-
default {
116-
Write-Verbose 'No target specified. Connecting to all installations.'
117-
$selectedInstallations = $installations
118-
}
119-
}
120-
121-
Write-Verbose "Found [$($selectedInstallations.Count)] installations for the target."
122-
$selectedInstallations | ForEach-Object {
123-
$installation = $_
124-
Write-Verbose "Processing installation [$($installation.Target.Name)] [$($installation.id)]"
125-
$token = New-GitHubAppInstallationAccessToken -Context $Context -ID $installation.id
126-
127-
$contextParams = @{
128-
AuthType = [string]'IAT'
129-
TokenType = [string]'ghs'
130-
DisplayName = [string]$Context.DisplayName
131-
ApiBaseUri = [string]$Context.ApiBaseUri
132-
ApiVersion = [string]$Context.ApiVersion
133-
HostName = [string]$Context.HostName
134-
HttpVersion = [string]$Context.HttpVersion
135-
PerPage = [int]$Context.PerPage
136-
ClientID = [string]$Context.ClientID
137-
InstallationID = [string]$installation.ID
138-
Permissions = [GitHubPermission[]]$installation.Permissions
139-
Events = [string[]]$installation.Events
140-
InstallationType = [string]$installation.Type
141-
Token = [securestring]$token.Token
142-
TokenExpiresAt = [datetime]$token.ExpiresAt
143-
}
144-
145-
switch ($installation.Type) {
146-
'User' {
147-
$contextParams['InstallationName'] = [string]$installation.Target.Name
148-
$contextParams['Owner'] = [string]$installation.Target.Name
149-
}
150-
'Organization' {
151-
$contextParams['InstallationName'] = [string]$installation.Target.Name
152-
$contextParams['Owner'] = [string]$installation.Target.Name
153-
}
154-
'Enterprise' {
155-
$contextParams['InstallationName'] = [string]$installation.Target.Name
156-
$contextParams['Enterprise'] = [string]$installation.Target.Name
206+
$selectedInstallations | ForEach-Object -ThrottleLimit $ThrottleLimit -Parallel {
207+
$params = @{
208+
ID = $_.ID
209+
Context = $using:Context
210+
PassThru = $using:PassThru
211+
Silent = $using:Silent
212+
Default = $using:Default
213+
}
214+
Connect-GitHubApp @params
157215
}
216+
return
158217
}
159-
Write-Verbose 'Logging in using a managed installation access token...'
160-
$contextParams | Format-Table | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
161-
$contextObj = [GitHubAppInstallationContext]::new((Set-GitHubContext -Context $contextParams.Clone() -PassThru -Default:$Default))
162-
$contextObj | Format-List | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
163-
if (-not $Silent) {
164-
$name = $contextObj.Name
165-
if ($script:IsGitHubActions) {
166-
$green = $PSStyle.Foreground.Green
167-
$reset = $PSStyle.Reset
168-
Write-Host "$green✓$reset Connected $name!"
169-
} else {
170-
Write-Host '✓ ' -ForegroundColor Green -NoNewline
171-
Write-Host "Connected $name!"
218+
'All Installations' {
219+
Write-Verbose 'No target specified. Connecting to all installations.'
220+
$selectedInstallations = Get-GitHubAppInstallation -Context $Context
221+
$selectedInstallations | ForEach-Object -ThrottleLimit $ThrottleLimit -Parallel {
222+
$params = @{
223+
ID = $_.ID
224+
Context = $using:Context
225+
PassThru = $using:PassThru
226+
Silent = $using:Silent
227+
Default = $using:Default
228+
}
229+
Connect-GitHubApp @params
172230
}
231+
return
173232
}
174-
if ($PassThru) {
175-
Write-Debug "Passing context [$contextObj] to the pipeline."
176-
Write-Output $contextObj
177-
}
178-
$contextParams.Clear()
179233
}
180-
181234
}
182235

183236
end {

0 commit comments

Comments
 (0)