From 76d9f8870c49376c86343d84ef857e8a629806d7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Fri, 4 Jul 2025 23:36:58 +0200 Subject: [PATCH 01/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Add=20New-GitHu?= =?UTF-8?q?bOrganization=20function=20to=20create=20organizations=20in=20a?= =?UTF-8?q?=20specified=20enterprise?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/Organizations/Organization.ps1 | 42 +++++++++++ .../Organization/New-GitHubOrganization.ps1 | 71 +++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 examples/Organizations/Organization.ps1 create mode 100644 src/functions/public/Organization/New-GitHubOrganization.ps1 diff --git a/examples/Organizations/Organization.ps1 b/examples/Organizations/Organization.ps1 new file mode 100644 index 000000000..43df1de04 --- /dev/null +++ b/examples/Organizations/Organization.ps1 @@ -0,0 +1,42 @@ +$orgParam = @{ + Enterprise = 'msx' + Name = 'Marius-Test7' + Owner = 'GitHub-Automation' + BillingEmail = 'post@msx.no' +} + +$org = New-GitHubOrganization @orgParam + +$installAppParam = @{ + Enterprise = 'msx' + Organization = $org.login + ClientID = (Get-GitHubContext).ClientID + RepositorySelection = 'all' +} +Install-GitHubApp @installAppParam + +$updateOrgParam = @{ + Name = $org.login + Description = 'Test organization created by PowerShell script' + Location = 'Oslo, Norway' + BillingEmail = 'post@msx.no' + Company = 'MSX AS' + Email = 'info@msx.no' + Blog = 'https://msx.no/blog' + TwitterUsername = 'msx_no' + HasOrganizationProjects = $true + DefaultRepositoryPermission = 'read' + MembersCanCreateRepositories = $true + MembersCanCreatePublicRepositories = $true + MembersCanCreatePrivateRepositories = $true + MembersCanCreateInternalRepositories = $true + MembersCanCreatePages = $true + MembersCanCreatePublicPages = $true + MembersCanCreatePrivatePages = $true + MembersCanForkPrivateRepositories = $true + WebCommitSignoffRequired = $false + SecretScanningPushProtectionEnabledForNewRepositories = $true + SecretScanningPushProtectionCustomLinkEnabled = $false + SecretScanningPushProtectionCustomLink = '' +} +Update-GitHubOrganization @updateOrgParam diff --git a/src/functions/public/Organization/New-GitHubOrganization.ps1 b/src/functions/public/Organization/New-GitHubOrganization.ps1 new file mode 100644 index 000000000..188168acb --- /dev/null +++ b/src/functions/public/Organization/New-GitHubOrganization.ps1 @@ -0,0 +1,71 @@ +function New-GitHubOrganization { + <# + .SYNOPSIS + Creates a new GitHub organization within a specified enterprise. + + .DESCRIPTION + This function creates a new GitHub organization within the specified enterprise. + + .EXAMPLE + New-GitHubOrganization -Enterprise 'my-enterprise' -Name 'my-org' -Owner 'user1' -BillingEmail 'billing@example.com' + + .OUTPUTS + GitHubOrganization + + .LINK + https://psmodule.io/GitHub/Functions/Organization/New-GitHubOrganization/ + #> + [OutputType([GitHubOrganization])] + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] + param( + [Parameter()] + [string]$Enterprise, + + [Parameter(Mandatory)] + [string]$Name, + + [Parameter(Mandatory)] + [string[]]$Owner, + + [Parameter()] + [string]$BillingEmail, + + # 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()] + [object] $Context + ) + + + $enterpriseObject = Get-GitHubEnterprise -Name $Enterprise -Context $Context + Write-Verbose "Creating organization in enterprise: $($enterpriseObject.Name)" + + $inputParams = @{ + adminLogins = $Owner + billingEmail = $BillingEmail + enterpriseId = $enterpriseObject.NodeID + login = $Name + profileName = $Name + } + + $updateGraphQLInputs = @{ + Query = @' + mutation($input:CreateEnterpriseOrganizationInput!) { + createEnterpriseOrganization(input:$input) { + organization { + id + login + } + } + } +'@ + Variables = @{ + input = $inputParams + } + Context = $Context + } + if ($PSCmdlet.ShouldProcess("Creating organization '$Name' in enterprise '$Enterprise'")) { + $orgresult = Invoke-GitHubGraphQLQuery @updateGraphQLInputs + [GitHubOrganization]::new($orgresult.createEnterpriseOrganization.organization) + } +} From f51059c6bb0b223c10f10231710508b65dde71fb Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Sun, 6 Jul 2025 21:37:58 +0200 Subject: [PATCH 02/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Cleanup=20of=20?= =?UTF-8?q?Context=20usage=20in=20classes,=20and=20functions=20for=20Repos?= =?UTF-8?q?itory=20Rule=20Suites=20(Insights)=20(#461)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description This pull request introduces several changes across multiple files to enhance the functionality and structure of GitHub-related classes in the codebase. The most notable updates include replacing `HostName` with `GitHubContext` for improved context management, restructuring properties in `GitHubOwner` subclasses, and updating XML format definitions to reflect the new structure. - Fixes #454 ### Context Management Updates: * Replaced the `HostName` parameter with `GitHubContext` in constructors across multiple classes (`GitHubAppInstallation`, `GitHubArtifact`, `GitHubEnvironment`, `GitHubOrganization`). This change centralizes context-related properties, such as `HostName`, for better scalability and readability. ### GitHubOwner Class Restructuring: * Removed redundant properties (e.g., `Company`, `Blog`, `Plan`) from the `GitHubOwner` class and its subclasses (`GitHubEnterprise`, `GitHubOrganization`, `GitHubUser`). Added new properties such as `Description` and `Website` to better align with GraphQL schema mappings. ### GraphQL Mapping Enhancements: * Introduced static `$PropertyToGraphQLMap` hashtables in `GitHubEnterprise` and `GitHubOrganization` classes to define mappings between class properties and GraphQL fields, improving maintainability and integration with GraphQL APIs. ### XML Format Updates: * Updated the `GitHubOwner.Format.ps1xml` file to include new properties (`DisplayName`, `CreatedAt`) in table views for improved visualization of `GitHubOwner` objects. Removed deprecated columns such as `Company` and `Plan`. ## Type of change - [ ] 📖 [Docs] - [ ] 🪲 [Fix] - [x] 🩹 [Patch] - [ ] ⚠️ [Security fix] - [ ] 🚀 [Feature] - [ ] 🌟 [Breaking change] ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas --- .github/PSModule.yml | 2 +- .../public/App/GitHubAppInstallation.ps1 | 6 +- .../public/Artifacts/GitHubArtifact.ps1 | 4 +- .../public/Environment/GitHubEnvironment.ps1 | 3 +- src/classes/public/Owner/GitHubOwner.ps1 | 53 ++------- .../Owner/GitHubOwner/GitHubEnterprise.ps1 | 39 +++---- .../Owner/GitHubOwner/GitHubOrganization.ps1 | 92 ++++++++++++---- .../public/Owner/GitHubOwner/GitHubUser.ps1 | 52 +++++++-- src/formats/GitHubOwner.Format.ps1xml | 33 +++--- .../Get-GitHubAppInstallableOrganization.ps1 | 2 +- ...tHubAppInstallationForAuthenticatedApp.ps1 | 4 +- .../GitHub Apps/Get-GitHubAppJSONWebToken.ps1 | 1 - ...bEnterpriseOrganizationAppInstallation.ps1 | 2 +- .../New-GitHubAppInstallationAccessToken.ps1 | 13 +-- .../Artifacts/Get-GitHubArtifactById.ps1 | 2 +- .../Get-GitHubArtifactFromRepository.ps1 | 2 +- .../Get-GitHubArtifactFromWorkflowRun.ps1 | 2 +- .../Auth/Context/Remove-GitHubContext.ps1 | 1 - .../Enterprise/Get-GitHubEnterpriseByName.ps1 | 74 +++++++++++++ .../Enterprise/Get-GitHubEnterpriseList.ps1 | 100 +++++++++++++++++ .../Get-GitHubEnvironmentByName.ps1 | 5 +- .../Get-GitHubEnvironmentList.ps1 | 6 +- .../Get-GitHubAllOrganization.ps1 | 4 +- .../Organization/Get-GitHubMyOrganization.ps1 | 63 ----------- .../Get-GitHubOrganizationByName.ps1 | 2 +- .../Get-GitHubOrganizationListForAuthUser.ps1 | 104 ++++++++++++++++++ .../Get-GitHubUserOrganization.ps1 | 4 +- .../Get-GitHubRepositoryRuleSuiteById.ps1 | 5 - .../Get-GitHubRepositoryRuleSuiteList.ps1 | 4 - .../private/Users/Get-GitHubAllUser.ps1 | 12 +- .../private/Users/Get-GitHubMyUser.ps1 | 2 +- .../private/Users/Get-GitHubUserByName.ps1 | 2 +- .../public/Auth/Connect-GitHubApp.ps1 | 2 +- .../Enterprise/Get-GitHubEnterprise.ps1 | 80 ++++++-------- .../Environments/Set-GitHubEnvironment.ps1 | 4 +- .../Organization/Get-GitHubOrganization.ps1 | 2 +- .../Members/Get-GitHubOrganizationMember.ps1 | 4 +- .../Update-GitHubOrganization.ps1 | 12 +- .../Get-GitHubRepositorySecurityFix.ps1 | 1 - .../Get-GitHubRepositoryRuleSuite.ps1 | 1 - .../public/Users/Update-GitHubUser.ps1 | 16 +-- src/types/GitHubUser.Types.ps1xml | 8 ++ .../{Enterprise.ps1 => Enterprise.Tests.ps1} | 24 +--- tests/Organizations.Tests.ps1 | 2 +- tests/Users.Tests.ps1 | 4 + 45 files changed, 534 insertions(+), 326 deletions(-) create mode 100644 src/functions/private/Enterprise/Get-GitHubEnterpriseByName.ps1 create mode 100644 src/functions/private/Enterprise/Get-GitHubEnterpriseList.ps1 delete mode 100644 src/functions/private/Organization/Get-GitHubMyOrganization.ps1 create mode 100644 src/functions/private/Organization/Get-GitHubOrganizationListForAuthUser.ps1 rename src/functions/{public => private}/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteById.ps1 (94%) rename src/functions/{public => private}/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteList.ps1 (96%) rename tests/{Enterprise.ps1 => Enterprise.Tests.ps1} (66%) diff --git a/.github/PSModule.yml b/.github/PSModule.yml index c1eb7bd1a..6d578178e 100644 --- a/.github/PSModule.yml +++ b/.github/PSModule.yml @@ -1,3 +1,3 @@ Test: CodeCoverage: - PercentTarget: 0 + PercentTarget: 50 diff --git a/src/classes/public/App/GitHubAppInstallation.ps1 b/src/classes/public/App/GitHubAppInstallation.ps1 index 5335e4830..96fd2831c 100644 --- a/src/classes/public/App/GitHubAppInstallation.ps1 +++ b/src/classes/public/App/GitHubAppInstallation.ps1 @@ -65,7 +65,7 @@ $this.Url = $Object.html_url } - GitHubAppInstallation([PSCustomObject] $Object, [string] $Target, [string] $Type, [string] $HostName) { + GitHubAppInstallation([PSCustomObject] $Object, [string] $Target, [string] $Type, [GitHubContext] $Context) { $this.ID = $Object.id $this.App = [GitHubApp]::new( [PSCustomObject]@{ @@ -77,7 +77,7 @@ $this.Target = [GitHubOwner]@{ Name = $Target Type = $Type - Url = "https://$HostName/$Target" + Url = "https://$($Context.HostName)/$Target" } $this.Type = $Type $this.RepositorySelection = $Object.repository_selection @@ -88,6 +88,6 @@ $this.UpdatedAt = $Object.updated_at $this.SuspendedAt = $Object.suspended_at $this.SuspendedBy = [GitHubUser]::new($Object.suspended_by) - $this.Url = "https://$HostName/$($Type.ToLower())s/$Target/settings/installations/$($Object.id)" + $this.Url = "https://$($Context.HostName)/$($Type.ToLower())s/$Target/settings/installations/$($Object.id)" } } diff --git a/src/classes/public/Artifacts/GitHubArtifact.ps1 b/src/classes/public/Artifacts/GitHubArtifact.ps1 index 3e654860e..988c09931 100644 --- a/src/classes/public/Artifacts/GitHubArtifact.ps1 +++ b/src/classes/public/Artifacts/GitHubArtifact.ps1 @@ -37,14 +37,14 @@ GitHubArtifact() {} - GitHubArtifact([PSCustomObject]$Object, [string]$Owner, [string]$Repository, [string]$HostName) { + GitHubArtifact([PSCustomObject]$Object, [string]$Owner, [string]$Repository, [GitHubContext]$Context) { $this.ID = $Object.id $this.NodeID = $Object.node_id $this.Name = $Object.name $this.Owner = $Owner $this.Repository = $Repository $this.Size = $Object.size_in_bytes - $this.Url = "https://$($HostName)/$Owner/$Repository/actions/runs/$($Object.workflow_run.id)/artifacts/$($Object.id)" + $this.Url = "https://$($Context.HostName)/$Owner/$Repository/actions/runs/$($Object.workflow_run.id)/artifacts/$($Object.id)" $this.ArchiveDownloadUrl = $Object.archive_download_url $this.Expired = $Object.expired $this.Digest = $Object.digest diff --git a/src/classes/public/Environment/GitHubEnvironment.ps1 b/src/classes/public/Environment/GitHubEnvironment.ps1 index 4da7639c7..799addd97 100644 --- a/src/classes/public/Environment/GitHubEnvironment.ps1 +++ b/src/classes/public/Environment/GitHubEnvironment.ps1 @@ -28,12 +28,13 @@ GitHubEnvironment() {} - GitHubEnvironment([PSCustomObject]$Object, [string]$Owner, [string]$Repository) { + GitHubEnvironment([PSCustomObject]$Object, [string]$Owner, [string]$Repository, [GitHubContext]$Context) { $this.ID = $Object.id $this.NodeID = $Object.node_id $this.Name = $Object.name $this.Owner = $Owner $this.Repository = $Repository + $this.Url = "https://$($Context.HostName)/$Owner/$Repository/settings/environments/$($Object.id)/edit" $this.CreatedAt = $Object.created_at $this.UpdatedAt = $Object.updated_at $this.AdminsCanBypass = $Object.can_admins_bypass diff --git a/src/classes/public/Owner/GitHubOwner.ps1 b/src/classes/public/Owner/GitHubOwner.ps1 index cc932ce1a..81efa24b0 100644 --- a/src/classes/public/Owner/GitHubOwner.ps1 +++ b/src/classes/public/Owner/GitHubOwner.ps1 @@ -19,41 +19,17 @@ # Example: User [string] $Type - # The company the account is affiliated with. - # Example: GitHub - [string] $Company - - # The blog URL of the account. - # Example: https://github.com/blog - [string] $Blog - # The location of the account. # Example: San Francisco [string] $Location - # The email of the account. - # Example: octocat@github.com - [string] $Email - - # The Twitter username. - # Example: monalisa - [string] $TwitterUsername - - # The number of public repositories. - # Example: 2 - [System.Nullable[uint]] $PublicRepos + # The description of the organization. + # Example: A great organization + [string] $Description - # The number of public gists. - # Example: 1 - [System.Nullable[uint]] $PublicGists - - # The number of followers. - # Example: 20 - [System.Nullable[uint]] $Followers - - # The number of accounts this account is following. - # Example: 0 - [System.Nullable[uint]] $Following + # The website URL of the account. + # Example: https://github.com/blog + [string] $Website # The creation date of the account. # Example: 2008-01-14T04:33:35Z @@ -63,10 +39,6 @@ # Example: 2008-01-14T04:33:35Z [System.Nullable[datetime]] $UpdatedAt - # The user's plan. - # Includes: Name, Collaborators, PrivateRepos, Space - [GitHubPlan] $Plan - GitHubOwner() {} GitHubOwner([PSCustomObject]$Object) { @@ -78,20 +50,13 @@ $this.Name = $Object.slug ?? $Object.login $this.DisplayName = $Object.name $this.AvatarUrl = $Object.avatar_url - $this.Url = $Object.html_url + $this.Url = $Object.html_url ?? $Object.url $this.Type = $Object.type - $this.Company = $Object.company - $this.Blog = $Object.website_url ?? $Object.blog $this.Location = $Object.location - $this.Email = $Object.email - $this.TwitterUsername = $Object.twitter_username - $this.PublicRepos = $Object.public_repos - $this.PublicGists = $Object.public_gists - $this.Followers = $Object.followers - $this.Following = $Object.following + $this.Description = $Object.description ?? $Object.bio + $this.Website = $Object.websiteUrl ?? $Object.blog $this.CreatedAt = $Object.created_at $this.UpdatedAt = $Object.updated_at - $this.Plan = [GitHubPlan]::New($Object.plan) } [string] ToString() { diff --git a/src/classes/public/Owner/GitHubOwner/GitHubEnterprise.ps1 b/src/classes/public/Owner/GitHubOwner/GitHubEnterprise.ps1 index 790c19625..66fea40c4 100644 --- a/src/classes/public/Owner/GitHubOwner/GitHubEnterprise.ps1 +++ b/src/classes/public/Owner/GitHubOwner/GitHubEnterprise.ps1 @@ -1,19 +1,4 @@ class GitHubEnterprise : GitHubOwner { - # The description of the enterprise. - # Example: A great enterprise - [string] $Description - - # The description of the enterprise, as HTML. - # Example:
A great enterprise
- [string] $DescriptionHTML - - # The billing information for the organization. - [GitHubBillingInfo] $BillingInfo - - # The billing email address for the organization. - # Example: org@example.com - [string] $BillingEmail - # The readme of the enterprise. # Example: This is the readme for the enterprise [string] $Readme @@ -22,6 +7,22 @@ # Example:

This is the readme for the enterprise

[string] $ReadmeHTML + static [hashtable] $PropertyToGraphQLMap = @{ + ID = 'databaseId' + NodeID = 'id' + Name = 'slug' + DisplayName = 'name' + AvatarUrl = 'avatarUrl' + Url = 'url' + Website = 'websiteUrl' + Location = 'location' + CreatedAt = 'createdAt' + UpdatedAt = 'updatedAt' + Description = 'description' + Readme = 'readme' + ReadmeHTML = 'readmeHTML' + } + GitHubEnterprise() {} GitHubEnterprise([PSCustomObject] $Object) { @@ -35,17 +36,13 @@ $this.AvatarUrl = $Object.avatarUrl $this.Url = $Object.url $this.Type = $Object.type ?? 'Enterprise' - $this.Company = $Object.company - $this.Blog = $Object.websiteUrl $this.Location = $Object.location + $this.Description = $Object.description + $this.Website = $Object.websiteUrl $this.CreatedAt = $Object.createdAt $this.UpdatedAt = $Object.updatedAt # From GitHubEnterprise - $this.Description = $Object.description - $this.DescriptionHTML = $Object.descriptionHTML - $this.BillingEmail = $Object.billingEmail - $this.BillingInfo = [GitHubBillingInfo]::new($Object.billingInfo) $this.Readme = $Object.readme $this.ReadmeHTML = $Object.readmeHTML } diff --git a/src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 b/src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 index 5869a6367..48528dba2 100644 --- a/src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 +++ b/src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 @@ -1,7 +1,31 @@ class GitHubOrganization : GitHubOwner { - # The description of the organization. - # Example: A great organization - [string] $Description + # The email of the account. + # Example: octocat@github.com + [string] $Email + + # The Twitter username. + # Example: monalisa + [string] $TwitterUsername + + # The user's plan. + # Includes: Name, Collaborators, PrivateRepos, Space + [GitHubPlan] $Plan + + # The number of public repositories. + # Example: 2 + [System.Nullable[uint]] $PublicRepos + + # The number of public gists. + # Example: 1 + [System.Nullable[uint]] $PublicGists + + # The number of followers. + # Example: 20 + [System.Nullable[uint]] $Followers + + # The number of accounts this account is following. + # Example: 0 + [System.Nullable[uint]] $Following # The number of private gists. # Example: 81 @@ -49,7 +73,7 @@ # Whether two-factor authentication is required for members. # Example: $true - [System.Nullable[bool]] $TwoFactorRequirementEnabled + [System.Nullable[bool]] $RequiresTwoFactorAuthentication # The type of repositories members can create. # Example: all @@ -134,54 +158,74 @@ # The date and time when the organization was archived, if applicable. [System.Nullable[datetime]] $ArchivedAt + static [hashtable] $PropertyToGraphQLMap = @{ + ArchivedAt = 'archivedAt' + AvatarUrl = 'avatarUrl' + CreatedAt = 'createdAt' + Description = 'description' + DisplayName = 'name' + Email = 'email' + ID = 'databaseId' + Location = 'location' + Name = 'login' + NodeID = 'id' + IsVerified = 'isVerified' + # MembersCanForkPrivateRepositories = 'membersCanForkPrivateRepositories' + # RequiresTwoFactorAuthentication = 'requiresTwoFactorAuthentication' + TwitterUsername = 'twitterUsername' + UpdatedAt = 'updatedAt' + Url = 'url' + # RequireWebCommitSignoff = 'webCommitSignoffRequired' + Website = 'websiteUrl' + } + GitHubOrganization() {} - GitHubOrganization([PSCustomObject] $Object, [string] $HostName) { + GitHubOrganization([PSCustomObject] $Object, [GitHubContext] $Context) { # From GitHubNode - $this.ID = $Object.id - $this.NodeID = $Object.node_id + $this.ID = $Object.databaseId ?? $Object.id + $this.NodeID = $Object.node_id ?? $Object.id # From GitHubOwner $this.Name = $Object.login $this.DisplayName = $Object.name - $this.AvatarUrl = $Object.avatar_url - $this.Url = $Object.html_url ?? "https://$($HostName)/$($Object.login)" - $this.Type = $Object.type - $this.Company = $Object.company - $this.Blog = $Object.blog + $this.AvatarUrl = $Object.avatar_url ?? $Object.avatarUrl + $this.Url = $Object.html_url ?? $Object.url ?? "https://$($Context.HostName)/$($Object.login)" + $this.Type = $Object.type ?? 'Organization' $this.Location = $Object.location + $this.Description = $Object.description + $this.Website = $Object.website ?? $Object.blog + $this.CreatedAt = $Object.created_at ?? $Object.createdAt + $this.UpdatedAt = $Object.updated_at ?? $Object.updatedAt + + # From GitHubOrganization $this.Email = $Object.email - $this.TwitterUsername = $Object.twitter_username + $this.TwitterUsername = $Object.twitter_username ?? $Object.twitterUsername + $this.Plan = [GitHubPlan]::New($Object.plan) $this.PublicRepos = $Object.public_repos $this.PublicGists = $Object.public_gists $this.Followers = $Object.followers $this.Following = $Object.following - $this.CreatedAt = $Object.created_at - $this.UpdatedAt = $Object.updated_at - $this.Plan = [GitHubPlan]::New($Object.plan) - - # From GitHubOrganization - $this.Description = $Object.description $this.PrivateGists = $Object.total_private_gists $this.TotalPrivateRepos = $Object.total_private_repos $this.OwnedPrivateRepos = $Object.owned_private_repos $this.DiskUsage = $Object.disk_usage $this.Collaborators = $Object.collaborators - $this.IsVerified = $Object.is_verified + $this.IsVerified = $Object.is_verified ?? $Object.isVerified $this.HasOrganizationProjects = $Object.has_organization_projects $this.HasRepositoryProjects = $Object.has_repository_projects $this.BillingEmail = $Object.billing_email $this.DefaultRepositoryPermission = $Object.default_repository_permission $this.MembersCanCreateRepositories = $Object.members_can_create_repositories - $this.TwoFactorRequirementEnabled = $Object.two_factor_requirement_enabled + $this.RequiresTwoFactorAuthentication = $Object.two_factor_requirement_enabled ?? $Object.requiresTwoFactorAuthentication $this.MembersAllowedRepositoryCreationType = $Object.members_allowed_repository_creation_type $this.MembersCanCreatePublicRepositories = $Object.members_can_create_public_repositories $this.MembersCanCreatePrivateRepositories = $Object.members_can_create_private_repositories $this.MembersCanCreateInternalRepositories = $Object.members_can_create_internal_repositories $this.MembersCanInviteCollaborators = $Object.members_can_invite_collaborators $this.MembersCanCreatePages = $Object.members_can_create_pages - $this.MembersCanForkPrivateRepositories = $Object.members_can_fork_private_repositories - $this.RequireWebCommitSignoff = $Object.web_commit_signoff_required + $this.MembersCanForkPrivateRepositories = $Object.members_can_fork_private_repositories ?? $Object.membersCanForkPrivateRepositories + $this.RequireWebCommitSignoff = $Object.web_commit_signoff_required ?? $Object.requiresTwoFactorAuthentication $this.DeployKeysEnabledForRepositories = $Object.deploy_keys_enabled_for_repositories $this.MembersCanCreatePublicPages = $Object.members_can_create_public_pages $this.MembersCanCreatePrivatePages = $Object.members_can_create_private_pages @@ -194,7 +238,7 @@ $this.SecretScanningPushProtectionCustomLinkEnabled = $Object.secret_scanning_push_protection_custom_link_enabled $this.SecretScanningPushProtectionCustomLink = $Object.secret_scanning_push_protection_custom_link $this.SecretScanningValidityChecksEnabled = $Object.secret_scanning_validity_checks_enabled - $this.ArchivedAt = $Object.archived_at + $this.ArchivedAt = $Object.archived_at ?? $Object.archivedAt } [string] ToString() { diff --git a/src/classes/public/Owner/GitHubOwner/GitHubUser.ps1 b/src/classes/public/Owner/GitHubOwner/GitHubUser.ps1 index b6b1d4664..a9e4e4abe 100644 --- a/src/classes/public/Owner/GitHubOwner/GitHubUser.ps1 +++ b/src/classes/public/Owner/GitHubOwner/GitHubUser.ps1 @@ -1,15 +1,43 @@ class GitHubUser : GitHubOwner { + # The email of the account. + # Example: octocat@github.com + [string] $Email + # Whether the user is hireable. [System.Nullable[bool]] $Hireable - # The user's biography. - # Example: There once was... - [string] $Bio + # The company the account is affiliated with. + # Example: GitHub + [string] $Company + + # The Twitter username. + # Example: monalisa + [string] $TwitterUsername + + # The number of public repositories. + # Example: 2 + [System.Nullable[uint]] $PublicRepos + + # The number of public gists. + # Example: 1 + [System.Nullable[uint]] $PublicGists + + # The number of followers. + # Example: 20 + [System.Nullable[uint]] $Followers + + # The number of accounts this account is following. + # Example: 0 + [System.Nullable[uint]] $Following # The notification email address of the user. # Example: octocat@github.com [string] $NotificationEmail + # The user's plan. + # Includes: Name, Collaborators, PrivateRepos, Space + [GitHubPlan] $Plan + GitHubUser() {} GitHubUser([PSCustomObject]$Object) { @@ -23,23 +51,23 @@ $this.AvatarUrl = $Object.avatar_url $this.Url = $Object.html_url $this.Type = $Object.type - $this.Company = $Object.company - $this.Blog = $Object.blog $this.Location = $Object.location + $this.Description = $Object.bio + $this.Website = $Object.blog + $this.CreatedAt = $Object.created_at + $this.UpdatedAt = $Object.updated_at + + # From GitHubUser $this.Email = $Object.email + $this.Hireable = $Object.hireable + $this.Company = $Object.company $this.TwitterUsername = $Object.twitter_username $this.PublicRepos = $Object.public_repos $this.PublicGists = $Object.public_gists $this.Followers = $Object.followers $this.Following = $Object.following - $this.CreatedAt = $Object.created_at - $this.UpdatedAt = $Object.updated_at - $this.Plan = [GitHubPlan]::New($Object.plan) - - # From GitHubUser - $this.Hireable = $Object.hireable - $this.Bio = $Object.bio $this.NotificationEmail = $Object.notification_email + $this.Plan = [GitHubPlan]::New($Object.plan) } [string] ToString() { diff --git a/src/formats/GitHubOwner.Format.ps1xml b/src/formats/GitHubOwner.Format.ps1xml index 34d050cd5..c1d8dcb3f 100644 --- a/src/formats/GitHubOwner.Format.ps1xml +++ b/src/formats/GitHubOwner.Format.ps1xml @@ -7,9 +7,13 @@ GitHubOwner GitHubUser GitHubOrganization + GitHubEnterprise + + + @@ -20,15 +24,15 @@ - - - - + + + DisplayName + if ($Host.UI.SupportsVirtualTerminal -and @@ -46,10 +50,7 @@ Type - Company - - - Plan + CreatedAt @@ -65,6 +66,9 @@ + + DisplayName + Name @@ -74,9 +78,6 @@ NodeID - - DisplayName - AvatarUrl @@ -86,9 +87,6 @@ Type - - Company - Location @@ -96,10 +94,10 @@ Email - TwitterUsername + Description - Blog + Website CreatedAt @@ -107,9 +105,6 @@ UpdatedAt - - Plan - diff --git a/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallableOrganization.ps1 b/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallableOrganization.ps1 index 4d5017e44..5c03bfcfb 100644 --- a/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallableOrganization.ps1 +++ b/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallableOrganization.ps1 @@ -52,7 +52,7 @@ Invoke-GitHubAPI @inputObject | ForEach-Object { foreach ($organization in $_.Response) { - [GitHubOrganization]::new($organization, $Context.HostName) + [GitHubOrganization]::new($organization, $Context) } } } diff --git a/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallationForAuthenticatedApp.ps1 b/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallationForAuthenticatedApp.ps1 index f4dfcb18e..a4a218574 100644 --- a/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallationForAuthenticatedApp.ps1 +++ b/src/functions/private/Apps/GitHub Apps/Get-GitHubAppInstallationForAuthenticatedApp.ps1 @@ -47,8 +47,8 @@ } Invoke-GitHubAPI @inputObject | ForEach-Object { - $_.Response | ForEach-Object { - [GitHubAppInstallation]::new($_) + foreach ($installation in $_.Response) { + [GitHubAppInstallation]::new($installation) } } } diff --git a/src/functions/private/Apps/GitHub Apps/Get-GitHubAppJSONWebToken.ps1 b/src/functions/private/Apps/GitHub Apps/Get-GitHubAppJSONWebToken.ps1 index 133816e4f..9ac33c835 100644 --- a/src/functions/private/Apps/GitHub Apps/Get-GitHubAppJSONWebToken.ps1 +++ b/src/functions/private/Apps/GitHub Apps/Get-GitHubAppJSONWebToken.ps1 @@ -37,7 +37,6 @@ )] [CmdletBinding(DefaultParameterSetName = 'PrivateKey')] - [Alias('Get-GitHubAppJWT')] [OutputType([GitHubJsonWebToken])] param( # The client ID of the GitHub App. diff --git a/src/functions/private/Apps/GitHub Apps/Get-GitHubEnterpriseOrganizationAppInstallation.ps1 b/src/functions/private/Apps/GitHub Apps/Get-GitHubEnterpriseOrganizationAppInstallation.ps1 index 4609f1fe1..ea19a3c4d 100644 --- a/src/functions/private/Apps/GitHub Apps/Get-GitHubEnterpriseOrganizationAppInstallation.ps1 +++ b/src/functions/private/Apps/GitHub Apps/Get-GitHubEnterpriseOrganizationAppInstallation.ps1 @@ -62,7 +62,7 @@ Invoke-GitHubAPI @inputObject | ForEach-Object { foreach ($installation in $_.Response) { - [GitHubAppInstallation]::new($installation, $Organization, 'Organization', $context.HostName) + [GitHubAppInstallation]::new($installation, $Organization, 'Organization', $Context) } } } diff --git a/src/functions/private/Apps/GitHub Apps/New-GitHubAppInstallationAccessToken.ps1 b/src/functions/private/Apps/GitHub Apps/New-GitHubAppInstallationAccessToken.ps1 index 2291149ad..34369ff47 100644 --- a/src/functions/private/Apps/GitHub Apps/New-GitHubAppInstallationAccessToken.ps1 +++ b/src/functions/private/Apps/GitHub Apps/New-GitHubAppInstallationAccessToken.ps1 @@ -48,18 +48,15 @@ 'PSUseShouldProcessForStateChangingFunctions', '', Justification = 'No state is changed.' )] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', - Justification = 'The tokens are received as clear text. Mitigating exposure by removing variables and performing garbage collection.')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSAvoidUsingConvertToSecureStringWithPlainText', '', + Justification = 'The tokens are received as clear text. Mitigating exposure by removing variables and performing garbage collection.' + )] [CmdletBinding()] param( # The unique identifier of the installation. # Example: '12345678' - [Parameter( - Mandatory, - ValueFromPipeline, - ValueFromPipelineByPropertyName - )] - [Alias('installation_id', 'InstallationID')] + [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [int] $ID, # The context to run the command in. Used to get the details for the API call. diff --git a/src/functions/private/Artifacts/Get-GitHubArtifactById.ps1 b/src/functions/private/Artifacts/Get-GitHubArtifactById.ps1 index 1d634fbbb..782667043 100644 --- a/src/functions/private/Artifacts/Get-GitHubArtifactById.ps1 +++ b/src/functions/private/Artifacts/Get-GitHubArtifactById.ps1 @@ -68,7 +68,7 @@ function Get-GitHubArtifactById { } Invoke-GitHubAPI @inputObject | ForEach-Object { - [GitHubArtifact]::new($_.Response, $Owner, $Repository, $Context.HostName) + [GitHubArtifact]::new($_.Response, $Owner, $Repository, $Context) } } diff --git a/src/functions/private/Artifacts/Get-GitHubArtifactFromRepository.ps1 b/src/functions/private/Artifacts/Get-GitHubArtifactFromRepository.ps1 index d7f86c044..08087d229 100644 --- a/src/functions/private/Artifacts/Get-GitHubArtifactFromRepository.ps1 +++ b/src/functions/private/Artifacts/Get-GitHubArtifactFromRepository.ps1 @@ -88,7 +88,7 @@ function Get-GitHubArtifactFromRepository { } $artifacts | ForEach-Object { - [GitHubArtifact]::new($_, $Owner, $Repository, $Context.HostName) + [GitHubArtifact]::new($_, $Owner, $Repository, $Context) } } diff --git a/src/functions/private/Artifacts/Get-GitHubArtifactFromWorkflowRun.ps1 b/src/functions/private/Artifacts/Get-GitHubArtifactFromWorkflowRun.ps1 index a7b9b863b..7a54c1709 100644 --- a/src/functions/private/Artifacts/Get-GitHubArtifactFromWorkflowRun.ps1 +++ b/src/functions/private/Artifacts/Get-GitHubArtifactFromWorkflowRun.ps1 @@ -99,7 +99,7 @@ function Get-GitHubArtifactFromWorkflowRun { } $artifacts | ForEach-Object { - [GitHubArtifact]::new($_, $Owner, $Repository, $Context.HostName) + [GitHubArtifact]::new($_, $Owner, $Repository, $Context) } } diff --git a/src/functions/private/Auth/Context/Remove-GitHubContext.ps1 b/src/functions/private/Auth/Context/Remove-GitHubContext.ps1 index 4c93f5ddc..9b6f810d8 100644 --- a/src/functions/private/Auth/Context/Remove-GitHubContext.ps1 +++ b/src/functions/private/Auth/Context/Remove-GitHubContext.ps1 @@ -23,7 +23,6 @@ param( # The name of the context. [Parameter(Mandatory)] - [Alias('Name')] [string] $Context ) diff --git a/src/functions/private/Enterprise/Get-GitHubEnterpriseByName.ps1 b/src/functions/private/Enterprise/Get-GitHubEnterpriseByName.ps1 new file mode 100644 index 000000000..81d33aa5d --- /dev/null +++ b/src/functions/private/Enterprise/Get-GitHubEnterpriseByName.ps1 @@ -0,0 +1,74 @@ +function Get-GitHubEnterpriseByName { + <# + .SYNOPSIS + Retrieves details about a GitHub Enterprise instance by name (slug). + + .DESCRIPTION + This function retrieves detailed information about a GitHub Enterprise instance, including its avatar, billing details, storage usage, + creation date, and other metadata based on the provided name (slug). It returns an object of type GitHubEnterprise populated with this + information. + + .EXAMPLE + Get-GitHubEnterpriseByName -Name 'my-enterprise' + + Output: + ```powershell + Name : My Enterprise + Slug : my-enterprise + URL : https://github.com/enterprises/my-enterprise + CreatedAt : 2022-01-01T00:00:00Z + ViewerIsAdmin : True + ``` + + Retrieves details about the GitHub Enterprise instance named 'my-enterprise'. + + .OUTPUTS + GitHubEnterprise + + .NOTES + An object containing detailed information about the GitHub Enterprise instance, including billing info, URLs, and metadata. + #> + [OutputType([GitHubEnterprise])] + [CmdletBinding()] + param( + # The name (slug) of the GitHub Enterprise instance to retrieve. + [Parameter(Mandatory)] + [Alias('Slug')] + [string] $Name, + + # 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(Mandatory)] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $graphQLFields = ([GitHubEnterprise]::PropertyToGraphQLMap).Values + + $enterpriseQuery = @{ + query = @" +query(`$Slug: String!) { + enterprise(slug: `$Slug) { + $graphQLFields + } +} +"@ + Variables = @{ + Slug = $Name + } + Context = $Context + } + $enterpriseResult = Invoke-GitHubGraphQLQuery @enterpriseQuery + [GitHubEnterprise]::new($enterpriseResult.enterprise) + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/private/Enterprise/Get-GitHubEnterpriseList.ps1 b/src/functions/private/Enterprise/Get-GitHubEnterpriseList.ps1 new file mode 100644 index 000000000..cd2f890e4 --- /dev/null +++ b/src/functions/private/Enterprise/Get-GitHubEnterpriseList.ps1 @@ -0,0 +1,100 @@ +function Get-GitHubEnterpriseList { + <# + .SYNOPSIS + Retrieves a list of all GitHub Enterprise instances. + + .DESCRIPTION + This function retrieves detailed information about all GitHub Enterprise instances, including their avatars, billing details, storage usage, + creation dates, and other metadata. It returns an array of objects of type GitHubEnterprise populated with this information. + + .EXAMPLE + Get-GitHubEnterpriseList + + Output: + ```powershell + Name : My Enterprise + Slug : my-enterprise + URL : https://github.com/enterprises/my-enterprise + CreatedAt : 2022-01-01T00:00:00Z + + Name : Another Enterprise + Slug : another-enterprise + URL : https://github.com/enterprises/another-enterprise + CreatedAt : 2021-12-01T00:00:00Z + ``` + + Retrieves details about the GitHub Enterprise instance. + + .OUTPUTS + GitHubEnterprise[] + + .NOTES + An array of objects containing detailed information about the GitHub Enterprise instances, including billing info, URLs, and metadata. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseDeclaredVarsMoreThanAssignments', 'hasNextPage', Scope = 'Function', + Justification = 'Unknown issue with var scoping in blocks.' + )] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseDeclaredVarsMoreThanAssignments', 'after', Scope = 'Function', + Justification = 'Unknown issue with var scoping in blocks.' + )] + [OutputType([GitHubEnterprise[]])] + [CmdletBinding()] + 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(Mandatory)] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $hasNextPage = $false + $after = $null + $perPageSetting = Resolve-GitHubContextSetting -Name 'PerPage' -Value $PerPage -Context $Context + + $graphQLFields = ([GitHubEnterprise]::PropertyToGraphQLMap).Values + + do { + $enterpriseQuery = @{ + query = @" +query(`$perPage: Int!, `$after: String) { + viewer { + enterprises(first: `$perPage, after: `$after) { + nodes { + $graphQLFields + } + pageInfo { + endCursor + hasNextPage + } + } + } +} +"@ + Variables = @{ + perPage = $perPageSetting + after = $after + } + Context = $Context + } + Invoke-GitHubGraphQLQuery @enterpriseQuery | ForEach-Object { + foreach ($enterprise in $_.viewer.enterprises.nodes) { + [GitHubEnterprise]::new($enterprise) + } + $hasNextPage = $_.viewer.enterprises.pageInfo.hasNextPage + $after = $_.viewer.enterprises.pageInfo.endCursor + } + } while ($hasNextPage) + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/private/Environments/Get-GitHubEnvironmentByName.ps1 b/src/functions/private/Environments/Get-GitHubEnvironmentByName.ps1 index d4286cb88..0b9df7f01 100644 --- a/src/functions/private/Environments/Get-GitHubEnvironmentByName.ps1 +++ b/src/functions/private/Environments/Get-GitHubEnvironmentByName.ps1 @@ -50,7 +50,6 @@ filter Get-GitHubEnvironmentByName { Mandatory, ValueFromPipelineByPropertyName )] - [Alias('Organization', 'User')] [string] $Owner, # The name of the repository without the .git extension. The name is not case sensitive. @@ -88,9 +87,7 @@ filter Get-GitHubEnvironmentByName { } try { Invoke-GitHubAPI @inputObject | ForEach-Object { - $environment = [GitHubEnvironment]::new($_.Response, $Owner, $Repository) - $environment.Url = "https://$($Context.HostName)/$Owner/$Repository/settings/environments/$($environment.ID)/edit" - $environment + [GitHubEnvironment]::new($_.Response, $Owner, $Repository, $Context) } } catch { return diff --git a/src/functions/private/Environments/Get-GitHubEnvironmentList.ps1 b/src/functions/private/Environments/Get-GitHubEnvironmentList.ps1 index 85d191c16..c4cd691bb 100644 --- a/src/functions/private/Environments/Get-GitHubEnvironmentList.ps1 +++ b/src/functions/private/Environments/Get-GitHubEnvironmentList.ps1 @@ -82,10 +82,8 @@ filter Get-GitHubEnvironmentList { } Invoke-GitHubAPI @inputObject | ForEach-Object { - $_.Response.environments | ForEach-Object { - $environment = [GitHubEnvironment]::new($_, $Owner, $Repository) - $environment.Url = "https://$($Context.HostName)/$Owner/$Repository/settings/environments/$($environment.ID)/edit" - $environment + foreach ($environment in $_.Response.environments) { + [GitHubEnvironment]::new($environment, $Owner, $Repository, $Context) } } } diff --git a/src/functions/private/Organization/Get-GitHubAllOrganization.ps1 b/src/functions/private/Organization/Get-GitHubAllOrganization.ps1 index 98ffe0674..60f8aee2f 100644 --- a/src/functions/private/Organization/Get-GitHubAllOrganization.ps1 +++ b/src/functions/private/Organization/Get-GitHubAllOrganization.ps1 @@ -58,7 +58,9 @@ } Invoke-GitHubAPI @inputObject | ForEach-Object { - $_.Response | ForEach-Object { [GitHubOrganization]::new($_, $Context.HostName) } + foreach ($organization in $_.Response) { + [GitHubOrganization]::new($organization, $Context) + } } } end { diff --git a/src/functions/private/Organization/Get-GitHubMyOrganization.ps1 b/src/functions/private/Organization/Get-GitHubMyOrganization.ps1 deleted file mode 100644 index d11b5aebe..000000000 --- a/src/functions/private/Organization/Get-GitHubMyOrganization.ps1 +++ /dev/null @@ -1,63 +0,0 @@ -filter Get-GitHubMyOrganization { - <# - .SYNOPSIS - List organizations for the authenticated user - - .DESCRIPTION - List organizations for the authenticated user. - - **OAuth scope requirements** - - This only lists organizations that your authorization allows you to operate on - in some way (e.g., you can list teams with `read:org` scope, you can publicize your - organization membership with `user` scope, etc.). Therefore, this API requires at - least `user` or `read:org` scope. OAuth requests with insufficient scope receive a - `403 Forbidden` response. - - .EXAMPLE - Get-GitHubMyOrganization - - List organizations for the authenticated user. - - .OUTPUTS - GitHubOrganization - - .NOTES - [List organizations for the authenticated user](https://docs.github.com/rest/orgs/orgs#list-organizations-for-the-authenticated-user) - #> - [OutputType([GitHubOrganization])] - [CmdletBinding()] - param( - # The number of results per page (max 100). - [Parameter()] - [System.Nullable[int]] $PerPage, - - # 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(Mandatory)] - [object] $Context - ) - - begin { - $stackPath = Get-PSCallStackPath - Write-Debug "[$stackPath] - Start" - Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT - } - - process { - $inputObject = @{ - Method = 'GET' - APIEndpoint = '/user/orgs' - PerPage = $PerPage - Context = $Context - } - - Invoke-GitHubAPI @inputObject | ForEach-Object { - $_.Response | ForEach-Object { [GitHubOrganization]::new($_, $Context.HostName) } - } - } - - end { - Write-Debug "[$stackPath] - End" - } -} diff --git a/src/functions/private/Organization/Get-GitHubOrganizationByName.ps1 b/src/functions/private/Organization/Get-GitHubOrganizationByName.ps1 index 03595108f..aee398ab2 100644 --- a/src/functions/private/Organization/Get-GitHubOrganizationByName.ps1 +++ b/src/functions/private/Organization/Get-GitHubOrganizationByName.ps1 @@ -56,7 +56,7 @@ } Invoke-GitHubAPI @inputObject | ForEach-Object { - [GitHubOrganization]::new($_.Response, '') + [GitHubOrganization]::new($_.Response, $Context) } } end { diff --git a/src/functions/private/Organization/Get-GitHubOrganizationListForAuthUser.ps1 b/src/functions/private/Organization/Get-GitHubOrganizationListForAuthUser.ps1 new file mode 100644 index 000000000..a8024ee6b --- /dev/null +++ b/src/functions/private/Organization/Get-GitHubOrganizationListForAuthUser.ps1 @@ -0,0 +1,104 @@ +function Get-GitHubOrganizationListForAuthUser { + <# + .SYNOPSIS + Retrieves a list of all GitHub organizations for the authenticated user. + + .DESCRIPTION + This function retrieves detailed information about all GitHub organizations that the authenticated user belongs to, including their avatars, + creation dates, member counts, and other metadata. It returns an array of objects of type GitHubOrganization populated with this information. + + .EXAMPLE + Get-GitHubOrganizationListForAuthUser + + Output: + ```powershell + Name : MyOrganization + Login : my-org + URL : https://github.com/my-org + CreatedAt : 2022-01-01T00:00:00Z + + Name : Another Organization + Login : another-org + URL : https://github.com/another-org + CreatedAt : 2021-12-01T00:00:00Z + ``` + + Retrieves details about the GitHub organizations the authenticated user belongs to. + + .OUTPUTS + GitHubOrganization[] + + .NOTES + An array of objects containing detailed information about the GitHub organizations, including member info, URLs, and metadata. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseDeclaredVarsMoreThanAssignments', 'hasNextPage', Scope = 'Function', + Justification = 'Unknown issue with var scoping in blocks.' + )] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseDeclaredVarsMoreThanAssignments', 'after', Scope = 'Function', + Justification = 'Unknown issue with var scoping in blocks.' + )] + [OutputType([GitHubOrganization[]])] + [CmdletBinding()] + param( + # The number of results per page (max 100). + [Parameter()] + [System.Nullable[int]] $PerPage, + + # 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(Mandatory)] + [object] $Context + ) + + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } + + process { + $hasNextPage = $false + $after = $null + $perPageSetting = Resolve-GitHubContextSetting -Name 'PerPage' -Value $PerPage -Context $Context + + $graphQLFields = ([GitHubOrganization]::PropertyToGraphQLMap).Values + + do { + $organizationQuery = @{ + query = @" +query(`$perPage: Int!, `$after: String) { + viewer { + organizations(first: `$perPage, after: `$after) { + nodes { + $graphQLFields + } + pageInfo { + endCursor + hasNextPage + } + } + } +} +"@ + Variables = @{ + perPage = $perPageSetting + after = $after + } + Context = $Context + } + Invoke-GitHubGraphQLQuery @organizationQuery | ForEach-Object { + foreach ($organization in $_.viewer.organizations.nodes) { + [GitHubOrganization]::new($organization, $Context) + } + $hasNextPage = $_.viewer.organizations.pageInfo.hasNextPage + $after = $_.viewer.organizations.pageInfo.endCursor + } + } while ($hasNextPage) + } + + end { + Write-Debug "[$stackPath] - End" + } +} diff --git a/src/functions/private/Organization/Get-GitHubUserOrganization.ps1 b/src/functions/private/Organization/Get-GitHubUserOrganization.ps1 index 6a8df5659..6cd3d6e9b 100644 --- a/src/functions/private/Organization/Get-GitHubUserOrganization.ps1 +++ b/src/functions/private/Organization/Get-GitHubUserOrganization.ps1 @@ -55,8 +55,8 @@ } Invoke-GitHubAPI @inputObject | ForEach-Object { - foreach ($org in $_.Response) { - [GitHubOrganization]::new($org, $Context.HostName) + foreach ($organization in $_.Response) { + [GitHubOrganization]::new($organization, $Context) } } } diff --git a/src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteById.ps1 b/src/functions/private/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteById.ps1 similarity index 94% rename from src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteById.ps1 rename to src/functions/private/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteById.ps1 index 0bce42cff..e614f7f10 100644 --- a/src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteById.ps1 +++ b/src/functions/private/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteById.ps1 @@ -24,8 +24,6 @@ param( # The account owner of the repository. The name is not case sensitive. [Parameter(Mandatory)] - [Alias('Organization')] - [Alias('User')] [string] $Owner, # The name of the repository without the .git extension. The name is not case sensitive. @@ -34,7 +32,6 @@ # The unique identifier of the rule suite result. To get this ID, you can use GET /repos/ { owner }/ { repo }/rulesets/rule-suites for repositories and GET /orgs/ { org }/rulesets/rule-suites for organizations. [Parameter(Mandatory)] - [Alias('RuleSuiteId')] [int] $ID, # The context to run the command in. Used to get the details for the API call. @@ -66,5 +63,3 @@ Write-Debug "[$stackPath] - End" } } - -#SkipTest:FunctionTest:Will add a test for this function in a future PR diff --git a/src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteList.ps1 b/src/functions/private/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteList.ps1 similarity index 96% rename from src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteList.ps1 rename to src/functions/private/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteList.ps1 index d124a6b77..7843a405b 100644 --- a/src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteList.ps1 +++ b/src/functions/private/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuiteList.ps1 @@ -32,8 +32,6 @@ param( # The account owner of the repository. The name is not case sensitive. [Parameter(Mandatory)] - [Alias('Organization')] - [Alias('User')] [string] $Owner, # The name of the repository without the .git extension. The name is not case sensitive. @@ -104,5 +102,3 @@ Write-Debug "[$stackPath] - End" } } - -#SkipTest:FunctionTest:Will add a test for this function in a future PR diff --git a/src/functions/private/Users/Get-GitHubAllUser.ps1 b/src/functions/private/Users/Get-GitHubAllUser.ps1 index 43d57fc63..ea8233a2e 100644 --- a/src/functions/private/Users/Get-GitHubAllUser.ps1 +++ b/src/functions/private/Users/Get-GitHubAllUser.ps1 @@ -58,13 +58,13 @@ } Invoke-GitHubAPI @inputObject | ForEach-Object { - $_.Response | ForEach-Object { - if ($_.type -eq 'Organization') { - [GitHubOrganization]::New($_, '') - } elseif ($_.type -eq 'User') { - [GitHubUser]::New($_) + foreach ($account in $_.Response) { + if ($account.type -eq 'Organization') { + [GitHubOrganization]::New($account, $Context) + } elseif ($account.type -eq 'User') { + [GitHubUser]::New($account) } else { - [GitHubOwner]::New($_) + [GitHubOwner]::New($account) } } } diff --git a/src/functions/private/Users/Get-GitHubMyUser.ps1 b/src/functions/private/Users/Get-GitHubMyUser.ps1 index 7526a7837..6141d5043 100644 --- a/src/functions/private/Users/Get-GitHubMyUser.ps1 +++ b/src/functions/private/Users/Get-GitHubMyUser.ps1 @@ -44,7 +44,7 @@ Invoke-GitHubAPI @inputObject | ForEach-Object { if ($_.Response.type -eq 'Organization') { - [GitHubOrganization]::New($_.Response, $Context.HostName) + [GitHubOrganization]::New($_.Response, $Context) } elseif ($_.Response.type -eq 'User') { [GitHubUser]::New($_.Response) } else { diff --git a/src/functions/private/Users/Get-GitHubUserByName.ps1 b/src/functions/private/Users/Get-GitHubUserByName.ps1 index 701bca251..880b63e55 100644 --- a/src/functions/private/Users/Get-GitHubUserByName.ps1 +++ b/src/functions/private/Users/Get-GitHubUserByName.ps1 @@ -62,7 +62,7 @@ try { Invoke-GitHubAPI @inputObject | ForEach-Object { if ($_.Response.type -eq 'Organization') { - [GitHubOrganization]::New($_.Response, $Context.HostName) + [GitHubOrganization]::New($_.Response, $Context) } elseif ($_.Response.type -eq 'User') { [GitHubUser]::New($_.Response) } else { diff --git a/src/functions/public/Auth/Connect-GitHubApp.ps1 b/src/functions/public/Auth/Connect-GitHubApp.ps1 index c74caafba..1994c5082 100644 --- a/src/functions/public/Auth/Connect-GitHubApp.ps1 +++ b/src/functions/public/Auth/Connect-GitHubApp.ps1 @@ -122,7 +122,7 @@ $selectedInstallations | ForEach-Object { $installation = $_ Write-Verbose "Processing installation [$($installation.Target.Name)] [$($installation.id)]" - $token = New-GitHubAppInstallationAccessToken -Context $Context -InstallationID $installation.id + $token = New-GitHubAppInstallationAccessToken -Context $Context -ID $installation.id $contextParams = @{ AuthType = [string]'IAT' diff --git a/src/functions/public/Enterprise/Get-GitHubEnterprise.ps1 b/src/functions/public/Enterprise/Get-GitHubEnterprise.ps1 index 079a3a89b..20493743e 100644 --- a/src/functions/public/Enterprise/Get-GitHubEnterprise.ps1 +++ b/src/functions/public/Enterprise/Get-GitHubEnterprise.ps1 @@ -1,12 +1,30 @@ function Get-GitHubEnterprise { <# .SYNOPSIS - Retrieves details about a GitHub Enterprise instance by name (slug). + Retrieves GitHub Enterprise instance details for the authenticated user. .DESCRIPTION - This function retrieves detailed information about a GitHub Enterprise instance, including its avatar, billing details, storage usage, - creation date, and other metadata based on the provided name (slug). It returns an object of type GitHubEnterprise populated with this - information. + Retrieves detailed information about GitHub Enterprise instances available to the authenticated user. + By default, the command lists all accessible instances, including metadata such as the enterprise name, slug, URL, and creation date. If a + specific enterprise name is provided, details about that single instance are returned. + + .EXAMPLE + Get-GitHubEnterprise + + Output: + ```powershell + Name : My Enterprise + Slug : my-enterprise + URL : https://github.com/enterprises/my-enterprise + CreatedAt : 2022-01-01T00:00:00Z + + Name : Another Enterprise + Slug : another-enterprise + URL : https://github.com/enterprises/another-enterprise + CreatedAt : 2022-01-01T00:00:00Z + ``` + + Retrieves details about all GitHub Enterprise instances for the user. .EXAMPLE Get-GitHubEnterprise -Name 'my-enterprise' @@ -17,7 +35,6 @@ Slug : my-enterprise URL : https://github.com/enterprises/my-enterprise CreatedAt : 2022-01-01T00:00:00Z - ViewerIsAdmin : True ``` Retrieves details about the GitHub Enterprise instance named 'my-enterprise'. @@ -32,10 +49,10 @@ https://psmodule.io/GitHub/Functions/Enterprise/Get-GitHubEnterprise/ #> [OutputType([GitHubEnterprise])] - [CmdletBinding()] + [CmdletBinding(DefaultParameterSetName = 'List enterprises for the authenticated user')] param( # The name (slug) of the GitHub Enterprise instance to retrieve. - [Parameter(Mandatory)] + [Parameter(Mandatory, ParameterSetName = 'Get enterprise by name')] [Alias('Slug')] [string] $Name, @@ -53,49 +70,16 @@ } process { - $enterpriseQuery = @{ - query = @' -query($Slug: String!) { - enterprise(slug: $Slug) { - avatarUrl - billingEmail - billingInfo { - allLicensableUsersCount - assetPacks - bandwidthQuota - bandwidthUsage - bandwidthUsagePercentage - storageQuota - storageUsage - storageUsagePercentage - totalAvailableLicenses - totalLicenses - } - createdAt - databaseId - description - descriptionHTML - id - location - name - readme - readmeHTML - resourcePath - slug - updatedAt - url - viewerIsAdmin - websiteUrl - } -} -'@ - Variables = @{ - Slug = $Name + Write-Debug "ParameterSet: $($PSCmdlet.ParameterSetName)" + switch ($PSCmdlet.ParameterSetName) { + 'Get enterprise by name' { + Get-GitHubEnterpriseByName -Name $Name -Context $Context + break + } + default { + Get-GitHubEnterpriseList -Context $Context } - Context = $Context } - $enterpriseResult = Invoke-GitHubGraphQLQuery @enterpriseQuery - [GitHubEnterprise]::new($enterpriseResult.enterprise) } end { diff --git a/src/functions/public/Environments/Set-GitHubEnvironment.ps1 b/src/functions/public/Environments/Set-GitHubEnvironment.ps1 index 65c0b326c..b048f185e 100644 --- a/src/functions/public/Environments/Set-GitHubEnvironment.ps1 +++ b/src/functions/public/Environments/Set-GitHubEnvironment.ps1 @@ -182,9 +182,7 @@ if ($PSCmdlet.ShouldProcess("Environment [$Owner/$Repository/$Name]", 'Set')) { Invoke-GitHubAPI @inputObject | ForEach-Object { - $environment = [GitHubEnvironment]::new($_.Response, $Owner, $Repository) - $environment.Url = "https://$($Context.HostName)/$Owner/$Repository/settings/environments/$($environment.ID)/edit" - $environment + [GitHubEnvironment]::new($_.Response, $Owner, $Repository, $Context) } } } diff --git a/src/functions/public/Organization/Get-GitHubOrganization.ps1 b/src/functions/public/Organization/Get-GitHubOrganization.ps1 index cd490cd5d..526e66e74 100644 --- a/src/functions/public/Organization/Get-GitHubOrganization.ps1 +++ b/src/functions/public/Organization/Get-GitHubOrganization.ps1 @@ -114,7 +114,7 @@ Get-GitHubAllOrganization -Since $Since -PerPage $PerPage -Context $Context } 'List all organizations for the authenticated user' { - Get-GitHubMyOrganization -PerPage $PerPage -Context $Context + Get-GitHubOrganizationListForAuthUser -PerPage $PerPage -Context $Context } default { Write-Error "Invalid parameter set name: $($PSCmdlet.ParameterSetName)" diff --git a/src/functions/public/Organization/Members/Get-GitHubOrganizationMember.ps1 b/src/functions/public/Organization/Members/Get-GitHubOrganizationMember.ps1 index 75e9bc920..2354b1fb0 100644 --- a/src/functions/public/Organization/Members/Get-GitHubOrganizationMember.ps1 +++ b/src/functions/public/Organization/Members/Get-GitHubOrganizationMember.ps1 @@ -67,7 +67,9 @@ } Invoke-GitHubAPI @inputObject | ForEach-Object { - $_.Response | ForEach-Object { [GitHubUser]::new($_) } + foreach ($user in $_.Response) { + [GitHubUser]::new($user) + } } } diff --git a/src/functions/public/Organization/Update-GitHubOrganization.ps1 b/src/functions/public/Organization/Update-GitHubOrganization.ps1 index bfea406da..9095cf593 100644 --- a/src/functions/public/Organization/Update-GitHubOrganization.ps1 +++ b/src/functions/public/Organization/Update-GitHubOrganization.ps1 @@ -8,9 +8,9 @@ profile and member privileges. .EXAMPLE - Update-GitHubOrganization -Organization 'GitHub' -Blog 'https://github.blog' + Update-GitHubOrganization -Organization 'GitHub' -Description 'The official GitHub organization.' - Sets the blog URL for the organization 'GitHub' to ''. + Sets the description for the organization 'GitHub' to 'The official GitHub organization.'. .EXAMPLE $param = @{ @@ -134,9 +134,9 @@ [Parameter(ValueFromPipelineByPropertyName)] [bool] $WebCommitSignoffRequired, - # Path to the organization's blog. + # Path to the organization's site. [Parameter(ValueFromPipelineByPropertyName)] - [string] $Blog, + [string] $Website, # Whether secret scanning push protection is automatically enabled for new repositories. # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for @@ -171,7 +171,7 @@ $body = @{ name = $NewName billing_email = $BillingEmail - blog = $Blog + blog = $Website company = $Company description = $Description email = $Email @@ -204,7 +204,7 @@ if ($PSCmdlet.ShouldProcess("organization [$Name]", 'Set')) { Invoke-GitHubAPI @inputObject | ForEach-Object { - [GitHubOrganization]::new($_.Response, '') + [GitHubOrganization]::new($_.Response, $Context) } } } diff --git a/src/functions/public/Repositories/Repositories/Get-GitHubRepositorySecurityFix.ps1 b/src/functions/public/Repositories/Repositories/Get-GitHubRepositorySecurityFix.ps1 index e5356b44d..c26043b60 100644 --- a/src/functions/public/Repositories/Repositories/Get-GitHubRepositorySecurityFix.ps1 +++ b/src/functions/public/Repositories/Repositories/Get-GitHubRepositorySecurityFix.ps1 @@ -19,7 +19,6 @@ .LINK https://psmodule.io/GitHub/Functions/Repositories/Repositories/Get-GitHubRepositorySecurityFix #> - [Alias('Get-GitHubRepoSecurityFixes')] [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains a long link.')] param( diff --git a/src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuite.ps1 b/src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuite.ps1 index d24ceb1e3..741f9e9b3 100644 --- a/src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuite.ps1 +++ b/src/functions/public/Repositories/RuleSuite/Get-GitHubRepositoryRuleSuite.ps1 @@ -39,7 +39,6 @@ param( # The account owner of the repository. The name is not case sensitive. [Parameter()] - [Alias('org')] [string] $Owner, # The name of the repository without the .git extension. The name is not case sensitive. diff --git a/src/functions/public/Users/Update-GitHubUser.ps1 b/src/functions/public/Users/Update-GitHubUser.ps1 index 69af9e3d2..7338bb66c 100644 --- a/src/functions/public/Users/Update-GitHubUser.ps1 +++ b/src/functions/public/Users/Update-GitHubUser.ps1 @@ -19,9 +19,9 @@ Update the authenticated user's location to 'San Francisco' .EXAMPLE - Update-GitHubUser -Hireable $true -Bio 'I love programming' + Update-GitHubUser -Hireable $true -Description 'I love programming' - Update the authenticated user's hiring availability to 'true' and their biography to 'I love programming' + Update the authenticated user's hiring availability to 'true' and their description to 'I love programming' .NOTES [Update the authenticated user](https://docs.github.com/rest/users/users#update-the-authenticated-user) @@ -40,9 +40,10 @@ [Parameter()] [string] $Email, - # The new blog URL of the user. + # The new site for the user. [Parameter()] - [string] $Blog, + [Alias('Blog')] + [string] $Website, # The new Twitter username of the user. [Parameter()] @@ -62,7 +63,8 @@ # The new short biography of the user. [Parameter()] - [string] $Bio, + [Alias('Bio')] + [string] $Description, # 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. @@ -81,12 +83,12 @@ $body = @{ name = $DisplayName email = $Email - blog = $Blog + blog = $Website twitter_username = $TwitterUsername company = $Company location = $Location hireable = $Hireable - bio = $Bio + bio = $Description } $body | Remove-HashtableEntry -NullOrEmptyValues diff --git a/src/types/GitHubUser.Types.ps1xml b/src/types/GitHubUser.Types.ps1xml index f81e6433f..275d10688 100644 --- a/src/types/GitHubUser.Types.ps1xml +++ b/src/types/GitHubUser.Types.ps1xml @@ -7,6 +7,14 @@ User $this.Name + + Bio + $this.Description + + + Blog + $this.Website + diff --git a/tests/Enterprise.ps1 b/tests/Enterprise.Tests.ps1 similarity index 66% rename from tests/Enterprise.ps1 rename to tests/Enterprise.Tests.ps1 index 9a4760271..b6b7a73dd 100644 --- a/tests/Enterprise.ps1 +++ b/tests/Enterprise.Tests.ps1 @@ -33,11 +33,9 @@ Describe 'Template' { Write-Host ($context | Format-List | Out-String) } if ($AuthType -eq 'APP') { - It 'Connect-GitHubApp - Connects as a GitHub App to ' { + LogGroup 'Context - Installation' { $context = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent - LogGroup 'Context - Installation' { - Write-Host ($context | Format-List | Out-String) - } + Write-Host ($context | Format-List | Out-String) } } } @@ -46,7 +44,7 @@ Describe 'Template' { Write-Host ('-' * 60) } - It 'Get-GitHubEnterprise - Can get info about an enterprise' -Skip:($OwnerType -notlike 'enterprise') { + It 'Get-GitHubEnterprise - Can get info about an enterprise' -Skip:($OwnerType -ne 'enterprise') { $enterprise = Get-GitHubEnterprise -Name $Owner LogGroup 'Enterprise' { Write-Host ($enterprise | Select-Object * | Out-String) @@ -58,29 +56,15 @@ Describe 'Template' { $enterprise.ID | Should -Be 15567 $enterprise.NodeID | Should -Be 'E_kgDNPM8' $enterprise.AvatarUrl | Should -Be 'https://avatars.githubusercontent.com/b/15567?v=4' - $enterprise.BillingEmail | Should -Be 'marstor@hotmail.com' $enterprise.Url | Should -Be 'https://github.com/enterprises/msx' $enterprise.Type | Should -Be 'Enterprise' - $enterprise.BillingInfo | Should -BeOfType 'GitHubBillingInfo' - $enterprise.BillingInfo.AllLicensableUsersCount | Should -Be 1 - $enterprise.BillingInfo.AssetPacks | Should -Be 0 - $enterprise.BillingInfo.BandwidthQuota | Should -Be 5 - $enterprise.BillingInfo.BandwidthUsage | Should -Be 0 - $enterprise.BillingInfo.BandwidthUsagePercentage | Should -Be 0 - $enterprise.BillingInfo.StorageQuota | Should -Be 5 - $enterprise.BillingInfo.StorageUsage | Should -Be 0 - $enterprise.BillingInfo.StorageUsagePercentage | Should -Be 0 - $enterprise.BillingInfo.TotalAvailableLicenses | Should -Be 0 - $enterprise.BillingInfo.TotalLicenses | Should -Be 1 $enterprise.Readme | Should -Be 'This is a test' $enterprise.ReadmeHTML | Should -Be '

This is a test

' $enterprise.CreatedAt | Should -BeOfType 'DateTime' - $enterprise.CreatedAt | Should -Be (Get-Date '18.09.2022 19:53:09') $enterprise.UpdatedAt | Should -BeOfType 'DateTime' $enterprise.Description | Should -Be 'This is the description' - $enterprise.DescriptionHTML | Should -Be '
This is the description
' $enterprise.Location | Should -Be 'Oslo, Norway' - $enterprise.Blog | Should -Be 'https://msx.no' + $enterprise.Website | Should -Be 'https://msx.no' } } } diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 32ddb2b28..4136b6b53 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -94,7 +94,7 @@ Describe 'Organizations' { { Update-GitHubOrganization -Name $owner -Description 'Test Organization' } | Should -Not -Throw { Update-GitHubOrganization -Name $owner -DefaultRepositoryPermission read } | Should -Not -Throw { Update-GitHubOrganization -Name $owner -MembersCanCreateRepositories $true } | Should -Not -Throw - { Update-GitHubOrganization -Name $owner -Blog 'https://psmodule.io' } | Should -Not -Throw + { Update-GitHubOrganization -Name $owner -Website 'https://psmodule.io' } | Should -Not -Throw } } diff --git a/tests/Users.Tests.ps1 b/tests/Users.Tests.ps1 index 5dcd0ec18..f4cb7cc32 100644 --- a/tests/Users.Tests.ps1 +++ b/tests/Users.Tests.ps1 @@ -54,17 +54,21 @@ Describe 'Users' { $user = Get-GitHubUser { Update-GitHubUser -DisplayName 'Octocat' } | Should -Not -Throw { Update-GitHubUser -Blog 'https://psmodule.io' } | Should -Not -Throw + { Update-GitHubUser -Website 'https://psmodule.io' } | Should -Not -Throw { Update-GitHubUser -TwitterUsername 'PSModule' } | Should -Not -Throw { Update-GitHubUser -Company 'PSModule' } | Should -Not -Throw { Update-GitHubUser -Location 'USA' } | Should -Not -Throw { Update-GitHubUser -Bio 'I love programming' } | Should -Not -Throw + { Update-GitHubUser -Description 'I love programming' } | Should -Not -Throw $tmpUser = Get-GitHubUser $tmpUser.DisplayName | Should -Be 'Octocat' $tmpUser.Blog | Should -Be 'https://psmodule.io' + $tmpUser.Website | Should -Be 'https://psmodule.io' $tmpUser.TwitterUsername | Should -Be 'PSModule' $tmpUser.Company | Should -Be 'PSModule' $tmpUser.Location | Should -Be 'USA' $tmpUser.Bio | Should -Be 'I love programming' + $tmpUser.Description | Should -Be 'I love programming' # Flaky tests # { Update-GitHubUser -Hireable $true } | Should -Not -Throw From af28e9e17ed442e2c6603260b5f8d3c65caeb9a7 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 09:55:07 +0200 Subject: [PATCH 03/27] Add initial test scripts for GitHub API interactions - Created TEMPLATE.ps1 for Pester testing framework setup. - Added Teams.Tests.ps1 to test GitHub Teams API functionalities. - Introduced Users.Tests.ps1 for user-related API tests. - Developed Variables.Tests.ps1 to manage GitHub repository variables. - Each test script includes setup and teardown logic for authentication and resource cleanup. - Implemented various test cases for creating, updating, retrieving, and deleting GitHub resources. --- .github/PSModule.yml | 15 +++++ examples/Organizations/Organization.ps1 | 1 - .../Remove-GitHubOrganization.ps1 | 40 ++++++++----- {tests => test2}/Apps.Tests.ps1 | 0 {tests => test2}/Artifacts.Tests.ps1 | 0 {tests => test2}/Enterprise.Tests.ps1 | 0 {tests => test2}/Environments.Tests.ps1 | 0 {tests => test2}/GitHub.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 tests/Organizations.Tests.ps1 | 58 +++++++++++++------ 17 files changed, 80 insertions(+), 34 deletions(-) rename {tests => test2}/Apps.Tests.ps1 (100%) rename {tests => test2}/Artifacts.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}/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 6d578178e..2deabd938 100644 --- a/.github/PSModule.yml +++ b/.github/PSModule.yml @@ -1,3 +1,18 @@ +Build: + Docs: + Skip: true Test: + SourceCode: + Skip: true + PSModule: + Skip: true + Module: + Windows: + Skip: true + MacOS: + Skip: true + TestResults: + Skip: true CodeCoverage: PercentTarget: 50 + Skip: true diff --git a/examples/Organizations/Organization.ps1 b/examples/Organizations/Organization.ps1 index 43df1de04..4e4fcfbe3 100644 --- a/examples/Organizations/Organization.ps1 +++ b/examples/Organizations/Organization.ps1 @@ -4,7 +4,6 @@ $orgParam = @{ Owner = 'GitHub-Automation' BillingEmail = 'post@msx.no' } - $org = New-GitHubOrganization @orgParam $installAppParam = @{ diff --git a/src/functions/public/Organization/Remove-GitHubOrganization.ps1 b/src/functions/public/Organization/Remove-GitHubOrganization.ps1 index 0d9f3c310..b167632c8 100644 --- a/src/functions/public/Organization/Remove-GitHubOrganization.ps1 +++ b/src/functions/public/Organization/Remove-GitHubOrganization.ps1 @@ -27,13 +27,13 @@ [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] param( # The organization name. The name is not case sensitive. - [Parameter( - Mandatory, - ValueFromPipeline, - ValueFromPipelineByPropertyName - )] + [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] [string] $Name, + # The input object to process. Can be a single or an array of GitHubOrganization objects. + [Parameter(Mandatory, ParameterSetName = 'ArrayInput', ValueFromPipeline)] + [GitHubOrganization[]] $InputObject, + # 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()] @@ -48,14 +48,28 @@ } process { - $inputObject = @{ - Method = 'DELETE' - APIEndpoint = "/orgs/$Name" - Context = $Context - } + switch ($PSCmdlet.ParameterSetName) { + 'ArrayInput' { + foreach ($item in $InputObject) { + $params = @{ + Name = $item.Name + Context = $Context + } + Remove-GitHubOrganization @params + } + break + } + default { + $apiParams = @{ + Method = 'DELETE' + APIEndpoint = "/orgs/$Name" + Context = $Context + } - if ($PSCmdlet.ShouldProcess("organization [$Name]", 'DELETE')) { - $null = Invoke-GitHubAPI @inputObject + if ($PSCmdlet.ShouldProcess("organization [$Name]", 'Delete')) { + $null = Invoke-GitHubAPI @apiParams + } + } } } @@ -63,5 +77,3 @@ Write-Debug "[$stackPath] - End" } } - -#SkipTest:FunctionTest:Will add a test for this function in a future PR diff --git a/tests/Apps.Tests.ps1 b/test2/Apps.Tests.ps1 similarity index 100% rename from tests/Apps.Tests.ps1 rename to test2/Apps.Tests.ps1 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/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/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 diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 4136b6b53..33641ca3d 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -20,7 +20,9 @@ param() BeforeAll { - # DEFAULTS ACCROSS ALL TESTS + $testName = 'MsxOrgTests' + $os = $env:RUNNER_OS + $number = Get-Random } Describe 'Organizations' { @@ -32,6 +34,12 @@ Describe 'Organizations' { LogGroup 'Context' { Write-Host ($context | Select-Object * | Out-String) } + $orgPrefix = "$testName-$os-" + $orgName = "$orgPrefix$number" + + if ($OwnerType -eq 'enterprise'){ + Get-GitHubOrganization | Where-Object { $_.Name -eq $orgPrefix } | Remove-GitHubOrganization -Confirm:$false + } } AfterAll { Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent @@ -58,6 +66,7 @@ Describe 'Organizations' { } $organization | Should -Not -BeNullOrEmpty } + It "Get-GitHubOrganization - List public organizations for the user 'psmodule-user'" { $organizations = Get-GitHubOrganization -Username 'psmodule-user' LogGroup 'Organization' { @@ -65,6 +74,7 @@ Describe 'Organizations' { } $organizations | Should -Not -BeNullOrEmpty } + It 'Get-GitHubOrganizationMember - Gets the members of a specific organization' -Skip:($OwnerType -in ('user', 'enterprise')) { $members = Get-GitHubOrganizationMember -Organization $owner LogGroup 'Members' { @@ -73,28 +83,38 @@ Describe 'Organizations' { $members | Should -Not -BeNullOrEmpty } - # Tests for IAT UAT and PAT goes here It 'Get-GitHubOrganization - Gets the organizations for the authenticated user' -Skip:($OwnerType -notin ('user')) { { Get-GitHubOrganization } | Should -Not -Throw } - if ($OwnerType -eq 'organization' -and $Type -ne 'GitHub Actions') { - It 'Update-GitHubOrganization - Sets the organization configuration' { - { Update-GitHubOrganization -Name $owner -Company 'ABC' } | Should -Not -Throw - { - $email = (New-Guid).Guid + '@psmodule.io' - Update-GitHubOrganization -Name $owner -BillingEmail $email - } | Should -Not -Throw - { - $email = (New-Guid).Guid + '@psmodule.io' - Update-GitHubOrganization -Name $owner -Email $email - } | Should -Not -Throw - { Update-GitHubOrganization -Name $owner -TwitterUsername 'PSModule' } | Should -Not -Throw - { Update-GitHubOrganization -Name $owner -Location 'USA' } | Should -Not -Throw - { Update-GitHubOrganization -Name $owner -Description 'Test Organization' } | Should -Not -Throw - { Update-GitHubOrganization -Name $owner -DefaultRepositoryPermission read } | Should -Not -Throw - { Update-GitHubOrganization -Name $owner -MembersCanCreateRepositories $true } | Should -Not -Throw - { Update-GitHubOrganization -Name $owner -Website 'https://psmodule.io' } | Should -Not -Throw + It 'Update-GitHubOrganization - Sets the organization configuration' -Skip:($OwnerType -ne 'organization' -or $Type -eq 'GitHub Actions') { + { Update-GitHubOrganization -Name $owner -Company 'ABC' } | Should -Not -Throw + { + $email = (New-Guid).Guid + '@psmodule.io' + Update-GitHubOrganization -Name $owner -BillingEmail $email + } | Should -Not -Throw + { + $email = (New-Guid).Guid + '@psmodule.io' + Update-GitHubOrganization -Name $owner -Email $email + } | Should -Not -Throw + { Update-GitHubOrganization -Name $owner -TwitterUsername 'PSModule' } | Should -Not -Throw + { Update-GitHubOrganization -Name $owner -Location 'USA' } | Should -Not -Throw + { Update-GitHubOrganization -Name $owner -Description 'Test Organization' } | Should -Not -Throw + { Update-GitHubOrganization -Name $owner -DefaultRepositoryPermission read } | Should -Not -Throw + { Update-GitHubOrganization -Name $owner -MembersCanCreateRepositories $true } | Should -Not -Throw + { Update-GitHubOrganization -Name $owner -Website 'https://psmodule.io' } | Should -Not -Throw + } + + It 'New-GitHubOrganization - Creates a new organization' -Skip:($OwnerType -ne 'enterprise') { + $orgParam = @{ + Enterprise = 'msx' + Name = $orgName + Owner = 'MariusStorhaug' + BillingEmail = 'post@msx.no' + } + LogGroup 'Organization' { + $org = New-GitHubOrganization @orgParam + Write-Host ($org | Select-Object * | Out-String) } } From 3a6504451e05179e5f475dab9e11163215701449 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 10:26:55 +0200 Subject: [PATCH 04/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Fix=20property?= =?UTF-8?q?=20mapping=20for=20web=20commit=20signoff=20in=20GitHubOrganiza?= =?UTF-8?q?tion=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 b/src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 index 48528dba2..a99927110 100644 --- a/src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 +++ b/src/classes/public/Owner/GitHubOwner/GitHubOrganization.ps1 @@ -225,7 +225,7 @@ $this.MembersCanInviteCollaborators = $Object.members_can_invite_collaborators $this.MembersCanCreatePages = $Object.members_can_create_pages $this.MembersCanForkPrivateRepositories = $Object.members_can_fork_private_repositories ?? $Object.membersCanForkPrivateRepositories - $this.RequireWebCommitSignoff = $Object.web_commit_signoff_required ?? $Object.requiresTwoFactorAuthentication + $this.RequireWebCommitSignoff = $Object.web_commit_signoff_required ?? $Object.webCommitSignoffRequired $this.DeployKeysEnabledForRepositories = $Object.deploy_keys_enabled_for_repositories $this.MembersCanCreatePublicPages = $Object.members_can_create_public_pages $this.MembersCanCreatePrivatePages = $Object.members_can_create_private_pages From c516558794f2b6ccd7ecc4ddb1b965c6031d8c0b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 11:39:53 +0200 Subject: [PATCH 05/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20output?= =?UTF-8?q?=20type=20and=20repository=20selection=20validation=20in=20Inst?= =?UTF-8?q?all-GitHubAppOnEnterpriseOrganization=20function;=20remove=20ob?= =?UTF-8?q?solete=20tests=20from=20Organizations.Tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...tall-GitHubAppOnEnterpriseOrganization.ps1 | 8 ++- tests/Enterprise.Tests.ps1 | 70 ------------------- tests/Organizations.Tests.ps1 | 22 +++--- 3 files changed, 14 insertions(+), 86 deletions(-) delete mode 100644 tests/Enterprise.Tests.ps1 diff --git a/src/functions/private/Apps/GitHub Apps/Install-GitHubAppOnEnterpriseOrganization.ps1 b/src/functions/private/Apps/GitHub Apps/Install-GitHubAppOnEnterpriseOrganization.ps1 index b66c98e66..d8d847476 100644 --- a/src/functions/private/Apps/GitHub Apps/Install-GitHubAppOnEnterpriseOrganization.ps1 +++ b/src/functions/private/Apps/GitHub Apps/Install-GitHubAppOnEnterpriseOrganization.ps1 @@ -11,6 +11,7 @@ .EXAMPLE Install-GitHubAppOnEnterpriseOrganization -Enterprise 'msx' -Organization 'org' -ClientID '123456' #> + [OutputType([GitHubAppInstallation])] [CmdletBinding()] param( # The enterprise slug or ID. @@ -29,7 +30,7 @@ # - all - all repositories that the authenticated GitHub App installation can access. # - selected - select specific repositories. [Parameter(Mandatory)] - [ValidateSet('all', 'selected')] + [ValidateSet('All', 'Selected')] [string] $RepositorySelection, # The names of the repositories to which the installation will be granted access. @@ -49,6 +50,9 @@ } process { + if ($RepositorySelection) { + $RepositorySelection = $RepositorySelection.ToLower() + } $body = @{ client_id = $ClientID repository_selection = $RepositorySelection @@ -64,7 +68,7 @@ } Invoke-GitHubAPI @inputObject | ForEach-Object { - Write-Output $_.Response + [GitHubAppInstallation]::new($_.Response) } } diff --git a/tests/Enterprise.Tests.ps1 b/tests/Enterprise.Tests.ps1 deleted file mode 100644 index b6b7a73dd..000000000 --- a/tests/Enterprise.Tests.ps1 +++ /dev/null @@ -1,70 +0,0 @@ -#Requires -Modules @{ ModuleName = 'Pester'; RequiredVersion = '5.7.1' } - -[Diagnostics.CodeAnalysis.SuppressMessageAttribute( - 'PSUseDeclaredVarsMoreThanAssignments', '', - Justification = 'Pester grouping syntax: known issue.' -)] -[Diagnostics.CodeAnalysis.SuppressMessageAttribute( - 'PSAvoidUsingConvertToSecureStringWithPlainText', '', - Justification = 'Used to create a secure string for testing.' -)] -[Diagnostics.CodeAnalysis.SuppressMessageAttribute( - 'PSAvoidUsingWriteHost', '', - Justification = 'Log outputs to GitHub Actions logs.' -)] -[Diagnostics.CodeAnalysis.SuppressMessageAttribute( - 'PSAvoidLongLines', '', - Justification = 'Long test descriptions and skip switches' -)] -[CmdletBinding()] -param() - -BeforeAll { - # DEFAULTS ACCROSS ALL TESTS -} - -Describe 'Template' { - $authCases = . "$PSScriptRoot/Data/AuthCases.ps1" - - Context 'As using on ' -ForEach $authCases { - BeforeAll { - $context = Connect-GitHubAccount @connectParams -PassThru -Silent - LogGroup 'Context' { - Write-Host ($context | Format-List | Out-String) - } - if ($AuthType -eq 'APP') { - LogGroup 'Context - Installation' { - $context = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent - Write-Host ($context | Format-List | Out-String) - } - } - } - AfterAll { - Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent - Write-Host ('-' * 60) - } - - It 'Get-GitHubEnterprise - Can get info about an enterprise' -Skip:($OwnerType -ne 'enterprise') { - $enterprise = Get-GitHubEnterprise -Name $Owner - LogGroup 'Enterprise' { - Write-Host ($enterprise | Select-Object * | Out-String) - } - $enterprise | Should -Not -BeNullOrEmpty - $enterprise | Should -BeOfType 'GitHubEnterprise' - $enterprise.Name | Should -Be 'msx' - $enterprise.DisplayName | Should -Be 'MSX' - $enterprise.ID | Should -Be 15567 - $enterprise.NodeID | Should -Be 'E_kgDNPM8' - $enterprise.AvatarUrl | Should -Be 'https://avatars.githubusercontent.com/b/15567?v=4' - $enterprise.Url | Should -Be 'https://github.com/enterprises/msx' - $enterprise.Type | Should -Be 'Enterprise' - $enterprise.Readme | Should -Be 'This is a test' - $enterprise.ReadmeHTML | Should -Be '

This is a test

' - $enterprise.CreatedAt | Should -BeOfType 'DateTime' - $enterprise.UpdatedAt | Should -BeOfType 'DateTime' - $enterprise.Description | Should -Be 'This is the description' - $enterprise.Location | Should -Be 'Oslo, Norway' - $enterprise.Website | Should -Be 'https://msx.no' - } - } -} diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 33641ca3d..8deac2ee8 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -37,7 +37,14 @@ Describe 'Organizations' { $orgPrefix = "$testName-$os-" $orgName = "$orgPrefix$number" - if ($OwnerType -eq 'enterprise'){ + # Tests for APP goes here + if ($AuthType -eq 'APP') { + $context = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent + LogGroup 'Context - Installation' { + Write-Host ($context | Select-Object * | Out-String) + } + } + if ($OwnerType -eq 'enterprise') { Get-GitHubOrganization | Where-Object { $_.Name -eq $orgPrefix } | Remove-GitHubOrganization -Confirm:$false } } @@ -46,19 +53,6 @@ Describe 'Organizations' { Write-Host ('-' * 60) } - # Tests for APP goes here - if ($AuthType -eq 'APP') { - It 'Connect-GitHubApp - Connects as a GitHub App to ' { - $context = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent - LogGroup 'Context' { - Write-Host ($context | Select-Object * | Out-String) - } - } - } - - # Tests for runners goes here - if ($Type -eq 'GitHub Actions') {} - It "Get-GitHubOrganization - Gets a specific organization 'PSModule'" { $organization = Get-GitHubOrganization -Name 'PSModule' LogGroup 'Organization' { From a96765cac216fe4c53da458c87f3f051eb3f8371 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 11:58:27 +0200 Subject: [PATCH 06/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Add=20cleanup?= =?UTF-8?q?=20for=20enterprise=20organizations=20in=20AfterAll=20block=20o?= =?UTF-8?q?f=20Organizations.Tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 8deac2ee8..2888c967e 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -49,6 +49,10 @@ Describe 'Organizations' { } } AfterAll { + if ($OwnerType -eq 'enterprise') { + Get-GitHubOrganization | Where-Object { $_.Name -eq $orgPrefix } | Remove-GitHubOrganization -Confirm:$false + } + Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent Write-Host ('-' * 60) } From c7cc346ba935a734cf0e14ea9eb3c2031aa9b385 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 12:02:19 +0200 Subject: [PATCH 07/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20organi?= =?UTF-8?q?zation=20removal=20logic=20in=20AfterAll=20block=20to=20use=20w?= =?UTF-8?q?ildcard=20matching=20and=20add=20-WhatIf=20parameter=20for=20sa?= =?UTF-8?q?fety?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 2888c967e..14df98b67 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,12 +45,12 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { - Get-GitHubOrganization | Where-Object { $_.Name -eq $orgPrefix } | Remove-GitHubOrganization -Confirm:$false + Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Remove-GitHubOrganization -WhatIf } } AfterAll { if ($OwnerType -eq 'enterprise') { - Get-GitHubOrganization | Where-Object { $_.Name -eq $orgPrefix } | Remove-GitHubOrganization -Confirm:$false + Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Remove-GitHubOrganization -WhatIf } Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent From 82a012c0321dae2e2c2b9165d78a1577f9053528 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 12:17:50 +0200 Subject: [PATCH 08/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Pass=20context?= =?UTF-8?q?=20to=20GitHubOrganization=20constructor=20in=20New-GitHubOrgan?= =?UTF-8?q?ization=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/functions/public/Organization/New-GitHubOrganization.ps1 | 2 +- tests/Organizations.Tests.ps1 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/functions/public/Organization/New-GitHubOrganization.ps1 b/src/functions/public/Organization/New-GitHubOrganization.ps1 index 188168acb..1d0090f10 100644 --- a/src/functions/public/Organization/New-GitHubOrganization.ps1 +++ b/src/functions/public/Organization/New-GitHubOrganization.ps1 @@ -66,6 +66,6 @@ } if ($PSCmdlet.ShouldProcess("Creating organization '$Name' in enterprise '$Enterprise'")) { $orgresult = Invoke-GitHubGraphQLQuery @updateGraphQLInputs - [GitHubOrganization]::new($orgresult.createEnterpriseOrganization.organization) + [GitHubOrganization]::new($orgresult.createEnterpriseOrganization.organization, $Context) } } diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 14df98b67..41ad3e6e5 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,12 +45,12 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { - Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Remove-GitHubOrganization -WhatIf + Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Remove-GitHubOrganization } } AfterAll { if ($OwnerType -eq 'enterprise') { - Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Remove-GitHubOrganization -WhatIf + Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Remove-GitHubOrganization } Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent From 25f37bac87aa405236b261adb06ab97c24b680d0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 12:31:14 +0200 Subject: [PATCH 09/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Enhance=20New-G?= =?UTF-8?q?itHubOrganization=20function=20by=20adding=20mandatory=20parame?= =?UTF-8?q?ters=20for=20organization=20name=20and=20owners;=20improve=20de?= =?UTF-8?q?bug=20logging=20in=20process=20block?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Organization/New-GitHubOrganization.ps1 | 64 ++++++++++++------- tests/Organizations.Tests.ps1 | 2 +- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/functions/public/Organization/New-GitHubOrganization.ps1 b/src/functions/public/Organization/New-GitHubOrganization.ps1 index 1d0090f10..976761075 100644 --- a/src/functions/public/Organization/New-GitHubOrganization.ps1 +++ b/src/functions/public/Organization/New-GitHubOrganization.ps1 @@ -18,15 +18,19 @@ [OutputType([GitHubOrganization])] [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] param( + # The name of the enterprise to create the organization in. [Parameter()] [string]$Enterprise, + # The name of the organization to create. [Parameter(Mandatory)] [string]$Name, + # The owners of the organization. This should be a list of GitHub usernames. [Parameter(Mandatory)] [string[]]$Owner, + # The billing email for the organization. [Parameter()] [string]$BillingEmail, @@ -36,36 +40,48 @@ [object] $Context ) + begin { + $stackPath = Get-PSCallStackPath + Write-Debug "[$stackPath] - Start" + Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT + } - $enterpriseObject = Get-GitHubEnterprise -Name $Enterprise -Context $Context - Write-Verbose "Creating organization in enterprise: $($enterpriseObject.Name)" + process { + $enterpriseObject = Get-GitHubEnterprise -Name $Enterprise -Context $Context + Write-Verbose "Creating organization in enterprise: $($enterpriseObject.Name)" + $graphQLFields = ([GitHubOrganization]::PropertyToGraphQLMap).Values - $inputParams = @{ - adminLogins = $Owner - billingEmail = $BillingEmail - enterpriseId = $enterpriseObject.NodeID - login = $Name - profileName = $Name - } + $inputParams = @{ + adminLogins = $Owner + billingEmail = $BillingEmail + enterpriseId = $enterpriseObject.NodeID + login = $Name + profileName = $Name + } - $updateGraphQLInputs = @{ - Query = @' - mutation($input:CreateEnterpriseOrganizationInput!) { - createEnterpriseOrganization(input:$input) { - organization { - id - login - } + $updateGraphQLInputs = @{ + Query = @" +mutation(`$input:CreateEnterpriseOrganizationInput!) { + createEnterpriseOrganization(input:`$input) { + organization { + $graphQLFields } } -'@ - Variables = @{ - input = $inputParams +} +"@ + Variables = @{ + input = $inputParams + } + Context = $Context + } + if ($PSCmdlet.ShouldProcess("Creating organization '$Name' in enterprise '$Enterprise'")) { + $orgresult = Invoke-GitHubGraphQLQuery @updateGraphQLInputs + [GitHubOrganization]::new($orgresult.createEnterpriseOrganization.organization, $Context) } - Context = $Context } - if ($PSCmdlet.ShouldProcess("Creating organization '$Name' in enterprise '$Enterprise'")) { - $orgresult = Invoke-GitHubGraphQLQuery @updateGraphQLInputs - [GitHubOrganization]::new($orgresult.createEnterpriseOrganization.organization, $Context) + + end { + Write-Debug "[$stackPath] - End" } } + diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 41ad3e6e5..d86dc48fc 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -81,7 +81,7 @@ Describe 'Organizations' { $members | Should -Not -BeNullOrEmpty } - It 'Get-GitHubOrganization - Gets the organizations for the authenticated user' -Skip:($OwnerType -notin ('user')) { + It 'Get-GitHubOrganization - Gets the organizations for the authenticated user' { { Get-GitHubOrganization } | Should -Not -Throw } From 62cb520dcf83e69f55e7d555d183828d8833b514 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 12:37:07 +0200 Subject: [PATCH 10/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Ensure=20contex?= =?UTF-8?q?t=20is=20resolved=20in=20New-GitHubOrganization=20function's=20?= =?UTF-8?q?begin=20block?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/functions/public/Organization/New-GitHubOrganization.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/src/functions/public/Organization/New-GitHubOrganization.ps1 b/src/functions/public/Organization/New-GitHubOrganization.ps1 index 976761075..7279e9358 100644 --- a/src/functions/public/Organization/New-GitHubOrganization.ps1 +++ b/src/functions/public/Organization/New-GitHubOrganization.ps1 @@ -43,6 +43,7 @@ begin { $stackPath = Get-PSCallStackPath Write-Debug "[$stackPath] - Start" + $Context = Resolve-GitHubContext -Context $Context Assert-GitHubContext -Context $Context -AuthType IAT, PAT, UAT } From ce1c0c25f717c73b79b39b2d6d6f7bd72c80dd4a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 12:45:45 +0200 Subject: [PATCH 11/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Enhance=20organ?= =?UTF-8?q?ization=20cleanup=20logic=20in=20AfterAll=20block=20to=20log=20?= =?UTF-8?q?organization=20details=20before=20removal;=20improve=20organiza?= =?UTF-8?q?tion=20retrieval=20in=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index d86dc48fc..4fc01c2ec 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,12 +45,20 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { - Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Remove-GitHubOrganization + $orgs = Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + LogGroup 'Organizations' { + $orgs | Format-Table -AutoSize | Out-String + } + $orgs | Remove-GitHubOrganization } } AfterAll { if ($OwnerType -eq 'enterprise') { - Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Remove-GitHubOrganization + $orgs = Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + LogGroup 'Organizations' { + $orgs | Format-Table -AutoSize | Out-String + } + $orgs | Remove-GitHubOrganization } Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent @@ -82,6 +90,10 @@ Describe 'Organizations' { } It 'Get-GitHubOrganization - Gets the organizations for the authenticated user' { + $orgs = Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + LogGroup 'Organizations' { + $orgs | Format-Table -AutoSize | Out-String + } { Get-GitHubOrganization } | Should -Not -Throw } From 50db04b60e1a1e992cf0ddff89136a80c708d421 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 12:59:28 +0200 Subject: [PATCH 12/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20Get-Gi?= =?UTF-8?q?tHubOrganization=20calls=20to=20include=20-Enterprise=20paramet?= =?UTF-8?q?er=20for=20organization=20retrieval=20in=20enterprise=20context?= =?UTF-8?q?;=20ensure=20accurate=20logging=20of=20organizations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 4fc01c2ec..413bff596 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,7 +45,7 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { - $orgs = Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + $orgs = Get-GitHubOrganization -Enterprise $owner | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String } @@ -54,7 +54,7 @@ Describe 'Organizations' { } AfterAll { if ($OwnerType -eq 'enterprise') { - $orgs = Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + $orgs = Get-GitHubOrganization -Enterprise $owner | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String } @@ -89,7 +89,7 @@ Describe 'Organizations' { $members | Should -Not -BeNullOrEmpty } - It 'Get-GitHubOrganization - Gets the organizations for the authenticated user' { + It 'Get-GitHubOrganization - Gets the organizations for the authenticated user' -Skip:($Type -eq 'GitHub Actions') { $orgs = Get-GitHubOrganization | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String From 905c7da9aef35722d8d84ca99eec385a2e3b2e45 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 13:06:04 +0200 Subject: [PATCH 13/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20orga?= =?UTF-8?q?nization=20retrieval=20logic=20in=20test=20cases;=20remove=20un?= =?UTF-8?q?necessary=20enterprise=20parameter=20and=20cleanup=20calls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 413bff596..358aaeecb 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,20 +45,20 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { - $orgs = Get-GitHubOrganization -Enterprise $owner | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + $orgs = Get-GitHubOrganization # -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String } - $orgs | Remove-GitHubOrganization + $orgs # | Remove-GitHubOrganization } } AfterAll { if ($OwnerType -eq 'enterprise') { - $orgs = Get-GitHubOrganization -Enterprise $owner | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + $orgs = Get-GitHubOrganization # -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String } - $orgs | Remove-GitHubOrganization + $orgs # | Remove-GitHubOrganization } Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent From c5f3a201e329e8ccf6f32155774ce1da25b7fb1c Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 13:27:15 +0200 Subject: [PATCH 14/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20Get-Gi?= =?UTF-8?q?tHubOrganization=20calls=20to=20include=20-Enterprise=20paramet?= =?UTF-8?q?er=20for=20organization=20retrieval=20in=20enterprise=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 358aaeecb..1284b0f93 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,7 +45,7 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { - $orgs = Get-GitHubOrganization # -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + $orgs = Get-GitHubOrganization -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String } @@ -54,7 +54,7 @@ Describe 'Organizations' { } AfterAll { if ($OwnerType -eq 'enterprise') { - $orgs = Get-GitHubOrganization # -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String + $orgs = Get-GitHubOrganization -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String } From cd3b7e181fedebb092b4b5688127966e00f8b336 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 13:34:44 +0200 Subject: [PATCH 15/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Add=20logging?= =?UTF-8?q?=20for=20organization=20retrieval=20in=20enterprise=20context?= =?UTF-8?q?=20using=20Invoke-GitHubAPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 1284b0f93..662cff80c 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,6 +45,7 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { + (Invoke-GitHubAPI -ApiEndpoint '/organizations').Response | Out-String $orgs = Get-GitHubOrganization -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String From 571bb8ee7cd8829e25d9c5eec6080d0176c10315 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 13:36:02 +0200 Subject: [PATCH 16/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Add=20logging?= =?UTF-8?q?=20for=20organization=20retrieval=20in=20AfterAll=20block=20for?= =?UTF-8?q?=20enterprise=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 662cff80c..506a157df 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -55,6 +55,7 @@ Describe 'Organizations' { } AfterAll { if ($OwnerType -eq 'enterprise') { + (Invoke-GitHubAPI -ApiEndpoint '/organizations').Response | Out-String $orgs = Get-GitHubOrganization -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String LogGroup 'Organizations' { $orgs | Format-Table -AutoSize | Out-String From a544b0ac890d33a108d65786baad94d1736c1f7a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 13:55:24 +0200 Subject: [PATCH 17/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Simplify=20orga?= =?UTF-8?q?nization=20cleanup=20in=20AfterAll=20block=20by=20removing=20un?= =?UTF-8?q?necessary=20logging=20and=20directly=20removing=20organizations?= =?UTF-8?q?=20for=20enterprise=20context?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 506a157df..b76ccf189 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,22 +45,12 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { - (Invoke-GitHubAPI -ApiEndpoint '/organizations').Response | Out-String - $orgs = Get-GitHubOrganization -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String - LogGroup 'Organizations' { - $orgs | Format-Table -AutoSize | Out-String - } - $orgs # | Remove-GitHubOrganization + Remove-GitHubOrganization -Name $orgName } } AfterAll { if ($OwnerType -eq 'enterprise') { - (Invoke-GitHubAPI -ApiEndpoint '/organizations').Response | Out-String - $orgs = Get-GitHubOrganization -Enterprise $owner # | Where-Object { $_.Name -like "$orgPrefix*" } | Out-String - LogGroup 'Organizations' { - $orgs | Format-Table -AutoSize | Out-String - } - $orgs # | Remove-GitHubOrganization + Remove-GitHubOrganization -Name $orgName } Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent From 149de4c5d15e6ce9aa1dee77dd958cc2726fa7fd Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 14:01:22 +0200 Subject: [PATCH 18/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Set=20default?= =?UTF-8?q?=20parameter=20set=20name=20for=20CmdletBinding=20in=20Remove-G?= =?UTF-8?q?itHubOrganization=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/functions/public/Organization/Remove-GitHubOrganization.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/functions/public/Organization/Remove-GitHubOrganization.ps1 b/src/functions/public/Organization/Remove-GitHubOrganization.ps1 index b167632c8..8f31b57c3 100644 --- a/src/functions/public/Organization/Remove-GitHubOrganization.ps1 +++ b/src/functions/public/Organization/Remove-GitHubOrganization.ps1 @@ -24,7 +24,7 @@ https://psmodule.io/GitHub/Functions/Organization/Remove-GitHubOrganization #> [OutputType([void])] - [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + [CmdletBinding(DefaultParameterSetName = 'Remove an organization', SupportsShouldProcess, ConfirmImpact = 'High')] param( # The organization name. The name is not case sensitive. [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] From fc62a39165668196e29c8e4ae99d9ac506f4f432 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 14:08:43 +0200 Subject: [PATCH 19/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Bypass=20confir?= =?UTF-8?q?mation=20prompt=20in=20Remove-GitHubOrganization=20for=20enterp?= =?UTF-8?q?rise=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index b76ccf189..06dfd3da5 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -45,12 +45,12 @@ Describe 'Organizations' { } } if ($OwnerType -eq 'enterprise') { - Remove-GitHubOrganization -Name $orgName + Remove-GitHubOrganization -Name $orgName -Confirm:$false } } AfterAll { if ($OwnerType -eq 'enterprise') { - Remove-GitHubOrganization -Name $orgName + Remove-GitHubOrganization -Name $orgName -Confirm:$false } Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent From d539d439fc5cf98f48c6e9dc8cd177842a9b53de Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 14:19:01 +0200 Subject: [PATCH 20/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Remove=20organi?= =?UTF-8?q?zation=20deletion=20for=20enterprise=20in=20AfterAll=20block?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 06dfd3da5..1e2100379 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -44,9 +44,6 @@ Describe 'Organizations' { Write-Host ($context | Select-Object * | Out-String) } } - if ($OwnerType -eq 'enterprise') { - Remove-GitHubOrganization -Name $orgName -Confirm:$false - } } AfterAll { if ($OwnerType -eq 'enterprise') { From 500dc244e8b60cd21e1b788f1f752580866ab2be Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 14:33:45 +0200 Subject: [PATCH 21/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Add=20test=20fo?= =?UTF-8?q?r=20updating=20organization=20location=20in=20Update-GitHubOrga?= =?UTF-8?q?nization?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 1e2100379..00215ce51 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -117,6 +117,10 @@ Describe 'Organizations' { } } + It 'Update-GitHubOrganization - Updates the organization location' -Skip:($OwnerType -ne 'enterprise') { + { Update-GitHubOrganization -Name $orgName -Location 'New Location' } | Should -Not -Throw + } + Context 'Invitations' -Skip:($Owner -notin 'psmodule-test-org', 'psmodule-test-org2') { It 'New-GitHubOrganizationInvitation - Invites a user to an organization' { { From 9511cd1f19af9294ae10c45eb38981ffd93ce1d3 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 14:41:45 +0200 Subject: [PATCH 22/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Refactor=20orga?= =?UTF-8?q?nization=20tests=20to=20improve=20context=20handling=20and=20ad?= =?UTF-8?q?d=20tests=20for=20app=20installation=20and=20organization=20upd?= =?UTF-8?q?ates?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 39 ++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index 00215ce51..b294f3d09 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -39,17 +39,13 @@ Describe 'Organizations' { # Tests for APP goes here if ($AuthType -eq 'APP') { - $context = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent + $installationContext = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent LogGroup 'Context - Installation' { - Write-Host ($context | Select-Object * | Out-String) + Write-Host ($installationContext | Select-Object * | Out-String) } } } AfterAll { - if ($OwnerType -eq 'enterprise') { - Remove-GitHubOrganization -Name $orgName -Confirm:$false - } - Get-GitHubContext -ListAvailable | Disconnect-GitHubAccount -Silent Write-Host ('-' * 60) } @@ -117,10 +113,39 @@ Describe 'Organizations' { } } - It 'Update-GitHubOrganization - Updates the organization location' -Skip:($OwnerType -ne 'enterprise') { + It 'Update-GitHubOrganization - Updates the organization location using enterprise installation' -Skip:($OwnerType -ne 'enterprise') { { Update-GitHubOrganization -Name $orgName -Location 'New Location' } | Should -Not -Throw } + It 'Remove-GitHubOrganization - Removes an organization using enterprise installation' -Skip:($OwnerType -ne 'enterprise') { + { Remove-GitHubOrganization -Name $orgName -Confirm:$false } | Should -Not -Throw + } + + It 'Install-GitHubApp - Installs a GitHub App to an organization' -Skip:($OwnerType -ne 'enterprise') { + $installation = Install-GitHubApp -Enterprise $owner -Organization $orgName -ClientID $installationContext.ClientID -RepositorySelection 'all' + LogGroup 'Installed App' { + Write-Host ($installation | Select-Object * | Out-String) + } + $installation | Should -Not -BeNullOrEmpty + $installation | Should -BeOfType 'GitHubAppInstallation' + } + + It 'Connect-GitHubApp - Connects as a GitHub App to the organization' -Skip:($OwnerType -ne 'organization') { + $orgContext = Connect-GitHubApp -Organization $orgName -ClientID $installationContext.ClientID -PassThru -Silent + LogGroup 'Context' { + Write-Host ($orgContext | Select-Object * | Out-String) + } + $orgContext | Should -Not -BeNullOrEmpty + } + + It 'Update-GitHubOrganization - Updates the organization location using organization installation' -Skip:($OwnerType -ne 'enterprise') { + { Update-GitHubOrganization -Name $orgName -Location 'New Location' -Context $orgContext } | Should -Not -Throw + } + + It 'Remove-GitHubOrganization - Removes an organization using organization installation' -Skip:($OwnerType -ne 'enterprise') { + { Remove-GitHubOrganization -Name $orgName -Confirm:$false -Context $orgContext } | Should -Not -Throw + } + Context 'Invitations' -Skip:($Owner -notin 'psmodule-test-org', 'psmodule-test-org2') { It 'New-GitHubOrganizationInvitation - Invites a user to an organization' { { From 3adf4afd2426e519440d4e5415993805c0a440d0 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 14:43:26 +0200 Subject: [PATCH 23/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Remove=20commen?= =?UTF-8?q?ted=20placeholder=20for=20app=20tests=20in=20Organizations=20te?= =?UTF-8?q?st=20suite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index b294f3d09..c995a8a3a 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -37,7 +37,6 @@ Describe 'Organizations' { $orgPrefix = "$testName-$os-" $orgName = "$orgPrefix$number" - # Tests for APP goes here if ($AuthType -eq 'APP') { $installationContext = Connect-GitHubApp @connectAppParams -PassThru -Default -Silent LogGroup 'Context - Installation' { @@ -131,7 +130,7 @@ Describe 'Organizations' { } It 'Connect-GitHubApp - Connects as a GitHub App to the organization' -Skip:($OwnerType -ne 'organization') { - $orgContext = Connect-GitHubApp -Organization $orgName -ClientID $installationContext.ClientID -PassThru -Silent + $orgContext = Connect-GitHubApp -Organization $orgName -Context $context -PassThru -Silent LogGroup 'Context' { Write-Host ($orgContext | Select-Object * | Out-String) } From 676869b0f7cf60bb6bac43270a2e6bc72a102efe Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 14:57:30 +0200 Subject: [PATCH 24/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20Connec?= =?UTF-8?q?t-GitHubApp=20test=20to=20skip=20for=20non-enterprise=20organiz?= =?UTF-8?q?ations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index c995a8a3a..ea72ed3bc 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -129,7 +129,7 @@ Describe 'Organizations' { $installation | Should -BeOfType 'GitHubAppInstallation' } - It 'Connect-GitHubApp - Connects as a GitHub App to the organization' -Skip:($OwnerType -ne 'organization') { + It 'Connect-GitHubApp - Connects as a GitHub App to the organization' -Skip:($OwnerType -ne 'enterprise') { $orgContext = Connect-GitHubApp -Organization $orgName -Context $context -PassThru -Silent LogGroup 'Context' { Write-Host ($orgContext | Select-Object * | Out-String) From 75baf1128dbda681938cd01ef4bc64d66a4a4946 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 20:22:47 +0200 Subject: [PATCH 25/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Enhance=20error?= =?UTF-8?q?=20logging=20in=20Invoke-GitHubAPI=20by=20adding=20context=20in?= =?UTF-8?q?formation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/functions/public/API/Invoke-GitHubAPI.ps1 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/functions/public/API/Invoke-GitHubAPI.ps1 b/src/functions/public/API/Invoke-GitHubAPI.ps1 index 9261893b5..2c4d9279b 100644 --- a/src/functions/public/API/Invoke-GitHubAPI.ps1 +++ b/src/functions/public/API/Invoke-GitHubAPI.ps1 @@ -315,6 +315,10 @@ function Invoke-GitHubAPI { } $exception = @" + +---------------------------------- +Context: +$($Context | Format-List | Out-String) ---------------------------------- Request: $([pscustomobject]$APICall | Select-Object -ExcludeProperty Body, Headers | Format-List | Out-String) From b2375ab27d192421eede04fa0b5c8bf0cc5b6ebb Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 20:34:09 +0200 Subject: [PATCH 26/27] =?UTF-8?q?=F0=9F=A9=B9=20[Patch]:=20Update=20organi?= =?UTF-8?q?zation=20location=20and=20removal=20tests=20to=20expect=20excep?= =?UTF-8?q?tions=20for=20non-enterprise=20installations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/Organizations.Tests.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/Organizations.Tests.ps1 b/tests/Organizations.Tests.ps1 index ea72ed3bc..7d1740e5c 100644 --- a/tests/Organizations.Tests.ps1 +++ b/tests/Organizations.Tests.ps1 @@ -113,11 +113,11 @@ Describe 'Organizations' { } It 'Update-GitHubOrganization - Updates the organization location using enterprise installation' -Skip:($OwnerType -ne 'enterprise') { - { Update-GitHubOrganization -Name $orgName -Location 'New Location' } | Should -Not -Throw + { Update-GitHubOrganization -Name $orgName -Location 'New Location' } | Should -Throw } It 'Remove-GitHubOrganization - Removes an organization using enterprise installation' -Skip:($OwnerType -ne 'enterprise') { - { Remove-GitHubOrganization -Name $orgName -Confirm:$false } | Should -Not -Throw + { Remove-GitHubOrganization -Name $orgName -Confirm:$false } | Should -Throw } It 'Install-GitHubApp - Installs a GitHub App to an organization' -Skip:($OwnerType -ne 'enterprise') { @@ -138,11 +138,13 @@ Describe 'Organizations' { } It 'Update-GitHubOrganization - Updates the organization location using organization installation' -Skip:($OwnerType -ne 'enterprise') { - { Update-GitHubOrganization -Name $orgName -Location 'New Location' -Context $orgContext } | Should -Not -Throw + $orgContext = Connect-GitHubApp -Organization $orgName -Context $context -PassThru -Silent + Update-GitHubOrganization -Name $orgName -Location 'New Location' -Context $orgContext } It 'Remove-GitHubOrganization - Removes an organization using organization installation' -Skip:($OwnerType -ne 'enterprise') { - { Remove-GitHubOrganization -Name $orgName -Confirm:$false -Context $orgContext } | Should -Not -Throw + $orgContext = Connect-GitHubApp -Organization $orgName -Context $context -PassThru -Silent + Remove-GitHubOrganization -Name $orgName -Confirm:$false -Context $orgContext } Context 'Invitations' -Skip:($Owner -notin 'psmodule-test-org', 'psmodule-test-org2') { From 00bade556716acbc0e269ba11db25c87200a45ad Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Mon, 7 Jul 2025 20:42:08 +0200 Subject: [PATCH 27/27] Add comprehensive Pester tests for GitHub API interactions - Created TEMPLATE.ps1 for standardized test structure. - Implemented Teams.Tests.ps1 to validate GitHub Teams functionality, including team creation, retrieval, updating, and deletion. - Developed Users.Tests.ps1 to test user-related API calls, including user retrieval and updates. - Added Variables.Tests.ps1 to cover GitHub variable management, including setting, updating, and removing variables for users and organizations. - Each test file includes setup and teardown logic to ensure a clean testing environment. - Utilized Pester's logging capabilities to enhance output visibility during test execution. --- .github/PSModule.yml | 14 -------------- {test2 => tests}/Apps.Tests.ps1 | 0 {test2 => tests}/Artifacts.Tests.ps1 | 0 {test2 => tests}/Enterprise.Tests.ps1 | 0 {test2 => tests}/Environments.Tests.ps1 | 0 {test2 => tests}/GitHub.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 14 files changed, 14 deletions(-) rename {test2 => tests}/Apps.Tests.ps1 (100%) rename {test2 => tests}/Artifacts.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}/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 fc3a14340..6d578178e 100644 --- a/.github/PSModule.yml +++ b/.github/PSModule.yml @@ -1,17 +1,3 @@ -Build: - Docs: - Skip: true Test: - SourceCode: - Skip: true - PSModule: - Skip: true - Module: - Windows: - Skip: true - MacOS: - Skip: true - TestResults: - Skip: true CodeCoverage: PercentTarget: 50 diff --git a/test2/Apps.Tests.ps1 b/tests/Apps.Tests.ps1 similarity index 100% rename from test2/Apps.Tests.ps1 rename to tests/Apps.Tests.ps1 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/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/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