forgerunner

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package forgerunner implements a lightweight Actions runner for Forgejo and Gitea. It registers with the forge via ConnectRPC, polls for tasks, and executes workflow steps via direct process spawning — no Docker.

This package contains the shared logic. Platform-specific CLI entrypoints live in cmd/ephemerd-runner-forgejo (Forgejo) and cmd/ephemerd-runner-gitea (Gitea).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildEnv

func BuildEnv(task *forgerpc.Task, runnerName string) map[string]string

BuildEnv extracts environment variables from a forge task payload. These mirror the GITHUB_* and RUNNER_* variables that GHA sets.

func SecretsFromContext

func SecretsFromContext(task *forgerpc.Task) []string

SecretsFromContext extracts secret values from the task context for masking.

Types

type Command

type Command struct {
	Name   string
	Params map[string]string
	Value  string
}

Command is a parsed workflow command from process stdout.

::name param=val,param2=val2::message

func ParseCommand

func ParseCommand(line string) (*Command, bool)

ParseCommand extracts a workflow command from a log line. Returns nil, false if the line is not a command.

type Config

type Config struct {
	// Platform identifies the forge type ("forgejo" or "gitea").
	Platform string

	// InstanceURL is the forge instance base URL (e.g., "https://codeberg.org").
	InstanceURL string

	// Token is the runner registration token from the forge admin panel.
	Token string

	// Name is the runner display name. Defaults to hostname.
	Name string

	// Labels are the runs-on labels to register (e.g., "ubuntu-latest").
	Labels []string

	// Version is reported to the forge during registration.
	Version string

	// HTTPClient is an optional *http.Client for the ConnectRPC client.
	// If nil, a default client with 30s timeout is used.
	HTTPClient *http.Client

	Log *slog.Logger
}

Config configures a forge runner instance.

type Executor

type Executor struct {
	// contains filtered or unexported fields
}

Executor runs a single forge task: parses the workflow, executes steps, and reports results back to the forge.

func NewExecutor

func NewExecutor(client *forgerpc.Client, task *forgerpc.Task, log *slog.Logger) *Executor

NewExecutor creates an executor for a task.

func (*Executor) Run

func (e *Executor) Run(ctx context.Context) error

Run executes the task end-to-end.

type FileCommands

type FileCommands struct {
	Outputs  map[string]string // from GITHUB_OUTPUT
	EnvVars  map[string]string // from GITHUB_ENV
	PathAdds []string          // from GITHUB_PATH
}

FileCommands holds values read from GITHUB_OUTPUT, GITHUB_ENV, and GITHUB_PATH file-based command files after a step executes.

func ParseFileCommands

func ParseFileCommands(outputPath, envPath, pathPath string) (*FileCommands, error)

ParseFileCommands reads the file-based command files written by a step.

type Job

type Job struct {
	Name   string            `yaml:"name"`
	RunsOn RunsOn            `yaml:"runs-on"`
	Steps  []*Step           `yaml:"steps"`
	Env    map[string]string `yaml:"env"`
	If     string            `yaml:"if"`
}

Job is a single job within a workflow.

type LogReporter

type LogReporter struct {
	// contains filtered or unexported fields
}

LogReporter batches log lines and streams them to the forge via UpdateLog.

func NewLogReporter

func NewLogReporter(client *forgerpc.Client, taskID int64, masker *SecretMasker) *LogReporter

NewLogReporter creates a log reporter for the given task.

func (*LogReporter) AddLine

func (r *LogReporter) AddLine(content string)

AddLine appends a timestamped, secret-masked log line.

func (*LogReporter) Close

func (r *LogReporter) Close(ctx context.Context) error

Close flushes remaining lines and sends the final noMore=true signal.

func (*LogReporter) Flush

func (r *LogReporter) Flush(ctx context.Context) error

Flush sends any buffered log lines to the forge.

func (*LogReporter) LineCount

func (r *LogReporter) LineCount() int64

LineCount returns the total number of log lines added.

type Runner

type Runner struct {
	// contains filtered or unexported fields
}

Runner registers with a Forgejo or Gitea instance and executes workflow steps directly via process spawning — no Docker dependency.

func New

func New(cfg Config) (*Runner, error)

New creates a forge runner from the given config.

func (*Runner) Run

func (r *Runner) Run(ctx context.Context) error

Run registers the runner, declares labels, and polls for a single task. It blocks until the task is executed or the context is cancelled.

type RunsOn

type RunsOn struct {
	Labels []string
}

RunsOn handles the YAML runs-on field which can be a string or []string.

func (*RunsOn) UnmarshalYAML

func (r *RunsOn) UnmarshalYAML(value *yaml.Node) error

type ScriptResult

type ScriptResult struct {
	ExitCode   int
	Outputs    map[string]string // from GITHUB_OUTPUT file
	EnvChanges map[string]string // from GITHUB_ENV file
	PathAdds   []string          // from GITHUB_PATH file
}

ScriptResult is the outcome of running a script step.

func RunScript

func RunScript(ctx context.Context, step *Step, env map[string]string, workDir string, reporter *LogReporter, masker *SecretMasker) (*ScriptResult, error)

RunScript executes a run: step by writing the script to a temp file, spawning the appropriate shell, and capturing output.

type SecretMasker

type SecretMasker struct {
	// contains filtered or unexported fields
}

SecretMasker replaces registered secret values with "***" in log output.

func NewSecretMasker

func NewSecretMasker(secrets []string) *SecretMasker

NewSecretMasker creates a masker with the given secrets. Empty and short (< 3 char) secrets are ignored to avoid false positives.

func (*SecretMasker) AddSecret

func (m *SecretMasker) AddSecret(s string)

AddSecret registers an additional secret for masking.

func (*SecretMasker) Mask

func (m *SecretMasker) Mask(s string) string

Mask replaces all registered secrets in s with "***".

type Step

type Step struct {
	ID               string            `yaml:"id"`
	Name             string            `yaml:"name"`
	Run              string            `yaml:"run"`
	Shell            string            `yaml:"shell"`
	Env              map[string]string `yaml:"env"`
	WorkingDirectory string            `yaml:"working-directory"`
	If               string            `yaml:"if"`
	Uses             string            `yaml:"uses"`
	With             map[string]string `yaml:"with"`
}

Step is a single step within a job.

func (*Step) DisplayName

func (s *Step) DisplayName(index int) string

DisplayName returns the step's name, ID, or a fallback based on content.

type Workflow

type Workflow struct {
	Name string          `yaml:"name"`
	Jobs map[string]*Job `yaml:"jobs"`
}

Workflow is a parsed Actions workflow YAML.

func ParseWorkflow

func ParseWorkflow(data []byte) (*Workflow, error)

ParseWorkflow parses workflow YAML bytes into a Workflow.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL