Documentation
¶
Overview ¶
Package ci implements a local GitHub Actions workflow parser and executor. It provides 80% parity with GitHub Actions by executing `run:` shell blocks inside isolated Podman/Docker containers, while intentionally skipping composite/JS `uses:` actions.
LIMITATION: This engine does NOT support `uses:` actions. Third-party actions like actions/setup-go, actions/upload-artifact, or golangci/golangci-lint-action are skipped with a visible warning. Only `run:` shell blocks are executed. This is a deliberate design decision documented in docs/guide/ci.md.
Index ¶
- func CondensedMatrixName(jobKey string, matrix map[string]string) string
- func DiscoverWorkflows(projectDir string) ([]string, error)
- func MergeEnv(maps ...map[string]string) map[string]string
- func ResetWriterRegistry()
- func ResolveJobDAG(jobs map[string]*Job) ([][]string, error)
- type ExecuteConfig
- type ExpandedJob
- type Job
- type MatrixDef
- type PrefixedWriter
- type RunResult
- type Service
- type Step
- type StepResult
- type Strategy
- type StringOrSlice
- type TemplateContext
- type Workflow
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CondensedMatrixName ¶
CondensedMatrixName generates a short display name for matrix jobs suitable for the prefix column. E.g., "build (darwin, arm64)" → "build·dar·a64"
func DiscoverWorkflows ¶
DiscoverWorkflows lists all .yml/.yaml files in .github/workflows/.
func ResetWriterRegistry ¶
func ResetWriterRegistry()
ResetWriterRegistry clears the color assignment state. Useful for testing.
func ResolveJobDAG ¶
ResolveJobDAG performs a topological sort on jobs based on `needs:` dependencies. Returns execution tiers: each tier contains jobs that can run in parallel, and all jobs in a tier depend only on jobs in previous tiers.
Types ¶
type ExecuteConfig ¶
type ExecuteConfig struct {
Workflow *Workflow
Runtime string // "podman" or "docker"
Image string // container image override (empty = auto-detect)
JobFilter []string // run only these jobs (empty = all)
Secrets map[string]string // secrets from devx Vault
DryRun bool
JSONOutput bool
ProjectDir string
}
ExecuteConfig holds configuration for a CI execution run.
type ExpandedJob ¶
type ExpandedJob struct {
JobKey string // original job key in the workflow
DisplayName string // human-readable name (e.g. "build (darwin, arm64)")
Job *Job // reference to the original job definition
MatrixValues map[string]string // resolved matrix values for this expansion
}
ExpandedJob is a concrete job instance with a specific matrix combination resolved.
func ExpandMatrix ¶
func ExpandMatrix(jobKey string, job *Job) []ExpandedJob
ExpandMatrix takes a job and produces one ExpandedJob per matrix combination. If no matrix is defined, returns a single ExpandedJob with empty matrix values.
type Job ¶
type Job struct {
Name string `yaml:"name"`
RunsOn string `yaml:"runs-on"`
Needs StringOrSlice `yaml:"needs"`
If string `yaml:"if"`
Env map[string]string `yaml:"env"`
Strategy Strategy `yaml:"strategy"`
Services map[string]Service `yaml:"services"`
Steps []Step `yaml:"steps"`
TimeoutMinutes int `yaml:"timeout-minutes"`
ContinueOnError bool `yaml:"continue-on-error"`
}
Job represents a single job within a workflow.
type MatrixDef ¶
type MatrixDef struct {
// Values holds the primary matrix axes (e.g., {"goos": ["darwin","linux"]}).
Values map[string][]string `yaml:"-"`
Include []map[string]string `yaml:"include"`
Exclude []map[string]string `yaml:"exclude"`
}
MatrixDef holds the matrix definition including include/exclude.
type PrefixedWriter ¶
type PrefixedWriter struct {
// contains filtered or unexported fields
}
PrefixedWriter is a thread-safe, line-buffered writer that prepends a color-coded job name prefix to each line. It ensures parallel goroutine output doesn't interleave mid-line — identical to Docker Compose's multiplexed output strategy.
func NewPrefixedWriter ¶
NewPrefixedWriter creates a writer that prepends a styled prefix to every line. The mutex should be shared across all parallel writers to prevent interleaving.
func (*PrefixedWriter) Flush ¶
func (pw *PrefixedWriter) Flush()
Flush writes any remaining buffered content.
type RunResult ¶
type RunResult struct {
Job string `json:"job"`
Status string `json:"status"` // "passed", "failed", "skipped"
Duration time.Duration `json:"duration"`
Steps []StepResult `json:"steps"`
}
RunResult holds the outcome of a single job execution.
func Execute ¶
func Execute(cfg ExecuteConfig) ([]RunResult, error)
Execute runs the parsed workflow according to the execution plan.
type Service ¶
type Service struct {
Image string `yaml:"image"`
Env map[string]string `yaml:"env"`
Ports []string `yaml:"ports"`
Options string `yaml:"options"`
}
Service represents a job-level service container (e.g., postgres for CI).
type Step ¶
type Step struct {
Name string `yaml:"name"`
ID string `yaml:"id"`
Uses string `yaml:"uses"`
Run string `yaml:"run"`
Shell string `yaml:"shell"`
Env map[string]string `yaml:"env"`
With map[string]string `yaml:"with"`
If string `yaml:"if"`
WorkingDirectory string `yaml:"working-directory"`
ContinueOnError bool `yaml:"continue-on-error"`
TimeoutMinutes int `yaml:"timeout-minutes"`
}
Step represents a single step within a job.
type StepResult ¶
type StepResult struct {
Name string `json:"name"`
Status string `json:"status"` // "passed", "failed", "skipped"
Duration time.Duration `json:"duration"`
Output string `json:"output,omitempty"`
}
StepResult holds the outcome of a single step.
type Strategy ¶
type Strategy struct {
Matrix MatrixDef `yaml:"matrix"`
FailFast *bool `yaml:"fail-fast"`
MaxParallel int `yaml:"max-parallel"`
}
Strategy holds the matrix strategy for a job.
type StringOrSlice ¶
type StringOrSlice []string
StringOrSlice handles YAML fields that can be either a single string or a list.
func (*StringOrSlice) UnmarshalYAML ¶
func (s *StringOrSlice) UnmarshalYAML(node *yaml.Node) error
type TemplateContext ¶
type TemplateContext struct {
Env map[string]string // workflow + job + step env
Secrets map[string]string // from devx Vault providers
Matrix map[string]string // current matrix row values
// Warnings collects non-fatal substitution issues for reporting.
Warnings []string
}
TemplateContext holds all the values available for ${{ }} expression substitution.
func NewTemplateContext ¶
func NewTemplateContext(env, secrets, matrix map[string]string) *TemplateContext
NewTemplateContext creates a TemplateContext with sensible defaults for the stubbed github.* and runner.* contexts.
func (*TemplateContext) EvaluateCondition ¶
func (tc *TemplateContext) EvaluateCondition(condition string) bool
EvaluateCondition evaluates an `if:` conditional expression. Returns true if the step/job should run.
Strategy:
- Simple equality (matrix.goos == 'linux') → exact match
- Simple inequality (matrix.goos != 'linux') → exact non-match
- Complex expressions (contains(), hashFiles()) → fail-open (return true) with warning
- Empty string → true (no condition = always run)
func (*TemplateContext) Substitute ¶
func (tc *TemplateContext) Substitute(input string) string
Substitute replaces all ${{ ... }} expressions in the input string.