Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
924cf38
🚀 [Feature]: Enhance Connect-GitHubApp to support parallel connection…
MariusStorhaug Sep 17, 2025
9ad6865
🚀 [Feature]: Improve error handling and parallel processing in Connec…
MariusStorhaug Sep 17, 2025
6454a00
Add initial test scripts for GitHub API interactions
MariusStorhaug Sep 17, 2025
a253921
🚀 [Feature]: Refactor Connect-GitHubApp to use module version variabl…
MariusStorhaug Sep 17, 2025
7212939
Update src/functions/public/Auth/Connect-GitHubApp.ps1
MariusStorhaug Sep 17, 2025
27cd26f
🚀 [Refactor]: Improve code readability by formatting context object c…
MariusStorhaug Sep 17, 2025
9bb314b
🚀 [Feature]: Add 'Enterprise SCIM' permission definition to GitHubPer…
MariusStorhaug Sep 17, 2025
2ea9f4b
🚀 [Refactor]: Adjust ThrottleLimit calculation and implement retry lo…
MariusStorhaug Sep 17, 2025
5fc1cb2
Make New-GithubAppInstallationAccessToken a public function
MariusStorhaug Sep 20, 2025
cbf875d
🚀 [Feature]: Implement GitHub App installation functions and enhance …
MariusStorhaug Sep 20, 2025
cfb7f50
🚀 [Refactor]: Rename UpdateStatus to SetStatus and streamline permiss…
MariusStorhaug Sep 20, 2025
9ef022d
Renamed some functions based on what they do. + better sorting
MariusStorhaug Sep 20, 2025
9a90097
🚀 [Refactor]: Remove redundant AppID property from GitHubApp class
MariusStorhaug Sep 20, 2025
76495d5
🚀 [Refactor]: Simplify GitHubApp initialization by removing app_id an…
MariusStorhaug Sep 20, 2025
584cd17
🚀 [Fix]: Ensure Events property is properly initialized as an array i…
MariusStorhaug Sep 20, 2025
aa2fc89
🚀 [Refactor]: Update GitHubAppInstallation constructor to use GitHubA…
MariusStorhaug Sep 20, 2025
9c8cb9a
🚀 [Fix]: Correct typo in example usage of Get-GitHubAppInstallationFo…
MariusStorhaug Sep 20, 2025
2ef732f
🚀 [Refactor]: Remove unnecessary retrieval of authenticated app in Ge…
MariusStorhaug Sep 20, 2025
2a63509
🚀 [Refactor]: Remove retrieval of authenticated app in Get-GitHubAppI…
MariusStorhaug Sep 20, 2025
695bf4f
🚀 [Refactor]: Update synopsis and parameter set names in Get-GitHubAp…
MariusStorhaug Sep 20, 2025
db58e23
🚀 [Refactor]: Update GitHubAppInstallation constructor calls to use H…
MariusStorhaug Sep 20, 2025
a66329e
🚀 [Refactor]: Simplify Connect-GitHubApp calls by consolidating param…
MariusStorhaug Sep 20, 2025
4e92ad6
🚀 [Refactor]: Add App property to GitHubAppContext for better context…
MariusStorhaug Sep 20, 2025
9558950
🚀 [Refactor]: Update Get-GitHubApp calls to use Slug parameter and im…
MariusStorhaug Sep 20, 2025
69a02e6
🚀 [Refactor]: Update example in Get-GitHubApp documentation to use Sl…
MariusStorhaug Sep 20, 2025
f37247f
🚀 [Refactor]: Enhance GitHub app constructors to support null coalesc…
MariusStorhaug Sep 20, 2025
7e39c35
🚀 [Refactor]: Simplify GitHubAppInstallation constructor by assigning…
MariusStorhaug Sep 20, 2025
3b31737
🚀 [Refactor]: Update GitHubAppInstallation constructor to use hashtab…
MariusStorhaug Sep 21, 2025
7307616
🚀 [Refactor]: Update output messages in Connect-GitHubAccount and Con…
MariusStorhaug Sep 21, 2025
729a4d1
🚀 [Refactor]: Enhance logging in Apps.Tests by adding detailed output…
MariusStorhaug Sep 21, 2025
b11606b
🚀 [Refactor]: Update logging in Apps.Tests to specify context retriev…
MariusStorhaug Sep 21, 2025
986c0d5
🚀 [Refactor]: Optimize ComparePermissionLists method by replacing for…
MariusStorhaug Sep 21, 2025
57f49ad
🚀 [Refactor]: Replace ComparePermissionLists method with Compare-Obje…
MariusStorhaug Sep 21, 2025
335a6fa
🚀 [Refactor]: Uncomment and enhance test cases for GitHub App functio…
MariusStorhaug Sep 21, 2025
5d9d4d8
🚀 [Refactor]: Uncomment and enable assertions for GitHub App connecti…
MariusStorhaug Sep 21, 2025
fe680d1
🚀 [Refactor]: Consolidate GitHubPermission class; remove Get-GitHubPe…
MariusStorhaug Sep 21, 2025
5181267
🚀 [Refactor]: Update permission checks in Apps.Tests to use GitHubPer…
MariusStorhaug Sep 21, 2025
1f9e958
Merge branch 'main' of https://github.com/PSModule/GitHub into parall…
MariusStorhaug Sep 21, 2025
f38eba3
🚀 [Refactor]: Update permission handling in Apps.Tests and Permission…
MariusStorhaug Sep 22, 2025
064030c
Implement code changes to enhance functionality and improve performance
MariusStorhaug Sep 22, 2025
7093cee
🚀 [Refactor]: Update GitHubPermission method calls for consistency an…
MariusStorhaug Sep 22, 2025
23de006
Add comprehensive Pester tests for GitHub API interactions
MariusStorhaug Sep 22, 2025
6a92701
🚀 [Refactor]: Uncomment skipped sections in PSModule.yml for improved…
MariusStorhaug Sep 22, 2025
e4b1a1a
🚀 [Refactor]: Enhance Connect-GitHubApp function to support installat…
MariusStorhaug Sep 24, 2025
f235525
🚀 [Refactor]: Enhance GitHub organization handling by adding URL prop…
MariusStorhaug Sep 24, 2025
120694b
🚀 [Refactor]: Update GitHub app installation functions to include App…
MariusStorhaug Sep 24, 2025
6ac41ff
Add initial test scripts for GitHub API interactions
MariusStorhaug Sep 25, 2025
6e57a1b
🚀 [Refactor]: Simplify GitHubAppInstallation constructor by removing …
MariusStorhaug Sep 25, 2025
32c6dcb
🚀 [Refactor]: Remove unused Installation property from GitHubAppInsta…
MariusStorhaug Sep 25, 2025
e24e64d
🚀 [Refactor]: Update GitHubOrganization constructors to streamline in…
MariusStorhaug Sep 25, 2025
2c36eeb
🚀 [Refactor]: Update GitHubOrganization instantiation to directly inc…
MariusStorhaug Sep 25, 2025
4905669
🚀 [Refactor]: Update GitHubAppInstallation instantiation to directly …
MariusStorhaug Sep 25, 2025
d893b88
🚀 [Refactor]: Enhance GitHubAppInstallation constructor to conditiona…
MariusStorhaug Sep 25, 2025
0fc891e
Milemarker 51
MariusStorhaug Sep 26, 2025
a4e8543
🚀 [Enhancement]: Add ThrottleLimit parameter to Connect-GitHubApp for…
MariusStorhaug Sep 26, 2025
0b25b46
🚀 [Refactor]: Update module import statement in Connect-GitHubApp to …
MariusStorhaug Sep 26, 2025
e80c638
🚀 [Enhancement]: Add Get-LocalModule function to retrieve the current…
MariusStorhaug Sep 26, 2025
cfa2510
🚀 [Refactor]: Update module import in Connect-GitHubApp to use scoped…
MariusStorhaug Sep 26, 2025
ee70b56
🚀 [Refactor]: Initialize contextParamList as an array and append sele…
MariusStorhaug Sep 26, 2025
be2966a
🚀 [Refactor]: Simplify contextParamList initialization and improve co…
MariusStorhaug Sep 26, 2025
91ce75f
🚀 [Refactor]: Replace AddRange with foreach loop for adding context p…
MariusStorhaug Sep 26, 2025
128418e
🚀 [Refactor]: Initialize contextParamList as an array and update cont…
MariusStorhaug Sep 26, 2025
46f54a0
🚀 [Add]: Implement Revoke-GitHubAppInstallationAccessToken function f…
MariusStorhaug Sep 26, 2025
4311c14
🚀 [Refactor]: Update contextParamList handling to append selected ins…
MariusStorhaug Sep 26, 2025
2a568a5
🚀 [Refactor]: Replace foreach loop with direct contextParams usage fo…
MariusStorhaug Sep 26, 2025
6b05793
🚀 [Add]: Introduce ThrottleLimit parameter to Disconnect-GitHubAccoun…
MariusStorhaug Sep 26, 2025
0662c9a
🚀 [Add]: Reintroduce Remove-GitHubContext filter for managing context…
MariusStorhaug Sep 26, 2025
18429c4
fix
MariusStorhaug Sep 26, 2025
0fa48ec
Merge branch 'parallelConnect' of https://github.com/PSModule/GitHub …
MariusStorhaug Sep 26, 2025
3d377d8
🚀 [Refactor]: Enhance logging in 'Installation' context by adding det…
MariusStorhaug Sep 27, 2025
0a36360
🚀 [Refactor]: Add -Debug and -Verbose parameters to Connect-GitHubApp…
MariusStorhaug Sep 27, 2025
3aa446e
🚀 [Refactor]: Comment out existing tests for GitHubApp and GitHubAppI…
MariusStorhaug Sep 27, 2025
e9a2786
🚀 [Refactor]: Initialize context parameter list and update comment fo…
MariusStorhaug Sep 27, 2025
424acd9
🚀 [Refactor]: Update Get-GitHubContext and Disconnect-GitHubAccount f…
MariusStorhaug Sep 27, 2025
33b05d5
🚀 [Refactor]: Improve debug logging in Get-GitHubContext and fix cont…
MariusStorhaug Sep 27, 2025
469824b
🚀 [Refactor]: Update context collection in Get-GitHubContext to use S…
MariusStorhaug Sep 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions .github/PSModule.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
Test:
CodeCoverage:
PercentTarget: 50
# TestResults:
# Skip: true
# SourceCode:
# Skip: true
# PSModule:
# Skip: true
# Module:
# Windows:
# Skip: true
# MacOS:
# Skip: true
# Build:
# Docs:
# Skip: true
TestResults:
Skip: true
SourceCode:
Skip: true
PSModule:
Skip: true
Module:
Windows:
Skip: true
MacOS:
Skip: true
Build:
Docs:
Skip: true
209 changes: 139 additions & 70 deletions src/functions/public/Auth/Connect-GitHubApp.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
.DESCRIPTION
Connects to GitHub using a GitHub App to generate installation access tokens and create contexts for targets.
This function supports recursive processing and parallel connections to multiple installations.
Available target types:
- User
Expand All @@ -14,7 +15,7 @@
.EXAMPLE
Connect-GitHubApp
Connects to GitHub as all available targets using the logged in GitHub App.
Connects to GitHub as all available targets using the logged in GitHub App in parallel.
.EXAMPLE
Connect-GitHubApp -User 'octocat'
Expand All @@ -31,6 +32,16 @@
Connects to GitHub as the enterprise 'msx' using the logged in GitHub App.
.EXAMPLE
Get-GitHubAppInstallation | Connect-GitHubApp -ThrottleLimit 4
Gets all app installations and connects to them in parallel with a maximum of 4 concurrent connections.
.EXAMPLE
Connect-GitHubApp -User '*', -Organization 'psmodule', 'github' -ThrottleLimit 8
Connects to all users and the specified organizations in parallel with a maximum of 8 concurrent connections.
.NOTES
[Authenticating to the REST API](https://docs.github.com/rest/overview/other-authentication-methods#authenticating-for-saml-sso)
Expand All @@ -41,23 +52,32 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Is the CLI part of the module.')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '',
Justification = 'The tokens are received as clear text. Mitigating exposure by removing variables and performing garbage collection.')]
[CmdletBinding(DefaultParameterSetName = '__AllParameterSets')]
[CmdletBinding(DefaultParameterSetName = 'All Installations')]
param(
# The user account to connect to.
[Parameter(ParameterSetName = 'Filtered')]
[Parameter(ParameterSetName = 'Filtered', ValueFromPipelineByPropertyName)]
[SupportsWildcards()]
[string[]] $User,

# The organization to connect to.
[Parameter(ParameterSetName = 'Filtered')]
[Parameter(ParameterSetName = 'Filtered', ValueFromPipelineByPropertyName)]
[SupportsWildcards()]
[string[]] $Organization,

# The enterprise to connect to.
[Parameter(ParameterSetName = 'Filtered')]
[Parameter(ParameterSetName = 'Filtered', ValueFromPipelineByPropertyName)]
[SupportsWildcards()]
[string[]] $Enterprise,

# Installation objects from pipeline for parallel processing.
[Parameter(Mandatory, ParameterSetName = 'Installation', ValueFromPipeline)]
[GitHubAppInstallation[]] $Installation,

# The maximum number of parallel operations to run at once.
[Parameter(ParameterSetName = 'Filtered')]
[Parameter(ParameterSetName = 'Installation')]
[uint] $ThrottleLimit = ([Environment]::ProcessorCount * 2),

# Passes the context object to the pipeline.
[Parameter()]
[switch] $PassThru,
Expand All @@ -82,14 +102,100 @@
Write-Debug "[$stackPath] - Start"
$Context = Resolve-GitHubContext -Context $Context
Assert-GitHubContext -Context $Context -AuthType App
$selectedInstallations = @()
}

process {
$installations = Get-GitHubAppInstallation -Context $Context
$selectedInstallations = @()
Write-Verbose "Found [$($installations.Count)] installations."
switch ($PSCmdlet.ParameterSetName) {
'Installation' {
if ($Installation.Count -eq 1) {
Write-Verbose "Processing installation [$($Installation.Target.Name)] [$($Installation.ID)]"
$token = New-GitHubAppInstallationAccessToken -Context $Context -ID $Installation.ID

$contextParams = @{
AuthType = [string]'IAT'
TokenType = [string]'ghs'
DisplayName = [string]$Context.DisplayName
ApiBaseUri = [string]$Context.ApiBaseUri
ApiVersion = [string]$Context.ApiVersion
HostName = [string]$Context.HostName
HttpVersion = [string]$Context.HttpVersion
PerPage = [int]$Context.PerPage
ClientID = [string]$Context.ClientID
InstallationID = [string]$Installation.ID
Permissions = [GitHubPermission[]]$Installation.Permissions
Events = [string[]]$Installation.Events
InstallationType = [string]$Installation.Type
Token = [securestring]$token.Token
TokenExpiresAt = [datetime]$token.ExpiresAt
}

switch ($Installation.Type) {
'User' {
$contextParams['InstallationName'] = [string]$installation.Target.Name
$contextParams['Owner'] = [string]$installation.Target.Name
}
'Organization' {
$contextParams['InstallationName'] = [string]$installation.Target.Name
$contextParams['Owner'] = [string]$installation.Target.Name
}
'Enterprise' {
$contextParams['InstallationName'] = [string]$installation.Target.Name
$contextParams['Enterprise'] = [string]$installation.Target.Name
}
}
Write-Verbose 'Logging in using a managed installation access token...'
$contextParams | Format-Table | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
while ($true) {
try {
$contextObj = [GitHubAppInstallationContext]::new((Set-GitHubContext -Context $contextParams.Clone() -PassThru -Default:$Default))
} catch {
if ($attempts -lt 3) {
$attempts++
Write-Warning "Failed to create context. Retrying... [$attempts]"
Start-Sleep -Seconds (1 * $attempts)
} else {
throw $_
}
}
}
$contextObj | Format-List | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
if (-not $Silent) {
$name = $contextObj.Name
if ($script:IsGitHubActions) {
$green = $PSStyle.Foreground.Green
$reset = $PSStyle.Reset
Write-Host "$green$reset Connected $name!"
} else {
Write-Host '' -ForegroundColor Green -NoNewline
Write-Host "Connected $name!"
}
}
if ($PassThru) {
Write-Debug "Passing context [$contextObj] to the pipeline."
Write-Output $contextObj
}
return
}

$Installation | ForEach-Object -ThrottleLimit $ThrottleLimit -UseNewRunspace -Parallel {
Write-Host "Using GitHub $($script:PSModuleInfo.ModuleVersion)"
Import-Module -Name 'GitHub' -RequiredVersion $script:PSModuleInfo.ModuleVersion
$params = @{
Installation = $_
Context = $using:Context
PassThru = $using:PassThru
Silent = $using:Silent
Default = $using:Default
}
Connect-GitHubApp @params
}
return
}
'Filtered' {
$installations = Get-GitHubAppInstallation -Context $Context
Write-Verbose "Found [$($installations.Count)] installations."

$User | ForEach-Object {
$userItem = $_
Write-Verbose "User filter: [$userItem]."
Expand All @@ -111,73 +217,36 @@
$_.Type -eq 'Enterprise' -and $_.Target.Name -like $enterpriseItem
}
}
}
default {
Write-Verbose 'No target specified. Connecting to all installations.'
$selectedInstallations = $installations
}
}

