gha

package
v0.1.0-rc.3 Latest Latest
Warning

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

Go to latest
Published: Sep 18, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package gha observes GitHub Actions workflow runs: it waits for a run's jobs to complete, collects the run's artifacts as attestation subjects, and renders the run as a SLSA build provenance predicate.

The job watching and artifact collection logic is ported from the tejolote attester (kubernetes-sigs/tejolote, Apache-2.0, Copyright The Kubernetes Authors), adapted to feed the slsa-attester library.

Index

Constants

View Source
const BuildType = "https://slsa.dev/buildtypes/watcher/v1"

BuildType is the SLSA build type URI for provenance generated by watching a build system run from the outside.

Variables

This section is empty.

Functions

func ParseSpec

func ParseSpec(spec string) (owner, repo string, runID int64, err error)

ParseSpec parses a github://owner/repo/runID run spec.

func SpecFromEnvironment

func SpecFromEnvironment() string

SpecFromEnvironment derives the current run's spec from the environment the GitHub Actions runner sets, or "" when not running in GitHub Actions.

Types

type ArtifactOptions

type ArtifactOptions struct {
	// Expand controls how artifacts are hashed. When true each artifact zip
	// is unpacked and every contained file becomes its own subject, named
	// "<artifact>/<path in zip>". When false each artifact archive is hashed
	// as a single subject.
	Expand bool
	// Filter, when non-empty, is a list of globs (path.Match syntax) matched
	// against artifact names; only matching artifacts are collected.
	Filter []string
}

ArtifactOptions tune how the run's artifacts are collected.

type Client

type Client struct {
	Owner string
	Repo  string
	RunID int64
	// contains filtered or unexported fields
}

Client watches one GitHub Actions workflow run.

func New

func New(spec string) (*Client, error)

New returns a Client for the run identified by a github://owner/repo/runID spec. The GitHub API client authenticates with $GITHUB_TOKEN when set.

func (*Client) CollectArtifacts

func (c *Client) CollectArtifacts(ctx context.Context, opts ArtifactOptions) ([]*intoto.ResourceDescriptor, error)

CollectArtifacts downloads the run's GitHub Actions artifacts and returns one resource descriptor per attested file.

func (*Client) CollectReleaseAssets

func (c *Client) CollectReleaseAssets(ctx context.Context, tag string, filter []string) ([]*intoto.ResourceDescriptor, error)

CollectReleaseAssets returns one resource descriptor per asset of the release tagged tag in the watched repository. The digests come straight from the API, which records them as algorithm:hex when the asset is uploaded; assets predating GitHub's digest computation are downloaded and hashed as a fallback. The filter globs, when given, restrict collection by asset name.

func (*Client) Predicate

func (c *Client) Predicate(run *gogithub.WorkflowRun, ref string, inputs map[string]any) (*buildv1.Provenance, error)

Predicate renders the watched run as a SLSA build provenance v1 predicate. The builder is the workflow that ran; the source repository at the run's commit is recorded as a resolved dependency. The ref (from RunRef) and the inputs (from RunInputs) are recorded in the external parameters.

func (*Client) RunInputs

func (c *Client) RunInputs(ctx context.Context, run *gogithub.WorkflowRun) map[string]any

RunInputs returns the workflow inputs of the watched run for the provenance's external parameters. When running inside the attested run the actual values come from the triggering event's payload; otherwise the workflow definition is fetched at the run's commit and the declared defaults are recorded, since the API does not expose the values a triggerer overrode. Inputs are best-effort: failures are logged and an empty map returned, so a deleted workflow file does not fail the attestation.

func (*Client) RunRef

func (c *Client) RunRef(ctx context.Context, run *gogithub.WorkflowRun) string

RunRef returns the fully-qualified git ref the run built. Inside the attested run the runner's own GITHUB_REF is exact. For other runs the ref name is resolved through the git refs API, because the runs API reports a tag's name in head_branch, indistinguishable from a branch. When nothing resolves, the name is assumed to be a branch; with no name at all the head commit is returned.

func (*Client) SetAPIClient

func (c *Client) SetAPIClient(gh *gogithub.Client)

SetAPIClient replaces the GitHub API client (for tests).

func (*Client) Wait

func (c *Client) Wait(ctx context.Context, opts WatchOptions) (*gogithub.WorkflowRun, error)

Wait polls the watched run until it completes and returns its final state.

When the process is running inside the very run it is watching, waiting for the whole run to complete would deadlock: the watcher's own job is part of the run. In that case the watcher switches to job-level watching and excludes its own job, resolved through the runner name because the jobs API reports display names while $GITHUB_JOB only carries the YAML key.

type WatchOptions

type WatchOptions struct {
	// Jobs restricts watching to these job names (YAML keys or display
	// names). Empty means every job in the run.
	Jobs []string
	// Timeout is the maximum time to wait for the run to complete. Zero
	// disables the timeout.
	Timeout time.Duration
	// PollInterval is how often the run is polled (default 15s).
	PollInterval time.Duration
	// AllowSharedJob skips the dedicated-job check when attesting the run
	// the watcher itself runs in. See checkDedicatedJob for why sharing a
	// job with build steps is refused by default.
	AllowSharedJob bool
}

WatchOptions tune how a run is watched.

Jump to

Keyboard shortcuts

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