From dacf1071a88d22ad1ac37547ebf92f27096e23a0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 12 Sep 2025 13:45:18 +0000
Subject: [PATCH 01/43] Initial plan
From 65640847afcd47eea26e66450dc9a7ee3495732f Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 12 Sep 2025 13:55:21 +0000
Subject: [PATCH 02/43] Add status tracking to GitHubAppInstallation class to
compare permissions and events
Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>
---
.../public/App/GitHubAppInstallation.ps1 | 98 +++++++++++++++++++
...tHubAppInstallationForAuthenticatedApp.ps1 | 5 +-
2 files changed, 102 insertions(+), 1 deletion(-)
diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1
index 96fd2831c..0459560f8 100644
--- a/src/classes/public/App/GitHubAppInstallation.ps1
+++ b/src/classes/public/App/GitHubAppInstallation.ps1
@@ -41,8 +41,54 @@
# The URL to the target's profile based on the target type.
[string] $Url
+ # The status indicating if the installation permissions and events match the app's configuration.
+ [string] $Status
+
GitHubAppInstallation() {}
+ # Helper method to compare installation permissions and events with app configuration
+ hidden [string] CompareWithAppConfiguration([pscustomobject] $AppPermissions, [string[]] $AppEvents) {
+ if ($null -eq $AppPermissions -or $null -eq $AppEvents) {
+ return 'Unknown'
+ }
+
+ # Compare permissions - check if installation has all the permissions that the app requires
+ $permissionsMatch = $true
+ if ($AppPermissions.PSObject.Properties) {
+ foreach ($permission in $AppPermissions.PSObject.Properties) {
+ $appPermissionLevel = $permission.Value
+ $installationPermissionLevel = $this.Permissions.PSObject.Properties[$permission.Name]?.Value
+
+ # If app requires a permission but installation doesn't have it, or has lower level
+ if ($appPermissionLevel -ne 'none' -and $installationPermissionLevel -ne $appPermissionLevel) {
+ $permissionsMatch = $false
+ break
+ }
+ }
+ }
+
+ # Compare events - check if installation subscribes to all events that the app wants
+ $eventsMatch = $true
+ if ($AppEvents -and $AppEvents.Count -gt 0) {
+ foreach ($appEvent in $AppEvents) {
+ if ($appEvent -notin $this.Events) {
+ $eventsMatch = $false
+ break
+ }
+ }
+ }
+
+ if ($permissionsMatch -and $eventsMatch) {
+ return 'UpToDate'
+ } elseif (-not $permissionsMatch -and -not $eventsMatch) {
+ return 'PermissionsAndEventsOutdated'
+ } elseif (-not $permissionsMatch) {
+ return 'PermissionsOutdated'
+ } else {
+ return 'EventsOutdated'
+ }
+ }
+
GitHubAppInstallation([PSCustomObject] $Object) {
$this.ID = $Object.id
$this.App = [GitHubApp]::new(
@@ -63,6 +109,30 @@
$this.SuspendedAt = $Object.suspended_at
$this.SuspendedBy = [GitHubUser]::new($Object.suspended_by)
$this.Url = $Object.html_url
+ $this.Status = 'Unknown'
+ }
+
+ GitHubAppInstallation([PSCustomObject] $Object, [GitHubApp] $App) {
+ $this.ID = $Object.id
+ $this.App = [GitHubApp]::new(
+ [PSCustomObject]@{
+ client_id = $Object.client_id
+ app_id = $Object.app_id
+ app_slug = $Object.app_slug
+ }
+ )
+ $this.Target = [GitHubOwner]::new($Object.account)
+ $this.Type = $Object.target_type
+ $this.RepositorySelection = $Object.repository_selection
+ $this.Permissions = $Object.permissions
+ $this.Events = , ($Object.events)
+ $this.FilePaths = $Object.single_file_paths
+ $this.CreatedAt = $Object.created_at
+ $this.UpdatedAt = $Object.updated_at
+ $this.SuspendedAt = $Object.suspended_at
+ $this.SuspendedBy = [GitHubUser]::new($Object.suspended_by)
+ $this.Url = $Object.html_url
+ $this.Status = $this.CompareWithAppConfiguration($App.Permissions, $App.Events)
}
GitHubAppInstallation([PSCustomObject] $Object, [string] $Target, [string] $Type, [GitHubContext] $Context) {
@@ -89,5 +159,33 @@
$this.SuspendedAt = $Object.suspended_at
$this.SuspendedBy = [GitHubUser]::new($Object.suspended_by)
$this.Url = "https://$($Context.HostName)/$($Type.ToLower())s/$Target/settings/installations/$($Object.id)"
+ $this.Status = 'Unknown'
+ }
+
+ GitHubAppInstallation([PSCustomObject] $Object, [string] $Target, [string] $Type, [GitHubContext] $Context, [GitHubApp] $App) {
+ $this.ID = $Object.id
+ $this.App = [GitHubApp]::new(
+ [PSCustomObject]@{
+ client_id = $Object.client_id
+ app_id = $Object.app_id
+ app_slug = $Object.app_slug
+ }
+ )
+ $this.Target = [GitHubOwner]@{
+ Name = $Target
+ Type = $Type
+ Url = "https://$($Context.HostName)/$Target"
+ }
+ $this.Type = $Type
+ $this.RepositorySelection = $Object.repository_selection
+ $this.Permissions = $Object.permissions
+ $this.Events = , ($Object.events)
+ $this.FilePaths = $Object.single_file_paths
+ $this.CreatedAt = $Object.created_at
+ $this.UpdatedAt = $Object.updated_at
+ $this.SuspendedAt = $Object.suspended_at
+ $this.SuspendedBy = [GitHubUser]::new($Object.suspended_by)
+ $this.Url = "https://$($Context.HostName)/$($Type.ToLower())s/$Target/settings/installations/$($Object.id)"
+ $this.Status = $this.CompareWithAppConfiguration($App.Permissions, $App.Events)
}
}
diff --git a/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallationForAuthenticatedApp.ps1 b/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallationForAuthenticatedApp.ps1
index afbe9e03c..58f595659 100644
--- a/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallationForAuthenticatedApp.ps1
+++ b/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallationForAuthenticatedApp.ps1
@@ -46,9 +46,12 @@
Context = $Context
}
+ # Get the authenticated app to compare permissions and events
+ $authenticatedApp = Get-GitHubAuthenticatedApp -Context $Context
+
Invoke-GitHubAPI @apiParams | ForEach-Object {
foreach ($installation in $_.Response) {
- [GitHubAppInstallation]::new($installation)
+ [GitHubAppInstallation]::new($installation, $authenticatedApp)
}
}
}
From 439519d60ebd46acab835c9d6b36d243d1940bf8 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 12 Sep 2025 13:58:18 +0000
Subject: [PATCH 03/43] Add Status property to GitHubAppInstallation display
formats and update tests
Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>
---
.../GitHubAppInstallation.Format.ps1xml | 17 +++++++++
tests/Apps.Tests.ps1 | 35 +++++++++++++++++++
2 files changed, 52 insertions(+)
diff --git a/src/formats/GitHubAppInstallation.Format.ps1xml b/src/formats/GitHubAppInstallation.Format.ps1xml
index 876cc43b7..b8f97eca3 100644
--- a/src/formats/GitHubAppInstallation.Format.ps1xml
+++ b/src/formats/GitHubAppInstallation.Format.ps1xml
@@ -20,6 +20,9 @@
+
+
+
@@ -56,6 +59,17 @@
Type
+
+
+ switch ($_.Status) {
+ 'UpToDate' { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.Green)✓$($PSStyle.Reset)" } else { 'UpToDate' } }
+ 'PermissionsOutdated' { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.Yellow)⚠P$($PSStyle.Reset)" } else { 'PermissionsOutdated' } }
+ 'EventsOutdated' { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.Yellow)⚠E$($PSStyle.Reset)" } else { 'EventsOutdated' } }
+ 'PermissionsAndEventsOutdated' { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.Red)✗$($PSStyle.Reset)" } else { 'PermissionsAndEventsOutdated' } }
+ default { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.BrightBlack)?$($PSStyle.Reset)" } else { $_.Status } }
+ }
+
+
CreatedAt
@@ -88,6 +102,9 @@
Type
+
+ Status
+
Url
diff --git a/tests/Apps.Tests.ps1 b/tests/Apps.Tests.ps1
index 44803729b..7f59d3c1f 100644
--- a/tests/Apps.Tests.ps1
+++ b/tests/Apps.Tests.ps1
@@ -93,6 +93,9 @@ Describe 'Apps' {
$installation.SuspendedAt | Should -BeNullOrEmpty
$installation.SuspendedBy | Should -BeOfType 'GitHubUser'
$installation.SuspendedBy | Should -BeNullOrEmpty
+ # Validate the new Status property
+ $installation.Status | Should -Not -BeNullOrEmpty
+ $installation.Status | Should -BeIn @('Unknown', 'UpToDate', 'PermissionsOutdated', 'EventsOutdated', 'PermissionsAndEventsOutdated')
}
}
@@ -120,6 +123,38 @@ Describe 'Apps' {
$installation.SuspendedAt | Should -BeNullOrEmpty
$installation.SuspendedBy | Should -BeOfType 'GitHubUser'
$installation.SuspendedBy | Should -BeNullOrEmpty
+ # Validate the new Status property
+ $installation.Status | Should -Not -BeNullOrEmpty
+ $installation.Status | Should -BeIn @('Unknown', 'UpToDate', 'PermissionsOutdated', 'EventsOutdated', 'PermissionsAndEventsOutdated')
+ }
+
+ It 'Get-GitHubAppInstallation - Status tracking functionality' {
+ $githubApp = Get-GitHubApp
+ $installations = Get-GitHubAppInstallation
+ LogGroup 'Status tracking test' {
+ Write-Host "Testing installation status tracking against app configuration"
+ Write-Host "App Permissions: $($githubApp.Permissions | ConvertTo-Json -Compress)"
+ Write-Host "App Events: $($githubApp.Events -join ', ')"
+ }
+
+ foreach ($installation in $installations) {
+ LogGroup "Installation $($installation.ID) Status" {
+ Write-Host "Installation ID: $($installation.ID)"
+ Write-Host "Target: $($installation.Target.Name)"
+ Write-Host "Status: $($installation.Status)"
+ Write-Host "Installation Permissions: $($installation.Permissions | ConvertTo-Json -Compress)"
+ Write-Host "Installation Events: $($installation.Events -join ', ')"
+ }
+
+ # The status should be calculated based on app vs installation comparison
+ $installation.Status | Should -BeIn @('Unknown', 'UpToDate', 'PermissionsOutdated', 'EventsOutdated', 'PermissionsAndEventsOutdated')
+
+ # When we have app information (which we do in this context), status should not be Unknown
+ # for authenticated app installations
+ if ($PSCmdlet.ParameterSetName -eq 'List installations for the authenticated app') {
+ $installation.Status | Should -Not -Be 'Unknown'
+ }
+ }
}
}
From 4bffffe818a8e8165d3ff84693154c73b776b09b Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Fri, 12 Sep 2025 18:14:57 +0200
Subject: [PATCH 04/43] Fix app link
---
src/classes/public/App/GitHubAppInstallation.ps1 | 16 ++--------------
1 file changed, 2 insertions(+), 14 deletions(-)
diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1
index 0459560f8..7812e3140 100644
--- a/src/classes/public/App/GitHubAppInstallation.ps1
+++ b/src/classes/public/App/GitHubAppInstallation.ps1
@@ -114,13 +114,7 @@
GitHubAppInstallation([PSCustomObject] $Object, [GitHubApp] $App) {
$this.ID = $Object.id
- $this.App = [GitHubApp]::new(
- [PSCustomObject]@{
- client_id = $Object.client_id
- app_id = $Object.app_id
- app_slug = $Object.app_slug
- }
- )
+ $this.App = $App
$this.Target = [GitHubOwner]::new($Object.account)
$this.Type = $Object.target_type
$this.RepositorySelection = $Object.repository_selection
@@ -164,13 +158,7 @@
GitHubAppInstallation([PSCustomObject] $Object, [string] $Target, [string] $Type, [GitHubContext] $Context, [GitHubApp] $App) {
$this.ID = $Object.id
- $this.App = [GitHubApp]::new(
- [PSCustomObject]@{
- client_id = $Object.client_id
- app_id = $Object.app_id
- app_slug = $Object.app_slug
- }
- )
+ $this.App = $App
$this.Target = [GitHubOwner]@{
Name = $Target
Type = $Type
From 896aaac6cf1a74156aab2e036d9cc3cb674faf4b Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Fri, 12 Sep 2025 20:55:29 +0200
Subject: [PATCH 05/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Enhance=20argum?=
=?UTF-8?q?ent=20completers=20for=20GitHub=20configuration=20and=20update?=
=?UTF-8?q?=20authentication=20handling=20in=20API=20version=20retrieval?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/functions/public/Config/completers.ps1 | 35 ++++++++++++++++---
.../public/Meta/Get-GitHubApiVersion.ps1 | 5 ++-
src/variables/private/GitHub.ps1 | 1 -
3 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/src/functions/public/Config/completers.ps1 b/src/functions/public/Config/completers.ps1
index 1165d3170..c498f0497 100644
--- a/src/functions/public/Config/completers.ps1
+++ b/src/functions/public/Config/completers.ps1
@@ -10,10 +10,37 @@
Register-ArgumentCompleter -CommandName Set-GitHubConfig -ParameterName Value -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
- if ($fakeBoundParameters.Name -eq 'CompletionMode') {
- $pattern = switch (Get-GitHubConfig -Name CompletionMode) { 'Contains' { "*$wordToComplete*" } default { "$wordToComplete*" } }
- @('StartsWith', 'Contains') | Where-Object { $_ -like $pattern } | ForEach-Object {
- [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
+ $pattern = switch (Get-GitHubConfig -Name CompletionMode) { 'Contains' { "*$wordToComplete*" } default { "$wordToComplete*" } }
+ switch ($fakeBoundParameters.Name) {
+ 'CompletionMode' {
+ @('StartsWith', 'Contains') | Where-Object { $_ -like $pattern } | ForEach-Object {
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
+ }
+ }
+ 'HttpVersion' {
+ @('1.0', '1.1', '2.0', '3.0') | Where-Object { $_ -like $pattern } | ForEach-Object {
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
+ }
+ }
+ 'EnvironmentType' {
+ @('Local', 'GitHubActions', 'FunctionApp', 'Unknown') | Where-Object { $_ -like $pattern } | ForEach-Object {
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
+ }
+ }
+ 'ApiVersion' {
+ $params = @{
+ Context = $fakeBoundParameters.Context
+ Debug = $false
+ Verbose = $false
+ }
+ Get-GitHubApiVersion @params | Where-Object { $_ -like $pattern } | ForEach-Object {
+ [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
+ }
+ }
+ 'DefaultContext' {
+ Get-GitHubContext -ListAvailable | Where-Object { $_.Name -like $pattern } | ForEach-Object {
+ [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.Name)
+ }
}
}
}
diff --git a/src/functions/public/Meta/Get-GitHubApiVersion.ps1 b/src/functions/public/Meta/Get-GitHubApiVersion.ps1
index 7a618a104..cd9ac2b0a 100644
--- a/src/functions/public/Meta/Get-GitHubApiVersion.ps1
+++ b/src/functions/public/Meta/Get-GitHubApiVersion.ps1
@@ -34,10 +34,13 @@
$stackPath = Get-PSCallStackPath
Write-Debug "[$stackPath] - Start"
$Context = Resolve-GitHubContext -Context $Context -Anonymous $Anonymous
- Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT, Anonymous
+ Assert-GitHubContext -Context $Context -AuthType App, IAT, PAT, UAT, Anonymous
}
process {
+ if ($Context.AuthType -eq 'APP') {
+ $Context = 'Anonymous'
+ }
$apiParams = @{
Method = 'GET'
ApiEndpoint = '/versions'
diff --git a/src/variables/private/GitHub.ps1 b/src/variables/private/GitHub.ps1
index 190de6d2d..c5b04de1e 100644
--- a/src/variables/private/GitHub.ps1
+++ b/src/variables/private/GitHub.ps1
@@ -4,7 +4,6 @@ $script:IsLocal = -not ($script:IsGitHubActions -or $script:IsFunctionApp)
$script:GitHub = [pscustomobject]@{
ContextVault = 'PSModule.GitHub'
TokenPrefixPattern = '(?<=^(ghu|gho|ghs|github_pat|ghp)).*'
- EnvironmentType = Get-GitHubEnvironmentType
DefaultConfig = [GitHubConfig]@{
ID = 'Module'
HostName = ($env:GITHUB_SERVER_URL ?? 'github.com') -replace '^https?://'
From 5dfd0f5e3469abd5c206ae926c5503337aeddc46 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Fri, 12 Sep 2025 21:13:56 +0200
Subject: [PATCH 06/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Make=20the=20Co?=
=?UTF-8?q?ntext=20parameter=20mandatory=20in=20Switch-GitHubContext=20fun?=
=?UTF-8?q?ction?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/functions/public/Auth/Context/Switch-GitHubContext.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/functions/public/Auth/Context/Switch-GitHubContext.ps1 b/src/functions/public/Auth/Context/Switch-GitHubContext.ps1
index 0a6149a66..b4f7ed876 100644
--- a/src/functions/public/Auth/Context/Switch-GitHubContext.ps1
+++ b/src/functions/public/Auth/Context/Switch-GitHubContext.ps1
@@ -16,7 +16,7 @@
param(
# The context to run the command in. Used to get the details for the API call.
# Can be either a string or a GitHubContext object.
- [Parameter(ValueFromPipeline)]
+ [Parameter(Mandatory, ValueFromPipeline, Position = 0)]
[object] $Context
)
From 6447faa8fba94e7fa8dbfb3d75c07ed8fd4fc12f Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 13:20:32 +0200
Subject: [PATCH 07/43] Add initial test scripts for GitHub API interactions
- Created TEMPLATE.ps1 for Pester testing framework setup.
- Implemented Teams.Tests.ps1 to test GitHub Teams API functionalities including team creation, retrieval, updating, and deletion.
- Added Users.Tests.ps1 to validate user-related API calls, including user retrieval and updates.
- Developed Variables.Tests.ps1 to manage GitHub repository and organization variables, including creation, updating, and removal of variables.
---
.github/PSModule.yml | 28 +-
.../GitHubAppInstallationContext.ps1 | 4 +-
src/classes/public/GitHubPermission.ps1 | 1285 +++++++++++++++++
.../public/GitHubPermissionDefinition.ps1 | 46 -
src/variables/private/GitHub.ps1 | 1180 ---------------
{tests => test2}/Artifacts.Tests.ps1 | 0
{tests => test2}/Emojis.Tests.ps1 | 0
{tests => test2}/Enterprise.Tests.ps1 | 0
{tests => test2}/Environments.Tests.ps1 | 0
{tests => test2}/GitHub.Tests.ps1 | 0
{tests => test2}/GitHubFormatter.Tests.ps1 | 0
{tests => test2}/Organizations.Tests.ps1 | 0
{tests => test2}/README.md | 0
{tests => test2}/Releases.Tests.ps1 | 0
{tests => test2}/Repositories.Tests.ps1 | 0
{tests => test2}/Secrets.Tests.ps1 | 0
{tests => test2}/TEMPLATE.ps1 | 0
{tests => test2}/Teams.Tests.ps1 | 0
{tests => test2}/Users.Tests.ps1 | 0
{tests => test2}/Variables.Tests.ps1 | 0
20 files changed, 1301 insertions(+), 1242 deletions(-)
create mode 100644 src/classes/public/GitHubPermission.ps1
delete mode 100644 src/classes/public/GitHubPermissionDefinition.ps1
rename {tests => test2}/Artifacts.Tests.ps1 (100%)
rename {tests => test2}/Emojis.Tests.ps1 (100%)
rename {tests => test2}/Enterprise.Tests.ps1 (100%)
rename {tests => test2}/Environments.Tests.ps1 (100%)
rename {tests => test2}/GitHub.Tests.ps1 (100%)
rename {tests => test2}/GitHubFormatter.Tests.ps1 (100%)
rename {tests => test2}/Organizations.Tests.ps1 (100%)
rename {tests => test2}/README.md (100%)
rename {tests => test2}/Releases.Tests.ps1 (100%)
rename {tests => test2}/Repositories.Tests.ps1 (100%)
rename {tests => test2}/Secrets.Tests.ps1 (100%)
rename {tests => test2}/TEMPLATE.ps1 (100%)
rename {tests => test2}/Teams.Tests.ps1 (100%)
rename {tests => test2}/Users.Tests.ps1 (100%)
rename {tests => test2}/Variables.Tests.ps1 (100%)
diff --git a/.github/PSModule.yml b/.github/PSModule.yml
index 0e0770314..08dc7e549 100644
--- a/.github/PSModule.yml
+++ b/.github/PSModule.yml
@@ -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
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
index 2b817f3ec..d4a24882a 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
@@ -6,7 +6,7 @@
[System.Nullable[uint64]] $InstallationID
# The permissions that the app is requesting on the target
- [pscustomobject] $Permissions
+ [GitHubPermission[]] $Permissions
# The events that the app is subscribing to once installed
[string[]] $Events
@@ -41,7 +41,7 @@
$this.PerPage = $Object.PerPage
$this.ClientID = $Object.ClientID
$this.InstallationID = $Object.InstallationID
- $this.Permissions = $Object.Permissions
+ $this.Permissions = [GitHubPermission]::newFromObject($Object.Permissions)
$this.Events = $Object.Events
$this.InstallationType = $Object.InstallationType
$this.InstallationName = $Object.InstallationName
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
new file mode 100644
index 000000000..330f40599
--- /dev/null
+++ b/src/classes/public/GitHubPermission.ps1
@@ -0,0 +1,1285 @@
+class GitHubPermissionDefinition {
+ # The programmatic name of the permission as returned by the GitHub API
+ [string] $Name
+
+ # The human-friendly name of the permission as shown in the GitHub UI
+ [string] $DisplayName
+
+ # A brief description of what access the permission grants
+ [string] $Description
+
+ # A link to the relevant documentation or GitHub UI page
+ [uri] $URL
+
+ # The levels of access that can be granted for this permission
+ [string[]] $Options
+
+ # The type of permission (Fine-grained, Classic)
+ [string] $Type
+
+ # The scope at which this permission applies (Repository, Organization, User, Enterprise)
+ [string] $Scope
+
+ static [GitHubPermissionDefinition[]] $List = @(
+ # ------------------------------
+ # Repository Fine-Grained Permission Definitions
+ # ------------------------------
+ [GitHubPermissionDefinition]::new(
+ 'actions',
+ 'Actions',
+ 'Workflows, workflow runs and artifacts.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-actions',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'administration',
+ 'Administration',
+ 'Repository creation, deletion, settings, teams, and collaborators.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-administration',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'attestations',
+ 'Attestations',
+ 'Create and retrieve attestations for a repository.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-attestations',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'checks',
+ 'Checks',
+ 'Checks on code.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-checks',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'security_events',
+ 'Code scanning alerts',
+ 'View and manage code scanning alerts.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-code-scanning-alerts',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'codespaces',
+ 'Codespaces',
+ 'Create, edit, delete and list Codespaces.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-codespaces',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'codespaces_lifecycle_admin',
+ 'Codespaces lifecycle admin',
+ 'Manage the lifecycle of Codespaces, including starting and stopping.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-codespaces-lifecycle-admin',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'codespaces_metadata',
+ 'Codespaces metadata',
+ 'Access Codespaces metadata including the devcontainers and machine type.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-codespaces-metadata',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'codespaces_secrets',
+ 'Codespaces secrets',
+ 'Restrict Codespaces user secrets modifications to specific repositories.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-codespaces-secrets',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'statuses',
+ 'Commit statuses',
+ 'Commit statuses.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-commit-statuses',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'contents',
+ 'Contents',
+ 'Repository contents, commits, branches, downloads, releases, and merges.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-contents',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'repository_custom_properties',
+ 'Custom properties',
+ 'Read and write repository custom properties values at the repository level, when allowed by the property.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-custom-properties',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'vulnerability_alerts',
+ 'Dependabot alerts',
+ 'Retrieve Dependabot alerts.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-dependabot-alerts',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'dependabot_secrets',
+ 'Dependabot secrets',
+ 'Manage Dependabot repository secrets.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-dependabot-secrets',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'deployments',
+ 'Deployments',
+ 'Deployments and deployment statuses.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-deployments',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'discussions',
+ 'Discussions',
+ 'Discussions and related comments and labels.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-discussions',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'environments',
+ 'Environments',
+ 'Manage repository environments.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-environments',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'issues',
+ 'Issues',
+ 'Issues and related comments, assignees, labels, and milestones.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-issues',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'merge_queues',
+ 'Merge queues',
+ "Manage a repository's merge queues",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-merge-queues',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new( #Mandatory
+ 'metadata',
+ 'Metadata',
+ 'Search repositories, list collaborators, and access repository metadata.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-metadata',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'packages',
+ 'Packages',
+ 'Packages published to the GitHub Package Platform.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-packages',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'pages',
+ 'Pages',
+ 'Retrieve Pages statuses, configuration, and builds, as well as create new builds.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-pages',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'repository_projects',
+ 'Projects',
+ 'Manage classic projects within a repository.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-projects',
+ @(
+ 'read',
+ 'write',
+ 'admin'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'pull_requests',
+ 'Pull requests',
+ 'Pull requests and related comments, assignees, labels, milestones, and merges.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-pull-requests',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'repository_advisories',
+ 'Repository security advisories',
+ 'View and manage repository security advisories.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-repository-security-advisories',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'repo_secret_scanning_dismissal_requests',
+ 'Secret scanning alert dismissal requests',
+ 'View and manage secret scanning alert dismissal requests',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-secret-scanning-alert-dismissal-requests',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'secret_scanning_alerts',
+ 'Secret scanning alerts',
+ 'View and manage secret scanning alerts.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-secret-scanning-alerts',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'secret_scanning_bypass_requests',
+ 'Secret scanning push protection bypass requests',
+ 'Review and manage repository secret scanning push protection bypass requests.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-secret-scanning-push-protection-bypass-requests',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'secrets',
+ 'Secrets',
+ 'Manage Actions repository secrets.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-secrets',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'single_file',
+ 'Single file',
+ 'Manage just a single file.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-single-file',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'actions_variables',
+ 'Variables',
+ 'Manage Actions repository variables.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-variables',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'repository_hooks',
+ 'Webhooks',
+ 'Manage the post-receive hooks for a repository.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-webhooks',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'workflows',
+ 'Workflows',
+ 'Update GitHub Action workflow files.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#repository-permissions-for-workflows',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Repository'
+ ),
+
+ # ------------------------------
+ # Organization Fine-Grained Permission Definitions
+ # ------------------------------
+ [GitHubPermissionDefinition]::new(
+ 'organization_api_insights',
+ 'API Insights',
+ 'View statistics on how the API is being used for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-api-insights',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_administration',
+ 'Administration',
+ 'Manage access to an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-administration',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_user_blocking',
+ 'Blocking users',
+ 'View and manage users blocked by the organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-blocking-users',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_campaigns',
+ 'Campaigns',
+ 'Manage campaigns.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-campaigns',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_custom_org_roles',
+ 'Custom organization roles',
+ 'Create, edit, delete and list custom organization roles. View system organization roles.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-custom-organization-roles',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_custom_properties',
+ 'Custom properties',
+ 'Read and write repository custom properties values and administer definitions at the organization level.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-custom-properties',
+ @(
+ 'read',
+ 'write',
+ 'admin'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_custom_roles',
+ 'Custom repository roles',
+ 'Create, edit, delete and list custom repository roles.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-custom-repository-roles',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_events',
+ 'Events',
+ 'View events triggered by an activity in an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-events',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_copilot_seat_management',
+ 'GitHub Copilot Business',
+ 'Manage Copilot Business seats and settings',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-github-copilot-business',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'issue_fields',
+ 'Issue Fields',
+ 'Manage issue fields for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-issue-fields',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'issue_types',
+ 'Issue Types',
+ 'Manage issue types for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-issue-types',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_knowledge_bases',
+ 'Knowledge bases',
+ 'View and manage knowledge bases for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-knowledge-bases',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'members',
+ 'Members',
+ 'Organization members and teams.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-members',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_models',
+ 'Models',
+ 'Manage model access for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-models',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_network_configurations',
+ 'Network configurations',
+ 'View and manage hosted compute network configurations available to an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-network-configurations',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_announcement_banners',
+ 'Organization announcement banners',
+ 'View and modify announcement banners for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-organization-announcement-banners',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_secret_scanning_bypass_requests',
+ 'Organization bypass requests for secret scanning',
+ 'Review and manage secret scanning push protection bypass requests.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-organization-bypass-requests-for-secret-scanning',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_codespaces',
+ 'Organization codespaces',
+ 'Manage Codespaces for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-organization-codespaces',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_codespaces_secrets',
+ 'Organization codespaces secrets',
+ 'Manage Codespaces Secrets for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-organization-codespaces-secrets',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_codespaces_settings',
+ 'Organization codespaces settings',
+ 'Manage Codespaces settings for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-organization-codespaces-settings',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_dependabot_secrets',
+ 'Organization dependabot secrets',
+ 'Manage Dependabot organization secrets.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-organization-dependabot-secrets',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_code_scanning_dismissal_requests',
+ 'Organization dismissal requests for code scanning',
+ 'Review and manage code scanning alert dismissal requests.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-organization-dismissal-requests-for-code-scanning',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_private_registries',
+ 'Organization private registries',
+ 'Manage private registries for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-organization-private-registries',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_personal_access_token_requests',
+ 'Personal access token requests',
+ 'Manage personal access token requests from organization members.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-personal-access-token-requests',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_personal_access_tokens',
+ 'Personal access tokens',
+ 'View and revoke personal access tokens that have been granted access to an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-personal-access-tokens',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_plan',
+ 'Plan',
+ "View an organization's plan.",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-plan',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_projects',
+ 'Projects',
+ 'Manage projects for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-projects',
+ @(
+ 'read',
+ 'write',
+ 'admin'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'secret_scanning_dismissal_requests',
+ 'Secret scanning alert dismissal requests',
+ 'Review and manage secret scanning alert dismissal requests',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-secret-scanning-alert-dismissal-requests',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_secrets',
+ 'Secrets',
+ 'Manage Actions organization secrets.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-secrets',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_self_hosted_runners',
+ 'Self-hosted runners',
+ 'View and manage Actions self-hosted runners available to an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-self-hosted-runners',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'team_discussions',
+ 'Team discussions',
+ 'Manage team discussions and related comments.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-team-discussions',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_actions_variables',
+ 'Variables',
+ 'Manage Actions organization variables.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-variables',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'organization_hooks',
+ 'Webhooks',
+ 'Manage the post-receive hooks for an organization.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#organization-permissions-for-webhooks',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Organization'
+ ),
+
+ # ------------------------------
+ # User (Account) Fine-Grained Permission Definitions
+ # ------------------------------
+ [GitHubPermissionDefinition]::new(
+ 'blocking',
+ 'Block another user',
+ 'View and manage users blocked by the user.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-block-another-user',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'codespaces_user_secrets',
+ 'Codespaces user secrets',
+ 'Manage Codespaces user secrets.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-codespaces-user-secrets',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'copilot_messages',
+ 'Copilot Chat',
+ 'This application will receive your GitHub ID, your GitHub Copilot Chat session messages ' +
+ '(not including messages sent to another application), and timestamps of provided GitHub Copilot ' +
+ 'Chat session messages. This permission must be enabled for Copilot Extensions.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-copilot-chat',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'copilot_editor_context',
+ 'Copilot Editor Context',
+ 'This application will receive bits of Editor Context (e.g. currently opened file) whenever you send it a message through Copilot Chat.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-copilot-editor-context',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'emails',
+ 'Email addresses',
+ "Manage a user's email addresses.",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-email-addresses',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'user_events',
+ 'Events',
+ "View events triggered by a user's activity.",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-events',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'followers',
+ 'Followers',
+ "A user's followers",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-followers',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'gpg_keys',
+ 'GPG keys',
+ "View and manage a user's GPG keys.",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-gpg-keys',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'gists',
+ 'Gists',
+ "Create and modify a user's gists and comments.",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-gists',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'keys',
+ 'Git SSH keys',
+ 'Git SSH keys',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-git-ssh-keys',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'interaction_limits',
+ 'Interaction limits',
+ 'Interaction limits on repositories',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-interaction-limits',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'knowledge_bases',
+ 'Knowledge bases',
+ 'View knowledge bases for a user.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-knowledge-bases',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'user_models',
+ 'Models',
+ 'Allows access to GitHub Models.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-models',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'plan',
+ 'Plan',
+ "View a user's plan.",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-plan',
+ @(
+ 'read'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'profile',
+ 'Profile',
+ "Manage a user's profile settings.",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-profile',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'git_signing_ssh_public_keys',
+ 'SSH signing keys',
+ "View and manage a user's SSH signing keys.",
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-ssh-signing-keys',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'starring',
+ 'Starring',
+ 'List and manage repositories a user is starring.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-starring',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'watching',
+ 'Watching',
+ 'List and change repositories a user is subscribed to.',
+ 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
+ '#user-permissions-for-watching',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'User'
+ ),
+
+ # ------------------------------
+ # Enterprise Fine-Grained Permission Definitions
+ # ------------------------------
+ [GitHubPermissionDefinition]::new(
+ 'enterprise_custom_properties',
+ 'Custom properties',
+ 'View repository custom properties and administer definitions at the enterprise level.',
+ 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
+ '#enterprise-permissions-for-custom-properties',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Enterprise'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'enterprise_organization_installation_repositories',
+ 'Enterprise organization installation repositories',
+ 'Manage repository access of GitHub Apps on Enterprise-owned organizations',
+ 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
+ '#enterprise-permissions-for-enterprise-organization-installation-repositories',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Enterprise'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'enterprise_organization_installations',
+ 'Enterprise organization installations',
+ 'Manage installation of GitHub Apps on Enterprise-owned organizations',
+ 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
+ '#enterprise-permissions-for-enterprise-organization-installations',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Enterprise'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'enterprise_organizations',
+ 'Enterprise organizations',
+ 'Create and remove enterprise organizations',
+ 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
+ '#enterprise-permissions-for-enterprise-organizations',
+ @(
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Enterprise'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'enterprise_people',
+ 'Enterprise people',
+ 'Manage user access to the enterprise',
+ 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
+ '#enterprise-permissions-for-enterprise-people',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Enterprise'
+ ),
+ [GitHubPermissionDefinition]::new(
+ 'enterprise_sso',
+ 'Enterprise single sign-on',
+ 'View and manage enterprise single sign-on configuration',
+ 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
+ '#enterprise-permissions-for-enterprise-single-sign-on',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Enterprise'
+ )
+ )
+
+ GitHubPermissionDefinition() {}
+
+ GitHubPermissionDefinition(
+ [string]$Name,
+ [string]$DisplayName,
+ [string]$Description,
+ [string]$URL,
+ [string[]]$Options,
+ [string]$Type,
+ [string]$Scope
+ ) {
+ $this.Name = $Name
+ $this.DisplayName = $DisplayName
+ $this.Description = $Description
+ $this.URL = [uri]$URL
+ $this.Options = $Options
+ $this.Type = $Type
+ $this.Scope = $Scope
+ }
+
+ [string] ToString() {
+ return $this.Name
+ }
+}
+
+class GitHubPermission : GitHubPermissionDefinition {
+ # The value assigned to the permission. Must be one of the options defined in the parent class.
+ [string] $Value
+
+ GitHubPermission() : base() {}
+
+ GitHubPermission([string] $Permission, [string] $Value) : base() {
+ $definition = [GitHubPermissionDefinition]::List | Where-Object { $_.Name -eq $Permission }
+ if (-not $definition) {
+ throw "Invalid permission name: $Permission"
+ }
+ $this.Name = $definition.Name
+ $this.DisplayName = $definition.DisplayName
+ $this.Description = $definition.Description
+ $this.URL = $definition.URL
+ $this.Options = $definition.Options
+ $this.Type = $definition.Type
+ $this.Scope = $definition.Scope
+
+ if ($Value -and ($definition.Options -notcontains $Value)) {
+ throw "Invalid permission value: $Value for permission: $Permission"
+ }
+ $this.Value = $Value
+ }
+
+ static [GitHubPermission[]] newFromObject([pscustomobject] $Object) {
+ if (-not $Object) { return @() }
+ $result = @()
+ foreach ($name in ($Object | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name)) {
+ $tmpValue = $Object.$name
+ $definition = [GitHubPermissionDefinition]::List | Where-Object { $_.Name -eq $name }
+ if ($definition) {
+ if ($tmpValue -and ($definition.Options -notcontains $tmpValue)) {
+ # Skip invalid value for known permission
+ continue
+ }
+ $perm = [GitHubPermission]::new()
+ $perm.Name = $definition.Name
+ $perm.DisplayName = $definition.DisplayName
+ $perm.Description = $definition.Description
+ $perm.URL = $definition.URL
+ $perm.Options = $definition.Options
+ $perm.Type = $definition.Type
+ $perm.Scope = $definition.Scope
+ $perm.Value = $tmpValue
+ $result += $perm
+ } else {
+ # Unknown permission: create minimal object without metadata
+ $perm = [GitHubPermission]::new()
+ $perm.Name = $name
+ $perm.Value = $tmpValue
+ $result += $perm
+ }
+ }
+ return $result | Sort-Object Scope, DisplayName
+ }
+}
diff --git a/src/classes/public/GitHubPermissionDefinition.ps1 b/src/classes/public/GitHubPermissionDefinition.ps1
deleted file mode 100644
index 93ff6643f..000000000
--- a/src/classes/public/GitHubPermissionDefinition.ps1
+++ /dev/null
@@ -1,46 +0,0 @@
-class GitHubPermissionDefinition {
- # The programmatic name of the permission as returned by the GitHub API
- [string] $Name
-
- # The human-friendly name of the permission as shown in the GitHub UI
- [string] $DisplayName
-
- # A brief description of what access the permission grants
- [string] $Description
-
- # A link to the relevant documentation or GitHub UI page
- [uri] $URL
-
- # The levels of access that can be granted for this permission
- [string[]] $Options
-
- # The type of permission (Fine-grained, Classic)
- [string] $Type
-
- # The scope at which this permission applies (Repository, Organization, User, Enterprise)
- [string] $Scope
-
- GitHubPermissionDefinition() {}
-
- GitHubPermissionDefinition(
- [string]$Name,
- [string]$DisplayName,
- [string]$Description,
- [string]$URL,
- [string[]]$Options,
- [string]$Type,
- [string]$Scope
- ) {
- $this.Name = $Name
- $this.DisplayName = $DisplayName
- $this.Description = $Description
- $this.URL = [uri]$URL
- $this.Options = $Options
- $this.Type = $Type
- $this.Scope = $Scope
- }
-
- [string] ToString() {
- return $this.Name
- }
-}
diff --git a/src/variables/private/GitHub.ps1 b/src/variables/private/GitHub.ps1
index c5b04de1e..67f82414e 100644
--- a/src/variables/private/GitHub.ps1
+++ b/src/variables/private/GitHub.ps1
@@ -23,1184 +23,4 @@ $script:GitHub = [pscustomobject]@{
Config = $null
Event = $null
Runner = $null
- Permissions = @(
- # ------------------------------
- # Repository Fine-Grained Permission Definitions
- # ------------------------------
- [GitHubPermissionDefinition]::new(
- 'actions',
- 'Actions',
- 'Workflows, workflow runs and artifacts.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-actions',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'administration',
- 'Administration',
- 'Repository creation, deletion, settings, teams, and collaborators.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-administration',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'attestations',
- 'Attestations',
- 'Create and retrieve attestations for a repository.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-attestations',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'checks',
- 'Checks',
- 'Checks on code.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-checks',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'security_events',
- 'Code scanning alerts',
- 'View and manage code scanning alerts.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-code-scanning-alerts',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'codespaces',
- 'Codespaces',
- 'Create, edit, delete and list Codespaces.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-codespaces',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'codespaces_lifecycle_admin',
- 'Codespaces lifecycle admin',
- 'Manage the lifecycle of Codespaces, including starting and stopping.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-codespaces-lifecycle-admin',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'codespaces_metadata',
- 'Codespaces metadata',
- 'Access Codespaces metadata including the devcontainers and machine type.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-codespaces-metadata',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'codespaces_secrets',
- 'Codespaces secrets',
- 'Restrict Codespaces user secrets modifications to specific repositories.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-codespaces-secrets',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'statuses',
- 'Commit statuses',
- 'Commit statuses.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-commit-statuses',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'contents',
- 'Contents',
- 'Repository contents, commits, branches, downloads, releases, and merges.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-contents',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'repository_custom_properties',
- 'Custom properties',
- 'Read and write repository custom properties values at the repository level, when allowed by the property.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-custom-properties',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'vulnerability_alerts',
- 'Dependabot alerts',
- 'Retrieve Dependabot alerts.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-dependabot-alerts',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'dependabot_secrets',
- 'Dependabot secrets',
- 'Manage Dependabot repository secrets.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-dependabot-secrets',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'deployments',
- 'Deployments',
- 'Deployments and deployment statuses.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-deployments',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'discussions',
- 'Discussions',
- 'Discussions and related comments and labels.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-discussions',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'environments',
- 'Environments',
- 'Manage repository environments.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-environments',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'issues',
- 'Issues',
- 'Issues and related comments, assignees, labels, and milestones.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-issues',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'merge_queues',
- 'Merge queues',
- "Manage a repository's merge queues",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-merge-queues',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new( #Mandatory
- 'metadata',
- 'Metadata',
- 'Search repositories, list collaborators, and access repository metadata.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-metadata',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'packages',
- 'Packages',
- 'Packages published to the GitHub Package Platform.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-packages',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'pages',
- 'Pages',
- 'Retrieve Pages statuses, configuration, and builds, as well as create new builds.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-pages',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'repository_projects',
- 'Projects',
- 'Manage classic projects within a repository.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-projects',
- @(
- 'read',
- 'write',
- 'admin'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'pull_requests',
- 'Pull requests',
- 'Pull requests and related comments, assignees, labels, milestones, and merges.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-pull-requests',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'repository_advisories',
- 'Repository security advisories',
- 'View and manage repository security advisories.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-repository-security-advisories',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'repo_secret_scanning_dismissal_requests',
- 'Secret scanning alert dismissal requests',
- 'View and manage secret scanning alert dismissal requests',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-secret-scanning-alert-dismissal-requests',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'secret_scanning_alerts',
- 'Secret scanning alerts',
- 'View and manage secret scanning alerts.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-secret-scanning-alerts',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'secret_scanning_bypass_requests',
- 'Secret scanning push protection bypass requests',
- 'Review and manage repository secret scanning push protection bypass requests.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-secret-scanning-push-protection-bypass-requests',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'secrets',
- 'Secrets',
- 'Manage Actions repository secrets.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-secrets',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'single_file',
- 'Single file',
- 'Manage just a single file.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-single-file',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'actions_variables',
- 'Variables',
- 'Manage Actions repository variables.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-variables',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'repository_hooks',
- 'Webhooks',
- 'Manage the post-receive hooks for a repository.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-webhooks',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
- [GitHubPermissionDefinition]::new(
- 'workflows',
- 'Workflows',
- 'Update GitHub Action workflow files.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#repository-permissions-for-workflows',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Repository'
- ),
-
- # ------------------------------
- # Organization Fine-Grained Permission Definitions
- # ------------------------------
- [GitHubPermissionDefinition]::new(
- 'organization_api_insights',
- 'API Insights',
- 'View statistics on how the API is being used for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-api-insights',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_administration',
- 'Administration',
- 'Manage access to an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-administration',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_user_blocking',
- 'Blocking users',
- 'View and manage users blocked by the organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-blocking-users',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_campaigns',
- 'Campaigns',
- 'Manage campaigns.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-campaigns',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_custom_org_roles',
- 'Custom organization roles',
- 'Create, edit, delete and list custom organization roles. View system organization roles.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-custom-organization-roles',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_custom_properties',
- 'Custom properties',
- 'Read and write repository custom properties values and administer definitions at the organization level.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-custom-properties',
- @(
- 'read',
- 'write',
- 'admin'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_custom_roles',
- 'Custom repository roles',
- 'Create, edit, delete and list custom repository roles.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-custom-repository-roles',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_events',
- 'Events',
- 'View events triggered by an activity in an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-events',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_copilot_seat_management',
- 'GitHub Copilot Business',
- 'Manage Copilot Business seats and settings',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-github-copilot-business',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'issue_fields',
- 'Issue Fields',
- 'Manage issue fields for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-issue-fields',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'issue_types',
- 'Issue Types',
- 'Manage issue types for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-issue-types',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_knowledge_bases',
- 'Knowledge bases',
- 'View and manage knowledge bases for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-knowledge-bases',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'members',
- 'Members',
- 'Organization members and teams.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-members',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_models',
- 'Models',
- 'Manage model access for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-models',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_network_configurations',
- 'Network configurations',
- 'View and manage hosted compute network configurations available to an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-network-configurations',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_announcement_banners',
- 'Organization announcement banners',
- 'View and modify announcement banners for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-organization-announcement-banners',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_secret_scanning_bypass_requests',
- 'Organization bypass requests for secret scanning',
- 'Review and manage secret scanning push protection bypass requests.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-organization-bypass-requests-for-secret-scanning',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_codespaces',
- 'Organization codespaces',
- 'Manage Codespaces for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-organization-codespaces',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_codespaces_secrets',
- 'Organization codespaces secrets',
- 'Manage Codespaces Secrets for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-organization-codespaces-secrets',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_codespaces_settings',
- 'Organization codespaces settings',
- 'Manage Codespaces settings for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-organization-codespaces-settings',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_dependabot_secrets',
- 'Organization dependabot secrets',
- 'Manage Dependabot organization secrets.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-organization-dependabot-secrets',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_code_scanning_dismissal_requests',
- 'Organization dismissal requests for code scanning',
- 'Review and manage code scanning alert dismissal requests.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-organization-dismissal-requests-for-code-scanning',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_private_registries',
- 'Organization private registries',
- 'Manage private registries for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-organization-private-registries',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_personal_access_token_requests',
- 'Personal access token requests',
- 'Manage personal access token requests from organization members.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-personal-access-token-requests',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_personal_access_tokens',
- 'Personal access tokens',
- 'View and revoke personal access tokens that have been granted access to an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-personal-access-tokens',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_plan',
- 'Plan',
- "View an organization's plan.",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-plan',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_projects',
- 'Projects',
- 'Manage projects for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-projects',
- @(
- 'read',
- 'write',
- 'admin'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'secret_scanning_dismissal_requests',
- 'Secret scanning alert dismissal requests',
- 'Review and manage secret scanning alert dismissal requests',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-secret-scanning-alert-dismissal-requests',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_secrets',
- 'Secrets',
- 'Manage Actions organization secrets.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-secrets',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_self_hosted_runners',
- 'Self-hosted runners',
- 'View and manage Actions self-hosted runners available to an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-self-hosted-runners',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'team_discussions',
- 'Team discussions',
- 'Manage team discussions and related comments.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-team-discussions',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_actions_variables',
- 'Variables',
- 'Manage Actions organization variables.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-variables',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
- [GitHubPermissionDefinition]::new(
- 'organization_hooks',
- 'Webhooks',
- 'Manage the post-receive hooks for an organization.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#organization-permissions-for-webhooks',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Organization'
- ),
-
- # ------------------------------
- # User (Account) Fine-Grained Permission Definitions
- # ------------------------------
- [GitHubPermissionDefinition]::new(
- 'blocking',
- 'Block another user',
- 'View and manage users blocked by the user.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-block-another-user',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'codespaces_user_secrets',
- 'Codespaces user secrets',
- 'Manage Codespaces user secrets.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-codespaces-user-secrets',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'copilot_messages',
- 'Copilot Chat',
- 'This application will receive your GitHub ID, your GitHub Copilot Chat session messages ' +
- '(not including messages sent to another application), and timestamps of provided GitHub Copilot ' +
- 'Chat session messages. This permission must be enabled for Copilot Extensions.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-copilot-chat',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'copilot_editor_context',
- 'Copilot Editor Context',
- 'This application will receive bits of Editor Context (e.g. currently opened file) whenever you send it a message through Copilot Chat.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-copilot-editor-context',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'emails',
- 'Email addresses',
- "Manage a user's email addresses.",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-email-addresses',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'user_events',
- 'Events',
- "View events triggered by a user's activity.",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-events',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'followers',
- 'Followers',
- "A user's followers",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-followers',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'gpg_keys',
- 'GPG keys',
- "View and manage a user's GPG keys.",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-gpg-keys',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'gists',
- 'Gists',
- "Create and modify a user's gists and comments.",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-gists',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'keys',
- 'Git SSH keys',
- 'Git SSH keys',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-git-ssh-keys',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'interaction_limits',
- 'Interaction limits',
- 'Interaction limits on repositories',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-interaction-limits',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'knowledge_bases',
- 'Knowledge bases',
- 'View knowledge bases for a user.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-knowledge-bases',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'user_models',
- 'Models',
- 'Allows access to GitHub Models.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-models',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'plan',
- 'Plan',
- "View a user's plan.",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-plan',
- @(
- 'read'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'profile',
- 'Profile',
- "Manage a user's profile settings.",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-profile',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'git_signing_ssh_public_keys',
- 'SSH signing keys',
- "View and manage a user's SSH signing keys.",
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-ssh-signing-keys',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'starring',
- 'Starring',
- 'List and manage repositories a user is starring.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-starring',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
- [GitHubPermissionDefinition]::new(
- 'watching',
- 'Watching',
- 'List and change repositories a user is subscribed to.',
- 'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
- '#user-permissions-for-watching',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'User'
- ),
-
- # ------------------------------
- # Enterprise Fine-Grained Permission Definitions
- # ------------------------------
- [GitHubPermissionDefinition]::new(
- 'enterprise_custom_properties',
- 'Custom properties',
- 'View repository custom properties and administer definitions at the enterprise level.',
- 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
- '#enterprise-permissions-for-custom-properties',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Enterprise'
- ),
- [GitHubPermissionDefinition]::new(
- 'enterprise_organization_installation_repositories',
- 'Enterprise organization installation repositories',
- 'Manage repository access of GitHub Apps on Enterprise-owned organizations',
- 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
- '#enterprise-permissions-for-enterprise-organization-installation-repositories',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Enterprise'
- ),
- [GitHubPermissionDefinition]::new(
- 'enterprise_organization_installations',
- 'Enterprise organization installations',
- 'Manage installation of GitHub Apps on Enterprise-owned organizations',
- 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
- '#enterprise-permissions-for-enterprise-organization-installations',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Enterprise'
- ),
- [GitHubPermissionDefinition]::new(
- 'enterprise_organizations',
- 'Enterprise organizations',
- 'Create and remove enterprise organizations',
- 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
- '#enterprise-permissions-for-enterprise-organizations',
- @(
- 'write'
- ),
- 'Fine-grained',
- 'Enterprise'
- ),
- [GitHubPermissionDefinition]::new(
- 'enterprise_people',
- 'Enterprise people',
- 'Manage user access to the enterprise',
- 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
- '#enterprise-permissions-for-enterprise-people',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Enterprise'
- ),
- [GitHubPermissionDefinition]::new(
- 'enterprise_sso',
- 'Enterprise single sign-on',
- 'View and manage enterprise single sign-on configuration',
- 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
- '#enterprise-permissions-for-enterprise-single-sign-on',
- @(
- 'read',
- 'write'
- ),
- 'Fine-grained',
- 'Enterprise'
- )
- )
}
diff --git a/tests/Artifacts.Tests.ps1 b/test2/Artifacts.Tests.ps1
similarity index 100%
rename from tests/Artifacts.Tests.ps1
rename to test2/Artifacts.Tests.ps1
diff --git a/tests/Emojis.Tests.ps1 b/test2/Emojis.Tests.ps1
similarity index 100%
rename from tests/Emojis.Tests.ps1
rename to test2/Emojis.Tests.ps1
diff --git a/tests/Enterprise.Tests.ps1 b/test2/Enterprise.Tests.ps1
similarity index 100%
rename from tests/Enterprise.Tests.ps1
rename to test2/Enterprise.Tests.ps1
diff --git a/tests/Environments.Tests.ps1 b/test2/Environments.Tests.ps1
similarity index 100%
rename from tests/Environments.Tests.ps1
rename to test2/Environments.Tests.ps1
diff --git a/tests/GitHub.Tests.ps1 b/test2/GitHub.Tests.ps1
similarity index 100%
rename from tests/GitHub.Tests.ps1
rename to test2/GitHub.Tests.ps1
diff --git a/tests/GitHubFormatter.Tests.ps1 b/test2/GitHubFormatter.Tests.ps1
similarity index 100%
rename from tests/GitHubFormatter.Tests.ps1
rename to test2/GitHubFormatter.Tests.ps1
diff --git a/tests/Organizations.Tests.ps1 b/test2/Organizations.Tests.ps1
similarity index 100%
rename from tests/Organizations.Tests.ps1
rename to test2/Organizations.Tests.ps1
diff --git a/tests/README.md b/test2/README.md
similarity index 100%
rename from tests/README.md
rename to test2/README.md
diff --git a/tests/Releases.Tests.ps1 b/test2/Releases.Tests.ps1
similarity index 100%
rename from tests/Releases.Tests.ps1
rename to test2/Releases.Tests.ps1
diff --git a/tests/Repositories.Tests.ps1 b/test2/Repositories.Tests.ps1
similarity index 100%
rename from tests/Repositories.Tests.ps1
rename to test2/Repositories.Tests.ps1
diff --git a/tests/Secrets.Tests.ps1 b/test2/Secrets.Tests.ps1
similarity index 100%
rename from tests/Secrets.Tests.ps1
rename to test2/Secrets.Tests.ps1
diff --git a/tests/TEMPLATE.ps1 b/test2/TEMPLATE.ps1
similarity index 100%
rename from tests/TEMPLATE.ps1
rename to test2/TEMPLATE.ps1
diff --git a/tests/Teams.Tests.ps1 b/test2/Teams.Tests.ps1
similarity index 100%
rename from tests/Teams.Tests.ps1
rename to test2/Teams.Tests.ps1
diff --git a/tests/Users.Tests.ps1 b/test2/Users.Tests.ps1
similarity index 100%
rename from tests/Users.Tests.ps1
rename to test2/Users.Tests.ps1
diff --git a/tests/Variables.Tests.ps1 b/test2/Variables.Tests.ps1
similarity index 100%
rename from tests/Variables.Tests.ps1
rename to test2/Variables.Tests.ps1
From 6dc3cc6f591e8bb78cb5e526be012759faddf871 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 14:42:39 +0200
Subject: [PATCH 08/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20Permis?=
=?UTF-8?q?sions=20property=20type=20to=20GitHubPermission=20array=20in=20?=
=?UTF-8?q?GitHubApp=20and=20GitHubAppContext=20classes?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/App/GitHubApp.ps1 | 4 ++--
src/classes/public/Context/GitHubContext/GitHubAppContext.ps1 | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/classes/public/App/GitHubApp.ps1 b/src/classes/public/App/GitHubApp.ps1
index 620f52af5..80b78bff8 100644
--- a/src/classes/public/App/GitHubApp.ps1
+++ b/src/classes/public/App/GitHubApp.ps1
@@ -36,7 +36,7 @@
[System.Nullable[datetime]] $UpdatedAt
# The permissions that the app is requesting.
- [pscustomobject] $Permissions
+ [GitHubPermission[]] $Permissions
# The events that the app is subscribing to on its target.
[string[]] $Events
@@ -59,7 +59,7 @@
$this.Url = $Object.html_url
$this.CreatedAt = $Object.created_at
$this.UpdatedAt = $Object.updated_at
- $this.Permissions = $Object.permissions
+ $this.Permissions = [GitHubPermission]::newFromObject($Object.permissions)
$this.Events = , ($Object.events)
$this.Installations = $Object.installations_count
}
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
index 02cc68a67..815c5151a 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
@@ -15,7 +15,7 @@
[string] $OwnerType
# The permissions that the app is requesting on the target
- [pscustomobject] $Permissions
+ [GitHubPermission[]] $Permissions
# The events that the app is subscribing to once installed
[string[]] $Events
@@ -47,7 +47,7 @@
$this.KeyVaultKeyReference = $Object.KeyVaultKeyReference
$this.OwnerName = $Object.OwnerName
$this.OwnerType = $Object.OwnerType
- $this.Permissions = $Object.Permissions
+ $this.Permissions = [GitHubPermission]::newFromObject($Object.Permissions)
$this.Events = $Object.Events
}
}
From d3285a6dfb2d1045505abd53d6839c0b378b8d30 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 14:54:38 +0200
Subject: [PATCH 09/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Add=20GitHubPer?=
=?UTF-8?q?mission.Format.ps1xml=20for=20GitHubPermission=20table=20format?=
=?UTF-8?q?ting?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/formats/GitHubPermission.Format.ps1xml | 52 ++++++++++++++++++++++
1 file changed, 52 insertions(+)
create mode 100644 src/formats/GitHubPermission.Format.ps1xml
diff --git a/src/formats/GitHubPermission.Format.ps1xml b/src/formats/GitHubPermission.Format.ps1xml
new file mode 100644
index 000000000..d917b0c3c
--- /dev/null
+++ b/src/formats/GitHubPermission.Format.ps1xml
@@ -0,0 +1,52 @@
+
+
+
+
+ GitHubPermissionTable
+
+ GitHubPermission
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Scope
+
+
+
+ if ($Host.UI.SupportsVirtualTerminal -and
+ ($env:GITHUB_ACTIONS -ne 'true') -and $_.Url) {
+ $PSStyle.FormatHyperlink($_.DisplayName, $_.Url)
+ } else {
+ $_.DisplayName
+ }
+
+
+
+ Value
+
+
+ Description
+
+
+
+
+
+
+
+
From c402d1f2faed7b1e5f44a1d12b39e706b31cfedd Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 15:24:16 +0200
Subject: [PATCH 10/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Enhance=20GitHu?=
=?UTF-8?q?bPermission=20initialization=20to=20handle=20unknown=20permissi?=
=?UTF-8?q?ons=20and=20update=20permissions=20assignment=20in=20Set-GitHub?=
=?UTF-8?q?Context=20function?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 27 ++++++++++++-------
.../Auth/Context/Set-GitHubContext.ps1 | 2 +-
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 330f40599..432d85726 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1234,16 +1234,25 @@ class GitHubPermission : GitHubPermissionDefinition {
GitHubPermission([string] $Permission, [string] $Value) : base() {
$definition = [GitHubPermissionDefinition]::List | Where-Object { $_.Name -eq $Permission }
- if (-not $definition) {
- throw "Invalid permission name: $Permission"
+ if ($definition) {
+ $this.Name = $definition.Name
+ $this.DisplayName = $definition.DisplayName
+ $this.Description = $definition.Description
+ $this.URL = $definition.URL
+ $this.Options = $definition.Options
+ $this.Type = $definition.Type
+ $this.Scope = $definition.Scope
+ } else {
+ $this.Name = $Permission
+ $this.DisplayName = $Permission
+ $this.Description = 'Unknown permission - Open issue to add metadata'
+ $this.URL = $null
+ $this.Options = @()
+ $this.Type = 'Unknown'
+ $this.Scope = 'Unknown'
+
}
- $this.Name = $definition.Name
- $this.DisplayName = $definition.DisplayName
- $this.Description = $definition.Description
- $this.URL = $definition.URL
- $this.Options = $definition.Options
- $this.Type = $definition.Type
- $this.Scope = $definition.Scope
+
if ($Value -and ($definition.Options -notcontains $Value)) {
throw "Invalid permission value: $Value for permission: $Permission"
diff --git a/src/functions/private/Auth/Context/Set-GitHubContext.ps1 b/src/functions/private/Auth/Context/Set-GitHubContext.ps1
index c20ea4281..d3de2d165 100644
--- a/src/functions/private/Auth/Context/Set-GitHubContext.ps1
+++ b/src/functions/private/Auth/Context/Set-GitHubContext.ps1
@@ -127,7 +127,7 @@
$contextObj['Username'] = [string]$app.Slug
$contextObj['NodeID'] = [string]$app.NodeID
$contextObj['DatabaseID'] = [string]$app.ID
- $contextObj['Permissions'] = [PSCustomObject]$app.Permissions
+ $contextObj['Permissions'] = [GitHubPermission]::newFromObject($app.Permissions)
$contextObj['Events'] = [string[]]$app.Events
$contextObj['OwnerName'] = [string]$app.Owner.Name
$contextObj['OwnerType'] = [string]$app.Owner.Type
From 1fc35cfb9c2b640d1b11411a768966878b5ffd5b Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 16:42:38 +0200
Subject: [PATCH 11/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20perm?=
=?UTF-8?q?ission=20handling=20in=20GitHubApp=20and=20GitHubAppInstallatio?=
=?UTF-8?q?n=20classes=20to=20use=20NewFullCatalog=20for=20comprehensive?=
=?UTF-8?q?=20permission=20management?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/App/GitHubApp.ps1 | 2 +-
.../public/App/GitHubAppInstallation.ps1 | 39 +++++++++--------
.../GitHubAppInstallationContext.ps1 | 2 +-
src/classes/public/GitHubPermission.ps1 | 43 +++++++++++++++++++
.../Auth/Context/Set-GitHubContext.ps1 | 2 +-
.../public/Auth/Connect-GitHubApp.ps1 | 6 +--
6 files changed, 70 insertions(+), 24 deletions(-)
diff --git a/src/classes/public/App/GitHubApp.ps1 b/src/classes/public/App/GitHubApp.ps1
index 80b78bff8..86eda5817 100644
--- a/src/classes/public/App/GitHubApp.ps1
+++ b/src/classes/public/App/GitHubApp.ps1
@@ -59,7 +59,7 @@
$this.Url = $Object.html_url
$this.CreatedAt = $Object.created_at
$this.UpdatedAt = $Object.updated_at
- $this.Permissions = [GitHubPermission]::newFromObject($Object.permissions)
+ $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $null)
$this.Events = , ($Object.events)
$this.Installations = $Object.installations_count
}
diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1
index 7812e3140..7e02acf5a 100644
--- a/src/classes/public/App/GitHubAppInstallation.ps1
+++ b/src/classes/public/App/GitHubAppInstallation.ps1
@@ -14,8 +14,8 @@
# The type of repository selection.
[string] $RepositorySelection
- # The permissions that the app has on the target.
- [pscustomobject] $Permissions
+ # The permissions that the app has on the target (full catalog for applicable scopes).
+ [GitHubPermission[]] $Permissions
# The events that the app is subscribing to.
[string[]] $Events
@@ -47,23 +47,26 @@
GitHubAppInstallation() {}
# Helper method to compare installation permissions and events with app configuration
- hidden [string] CompareWithAppConfiguration([pscustomobject] $AppPermissions, [string[]] $AppEvents) {
+ hidden [string] CompareWithAppConfiguration([GitHubPermission[]] $AppPermissions, [string[]] $AppEvents) {
if ($null -eq $AppPermissions -or $null -eq $AppEvents) {
return 'Unknown'
}
- # Compare permissions - check if installation has all the permissions that the app requires
+ # Build lookup tables
+ $appLookup = @{}
+ foreach ($p in $AppPermissions) { $appLookup[$p.Name] = $p }
+ $instLookup = @{}
+ foreach ($p in $this.Permissions) { $instLookup[$p.Name] = $p }
+
+ # Compare permissions - check if installation has all the permissions that the app requires (for its scope)
$permissionsMatch = $true
- if ($AppPermissions.PSObject.Properties) {
- foreach ($permission in $AppPermissions.PSObject.Properties) {
- $appPermissionLevel = $permission.Value
- $installationPermissionLevel = $this.Permissions.PSObject.Properties[$permission.Name]?.Value
-
- # If app requires a permission but installation doesn't have it, or has lower level
- if ($appPermissionLevel -ne 'none' -and $installationPermissionLevel -ne $appPermissionLevel) {
- $permissionsMatch = $false
- break
- }
+ foreach ($appPerm in $AppPermissions) {
+ # Only evaluate permissions with a value (requested). Missing (null) == no access required.
+ if ([string]::IsNullOrEmpty($appPerm.Value)) { continue }
+ $instValue = $instLookup[$appPerm.Name].Value
+ if ($instValue -ne $appPerm.Value) {
+ $permissionsMatch = $false
+ break
}
}
@@ -101,7 +104,7 @@
$this.Target = [GitHubOwner]::new($Object.account)
$this.Type = $Object.target_type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = $Object.permissions
+ $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -118,7 +121,7 @@
$this.Target = [GitHubOwner]::new($Object.account)
$this.Type = $Object.target_type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = $Object.permissions
+ $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -145,7 +148,7 @@
}
$this.Type = $Type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = $Object.permissions
+ $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -166,7 +169,7 @@
}
$this.Type = $Type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = $Object.permissions
+ $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
index d4a24882a..2ef4a142f 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
@@ -41,7 +41,7 @@
$this.PerPage = $Object.PerPage
$this.ClientID = $Object.ClientID
$this.InstallationID = $Object.InstallationID
- $this.Permissions = [GitHubPermission]::newFromObject($Object.Permissions)
+ $this.Permissions = $Object.Permissions
$this.Events = $Object.Events
$this.InstallationType = $Object.InstallationType
$this.InstallationName = $Object.InstallationName
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 432d85726..c277b58fa 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1291,4 +1291,47 @@ class GitHubPermission : GitHubPermissionDefinition {
}
return $result | Sort-Object Scope, DisplayName
}
+
+ # Returns a full catalog of permissions, ensuring all known permissions are present.
+ # If an object with granted permissions is provided, its values are merged.
+ static [GitHubPermission[]] NewFullCatalog([pscustomobject] $Object, [string] $InstallationType) {
+ $granted = [GitHubPermission]::newFromObject($Object)
+ $grantedLookup = @{}
+ foreach ($g in $granted) { $grantedLookup[$g.Name] = $g }
+
+ $full = @()
+ foreach ($definition in [GitHubPermissionDefinition]::List) {
+ if ($grantedLookup.ContainsKey($definition.Name)) {
+ $full += $grantedLookup[$definition.Name]
+ } else {
+ $perm = [GitHubPermission]::new()
+ $perm.Name = $definition.Name
+ $perm.DisplayName = $definition.DisplayName
+ $perm.Description = $definition.Description
+ $perm.URL = $definition.URL
+ $perm.Options = $definition.Options
+ $perm.Type = $definition.Type
+ $perm.Scope = $definition.Scope
+ $perm.Value = $null
+ $full += $perm
+ }
+ }
+
+ # Include unknown permissions (those not in catalog) as-is
+ foreach ($g in $granted) {
+ if (-not ([GitHubPermissionDefinition]::List.Name -contains $g.Name)) {
+ $full += $g
+ }
+ }
+ $full = $full | Sort-Object Scope, DisplayName
+
+ if (-not $InstallationType) { return $full }
+
+ switch ($InstallationType) {
+ 'Enterprise' { return $full | Where-Object { $_.Scope -eq 'Enterprise' } }
+ 'Organization' { return $full | Where-Object { $_.Scope -in @('Organization','Repository') } }
+ 'User' { return $full | Where-Object { $_.Scope -in @('User','Repository') } }
+ default { return $full }
+ }
+ }
}
diff --git a/src/functions/private/Auth/Context/Set-GitHubContext.ps1 b/src/functions/private/Auth/Context/Set-GitHubContext.ps1
index d3de2d165..91ba59e6f 100644
--- a/src/functions/private/Auth/Context/Set-GitHubContext.ps1
+++ b/src/functions/private/Auth/Context/Set-GitHubContext.ps1
@@ -127,7 +127,7 @@
$contextObj['Username'] = [string]$app.Slug
$contextObj['NodeID'] = [string]$app.NodeID
$contextObj['DatabaseID'] = [string]$app.ID
- $contextObj['Permissions'] = [GitHubPermission]::newFromObject($app.Permissions)
+ $contextObj['Permissions'] = [GitHubPermission[]]$app.Permissions
$contextObj['Events'] = [string[]]$app.Events
$contextObj['OwnerName'] = [string]$app.Owner.Name
$contextObj['OwnerType'] = [string]$app.Owner.Type
diff --git a/src/functions/public/Auth/Connect-GitHubApp.ps1 b/src/functions/public/Auth/Connect-GitHubApp.ps1
index e69343465..7e208f006 100644
--- a/src/functions/public/Auth/Connect-GitHubApp.ps1
+++ b/src/functions/public/Auth/Connect-GitHubApp.ps1
@@ -134,9 +134,9 @@
HttpVersion = [string]$Context.HttpVersion
PerPage = [int]$Context.PerPage
ClientID = [string]$Context.ClientID
- InstallationID = [string]$installation.id
- Permissions = [pscustomobject]$installation.permissions
- Events = [string[]]$installation.events
+ InstallationID = [string]$installation.ID
+ Permissions = [GitHubPermission[]]$installation.Permissions
+ Events = [string[]]$installation.Events
InstallationType = [string]$installation.Type
Token = [securestring]$token.Token
TokenExpiresAt = [datetime]$token.ExpiresAt
From bfe5279e2b49128368bed920ae92e9674c8b6727 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 16:43:19 +0200
Subject: [PATCH 12/43] Fix formatting in NewFullCatalog function for better
readability of scope conditions
---
src/classes/public/GitHubPermission.ps1 | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index c277b58fa..f4d147e63 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1329,8 +1329,8 @@ class GitHubPermission : GitHubPermissionDefinition {
switch ($InstallationType) {
'Enterprise' { return $full | Where-Object { $_.Scope -eq 'Enterprise' } }
- 'Organization' { return $full | Where-Object { $_.Scope -in @('Organization','Repository') } }
- 'User' { return $full | Where-Object { $_.Scope -in @('User','Repository') } }
+ 'Organization' { return $full | Where-Object { $_.Scope -in @('Organization', 'Repository') } }
+ 'User' { return $full | Where-Object { $_.Scope -in @('User', 'Repository') } }
default { return $full }
}
}
From 2c60136993f4fc978586f65c112ca7c5815eb41b Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 16:47:44 +0200
Subject: [PATCH 13/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Simplify=20retu?=
=?UTF-8?q?rn=20statement=20in=20NewFullCatalog=20function=20for=20clarity?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index f4d147e63..3ea2b16fb 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1331,7 +1331,7 @@ class GitHubPermission : GitHubPermissionDefinition {
'Enterprise' { return $full | Where-Object { $_.Scope -eq 'Enterprise' } }
'Organization' { return $full | Where-Object { $_.Scope -in @('Organization', 'Repository') } }
'User' { return $full | Where-Object { $_.Scope -in @('User', 'Repository') } }
- default { return $full }
}
+ return $full
}
}
From 32710e4b6e8bd16c38ca84217663608f59eb91f1 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 16:53:47 +0200
Subject: [PATCH 14/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20permis?=
=?UTF-8?q?sions=20assignment=20in=20GitHubAppInstallationContext=20to=20u?=
=?UTF-8?q?se=20NewFullCatalog=20for=20improved=20permission=20management?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Context/GitHubContext/GitHubAppInstallationContext.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
index 2ef4a142f..37fa9c5ba 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
@@ -41,7 +41,7 @@
$this.PerPage = $Object.PerPage
$this.ClientID = $Object.ClientID
$this.InstallationID = $Object.InstallationID
- $this.Permissions = $Object.Permissions
+ $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.Permissions, $Object.InstallationType)
$this.Events = $Object.Events
$this.InstallationType = $Object.InstallationType
$this.InstallationName = $Object.InstallationName
From a8097a42d4d156d2d79effcce69968a514502d49 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 22:12:54 +0200
Subject: [PATCH 15/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20perm?=
=?UTF-8?q?ission=20handling=20to=20use=20newPermissionList=20for=20consis?=
=?UTF-8?q?tency=20across=20GitHubApp,=20GitHubAppInstallation,=20and=20Gi?=
=?UTF-8?q?tHubAppContext=20classes?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/App/GitHubApp.ps1 | 2 +-
.../public/App/GitHubAppInstallation.ps1 | 8 ++--
.../GitHubContext/GitHubAppContext.ps1 | 2 +-
.../GitHubAppInstallationContext.ps1 | 2 +-
src/classes/public/GitHubPermission.ps1 | 44 +++++--------------
5 files changed, 19 insertions(+), 39 deletions(-)
diff --git a/src/classes/public/App/GitHubApp.ps1 b/src/classes/public/App/GitHubApp.ps1
index 86eda5817..bf2cba325 100644
--- a/src/classes/public/App/GitHubApp.ps1
+++ b/src/classes/public/App/GitHubApp.ps1
@@ -59,7 +59,7 @@
$this.Url = $Object.html_url
$this.CreatedAt = $Object.created_at
$this.UpdatedAt = $Object.updated_at
- $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $null)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $null)
$this.Events = , ($Object.events)
$this.Installations = $Object.installations_count
}
diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1
index 7e02acf5a..d23ea7186 100644
--- a/src/classes/public/App/GitHubAppInstallation.ps1
+++ b/src/classes/public/App/GitHubAppInstallation.ps1
@@ -104,7 +104,7 @@
$this.Target = [GitHubOwner]::new($Object.account)
$this.Type = $Object.target_type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $this.Type)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -121,7 +121,7 @@
$this.Target = [GitHubOwner]::new($Object.account)
$this.Type = $Object.target_type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $this.Type)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -148,7 +148,7 @@
}
$this.Type = $Type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $this.Type)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -169,7 +169,7 @@
}
$this.Type = $Type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.permissions, $this.Type)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
index 815c5151a..9975974ce 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
@@ -47,7 +47,7 @@
$this.KeyVaultKeyReference = $Object.KeyVaultKeyReference
$this.OwnerName = $Object.OwnerName
$this.OwnerType = $Object.OwnerType
- $this.Permissions = [GitHubPermission]::newFromObject($Object.Permissions)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.Permissions, $null)
$this.Events = $Object.Events
}
}
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
index 37fa9c5ba..ee6ee092d 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
@@ -41,7 +41,7 @@
$this.PerPage = $Object.PerPage
$this.ClientID = $Object.ClientID
$this.InstallationID = $Object.InstallationID
- $this.Permissions = [GitHubPermission]::NewFullCatalog($Object.Permissions, $Object.InstallationType)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.Permissions, $Object.InstallationType)
$this.Events = $Object.Events
$this.InstallationType = $Object.InstallationType
$this.InstallationName = $Object.InstallationName
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 3ea2b16fb..5bf75db69 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1242,7 +1242,11 @@ class GitHubPermission : GitHubPermissionDefinition {
$this.Options = $definition.Options
$this.Type = $definition.Type
$this.Scope = $definition.Scope
+ if ($Value -and ($definition.Options -notcontains $Value)) {
+ throw "Invalid permission value: $Value for permission: $Permission"
+ }
} else {
+ # Unknown permission: accept any value without validation
$this.Name = $Permission
$this.DisplayName = $Permission
$this.Description = 'Unknown permission - Open issue to add metadata'
@@ -1250,43 +1254,20 @@ class GitHubPermission : GitHubPermissionDefinition {
$this.Options = @()
$this.Type = 'Unknown'
$this.Scope = 'Unknown'
-
- }
-
-
- if ($Value -and ($definition.Options -notcontains $Value)) {
- throw "Invalid permission value: $Value for permission: $Permission"
}
$this.Value = $Value
}
- static [GitHubPermission[]] newFromObject([pscustomobject] $Object) {
+ static [GitHubPermission[]] newPermission([pscustomobject] $Object) {
if (-not $Object) { return @() }
$result = @()
foreach ($name in ($Object | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name)) {
$tmpValue = $Object.$name
- $definition = [GitHubPermissionDefinition]::List | Where-Object { $_.Name -eq $name }
- if ($definition) {
- if ($tmpValue -and ($definition.Options -notcontains $tmpValue)) {
- # Skip invalid value for known permission
- continue
- }
- $perm = [GitHubPermission]::new()
- $perm.Name = $definition.Name
- $perm.DisplayName = $definition.DisplayName
- $perm.Description = $definition.Description
- $perm.URL = $definition.URL
- $perm.Options = $definition.Options
- $perm.Type = $definition.Type
- $perm.Scope = $definition.Scope
- $perm.Value = $tmpValue
- $result += $perm
- } else {
- # Unknown permission: create minimal object without metadata
- $perm = [GitHubPermission]::new()
- $perm.Name = $name
- $perm.Value = $tmpValue
- $result += $perm
+ try {
+ $result += [GitHubPermission]::new($name, $tmpValue)
+ } catch {
+ # Skip invalid value for known permission (constructor throws); preserves original behavior.
+ continue
}
}
return $result | Sort-Object Scope, DisplayName
@@ -1294,8 +1275,8 @@ class GitHubPermission : GitHubPermissionDefinition {
# Returns a full catalog of permissions, ensuring all known permissions are present.
# If an object with granted permissions is provided, its values are merged.
- static [GitHubPermission[]] NewFullCatalog([pscustomobject] $Object, [string] $InstallationType) {
- $granted = [GitHubPermission]::newFromObject($Object)
+ static [GitHubPermission[]] newPermissionList([pscustomobject] $Object, [string] $InstallationType) {
+ $granted = [GitHubPermission]::newPermission($Object)
$grantedLookup = @{}
foreach ($g in $granted) { $grantedLookup[$g.Name] = $g }
@@ -1317,7 +1298,6 @@ class GitHubPermission : GitHubPermissionDefinition {
}
}
- # Include unknown permissions (those not in catalog) as-is
foreach ($g in $granted) {
if (-not ([GitHubPermissionDefinition]::List.Name -contains $g.Name)) {
$full += $g
From 968dce5192fb09a364f9e2dd450ca2b30363a89b Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 23:35:04 +0200
Subject: [PATCH 16/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Add=20new=20per?=
=?UTF-8?q?mission=20definition=20for=20enterprise=20custom=20organization?=
=?UTF-8?q?=20roles=20with=20detailed=20description=20and=20access=20level?=
=?UTF-8?q?s?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 5bf75db69..0abbf2996 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1135,6 +1135,19 @@ class GitHubPermissionDefinition {
'Fine-grained',
'Enterprise'
),
+ [GitHubPermissionDefinition]::new(
+ 'enterprise_custom_org_roles',
+ 'Enterprise custom organization roles',
+ 'Create, edit, delete and list custom organization roles at the enterprise level. View system organization roles.',
+ 'https://docs.github.com/enterprise-cloud@latest/rest/overview/permissions-required-for-github-apps' +
+ '#enterprise-permissions-for-enterprise-custom-organization-roles',
+ @(
+ 'read',
+ 'write'
+ ),
+ 'Fine-grained',
+ 'Enterprise'
+ ),
[GitHubPermissionDefinition]::new(
'enterprise_organization_installation_repositories',
'Enterprise organization installation repositories',
From 6ce56a6945f20bbfed3678698bcbfa5a1b9fba64 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sat, 13 Sep 2025 23:45:12 +0200
Subject: [PATCH 17/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Remove=20'read'?=
=?UTF-8?q?=20option=20from=20permission=20definition=20for=20improved=20c?=
=?UTF-8?q?larity=20in=20access=20levels?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 0abbf2996..5c8e10e8c 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1073,7 +1073,6 @@ class GitHubPermissionDefinition {
'https://docs.github.com/rest/overview/permissions-required-for-github-apps' +
'#user-permissions-for-profile',
@(
- 'read',
'write'
),
'Fine-grained',
From 8d245b69defa3e01ba650b8f67218403c56c635d Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sun, 14 Sep 2025 01:13:20 +0200
Subject: [PATCH 18/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Remove=20Compar?=
=?UTF-8?q?eWithAppConfiguration=20method=20and=20replace=20with=20UpdateS?=
=?UTF-8?q?tatus=20for=20improved=20permission=20status=20management=20in?=
=?UTF-8?q?=20GitHubAppInstallation=20class?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../public/App/GitHubAppInstallation.ps1 | 110 ++++++++++--------
src/classes/public/GitHubPermission.ps1 | 2 -
2 files changed, 62 insertions(+), 50 deletions(-)
diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1
index d23ea7186..327e89686 100644
--- a/src/classes/public/App/GitHubAppInstallation.ps1
+++ b/src/classes/public/App/GitHubAppInstallation.ps1
@@ -46,52 +46,6 @@
GitHubAppInstallation() {}
- # Helper method to compare installation permissions and events with app configuration
- hidden [string] CompareWithAppConfiguration([GitHubPermission[]] $AppPermissions, [string[]] $AppEvents) {
- if ($null -eq $AppPermissions -or $null -eq $AppEvents) {
- return 'Unknown'
- }
-
- # Build lookup tables
- $appLookup = @{}
- foreach ($p in $AppPermissions) { $appLookup[$p.Name] = $p }
- $instLookup = @{}
- foreach ($p in $this.Permissions) { $instLookup[$p.Name] = $p }
-
- # Compare permissions - check if installation has all the permissions that the app requires (for its scope)
- $permissionsMatch = $true
- foreach ($appPerm in $AppPermissions) {
- # Only evaluate permissions with a value (requested). Missing (null) == no access required.
- if ([string]::IsNullOrEmpty($appPerm.Value)) { continue }
- $instValue = $instLookup[$appPerm.Name].Value
- if ($instValue -ne $appPerm.Value) {
- $permissionsMatch = $false
- break
- }
- }
-
- # Compare events - check if installation subscribes to all events that the app wants
- $eventsMatch = $true
- if ($AppEvents -and $AppEvents.Count -gt 0) {
- foreach ($appEvent in $AppEvents) {
- if ($appEvent -notin $this.Events) {
- $eventsMatch = $false
- break
- }
- }
- }
-
- if ($permissionsMatch -and $eventsMatch) {
- return 'UpToDate'
- } elseif (-not $permissionsMatch -and -not $eventsMatch) {
- return 'PermissionsAndEventsOutdated'
- } elseif (-not $permissionsMatch) {
- return 'PermissionsOutdated'
- } else {
- return 'EventsOutdated'
- }
- }
-
GitHubAppInstallation([PSCustomObject] $Object) {
$this.ID = $Object.id
$this.App = [GitHubApp]::new(
@@ -129,7 +83,7 @@
$this.SuspendedAt = $Object.suspended_at
$this.SuspendedBy = [GitHubUser]::new($Object.suspended_by)
$this.Url = $Object.html_url
- $this.Status = $this.CompareWithAppConfiguration($App.Permissions, $App.Events)
+ $this.UpdateStatus()
}
GitHubAppInstallation([PSCustomObject] $Object, [string] $Target, [string] $Type, [GitHubContext] $Context) {
@@ -177,6 +131,66 @@
$this.SuspendedAt = $Object.suspended_at
$this.SuspendedBy = [GitHubUser]::new($Object.suspended_by)
$this.Url = "https://$($Context.HostName)/$($Type.ToLower())s/$Target/settings/installations/$($Object.id)"
- $this.Status = $this.CompareWithAppConfiguration($App.Permissions, $App.Events)
+ $this.UpdateStatus()
+ }
+
+ # Updates the Status property by comparing installation permissions with app permissions
+ # filtered by the appropriate scope based on installation type
+ [void] UpdateStatus() {
+ if (-not $this.App -or -not $this.App.Permissions) {
+ $this.Status = 'Unknown'
+ return
+ }
+
+ # Get app permissions filtered by installation type scope
+ $appPermissionsFiltered = switch ($this.Type) {
+ 'Enterprise' {
+ $this.App.Permissions | Where-Object { $_.Scope -eq 'Enterprise' }
+ }
+ 'Organization' {
+ $this.App.Permissions | Where-Object { $_.Scope -in @('Organization', 'Repository') }
+ }
+ 'User' {
+ $this.App.Permissions | Where-Object { $_.Scope -in @('User', 'Repository') }
+ }
+ default {
+ $this.App.Permissions
+ }
+ }
+
+ # Compare permissions by creating lookup dictionaries
+ $appPermissionLookup = @{}
+ foreach ($perm in $appPermissionsFiltered) {
+ $appPermissionLookup[$perm.Name] = $perm.Value
+ }
+
+ $installationPermissionLookup = @{}
+ foreach ($perm in $this.Permissions) {
+ $installationPermissionLookup[$perm.Name] = $perm.Value
+ }
+
+ # Check if permissions match
+ $permissionsMatch = $true
+
+ # Check if all app permissions exist in installation with same values
+ foreach ($name in $appPermissionLookup.Keys) {
+ if (-not $installationPermissionLookup.ContainsKey($name) -or
+ $installationPermissionLookup[$name] -ne $appPermissionLookup[$name]) {
+ $permissionsMatch = $false
+ break
+ }
+ }
+
+ # Check if installation has any extra permissions not in the app
+ if ($permissionsMatch) {
+ foreach ($name in $installationPermissionLookup.Keys) {
+ if (-not $appPermissionLookup.ContainsKey($name)) {
+ $permissionsMatch = $false
+ break
+ }
+ }
+ }
+
+ $this.Status = $permissionsMatch ? 'Ok' : 'Outdated'
}
}
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 5c8e10e8c..e2695e266 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1285,8 +1285,6 @@ class GitHubPermission : GitHubPermissionDefinition {
return $result | Sort-Object Scope, DisplayName
}
- # Returns a full catalog of permissions, ensuring all known permissions are present.
- # If an object with granted permissions is provided, its values are merged.
static [GitHubPermission[]] newPermissionList([pscustomobject] $Object, [string] $InstallationType) {
$granted = [GitHubPermission]::newPermission($Object)
$grantedLookup = @{}
From 4b901dd5de5e0207ec443287f23462da32f5f6fe Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sun, 14 Sep 2025 19:34:27 +0200
Subject: [PATCH 19/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20permis?=
=?UTF-8?q?sion=20filtering=20for=20'User'=20scope=20to=20only=20include?=
=?UTF-8?q?=20'Repository'=20in=20GitHubPermission=20and=20GitHubAppInstal?=
=?UTF-8?q?lation=20classes?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/App/GitHubAppInstallation.ps1 | 2 +-
src/classes/public/GitHubPermission.ps1 | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1
index 327e89686..80beea68f 100644
--- a/src/classes/public/App/GitHubAppInstallation.ps1
+++ b/src/classes/public/App/GitHubAppInstallation.ps1
@@ -151,7 +151,7 @@
$this.App.Permissions | Where-Object { $_.Scope -in @('Organization', 'Repository') }
}
'User' {
- $this.App.Permissions | Where-Object { $_.Scope -in @('User', 'Repository') }
+ $this.App.Permissions | Where-Object { $_.Scope -in @('Repository') }
}
default {
$this.App.Permissions
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index e2695e266..e9b9f527e 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1320,7 +1320,7 @@ class GitHubPermission : GitHubPermissionDefinition {
switch ($InstallationType) {
'Enterprise' { return $full | Where-Object { $_.Scope -eq 'Enterprise' } }
'Organization' { return $full | Where-Object { $_.Scope -in @('Organization', 'Repository') } }
- 'User' { return $full | Where-Object { $_.Scope -in @('User', 'Repository') } }
+ 'User' { return $full | Where-Object { $_.Scope -in @('Repository') } }
}
return $full
}
From 4172baba39708079da63bb60feff691002f36b49 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sun, 14 Sep 2025 20:59:02 +0200
Subject: [PATCH 20/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20permis?=
=?UTF-8?q?sion=20validation=20in=20tests=20to=20ensure=20correct=20types?=
=?UTF-8?q?=20and=20counts=20for=20GitHubPermission=20objects?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 62 +++++++------------------
tests/Apps.Tests.ps1 | 53 +++++++--------------
2 files changed, 34 insertions(+), 81 deletions(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index e9b9f527e..174008304 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1270,58 +1270,30 @@ class GitHubPermission : GitHubPermissionDefinition {
$this.Value = $Value
}
- static [GitHubPermission[]] newPermission([pscustomobject] $Object) {
- if (-not $Object) { return @() }
- $result = @()
- foreach ($name in ($Object | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name)) {
- $tmpValue = $Object.$name
- try {
- $result += [GitHubPermission]::new($name, $tmpValue)
- } catch {
- # Skip invalid value for known permission (constructor throws); preserves original behavior.
- continue
- }
+ static [GitHubPermission[]] newPermissionListTemplate ([string] $InstallationType) {
+ $all = [GitHubPermissionDefinition]::List
+ $expectedDefs = switch ($InstallationType) {
+ 'Enterprise' { $all | Where-Object { $_.Scope -eq 'Enterprise' } }
+ 'Organization' { $all | Where-Object { $_.Scope -in @('Organization', 'Repository') } }
+ 'User' { $all | Where-Object { $_.Scope -in @('Repository') } }
+ }
+ $full = foreach ($def in $expectedDefs) {
+ [GitHubPermission]::new($def.Name, $null)
}
- return $result | Sort-Object Scope, DisplayName
+ return $full
}
static [GitHubPermission[]] newPermissionList([pscustomobject] $Object, [string] $InstallationType) {
- $granted = [GitHubPermission]::newPermission($Object)
- $grantedLookup = @{}
- foreach ($g in $granted) { $grantedLookup[$g.Name] = $g }
+ $permissions = [GitHubPermission]::newPermissionListTemplate($InstallationType)
- $full = @()
- foreach ($definition in [GitHubPermissionDefinition]::List) {
- if ($grantedLookup.ContainsKey($definition.Name)) {
- $full += $grantedLookup[$definition.Name]
+ foreach ($prop in $Object.PSObject.Properties) {
+ $knownPermission = $permissions | Where-Object { $_.Name -eq $prop.Name }
+ if ($knownPermission) {
+ $knownPermission.Value = $prop.Value
} else {
- $perm = [GitHubPermission]::new()
- $perm.Name = $definition.Name
- $perm.DisplayName = $definition.DisplayName
- $perm.Description = $definition.Description
- $perm.URL = $definition.URL
- $perm.Options = $definition.Options
- $perm.Type = $definition.Type
- $perm.Scope = $definition.Scope
- $perm.Value = $null
- $full += $perm
- }
- }
-
- foreach ($g in $granted) {
- if (-not ([GitHubPermissionDefinition]::List.Name -contains $g.Name)) {
- $full += $g
+ $permissions += [GitHubPermission]::new($prop.Name, $prop.Value)
}
}
- $full = $full | Sort-Object Scope, DisplayName
-
- if (-not $InstallationType) { return $full }
-
- switch ($InstallationType) {
- 'Enterprise' { return $full | Where-Object { $_.Scope -eq 'Enterprise' } }
- 'Organization' { return $full | Where-Object { $_.Scope -in @('Organization', 'Repository') } }
- 'User' { return $full | Where-Object { $_.Scope -in @('Repository') } }
- }
- return $full
+ return $permissions | Sort-Object Scope, DisplayName
}
}
diff --git a/tests/Apps.Tests.ps1 b/tests/Apps.Tests.ps1
index 7f59d3c1f..20f94afd5 100644
--- a/tests/Apps.Tests.ps1
+++ b/tests/Apps.Tests.ps1
@@ -56,7 +56,9 @@ Describe 'Apps' {
$app.Url | Should -Not -BeNullOrEmpty
$app.CreatedAt | Should -Not -BeNullOrEmpty
$app.UpdatedAt | Should -Not -BeNullOrEmpty
- $app.Permissions | Should -BeOfType 'PSCustomObject'
+ $app.Permissions.Count | Should -BeGreaterThan 0
+ $app.Permissions | Should -BeOfType 'GitHubPermission'
+ $app.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
$app.Events | Should -BeOfType 'string'
$app.Installations | Should -Not -BeNullOrEmpty
}
@@ -86,16 +88,17 @@ Describe 'Apps' {
$installation.Target | Should -Not -BeNullOrEmpty
$installation.Type | Should -BeIn @('Enterprise', 'Organization', 'User')
$installation.RepositorySelection | Should -Not -BeNullOrEmpty
- $installation.Permissions | Should -BeOfType 'PSCustomObject'
+ $installation.Permissions.Count | Should -BeGreaterThan 0
+ $installation.Permissions | Should -BeOfType [GitHubPermission]
+ $installation.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
$installation.Events | Should -BeOfType 'string'
$installation.CreatedAt | Should -Not -BeNullOrEmpty
$installation.UpdatedAt | Should -Not -BeNullOrEmpty
$installation.SuspendedAt | Should -BeNullOrEmpty
$installation.SuspendedBy | Should -BeOfType 'GitHubUser'
$installation.SuspendedBy | Should -BeNullOrEmpty
- # Validate the new Status property
$installation.Status | Should -Not -BeNullOrEmpty
- $installation.Status | Should -BeIn @('Unknown', 'UpToDate', 'PermissionsOutdated', 'EventsOutdated', 'PermissionsAndEventsOutdated')
+ $installation.Status | Should -BeIn @('Ok', 'Outdated')
}
}
@@ -116,45 +119,17 @@ Describe 'Apps' {
$installation.Target | Should -Be $owner
$installation.Type | Should -Be $ownerType
$installation.RepositorySelection | Should -Not -BeNullOrEmpty
- $installation.Permissions | Should -BeOfType 'PSCustomObject'
+ $installation.Permissions.Count | Should -BeGreaterThan 0
+ $installation.Permissions | Should -BeOfType [GitHubPermission]
+ $installation.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
$installation.Events | Should -BeOfType 'string'
$installation.CreatedAt | Should -Not -BeNullOrEmpty
$installation.UpdatedAt | Should -Not -BeNullOrEmpty
$installation.SuspendedAt | Should -BeNullOrEmpty
$installation.SuspendedBy | Should -BeOfType 'GitHubUser'
$installation.SuspendedBy | Should -BeNullOrEmpty
- # Validate the new Status property
$installation.Status | Should -Not -BeNullOrEmpty
- $installation.Status | Should -BeIn @('Unknown', 'UpToDate', 'PermissionsOutdated', 'EventsOutdated', 'PermissionsAndEventsOutdated')
- }
-
- It 'Get-GitHubAppInstallation - Status tracking functionality' {
- $githubApp = Get-GitHubApp
- $installations = Get-GitHubAppInstallation
- LogGroup 'Status tracking test' {
- Write-Host "Testing installation status tracking against app configuration"
- Write-Host "App Permissions: $($githubApp.Permissions | ConvertTo-Json -Compress)"
- Write-Host "App Events: $($githubApp.Events -join ', ')"
- }
-
- foreach ($installation in $installations) {
- LogGroup "Installation $($installation.ID) Status" {
- Write-Host "Installation ID: $($installation.ID)"
- Write-Host "Target: $($installation.Target.Name)"
- Write-Host "Status: $($installation.Status)"
- Write-Host "Installation Permissions: $($installation.Permissions | ConvertTo-Json -Compress)"
- Write-Host "Installation Events: $($installation.Events -join ', ')"
- }
-
- # The status should be calculated based on app vs installation comparison
- $installation.Status | Should -BeIn @('Unknown', 'UpToDate', 'PermissionsOutdated', 'EventsOutdated', 'PermissionsAndEventsOutdated')
-
- # When we have app information (which we do in this context), status should not be Unknown
- # for authenticated app installations
- if ($PSCmdlet.ParameterSetName -eq 'List installations for the authenticated app') {
- $installation.Status | Should -Not -Be 'Unknown'
- }
- }
+ $installation.Status | Should -BeIn @('Ok', 'Outdated')
}
}
@@ -235,6 +210,12 @@ Describe 'Apps' {
$context.TokenType | Should -Be 'ghs'
$context.HttpVersion | Should -Be $config.HttpVersion
$context.PerPage | Should -Be $config.PerPage
+ $context.Permissions.Count | Should -BeGreaterThan 0
+ $context.Permissions | Should -BeOfType [GitHubPermission]
+ $context.Permissions.Name | Should -BeIn ([GitHubPermission]::List).Name
+ $context.Permissions.Value | Should -BeIn ([GitHubPermission]::List)
+ $context.Events | Should -BeOfType 'string'
+
}
It 'Connect-GitHubApp - TokenExpiresIn property should be calculated correctly' {
From 68c1bd788bd25328b4f4cea10e739c29d2060a4e Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sun, 14 Sep 2025 21:18:19 +0200
Subject: [PATCH 21/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20perm?=
=?UTF-8?q?ission=20list=20creation=20in=20GitHubPermission=20class=20for?=
=?UTF-8?q?=20improved=20clarity=20and=20performance?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 174008304..f7303d517 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1277,8 +1277,9 @@ class GitHubPermission : GitHubPermissionDefinition {
'Organization' { $all | Where-Object { $_.Scope -in @('Organization', 'Repository') } }
'User' { $all | Where-Object { $_.Scope -in @('Repository') } }
}
- $full = foreach ($def in $expectedDefs) {
- [GitHubPermission]::new($def.Name, $null)
+ $full = @()
+ foreach ($def in $expectedDefs) {
+ $full += [GitHubPermission]::new($def.Name, $null)
}
return $full
}
@@ -1297,3 +1298,11 @@ class GitHubPermission : GitHubPermissionDefinition {
return $permissions | Sort-Object Scope, DisplayName
}
}
+
+$Object = [pscustomobject]@{
+ contents = 'read'
+ issues = 'write'
+ unknown_permission = 'custom_value'
+}
+
+$InstallationType = 'Organization'
From 4b67e3d5609e4b2016d7156f19d58761960ea2b7 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sun, 14 Sep 2025 21:52:46 +0200
Subject: [PATCH 22/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Remove=20unused?=
=?UTF-8?q?=20variables=20related=20to=20permissions=20in=20GitHubPermissi?=
=?UTF-8?q?on=20class=20for=20cleaner=20code?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 8 --------
1 file changed, 8 deletions(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index f7303d517..6fc9b70a9 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1298,11 +1298,3 @@ class GitHubPermission : GitHubPermissionDefinition {
return $permissions | Sort-Object Scope, DisplayName
}
}
-
-$Object = [pscustomobject]@{
- contents = 'read'
- issues = 'write'
- unknown_permission = 'custom_value'
-}
-
-$InstallationType = 'Organization'
From db204adbe3e3b9fdc5341157e2c47aa9584a00ea Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sun, 14 Sep 2025 22:16:04 +0200
Subject: [PATCH 23/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Add=20default?=
=?UTF-8?q?=20case=20to=20permission=20filtering=20in=20GitHubPermission?=
=?UTF-8?q?=20class=20for=20improved=20handling=20of=20unexpected=20scopes?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 6fc9b70a9..4279e5c9e 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1276,6 +1276,7 @@ class GitHubPermission : GitHubPermissionDefinition {
'Enterprise' { $all | Where-Object { $_.Scope -eq 'Enterprise' } }
'Organization' { $all | Where-Object { $_.Scope -in @('Organization', 'Repository') } }
'User' { $all | Where-Object { $_.Scope -in @('Repository') } }
+ default { $all }
}
$full = @()
foreach ($def in $expectedDefs) {
From 51eed1f21e147c29f8985b41b97e46cdf9a322d0 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Sun, 14 Sep 2025 22:36:55 +0200
Subject: [PATCH 24/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Enhance=20loggi?=
=?UTF-8?q?ng=20in=20Apps.Tests=20by=20adding=20permission=20context=20out?=
=?UTF-8?q?put=20and=20refining=20app=20retrieval=20tests?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
test2/GitHub.Tests.ps1 | 1 +
tests/Apps.Tests.ps1 | 30 ++++++++++++++++--------------
2 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/test2/GitHub.Tests.ps1 b/test2/GitHub.Tests.ps1
index 53b9e347e..9a7c69a17 100644
--- a/test2/GitHub.Tests.ps1
+++ b/test2/GitHub.Tests.ps1
@@ -124,6 +124,7 @@ Describe 'Auth' {
It 'Connect-GitHubAccount - Connects to GitHub CLI on runners' {
[string]::IsNullOrEmpty($(gh auth token)) | Should -Be $false
}
+
It 'Get-GitHubViewer - Gets the logged in context' {
$viewer = Get-GitHubViewer
LogGroup 'Viewer' {
diff --git a/tests/Apps.Tests.ps1 b/tests/Apps.Tests.ps1
index 20f94afd5..1a9139cbc 100644
--- a/tests/Apps.Tests.ps1
+++ b/tests/Apps.Tests.ps1
@@ -26,7 +26,10 @@ Describe 'Apps' {
BeforeAll {
LogGroup 'Context' {
$context = Connect-GitHubAccount @connectParams -PassThru -Silent
- Write-Host ($context | Format-List | Out-String)
+ Write-Host "$($context | Format-List | Out-String)"
+ }
+ LogGroup 'Permissions' {
+ Write-Host "$($context.Permissions | Format-Table | Out-String)"
}
}
@@ -35,6 +38,15 @@ Describe 'Apps' {
Write-Host ('-' * 60)
}
+ # Tests for IAT UAT and PAT goes here
+ It 'Get-GitHubApp - Get an app by slug' -Skip:($AuthType -eq 'APP') {
+ $app = Get-GitHubApp -Slug 'github-actions'
+ LogGroup 'App by slug' {
+ Write-Host ($app | Format-List | Out-String)
+ }
+ $app | Should -Not -BeNullOrEmpty
+ }
+
# Tests for APP goes here
if ($AuthType -eq 'APP') {
Context 'GitHub Apps' {
@@ -73,16 +85,15 @@ Describe 'Apps' {
It 'Get-GitHubAppInstallation - Can get app installations' {
$githubApp = Get-GitHubApp
$installations = Get-GitHubAppInstallation
- LogGroup 'Installations' {
- Write-Host ($installations | Format-List | Out-String)
- }
$installations | Should -Not -BeNullOrEmpty
foreach ($installation in $installations) {
+ LogGroup "Installation - $($installation.Target.Name)" {
+ Write-Host "$($installations | Format-List | Out-String)"
+ }
$installation | Should -BeOfType 'GitHubAppInstallation'
$installation.ID | Should -Not -BeNullOrEmpty
$installation.App | Should -BeOfType 'GitHubApp'
$installation.App.ClientID | Should -Be $githubApp.ClientID
- $installation.App.AppID | Should -Not -BeNullOrEmpty
$installation.App.Slug | Should -Not -BeNullOrEmpty
$installation.Target | Should -BeOfType 'GitHubOwner'
$installation.Target | Should -Not -BeNullOrEmpty
@@ -235,14 +246,5 @@ Describe 'Apps' {
}
}
}
-
- # Tests for IAT UAT and PAT goes here
- It 'Get-GitHubApp - Get an app by slug' -Skip:($AuthType -eq 'APP') {
- $app = Get-GitHubApp -Slug 'github-actions'
- LogGroup 'App by slug' {
- Write-Host ($app | Format-List | Out-String)
- }
- $app | Should -Not -BeNullOrEmpty
- }
}
}
From 54f4957177c31b4dadedd4581a33f589b5a66375 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 09:35:40 +0200
Subject: [PATCH 25/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20GitH?=
=?UTF-8?q?ub=20app=20tests=20for=20improved=20structure=20and=20clarity,?=
=?UTF-8?q?=20consolidating=20test=20cases=20and=20enhancing=20readability?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tests/Apps.Tests.ps1 | 311 +++++++++++++++++++++----------------------
1 file changed, 154 insertions(+), 157 deletions(-)
diff --git a/tests/Apps.Tests.ps1 b/tests/Apps.Tests.ps1
index 1a9139cbc..a6f64a4eb 100644
--- a/tests/Apps.Tests.ps1
+++ b/tests/Apps.Tests.ps1
@@ -38,7 +38,6 @@ Describe 'Apps' {
Write-Host ('-' * 60)
}
- # Tests for IAT UAT and PAT goes here
It 'Get-GitHubApp - Get an app by slug' -Skip:($AuthType -eq 'APP') {
$app = Get-GitHubApp -Slug 'github-actions'
LogGroup 'App by slug' {
@@ -47,88 +46,55 @@ Describe 'Apps' {
$app | Should -Not -BeNullOrEmpty
}
- # Tests for APP goes here
- if ($AuthType -eq 'APP') {
- Context 'GitHub Apps' {
- It 'Get-GitHubApp - Can get app details' {
- $app = Get-GitHubApp
- LogGroup 'App' {
- Write-Host ($app | Format-List | Out-String)
- }
- $app | Should -Not -BeNullOrEmpty
- $app | Should -BeOfType 'GitHubApp'
- $app.ID | Should -Not -BeNullOrEmpty
- $app.ClientID | Should -Not -BeNullOrEmpty
- $app.Slug | Should -Not -BeNullOrEmpty
- $app.NodeID | Should -Not -BeNullOrEmpty
- $app.Owner | Should -BeOfType 'GitHubOwner'
- $app.Name | Should -Not -BeNullOrEmpty
- $app.Description | Should -Not -BeNullOrEmpty
- $app.ExternalUrl | Should -Not -BeNullOrEmpty
- $app.Url | Should -Not -BeNullOrEmpty
- $app.CreatedAt | Should -Not -BeNullOrEmpty
- $app.UpdatedAt | Should -Not -BeNullOrEmpty
- $app.Permissions.Count | Should -BeGreaterThan 0
- $app.Permissions | Should -BeOfType 'GitHubPermission'
- $app.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
- $app.Events | Should -BeOfType 'string'
- $app.Installations | Should -Not -BeNullOrEmpty
- }
-
- It 'Get-GitHubAppInstallationRequest - Can get installation requests' {
- $installationRequests = Get-GitHubAppInstallationRequest
- LogGroup 'Installation requests' {
- Write-Host ($installationRequests | Format-List | Out-String)
- }
+ Context 'GitHub Apps' -Skip:($AuthType -ne 'APP') {
+ It 'Get-GitHubApp - Can get app details' {
+ $app = Get-GitHubApp
+ LogGroup 'App' {
+ Write-Host ($app | Format-List | Out-String)
}
+ $app | Should -Not -BeNullOrEmpty
+ $app | Should -BeOfType 'GitHubApp'
+ $app.ID | Should -Not -BeNullOrEmpty
+ $app.ClientID | Should -Not -BeNullOrEmpty
+ $app.Slug | Should -Not -BeNullOrEmpty
+ $app.NodeID | Should -Not -BeNullOrEmpty
+ $app.Owner | Should -BeOfType 'GitHubOwner'
+ $app.Name | Should -Not -BeNullOrEmpty
+ $app.Description | Should -Not -BeNullOrEmpty
+ $app.ExternalUrl | Should -Not -BeNullOrEmpty
+ $app.Url | Should -Not -BeNullOrEmpty
+ $app.CreatedAt | Should -Not -BeNullOrEmpty
+ $app.UpdatedAt | Should -Not -BeNullOrEmpty
+ $app.Permissions.Count | Should -BeGreaterThan 0
+ $app.Permissions | Should -BeOfType 'GitHubPermission'
+ $app.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
+ $app.Events | Should -BeOfType 'string'
+ $app.Installations | Should -Not -BeNullOrEmpty
+ }
- It 'Get-GitHubAppInstallation - Can get app installations' {
- $githubApp = Get-GitHubApp
- $installations = Get-GitHubAppInstallation
- $installations | Should -Not -BeNullOrEmpty
- foreach ($installation in $installations) {
- LogGroup "Installation - $($installation.Target.Name)" {
- Write-Host "$($installations | Format-List | Out-String)"
- }
- $installation | Should -BeOfType 'GitHubAppInstallation'
- $installation.ID | Should -Not -BeNullOrEmpty
- $installation.App | Should -BeOfType 'GitHubApp'
- $installation.App.ClientID | Should -Be $githubApp.ClientID
- $installation.App.Slug | Should -Not -BeNullOrEmpty
- $installation.Target | Should -BeOfType 'GitHubOwner'
- $installation.Target | Should -Not -BeNullOrEmpty
- $installation.Type | Should -BeIn @('Enterprise', 'Organization', 'User')
- $installation.RepositorySelection | Should -Not -BeNullOrEmpty
- $installation.Permissions.Count | Should -BeGreaterThan 0
- $installation.Permissions | Should -BeOfType [GitHubPermission]
- $installation.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
- $installation.Events | Should -BeOfType 'string'
- $installation.CreatedAt | Should -Not -BeNullOrEmpty
- $installation.UpdatedAt | Should -Not -BeNullOrEmpty
- $installation.SuspendedAt | Should -BeNullOrEmpty
- $installation.SuspendedBy | Should -BeOfType 'GitHubUser'
- $installation.SuspendedBy | Should -BeNullOrEmpty
- $installation.Status | Should -Not -BeNullOrEmpty
- $installation.Status | Should -BeIn @('Ok', 'Outdated')
- }
+ It 'Get-GitHubAppInstallationRequest - Can get installation requests' {
+ $installationRequests = Get-GitHubAppInstallationRequest
+ LogGroup 'Installation requests' {
+ Write-Host ($installationRequests | Format-List | Out-String)
}
+ }
- It 'Get-GitHubAppInstallation - ' {
- $githubApp = Get-GitHubApp
- $installation = Get-GitHubAppInstallation | Where-Object { ($_.Target.Name -eq $owner) -and ($_.Type -eq $ownerType) }
- LogGroup "Installation - $ownerType" {
- Write-Host ($installation | Format-List | Out-String)
+ It 'Get-GitHubAppInstallation - Can get app installations' {
+ $githubApp = Get-GitHubApp
+ $installations = Get-GitHubAppInstallation
+ $installations | Should -Not -BeNullOrEmpty
+ foreach ($installation in $installations) {
+ LogGroup "Installation - $($installation.Target.Name)" {
+ Write-Host "$($installations | Format-List | Out-String)"
}
- $installation | Should -Not -BeNullOrEmpty
$installation | Should -BeOfType 'GitHubAppInstallation'
$installation.ID | Should -Not -BeNullOrEmpty
$installation.App | Should -BeOfType 'GitHubApp'
$installation.App.ClientID | Should -Be $githubApp.ClientID
- $installation.App.AppID | Should -Not -BeNullOrEmpty
$installation.App.Slug | Should -Not -BeNullOrEmpty
$installation.Target | Should -BeOfType 'GitHubOwner'
- $installation.Target | Should -Be $owner
- $installation.Type | Should -Be $ownerType
+ $installation.Target | Should -Not -BeNullOrEmpty
+ $installation.Type | Should -BeIn @('Enterprise', 'Organization', 'User')
$installation.RepositorySelection | Should -Not -BeNullOrEmpty
$installation.Permissions.Count | Should -BeGreaterThan 0
$installation.Permissions | Should -BeOfType [GitHubPermission]
@@ -144,106 +110,137 @@ Describe 'Apps' {
}
}
- Context 'Webhooks' {
- It 'Get-GitHubAppWebhookConfiguration - Can get the webhook configuration' {
- $webhookConfig = Get-GitHubAppWebhookConfiguration
- LogGroup 'Webhook config' {
- Write-Host ($webhookConfig | Format-Table | Out-String)
- }
- $webhookConfig | Should -Not -BeNullOrEmpty
+ It 'Get-GitHubAppInstallation - ' {
+ $githubApp = Get-GitHubApp
+ $installation = Get-GitHubAppInstallation | Where-Object { ($_.Target.Name -eq $owner) -and ($_.Type -eq $ownerType) }
+ LogGroup "Installation - $ownerType" {
+ Write-Host ($installation | Format-List | Out-String)
}
+ $installation | Should -Not -BeNullOrEmpty
+ $installation | Should -BeOfType 'GitHubAppInstallation'
+ $installation.ID | Should -Not -BeNullOrEmpty
+ $installation.App | Should -BeOfType 'GitHubApp'
+ $installation.App.ClientID | Should -Be $githubApp.ClientID
+ $installation.App.Slug | Should -Not -BeNullOrEmpty
+ $installation.Target | Should -BeOfType 'GitHubOwner'
+ $installation.Target | Should -Be $owner
+ $installation.Type | Should -Be $ownerType
+ $installation.RepositorySelection | Should -Not -BeNullOrEmpty
+ $installation.Permissions.Count | Should -BeGreaterThan 0
+ $installation.Permissions | Should -BeOfType [GitHubPermission]
+ $installation.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
+ $installation.Events | Should -BeOfType 'string'
+ $installation.CreatedAt | Should -Not -BeNullOrEmpty
+ $installation.UpdatedAt | Should -Not -BeNullOrEmpty
+ $installation.SuspendedAt | Should -BeNullOrEmpty
+ $installation.SuspendedBy | Should -BeOfType 'GitHubUser'
+ $installation.SuspendedBy | Should -BeNullOrEmpty
+ $installation.Status | Should -Not -BeNullOrEmpty
+ $installation.Status | Should -BeIn @('Ok', 'Outdated')
+ }
+ }
- It 'Update-GitHubAppWebhookConfiguration - Can update the webhook configuration' {
- { Update-GitHubAppWebhookConfiguration -ContentType 'form' } | Should -Not -Throw
- $webhookConfig = Get-GitHubAppWebhookConfiguration
- LogGroup 'Webhook config - form' {
- Write-Host ($webhookConfig | Format-Table | Out-String)
- }
- { Update-GitHubAppWebhookConfiguration -ContentType 'json' } | Should -Not -Throw
- $webhookConfig = Get-GitHubAppWebhookConfiguration
- LogGroup 'Webhook config - json' {
- Write-Host ($webhookConfig | Format-Table | Out-String)
- }
+ Context 'Webhooks' -Skip:($AuthType -ne 'APP') {
+ It 'Get-GitHubAppWebhookConfiguration - Can get the webhook configuration' {
+ $webhookConfig = Get-GitHubAppWebhookConfiguration
+ LogGroup 'Webhook config' {
+ Write-Host ($webhookConfig | Format-Table | Out-String)
}
+ $webhookConfig | Should -Not -BeNullOrEmpty
+ }
- It 'Get-GitHubAppWebhookDelivery - Can get webhook deliveries' {
- $deliveries = Get-GitHubAppWebhookDelivery
- LogGroup 'Deliveries' {
- Write-Host ($deliveries | Format-Table | Out-String)
- }
- $deliveries | Should -Not -BeNullOrEmpty
+ It 'Update-GitHubAppWebhookConfiguration - Can update the webhook configuration' {
+ { Update-GitHubAppWebhookConfiguration -ContentType 'form' } | Should -Not -Throw
+ $webhookConfig = Get-GitHubAppWebhookConfiguration
+ LogGroup 'Webhook config - form' {
+ Write-Host ($webhookConfig | Format-Table | Out-String)
}
-
- It 'Get-GitHubAppWebhookDelivery - Can redeliver a webhook delivery' {
- $deliveries = Get-GitHubAppWebhookDelivery | Select-Object -First 1
- LogGroup 'Delivery - redeliver' {
- Write-Host ($deliveries | Format-Table | Out-String)
- }
- { Invoke-GitHubAppWebhookReDelivery -ID $deliveries.id } | Should -Not -Throw
- LogGroup 'Delivery - redeliver' {
- Write-Host ($deliveries | Format-Table | Out-String)
- }
+ { Update-GitHubAppWebhookConfiguration -ContentType 'json' } | Should -Not -Throw
+ $webhookConfig = Get-GitHubAppWebhookConfiguration
+ LogGroup 'Webhook config - json' {
+ Write-Host ($webhookConfig | Format-Table | Out-String)
}
}
- Context 'Installation' {
- BeforeAll {
- $githubApp = Get-GitHubApp
- $config = Get-GitHubConfig
- $context = Connect-GitHubApp @connectAppParams -PassThru -Silent
- LogGroup 'Context' {
- Write-Host ($context | Format-List | Out-String)
- }
+ It 'Get-GitHubAppWebhookDelivery - Can get webhook deliveries' {
+ $deliveries = Get-GitHubAppWebhookDelivery
+ LogGroup 'Deliveries' {
+ Write-Host ($deliveries | Format-Table | Out-String)
}
+ $deliveries | Should -Not -BeNullOrEmpty
+ }
- It 'Connect-GitHubApp - Connects as a GitHub App to ' {
- $context | Should -BeOfType 'GitHubAppInstallationContext'
- $context.ClientID | Should -Be $githubApp.ClientID
- $context.TokenExpiresAt | Should -BeOfType [datetime]
- $context.InstallationID | Should -BeOfType [uint64]
- $context.InstallationID | Should -BeGreaterThan 0
- $context.Permissions | Should -BeOfType [PSCustomObject]
- $context.Events | Should -BeOfType 'string'
- $context.InstallationType | Should -Be $ownertype
- $context.InstallationName | Should -Be $owner
- $context.ID | Should -Be "$($config.HostName)/$($githubApp.Slug)/$ownertype/$owner"
- $context.Name | Should -Be "$($config.HostName)/$($githubApp.Slug)/$ownertype/$owner"
- $context.DisplayName | Should -Be $githubApp.Name
- $context.Type | Should -Be 'Installation'
- $context.HostName | Should -Be $config.HostName
- $context.ApiBaseUri | Should -Be $config.ApiBaseUri
- $context.ApiVersion | Should -Be $config.ApiVersion
- $context.AuthType | Should -Be 'IAT'
- $context.NodeID | Should -Not -BeNullOrEmpty
- $context.DatabaseID | Should -Not -BeNullOrEmpty
- $context.UserName | Should -Be $githubApp.Slug
- $context.Token | Should -BeOfType [System.Security.SecureString]
- $context.TokenType | Should -Be 'ghs'
- $context.HttpVersion | Should -Be $config.HttpVersion
- $context.PerPage | Should -Be $config.PerPage
- $context.Permissions.Count | Should -BeGreaterThan 0
- $context.Permissions | Should -BeOfType [GitHubPermission]
- $context.Permissions.Name | Should -BeIn ([GitHubPermission]::List).Name
- $context.Permissions.Value | Should -BeIn ([GitHubPermission]::List)
- $context.Events | Should -BeOfType 'string'
-
+ It 'Get-GitHubAppWebhookDelivery - Can redeliver a webhook delivery' {
+ $deliveries = Get-GitHubAppWebhookDelivery | Select-Object -First 1
+ LogGroup 'Delivery - redeliver' {
+ Write-Host ($deliveries | Format-Table | Out-String)
}
+ { Invoke-GitHubAppWebhookReDelivery -ID $deliveries.id } | Should -Not -Throw
+ LogGroup 'Delivery - redeliver' {
+ Write-Host ($deliveries | Format-Table | Out-String)
+ }
+ }
+ }
- It 'Connect-GitHubApp - TokenExpiresIn property should be calculated correctly' {
- $context.TokenExpiresIn | Should -BeOfType [TimeSpan]
- $context.TokenExpiresIn.TotalMinutes | Should -BeGreaterThan 0
- $context.TokenExpiresIn.TotalMinutes | Should -BeLessOrEqual 60
+ Context 'Installation' -Skip:($AuthType -ne 'APP') {
+ BeforeAll {
+ $githubApp = Get-GitHubApp
+ $config = Get-GitHubConfig
+ $context = Connect-GitHubApp @connectAppParams -PassThru -Silent
+ LogGroup 'Context' {
+ Write-Host "$($context | Format-List | Out-String)"
+ }
+ LogGroup 'Permissions' {
+ Write-Host "$($context.Permissions | Format-Table | Out-String)"
}
+ }
- It 'Revoked GitHub App token should fail on API call' -Skip:($TokenType -eq 'GITHUB_TOKEN') {
- $org = Get-GitHubOrganization -Name PSModule -Context $context
- $org | Should -Not -BeNullOrEmpty
- $context | Disconnect-GitHub
+ It 'Connect-GitHubApp - Connects as a GitHub App to ' {
+ $context | Should -BeOfType 'GitHubAppInstallationContext'
+ $context.ClientID | Should -Be $githubApp.ClientID
+ $context.TokenExpiresAt | Should -BeOfType [datetime]
+ $context.InstallationID | Should -BeOfType [uint64]
+ $context.InstallationID | Should -BeGreaterThan 0
+ $context.Events | Should -BeOfType 'string'
+ $context.InstallationType | Should -Be $ownertype
+ $context.InstallationName | Should -Be $owner
+ $context.ID | Should -Be "$($config.HostName)/$($githubApp.Slug)/$ownertype/$owner"
+ $context.Name | Should -Be "$($config.HostName)/$($githubApp.Slug)/$ownertype/$owner"
+ $context.DisplayName | Should -Be $githubApp.Name
+ $context.Type | Should -Be 'Installation'
+ $context.HostName | Should -Be $config.HostName
+ $context.ApiBaseUri | Should -Be $config.ApiBaseUri
+ $context.ApiVersion | Should -Be $config.ApiVersion
+ $context.AuthType | Should -Be 'IAT'
+ $context.NodeID | Should -Not -BeNullOrEmpty
+ $context.DatabaseID | Should -Not -BeNullOrEmpty
+ $context.UserName | Should -Be $githubApp.Slug
+ $context.Token | Should -BeOfType [System.Security.SecureString]
+ $context.TokenType | Should -Be 'ghs'
+ $context.HttpVersion | Should -Be $config.HttpVersion
+ $context.PerPage | Should -Be $config.PerPage
+ $context.Permissions.Count | Should -BeGreaterThan 0
+ $context.Permissions | Should -BeOfType [GitHubPermission]
+ $context.Permissions.Name | Should -BeIn ([GitHubPermission]::List).Name
+ $context.Permissions.Value | Should -BeIn ([GitHubPermission]::List)
+ $context.Events | Should -BeOfType 'string'
- {
- Invoke-RestMethod -Method Get -Uri "$($context.ApiBaseUri)/orgs/PSModule" -Authentication Bearer -Token $context.token
- } | Should -Throw
- }
+ }
+
+ It 'Connect-GitHubApp - TokenExpiresIn property should be calculated correctly' {
+ $context.TokenExpiresIn | Should -BeOfType [TimeSpan]
+ $context.TokenExpiresIn.TotalMinutes | Should -BeGreaterThan 0
+ $context.TokenExpiresIn.TotalMinutes | Should -BeLessOrEqual 60
+ }
+
+ It 'Revoked GitHub App token should fail on API call' -Skip:($TokenType -eq 'GITHUB_TOKEN') {
+ $org = Get-GitHubOrganization -Name PSModule -Context $context
+ $org | Should -Not -BeNullOrEmpty
+ $context | Disconnect-GitHub
+
+ {
+ Invoke-RestMethod -Method Get -Uri "$($context.ApiBaseUri)/orgs/PSModule" -Authentication Bearer -Token $context.token
+ } | Should -Throw
}
}
}
From fa601ec439d02eb8be83fab8aeb780c2331718ae Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 09:54:49 +0200
Subject: [PATCH 26/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Fix=20logging?=
=?UTF-8?q?=20in=20installation=20tests=20to=20output=20individual=20insta?=
=?UTF-8?q?llation=20details=20instead=20of=20the=20entire=20list?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tests/Apps.Tests.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/Apps.Tests.ps1 b/tests/Apps.Tests.ps1
index a6f64a4eb..9ae2bce54 100644
--- a/tests/Apps.Tests.ps1
+++ b/tests/Apps.Tests.ps1
@@ -85,7 +85,7 @@ Describe 'Apps' {
$installations | Should -Not -BeNullOrEmpty
foreach ($installation in $installations) {
LogGroup "Installation - $($installation.Target.Name)" {
- Write-Host "$($installations | Format-List | Out-String)"
+ Write-Host "$($installation | Format-List | Out-String)"
}
$installation | Should -BeOfType 'GitHubAppInstallation'
$installation.ID | Should -Not -BeNullOrEmpty
From ee7477c4be40efc7b0c27f2b804cf1fef935850f Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 10:49:29 +0200
Subject: [PATCH 27/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20perm?=
=?UTF-8?q?ission=20checks=20in=20Apps.Tests=20to=20use=20a=20single=20var?=
=?UTF-8?q?iable=20for=20GitHubPermissionDefinition=20list?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tests/Apps.Tests.ps1 | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/tests/Apps.Tests.ps1 b/tests/Apps.Tests.ps1
index 9ae2bce54..fc36ba570 100644
--- a/tests/Apps.Tests.ps1
+++ b/tests/Apps.Tests.ps1
@@ -24,6 +24,7 @@ Describe 'Apps' {
Context 'As using on ' -ForEach $authCases {
BeforeAll {
+ $permissionsDefinitions = [GitHubPermissionDefinition]::List
LogGroup 'Context' {
$context = Connect-GitHubAccount @connectParams -PassThru -Silent
Write-Host "$($context | Format-List | Out-String)"
@@ -67,7 +68,7 @@ Describe 'Apps' {
$app.UpdatedAt | Should -Not -BeNullOrEmpty
$app.Permissions.Count | Should -BeGreaterThan 0
$app.Permissions | Should -BeOfType 'GitHubPermission'
- $app.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
+ $app.Permissions.Name | Should -BeIn $permissionsDefinitions.Name
$app.Events | Should -BeOfType 'string'
$app.Installations | Should -Not -BeNullOrEmpty
}
@@ -98,7 +99,7 @@ Describe 'Apps' {
$installation.RepositorySelection | Should -Not -BeNullOrEmpty
$installation.Permissions.Count | Should -BeGreaterThan 0
$installation.Permissions | Should -BeOfType [GitHubPermission]
- $installation.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
+ $installation.Permissions.Name | Should -BeIn $permissionsDefinitions.Name
$installation.Events | Should -BeOfType 'string'
$installation.CreatedAt | Should -Not -BeNullOrEmpty
$installation.UpdatedAt | Should -Not -BeNullOrEmpty
@@ -128,7 +129,7 @@ Describe 'Apps' {
$installation.RepositorySelection | Should -Not -BeNullOrEmpty
$installation.Permissions.Count | Should -BeGreaterThan 0
$installation.Permissions | Should -BeOfType [GitHubPermission]
- $installation.Permissions.Name | Should -BeIn ([GitHubPermissionDefinition]::List).Name
+ $installation.Permissions.Name | Should -BeIn $permissionsDefinitions.Name
$installation.Events | Should -BeOfType 'string'
$installation.CreatedAt | Should -Not -BeNullOrEmpty
$installation.UpdatedAt | Should -Not -BeNullOrEmpty
@@ -186,6 +187,7 @@ Describe 'Apps' {
BeforeAll {
$githubApp = Get-GitHubApp
$config = Get-GitHubConfig
+ $permissionsDefinitions = [GitHubPermissionDefinition]::List
$context = Connect-GitHubApp @connectAppParams -PassThru -Silent
LogGroup 'Context' {
Write-Host "$($context | Format-List | Out-String)"
@@ -221,8 +223,7 @@ Describe 'Apps' {
$context.PerPage | Should -Be $config.PerPage
$context.Permissions.Count | Should -BeGreaterThan 0
$context.Permissions | Should -BeOfType [GitHubPermission]
- $context.Permissions.Name | Should -BeIn ([GitHubPermission]::List).Name
- $context.Permissions.Value | Should -BeIn ([GitHubPermission]::List)
+ $context.Permissions.Name | Should -BeIn $permissionsDefinitions.Name
$context.Events | Should -BeOfType 'string'
}
From fb83868e3201753b7d608eb9f00a179f0b8cd12f Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 12:19:26 +0200
Subject: [PATCH 28/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20perm?=
=?UTF-8?q?ission=20list=20creation=20in=20GitHubPermission=20class=20for?=
=?UTF-8?q?=20improved=20handling=20of=20permissions=20from=20PSCustomObje?=
=?UTF-8?q?ct?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/App/GitHubApp.ps1 | 2 +-
.../GitHubContext/GitHubAppContext.ps1 | 2 +-
src/classes/public/GitHubPermission.ps1 | 77 +++++++++++++++----
3 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/src/classes/public/App/GitHubApp.ps1 b/src/classes/public/App/GitHubApp.ps1
index bf2cba325..9e66bf081 100644
--- a/src/classes/public/App/GitHubApp.ps1
+++ b/src/classes/public/App/GitHubApp.ps1
@@ -59,7 +59,7 @@
$this.Url = $Object.html_url
$this.CreatedAt = $Object.created_at
$this.UpdatedAt = $Object.updated_at
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $null)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions)
$this.Events = , ($Object.events)
$this.Installations = $Object.installations_count
}
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
index 9975974ce..a94dc67a1 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
@@ -47,7 +47,7 @@
$this.KeyVaultKeyReference = $Object.KeyVaultKeyReference
$this.OwnerName = $Object.OwnerName
$this.OwnerType = $Object.OwnerType
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.Permissions, $null)
+ $this.Permissions = [GitHubPermission]::newPermissionList($Object.Permissions)
$this.Events = $Object.Events
}
}
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 4279e5c9e..b8ddc8de7 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1270,32 +1270,83 @@ class GitHubPermission : GitHubPermissionDefinition {
$this.Value = $Value
}
- static [GitHubPermission[]] newPermissionListTemplate ([string] $InstallationType) {
- $all = [GitHubPermissionDefinition]::List
- $expectedDefs = switch ($InstallationType) {
+ # Create a new list of all known permissions with null values
+ static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList() {
+ $tmpList = [System.Collections.Generic.List[GitHubPermission]]::new()
+ foreach ($def in [GitHubPermissionDefinition]::List) {
+ $tmpList.Add([GitHubPermission]@{
+ Name = $def.Name
+ Value = $null
+ DisplayName = $def.DisplayName
+ Description = $def.Description
+ URL = $def.URL
+ Options = $def.Options
+ Type = $def.Type
+ Scope = $def.Scope
+ })
+ }
+ return $tmpList | Sort-Object Scope, DisplayName
+ }
+
+ # Create a new list of permissions filtered by installation typem with null values
+ static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList([string] $InstallationType) {
+ $all = [GitHubPermission]::NewPermissionList()
+ $returned = switch ($InstallationType) {
'Enterprise' { $all | Where-Object { $_.Scope -eq 'Enterprise' } }
'Organization' { $all | Where-Object { $_.Scope -in @('Organization', 'Repository') } }
'User' { $all | Where-Object { $_.Scope -in @('Repository') } }
default { $all }
}
- $full = @()
- foreach ($def in $expectedDefs) {
- $full += [GitHubPermission]::new($def.Name, $null)
- }
- return $full
+ return $returned | Sort-Object Scope, DisplayName
}
- static [GitHubPermission[]] newPermissionList([pscustomobject] $Object, [string] $InstallationType) {
- $permissions = [GitHubPermission]::newPermissionListTemplate($InstallationType)
+ # Create a new list of all permissions with values from a PSCustomObject
+ static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList([pscustomobject] $Object) {
+ $all = [GitHubPermission]::NewPermissionList()
+ foreach ($prop in $Object.PSObject.Properties) {
+ $knownPermission = $all | Where-Object { $_.Name -eq $prop.Name }
+ if ($knownPermission) {
+ $knownPermission.Value = $prop.Value
+ } else {
+ $all.Add(
+ [GitHubPermission]@{
+ Name = $prop.Name
+ Value = $prop.Value
+ DisplayName = $prop.Name
+ Description = 'Unknown permission - Open issue to add metadata'
+ URL = $null
+ Options = @()
+ Type = 'Unknown'
+ Scope = 'Unknown'
+ }
+ )
+ }
+ }
+ return $all | Sort-Object Scope, DisplayName
+ }
+ # Create a new list of permissions filtered by installation type with values from a PSCustomObject
+ static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList([pscustomobject] $Object, [string] $InstallationType) {
+ $all = [GitHubPermission]::NewPermissionList()
foreach ($prop in $Object.PSObject.Properties) {
- $knownPermission = $permissions | Where-Object { $_.Name -eq $prop.Name }
+ $knownPermission = $all | Where-Object { $_.Name -eq $prop.Name }
if ($knownPermission) {
$knownPermission.Value = $prop.Value
} else {
- $permissions += [GitHubPermission]::new($prop.Name, $prop.Value)
+ $all.Add(
+ [GitHubPermission]@{
+ Name = $prop.Name
+ Value = $prop.Value
+ DisplayName = $prop.Name
+ Description = 'Unknown permission - Open issue to add metadata'
+ URL = $null
+ Options = @()
+ Type = 'Unknown'
+ Scope = 'Unknown'
+ }
+ )
}
}
- return $permissions | Sort-Object Scope, DisplayName
+ return $all | Sort-Object Scope, DisplayName
}
}
From 2e46e9dd716bc544aad51b441a999a6437720658 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 13:12:19 +0200
Subject: [PATCH 29/43] Refactor NewPermissionList methods to improve property
handling from PSCustomObject
---
src/classes/public/GitHubPermission.ps1 | 26 +++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index b8ddc8de7..c1bab63b1 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1303,16 +1303,17 @@ class GitHubPermission : GitHubPermissionDefinition {
# Create a new list of all permissions with values from a PSCustomObject
static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList([pscustomobject] $Object) {
$all = [GitHubPermission]::NewPermissionList()
- foreach ($prop in $Object.PSObject.Properties) {
- $knownPermission = $all | Where-Object { $_.Name -eq $prop.Name }
+ foreach ($name in $Object.PSObject.Properties.Name) {
+ $objectValue = $Object.$name
+ $knownPermission = $all | Where-Object { $_.Name -eq $name }
if ($knownPermission) {
- $knownPermission.Value = $prop.Value
+ $knownPermission.Value = $objectValue
} else {
$all.Add(
[GitHubPermission]@{
- Name = $prop.Name
- Value = $prop.Value
- DisplayName = $prop.Name
+ Name = $name
+ Value = $objectValue
+ DisplayName = $name
Description = 'Unknown permission - Open issue to add metadata'
URL = $null
Options = @()
@@ -1328,16 +1329,17 @@ class GitHubPermission : GitHubPermissionDefinition {
# Create a new list of permissions filtered by installation type with values from a PSCustomObject
static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList([pscustomobject] $Object, [string] $InstallationType) {
$all = [GitHubPermission]::NewPermissionList()
- foreach ($prop in $Object.PSObject.Properties) {
- $knownPermission = $all | Where-Object { $_.Name -eq $prop.Name }
+ foreach ($name in $Object.PSObject.Properties.Name) {
+ $objectValue = $Object.$name
+ $knownPermission = $all | Where-Object { $_.Name -eq $name }
if ($knownPermission) {
- $knownPermission.Value = $prop.Value
+ $knownPermission.Value = $objectValue
} else {
$all.Add(
[GitHubPermission]@{
- Name = $prop.Name
- Value = $prop.Value
- DisplayName = $prop.Name
+ Name = $name
+ Value = $objectValue
+ DisplayName = $name
Description = 'Unknown permission - Open issue to add metadata'
URL = $null
Options = @()
From 53e52490a87c58d24cc16656dc959773864a12b8 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 13:28:23 +0200
Subject: [PATCH 30/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20NewP?=
=?UTF-8?q?ermissionList=20method=20calls=20to=20use=20consistent=20casing?=
=?UTF-8?q?=20across=20GitHubPermission=20class=20and=20related=20contexts?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/App/GitHubApp.ps1 | 2 +-
.../public/App/GitHubAppInstallation.ps1 | 8 ++---
.../GitHubContext/GitHubAppContext.ps1 | 2 +-
.../GitHubAppInstallationContext.ps1 | 2 +-
src/classes/public/GitHubPermission.ps1 | 31 ++++++++++---------
.../Get-GitHubAuthenticatedApp.ps1 | 3 +-
6 files changed, 25 insertions(+), 23 deletions(-)
diff --git a/src/classes/public/App/GitHubApp.ps1 b/src/classes/public/App/GitHubApp.ps1
index 9e66bf081..9356e308c 100644
--- a/src/classes/public/App/GitHubApp.ps1
+++ b/src/classes/public/App/GitHubApp.ps1
@@ -59,7 +59,7 @@
$this.Url = $Object.html_url
$this.CreatedAt = $Object.created_at
$this.UpdatedAt = $Object.updated_at
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions)
+ $this.Permissions = [GitHubPermission]::NewPermissionList($Object.permissions)
$this.Events = , ($Object.events)
$this.Installations = $Object.installations_count
}
diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1
index 80beea68f..ed3365543 100644
--- a/src/classes/public/App/GitHubAppInstallation.ps1
+++ b/src/classes/public/App/GitHubAppInstallation.ps1
@@ -58,7 +58,7 @@
$this.Target = [GitHubOwner]::new($Object.account)
$this.Type = $Object.target_type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $this.Type)
+ $this.Permissions = [GitHubPermission]::NewPermissionList($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -75,7 +75,7 @@
$this.Target = [GitHubOwner]::new($Object.account)
$this.Type = $Object.target_type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $this.Type)
+ $this.Permissions = [GitHubPermission]::NewPermissionList($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -102,7 +102,7 @@
}
$this.Type = $Type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $this.Type)
+ $this.Permissions = [GitHubPermission]::NewPermissionList($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
@@ -123,7 +123,7 @@
}
$this.Type = $Type
$this.RepositorySelection = $Object.repository_selection
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.permissions, $this.Type)
+ $this.Permissions = [GitHubPermission]::NewPermissionList($Object.permissions, $this.Type)
$this.Events = , ($Object.events)
$this.FilePaths = $Object.single_file_paths
$this.CreatedAt = $Object.created_at
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
index a94dc67a1..856433681 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppContext.ps1
@@ -47,7 +47,7 @@
$this.KeyVaultKeyReference = $Object.KeyVaultKeyReference
$this.OwnerName = $Object.OwnerName
$this.OwnerType = $Object.OwnerType
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.Permissions)
+ $this.Permissions = [GitHubPermission]::NewPermissionList($Object.Permissions)
$this.Events = $Object.Events
}
}
diff --git a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1 b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
index ee6ee092d..93b5a7934 100644
--- a/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
+++ b/src/classes/public/Context/GitHubContext/GitHubAppInstallationContext.ps1
@@ -41,7 +41,7 @@
$this.PerPage = $Object.PerPage
$this.ClientID = $Object.ClientID
$this.InstallationID = $Object.InstallationID
- $this.Permissions = [GitHubPermission]::newPermissionList($Object.Permissions, $Object.InstallationType)
+ $this.Permissions = [GitHubPermission]::NewPermissionList($Object.Permissions, $Object.InstallationType)
$this.Events = $Object.Events
$this.InstallationType = $Object.InstallationType
$this.InstallationName = $Object.InstallationName
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index c1bab63b1..119e0d822 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1271,25 +1271,26 @@ class GitHubPermission : GitHubPermissionDefinition {
}
# Create a new list of all known permissions with null values
- static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList() {
- $tmpList = [System.Collections.Generic.List[GitHubPermission]]::new()
+ static [System.Collections.ArrayList] NewPermissionList() {
+ $tmpList = [System.Collections.ArrayList]::new()
foreach ($def in [GitHubPermissionDefinition]::List) {
- $tmpList.Add([GitHubPermission]@{
- Name = $def.Name
- Value = $null
- DisplayName = $def.DisplayName
- Description = $def.Description
- URL = $def.URL
- Options = $def.Options
- Type = $def.Type
- Scope = $def.Scope
- })
+ $object = [GitHubPermission]@{
+ Name = $def.Name
+ Value = $null
+ DisplayName = $def.DisplayName
+ Description = $def.Description
+ URL = $def.URL
+ Options = $def.Options
+ Type = $def.Type
+ Scope = $def.Scope
+ }
+ $tmpList.Add($object)
}
return $tmpList | Sort-Object Scope, DisplayName
}
# Create a new list of permissions filtered by installation typem with null values
- static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList([string] $InstallationType) {
+ static [System.Collections.ArrayList] NewPermissionList([string] $InstallationType) {
$all = [GitHubPermission]::NewPermissionList()
$returned = switch ($InstallationType) {
'Enterprise' { $all | Where-Object { $_.Scope -eq 'Enterprise' } }
@@ -1301,7 +1302,7 @@ class GitHubPermission : GitHubPermissionDefinition {
}
# Create a new list of all permissions with values from a PSCustomObject
- static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList([pscustomobject] $Object) {
+ static [System.Collections.ArrayList] NewPermissionList([pscustomobject] $Object) {
$all = [GitHubPermission]::NewPermissionList()
foreach ($name in $Object.PSObject.Properties.Name) {
$objectValue = $Object.$name
@@ -1327,7 +1328,7 @@ class GitHubPermission : GitHubPermissionDefinition {
}
# Create a new list of permissions filtered by installation type with values from a PSCustomObject
- static [System.Collections.Generic.List[GitHubPermission]] NewPermissionList([pscustomobject] $Object, [string] $InstallationType) {
+ static [System.Collections.ArrayList] NewPermissionList([pscustomobject] $Object, [string] $InstallationType) {
$all = [GitHubPermission]::NewPermissionList()
foreach ($name in $Object.PSObject.Properties.Name) {
$objectValue = $Object.$name
diff --git a/src/functions/private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1 b/src/functions/private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1
index 9686c3cfa..44b2164d4 100644
--- a/src/functions/private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1
+++ b/src/functions/private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1
@@ -41,7 +41,8 @@
Context = $Context
}
- Invoke-GitHubAPI @apiParams | ForEach-Object {
+ $response = Invoke-GitHubAPI @apiParams
+ | ForEach-Object {
[GitHubApp]::new($_.Response)
}
}
From 2a1944bd5559f8fffbaef867bf44693fad6f2efe Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 13:37:02 +0200
Subject: [PATCH 31/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Simplify=20resp?=
=?UTF-8?q?onse=20handling=20in=20Get-GitHubAuthenticatedApp=20by=20removi?=
=?UTF-8?q?ng=20unnecessary=20variable=20assignment?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1 | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/functions/private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1 b/src/functions/private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1
index 44b2164d4..9686c3cfa 100644
--- a/src/functions/private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1
+++ b/src/functions/private/Apps/GitHub Apps/Get-GitHubAuthenticatedApp.ps1
@@ -41,8 +41,7 @@
Context = $Context
}
- $response = Invoke-GitHubAPI @apiParams
- | ForEach-Object {
+ Invoke-GitHubAPI @apiParams | ForEach-Object {
[GitHubApp]::new($_.Response)
}
}
From 20f713f7a745d33f2178252b0c7768afbc6777e9 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 13:58:55 +0200
Subject: [PATCH 32/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Simplify=20GitH?=
=?UTF-8?q?ubPermission=20constructor=20and=20NewPermissionList=20methods?=
=?UTF-8?q?=20for=20improved=20clarity=20and=20performance?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 71 ++++++-------------------
1 file changed, 16 insertions(+), 55 deletions(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index 119e0d822..d39cdbbb1 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1245,36 +1245,20 @@ class GitHubPermission : GitHubPermissionDefinition {
GitHubPermission() : base() {}
GitHubPermission([string] $Permission, [string] $Value) : base() {
- $definition = [GitHubPermissionDefinition]::List | Where-Object { $_.Name -eq $Permission }
- if ($definition) {
- $this.Name = $definition.Name
- $this.DisplayName = $definition.DisplayName
- $this.Description = $definition.Description
- $this.URL = $definition.URL
- $this.Options = $definition.Options
- $this.Type = $definition.Type
- $this.Scope = $definition.Scope
- if ($Value -and ($definition.Options -notcontains $Value)) {
- throw "Invalid permission value: $Value for permission: $Permission"
- }
- } else {
- # Unknown permission: accept any value without validation
- $this.Name = $Permission
- $this.DisplayName = $Permission
- $this.Description = 'Unknown permission - Open issue to add metadata'
- $this.URL = $null
- $this.Options = @()
- $this.Type = 'Unknown'
- $this.Scope = 'Unknown'
- }
+ $this.Name = $Permission
$this.Value = $Value
+ $this.DisplayName = $Permission
+ $this.Description = 'Unknown permission - Open issue to add metadata'
+ $this.URL = $null
+ $this.Options = @()
+ $this.Type = 'Unknown'
+ $this.Scope = 'Unknown'
}
# Create a new list of all known permissions with null values
- static [System.Collections.ArrayList] NewPermissionList() {
- $tmpList = [System.Collections.ArrayList]::new()
- foreach ($def in [GitHubPermissionDefinition]::List) {
- $object = [GitHubPermission]@{
+ static [GitHubPermission[]] NewPermissionList() {
+ $tmpList = foreach ($def in [GitHubPermissionDefinition]::List) {
+ [GitHubPermission]@{
Name = $def.Name
Value = $null
DisplayName = $def.DisplayName
@@ -1284,13 +1268,12 @@ class GitHubPermission : GitHubPermissionDefinition {
Type = $def.Type
Scope = $def.Scope
}
- $tmpList.Add($object)
}
return $tmpList | Sort-Object Scope, DisplayName
}
- # Create a new list of permissions filtered by installation typem with null values
- static [System.Collections.ArrayList] NewPermissionList([string] $InstallationType) {
+ # Create a new list of permissions filtered by installation type with null values
+ static [GitHubPermission[]] NewPermissionList([string] $InstallationType) {
$all = [GitHubPermission]::NewPermissionList()
$returned = switch ($InstallationType) {
'Enterprise' { $all | Where-Object { $_.Scope -eq 'Enterprise' } }
@@ -1302,7 +1285,7 @@ class GitHubPermission : GitHubPermissionDefinition {
}
# Create a new list of all permissions with values from a PSCustomObject
- static [System.Collections.ArrayList] NewPermissionList([pscustomobject] $Object) {
+ static [GitHubPermission[]] NewPermissionList([pscustomobject] $Object) {
$all = [GitHubPermission]::NewPermissionList()
foreach ($name in $Object.PSObject.Properties.Name) {
$objectValue = $Object.$name
@@ -1310,18 +1293,7 @@ class GitHubPermission : GitHubPermissionDefinition {
if ($knownPermission) {
$knownPermission.Value = $objectValue
} else {
- $all.Add(
- [GitHubPermission]@{
- Name = $name
- Value = $objectValue
- DisplayName = $name
- Description = 'Unknown permission - Open issue to add metadata'
- URL = $null
- Options = @()
- Type = 'Unknown'
- Scope = 'Unknown'
- }
- )
+ $all += [GitHubPermission]::new($name, $objectValue)
}
}
return $all | Sort-Object Scope, DisplayName
@@ -1329,25 +1301,14 @@ class GitHubPermission : GitHubPermissionDefinition {
# Create a new list of permissions filtered by installation type with values from a PSCustomObject
static [System.Collections.ArrayList] NewPermissionList([pscustomobject] $Object, [string] $InstallationType) {
- $all = [GitHubPermission]::NewPermissionList()
+ $all = [GitHubPermission]::NewPermissionList($InstallationType)
foreach ($name in $Object.PSObject.Properties.Name) {
$objectValue = $Object.$name
$knownPermission = $all | Where-Object { $_.Name -eq $name }
if ($knownPermission) {
$knownPermission.Value = $objectValue
} else {
- $all.Add(
- [GitHubPermission]@{
- Name = $name
- Value = $objectValue
- DisplayName = $name
- Description = 'Unknown permission - Open issue to add metadata'
- URL = $null
- Options = @()
- Type = 'Unknown'
- Scope = 'Unknown'
- }
- )
+ $all += [GitHubPermission]::new($name, $objectValue)
}
}
return $all | Sort-Object Scope, DisplayName
From ac1a3a7c6be83b3ae23395735ac4f381d338329f Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 14:32:53 +0200
Subject: [PATCH 33/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20NewPer?=
=?UTF-8?q?missionList=20methods=20to=20return=20GitHubPermission=20array?=
=?UTF-8?q?=20and=20enhance=20import=20functionality?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/GitHubPermission.ps1 | 34 ++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index d39cdbbb1..b8b57023a 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1300,7 +1300,7 @@ class GitHubPermission : GitHubPermissionDefinition {
}
# Create a new list of permissions filtered by installation type with values from a PSCustomObject
- static [System.Collections.ArrayList] NewPermissionList([pscustomobject] $Object, [string] $InstallationType) {
+ static [GitHubPermission[]] NewPermissionList([pscustomobject] $Object, [string] $InstallationType) {
$all = [GitHubPermission]::NewPermissionList($InstallationType)
foreach ($name in $Object.PSObject.Properties.Name) {
$objectValue = $Object.$name
@@ -1313,4 +1313,36 @@ class GitHubPermission : GitHubPermissionDefinition {
}
return $all | Sort-Object Scope, DisplayName
}
+
+ # Create a new list of permissions with values from an array of objects (import functionality)
+ static [GitHubPermission[]] NewPermissionList([object[]] $Objects) {
+ $all = [GitHubPermission]::NewPermissionList()
+ foreach ($obj in $Objects) {
+ $name = $obj.Name
+ $value = $obj.Value
+ $knownPermission = $all | Where-Object { $_.Name -eq $name }
+ if ($knownPermission) {
+ $knownPermission.Value = $value
+ } else {
+ $all += [GitHubPermission]::new($name, $value)
+ }
+ }
+ return $all | Sort-Object Scope, DisplayName
+ }
+
+ # Create a new list of permissions filtered by installation type with values from an array of objects (import functionality)
+ static [GitHubPermission[]] NewPermissionList([object[]] $Objects, [string] $InstallationType) {
+ $all = [GitHubPermission]::NewPermissionList($InstallationType)
+ foreach ($obj in $Objects) {
+ $name = $obj.Name
+ $value = $obj.Value
+ $knownPermission = $all | Where-Object { $_.Name -eq $name }
+ if ($knownPermission) {
+ $knownPermission.Value = $value
+ } else {
+ $all += [GitHubPermission]::new($name, $value)
+ }
+ }
+ return $all | Sort-Object Scope, DisplayName
+ }
}
From 5f8a82ec7c59ed1820af0fac47a9d87a52dcd43f Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 14:35:39 +0200
Subject: [PATCH 34/43] Refactor NewPermissionList methods to streamline object
property access and improve readability
---
src/classes/public/GitHubPermission.ps1 | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/src/classes/public/GitHubPermission.ps1 b/src/classes/public/GitHubPermission.ps1
index b8b57023a..db355a3f8 100644
--- a/src/classes/public/GitHubPermission.ps1
+++ b/src/classes/public/GitHubPermission.ps1
@@ -1318,13 +1318,11 @@ class GitHubPermission : GitHubPermissionDefinition {
static [GitHubPermission[]] NewPermissionList([object[]] $Objects) {
$all = [GitHubPermission]::NewPermissionList()
foreach ($obj in $Objects) {
- $name = $obj.Name
- $value = $obj.Value
- $knownPermission = $all | Where-Object { $_.Name -eq $name }
+ $knownPermission = $all | Where-Object { $_.Name -eq $obj.Name }
if ($knownPermission) {
- $knownPermission.Value = $value
+ $knownPermission.Value = $obj.Value
} else {
- $all += [GitHubPermission]::new($name, $value)
+ $all += [GitHubPermission]::new($obj.Name, $obj.Value)
}
}
return $all | Sort-Object Scope, DisplayName
@@ -1334,13 +1332,11 @@ class GitHubPermission : GitHubPermissionDefinition {
static [GitHubPermission[]] NewPermissionList([object[]] $Objects, [string] $InstallationType) {
$all = [GitHubPermission]::NewPermissionList($InstallationType)
foreach ($obj in $Objects) {
- $name = $obj.Name
- $value = $obj.Value
- $knownPermission = $all | Where-Object { $_.Name -eq $name }
+ $knownPermission = $all | Where-Object { $_.Name -eq $obj.Name }
if ($knownPermission) {
- $knownPermission.Value = $value
+ $knownPermission.Value = $obj.Value
} else {
- $all += [GitHubPermission]::new($name, $value)
+ $all += [GitHubPermission]::new($obj.Name, $obj.Value)
}
}
return $all | Sort-Object Scope, DisplayName
From fe0dae803a97ed51bc5a1a76b6ac45438164ff97 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 15:07:13 +0200
Subject: [PATCH 35/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20Get-Gi?=
=?UTF-8?q?tHubPermissionDefinition=20to=20use=20List=20property=20for=20p?=
=?UTF-8?q?ermissions=20and=20improve=20test=20assertions=20for=20clarity?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../public/Permission/Get-GitHubPermissionDefinition.ps1 | 2 +-
tests/Permissions.Tests.ps1 | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/functions/public/Permission/Get-GitHubPermissionDefinition.ps1 b/src/functions/public/Permission/Get-GitHubPermissionDefinition.ps1
index 0019adf59..f7db75c69 100644
--- a/src/functions/public/Permission/Get-GitHubPermissionDefinition.ps1
+++ b/src/functions/public/Permission/Get-GitHubPermissionDefinition.ps1
@@ -86,7 +86,7 @@ function Get-GitHubPermissionDefinition {
return $false
}
- $script:GitHub.Permissions | Where-Object {
+ [GitHubPermissionDefinition]::List | Where-Object {
(& $test -Value $_.Name -Patterns $Name) -and
(& $test -Value $_.DisplayName -Patterns $DisplayName) -and
(& $test -Value $_.Type -Patterns $Type) -and
diff --git a/tests/Permissions.Tests.ps1 b/tests/Permissions.Tests.ps1
index 043358796..a3864fd98 100644
--- a/tests/Permissions.Tests.ps1
+++ b/tests/Permissions.Tests.ps1
@@ -93,7 +93,7 @@ Describe 'Permissions' {
$result = Get-GitHubPermissionDefinition
$result | Should -Not -BeNullOrEmpty
$result | Should -BeOfType [GitHubPermissionDefinition]
- ($result | Measure-Object).Count | Should -BeGreaterThan 0
+ $result.Count | Should -BeGreaterThan 0
}
It 'Should return only Fine-grained permissions when filtered by Type' {
From 3529d91f9b47d03df1b8485c9f93f8b9bd80a006 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 15:26:22 +0200
Subject: [PATCH 36/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Enhance=20app?=
=?UTF-8?q?=20context=20tests=20to=20verify=20Permissions=20property=20and?=
=?UTF-8?q?=20ensure=20valid=20permission=20types?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tests/Permissions.Tests.ps1 | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/tests/Permissions.Tests.ps1 b/tests/Permissions.Tests.ps1
index a3864fd98..fc5f72999 100644
--- a/tests/Permissions.Tests.ps1
+++ b/tests/Permissions.Tests.ps1
@@ -39,13 +39,17 @@ Describe 'Permissions' {
BeforeAll {
$installationContext = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent
LogGroup 'Context - Installation' {
- Write-Host ($installationContext | Format-List | Out-String)
+ Write-Host "$($installationContext | Format-List | Out-String)"
+ }
+ LogGroup 'Permissions' {
+ Write-Host "$($installationContext.Permissions | Format-List | Out-String)"
}
}
It 'App context should have Permissions property populated' -Skip:($AuthType -ne 'APP') {
- $installationContext.Permissions | Should -Not -BeNullOrEmpty
- $installationContext.Permissions | Should -BeOfType [pscustomobject]
+ $installationContext.Permissions.Count | Should -BeGreaterThan 0
+ $installationContext.Permissions | Should -BeOfType [GitHubPermission]
+ $installationContext.Permissions | Should -BeIn $permissionsDefinitions.Name
}
It 'All app installation permissions should exist in permission catalog and be valid options' -Skip:($AuthType -ne 'APP') {
From b4cfbdad5c021278ab4deba46b39a88cdce3c6c4 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 15:27:02 +0200
Subject: [PATCH 37/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Remove=20skip?=
=?UTF-8?q?=20condition=20from=20app=20context=20permission=20tests=20to?=
=?UTF-8?q?=20ensure=20they=20always=20run?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tests/Permissions.Tests.ps1 | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tests/Permissions.Tests.ps1 b/tests/Permissions.Tests.ps1
index fc5f72999..cba8bf312 100644
--- a/tests/Permissions.Tests.ps1
+++ b/tests/Permissions.Tests.ps1
@@ -46,13 +46,13 @@ Describe 'Permissions' {
}
}
- It 'App context should have Permissions property populated' -Skip:($AuthType -ne 'APP') {
+ It 'App context should have Permissions property populated' {
$installationContext.Permissions.Count | Should -BeGreaterThan 0
$installationContext.Permissions | Should -BeOfType [GitHubPermission]
$installationContext.Permissions | Should -BeIn $permissionsDefinitions.Name
}
- It 'All app installation permissions should exist in permission catalog and be valid options' -Skip:($AuthType -ne 'APP') {
+ It 'All app installation permissions should exist in permission catalog and be valid options' {
$catalog = Get-GitHubPermissionDefinition
$catalogNames = $catalog.Name
@@ -77,7 +77,7 @@ Describe 'Permissions' {
}
}
- It 'Permission catalog should contain all permissions granted to the app installation' -Skip:($AuthType -ne 'APP') {
+ It 'Permission catalog should contain all permissions granted to the app installation' {
$catalog = Get-GitHubPermissionDefinition
$missing = @()
$installationContext.Permissions.PSObject.Properties | ForEach-Object {
From f72dad007702aa74f71c5fab73fbd5565e088c17 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 15:43:22 +0200
Subject: [PATCH 38/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20app=20?=
=?UTF-8?q?context=20tests=20to=20use=20Format-Table=20for=20permissions?=
=?UTF-8?q?=20output=20and=20streamline=20permission=20validation=20logic?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tests/Permissions.Tests.ps1 | 37 +++++--------------------------------
1 file changed, 5 insertions(+), 32 deletions(-)
diff --git a/tests/Permissions.Tests.ps1 b/tests/Permissions.Tests.ps1
index cba8bf312..ba36b50dd 100644
--- a/tests/Permissions.Tests.ps1
+++ b/tests/Permissions.Tests.ps1
@@ -37,57 +37,30 @@ Describe 'Permissions' {
Context 'For Apps' -Skip:($AuthType -ne 'APP') {
BeforeAll {
+ $permissionsDefinitions = [GitHubPermissionDefinition]::List
$installationContext = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent
LogGroup 'Context - Installation' {
Write-Host "$($installationContext | Format-List | Out-String)"
}
LogGroup 'Permissions' {
- Write-Host "$($installationContext.Permissions | Format-List | Out-String)"
+ Write-Host "$($installationContext.Permissions | Format-Table | Out-String)"
}
}
It 'App context should have Permissions property populated' {
$installationContext.Permissions.Count | Should -BeGreaterThan 0
$installationContext.Permissions | Should -BeOfType [GitHubPermission]
- $installationContext.Permissions | Should -BeIn $permissionsDefinitions.Name
- }
-
- It 'All app installation permissions should exist in permission catalog and be valid options' {
- $catalog = Get-GitHubPermissionDefinition
- $catalogNames = $catalog.Name
-
- # Flatten context permission hashtable/object into name/value pairs (value is access level like read/write/admin)
- $granted = @()
- $installationContext.Permissions.PSObject.Properties | ForEach-Object {
- if ($_.Name -eq 'metadata') { return } # metadata is mandatory; still in catalog but just proceed normally
- $granted += [pscustomobject]@{ Name = $_.Name; Level = [string]$_.Value }
- }
-
- # Unknown permissions (present in context but not in catalog)
- $unknown = $granted | Where-Object { $_.Name -notin $catalogNames }
- if ($unknown) {
- throw "Unknown permission(s) detected in app installation: $($unknown.Name -join ', ')"
- }
-
- # For each granted permission ensure level is one of the catalog options
- foreach ($g in $granted) {
- $def = $catalog | Where-Object Name -EQ $g.Name
- $def | Should -Not -BeNullOrEmpty
- $def.Options | Should -Contain $g.Level
- }
+ $installationContext.Permissions.Name | Should -BeIn $permissionsDefinitions.Name
}
It 'Permission catalog should contain all permissions granted to the app installation' {
- $catalog = Get-GitHubPermissionDefinition
$missing = @()
$installationContext.Permissions.PSObject.Properties | ForEach-Object {
- if ($_.Name -notin $catalog.Name) {
+ if ($_.Name -notin $permissionsDefinitions.Name) {
$missing += $_.Name
}
}
- if ($missing.Count -gt 0) {
- throw "Missing permission definitions for: $($missing -join ', ')"
- }
+ $missing.Count | Should -Be 0 -Because "The following permissions are missing from the catalog: $($missing -join ', ')"
}
}
}
From 14499879db092b2b5cb92f19bda654288ac18973 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 16:16:44 +0200
Subject: [PATCH 39/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Simplify=20perm?=
=?UTF-8?q?ission=20validation=20by=20directly=20iterating=20over=20Permis?=
=?UTF-8?q?sions=20instead=20of=20PSObject.Properties?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tests/Permissions.Tests.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/Permissions.Tests.ps1 b/tests/Permissions.Tests.ps1
index ba36b50dd..99662a3d3 100644
--- a/tests/Permissions.Tests.ps1
+++ b/tests/Permissions.Tests.ps1
@@ -55,7 +55,7 @@ Describe 'Permissions' {
It 'Permission catalog should contain all permissions granted to the app installation' {
$missing = @()
- $installationContext.Permissions.PSObject.Properties | ForEach-Object {
+ $installationContext.Permissions | ForEach-Object {
if ($_.Name -notin $permissionsDefinitions.Name) {
$missing += $_.Name
}
From 058bdcee48d831a05ec398a2f49259fc1dc47686 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 17:20:34 +0200
Subject: [PATCH 40/43] Add initial test scripts for GitHub API interactions
- Created TEMPLATE.ps1 for Pester testing framework setup.
- Implemented Teams.Tests.ps1 to test GitHub Teams API functionalities including team creation, retrieval, updating, and deletion.
- Developed Users.Tests.ps1 to validate user-related API calls such as fetching user details and updating user information.
- Added Variables.Tests.ps1 to test GitHub repository and organization variable management, including setting, updating, and removing variables.
---
.github/PSModule.yml | 28 +++++++++++-----------
{test2 => tests}/Artifacts.Tests.ps1 | 0
{test2 => tests}/Emojis.Tests.ps1 | 0
{test2 => tests}/Enterprise.Tests.ps1 | 0
{test2 => tests}/Environments.Tests.ps1 | 0
{test2 => tests}/GitHub.Tests.ps1 | 0
{test2 => tests}/GitHubFormatter.Tests.ps1 | 0
{test2 => tests}/Organizations.Tests.ps1 | 0
{test2 => tests}/README.md | 0
{test2 => tests}/Releases.Tests.ps1 | 0
{test2 => tests}/Repositories.Tests.ps1 | 0
{test2 => tests}/Secrets.Tests.ps1 | 0
{test2 => tests}/TEMPLATE.ps1 | 0
{test2 => tests}/Teams.Tests.ps1 | 0
{test2 => tests}/Users.Tests.ps1 | 0
{test2 => tests}/Variables.Tests.ps1 | 0
16 files changed, 14 insertions(+), 14 deletions(-)
rename {test2 => tests}/Artifacts.Tests.ps1 (100%)
rename {test2 => tests}/Emojis.Tests.ps1 (100%)
rename {test2 => tests}/Enterprise.Tests.ps1 (100%)
rename {test2 => tests}/Environments.Tests.ps1 (100%)
rename {test2 => tests}/GitHub.Tests.ps1 (100%)
rename {test2 => tests}/GitHubFormatter.Tests.ps1 (100%)
rename {test2 => tests}/Organizations.Tests.ps1 (100%)
rename {test2 => tests}/README.md (100%)
rename {test2 => tests}/Releases.Tests.ps1 (100%)
rename {test2 => tests}/Repositories.Tests.ps1 (100%)
rename {test2 => tests}/Secrets.Tests.ps1 (100%)
rename {test2 => tests}/TEMPLATE.ps1 (100%)
rename {test2 => tests}/Teams.Tests.ps1 (100%)
rename {test2 => tests}/Users.Tests.ps1 (100%)
rename {test2 => tests}/Variables.Tests.ps1 (100%)
diff --git a/.github/PSModule.yml b/.github/PSModule.yml
index 08dc7e549..0e0770314 100644
--- a/.github/PSModule.yml
+++ b/.github/PSModule.yml
@@ -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
diff --git a/test2/Artifacts.Tests.ps1 b/tests/Artifacts.Tests.ps1
similarity index 100%
rename from test2/Artifacts.Tests.ps1
rename to tests/Artifacts.Tests.ps1
diff --git a/test2/Emojis.Tests.ps1 b/tests/Emojis.Tests.ps1
similarity index 100%
rename from test2/Emojis.Tests.ps1
rename to tests/Emojis.Tests.ps1
diff --git a/test2/Enterprise.Tests.ps1 b/tests/Enterprise.Tests.ps1
similarity index 100%
rename from test2/Enterprise.Tests.ps1
rename to tests/Enterprise.Tests.ps1
diff --git a/test2/Environments.Tests.ps1 b/tests/Environments.Tests.ps1
similarity index 100%
rename from test2/Environments.Tests.ps1
rename to tests/Environments.Tests.ps1
diff --git a/test2/GitHub.Tests.ps1 b/tests/GitHub.Tests.ps1
similarity index 100%
rename from test2/GitHub.Tests.ps1
rename to tests/GitHub.Tests.ps1
diff --git a/test2/GitHubFormatter.Tests.ps1 b/tests/GitHubFormatter.Tests.ps1
similarity index 100%
rename from test2/GitHubFormatter.Tests.ps1
rename to tests/GitHubFormatter.Tests.ps1
diff --git a/test2/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1
similarity index 100%
rename from test2/Organizations.Tests.ps1
rename to tests/Organizations.Tests.ps1
diff --git a/test2/README.md b/tests/README.md
similarity index 100%
rename from test2/README.md
rename to tests/README.md
diff --git a/test2/Releases.Tests.ps1 b/tests/Releases.Tests.ps1
similarity index 100%
rename from test2/Releases.Tests.ps1
rename to tests/Releases.Tests.ps1
diff --git a/test2/Repositories.Tests.ps1 b/tests/Repositories.Tests.ps1
similarity index 100%
rename from test2/Repositories.Tests.ps1
rename to tests/Repositories.Tests.ps1
diff --git a/test2/Secrets.Tests.ps1 b/tests/Secrets.Tests.ps1
similarity index 100%
rename from test2/Secrets.Tests.ps1
rename to tests/Secrets.Tests.ps1
diff --git a/test2/TEMPLATE.ps1 b/tests/TEMPLATE.ps1
similarity index 100%
rename from test2/TEMPLATE.ps1
rename to tests/TEMPLATE.ps1
diff --git a/test2/Teams.Tests.ps1 b/tests/Teams.Tests.ps1
similarity index 100%
rename from test2/Teams.Tests.ps1
rename to tests/Teams.Tests.ps1
diff --git a/test2/Users.Tests.ps1 b/tests/Users.Tests.ps1
similarity index 100%
rename from test2/Users.Tests.ps1
rename to tests/Users.Tests.ps1
diff --git a/test2/Variables.Tests.ps1 b/tests/Variables.Tests.ps1
similarity index 100%
rename from test2/Variables.Tests.ps1
rename to tests/Variables.Tests.ps1
From c5d8ad08c757dcbefcf673485c5918b8dc613f31 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 17:37:16 +0200
Subject: [PATCH 41/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Clarify=20comme?=
=?UTF-8?q?nt=20for=20Permissions=20property=20in=20GitHubAppInstallation?=
=?UTF-8?q?=20class?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/classes/public/App/GitHubAppInstallation.ps1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1
index ed3365543..3fecc9140 100644
--- a/src/classes/public/App/GitHubAppInstallation.ps1
+++ b/src/classes/public/App/GitHubAppInstallation.ps1
@@ -14,7 +14,7 @@
# The type of repository selection.
[string] $RepositorySelection
- # The permissions that the app has on the target (full catalog for applicable scopes).
+ # The permissions that the app has on the target.
[GitHubPermission[]] $Permissions
# The events that the app is subscribing to.
From c4021cc82726e8307ce9e387ffef30e54d873f8a Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 17:37:24 +0200
Subject: [PATCH 42/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Replace=20Scrip?=
=?UTF-8?q?tBlock=20with=20PropertyName=20for=20Status=20column=20in=20Git?=
=?UTF-8?q?HubAppInstallation=20format?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/formats/GitHubAppInstallation.Format.ps1xml | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/src/formats/GitHubAppInstallation.Format.ps1xml b/src/formats/GitHubAppInstallation.Format.ps1xml
index b8f97eca3..d81a69fe6 100644
--- a/src/formats/GitHubAppInstallation.Format.ps1xml
+++ b/src/formats/GitHubAppInstallation.Format.ps1xml
@@ -60,15 +60,7 @@
Type
-
- switch ($_.Status) {
- 'UpToDate' { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.Green)✓$($PSStyle.Reset)" } else { 'UpToDate' } }
- 'PermissionsOutdated' { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.Yellow)⚠P$($PSStyle.Reset)" } else { 'PermissionsOutdated' } }
- 'EventsOutdated' { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.Yellow)⚠E$($PSStyle.Reset)" } else { 'EventsOutdated' } }
- 'PermissionsAndEventsOutdated' { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.Red)✗$($PSStyle.Reset)" } else { 'PermissionsAndEventsOutdated' } }
- default { if ($Host.UI.SupportsVirtualTerminal -and ($env:GITHUB_ACTIONS -ne 'true')) { "$($PSStyle.Foreground.BrightBlack)?$($PSStyle.Reset)" } else { $_.Status } }
- }
-
+ Status
CreatedAt
From 90418145b5026e0a2791c10be5e78ad0c70d0314 Mon Sep 17 00:00:00 2001
From: Marius Storhaug
Date: Mon, 15 Sep 2025 23:25:44 +0200
Subject: [PATCH 43/43] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20argume?=
=?UTF-8?q?nt=20completers=20to=20use=20GitHubPermissionDefinition=20for?=
=?UTF-8?q?=20consistent=20permission=20retrieval?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/functions/public/Permission/completers.ps1 | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/functions/public/Permission/completers.ps1 b/src/functions/public/Permission/completers.ps1
index 4586354f0..dc0be7453 100644
--- a/src/functions/public/Permission/completers.ps1
+++ b/src/functions/public/Permission/completers.ps1
@@ -2,7 +2,7 @@
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
$pattern = switch (Get-GitHubConfig -Name CompletionMode) { 'Contains' { "*$wordToComplete*" } default { "$wordToComplete*" } }
- $script:GitHub.Permissions.Name | Sort-Object -Unique | Where-Object { $_ -like $pattern } | ForEach-Object {
+ [GitHubPermissionDefinition]::List.Name | Sort-Object -Unique | Where-Object { $_ -like $pattern } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
@@ -11,7 +11,7 @@ Register-ArgumentCompleter -CommandName Get-GitHubPermissionDefinition -Paramete
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
$pattern = switch (Get-GitHubConfig -Name CompletionMode) { 'Contains' { "*$wordToComplete*" } default { "$wordToComplete*" } }
- $script:GitHub.Permissions.DisplayName | Sort-Object -Unique | Where-Object { $_ -like $pattern } | ForEach-Object {
+ [GitHubPermissionDefinition]::List.DisplayName | Sort-Object -Unique | Where-Object { $_ -like $pattern } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
@@ -20,7 +20,7 @@ Register-ArgumentCompleter -CommandName Get-GitHubPermissionDefinition -Paramete
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
$pattern = switch (Get-GitHubConfig -Name CompletionMode) { 'Contains' { "*$wordToComplete*" } default { "$wordToComplete*" } }
- $script:GitHub.Permissions.Type | Sort-Object -Unique | Where-Object { $_ -like $pattern } | ForEach-Object {
+ [GitHubPermissionDefinition]::List.Type | Sort-Object -Unique | Where-Object { $_ -like $pattern } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
@@ -29,7 +29,7 @@ Register-ArgumentCompleter -CommandName Get-GitHubPermissionDefinition -Paramete
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
$pattern = switch (Get-GitHubConfig -Name CompletionMode) { 'Contains' { "*$wordToComplete*" } default { "$wordToComplete*" } }
- $script:GitHub.Permissions.Scope | Sort-Object -Unique | Where-Object { $_ -like $pattern } | ForEach-Object {
+ [GitHubPermissionDefinition]::List.Scope | Sort-Object -Unique | Where-Object { $_ -like $pattern } | ForEach-Object {
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}