Skip to content

Commit 86a4d36

Browse files
committed
20220625A
1 parent d4dd134 commit 86a4d36

File tree

10 files changed

+224
-19
lines changed

10 files changed

+224
-19
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ Import-Module -Name 'hugoalh.GitHubActionsToolkit' -Prefix 'GitHubActions' -Scop
7272
- `Import-GitHubActionsArtifact` 🧪
7373
- `Remove-GitHubActionsProblemMatcher`
7474
- `Remove-GitHubActionsStepSummary`
75+
- `Restore-GitHubActionsCache` 🧪
76+
- `Save-GitHubActionsCache` 🧪
7577
- `Set-GitHubActionsEnvironmentVariable`
7678
- `Set-GitHubActionsOutput`
7779
- `Set-GitHubActionsState`

hugoalh.GitHubActionsToolkit/hugoalh.GitHubActionsToolkit.psd1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@
8787
'Import-Artifact',
8888
'Remove-ProblemMatcher',
8989
'Remove-StepSummary',
90+
'Restore-Cache',
91+
'Save-Cache',
9092
'Set-EnvironmentVariable',
9193
'Set-Output',
9294
'Set-State',
@@ -147,12 +149,14 @@
147149
'Enable-ProcessingCommand',
148150
'Enter-Group',
149151
'Exit-Group',
152+
'Export-Cache',
150153
'Get-Event',
151154
'Get-OidcToken',
152155
'Get-Payload',
153156
'Get-WebhookEvent',
154157
'Get-WebhookPayload',
155158
'Get-WorkflowRunUrl',
159+
'Import-Cache',
156160
'Restore-Artifact',
157161
'Restore-State',
158162
'Save-Artifact',

