Help us shape the future of Go! Take the 2026 Go Developer Survey

debugger

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package debugger: see session.go for the package doc.

Package debugger: see session.go for the package doc.

Package debugger: see session.go for the package doc.

Package debugger is actl's frontend-agnostic core (see CLAUDE.md §5). It owns the barrier-driven pause loop and the halt/pass policy; it imports no frontend, prints nothing, and owns no terminal. The TUI, a future DAP server, and the headless/agent driver are all peers that consume this API:

commands in  — Step / Continue / Abort / SetBreakpoint
events out   — PauseEvent on Pauses(), completion on Done()

It drives act through the soft-fork StepBarrier hook (third_party/act): act keeps the job container alive between step execs, so blocking inside the barrier yields a live workspace + env to inspect.

Package debugger: see session.go for the package doc.

Index

Constants

View Source
const (
	GCPAuthAction   = "google-github-actions/auth"
	AWSAuthAction   = "aws-actions/configure-aws-credentials"
	AzureAuthAction = "azure/login"
)

Auth action refs intercepted for identity handling (§4). Exported so a host-side pre-scan (cmd/actl) can keep cloud-CLI invocation lazy without re-spelling the literals.

Variables

View Source
var ErrAborted = errors.New("debugger: run aborted by user")

ErrAborted is the run error when the front-end aborts via Abort.

Functions

func StepUses added in v0.1.1

func StepUses(st *model.Step, action string) bool

StepUses reports whether step st uses action, matching both the bare ref ("owner/repo") and a pinned version ("owner/repo@v2"). The one place actl decides what "this step uses X" means.

Types

type AWSIdentity

type AWSIdentity struct {
	AccessKeyID     string // → AWS_ACCESS_KEY_ID
	SecretAccessKey string // → AWS_SECRET_ACCESS_KEY
	SessionToken    string // → AWS_SESSION_TOKEN (empty for long-lived creds)
	Account         string // local caller identity (arn), for the transparency line (best-effort)
}

AWSIdentity is the host-resolved ambient AWS credentials for the opt-in ambient fallback (CLAUDE.md §4), the AWS analog of GCPIdentity. The default is bring-a-credential (static keys, see Options.AWSAccessKeyID/AWSSecretAccessKey); ambient is used only with -aws-ambient. Unlike GCP these are env-only — no file is mounted — so the core just injects them at the step's position. Discovery is a host concern (cmd/actl).

type AuthMode added in v0.2.0

type AuthMode int

AuthMode describes how a cloud's federated auth steps were handled locally — the identity strategy is bring-a-credential by default, with ambient personal login only as an opt-in fallback (CLAUDE.md §4). One value per cloud, for the transparency line.

const (
	AuthNone        AuthMode = iota // the job has no auth step for this cloud
	AuthDeclared                    // only secret/key-mode steps — left to run as declared (faithful, untouched)
	AuthSubstituted                 // federated steps rewritten to a brought scoped credential (the default path)
	AuthAmbient                     // federated steps satisfied by the dev's ambient personal login (opt-in fallback)
	AuthUnsatisfied                 // federated steps neutralized — no credential available, cloud calls will fail
)

type ConfigSummary

type ConfigSummary struct {
	Secrets []string // secret names (sorted), values withheld
	Vars    []string // var names (sorted)
	Env     []string // env names (sorted)
}

ConfigSummary is a redacted view of the secrets/vars/env supplied to the run: the names that loaded, never their values, so a transparency line (and any screenshot of it) leaks nothing sensitive.

type DockerUnavailableError

type DockerUnavailableError struct{ Cause error }

DockerUnavailableError is returned by New when the Docker daemon can't be reached. act execs every step into a real job container, so a running daemon is a hard prerequisite; surfacing it up front (with a friendly message) beats act's cryptic mid-run failure. Cause is the underlying connection/ping error.

func (*DockerUnavailableError) Error

func (e *DockerUnavailableError) Error() string

func (*DockerUnavailableError) Unwrap

func (e *DockerUnavailableError) Unwrap() error

type EnvOverlay

type EnvOverlay struct {
	Secrets map[string]string
	Vars    map[string]string
}

