Skip to content

Commit

Permalink
🚀 [Feature]: Add classes and restructure context handling (#191)
Browse files Browse the repository at this point in the history
## Description


This pull request introduces several new classes and refactors existing
ones to enhance the GitHub context management in PowerShell scripts.
Additionally, it includes changes to improve logging and configuration
initialization. The most important changes are summarized below:

### New Classes for GitHub Context Management:
*
[`src/classes/public/Config/GitHubConfig.ps1`](diffhunk://#diff-b30ece1b52dbf4e2436f25c9d00b18f0420696da62094aa2b6eb7cfa765aeac9R1-R19):
Added a new `GitHubConfig` class to manage GitHub configuration
settings.
*
[`src/classes/public/Context/GitHubContext.ps1`](diffhunk://#diff-a8076f3b68ae776032b69baf8cc6198b2f00f834af814088fa260d0be7b684a8R1-R58):
Added a new `GitHubContext` class to encapsulate GitHub context details.
*
[`src/classes/public/Context/GitHubContext/AppGitHubContext.ps1`](diffhunk://#diff-59869473eaaec5f3a6e02c2c8cca88b9cc96f5e9fd840a87ead0d079c2c61372R1-R18):
Added a new `AppGitHubContext` class for managing GitHub App contexts.
*
[`src/classes/public/Context/GitHubContext/InstallationGitHubContext.ps1`](diffhunk://#diff-c9fc34da1bb954dfdae3f8d44c516bf8605d70c07941cd7b2c708ddd739292c0R1-R25):
Added a new `InstallationGitHubContext` class for managing installation
contexts.
*
[`src/classes/public/Context/GitHubContext/UserGitHubContext.ps1`](diffhunk://#diff-362543d00b76fa5b7f197c241363be74af60997ed87ea9209907944a89e5f069R1-R38):
Added a new `UserGitHubContext` class for managing user contexts.

### Refactoring and Improvements:
*
[`src/classes/public/GitHubContext.ps1`](diffhunk://#diff-7efa17a35bd3237f73bc3b2e42c17af4f5daa196e54adb04314ea31c3d8cc46cL1-L105):
Removed the old `GitHubContext` class, which has been replaced by the
new context classes.
*
[`src/functions/private/Auth/Context/Resolve-GitHubContext.ps1`](diffhunk://#diff-096a5462baf72d04ba840145e46b05d4651afb1cce7c439631f4442c239f63e1L36-R64):
Improved logging by changing the output format to `Format-Table` and
added verbose logging for resolved contexts.
*
[`src/functions/public/Auth/Connect-GitHubAccount.ps1`](diffhunk://#diff-12918e90451cdedb78571b9a67ac0313331a25175cebb606b7108b7bf06af092L152-R172):
Refactored to use the new `GitHubConfig` and improved handling of
default client IDs and tokens.
[[1]](diffhunk://#diff-12918e90451cdedb78571b9a67ac0313331a25175cebb606b7108b7bf06af092L152-R172)
[[2]](diffhunk://#diff-12918e90451cdedb78571b9a67ac0313331a25175cebb606b7108b7bf06af092L183-R182)
[[3]](diffhunk://#diff-12918e90451cdedb78571b9a67ac0313331a25175cebb606b7108b7bf06af092L192-R215)
[[4]](diffhunk://#diff-12918e90451cdedb78571b9a67ac0313331a25175cebb606b7108b7bf06af092L213-R226)
[[5]](diffhunk://#diff-12918e90451cdedb78571b9a67ac0313331a25175cebb606b7108b7bf06af092L230-R241)

### Configuration Initialization:
*
[`src/functions/private/Config/Initialize-GitHubConfig.ps1`](diffhunk://#diff-0bd6f61981cdae153b550552b394da11c794e8ad8ae819fbb7bb702022a02e5dR1-R36):
Added a new function `Initialize-GitHubConfig` to initialize GitHub
configuration settings.

### Utility Enhancements:
*
[`src/functions/private/Utilities/PowerShell/Get-FunctionParameter.ps1`](diffhunk://#diff-afa78d5c608d4346e2ff36f1459e8e48966e192179f7689980cf44e978ab74bfL26-R26):
Enhanced the `Get-FunctionParameter` function to optionally return
parameters as a hashtable.
[[1]](diffhunk://#diff-afa78d5c608d4346e2ff36f1459e8e48966e192179f7689980cf44e978ab74bfL26-R26)
[[2]](diffhunk://#diff-afa78d5c608d4346e2ff36f1459e8e48966e192179f7689980cf44e978ab74bfL40-R44)
[[3]](diffhunk://#diff-afa78d5c608d4346e2ff36f1459e8e48966e192179f7689980cf44e978ab74bfR78-R81)

### Workflow Update:
*
[`.github/workflows/Linter.yml`](diffhunk://#diff-482e65806ed9e4a7320f14964764086b91fed4a28d12e4efde1776472e147e79R34):
Skipping validation for PowerShell scripts in the linter workflow.

## Type of change

<!-- Use the check-boxes [x] on the options that are relevant. -->

- [ ] 📖 [Docs]
- [ ] 🪲 [Fix]
- [ ] 🩹 [Patch]
- [ ] ⚠️ [Security fix]
- [x] 🚀 [Feature]
- [ ] 🌟 [Breaking change]

## Checklist

<!-- Use the check-boxes [x] on the options that are relevant. -->

- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
  • Loading branch information
MariusStorhaug authored Dec 9, 2024
1 parent acd573f commit c11742e
Show file tree
Hide file tree
Showing 34 changed files with 728 additions and 745 deletions.
8 changes: 4 additions & 4 deletions .github/linters/.powershell-psscriptanalyzer.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
@{
#CustomRulePath='path\to\CustomRuleModule.psm1'
#RecurseCustomRulePath='path\of\customrules'
#Severity = @(
# 'Error'
# 'Warning'
#)
# Severity = @(
# 'Error'
# 'Warning'
# )
#IncludeDefaultRules=${true}
ExcludeRules = @(
'PSMissingModuleManifestField'
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/Linter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ jobs:
VALIDATE_MARKDOWN_PRETTIER: false
VALIDATE_YAML_PRETTIER: false
VALIDATE_GITLEAKS: false
VALIDATE_POWERSHELL: false # Added due to class usage in the project... TypeNotFound
19 changes: 19 additions & 0 deletions src/classes/public/Config/GitHubConfig.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class GitHubConfig : Context {
# The access token grace period in hours.
[int] $AccessTokenGracePeriodInHours

# The default context.
[string] $DefaultContext

# The default GitHub App client ID.
[string] $GitHubAppClientID

# The default host name.
[string] $HostName

# The default OAuth app client ID.
[string] $OAuthAppClientID

# Simple parameterless constructor
GitHubConfig() {}
}
58 changes: 58 additions & 0 deletions src/classes/public/Context/GitHubContext.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
class GitHubContext : Context {
# The GitHub Context Name.
# HostName/Username or HostName/AppSlug
# github.com/Octocat
[string] $Name

# The context type
# User / App / Installation
[string] $Type

# The API hostname.
# github.com / msx.ghe.com / github.local
[string] $HostName

# The API base URI.
# https://api.github.com
[string] $ApiBaseUri

# The GitHub API version.
# 2022-11-28
[string] $ApiVersion

# The authentication type.
# UAT / PAT / App / IAT
[string] $AuthType

# User ID / App ID as GraphQL Node ID
[string] $NodeID

# The Database ID of the context.
[string] $DatabaseID

# The user name.
[string] $UserName

# The access token.
[securestring] $Token

# The token type.
# ghu / gho / ghp / github_pat / PEM / ghs /
[string] $TokenType

# The default value for the Enterprise parameter.
[string] $Enterprise

# The default value for the Owner parameter.
[string] $Owner

# The default value for the Repo parameter.
[string] $Repo

# Simple parameterless constructor
GitHubContext() {}

[string] ToString() {
return $this.Name
}
}
18 changes: 18 additions & 0 deletions src/classes/public/Context/GitHubContext/AppGitHubContext.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class AppGitHubContext : GitHubContext {
# Client ID for GitHub Apps
[string] $ClientID

# Creates a context object from a hashtable of key-vaule pairs.
AppGitHubContext([hashtable]$Properties) {
foreach ($Property in $Properties.Keys) {
$this.$Property = $Properties.$Property
}
}

# Creates a context object from a PSCustomObject.
AppGitHubContext([PSCustomObject]$Object) {
$Object.PSObject.Properties | ForEach-Object {
$this.($_.Name) = $_.Value
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class InstallationGitHubContext : GitHubContext {
# Client ID for GitHub Apps
[string] $ClientID

# The token expiration date.
# 2024-01-01-00:00:00
[datetime] $TokenExpirationDate

# The installation ID.
[int] $InstallationID

# Creates a context object from a hashtable of key-vaule pairs.
InstallationGitHubContext([hashtable]$Properties) {
foreach ($Property in $Properties.Keys) {
$this.$Property = $Properties.$Property
}
}

# Creates a context object from a PSCustomObject.
InstallationGitHubContext([PSCustomObject]$Object) {
$Object.PSObject.Properties | ForEach-Object {
$this.($_.Name) = $_.Value
}
}
}
38 changes: 38 additions & 0 deletions src/classes/public/Context/GitHubContext/UserGitHubContext.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class UserGitHubContext : GitHubContext {
# The authentication client ID.
# Client ID for UAT
[string] $AuthClientID

# The device flow type.
# GitHubApp / OAuthApp
[string] $DeviceFlowType

# The scope when authenticating with OAuth.
# 'gist read:org repo workflow'
[string] $Scope

# The token expiration date.
# 2024-01-01-00:00:00
[datetime] $TokenExpirationDate

# The refresh token.
[securestring] $RefreshToken

# The refresh token expiration date.
# 2024-01-01-00:00:00
[datetime] $RefreshTokenExpirationDate

# Creates a context object from a hashtable of key-vaule pairs.
UserGitHubContext([hashtable]$Properties) {
foreach ($Property in $Properties.Keys) {
$this.$Property = $Properties.$Property
}
}

# Creates a context object from a PSCustomObject.
UserGitHubContext([PSCustomObject]$Object) {
$Object.PSObject.Properties | ForEach-Object {
$this.($_.Name) = $_.Value
}
}
}
105 changes: 0 additions & 105 deletions src/classes/public/GitHubContext.ps1

This file was deleted.

31 changes: 17 additions & 14 deletions src/functions/private/Auth/Context/Resolve-GitHubContext.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -33,32 +33,35 @@
$commandName = $MyInvocation.MyCommand.Name
Write-Verbose "[$commandName] - Start"
Write-Verbose 'Context:'
$Context | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
$Context | Format-Table | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
}

process {
if ($Context -is [string]) {
$contextName = $Context
Write-Debug "Getting context: [$contextName]"
Write-Verbose "Getting context: [$contextName]"
$Context = Get-GitHubContext -Context $contextName
}

if (-not $Context) {
throw "Context [$contextName] not found. Please provide a valid context or log in using 'Connect-GitHub'."
}

switch ($Context.Type) {
'App' {
$availableContexts = Get-GitHubContext -ListAvailable |
Where-Object { $_.Type -eq 'Installation' -and $_.ClientID -eq $Context.ClientID }
$params = Get-FunctionParameter -Scope 2
Write-Verbose 'Resolving parameters used in called function'
Write-Verbose ($params | Out-String)
if ($params.Keys -in 'Owner', 'Organization') {
$Context = $availableContexts | Where-Object { $_.Owner -eq $params.Owner }
}
}
}
# switch ($Context.Type) {
# 'App' {
# $availableContexts = Get-GitHubContext -ListAvailable |
# Where-Object { $_.Type -eq 'Installation' -and $_.ClientID -eq $Context.ClientID }
# $params = Get-FunctionParameter -Scope 2
# Write-Verbose 'Resolving parameters used in called function'
# Write-Verbose ($params | Out-String)
# if ($params.Keys -in 'Owner', 'Organization') {
# $Context = $availableContexts | Where-Object { $_.Owner -eq $params.Owner }
# }
# }
# }

Write-Verbose 'Resolved Context:'
$Context | Out-String -Stream | ForEach-Object { Write-Verbose $_ }
}

end {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,9 @@
)

$Context = Resolve-GitHubContext -Context $Context

$gitHubConfig = Get-GitHubConfig
$tokenExpirationDate = $Context.TokenExpirationDate
$currentDateTime = Get-Date
$remainingDuration = [datetime]$tokenExpirationDate - $currentDateTime

# If the remaining time is less that $script:Auth.AccessTokenGracePeriodInHours then the token should be refreshed
$remainingDuration.TotalHours -lt $gitHubConfig.AccessTokenGracePeriodInHours
$remainingDuration.TotalHours -lt $script:GitHub.Config.AccessTokenGracePeriodInHours
}
36 changes: 36 additions & 0 deletions src/functions/private/Config/Initialize-GitHubConfig.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
function Initialize-GitHubConfig {
<#
.SYNOPSIS
.DESCRIPTION
.EXAMPLE
Initialize-GitHubConfig
#>
[OutputType([void])]
[CmdletBinding()]
param ()

begin {
$commandName = $MyInvocation.MyCommand.Name
Write-Debug "[$commandName] - Start"
}

process {
try {
$context = [GitHubConfig](Get-Context -ID $script:GitHub.Config.ID)
if (-not $context) {
$context = Set-Context -ID $script:GitHub.Config.ID -Context $script:GitHub.Config -PassThru
}
$script:GitHub.Config = [GitHubConfig]$context
$script:GitHub.Initialized = $true
} catch {
Write-Error $_
throw 'Failed to initialize GitHub config'
}
}

end {
Write-Debug "[$commandName] - End"
}
}
Loading

0 comments on commit c11742e

Please sign in to comment.