Documentation
¶
Overview ¶
Package releasepromote promotes the latest release candidate of auto-release repositories to a stable release: what `devctl release promote` does. The auto-release workflow cuts a candidate vX.Y.Z-rc.N, a GitHub pre-release, on every releasable push; a stable release is cut only by running that workflow by hand with release-type stable, which promotes the latest candidate since the last stable release. The package checks that the workflow on the default branch is one that promotes, picks that candidate from the repository's releases reachable from the default branch, checks that its commit is built (the rule the workflow applies) and dispatches the workflow on the default branch. The workflow does the promotion and its own checks; nothing here waits for its run.
Index ¶
- Constants
- Variables
- func NewestBuilt(releases []githubclient.Release, ...) (string, error)
- func Promote(ctx context.Context, config Config, repositories []string, result *Result) error
- func SelectCandidate(releases []githubclient.Release, reachable func(tag string) (bool, error)) (stable, candidate string, err error)
- func SelectVersion(releases []githubclient.Release, reachable func(tag string) (bool, error), ...) (stable, candidate string, err error)
- func SplitRepository(s string) (owner, repo string, ok bool)
- func TeamRepositories(ctx context.Context, gh *github.Client, team string) ([]string, error)
- func ValidVersion(version string) bool
- type Config
- type Document
- type GitHub
- type Identity
- type Repository
- type Result
- type Sources
Constants ¶
const ( // StateDispatched: the workflow was dispatched with release-type stable. StateDispatched = "dispatched" // StateWouldDispatch: with --dry-run, the workflow would be dispatched. StateWouldDispatch = "would_dispatch" // StateNothingToPromote: no candidate pre-release newer than the latest // stable release. StateNothingToPromote = "nothing_to_promote" // StateNotBuilt: a commit status of the candidate's commit is not // success; statusState names the combined state, newestBuilt the // highest other candidate that is built. StateNotBuilt = "not_built" // StateNotAutoRelease: the repository has no auto-release workflow. StateNotAutoRelease = "not_auto_release" // StateOutdatedWorkflow: the auto-release workflow on the default branch // has no promotion step: its release-type stable tags the branch head; or, // with --version, its promotion step takes no version input. StateOutdatedWorkflow = "outdated_workflow" // StateFailed: a read or the dispatch failed; the message has GitHub's // answer. StateFailed = "failed" )
The states of one repository.
const Command = "release promote"
Command is the envelope's command name.
const Workflow = "zz_generated.auto_release.yaml"
Workflow is the file name of the generated auto-release workflow.
Variables ¶
var ErrNotCandidate = errors.New("not a release candidate to promote")
ErrNotCandidate is a version named for promotion that is not a release candidate the workflow promotes: no published release of that tag, not newer than the last stable release, or not on the default branch.
var ErrNotPrerelease = errors.New("not a GitHub pre-release")
ErrNotPrerelease is the highest candidate being a full GitHub release, not a pre-release: the workflow stops on it rather than promote a lower one.
Functions ¶
func NewestBuilt ¶ added in v8.142.0
func NewestBuilt(releases []githubclient.Release, reachable, built func(tag string) (bool, error), except string) (string, error)
NewestBuilt is the highest release candidate other than except that the workflow would promote with `version` and that built accepts, "" when there is none: a published pre-release newer than the highest stable release reachable from the default branch, and reachable itself. Candidates are asked highest first, built only for reachable pre-releases, and only until the first built one.
func Promote ¶
Promote runs the promotion of every repository, owner/repo each, in order, and fills result.Repositories. A repository that is not dispatched is reported in its entry and does not stop the others; the error is then an agentcli.ExitRed outcome naming them. Nil when every repository was dispatched, would be, or has nothing to promote.
func SelectCandidate ¶
func SelectCandidate(releases []githubclient.Release, reachable func(tag string) (bool, error)) (stable, candidate string, err error)
SelectCandidate returns the tag of the highest stable release reachable from the default branch and of the highest reachable candidate newer than it, "" for either when there is none: the tags the workflow's `--merged HEAD` lets it see. reachable says whether a tag is on the default branch; it is asked from the highest tag down and only until the first reachable one, so a higher stable release or candidate of another branch (a backport line) is skipped without hiding the default branch's. Drafts are no releases. The highest candidate must be a GitHub pre-release, the form the workflow promotes: a full release there is ErrNotPrerelease with its tag, never a lower candidate, as the workflow refuses it too. Versions are compared as semver, so rc.10 follows rc.9 and a candidate for a higher version follows one it replaced.
func SelectVersion ¶ added in v8.142.0
func SelectVersion(releases []githubclient.Release, reachable func(tag string) (bool, error), version string) (stable, candidate string, err error)
SelectVersion is SelectCandidate for the named candidate version instead of the highest: the tag of the highest stable release reachable from the default branch, and version once it is a published release newer than that stable release and reachable, the candidates the workflow's `version` input accepts. Anything else is ErrNotCandidate saying why; a candidate that is a full release is ErrNotPrerelease, as the workflow refuses it.
func SplitRepository ¶
SplitRepository reads owner/repo.
func TeamRepositories ¶
TeamRepositories lists owner/repo of every entry of a team's file in giantswarm/github whose release model is auto-release (releaseWorkflow, defaulting from gen.ci.generate) and whose life is not over (archived or deleted), in file order. The repositories are in the organisation the team files describe. A team without a file is a usage error.
func ValidVersion ¶ added in v8.142.0
ValidVersion says whether version has the form of a candidate tag, vX.Y.Z-rc.N.
Types ¶
type Config ¶
type Config struct {
// GitHub is required.
GitHub GitHub
// DryRun checks every repository and dispatches nothing.
DryRun bool
// Version is the candidate vX.Y.Z-rc.N to promote instead of the
// latest; empty promotes the latest. [ValidVersion] checks its form.
Version string
// NotFoundHint is added to GitHub's 404 for a repository: what the
// token reaches. Empty adds nothing.
NotFoundHint string
// Progress receives one line per repository; nil is silent.
Progress *agentcli.Progress
}
Config configures a promotion.
type GitHub ¶
type GitHub interface {
DefaultBranch(ctx context.Context, owner, repo string) (string, error)
ReadFile(ctx context.Context, owner, repo, path, ref string) ([]byte, bool, error)
ListReleases(ctx context.Context, owner, repo string) ([]githubclient.Release, error)
Reachable(ctx context.Context, owner, repo, ref, branch string) (bool, error)
GetCombinedStatus(ctx context.Context, owner, repo, ref string) (githubclient.CombinedStatus, error)
DispatchWorkflow(ctx context.Context, owner, repo, file, ref string, inputs map[string]any) error
}
GitHub is what a promotion reads from and writes to GitHub; *githubclient.Client is one.
type Identity ¶ added in v8.105.0
type Identity struct {
// Source is "keychain", the devctl GitHub App login, or "$NAME", the
// environment variable that overrides it; empty until the token is
// resolved.
Source string `json:"source"`
// Login is the account of the App login; empty for a token from the
// environment, whose account devctl does not look up.
Login string `json:"login"`
}
Identity is the GitHub token a promotion acts with.
type Repository ¶
type Repository struct {
// Repository is owner/repo.
Repository string `json:"repository"`
// Stable is the tag of the latest stable release; empty when there is
// none.
Stable string `json:"stable"`
// Candidate is the tag of the candidate to promote; empty when there is
// none.
Candidate string `json:"candidate"`
// NewestBuilt is, for not_built, the highest other candidate the
// workflow would promote whose commit is built: promote it with
// --version instead of waiting. Empty when there is none or for another
// state.
NewestBuilt string `json:"newestBuilt,omitempty"`
// StatusState is the combined commit status of the candidate: success,
// pending, failure or error; empty until read.
StatusState string `json:"statusState"`
// State is one of the State constants.
State string `json:"state"`
// Message says what was done or why not.
Message string `json:"message"`
// Warnings name what the promotion went on despite: a failed commit
// status of an advisory job (circleciclient.AdvisoryJobs), which the
// release does not require. Empty when there is none.
Warnings []string `json:"warnings,omitempty"`
}
Repository is one repository's promotion as the document reports it.
func (Repository) OK ¶
func (r Repository) OK() bool
OK says whether the repository is dispatched, would be, or has nothing to promote.
type Result ¶
type Result struct {
// Team is the team whose repositories were promoted; empty for named
// repositories.
Team string `json:"team"`
// DryRun is set with --dry-run: nothing was dispatched.
DryRun bool `json:"dryRun"`
// Identity is who dispatched the workflows, or would with --dry-run.
Identity Identity `json:"identity"`
// Repositories are the repositories in the order they were given or
// the team file lists them.
Repositories []Repository `json:"repositories"`
}
Result is the command's document below the envelope.
type Sources ¶
type Sources struct {
GitHub GitHub
// Team lists the auto-release repositories of a team.
Team func(ctx context.Context, team string) ([]string, error)
// NotFoundHint is [Config]'s.
NotFoundHint string
// Identity is who the token acts as, for the document.
Identity Identity
}
Sources are what one promotion reads and writes, opened after the version gate.
func OpenSources ¶
func OpenSources(ctx context.Context, endpoints agentcli.Endpoints, transport http.RoundTripper, warn func(string)) (*Sources, error)
OpenSources is the production wiring: the GitHub token of authstore.ResolveGitHub (the App login, or a token in the environment that overrides it; its warning goes to warn), conditional requests below it, and the team files of the organisation. The requests go through transport.