EnvOverlay is a per-`environment:` overlay of secrets/vars applied when the debugged job targets that deployment environment (GHA scopes secrets/vars by `environment:`). The host (cmd/actl) resolves each environment's secret-file/inline-vars into these flat maps; the core merges the matching one over the flat defaults (CLI overrides still win — see New).

type EnvSummary

type EnvSummary struct {
	Name    string // the job's `environment:` (deployment environment), "" if none
	Secrets int    // overlay secret keys merged in
	Vars    int    // overlay var keys merged in
}

EnvSummary describes the per-`environment:` overlay applied for the debugged job, for a transparency line: the environment the job targets and how many secrets/vars its overlay contributed. Name is empty when the job targets no environment; Name set with zero counts means the job targets an environment for which no overlay was configured (the flat defaults are used as-is). Values are never retained here.

type EventSummary

type EventSummary struct {
	EventName string // the planned event (github.event_name)
	Path      string // user-supplied event JSON path, if any (else synthesized "{}")
	Synthetic bool   // payload was synthesized (no -event-file)
}

EventSummary describes the github.event payload backing the run, for a transparency line.

type GCPIdentity

type GCPIdentity struct {
	CredentialFile string // host path to the ADC json, bind-mounted ro into the container
	AccessToken    string // ambient ADC access token → CLOUDSDK_AUTH_ACCESS_TOKEN
	Account        string // local identity, for the transparency line (best-effort, may be empty)
}

GCPIdentity is the host-resolved ambient GCP credentials the CLI passes in for the opt-in ambient fallback (CLAUDE.md §4). The default identity path is bring-a-credential (a service-account key, see Options.GCPKeyJSON); ambient is used only when the dev opts in with -gcp-ambient. Locally there is no GitHub OIDC issuer, so a federated `google-github-actions/auth` (WIF) can't mint a token; ambient intercepts that step and injects the dev's already-present credentials. The core never shells out to gcloud — discovery/minting is a host concern (cmd/actl); the core only consumes the data.

type GitHubContextSummary

type GitHubContextSummary struct {
	Repository string   // github.repository (resolved from local git or overridden)
	Ref        string   // github.ref
	Sha        string   // github.sha (short, for display)
	Actor      string   // github.actor ("" → act's "nektos/act" placeholder)
	Overridden []string // which of repository/ref/sha/actor came from a flag
}

GitHubContextSummary is the resolved github.* runtime context for a transparency line: the values act will expose (repository/ref/sha/actor), which the user overrode, and a note that run ids are placeholders locally.

type IdentitySummary added in v0.2.0

type IdentitySummary struct {
	Cloud    string   // "GCP" / "AWS" / "Azure" — names the line
	Mode     AuthMode // how the federated steps were handled
	Steps    []string // intercepted federated auth step labels
	Targets  []string // federation target per federated step (as declared in the workflow)
	Declared []string // secret/key-mode step labels left to run untouched
	Account  string   // the identity we run as (brought principal, or ambient account)
	Region   string   // AWS only: the declared aws-region honored ("" otherwise)
	// Ambient-only detail (Mode == AuthAmbient), for the GCP/AWS ambient line:
	File  bool // an ambient credential file was mounted into the container (GCP)
	Token bool // an ambient access token was injected (GCP)
}

IdentitySummary is a redacted view of one cloud's identity handling for a transparency line: which federated auth steps were intercepted, the federation target each would have used in real CI, which mode satisfied them (substituted brought credential / ambient / none), and the identity we run as. No credential material is retained here. Shared by GCP, AWS, and Azure (CLAUDE.md §4).

type InputsSummary

type InputsSummary struct {
	Provided map[string]string // inputs.* the user supplied
	Defaults []string          // declared inputs not supplied (act fills their default)
	Declared bool              // the workflow declares inputs for this event
}

InputsSummary lists the workflow's declared dispatch/call inputs and which were supplied vs. left to their declared default, for a transparency line. Values are the user's own CLI inputs (not secrets), so they're shown.

type JobListing

type JobListing struct {
	ID          string
	Name        string
	Environment string   // deployment environment (`environment:`), "" if none
	Matrix      []string // combination labels ("k=v, …") when the job has more than one; nil otherwise
	Steps       []StepListing
}

JobListing is one job in a Listing.

type Listing

type Listing struct {
	WorkflowPath string
	Event        string
	Jobs         []JobListing
}

Listing is a Docker-free inventory of a workflow's jobs and steps, produced by List for `actl -list` so the user can see what they'd debug (jobs, their environment and matrix combinations, and each job's steps) without starting a container.

func List

func List(opts Options) (*Listing, error)

List parses and plans the workflow and returns its jobs and steps without touching Docker — the read-only counterpart to New, sharing the same parsePlan prefix. It does not select a single job (it lists them all), so a multi-job or matrix workflow is reported in full rather than prompting.

type MultipleJobsError

type MultipleJobsError struct{ Jobs []string }

MultipleJobsError is returned by New when the workflow has more than one job and Options.JobID did not pick one. It lists the available job ids so a frontend can prompt for a choice.

func (*MultipleJobsError) Error

func (e *MultipleJobsError) Error() string

type MultipleMatrixError

type MultipleMatrixError struct {
	Job    string
	Combos []string // candidate combinations as "k=v, k2=v2" labels, sorted
}

MultipleMatrixError is returned by New when the selected job is a matrix job and the supplied -matrix selection does not pin it to a single combination (debugging one job means debugging one combination). It lists the candidates that remain so a frontend can prompt; the same shape as MultipleJobsError.

func (*MultipleMatrixError) Error

func (e *MultipleMatrixError) Error() string

type NeedsInput

type NeedsInput struct {
	Outputs map[string]string
	Result  string
}

NeedsInput seeds an upstream job's contribution to the needs context when a downstream job is debugged in isolation (the upstream job is not run). Outputs holds only the keys the user provided; Result defaults to "success" if empty.

type NeedsSummary

type NeedsSummary struct {
	Job     string
	Live    bool
	Result  string
	Assumed bool
	Outputs map[string]string
}

NeedsSummary describes how one of the selected job's needs was satisfied locally, for a transparency line. With Live (the --with-deps mode) the upstream job runs for real and the seeded fields are unused; otherwise Result is the effective value (Assumed when defaulted) and Outputs holds the seeded keys.

type Options

type Options struct {
	WorkflowPath    string                     // path to the workflow file
	EventName       string                     // event to plan for (default "push")
	JobID           string                     // which job to debug; required only if the event plans more than one
	Matrix          map[string]map[string]bool // matrix combination to pin (act's Config.Matrix shape: key→value→true); required only if the job's matrix has more than one combination
	WithDeps        bool                       // run the job's upstream needs for real (to completion) before debugging it, instead of isolating
	Image           string                     // docker image mapped to ubuntu-latest when Images is empty (default catthehacker); back-compat sugar for Images
	Images          map[string]string          // runner label → docker image (act's -P/Platforms map); empty falls back to {ubuntu-latest: Image}
	Workdir         string                     // workspace bind-mounted into the container so local 'uses: ./' actions resolve; empty = an isolated empty temp dir (steps can't write to your tree). NOTE: a set workdir is mounted, so steps can write to it
	Source          string                     // working tree a default actions/checkout copies into the workspace (no host mutation); empty = current dir. Ignored when Workdir is set
	Secrets         map[string]string          // secrets.* base (flat defaults, e.g. from secret-file); the env overlay and SecretOverrides layer on top
	Vars            map[string]string          // vars.* base (flat defaults); the env overlay and VarOverrides layer on top
	Env             map[string]string          // extra env for containers
	Environments    map[string]EnvOverlay      // per-`environment:` secrets/vars overlays, keyed by environment name; the one matching the debugged job's `environment:` is merged over Secrets/Vars
	SecretOverrides map[string]string          // secrets.* applied last (after the env overlay) so an explicit CLI -secret wins; nil for library callers
	VarOverrides    map[string]string          // vars.* applied last (after the env overlay) so an explicit CLI -var wins; nil for library callers
	// Cloud identity (CLAUDE.md §4). The default is bring-a-credential: a scoped
	// non-personal credential rewrites a federated auth step to its secret/key mode so
	// the real action runs. Ambient personal login is an opt-in fallback (GCP/AWS only;
	// Azure has none) — non-nil GCP/AWS means -…-ambient was set and the creds resolved.
	GCPKeyJSON         string                // service-account key JSON content → rewrites a federated google-github-actions/auth to credentials_json mode
	AzureCredsJSON     string                // service-principal creds JSON content → rewrites a federated azure/login to creds mode
	AWSAccessKeyID     string                // brought static access key id → rewrites a federated aws-actions/configure-aws-credentials to static-key mode
	AWSSecretAccessKey string                // brought static secret access key (paired with AWSAccessKeyID)
	GCP                *GCPIdentity          // ambient GCP creds for the opt-in fallback (nil unless -gcp-ambient)
	AWS                *AWSIdentity          // ambient AWS creds for the opt-in fallback (nil unless -aws-ambient)
	Needs              map[string]NeedsInput // seeded needs.<job>.* for isolated debugging, keyed by upstream job id (ignored with WithDeps)
	BreakOnError       bool                  // in Continue mode, halt after a step that errored
	Breakpoints        []int                 // zero-based step indices to halt before, in Continue mode
	BreakpointNames    []string              // step names to halt before, resolved to indices against the job's steps in New (a name with no matching step is an error)

	// Runtime context GitHub injects in real CI that a clean local runner lacks
	// — all seed-and-be-honest surfaces (CLAUDE.md §4), each with a transparency line.
	GitHubToken string            // GITHUB_TOKEN → github.token (and mirrored into secrets.GITHUB_TOKEN); empty falls back to Secrets["GITHUB_TOKEN"]
	Inputs      map[string]string // workflow_dispatch/workflow_call inputs.* (user values; act applies declared defaults + typing on top)
	EventPath   string            // path to a github.event payload JSON; empty = "{}" (plus any Inputs)
	Repository  string            // override github.repository (env GITHUB_REPOSITORY); empty = act derives from local git
	Ref         string            // override github.ref (env GITHUB_REF); empty = act derives from local git
	Sha         string            // override github.sha (env SHA_REF, act's read key); empty = act derives from local git
	Actor       string            // override github.actor (Config.Actor); empty = act's "nektos/act" placeholder
	// GitHubOverrides names the github.* fields the user set explicitly by flag (any of
	// "repository"/"ref"/"sha"/"actor"), so the transparency line marks those as overrides.
	// The values above may also be filled from local git for an honest display — only an
	// entry here means the user overrode it, not merely that the value is non-empty.
	GitHubOverrides []string
}

Options configures a debug Session. Only WorkflowPath is required.

type PauseEvent

type PauseEvent struct {
	When  When        // before or after the step's main executor
	Index int         // zero-based step index within the job
	Step  *model.Step // the step at this boundary
	Err   error       // for When==After: the step's error, or nil
}

PauseEvent is emitted when the run halts at a step boundary.

type ProgressEvent added in v0.1.1

type ProgressEvent struct {
	Index int         // zero-based step index now starting
	Step  *model.Step // the step at this boundary
}

ProgressEvent is emitted as the run passes a step's "before" boundary without halting (Continue mode, no breakpoint), so a frontend can follow execution — the step-list highlight tracks the running step even when no pause fires. It's purely advisory: the send is non-blocking and may be dropped under load, and the authoritative state is still PauseEvent/Done. Emitted only for the debugged job.

type ServicesSummary

type ServicesSummary struct {
	Names []string // service container names (sorted)
}

ServicesSummary lists the names of the job's `services:` containers, for a transparency line. act starts these natively when the job runs; actl only surfaces that they will start. Empty when the job declares no services.

type Session

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

Session is one debug run of a single job. Construct with New, then Start.

func New

func New(opts Options) (*Session, error)

New parses the workflow, plans the chosen job, and wires the pause barrier. It does not start execution; call Start. v0.1 debugs a single job: if the event plans more than one, Options.JobID must pick one (else a MultipleJobsError lists the choices).

func (*Session) AWSSummary

func (s *Session) AWSSummary() IdentitySummary

AWSSummary returns the redacted view of the AWS identity handling, for a transparency line. Its Steps/Declared are empty when the job has no aws-actions/configure-aws-credentials step.

func (*Session) Abort

func (s *Session) Abort()

Abort resumes with an order to stop the job (the run ends with ErrAborted).

func (*Session) AzureSummary added in v0.2.0

func (s *Session) AzureSummary() IdentitySummary

AzureSummary returns the redacted view of the Azure identity handling, for a transparency line. Azure has no ambient fallback (CLAUDE.md §4). Its Steps/Declared are empty when the job has no azure/login step.

func (*Session) CanRerun

func (s *Session) CanRerun() bool

CanRerun reports whether Rerun is available — only after a step's main has run (rerunning before it would double-execute on resume).

func (*Session) CheckoutSource

func (s *Session) CheckoutSource() string

CheckoutSource is the host working tree copied into the workspace at checkout time; empty when there's nothing to copy (e.g. a -workdir mount already holds the code, or there were no intercepted checkouts).

func (*Session) CheckoutSteps

func (s *Session) CheckoutSteps() []string

CheckoutSteps returns the labels of default `actions/checkout` steps that were intercepted (rewritten to no-ops), for a transparency line. Empty when none.

func (*Session) ConfigSummary

func (s *Session) ConfigSummary() ConfigSummary

ConfigSummary returns the redacted names of the secrets/vars/env supplied to the run (values withheld), for a transparency line.

func (*Session) ContainerName

func (s *Session) ContainerName() string

ContainerName is the docker name of the live job container at the current pause (empty while running or if no container is in use). A frontend can drop an interactive shell into it; the core stays out of the terminal (CLAUDE.md §5).

func (*Session) Continue

func (s *Session) Continue()

Continue resumes and runs until a breakpoint, a break-on-error stop, or the end of the job.

func (*Session) CurrentRun

func (s *Session) CurrentRun() string

CurrentRun returns the paused step's `run:` script (empty for a `uses:` step or while running) — for pre-filling an editor before Rerun.

func (*Session) Done

func (s *Session) Done() <-chan struct{}

Done is closed when the run has finished (successfully, with an error, or aborted). Read Err afterwards.

func (*Session) Env

func (s *Session) Env() map[string]string

Env returns a copy of the job's environment captured at the current pause, or nil while the run is executing. Inspection is only meaningful while paused.

func (*Session) EnvSummary

func (s *Session) EnvSummary() EnvSummary

EnvSummary returns the per-`environment:` overlay applied for the debugged job (the environment it targets and how many secrets/vars its overlay contributed), for a transparency line. Its Name is empty when the job targets no environment.

func (*Session) Err

func (s *Session) Err() error

Err returns the run result. Only valid once Done is closed.

func (*Session) EventSummary

func (s *Session) EventSummary() EventSummary

EventSummary reports the github.event payload backing the run, for a transparency line.

func (*Session) GCPSummary

func (s *Session) GCPSummary() IdentitySummary

GCPSummary returns the redacted view of the GCP identity handling (which auth steps were intercepted, the federation target, and how they were satisfied), for a transparency line. Its Steps/Declared are empty when the job has no auth step.

func (*Session) GitHubContextSummary

func (s *Session) GitHubContextSummary() GitHubContextSummary

GitHubContextSummary reports the resolved github.* runtime context (repository/ ref/sha/actor and any overrides), for a transparency line.

func (*Session) InputsSummary

func (s *Session) InputsSummary() InputsSummary

InputsSummary reports the workflow's declared inputs and which were supplied vs defaulted, for a transparency line. Declared is false when the event takes no inputs.

func (*Session) JobID

func (s *Session) JobID() string

JobID is the id of the job being debugged.

func (*Session) LocalUsesSteps

func (s *Session) LocalUsesSteps() []string

LocalUsesSteps returns the labels of steps that reference a local action (`uses: ./…`) — these need a real workspace (run with a workdir set).

func (*Session) Logs

func (s *Session) Logs() <-chan string

Logs delivers act's output line by line (job + step logs, with secrets masked). Drain it concurrently; it is buffered but a frontend should keep reading.

func (*Session) NeedsSummary

func (s *Session) NeedsSummary() []NeedsSummary

NeedsSummary reports how the selected job's needs were satisfied (seeded in isolation, or live with --with-deps), for a transparency line. Empty when the job has no needs.

func (*Session) Pauses

func (s *Session) Pauses() <-chan PauseEvent

Pauses delivers a PauseEvent each time the run halts. The run stays blocked until a control method (Step/Continue/Abort) is called.

func (*Session) Progress added in v0.1.1

func (s *Session) Progress() <-chan ProgressEvent

Progress delivers an advisory ProgressEvent as each step starts while the run is passing through (Continue mode), letting a frontend track the running step without a halt. The channel is buffered and lossy — the run never blocks on it — so it's a hint, not a guarantee; Pauses/Done remain authoritative. Optional to consume.

func (*Session) Rerun

func (s *Session) Rerun() error

Rerun re-executes the paused step's main in the live container, picking up any SetRun/SetEnv edits. It blocks until the step finishes; output arrives on Logs(). Only valid while paused after a step has run.

func (*Session) ServicesSummary

func (s *Session) ServicesSummary() ServicesSummary

ServicesSummary returns the names of the job's `services:` containers (which act starts natively when the job runs), for a transparency line. Empty when none.

func (*Session) SetBreakpoint

func (s *Session) SetBreakpoint(index int, on bool)

SetBreakpoint toggles a halt before the step at the given zero-based index (consulted in Continue mode). Safe to call before Start or while paused.

func (*Session) SetEnv

func (s *Session) SetEnv(key, value string)

SetEnv sets or overrides a job env var in memory. The next Rerun (and later steps) see it. No-op while running.

func (*Session) SetRun

func (s *Session) SetRun(script string)

SetRun replaces the paused step's `run:` script in memory (the file on disk is untouched). The next Rerun picks it up. No-op while running.

func (*Session) Start

func (s *Session) Start(ctx context.Context)

Start launches the run in the background. The run halts at the first barrier (before the first step) per the default Step mode; drive it via the control methods and Pauses. Done is closed when the run finishes.

func (*Session) Step

func (s *Session) Step()

Step resumes and halts again at the next barrier.

func (*Session) Steps

func (s *Session) Steps() []*model.Step

Steps returns the job's steps in declaration order (for rendering a step list before the run starts).

func (*Session) TokenSummary

func (s *Session) TokenSummary() TokenSummary

TokenSummary reports how github.token was satisfied (set from a flag/secret, or absent), for a transparency line.

func (*Session) WithDeps

func (s *Session) WithDeps() bool

WithDeps reports whether the job's upstream needs run for real before it.

func (*Session) Workspace

func (s *Session) Workspace() string

Workspace returns the bind-mounted workspace path, or empty when isolated. When non-empty, steps run in the container can write to this path on the host.

func (*Session) WorkspaceIsolated

func (s *Session) WorkspaceIsolated() bool

WorkspaceIsolated reports whether the run uses an empty temp workspace (no user repo), in which case local `uses: ./…` actions and checkout can't resolve.

type StepListing

type StepListing struct {
	Index int
	Label string // step display label (name / uses / run)
	Kind  string // run / docker / local / remote / reusable
}

StepListing is one step in a JobListing.

type TokenSummary

type TokenSummary struct {
	Present bool   // github.token (and secrets.GITHUB_TOKEN) was set
	Source  string // "flag", "secret", or "" when absent
}

TokenSummary is a redacted view of the GITHUB_TOKEN substitution for a transparency line: whether github.token was set and where it came from, never the token itself.

type When

type When int

When marks which side of a step's main executor a pause occurred on. It mirrors the fork's runner.BarrierWhen but keeps act's type out of frontend code.

const (
	Before When = iota // before the step's main executor ran
	After              // after the step's main executor returned
)

func (When) String

func (w When) String() string

Jump to

Keyboard shortcuts

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