feat: some basic action core logic
This commit is contained in:
parent
a2e2ddb502
commit
917952884e
7 changed files with 552 additions and 0 deletions
3
eng/Containerfile
Normal file
3
eng/Containerfile
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
FROM mcr.microsoft.com/dotnet/sdk:10.0
|
||||
WORKDIR /work
|
||||
COPY ./src /work
|
||||
37
src/Geekeey.Build.Pwsh.psd1
Normal file
37
src/Geekeey.Build.Pwsh.psd1
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
@{
|
||||
RootModule = 'Geekeey.Build.Pwsh.psm1'
|
||||
ModuleVersion = '1.0.0'
|
||||
GUID = '234baa68-d26f-4bf9-996d-45ec3520cb95'
|
||||
Author = 'The Geekeey Authors'
|
||||
CompanyName = 'Geekeey'
|
||||
Copyright = '(c) The Geekeey Authors. Licensed under EUPL-1.2.'
|
||||
Description = 'Forgejo Actions helper functions for PowerShell.'
|
||||
FunctionsToExport = @(
|
||||
'Set-ActionOutput',
|
||||
'Set-ActionEnv',
|
||||
'Add-ActionPath',
|
||||
'Add-ActionMask',
|
||||
'Add-ActionMatcher',
|
||||
'Remove-ActionMatcher',
|
||||
'Save-ActionState',
|
||||
'Add-ActionStepSummary',
|
||||
'Get-ActionInput',
|
||||
'Write-ActionDebug',
|
||||
'Write-ActionNotice',
|
||||
'Write-ActionWarning',
|
||||
'Write-ActionError',
|
||||
'Stop-Action',
|
||||
'Invoke-ForgejoApi',
|
||||
'Get-ForgejoContext'
|
||||
)
|
||||
CmdletsToExport = @()
|
||||
VariablesToExport = @()
|
||||
AliasesToExport = @()
|
||||
PowerShellVersion = '7.0'
|
||||
PrivateData = @{
|
||||
PSData = @{
|
||||
LicenseUri = 'https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12'
|
||||
Tags = @('Forgejo', 'Actions', 'CI')
|
||||
}
|
||||
}
|
||||
}
|
||||
488
src/Geekeey.Build.Pwsh.psm1
Normal file
488
src/Geekeey.Build.Pwsh.psm1
Normal file
|
|
@ -0,0 +1,488 @@
|
|||
# Copyright (c) The Geekeey Authors
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
$Script:MULTILINE_DELIMITER = "234baa68-d26f-4bf9-996d-45ec3520cb95"
|
||||
|
||||
function Write-FileInstruction
|
||||
{
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$EnvVar,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Name,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Value
|
||||
)
|
||||
$filePath = [System.Environment]::GetEnvironmentVariable($EnvVar)
|
||||
if ([string]::IsNullOrEmpty($filePath))
|
||||
{
|
||||
throw "$EnvVar is not set"
|
||||
}
|
||||
$content = "${Name}<<${MULTILINE_DELIMITER}`n${Value}`n${MULTILINE_DELIMITER}"
|
||||
Add-Content -Path $filePath -Value $content
|
||||
}
|
||||
|
||||
function Set-ActionOutput
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets an output variable for the workflow.
|
||||
.PARAMETER Name
|
||||
The name of the output variable.
|
||||
.PARAMETER Value
|
||||
The value to set.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Name,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Value
|
||||
)
|
||||
Write-FileInstruction -EnvVar "FORGEJO_OUTPUT" -Name $Name -Value $Value
|
||||
}
|
||||
|
||||
function Set-ActionEnv
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sets an environment variable for subsequent steps.
|
||||
.PARAMETER Name
|
||||
The name of the environment variable.
|
||||
.PARAMETER Value
|
||||
The value to set.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Name,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Value
|
||||
)
|
||||
Write-FileInstruction -EnvVar "FORGEJO_ENV" -Name $Name -Value $Value
|
||||
}
|
||||
|
||||
function Add-ActionPath
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Adds a directory to the PATH for subsequent steps.
|
||||
.PARAMETER Path
|
||||
The directory path to add.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Path
|
||||
)
|
||||
$filePath = [System.Environment]::GetEnvironmentVariable("FORGEJO_PATH")
|
||||
if ([string]::IsNullOrEmpty($filePath))
|
||||
{
|
||||
throw "FORGEJO_PATH is not set"
|
||||
}
|
||||
Add-Content -Path $filePath -Value $Path
|
||||
}
|
||||
|
||||
function Save-ActionState
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Saves a state value for use in subsequent steps of the same job.
|
||||
.PARAMETER Name
|
||||
The name of the state variable.
|
||||
.PARAMETER Value
|
||||
The value to save.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Name,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Value
|
||||
)
|
||||
Write-FileInstruction -EnvVar "FORGEJO_STATE" -Name $Name -Value $Value
|
||||
}
|
||||
|
||||
function Add-ActionStepSummary
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Writes a summary for the workflow run step.
|
||||
.PARAMETER Summary
|
||||
The markdown summary text.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Summary
|
||||
)
|
||||
$envPath = $env:FORGEJO_STEP_SUMMARY
|
||||
if ([string]::IsNullOrEmpty($envPath))
|
||||
{
|
||||
throw "FORGEJO_STEP_SUMMARY is not set"
|
||||
}
|
||||
Add-Content -Path $envPath -Value $Summary
|
||||
}
|
||||
|
||||
function Add-ActionMask
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Masks a value in log output. Future attempts to log this value will show "***".
|
||||
.PARAMETER Value
|
||||
The value to mask.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Value
|
||||
)
|
||||
Write-Host "::add-mask::$Value"
|
||||
}
|
||||
|
||||
function Add-ActionMatcher
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Registers a problem matcher from a JSON file.
|
||||
.PARAMETER Path
|
||||
The path to the problem matcher JSON file.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Path
|
||||
)
|
||||
Write-Host "::add-matcher::$Path"
|
||||
}
|
||||
|
||||
function Remove-ActionMatcher
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Removes a previously registered problem matcher by owner.
|
||||
.PARAMETER Owner
|
||||
The owner of the problem matcher to remove.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Owner
|
||||
)
|
||||
Write-Host "::remove-matcher owner=$Owner"
|
||||
}
|
||||
|
||||
function Start-ActionGroup
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Starts an expandable group in the log.
|
||||
.PARAMETER Title
|
||||
The group title.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Title
|
||||
)
|
||||
Write-Host "::group::$Title"
|
||||
}
|
||||
|
||||
function Stop-ActionGroup
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Ends the most recently started log group.
|
||||
#>
|
||||
Write-Host "::endgroup::"
|
||||
}
|
||||
|
||||
function Set-ActionCommandEcho
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Enables or disables echoing of workflow commands to the log.
|
||||
.PARAMETER Enabled
|
||||
If $true, workflow commands are echoed; otherwise they are not.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[bool]$Enabled
|
||||
)
|
||||
$value = if ($Enabled) { "on" } else { "off" }
|
||||
Write-Host "::echo::$value"
|
||||
}
|
||||
|
||||
function Suspend-ActionCommands
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Stops processing of workflow commands until resumed.
|
||||
.PARAMETER Token
|
||||
A unique token used to later resume command processing.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Token
|
||||
)
|
||||
Write-Host "::stop-commands::$Token"
|
||||
}
|
||||
|
||||
function Resume-ActionCommands
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Resumes processing of workflow commands.
|
||||
.PARAMETER Token
|
||||
The same token previously passed to Suspend-ActionCommands.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Token
|
||||
)
|
||||
Write-Host "::$Token::"
|
||||
}
|
||||
|
||||
function Get-ActionInput
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets an input value by name.
|
||||
.PARAMETER Name
|
||||
The input name (spaces are replaced with underscores, uppercased).
|
||||
.PARAMETER Required
|
||||
If $true, throws when the input is not set.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Name,
|
||||
[switch]$Required
|
||||
)
|
||||
|
||||
$value = [System.Environment]::GetEnvironmentVariable("INPUT_$($Name.Replace(' ', '_').ToUpper())")?.Trim()
|
||||
|
||||
if ($Required -and [string]::IsNullOrEmpty($value))
|
||||
{
|
||||
Stop-Action "Input '$Name' is required but not provided."
|
||||
}
|
||||
|
||||
return $value
|
||||
}
|
||||
|
||||
function Get-ActionState
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets a state value saved by Save-ActionState.
|
||||
.PARAMETER Name
|
||||
The name of the state variable.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Name
|
||||
)
|
||||
|
||||
$value = [System.Environment]::GetEnvironmentVariable("STATE_$($Name.Replace(' ', '_').ToUpper())")?.Trim()
|
||||
|
||||
return $value
|
||||
}
|
||||
|
||||
function Test-ActionDebug
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns $true when debug logging is enabled (RUNNER_DEBUG=1).
|
||||
#>
|
||||
$value = [System.Environment]::GetEnvironmentVariable("RUNNER_DEBUG")
|
||||
return $value -eq "1"
|
||||
}
|
||||
|
||||
function Write-ActionDebug
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Writes a debug-level message.
|
||||
.PARAMETER Message
|
||||
The message to write.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Message
|
||||
)
|
||||
Write-Host "::debug::$Message"
|
||||
}
|
||||
|
||||
function Write-ActionNotice
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Writes a notice-level message.
|
||||
.PARAMETER Message
|
||||
The message to write.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Message
|
||||
)
|
||||
Write-Host "::notice::$Message"
|
||||
}
|
||||
|
||||
function Write-ActionWarning
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Writes a warning-level message.
|
||||
.PARAMETER Message
|
||||
The message to write.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Message
|
||||
)
|
||||
Write-Host "::warning::$Message"
|
||||
}
|
||||
|
||||
function Write-ActionError
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Writes an error-level message.
|
||||
.PARAMETER Message
|
||||
The message to write.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Message
|
||||
)
|
||||
Write-Host "::error::$Message"
|
||||
}
|
||||
|
||||
function Stop-Action
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Fails the action with an error message.
|
||||
.PARAMETER Message
|
||||
The error message.
|
||||
.PARAMETER ExitCode
|
||||
The exit code (default: 1).
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Message,
|
||||
[int]$ExitCode = 1
|
||||
)
|
||||
Write-ActionError $Message
|
||||
exit $ExitCode
|
||||
}
|
||||
|
||||
function Invoke-ForgejoApi
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Makes an authenticated Forgejo API call.
|
||||
.PARAMETER Method
|
||||
The HTTP method (GET, POST, PUT, PATCH, DELETE).
|
||||
.PARAMETER Path
|
||||
The API path (e.g., "/repos/{owner}/{repo}/issues").
|
||||
.PARAMETER Body
|
||||
Optional request body (will be converted to JSON).
|
||||
.PARAMETER ContentType
|
||||
The content type (default: application/json).
|
||||
.OUTPUTS
|
||||
The deserialized JSON response.
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[ValidateSet("GET", "POST", "PUT", "PATCH", "DELETE")]
|
||||
[string]$Method,
|
||||
[Parameter(Mandatory)]
|
||||
[string]$Path,
|
||||
[object]$Body,
|
||||
[string]$ContentType = "application/json"
|
||||
)
|
||||
|
||||
$token = $env:FORGEJO_TOKEN
|
||||
if ([string]::IsNullOrEmpty($token))
|
||||
{
|
||||
throw "FORGEJO_TOKEN is not set."
|
||||
}
|
||||
|
||||
$serverUrl = $env:FORGEJO_SERVER_URL
|
||||
if ([string]::IsNullOrEmpty($serverUrl))
|
||||
{
|
||||
throw "FORGEJO_SERVER_URL is not set."
|
||||
}
|
||||
|
||||
$headers = @{
|
||||
"Authorization" = "token $token"
|
||||
"Accept" = "application/json"
|
||||
}
|
||||
|
||||
$params = @{
|
||||
Method = $Method
|
||||
Uri = "$serverUrl/api/v1$Path"
|
||||
Headers = $headers
|
||||
ContentType = $ContentType
|
||||
}
|
||||
|
||||
if ($Body)
|
||||
{
|
||||
$params.Body = ($Body | ConvertTo-Json -Depth 100 -Compress)
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return (Invoke-RestMethod @params)
|
||||
}
|
||||
catch
|
||||
{
|
||||
$statusCode = $_.Exception.Response.StatusCode.value__
|
||||
$message = $_.ErrorDetails.Message
|
||||
if ([string]::IsNullOrEmpty($message))
|
||||
{
|
||||
$message = $_.Exception.Message
|
||||
}
|
||||
throw "Forgejo API call failed: $Method $Path -> $statusCode $message"
|
||||
}
|
||||
}
|
||||
|
||||
function Get-ForgejoContext
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Returns a hashtable with the Forgejo Actions context.
|
||||
.DESCRIPTION
|
||||
Provides access to ev payload, repository info, and a convenience
|
||||
method for making authenticated API calls.
|
||||
.OUTPUTS
|
||||
Hashtable with Context, Repository, ServerUrl, Token, Ref, Sha, RunId,
|
||||
and an InvokeApi scriptblock.
|
||||
#>
|
||||
|
||||
$ev = @{}
|
||||
if ($env:FORGEJO_EVENT_PATH -and (Test-Path $env:FORGEJO_EVENT_PATH))
|
||||
{
|
||||
try
|
||||
{
|
||||
$ev = (Get-Content $env:FORGEJO_EVENT_PATH -Raw | ConvertFrom-Json -AsHashtable)
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-ActionWarning "Failed to parse FORGEJO_EVENT_PATH: $_"
|
||||
}
|
||||
}
|
||||
|
||||
return @{
|
||||
Event = $ev
|
||||
Repository = $env:FORGEJO_REPOSITORY
|
||||
ServerUrl = $env:FORGEJO_SERVER_URL
|
||||
Token = $env:FORGEJO_TOKEN
|
||||
Ref = $env:FORGEJO_REF
|
||||
Sha = $env:FORGEJO_SHA
|
||||
RunId = $env:FORGEJO_RUN_ID
|
||||
RunNumber = $env:FORGEJO_RUN_NUMBER
|
||||
Actor = $env:FORGEJO_ACTOR
|
||||
Workflow = $env:FORGEJO_WORKFLOW
|
||||
Job = $env:FORGEJO_JOB
|
||||
Action = $env:FORGEJO_ACTION
|
||||
# Convenience: $Forgejo.InvokeApi("GET", "/repos/{owner}/{repo}/issues")
|
||||
InvokeApi = [ScriptBlock] {
|
||||
param($Method, $Path, $Body)
|
||||
Invoke-ForgejoApi -Method $Method -Path $Path -Body $Body
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/collection/checkout.ps1
Normal file
1
src/collection/checkout.ps1
Normal file
|
|
@ -0,0 +1 @@
|
|||
using module ../Geekeey.Build.Pwsh.psd1
|
||||
22
src/collection/pwsh.ps1
Normal file
22
src/collection/pwsh.ps1
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright (c) The Geekeey Authors
|
||||
# SPDX-License-Identifier: EUPL-1.2
|
||||
using module ../Geekeey.Build.Pwsh.psd1
|
||||
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$ProgressPreference = 'Ignore'
|
||||
|
||||
$PSNativeCommandUseErrorActionPreference = $true
|
||||
|
||||
$script = Get-ActionInput -Name "script" -Required
|
||||
|
||||
try
|
||||
{
|
||||
Invoke-Expression $script
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-ActionError "Script failed: $_"
|
||||
exit 1
|
||||
}
|
||||
1
src/collection/ssh-add-key.ps1
Normal file
1
src/collection/ssh-add-key.ps1
Normal file
|
|
@ -0,0 +1 @@
|
|||
using module ../Geekeey.Build.Pwsh.psm1
|
||||
0
src/core/context.ps1
Normal file
0
src/core/context.ps1
Normal file
Loading…
Add table
Add a link
Reference in a new issue