Skip to content

Commit e4c453e

Browse files
committed
Smart wrapper
1 parent 34905d6 commit e4c453e

File tree

2 files changed

+169
-124
lines changed

2 files changed

+169
-124
lines changed

hugoalh.GitHubActionsToolkit/module/nodejs-wrapper.psm1

Lines changed: 165 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ Import-Module -Name (
66
) |
77
ForEach-Object -Process { Join-Path -Path $PSScriptRoot -ChildPath "$_.psm1" }
88
) -Prefix 'GitHubActions' -Scope 'Local'
9-
[Boolean]$IsTested = $False
10-
[Boolean]$ResultDependencies = $False
11-
[Boolean]$ResultEnvironment = $False
129
[SemVer]$NodeJsMinimumVersion = [SemVer]::Parse('14.15.0')
1310
[SemVer]$NpmMinimumVersion = [SemVer]::Parse('6.14.8')
1411
[SemVer]$PnpmMinimumVersion = [SemVer]::Parse('7.28.0')
1512
[RegEx]$SemVerRegEx = 'v?\d+\.\d+\.\d+'
1613
[String]$WrapperRoot = Join-Path -Path $PSScriptRoot -ChildPath 'nodejs-wrapper'
17-
[String]$WrapperMetaPath = Join-Path -Path $WrapperRoot -ChildPath 'package.json'
18-
[String]$WrapperScriptPath = Join-Path -Path $WrapperRoot -ChildPath 'unbundled.js'
14+
[String]$WrapperPackageFilePath = Join-Path -Path $WrapperRoot -ChildPath 'package.json'
15+
[String]$WrapperPackageLockFilePath = Join-Path -Path $WrapperRoot -ChildPath 'pnpm-lock.yaml'
16+
[String]$WrapperBundledFilePath = Join-Path -Path $WrapperRoot -ChildPath 'bundled.js'
17+
[String]$WrapperUnbundledFilePath = Join-Path -Path $WrapperRoot -ChildPath 'unbundled.js'
18+
[Boolean]$EnvironmentTested = $False
19+
[Boolean]$EnvironmentResult = $False
20+
[Boolean]$DependenciesTested = $False
21+
[Boolean]$DependenciesResult = $False
1922
<#
2023
.SYNOPSIS
2124
GitHub Actions - Internal - Convert From Base64 String To Utf8 String
@@ -56,6 +59,89 @@ Function Convert-FromUtf8StringToBase64String {
5659
}
5760
<#
5861
.SYNOPSIS
62+
GitHub Actions - Internal - Install NodeJS Dependencies
63+
.DESCRIPTION
64+
Use to install NodeJS wrapper API dependencies when bundled wrapper failed and retry with unbundled wrapper.
65+
.OUTPUTS
66+
[Boolean] Test result.
67+
#>
68+
Function Install-NodeJsDependencies {
69+
[CmdletBinding()]
70+
[OutputType([Boolean])]
71+
Param ()
72+
If ($DependenciesTested) {
73+
Write-Output -InputObject $DependenciesResult
74+
Return
75+
}
76+
Try {
77+
Try {
78+
$Null = Get-Command -Name 'npm' -CommandType 'Application' -ErrorAction 'Stop'# `Get-Command` will throw error when nothing is found.
79+
}
80+
Catch {
81+
Throw 'Unable to find NPM!'
82+
}
83+
Try {
84+
[String]$NpmVersionStdOut = npm --version |
85+
Join-String -Separator "`n"
86+
If (
87+
$NpmVersionStdOut -inotmatch $SemVerRegEx -or
88+
$NpmMinimumVersion -igt [SemVer]::Parse(($Matches[0] -ireplace '^v', ''))
89+
) {
90+
Throw
91+
}
92+
}
93+
Catch {
94+
Throw 'NPM is not match the requirement!'
95+
}
96+
Try {
97+
$Null = Get-Command -Name 'pnpm' -CommandType 'Application' -ErrorAction 'Stop'# `Get-Command` will throw error when nothing is found.
98+
[String]$PnpmVersionStdOut = pnpm --version |
99+
Join-String -Separator "`n"
100+
If (
101+
$PnpmVersionStdOut -inotmatch $SemVerRegEx -or
102+
$PnpmMinimumVersion -igt [SemVer]::Parse(($Matches[0] -ireplace '^v', ''))
103+
) {
104+
Throw
105+
}
106+
}
107+
Catch {
108+
Try {
109+
$Null = npm install --global pnpm@latest
110+
}
111+
Catch {
112+
Throw 'Unable to install PNPM!'
113+
}
114+
}
115+
Try {
116+
$CurrentWorkingRoot = Get-Location
117+
$Null = Set-Location -LiteralPath $WrapperRoot
118+
Try {
119+
$Null = pnpm install
120+
}
121+
Catch {
122+
Throw 'Unable to install NodeJS wrapper API dependencies!'
123+
}
124+
Finally {
125+
Set-Location -LiteralPath $CurrentWorkingRoot.Path
126+
}
127+
}
128+
Catch {
129+
Throw $_
130+
}
131+
}
132+
Catch {
133+
Write-Verbose -Message $_
134+
$Script:DependenciesTested = $True
135+
$Script:DependenciesResult = $False
136+
Write-Output -InputObject $DependenciesResult
137+
Return
138+
}
139+
$Script:DependenciesTested = $True
140+
$Script:DependenciesResult = $True
141+
Write-Output -InputObject $DependenciesResult
142+
}
143+
<#
144+
.SYNOPSIS
59145
GitHub Actions - Invoke NodeJS Wrapper
60146
.DESCRIPTION
61147
Invoke NodeJS wrapper.
@@ -80,28 +166,62 @@ Function Invoke-NodeJsWrapper {
80166
Write-Error -Message 'This function depends and requires to invoke with the compatible NodeJS environment!' -Category 'ResourceUnavailable'
81167
Return
82168
}
83-
If (!(Test-Path -LiteralPath $WrapperMetaPath -PathType 'Leaf')) {
84-
Write-Error -Message 'Wrapper meta is missing!' -Category 'ResourceUnavailable'
85-
Return
86-
}
87-
If (!(Test-Path -LiteralPath $WrapperScriptPath -PathType 'Leaf')) {
88-
Write-Error -Message 'Wrapper script is missing!' -Category 'ResourceUnavailable'
89-
Return
169+
ForEach ($Item In @($WrapperPackageFilePath, $WrapperPackageLockFilePath, $WrapperBundledFilePath, $WrapperUnbundledFilePath)) {
170+
If (!(Test-Path -LiteralPath $Item -PathType 'Leaf')) {
171+
Write-Error -Message "Wrapper resource `"$Item`" is missing!" -Category 'ResourceUnavailable'
172+
Return
173+
}
90174
}
91175
}
92176
[String]$ResultSeparator = "=====$(New-GitHubActionsRandomToken)====="
177+
[String]$Base64Name = Convert-FromUtf8StringToBase64String -InputObject $Name
178+
[String]$Base64Argument = $Argument |
179+
ConvertTo-Json -Depth 100 -Compress |
180+
Convert-FromUtf8StringToBase64String
181+
[String]$Base64ResultSeparator = Convert-FromUtf8StringToBase64String -InputObject $ResultSeparator
182+
Try {
183+
[String[]]$Result = Invoke-Expression -Command "node --no-deprecation --no-warnings `"$WrapperBundledFilePath`" $Base64Name $Base64Argument $Base64ResultSeparator"
184+
[UInt32[]]$ResultSkipIndexes = @()
185+
For ([UInt32]$ResultIndex = 0; $ResultIndex -ilt $Result.Count; $ResultIndex++) {
186+
[String]$ResultLine = $Result[$ResultIndex]
187+
If ($ResultLine -imatch '^::.+?::.*$') {
188+
Write-Host -Object $ResultLine
189+
$ResultSkipIndexes += $ResultIndex
190+
Continue
191+
}
192+
If ($ResultLine -ieq $ResultSeparator) {
193+
$ResultSkipIndexes += @($ResultIndex..($Result.Count - 1))
194+
Break
195+
}
196+
}
197+
If ($LASTEXITCODE -ine 0) {
198+
Throw "Unexpected exit code ``$LASTEXITCODE``! $(
199+
$Result |
200+
Select-Object -SkipIndex $ResultSkipIndexes |
201+
Join-String -Separator "`n"
202+
)"
203+
}
204+
$Result[$Result.Count - 1] |
205+
Convert-FromBase64StringToUtf8String |
206+
ConvertFrom-Json -Depth 100 |
207+
Write-Output
208+
Return
209+
}
210+
Catch {
211+
Write-Warning -Message "Unable to successfully invoke NodeJS bundled wrapper (``$Name``): $_"
212+
}
93213
Try {
94-
[String[]]$Result = Invoke-Expression -Command "node --no-deprecation --no-warnings `"$WrapperScriptPath`" $(Convert-FromUtf8StringToBase64String -InputObject $Name) $(
95-
$Argument |
96-
ConvertTo-Json -Depth 100 -Compress |
97-
Convert-FromUtf8StringToBase64String
98-
) $(Convert-FromUtf8StringToBase64String -InputObject $ResultSeparator)"
214+
If (!(Install-NodeJsDependencies)) {
215+
Throw 'Unable to install NodeJS wrapper API dependencies!'
216+
}
217+
[String[]]$Result = Invoke-Expression -Command "node --no-deprecation --no-warnings `"$WrapperUnbundledFilePath`" $Base64Name $Base64Argument $Base64ResultSeparator"
99218
[UInt32[]]$ResultSkipIndexes = @()
100219
For ([UInt32]$ResultIndex = 0; $ResultIndex -ilt $Result.Count; $ResultIndex++) {
101220
[String]$ResultLine = $Result[$ResultIndex]
102221
If ($ResultLine -imatch '^::.+?::.*$') {
103222
Write-Host -Object $ResultLine
104223
$ResultSkipIndexes += $ResultIndex
224+
Continue
105225
}
106226
If ($ResultLine -ieq $ResultSeparator) {
107227
$ResultSkipIndexes += @($ResultIndex..($Result.Count - 1))
@@ -119,9 +239,10 @@ Function Invoke-NodeJsWrapper {
119239
Convert-FromBase64StringToUtf8String |
120240
ConvertFrom-Json -Depth 100 |
121241
Write-Output
242+
Return
122243
}
123244
Catch {
124-
Write-Error -Message "Unable to successfully invoke NodeJS wrapper (``$Name``): $_" -Category 'InvalidData'
245+
Write-Error -Message "Unable to successfully invoke NodeJS unbundled wrapper (``$Name``): $_" -Category 'InvalidData'
125246
}
126247
}
127248
<#
@@ -131,8 +252,6 @@ GitHub Actions - Test NodeJS Environment
131252
Test the current machine whether has compatible NodeJS environment; Test result always cache for reuse.
132253
.PARAMETER Retest
133254
Whether to redo this test by ignore the cached test result.
134-
.PARAMETER ReinstallDependencies
135-
Whether to force reinstall dependencies even though available.
136255
.OUTPUTS
137256
[Boolean] Test result.
138257
#>
@@ -141,119 +260,46 @@ Function Test-NodeJsEnvironment {
141260
[OutputType([Boolean])]
142261
Param (
143262
[Alias('Redo')][Switch]$Retest,
144-
[Alias('Reinstall', 'ReinstallDependency', 'ReinstallPackage', 'ReinstallPackages')][Switch]$ReinstallDependencies
263+
[Alias('Reinstall', 'ReinstallDependency', 'ReinstallPackage', 'ReinstallPackages')][Switch]$ReinstallDependencies# Deprecated, keep as legacy.
145264
)
146-
If ($IsTested -and !$Retest.IsPresent -and !$ReinstallDependencies.IsPresent) {
265+
If ($EnvironmentTested -and !$Retest.IsPresent) {
147266
Write-Verbose -Message 'Previously tested NodeJS environment; Return previous result.'
148-
Write-Output -InputObject ($ResultDependencies -and $ResultEnvironment)
267+
Write-Output -InputObject $EnvironmentResult
149268
Return
150269
}
151-
$Script:IsTested = $False
152-
If ($ReinstallDependencies.IsPresent) {
153-
$Script:ResultDependencies = $False
154-
}
155-
If ($Retest.IsPresent) {
156-
$Script:ResultEnvironment = $False
157-
}
158-
If (!$ResultEnvironment) {
270+
$Script:EnvironmentTested = $False
271+
$Script:EnvironmentResult = $False
272+
Try {
159273
Try {
160-
Try {
161-
$Null = Get-Command -Name 'node' -CommandType 'Application' -ErrorAction 'Stop'# `Get-Command` will throw error when nothing is found.
162-
}
163-
Catch {
164-
Throw 'Unable to find NodeJS!'
165-
}
166-
Try {
167-
[String]$NodeJsVersionStdOut = node --no-deprecation --no-warnings --version |
168-
Join-String -Separator "`n"
169-
If (
170-
$NodeJsVersionStdOut -inotmatch $SemVerRegEx -or
171-
$NodeJsMinimumVersion -igt [SemVer]::Parse(($Matches[0] -ireplace '^v', ''))
172-
) {
173-
Throw
174-
}
175-
}
176-
Catch {
177-
Throw 'NodeJS is not match the requirement!'
178-
}
179-
Try {
180-
$Null = Get-Command -Name 'npm' -CommandType 'Application' -ErrorAction 'Stop'# `Get-Command` will throw error when nothing is found.
181-
}
182-
Catch {
183-
Throw 'Unable to find NPM!'
184-
}
185-
Try {
186-
[String]$NpmVersionStdOut = npm --version |
187-
Join-String -Separator "`n"
188-
If (
189-
$NpmVersionStdOut -inotmatch $SemVerRegEx -or
190-
$NpmMinimumVersion -igt [SemVer]::Parse(($Matches[0] -ireplace '^v', ''))
191-
) {
192-
Throw
193-
}
194-
}
195-
Catch {
196-
Throw 'NPM is not match the requirement!'
197-
}
274+
$Null = Get-Command -Name 'node' -CommandType 'Application' -ErrorAction 'Stop'# `Get-Command` will throw error when nothing is found.
198275
}
199276
Catch {
200-
Write-Verbose -Message $_
201-
$Script:IsTested = $True
202-
$Script:ResultEnvironment = $False
203-
Write-Output -InputObject ($ResultDependencies -and $ResultEnvironment)
204-
Return
277+
Throw 'Unable to find NodeJS!'
205278
}
206-
}
207-
$Script:ResultEnvironment = $True
208-
If (!$ResultDependencies) {
209279
Try {
210-
Try {
211-
$Null = Get-Command -Name 'pnpm' -CommandType 'Application' -ErrorAction 'Stop'# `Get-Command` will throw error when nothing is found.
212-
[String]$PnpmVersionStdOut = pnpm --version |
213-
Join-String -Separator "`n"
214-
If (
215-
$PnpmVersionStdOut -inotmatch $SemVerRegEx -or
216-
$PnpmMinimumVersion -igt [SemVer]::Parse(($Matches[0] -ireplace '^v', ''))
217-
) {
218-
Throw
219-
}
220-
}
221-
Catch {
222-
Try {
223-
$Null = npm install --global pnpm@latest
224-
}
225-
Catch {
226-
Throw 'Unable to install PNPM!'
227-
}
228-
}
229-
Try {
230-
$CurrentWorkingDirectory = Get-Location
231-
$Null = Set-Location -LiteralPath $WrapperRoot
232-
Try {
233-
$Null = pnpm install
234-
}
235-
Catch {
236-
Throw 'Unable to install NodeJS wrapper API dependencies!'
237-
}
238-
Finally {
239-
Set-Location -LiteralPath $CurrentWorkingDirectory.Path
240-
}
241-
}
242-
Catch {
243-
Throw $_
280+
[String]$NodeJsVersionStdOut = node --no-deprecation --no-warnings --version |
281+
Join-String -Separator "`n"
282+
If (
283+
$NodeJsVersionStdOut -inotmatch $SemVerRegEx -or
284+
$NodeJsMinimumVersion -igt [SemVer]::Parse(($Matches[0] -ireplace '^v', ''))
285+
) {
286+
Throw
244287
}
245288
}
246289
Catch {
247-
Write-Verbose -Message $_
248-
$Script:IsTested = $True
249-
$Script:ResultDependencies = $False
250-
Write-Output -InputObject ($ResultDependencies -and $ResultEnvironment)
251-
Return
290+
Throw 'NodeJS is not match the requirement!'
252291
}
253292
}
254-
$Script:IsTested = $True
255-
$Script:ResultDependencies = $True
256-
Write-Output -InputObject ($ResultDependencies -and $ResultEnvironment)
293+
Catch {
294+
Write-Verbose -Message $_
295+
$Script:EnvironmentTested = $True
296+
$Script:EnvironmentResult = $False
297+
Write-Output -InputObject $EnvironmentResult
298+
Return
299+
}
300+
$Script:EnvironmentTested = $True
301+
$Script:EnvironmentResult = $True
302+
Write-Output -InputObject $EnvironmentResult
257303
}
258304
Export-ModuleMember -Function @(
259305
'Invoke-NodeJsWrapper',

nodejs-wrapper-source/bundler.ps1

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@ If (Test-Path -LiteralPath $WrapperOutputRoot -PathType 'Container') {
1212
Remove-Item -Confirm
1313
}
1414
Else {
15-
$Null = New-Item -Path $WrapperOutputRoot -ItemType 'Directory'
15+
New-Item -Path $WrapperOutputRoot -ItemType 'Directory'
1616
}
1717

1818
<# Create bundled wrapper. #>
19-
[String]$CurrentWorkingRoot = Get-Location |
20-
Select-Object -ExpandProperty 'Path'
19+
$CurrentWorkingRoot = Get-Location
2120
[String]$WrapperOutputRootResolve = $WrapperOutputRoot |
2221
Resolve-Path |
2322
Select-Object -ExpandProperty 'Path' -First 1
@@ -29,10 +28,10 @@ Catch {
2928
Write-Error -Message $_
3029
}
3130
Finally {
32-
Set-Location -LiteralPath $CurrentWorkingRoot
31+
Set-Location -LiteralPath $CurrentWorkingRoot.Path
3332
}
3433

35-
<# Resolve bundler rubbish. #>
34+
<# Resolve bundler issues. #>
3635
ForEach ($Item In (Get-ChildItem -LiteralPath $WrapperOutputRoot -Recurse)) {
3736
If ($Item.Name -ieq 'index.js') {
3837
Rename-Item -LiteralPath $Item.FullName -NewName (Join-Path -Path $Item.Directory -ChildPath $WrapperOutputBundledFileName) -Confirm

0 commit comments

Comments
 (0)