Build/GitHub/Action/WaveAction.ps1
|
<# .Synopsis GitHub Action for Wave .Description GitHub Action for Wave. This will: * Import Wave * If `-Run` is provided, run that script * Otherwise, unless `-SkipScriptFile` is passed, run all *.wave.ps1 files beneath the workflow directory * If any `-ActionScript` was provided, run scripts from the action path that match a wildcard pattern. #> param( # A PowerShell Script that uses Wave. # Any files outputted from the script will be added to the repository. [string] $Run, # The Script File Pattern. # Scripts in the repository that match this pattern will be run. [string] $ScriptFilePattern = '\.wave?\.ps1$', # If set, will not process any files that match the script file pattern. [switch] $SkipScriptFile, # A list of modules to be installed from the PowerShell gallery before scripts run. [string[]] $InstallModule, # The name of one or more scripts to run, from this action's path. [string[]] $ActionScript, # The github token to use for requests. [string] $GitHubToken = '{{ secrets.GITHUB_TOKEN }}' ) $ErrorActionPreference = 'continue' "::group::Parameters" | Out-Host [PSCustomObject]$PSBoundParameters | Format-List | Out-Host "::endgroup::" | Out-Host $gitHubEventJson = [IO.File]::ReadAllText($env:GITHUB_EVENT_PATH) $gitHubEvent = if ($env:GITHUB_EVENT_PATH) { $gitHubEventJson | ConvertFrom-Json } else { $null } "::group::Parameters" | Out-Host $gitHubEvent | Format-List | Out-Host "::endgroup::" | Out-Host $anyFilesChanged = $false $ActionModuleName = 'Wave' $actorInfo = $null $checkDetached = git symbolic-ref -q HEAD if ($LASTEXITCODE) { "::warning::On detached head, skipping action" | Out-Host exit 0 } function InstallActionModule { param([string]$ModuleToInstall) $moduleInWorkspace = Get-ChildItem -Path $env:GITHUB_WORKSPACE -Recurse -File | Where-Object Name -eq "$($moduleToInstall).psd1" | Where-Object { $(Get-Content $_.FullName -Raw) -match 'ModuleVersion' } if (-not $moduleInWorkspace) { $availableModules = Get-Module -ListAvailable if ($availableModules.Name -notcontains $moduleToInstall) { Install-Module $moduleToInstall -Scope CurrentUser -Force -AcceptLicense -AllowClobber } Import-Module $moduleToInstall -Force -PassThru | Out-Host } else { Import-Module $moduleInWorkspace.FullName -Force -PassThru | Out-Host } } function ImportActionModule { #region -InstallModule if ($InstallModule) { "::group::Installing Modules" | Out-Host foreach ($moduleToInstall in $InstallModule) { InstallActionModule -ModuleToInstall $moduleToInstall } "::endgroup::" | Out-Host } #endregion -InstallModule if ($env:GITHUB_ACTION_PATH) { $LocalModulePath = Join-Path $env:GITHUB_ACTION_PATH "$ActionModuleName.psd1" if (Test-path $LocalModulePath) { Import-Module $LocalModulePath -Force -PassThru | Out-String } else { throw "Module '$ActionModuleName' not found" } } elseif (-not (Get-Module $ActionModuleName)) { throw "Module '$ActionModuleName' not found" } "::notice title=ModuleLoaded::$ActionModuleName Loaded from Path - $($LocalModulePath)" | Out-Host if ($env:GITHUB_STEP_SUMMARY) { "# $($ActionModuleName)" | Out-File -Append -FilePath $env:GITHUB_STEP_SUMMARY } } function InvokeActionModule { $myScriptStart = [DateTime]::Now $myScript = $ExecutionContext.SessionState.PSVariable.Get("Run").Value if ($myScript) { Invoke-Expression -Command $myScript | Out-Host return } $myScriptTook = [Datetime]::Now - $myScriptStart $MyScriptFilesStart = [DateTime]::Now $myScriptList = @() $shouldSkip = $ExecutionContext.SessionState.PSVariable.Get("SkipScriptFile").Value if ($shouldSkip) { return } $scriptFiles = @(@( Get-ChildItem -Recurse -Path $env:GITHUB_WORKSPACE | Where-Object Extension -eq .ps1 | Where-Object Name -Match $ScriptFilePattern if ($ActionScript) { if ($ActionScript -match '^\s{0,}/' -and $ActionScript -match '/\s{0,}$') { $ActionScriptPattern = $ActionScript.Trim('/').Trim() -as [regex] if ($ActionScriptPattern) { $ActionScriptPattern = [regex]::new($ActionScript.Trim('/').Trim(), 'IgnoreCase,IgnorePatternWhitespace', [timespan]::FromSeconds(0.5)) Get-ChildItem -Recurse -Path $env:GITHUB_ACTION_PATH | Where-Object { $_.Name -Match "\.$($ActionModuleName)\.ps1$" -and $_.FullName -match $ActionScriptPattern } } } else { Get-ChildItem -Recurse -Path $env:GITHUB_ACTION_PATH | Where-Object Name -Match "\.$($ActionModuleName)s?\.ps1$" | Where-Object FullName -Like $ActionScript } } ) | Select-Object -Unique) "Found $($scriptFiles.Length) script files matching '$($ScriptFilePattern)'" | Out-Host $scriptFiles | Out-Host $scriptFiles | ForEach-Object -Begin { if ($env:GITHUB_STEP_SUMMARY) { "## $ActionModuleName Scripts" | Out-File -Append -FilePath $env:GITHUB_STEP_SUMMARY } } -Process { $myScriptList += $_.FullName.Replace($env:GITHUB_WORKSPACE, '').TrimStart('/') $myScriptCount++ $scriptFile = $_ if ($env:GITHUB_STEP_SUMMARY) { "### $($scriptFile.Fullname -replace [Regex]::Escape($env:GITHUB_WORKSPACE))" | Out-File -Append -FilePath $env:GITHUB_STEP_SUMMARY } $scriptCmd = $ExecutionContext.SessionState.InvokeCommand.GetCommand($scriptFile.FullName, 'ExternalScript') foreach ($requiredModule in $CommandInfo.ScriptBlock.Ast.ScriptRequirements.RequiredModules) { if ($requiredModule.Name -and (-not $requiredModule.MaximumVersion) -and (-not $requiredModule.RequiredVersion) ) { InstallActionModule $requiredModule.Name } } Push-Location $scriptFile.Directory.Fullname $scriptFileOutputs = . $scriptCmd $scriptFileOutputs | Out-Host Pop-Location } $MyScriptFilesTook = [Datetime]::Now - $MyScriptFilesStart $SummaryOfMyScripts = "$myScriptCount $ActionModuleName scripts took $($MyScriptFilesTook.TotalSeconds) seconds" $SummaryOfMyScripts | Out-Host if ($env:GITHUB_STEP_SUMMARY) { $SummaryOfMyScripts | Out-File -Append -FilePath $env:GITHUB_STEP_SUMMARY } #region Custom #endregion Custom } function OutError { $anyRuntimeExceptions = $false foreach ($err in $error) { $errParts = @( "::error " @( if ($err.InvocationInfo.ScriptName) { "file=$($err.InvocationInfo.ScriptName)" } if ($err.InvocationInfo.ScriptLineNumber -ge 1) { "line=$($err.InvocationInfo.ScriptLineNumber)" if ($err.InvocationInfo.OffsetInLine -ge 1) { "col=$($err.InvocationInfo.OffsetInLine)" } } if ($err.CategoryInfo.Activity) { "title=$($err.CategoryInfo.Activity)" } ) -join ',' "::" $err.Exception.Message if ($err.CategoryInfo.Category -eq 'OperationStopped' -and $err.CategoryInfo.Reason -eq 'RuntimeException') { $anyRuntimeExceptions = $true } ) -join '' $errParts | Out-Host if ($anyRuntimeExceptions) { exit 1 } } } . ImportActionModule . InvokeActionModule . OutError |