hugoalh.GitHubActionsToolkit/hugoalh.GitHubActionsToolkit.psm1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
[String[]]$ModulesNames = @(
55
'command-base',
66
'artifact',
7+
'cache',
78
'command-control',
89
'environment-variable',
910
'log',

hugoalh.GitHubActionsToolkit/module/artifact.psm1

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Import-Module -Name @(
88
.SYNOPSIS
99
GitHub Actions - Export Artifact
1010
.DESCRIPTION
11-
Export artifact to persist data after a job has completed, and share that data with another job in the same workflow.
11+
Export artifact to persist data and/or share with another job in the same workflow.
1212
.PARAMETER Name
1313
Artifact name.
1414
.PARAMETER Path
@@ -35,10 +35,11 @@ Function Export-Artifact {
3535
[Parameter(Mandatory = $True, ParameterSetName = 'LiteralPath', ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)][Alias('LiteralFile', 'LiteralFiles', 'LiteralPaths', 'LP', 'PSPath', 'PSPaths')][String[]]$LiteralPath,
3636
[Alias('Root')][String]$BaseRoot = $Env:GITHUB_WORKSPACE,
3737
[Alias('ContinueOnError', 'ContinueOnIssue', 'ContinueOnIssues', 'IgnoreIssuePath')][Switch]$IgnoreIssuePaths,
38-
[Alias('RetentionDay')][ValidateRange(1, 90)][Byte]$RetentionTime
38+
[ValidateRange(1, 90)][AllowNull()][Alias('RetentionDay')][Byte]$RetentionTime = $Null
3939
)
4040
Begin {
4141
If (
42+
$Null -ieq $BaseRoot -or
4243
![System.IO.Path]::IsPathRooted($BaseRoot) -or
4344
!(Test-Path -LiteralPath $BaseRoot -PathType 'Container')
4445
) {
@@ -196,35 +197,35 @@ Set-Alias -Name 'Restore-Artifact' -Value 'Import-Artifact' -Option 'ReadOnly' -
196197
.SYNOPSIS
197198
GitHub Actions (Internal) - Test Artifact Name
198199
.DESCRIPTION
199-
Test artifact name whether is valid.
200+
Test GitHub Actions artifact name whether is valid.
200201
.PARAMETER InputObject
201-
Artifact name that need to test.
202+
GitHub Actions artifact name that need to test.
202203
.OUTPUTS
203204
[Boolean] Test result.
204205
#>
205206
Function Test-ArtifactName {
206207
[CmdletBinding()]
207208
[OutputType([Boolean])]
208209
Param (
209-
[Parameter(Mandatory = $True, Position = 0)][Alias('Input', 'Object')][String]$InputObject
210+
[Parameter(Mandatory = $True, Position = 0)][AllowEmptyString()][Alias('Input', 'Object')][String]$InputObject
210211
)
211212
Return ((Test-ArtifactPath -InputObject $InputObject) -and $InputObject -imatch '^[^\\/]+$')
212213
}
213214
<#
214215
.SYNOPSIS
215216
GitHub Actions (Internal) - Test Artifact Path
216217
.DESCRIPTION
217-
Test artifact path whether is valid.
218+
Test GitHub Actions artifact path whether is valid.
218219
.PARAMETER InputObject
219-
Artifact path that need to test.
220+
GitHub Actions artifact path that need to test.
220221
.OUTPUTS
221222
[Boolean] Test result.
222223
#>
223224
Function Test-ArtifactPath {
224225
[CmdletBinding()]
225226
[OutputType([Boolean])]
226227
Param (
227-
[Parameter(Mandatory = $True, Position = 0)][Alias('Input', 'Object')][String]$InputObject
228+
[Parameter(Mandatory = $True, Position = 0)][AllowEmptyString()][Alias('Input', 'Object')][String]$InputObject
228229
)
229230
Return ($InputObject -imatch '^[^":<>|*?\n\r\t]+$')
230231
}
Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#Requires -PSEdition Core
2+
#Requires -Version 7.2
3+
Import-Module -Name @(
4+
(Join-Path -Path $PSScriptRoot -ChildPath 'nodejs-invoke.psm1'),
5+
(Join-Path -Path $PSScriptRoot -ChildPath 'utility.psm1')
6+
) -Prefix 'GitHubActions' -Scope 'Local'
7+
<#
8+
.SYNOPSIS
9+
GitHub Actions - Restore Cache
10+
.DESCRIPTION
11+
Restore cache that shared data from previous job in the same workflow.
12+
.PARAMETER Key
13+
Cache key.
14+
.PARAMETER Path
15+
Cache destination path.
16+
.PARAMETER LiteralPath
17+
Cache destination literal path.
18+
.PARAMETER NotUseAzureSdk
19+
Do not use Azure Blob SDK to download caches that are stored on Azure Blob Storage, this maybe affect reliability and performance.
20+
.PARAMETER DownloadConcurrency
21+
Number of parallel downloads (only for Azure SDK).
22+
.PARAMETER Timeout
23+
Maximum time for each download request by seconds (only for Azure SDK).
24+
.OUTPUTS
25+
[String] The key of the cache hit.
26+
#>
27+
Function Restore-Cache {
28+
[CmdletBinding(DefaultParameterSetName = 'Path', HelpUri = 'https://github.com/hugoalh-studio/ghactions-toolkit-powershell/wiki/api_function_restore-githubactionscache#Restore-GitHubActionsCache')]
29+
[OutputType([String])]
30+
Param (
31+
[Parameter(Mandatory = $True, Position = 0)][ValidateScript({
32+
Return (Test-CacheKey -InputObject $_)
33+
}, ErrorMessage = '`{0}` is not a valid GitHub Actions cache key, and/or more than 512 characters!')][Alias('Keys', 'Name', 'Names')][String[]]$Key,
34+
[Parameter(Mandatory = $True, ParameterSetName = 'Path', Position = 1, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)][SupportsWildcards()][Alias('File', 'Files', 'Paths')][String[]]$Path,
35+
[Parameter(Mandatory = $True, ParameterSetName = 'LiteralPath', ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)][Alias('LiteralFile', 'LiteralFiles', 'LiteralPaths', 'LP', 'PSPath', 'PSPaths')][String[]]$LiteralPath,
36+
[Alias('NoAzureSdk')][Switch]$NotUseAzureSdk,
37+
[ValidateRange(1, 16)][AllowNull()][Byte]$DownloadConcurrency = $Null,
38+
[ValidateRange(5, 900)][AllowNull()][UInt16]$Timeout = $Null
39+
)
40+
Begin {
41+
[String[]]$PathsProceed = @()
42+
}
43+
Process {
44+
Switch ($PSCmdlet.ParameterSetName) {
45+
'Path' {
46+
$PathsProceed += $Path
47+
}
48+
'LiteralPath' {
49+
$PathsProceed += ($LiteralPath | ForEach-Object -Process {
50+
Return [WildcardPattern]::Escape($_)
51+
})
52+
}
53+
}
54+
}
55+
End {
56+
If (!(Test-GitHubActionsEnvironment -Cache)) {
57+
Return (Write-Error -Message 'Unable to get GitHub Actions cache resources!' -Category 'ResourceUnavailable')
58+
}
59+
[String[]]$KeysProceed = @()
60+
If ($Key.Count -igt 10) {
61+
Write-Warning -Message "Keys are limit to maximum count of 10! Only first 10 keys will use."
62+
$KeysProceed += ($Key | Select-Object -First 10)
63+
} Else {
64+
$KeysProceed += $Key
65+
}
66+
If ($PathsProceed.Count -ieq 0) {
67+
Return (Write-Error -Message 'No valid path is defined!' -Category 'NotSpecified')
68+
}
69+
[Hashtable]$InputObject = @{
70+
Path = $PathsProceed
71+
PrimaryKey = $KeysProceed[0]
72+
RestoreKey = ($KeysProceed | Select-Object -SkipIndex 0)
73+
UseAzureSdk = !$NotUseAzureSdk.IsPresent
74+
}
75+
If (!$NotUseAzureSdk.IsPresent) {
76+
If ($Null -ine $DownloadConcurrency) {
77+
$InputObject.DownloadConcurrency = $DownloadConcurrency
78+
}
79+
If ($Null -ine $Timeout) {
80+
$InputObject.Timeout = $Timeout * 1000
81+
}
82+
}
83+
$ResultRaw = Invoke-GitHubActionsNodeJsWrapper -Path 'cache\restore.js' -InputObject ([PSCustomObject]$InputObject | ConvertTo-Json -Depth 100 -Compress)
84+
If ($ResultRaw -ieq $False) {
85+
Return
86+
}
87+
Return ($ResultRaw | ConvertFrom-Json -Depth 100).CacheKey
88+
}
89+
}
90+
Set-Alias -Name 'Import-Cache' -Value 'Restore-Cache' -Option 'ReadOnly' -Scope 'Local'
91+
<#
92+
.SYNOPSIS
93+
GitHub Actions - Save cache
94+
.DESCRIPTION
95+
Save cache to persist data and/or share with another job in the same workflow.
96+
.PARAMETER Key
97+
Cache key.
98+
.PARAMETER Path
99+
Cache path.
100+
.PARAMETER LiteralPath
101+
Cache literal path.
102+
.PARAMETER UploadChunkSizes
103+
Maximum chunk size by bytes.
104+
.PARAMETER UploadConcurrency
105+
Number of parallel uploads.
106+
.OUTPUTS
107+
[String] Cache ID.
108+
#>
109+
Function Save-Cache {
110+
[CmdletBinding(DefaultParameterSetName = 'Path', HelpUri = 'https://github.com/hugoalh-studio/ghactions-toolkit-powershell/wiki/api_function_save-githubactionscache#Save-GitHubActionsCache')]
111+
[OutputType([String])]
112+
Param (
113+
[Parameter(Mandatory = $True, Position = 0)][ValidateScript({
114+
Return (Test-CacheKey -InputObject $_)
115+
}, ErrorMessage = '`{0}` is not a valid GitHub Actions cache key, and/or more than 512 characters!')][Alias('Name')][String]$Key,
116+
[Parameter(Mandatory = $True, ParameterSetName = 'Path', Position = 1, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)][SupportsWildcards()][Alias('File', 'Files', 'Paths')][String[]]$Path,
117+
[Parameter(Mandatory = $True, ParameterSetName = 'LiteralPath', ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)][Alias('LiteralFile', 'LiteralFiles', 'LiteralPaths', 'LP', 'PSPath', 'PSPaths')][String[]]$LiteralPath,
118+
[ValidateRange(1KB, 1GB)][AllowNull()][UInt32]$UploadChunkSizes = $Null,
119+
[ValidateRange(1, 16)][AllowNull()][Byte]$UploadConcurrency = $Null
120+
)
121+
Begin {
122+
[String[]]$PathsProceed = @()
123+
}
124+
Process {
125+
Switch ($PSCmdlet.ParameterSetName) {
126+
'Path' {
127+
$PathsProceed += $Path
128+
}
129+
'LiteralPath' {
130+
$PathsProceed += ($LiteralPath | ForEach-Object -Process {
131+
Return [WildcardPattern]::Escape($_)
132+
})
133+
}
134+
}
135+
}
136+
End {
137+
If (!(Test-GitHubActionsEnvironment -Cache)) {
138+
Return (Write-Error -Message 'Unable to get GitHub Actions cache resources!' -Category 'ResourceUnavailable')
139+
}
140+
If ($PathsProceed.Count -ieq 0) {
141+
Return (Write-Error -Message 'No valid path is defined!' -Category 'NotSpecified')
142+
}
143+
[Hashtable]$InputObject = @{
144+
Key = $Key
145+
Path = $PathsProceed
146+
}
147+
If ($Null -ine $UploadChunkSizes) {
148+
$InputObject.UploadChunkSizes = $UploadChunkSizes
149+
}
150+
If ($Null -ine $UploadConcurrency) {
151+
$InputObject.UploadConcurrency = $UploadConcurrency
152+
}
153+
$ResultRaw = Invoke-GitHubActionsNodeJsWrapper -Path 'cache\save.js' -InputObject ([PSCustomObject]$InputObject | ConvertTo-Json -Depth 100 -Compress)
154+
If ($ResultRaw -ieq $False) {
155+
Return
156+
}
157+
Return ($ResultRaw | ConvertFrom-Json -Depth 100).CacheId
158+
}
159+
}
160+
Set-Alias -Name 'Export-Cache' -Value 'Save-Cache' -Option 'ReadOnly' -Scope 'Local'
161+
<#
162+
.SYNOPSIS
163+
GitHub Actions (Internal) - Test Cache Key
164+
.DESCRIPTION
165+
Test GitHub Actions cache key whether is valid.
166+
.PARAMETER InputObject
167+
GitHub Actions cache key that need to test.
168+
.OUTPUTS
169+
[Boolean] Test result.
170+
#>
171+
Function Test-CacheKey {
172+
[CmdletBinding()]
173+
[OutputType([Boolean])]
174+
Param (
175+
[Parameter(Mandatory = $True, Position = 0)][AllowEmptyString()][Alias('Input', 'Object')][String]$InputObject
176+
)
177+
Return ($InputObject.Length -ile 512 -and $InputObject -imatch '^[^,\n\r]+$')
178+
}
179+
Export-ModuleMember -Function @(
180+
'Restore-Cache',
181+
'Save-Cache'
182+
) -Alias @(
183+
'Export-Cache',
184+
'Import-Cache'
185+
)

hugoalh.GitHubActionsToolkit/module/command-control.psm1

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,17 @@ Set-Alias -Name 'Start-ProcessingCommands' -Value 'Enable-ProcessingCommands' -O
153153
.SYNOPSIS
154154
GitHub Actions (Internal) - Test Processing Commands End Token
155155
.DESCRIPTION
156-
Test processing commands end token whether is valid.
156+
Test GitHub Actions processing commands end token whether is valid.
157157
.PARAMETER InputObject
158-
Processing commands end token that need to test.
158+
GitHub Actions processing commands end token that need to test.
159159
.OUTPUTS
160160
[Boolean] Test result.
161161
#>
162162
Function Test-ProcessingCommandsEndToken {
163163
[CmdletBinding()]
164164
[OutputType([Boolean])]
165165
Param (
166-
[Parameter(Mandatory = $True, Position = 0)][Alias('Input', 'Object')][String]$InputObject
166+
[Parameter(Mandatory = $True, Position = 0)][AllowEmptyString()][Alias('Input', 'Object')][String]$InputObject
167167
)
168168
Return ($InputObject -imatch '^(?:[\da-z][\da-z_-]*)?[\da-z]$' -and $InputObject.Length -ige 4 -and $InputObject -inotin $GitHubActionsCommands)
169169
}

hugoalh.GitHubActionsToolkit/module/environment-variable.psm1

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Function Add-PATH {
3333
[String[]]$Result = @()
3434
}
3535
Process {
36-
ForEach ($Item In $Path) {
36+
ForEach ($Item In ($Path | Select-Object -Unique)) {
3737
If (!$NoValidator.IsPresent -and !(Test-Path -Path $Item -PathType 'Container' -IsValid)) {
3838
Write-Error -Message "``$Item`` is not a valid PATH!" -Category 'SyntaxError'
3939
Continue
@@ -43,7 +43,7 @@ Function Add-PATH {
4343
}
4444
End {
4545
If ($Result.Count -igt 0) {
46-
Switch ($Scope -isplit ', ') {
46+
Switch ($Scope.ToString() -isplit ', ') {
4747
{ $_ -icontains 'Current' } {
4848
[String[]]$PATHRaw = [System.Environment]::GetEnvironmentVariable('PATH') -isplit [System.IO.Path]::PathSeparator
4949
$PATHRaw += $Result
@@ -127,7 +127,7 @@ Function Set-EnvironmentVariable {
127127
End {
128128
If ($Result.Count -igt 0) {
129129
[PSCustomObject[]]$ResultEnumerator = $Result.GetEnumerator()
130-
Switch ($Scope -isplit ', ') {
130+
Switch ($Scope.ToString() -isplit ', ') {
131131
{ $_ -icontains 'Current' } {
132132
ForEach ($Item In $ResultEnumerator) {
133133
[System.Environment]::SetEnvironmentVariable($Item.Name, $Item.Value)
@@ -165,7 +165,7 @@ Function Test-EnvironmentVariableName {
165165
[CmdletBinding()]
166166
[OutputType([Boolean])]
167167
Param (
168-
[Parameter(Mandatory = $True, Position = 0)][Alias('Input', 'Object')][String]$InputObject
168+
[Parameter(Mandatory = $True, Position = 0)][AllowEmptyString()][Alias('Input', 'Object')][String]$InputObject
169169
)
170170
Return ($InputObject -imatch '^(?:[\da-z][\da-z_-]*)?[\da-z]$' -and $InputObject -inotmatch '^(?:CI|PATH)$' -and $InputObject -inotmatch '^(?:ACTIONS|GITHUB|RUNNER)_')
171171
}

hugoalh.GitHubActionsToolkit/module/nodejs-invoke.psm1

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,24 @@ Function Invoke-NodeJsWrapper {
3737
[String]$ResultSeparator = "====== $((New-Guid).Guid -ireplace '-', '') ======"
3838
Try {
3939
[String[]]$Result = Invoke-Expression -Command "node --no-deprecation --no-warnings `"$($WrapperFullName -ireplace '\\', '/')`" `"$($InputObject | ConvertTo-Json -Depth 100 -Compress)`" `"$ResultSeparator`""
40+
[UInt32]$ResultSkipIndex = @()
41+
for ($ResultIndex = 0; $ResultIndex -lt $Result.Count; $ResultIndex++) {
42+
[String]$Item = $Result[$ResultIndex]
43+
If (
44+
$Item -imatch '^::error' -or
45+
$Item -imatch '^::notice' -or
46+
$Item -imatch '^::warning'
47+
) {
48+
Write-Host -Object $Item
49+
$ResultSkipIndex += $ResultIndex
50+
}
51+
}
4052
If ($LASTEXITCODE -ine 0) {
41-
Throw "Unexpected error: $($Result -join "`n")"
53+
Throw "Unexpected last exit code ``$LASTEXITCODE``! $(($Result | Select-Object -SkipIndex $ResultSkipIndex) -join "`n")"
4254
}
4355
Return ($Result[($Result.IndexOf($ResultSeparator) + 1)..($Result.Count - 1)] -join "`n" | ConvertFrom-Json -Depth 100)
4456
} Catch {
45-
Write-Error -Message "Unable to execute wrapper ``$Path``! $_" -Category 'InvalidData'
57+
Write-Error -Message "Unable to successfully execute wrapper ``$Path``! $_" -Category 'InvalidData'
4658
Return $False
4759
}
4860
}

hugoalh.GitHubActionsToolkit/module/nodejs-test.psm1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Test the current machine whether has compatible NodeJS and NPM environment, and
1414
.PARAMETER ReinstallDependencies
1515
Force to reinstall dependencies even though available.
1616
.PARAMETER Retest
17-
Redo this test by ignore the cached test result.
17+
Redo this test, ignore the cached test result.
1818
.OUTPUTS
1919
[Boolean] Test result.
2020
#>

hugoalh.GitHubActionsToolkit/module/nodejs-wrapper/cache/save.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ const result = await ghactionsCacheSaveCache(input.Path, input.Key, {
1010
});
1111
console.log(process.argv[3]);
1212
console.log(JSON.stringify({
13-
CacheID: result
13+
CacheId: result
1414
}));
1515
process.exit(0);

0 commit comments

Comments
 (0)