Skip to content

Commit 1b4773a

Browse files
🩹 [Patch]: Add a dynamically format property for GitHubContext (#449)
## Description This pull request introduces a new `Remaining` property to GitHub context types and updates the display format to show the time remaining until token expiration. The changes improve the clarity and usability of token expiration information by providing both textual and color-coded visual indicators. ### Enhancements to GitHub context display: * **Added a new column for `Remaining` in the table display**: - Updated `src/formats/GitHubContext.Format.ps1xml` to include a `Remaining` column header and display logic for the time remaining until token expiration. The display uses a color-coded system based on the ratio of remaining time to the maximum allowed duration, enhancing visual clarity. [[1]](diffhunk://#diff-c7dd80cd4c4440ccbe24930842a2e172614dbfd79d31393d68852200eacc2c74R29-R31) [[2]](diffhunk://#diff-c7dd80cd4c4440ccbe24930842a2e172614dbfd79d31393d68852200eacc2c74R55-R97) ### GitHub context types improvements: * **Introduced the `Remaining` property for token expiration**: - Added a `Remaining` script property to both `InstallationGitHubContext` and `UserGitHubContext` types in `src/types/GitHubContext.Types.ps1xml`. This property calculates the time span between the current date and the token expiration date, enabling the new display functionality. ## Type of change <!-- Use the check-boxes [x] on the options that are relevant. --> - [ ] 📖 [Docs] - [ ] 🪲 [Fix] - [x] 🩹 [Patch] - [ ] ⚠️ [Security fix] - [ ] 🚀 [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
1 parent a2e49c2 commit 1b4773a

File tree

8 files changed

+183
-50
lines changed

8 files changed

+183
-50
lines changed

src/classes/public/Context/GitHubContext.ps1

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,29 @@
6262
# The default value for the 'per_page' API parameter used in 'GET' functions that support paging.
6363
[int] $PerPage
6464

65-
# Simple parameterless constructor
6665
GitHubContext() {}
6766

67+
GitHubContext([pscustomobject]$Object) {
68+
$this.ID = $Object.ID
69+
$this.Name = $Object.Name
70+
$this.DisplayName = $Object.DisplayName
71+
$this.Type = $Object.Type
72+
$this.HostName = $Object.HostName
73+
$this.ApiBaseUri = $Object.ApiBaseUri
74+
$this.ApiVersion = $Object.ApiVersion
75+
$this.AuthType = $Object.AuthType
76+
$this.NodeID = $Object.NodeID
77+
$this.DatabaseID = $Object.DatabaseID
78+
$this.UserName = $Object.UserName
79+
$this.Token = $Object.Token
80+
$this.TokenType = $Object.TokenType
81+
$this.Enterprise = $Object.Enterprise
82+
$this.Owner = $Object.Owner
83+
$this.Repository = $Object.Repository
84+
$this.HttpVersion = $Object.HttpVersion
85+
$this.PerPage = $Object.PerPage
86+
}
87+
6888
[string] ToString() {
6989
return $this.Name
7090
}

src/classes/public/Context/GitHubContext/AppGitHubContext.ps1

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,31 @@
1414
# The events that the app is subscribing to once installed
1515
[string[]] $Events
1616

17-
# Simple parameterless constructor
1817
AppGitHubContext() {}
1918

20-
# Creates a context object from a hashtable of key-vaule pairs.
21-
AppGitHubContext([hashtable]$Properties) {
22-
foreach ($Property in $Properties.Keys) {
23-
$this.$Property = $Properties.$Property
24-
}
25-
}
26-
27-
# Creates a context object from a PSCustomObject.
28-
AppGitHubContext([PSCustomObject]$Object) {
29-
$Object.PSObject.Properties | ForEach-Object {
30-
$this.($_.Name) = $_.Value
31-
}
19+
AppGitHubContext([pscustomobject]$Object) {
20+
$this.ID = $Object.ID
21+
$this.Name = $Object.Name
22+
$this.DisplayName = $Object.DisplayName
23+
$this.Type = $Object.Type
24+
$this.HostName = $Object.HostName
25+
$this.ApiBaseUri = $Object.ApiBaseUri
26+
$this.ApiVersion = $Object.ApiVersion
27+
$this.AuthType = $Object.AuthType
28+
$this.NodeID = $Object.NodeID
29+
$this.DatabaseID = $Object.DatabaseID
30+
$this.UserName = $Object.UserName
31+
$this.Token = $Object.Token
32+
$this.TokenType = $Object.TokenType
33+
$this.Enterprise = $Object.Enterprise
34+
$this.Owner = $Object.Owner
35+
$this.Repository = $Object.Repository
36+
$this.HttpVersion = $Object.HttpVersion
37+
$this.PerPage = $Object.PerPage
38+
$this.ClientID = $Object.ClientID
39+
$this.OwnerName = $Object.OwnerName
40+
$this.OwnerType = $Object.OwnerType
41+
$this.Permissions = $Object.Permissions
42+
$this.Events = $Object.Events
3243
}
3344
}

src/classes/public/Context/GitHubContext/InstallationGitHubContext.ps1

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
# The token expiration date.
66
# 2024-01-01-00:00:00
7-
[datetime] $TokenExpirationDate
7+
[System.Nullable[datetime]] $TokenExpirationDate
88

99
# The installation ID.
10-
[uint64] $InstallationID
10+
[System.Nullable[uint64]] $InstallationID
1111

1212
# The permissions that the app is requesting on the target
1313
[pscustomobject] $Permissions
@@ -21,20 +21,33 @@
2121
# The target login or slug of the installation.
2222
[string] $InstallationName
2323

24-
# Simple parameterless constructor
2524
InstallationGitHubContext() {}
2625

27-
# Creates a context object from a hashtable of key-vaule pairs.
28-
InstallationGitHubContext([hashtable]$Properties) {
29-
foreach ($Property in $Properties.Keys) {
30-
$this.$Property = $Properties.$Property
31-
}
32-
}
33-
34-
# Creates a context object from a PSCustomObject.
35-
InstallationGitHubContext([PSCustomObject]$Object) {
36-
$Object.PSObject.Properties | ForEach-Object {
37-
$this.($_.Name) = $_.Value
38-
}
26+
InstallationGitHubContext([pscustomobject]$Object) {
27+
$this.ID = $Object.ID
28+
$this.Name = $Object.Name
29+
$this.DisplayName = $Object.DisplayName
30+
$this.Type = $Object.Type
31+
$this.HostName = $Object.HostName
32+
$this.ApiBaseUri = $Object.ApiBaseUri
33+
$this.ApiVersion = $Object.ApiVersion
34+
$this.AuthType = $Object.AuthType
35+
$this.NodeID = $Object.NodeID
36+
$this.DatabaseID = $Object.DatabaseID
37+
$this.UserName = $Object.UserName
38+
$this.Token = $Object.Token
39+
$this.TokenType = $Object.TokenType
40+
$this.Enterprise = $Object.Enterprise
41+
$this.Owner = $Object.Owner
42+
$this.Repository = $Object.Repository
43+
$this.HttpVersion = $Object.HttpVersion
44+
$this.PerPage = $Object.PerPage
45+
$this.ClientID = $Object.ClientID
46+
$this.TokenExpirationDate = $Object.TokenExpirationDate
47+
$this.InstallationID = $Object.InstallationID
48+
$this.Permissions = $Object.Permissions
49+
$this.Events = $Object.Events
50+
$this.InstallationType = $Object.InstallationType
51+
$this.InstallationName = $Object.InstallationName
3952
}
4053
}

src/classes/public/Context/GitHubContext/UserGitHubContext.ps1

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,41 @@
1313

1414
# The token expiration date.
1515
# 2024-01-01-00:00:00
16-
[datetime] $TokenExpirationDate
16+
[System.Nullable[datetime]] $TokenExpirationDate
1717

1818
# The refresh token.
1919
[securestring] $RefreshToken
2020

2121
# The refresh token expiration date.
2222
# 2024-01-01-00:00:00
23-
[datetime] $RefreshTokenExpirationDate
23+
[System.Nullable[datetime]] $RefreshTokenExpirationDate
2424

25-
# Simple parameterless constructor
2625
UserGitHubContext() {}
2726

28-
# Creates a context object from a hashtable of key-vaule pairs.
29-
UserGitHubContext([hashtable]$Properties) {
30-
foreach ($Property in $Properties.Keys) {
31-
$this.$Property = $Properties.$Property
32-
}
33-
}
34-
35-
# Creates a context object from a PSCustomObject.
3627
UserGitHubContext([PSCustomObject]$Object) {
37-
$Object.PSObject.Properties | ForEach-Object {
38-
$this.($_.Name) = $_.Value
39-
}
28+
$this.ID = $Object.ID
29+
$this.Name = $Object.Name
30+
$this.DisplayName = $Object.DisplayName
31+
$this.Type = $Object.Type
32+
$this.HostName = $Object.HostName
33+
$this.ApiBaseUri = $Object.ApiBaseUri
34+
$this.ApiVersion = $Object.ApiVersion
35+
$this.AuthType = $Object.AuthType
36+
$this.NodeID = $Object.NodeID
37+
$this.DatabaseID = $Object.DatabaseID
38+
$this.UserName = $Object.UserName
39+
$this.Token = $Object.Token
40+
$this.TokenType = $Object.TokenType
41+
$this.Enterprise = $Object.Enterprise
42+
$this.Owner = $Object.Owner
43+
$this.Repository = $Object.Repository
44+
$this.HttpVersion = $Object.HttpVersion
45+
$this.PerPage = $Object.PerPage
46+
$this.AuthClientID = $Object.AuthClientID
47+
$this.DeviceFlowType = $Object.DeviceFlowType
48+
$this.Scope = $Object.Scope
49+
$this.TokenExpirationDate = $Object.TokenExpirationDate
50+
$this.RefreshToken = $Object.RefreshToken
51+
$this.RefreshTokenExpirationDate = $Object.RefreshTokenExpirationDate
4052
}
4153
}