Write-Verbose "Found [$($selectedInstallations.Count)] installations for the target."
$selectedInstallations | ForEach-Object {
$installation = $_
Write-Verbose "Processing installation [$($installation.Target.Name)] [$($installation.id)]"
$token = New-GitHubAppInstallationAccessToken -Context $Context -ID $installation.id

$contextParams = @{
AuthType = [string]'IAT'
TokenType = [string]'ghs'
DisplayName = [string]$Context.DisplayName
ApiBaseUri = [string]$Context.ApiBaseUri
ApiVersion = [string]$Context.ApiVersion
HostName = [string]$Context.HostName
HttpVersion = [string]$Context.HttpVersion
PerPage = [int]$Context.PerPage
ClientID = [string]$Context.ClientID
InstallationID = [string]$installation.ID
Permissions = [GitHubPermission[]]$installation.Permissions
Events = [string[]]$installation.Events
InstallationType = [string]$installation.Type
Token = [securestring]$token.Token
TokenExpiresAt = [datetime]$token.ExpiresAt
}

switch ($installation.Type) {
'User' {
$contextParams['InstallationName'] = [string]$installation.Target.Name
$contextParams['Owner'] = [string]$installation.Target.Name
}
'Organization' {
$contextParams['InstallationName'] = [string]$installation.Target.Name
$contextParams['Owner'] = [string]$installation.Target.Name
}
'Enterprise' {
$contextParams['InstallationName'] = [string]$installation.Target.Name
$contextParams['Enterprise'] = [string]$installation.Target.Name
$selectedInstallations | ForEach-Object -ThrottleLimit $ThrottleLimit -UseNewRunspace -Parallel {
Import-Module -Name 'GitHub' -RequiredVersion $script:PSModuleInfo.ModuleVersion -Force
$params = @{
Installation = $_
Context = $using:Context
PassThru = $using:PassThru
Silent = $using:Silent
Default = $using:Default
}
Connect-GitHubApp @params
}
return
}
Write-Verbose 'Logging in using a managed installation access token...'
$contextParams | Format-Table | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
$contextObj = [GitHubAppInstallationContext]::new((Set-GitHubContext -Context $contextParams.Clone() -PassThru -Default:$Default))
$contextObj | Format-List | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
if (-not $Silent) {
$name = $contextObj.Name
if ($script:IsGitHubActions) {
$green = $PSStyle.Foreground.Green
$reset = $PSStyle.Reset
Write-Host "$green$reset Connected $name!"
} else {
Write-Host '' -ForegroundColor Green -NoNewline
Write-Host "Connected $name!"
'All Installations' {
Write-Verbose 'No target specified. Connecting to all installations.'
$selectedInstallations = Get-GitHubAppInstallation -Context $Context
$selectedInstallations | ForEach-Object -ThrottleLimit $ThrottleLimit -UseNewRunspace -Parallel {
Import-Module -Name 'GitHub' -RequiredVersion $script:PSModuleInfo.ModuleVersion -Force
$params = @{
Installation = $_
Context = $using:Context
PassThru = $using:PassThru
Silent = $using:Silent
Default = $using:Default
}
Connect-GitHubApp @params
}
return
}
if ($PassThru) {
Write-Debug "Passing context [$contextObj] to the pipeline."
Write-Output $contextObj
}
$contextParams.Clear()
}

}

end {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading