release

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package release holds the pure, table-driven-testable logic that the release CI workflows depend on: the release-PR title grammar, the git-tag grammar, the typed release-kind derivation, and the final-release guard decision.

Everything here is deliberately side-effect-free so the negative paths (a malformed title, a non-release tag, a final release with no proven rc) are unit-testable BEFORE they run in a workflow. The thin CLI in cmd/release-guard wires these functions to real git/gh queries; the workflows shell out to that CLI.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFastForward = errors.New("release: ref update rejected as non-fast-forward — the ref advanced since its tip was read; re-read the ref tip and retry the bubble")

ErrNotFastForward is returned (wrapped) by GitHubClient.UpdateRefFastForward when GitHub rejects a ref update because it would not be a fast-forward (HTTP 422 whose message says "...is not a fast forward"). With the update forced to a non-clobbering fast-forward compare-and-swap, this is the server-side signal that the ref advanced since its tip was read: the bubble caller re-reads the ref tip and retries. A 422 for any OTHER reason (bad SHA, malformed ref) is surfaced as its own actionable error, never misreported as non-fast-forward.

Functions

func AssembleMessage

func AssembleMessage(subject string, p PRProvenance) string

AssembleMessage joins a caller-provided subject with the provenance's git trailers in the fixed order Closes / Approved-by / Reviewed-by / Co-authored-by (a blank line separates the subject from the trailer block; a subject with no trailers is returned as-is). Every trailer value is line-flattened so it cannot inject extra lines or a forged trailer.

It is the SINGLE SOURCE of the bubble trailer grammar: BubbleMergeMessage uses it (with the canonical "Merge PR #<n>: <title>" subject), and the bubble orchestrator's no-PR fallback reuses it (with its own "Merge commit <sha>" subject) so the trailer format is never re-implemented across the boundary.

func BubbleMergeMessage

func BubbleMergeMessage(p PRProvenance) string

BubbleMergeMessage renders the merge-commit message for a bubble M from the resolved PR provenance: a single-line subject, then (if any trailers exist) a blank line and the git trailers in fixed order — Closes, Approved-by, Reviewed-by, Co-authored-by. It is deliberately NOT the PR body; the squash commit already carries the title + body, so M records only the merge provenance.

Both the subject and every trailer value are forced single-line (any CR/LF/tab is collapsed to a space) so neither a multi-line title nor a multi-line trailer value can break the subject/trailer structure or inject a forged trailer. When the title is empty/unresolved the subject falls back to "Merge PR #<n>".

func CheckFinal

func CheckFinal(final Version, evidence FinalEvidence, policy FinalPolicy) error

CheckFinal decides whether a FINAL release may proceed.

A final release is permitted only if at least one same-base-version release candidate exists that is BOTH (a) green — its release.yml run succeeded — AND (b) an ancestor of the final commit. This enforces the "final ⇒ proven rc on the same commit lineage" invariant inside the pipeline rather than by convention. rc-to-final tree identity is impossible (they are different merge commits by construction), so ancestry is the strongest cheap invariant.

CheckFinal is pure: the caller supplies the observed rc statuses. It returns nil to proceed, or an actionable error naming exactly which condition failed for every candidate considered.

func CheckReleaseWorkflowFile

func CheckReleaseWorkflowFile(workflowPath string, policy WorkflowPolicy) error

CheckReleaseWorkflowFile validates the workflow file at workflowPath against the supplied per-repo WorkflowPolicy: every JobRule's job must exist, declare the required needs-edges, and (for reusable gates or a required permission scope) match the ReusableRule / PermissionsRule.

func IsMaintainer

func IsMaintainer(perm CollaboratorPermission) bool

IsMaintainer reports whether a collaborator permission grants release- maintainer authority (may open OR approve a release PR).

This is the SINGLE source of the maintainer predicate. Both release-pr.yml gates — the PR-author check and the approver check — consume it via `release-guard check-maintainer`, so the {admin, maintain} set is defined exactly once (no duplicated `admin|maintain` shell case across jobs).

func LatestApprovers

func LatestApprovers(reviews []Review) []string

LatestApprovers returns logins whose latest non-COMMENTED review is APPROVED. Plain comments do not withdraw or shadow a standing approval.

The "latest" review is determined by input slice order: the loop below is intentionally last-write-wins per reviewer. The release-guard caller feeds this from GitHub's pull-request reviews API, which returns reviews in ascending chronological/id order, and that order is preserved through `gh api --paginate --slurp` and parseReviews flattening. This id/input order is preferred over sorting by submitted_at because GitHub IDs are stable and order-preserving even when multiple reviews have same-second submitted_at timestamps.

func ParseReleaseTitle

func ParseReleaseTitle(title string) (Version, ReleaseKind, error)

ParseReleaseTitle parses a release-PR title of the form "release(vX.Y.Z): subject" or "release(vX.Y.Z-rcN): subject" and returns the validated version and its kind.

On any grammar violation it returns (KindInvalid, error) with an actionable message describing the expected shape and a concrete example. This is the single implementation of the title grammar; the workflows must NOT re-encode it inline.

func ParseTag

func ParseTag(tag string) (Version, ReleaseKind, error)

ParseTag parses a git tag as a schema release reference. It accepts ONLY bare "vX.Y.Z[-rcN]" tags; namespaced tags such as the legacy "pkg/schema/v1.2.3" (retained from when this module was nested in peasant) are rejected because they are not releases of THIS module and must never trigger the release pipeline. (The release.yml trigger filter `v*` already excludes pkg/schema/v* by name; this parse is the defense-in-depth guard inside the workflow.)

func RunGreenForCommit

func RunGreenForCommit(runs []WorkflowRun, commitSHA string) bool

RunGreenForCommit reports whether runs contains a completed, successful run of the workflow for commitSHA. It is the pure, table-testable predicate lifted out of the old runGreen's inline scan: a tag run's HeadSHA is the tagged commit, so a later success on the same commit is also accepted. Matching on the commit SHA (rather than the latest run) keeps the rule independent of run ordering or the now-dropped 100-run client-side cap.

Types

type BubbleDecision

type BubbleDecision int

BubbleDecision is the typed outcome of evaluating whether (and how) a freshly squash-merged commit should be "bubbled" into the develop history as a merge-commit triangle (T -> M, parents [T, S], M.tree == S.tree).

It is a strongly-typed enum (per the repo's no-stringly-typed-API rule) so the orchestrator branches on named constants and never compares bare strings. All safety-relevant branching lives in DecideBubble — never in workflow bash.

const (
	// BubbleProceed: develop's tip is exactly the squash S (a single-parent
	// commit at S.tree). The bubble merge-commit M should be built and the ref
	// fast-forwarded S -> M.
	BubbleProceed BubbleDecision = iota
	// BubbleSkipNotSquash: the target commit is not a single-parent squash
	// (S.parentCount != 1), so it is not an eligible squash-merge. Skip, exit 0.
	BubbleSkipNotSquash
	// BubbleSkipAlreadyBubbled: develop's tip is already the bubble merge-commit
	// for S (a two-parent merge whose tree equals S.tree, distinct from S).
	// Re-running on an already-bubbled tip is a no-op. Skip, exit 0.
	BubbleSkipAlreadyBubbled
	// BubbleRetryTipAdvanced: develop's tip has advanced to some other commit
	// (its tree differs from S.tree and it is not S), so the read is stale. The
	// orchestrator must re-read the tip and re-decide (bounded retry).
	BubbleRetryTipAdvanced
)

func DecideBubble

func DecideBubble(f BubbleFacts) BubbleDecision

DecideBubble maps topology facts to a typed decision with the PINNED precedence:

NotSquash(SParentCount != 1) > AlreadyBubbled > TipAdvanced > Proceed

Precedence only matters where facts overlap; the canonical overlaps are:

  • NotSquash dominates everything: a non-single-parent S is never bubbled, regardless of what the tip looks like.
  • AlreadyBubbled vs TipAdvanced: both have tip != S. A tip that is a genuine two-parent merge at S.tree is the already-built bubble (no-op), NOT a "tip advanced" retry (B12).

func (BubbleDecision) String

func (d BubbleDecision) String() string

String renders the decision for CLI output, logs, and error messages.

type BubbleFacts

type BubbleFacts struct {
	// SParentCount is the number of parents of the target squash commit S. A
	// native squash-merge produces a single-parent commit, so the only eligible
	// value is 1; anything else means S is not a squash (B4 / R-B).
	SParentCount int
	// TipParentCount is the number of parents of develop's current tip. A bubble
	// merge-commit M has two parents [T, S]; this distinguishes a genuine bubble
	// tip from an unrelated same-tree commit when classifying AlreadyBubbled.
	TipParentCount int
	// TipTreeEqualsS reports whether develop's tip has the same tree as S. A
	// bubble M is built with M.tree == S.tree, so a two-parent tip at S.tree is
	// the already-bubbled state.
	TipTreeEqualsS bool
	// TipEqualsS reports whether develop's tip is the squash S itself (the
	// just-fast-forwarded, ready-to-bubble state).
	TipEqualsS bool
}

BubbleFacts are the side-effect-free topology facts the orchestrator reads from the GitHub Git Data API (the squash S and develop's current tip) and feeds to DecideBubble. Keeping the decision a pure function of these facts is what makes every branch (B12 precedence) unit-testable BEFORE any protected branch is written.

func BubbleFactsFromCommits

func BubbleFactsFromCommits(squash, tip GitCommit) BubbleFacts

BubbleFactsFromCommits derives the pure BubbleFacts that DecideBubble consumes from the SLICE-1 git-data own-types: a candidate squash commit S and develop's current tip commit. It is the mechanical realignment from the GitHub Git Data projection (release.GitCommit) onto the decision's topology facts, so callers resolve facts from own-types instead of hand-assembling a BubbleFacts literal.

It is a PURE projection of the two commits. Choosing WHICH commit is the candidate S for a given tip (e.g. a two-parent merge's second parent) and any safety reclassification of a stable non-bubble merge tip remain the orchestrator's responsibility — this function only maps (S, tip) -> facts.

type BubbleItem

type BubbleItem struct {
	Squash  Squash
	Message string
}

BubbleItem is a fully pre-resolved unit of work for the Bubbler: the squash to bubble plus its rendered merge-commit Message. The orchestrator resolves provenance and renders Message via BubbleMergeMessage so that the Bubbler (the I/O layer) carries no provenance logic and creates exactly one M per item in a drain-all chain, each M carrying its own PR's trailers.

type CollaboratorPermission

type CollaboratorPermission string

CollaboratorPermission is a GitHub repository collaborator permission level — the `.permission` field returned by the collaborators API. Typed per the repo's no-stringly-typed rule so the maintainer predicate compares against named constants, not bare strings.

const (
	PermAdmin    CollaboratorPermission = "admin"
	PermMaintain CollaboratorPermission = "maintain"
	PermWrite    CollaboratorPermission = "write"
	PermTriage   CollaboratorPermission = "triage"
	PermRead     CollaboratorPermission = "read"
	PermNone     CollaboratorPermission = "none"
)

func (CollaboratorPermission) String

func (p CollaboratorPermission) String() string

String renders the permission for CLI output and error messages.

type CompletionStatus

type CompletionStatus string

CompletionStatus is derived from the repository's published release record. Unknown is the zero value so a skipped or failed lookup cannot authorize a bootstrap.

const (
	CompletionUnknown    CompletionStatus = ""
	CompletionIncomplete CompletionStatus = "incomplete"
	CompletionSucceeded  CompletionStatus = "succeeded"
)

type FinalEvidence

type FinalEvidence struct {
	RCs                    []RCStatus
	ProductTagScan         ProductTagScanStatus
	PriorReleases          []Version
	InitialFinalCompletion CompletionStatus
}

FinalEvidence is the repository evidence used to decide whether a final may proceed. PriorReleases excludes the tag currently being checked.

type FinalPolicy

type FinalPolicy struct {
	InitialFinal Version
}

FinalPolicy controls the one narrow exception to the normal final-release rule. An empty InitialFinal keeps the ordinary same-version ancestor-rc requirement. A non-empty value permits only that exact final version, and only while the repository has no prior product releases.

type GitCommit

type GitCommit struct {
	// SHA is the commit's own object SHA (server-assigned on create).
	SHA string
	// TreeSHA is the SHA of the tree this commit points at. A bubble merge commit
	// M over squash S carries S's tree, so M.TreeSHA == S.TreeSHA.
	TreeSHA string
	// ParentSHAs are the parent commit SHAs in order. For a bubble merge commit M
	// over squash S onto tip T, ParentSHAs is [T, S] (first-parent T).
	ParentSHAs []string
	// Message is the commit message. The bubble orchestrator reads a squash
	// commit's message to recover its "(#n)" PR suffix, Co-authored-by trailers,
	// and Closes/Fixes issue references when building the bubble merge message.
	Message string
}

GitCommit is the subset of a git commit object the bubble needs: its own SHA, the tree it points at, and its parents (first-parent first). It is the decoded shape of both "get a commit" (GET git/commits/{sha}) and the "create a commit" (POST git/commits) response, so the same own-type serves the not-a-squash / already-bubbled decisions and the created merge commit.

type GitRef

type GitRef struct {
	// SHA is the object SHA the reference points at — the tip the bubbler reads
	// before it fast-forwards the ref.
	SHA string
}

GitRef is a git reference resolved to the commit SHA it points at. It is the own-type projection of GitHub's Git Data "get a reference" response (mirroring Review / WorkflowRun / CollaboratorPermission) so the squash-merge bubble orchestrator never touches a *github.Reference and the go-github pointer-field nil-guards stay at the cmd/release-guard wrapper boundary.

type JobRule

type JobRule struct {
	Name        string           `yaml:"name"`
	Needs       []string         `yaml:"needs"`
	Reusable    *ReusableRule    `yaml:"reusable"`
	Permissions *PermissionsRule `yaml:"permissions"`
	Environment string           `yaml:"environment"`
}

JobRule constrains a single workflow job. Name is required; Needs lists the required needs-edges; Reusable (when non-nil) requires the job to be a reusable-workflow gate matching the ReusableRule; Permissions (when non-nil) requires the job's own `permissions:` block to grant the scopes in PermissionsRule; Environment (when non-empty) requires the job's `environment:` to equal it - scoping which GitHub Actions environment (and therefore, for an OIDC-trusted-publishing job, which environment's protection rules) the job runs under.

Permissions/Environment recognize only the exact forms this repo's workflows use - the explicit `permissions:` map (not the `read-all`/`write-all` bare scalar shorthand) and a bare scalar `environment:` (not the `{name, url}` mapping form). GitHub accepts all of those forms; this checker intentionally does not parse the unrecognized ones (rather than silently mis-accept or mis-reject them) and instead fails closed with an error naming the unsupported form, per checkJobPermissionsAgainstRule / checkJobEnvironmentAgainstRule below.

type NewCommit

type NewCommit struct {
	// Message is the commit message.
	Message string
	// TreeSHA is the SHA of the tree the new commit points at.
	TreeSHA string
	// ParentSHAs are the parent commit SHAs in order (first-parent first). For a
	// bubble merge commit M over squash S onto tip T, this is [T, S].
	ParentSHAs []string
}

NewCommit is the input to GitHubClient.CreateCommit: the fields the caller supplies to build a git commit via the Git Data API. Kept distinct from GitCommit (the response own-type) so the created SHA is not something a caller can pretend to know before the server assigns it.

type PRProvenance

type PRProvenance struct {
	// Number is the pull-request number for the "Merge PR #<n>" subject.
	Number int
	// Title is the PR title; when empty the subject falls back to "Merge PR #<n>".
	Title string
	// ClosesIssues renders one "Closes #<issue>" trailer per entry, in order.
	ClosesIssues []int
	// ApprovedBy renders one "Approved-by: <value>" trailer per entry, in order.
	// Sourced from LatestApprovers over the PR's reviews.
	ApprovedBy []string
	// ReviewedBy renders one "Reviewed-by: <value>" trailer per entry, in order.
	ReviewedBy []string
	// CoAuthoredBy renders one "Co-authored-by: <value>" trailer per entry; each
	// value is already in "Name <email>" form.
	CoAuthoredBy []string
}

PRProvenance is the per-PR attribution resolved by the orchestrator from the GitHub API and rendered into a bubble merge-commit's trailers by BubbleMergeMessage. It carries the data for the subject and the Closes/Approved-by/Reviewed-by/Co-authored-by trailers — NOT the PR body (the squash commit already carries the title + body).

type PermissionsRule

type PermissionsRule struct {
	IDToken bool `yaml:"idToken"`
}

PermissionsRule constrains a job's own `permissions:` block. IDToken (when true) requires `permissions.id-token: write` on the job - the scope an OIDC trusted-publishing step (e.g. `pnpm publish` to npm) needs to mint its token. Job-level `permissions:` REPLACES the workflow-level default entirely (GitHub Actions does not merge the two), so this checks the job's own block, not the workflow top level.

type ProductTagScanStatus

type ProductTagScanStatus string

ProductTagScanStatus proves whether the complete product-tag scan succeeded. The zero value is deliberately unproven so omitted evidence fails closed.

const (
	ProductTagScanUnproven ProductTagScanStatus = ""
	ProductTagScanComplete ProductTagScanStatus = "complete"
)

type Pull

type Pull struct {
	// Number is the pull request number.
	Number int
	// Title is the pull request title.
	Title string
	// Body is the pull request body (markdown), available for provenance context.
	Body string
}

Pull is the subset of a GitHub pull request the bubbler needs to build per-PR provenance in the bubble merge message: the number and title (body carried for context). Own-type projection of the "get a pull request" response so the policy layer stays free of any go-github import.

type RCStatus

type RCStatus struct {
	// Tag is the release-candidate tag, e.g. v0.1.0-rc1.
	Tag Version `yaml:"tag"`
	// RunGreen is true when the rc tag's release.yml run completed successfully.
	RunGreen bool `yaml:"runGreen"`
	// IsAncestor is true when the rc tag's commit is an ancestor of the final
	// release commit (the final was tagged on a descendant of the proven rc).
	IsAncestor bool `yaml:"isAncestor"`
}

RCStatus is the observed state of one release-candidate tag relative to a pending final release: whether its release.yml run was green, and whether the rc tag is an ancestor of the final release commit (git merge-base --is-ancestor). The CLI populates these from real git/gh queries; CheckFinal consumes them as pure data.

type ReleaseKind

type ReleaseKind string

ReleaseKind classifies a release reference (a PR title or a git tag) as a release candidate, a final release, or an invalid/unrecognized reference.

It is a strongly-typed enum (per the repo's no-stringly-typed-API rule) so that workflow steps and Go callers compare against named constants rather than bare strings.

const (
	// KindInvalid is returned together with an error whenever a reference does
	// not parse as a release.
	KindInvalid ReleaseKind = "invalid"
	// KindRC is a release candidate: a version carrying an -rcN prerelease
	// suffix (e.g. v0.1.0-rc1). RCs never publish to external package repos.
	KindRC ReleaseKind = "rc"
	// KindFinal is a final, non-prerelease version (e.g. v0.1.0).
	KindFinal ReleaseKind = "final"
)

func (ReleaseKind) String

func (k ReleaseKind) String() string

String renders the kind for CLI output and workflow consumption.

type ReusableRule

type ReusableRule struct {
	Uses           string `yaml:"uses"`
	SecretsInherit bool   `yaml:"secretsInherit"`
	ForbidIf       bool   `yaml:"forbidIf"`
}

ReusableRule constrains a reusable-workflow gate job (peasant's e2e / release-e2e shape): it must `uses:` the named reusable workflow, pass `secrets: inherit` (when SecretsInherit), and carry no `if:` condition (when ForbidIf) so the gate runs on every release tag rather than selected paths.

type Review

type Review struct {
	User  *ReviewUser `json:"user"`
	State ReviewState `json:"state"`
}

Review is the subset of a GitHub pull-request review needed by the release approval gate.

type ReviewState

type ReviewState string

ReviewState is the `.state` field returned by the GitHub pull-request reviews API for a submitted review.

const (
	ReviewStateApproved         ReviewState = "APPROVED"
	ReviewStateCommented        ReviewState = "COMMENTED"
	ReviewStateChangesRequested ReviewState = "CHANGES_REQUESTED"
	ReviewStateDismissed        ReviewState = "DISMISSED"
)

func (ReviewState) String

func (s ReviewState) String() string

String renders the review state for CLI output and error messages.

type ReviewUser

type ReviewUser struct {
	Login string `json:"login"`
}

ReviewUser is the GitHub user shape embedded in a pull-request review.

type Squash

type Squash struct {
	SHA       string
	ParentSHA string
	TreeSHA   string
}

Squash identifies a single-parent squash-merge commit S that is a candidate for bubbling. TreeSHA is set explicitly on the bubble merge-commit M so that M.tree == S.tree without a content merge (the conflict-free, signed-M path).

type TagRef

type TagRef struct {
	// Name is the tag's short name (e.g. "v1.2.3", "v1.2.3-rc4", "pkg/schema/v0.2.0").
	Name string
	// CommitSHA is the commit the tag points at.
	CommitSHA string
}

TagRef is a repository tag resolved to the commit it points at. It is the own-type projection of GitHub's "list repository tags" response (RepositoryTag), so the first-run bubble guard can test drained commits against release-tag commits without importing go-github. GitHub's list-tags endpoint dereferences annotated tags, so CommitSHA is always the underlying commit SHA for both lightweight and annotated tags.

type Version

type Version string

Version is a validated schema release version, always including the leading "v" (e.g. "v0.1.0" or "v0.1.0-rc1"). Construct only via NewVersion so the invariant (matches the frozen grammar) holds everywhere a Version is seen.

func NewVersion

func NewVersion(raw string) (Version, error)

NewVersion validates raw against the frozen release-version grammar and returns a typed Version. On failure it returns an actionable error naming the expected shape and a concrete example.

func (Version) Base

func (v Version) Base() Version

Base returns the version with any -rcN suffix stripped: the final version a release candidate is a candidate FOR. For a final version Base is the identity (v0.1.0 -> v0.1.0); for an rc it strips the suffix (v0.1.0-rc3 -> v0.1.0).

func (Version) IsRC

func (v Version) IsRC() bool

IsRC reports whether the version carries an -rcN prerelease suffix.

func (Version) Kind

func (v Version) Kind() ReleaseKind

Kind returns KindRC for prerelease (-rcN) versions and KindFinal otherwise. A Version is, by construction, never KindInvalid.

func (Version) String

func (v Version) String() string

String renders the version (with its leading "v").

type WorkflowPolicy

type WorkflowPolicy struct {
	Jobs []JobRule `yaml:"jobs"`
}

WorkflowPolicy is the per-repo, declarative projection of the release-workflow assertions that were previously hardcoded in each repo's workflow_guard.go. It is data, not a DSL: each JobRule states a job that must exist, the needs-edges it must declare, and (optionally) the reusable-workflow shape or the job permissions/environment binding it must carry. schema and peasant supply different policy files; the shared tool holds no repo-specific job-shape knowledge.

func LoadWorkflowPolicy

func LoadWorkflowPolicy(path string) (WorkflowPolicy, error)

LoadWorkflowPolicy reads and parses a repo's release-guard policy file (.github/release-guard.policy.yml) into a WorkflowPolicy. Unknown fields are rejected so a typo'd policy key fails loudly rather than silently disabling a gate.

type WorkflowRun

type WorkflowRun struct {
	HeadSHA    string
	Status     WorkflowRunStatus
	Conclusion WorkflowRunConclusion
}

WorkflowRun is the minimal projection of a GitHub Actions workflow run the release-final gate consumes: the commit it ran against and its terminal state. It is an own-type (mirroring release.Review and release.CollaboratorPermission) so the policy predicate never touches a *github.WorkflowRun and the go-github pointer-field nil-guards stay at the wrapper boundary.

type WorkflowRunConclusion

type WorkflowRunConclusion string

WorkflowRunConclusion is the `.conclusion` field of a GitHub Actions workflow run — meaningful only once Status is WorkflowRunCompleted. Typed for the same reason as WorkflowRunStatus.

const (
	// WorkflowRunSuccess is the only conclusion a green run can have.
	WorkflowRunSuccess WorkflowRunConclusion = "success"
	// WorkflowRunFailure is a completed run that failed.
	WorkflowRunFailure WorkflowRunConclusion = "failure"
	// WorkflowRunNeutral is a completed run that neither passed nor failed.
	WorkflowRunNeutral WorkflowRunConclusion = "neutral"
	// WorkflowRunCancelled is a completed run that was cancelled.
	WorkflowRunCancelled WorkflowRunConclusion = "cancelled"
	// WorkflowRunSkipped is a completed run that was skipped.
	WorkflowRunSkipped WorkflowRunConclusion = "skipped"
	// WorkflowRunTimedOut is a completed run that exceeded its time limit.
	WorkflowRunTimedOut WorkflowRunConclusion = "timed_out"
	// WorkflowRunActionRequired is a completed run that needs manual action.
	WorkflowRunActionRequired WorkflowRunConclusion = "action_required"
	// WorkflowRunStale is a completed run whose result is considered stale.
	WorkflowRunStale WorkflowRunConclusion = "stale"
	// WorkflowRunNoConclusion is the empty conclusion of a not-yet-completed run.
	WorkflowRunNoConclusion WorkflowRunConclusion = ""
)

type WorkflowRunStatus

type WorkflowRunStatus string

WorkflowRunStatus is the `.status` field of a GitHub Actions workflow run. Typed per the repo's no-stringly-typed rule so the release-run predicate compares against named constants, not bare strings. The wrapper at the cmd/release-guard go-github seam maps the upstream *github.WorkflowRun.Status onto these values; internal/release stays free of any go-github import.

const (
	// WorkflowRunCompleted is the only status a green run can have — the run has
	// finished and its Conclusion is meaningful.
	WorkflowRunCompleted WorkflowRunStatus = "completed"
	// WorkflowRunInProgress is a run that is still executing (no conclusion yet).
	WorkflowRunInProgress WorkflowRunStatus = "in_progress"
	// WorkflowRunQueued is a run accepted but not yet started.
	WorkflowRunQueued WorkflowRunStatus = "queued"
	// WorkflowRunRequested is a run requested but not yet queued.
	WorkflowRunRequested WorkflowRunStatus = "requested"
	// WorkflowRunWaiting is a run paused waiting on a deployment gate/approval.
	WorkflowRunWaiting WorkflowRunStatus = "waiting"
	// WorkflowRunPending is a run pending (concurrency or other hold).
	WorkflowRunPending WorkflowRunStatus = "pending"
)

Jump to

Keyboard shortcuts

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