src/formats/GitHubContext.Format.ps1xml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
<TableColumnHeader>
2727
<Label>TokenExpirationDate</Label>
2828
</TableColumnHeader>
29+
<TableColumnHeader>
30+
<Label>Remaining</Label>
31+
</TableColumnHeader>
2932
</TableHeaders>
3033
<TableRowEntries>
3134
<TableRowEntry>
@@ -49,6 +52,51 @@
4952
<TableColumnItem>
5053
<PropertyName>TokenExpirationDate</PropertyName>
5154
</TableColumnItem>
55+
<TableColumnItem>
56+
<ScriptBlock>
57+
if ($null -eq $_.Remaining) {
58+
return
59+
}
60+
61+
if ($_.Remaining -lt 0) {
62+
$text = "Expired"
63+
} else {
64+
$text = "$($_.Remaining.Hours)h $($_.Remaining.Minutes)m $($_.Remaining.Seconds)s"
65+
}
66+
67+
if ($Host.UI.SupportsVirtualTerminal -and
68+
($env:GITHUB_ACTIONS -ne 'true')) {
69+
switch ($_.AuthType) {
70+
'UAT' {
71+
$MaxValue = [TimeSpan]::FromHours(8)
72+
}
73+
'IAT' {
74+
$MaxValue = [TimeSpan]::FromHours(1)
75+
}
76+
}
77+
$ratio = [Math]::Min(($_.Remaining / $MaxValue), 1)
78+
79+
if ($ratio -ge 1) {
80+
$r = 0
81+
$g = 255
82+
} elseif ($ratio -le 0) {
83+
$r = 255
84+
$g = 0
85+
} elseif ($ratio -ge 0.5) {
86+
$r = [Math]::Round(255 * (2 - 2 * $ratio))
87+
$g = 255
88+
} else {
89+
$r = 255
90+
$g = [Math]::Round(255 * (2 * $ratio))
91+
}
92+
$b = 0
93+
$color = $PSStyle.Foreground.FromRgb($r, $g, $b)
94+
"$color$text$($PSStyle.Reset)"
95+
} else {
96+
$text
97+
}
98+
</ScriptBlock>
99+
</TableColumnItem>
52100
</TableColumnItems>
53101
</TableRowEntry>
54102
</TableRowEntries>

src/functions/private/Auth/Context/Resolve-GitHubContext.ps1

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@
4545
Write-Verbose "Anonymous: [$Anonymous]"
4646
if ($Anonymous -or $Context -eq 'Anonymous') {
4747
Write-Verbose 'Returning Anonymous context.'
48-
return [GitHubContext]@{
49-
Name = 'Anonymous'
50-
AuthType = 'Anonymous'
51-
}
48+
return [GitHubContext]::new(
49+
[pscustomobject]@{
50+
Name = 'Anonymous'
51+
AuthType = 'Anonymous'
52+
}
53+
)
5254
}
5355

5456
if ($Context -is [string]) {

src/functions/public/Auth/Context/Get-GitHubContext.ps1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,13 @@
7373
Write-Verbose "Converting to: [$($contextObj.Type)GitHubContext]"
7474
switch ($contextObj.Type) {
7575
'User' {
76-
[UserGitHubContext]::new($contextObj)
76+
[UserGitHubContext]::new([pscustomobject]$contextObj)
7777
}
7878
'App' {
79-
[AppGitHubContext]::new($contextObj)
79+
[AppGitHubContext]::new([pscustomobject]$contextObj)
8080
}
8181
'Installation' {
82-
[InstallationGitHubContext]::new($contextObj)
82+
[InstallationGitHubContext]::new([pscustomobject]$contextObj)
8383
}
8484
default {
8585
throw "Unknown context type: [$($contextObj.Type)]"

src/types/GitHubContext.Types.ps1xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Types>
3+
<Type>
4+
<Name>UserGitHubContext</Name>
5+
<Members>
6+
<ScriptProperty>
7+
<Name>Remaining</Name>
8+
<GetScriptBlock>
9+
if ($null -eq $this.TokenExpirationDate) { return }
10+
New-TimeSpan -Start (Get-Date) -End $this.TokenExpirationDate
11+
</GetScriptBlock>
12+
</ScriptProperty>
13+
</Members>
14+
</Type>
15+
<Type>
16+
<Name>InstallationGitHubContext</Name>
17+
<Members>
18+
<ScriptProperty>
19+
<Name>Remaining</Name>
20+
<GetScriptBlock>
21+
if ($null -eq $this.TokenExpirationDate) { return }
22+
New-TimeSpan -Start (Get-Date) -End $this.TokenExpirationDate
23+
</GetScriptBlock>
24+
</ScriptProperty>
25+
</Members>
26+
</Type>
27+
</Types>

0 commit comments

Comments
 (0)