Documentation
¶
Overview ¶
Package agentcli is what devctl's agent-facing commands share: the JSON envelope every one of them prints as its only stdout output, the exit-code table, the clock that DEVCTL_TIME_SCALE speeds up for tests, the endpoint configuration read from the environment, the --progress writer and the retrying transport under the API clients.
An agent-facing command blocks, prints one JSON document on stdout when it finishes and nothing else, and exits with a code from the table below. Progress, when asked for with --progress, goes to stderr.
Index ¶
- Constants
- func Emit(w io.Writer, document any) error
- func Exit(err error) int
- func FlagError(command string, err error) error
- func ProgressFlag(cmd *cobra.Command, v *bool)
- func Report(w io.Writer, doc Document, ok Verdict, err error) error
- type Clock
- type Document
- type Endpoints
- type Envelope
- type ExitCoder
- type ExitError
- type Progress
- type RetriesExhaustedError
- type Retrying
- type Verdict
Constants ¶
const ( // EnvGitHubAPIURL is the GitHub REST API (https://api.github.com). EnvGitHubAPIURL = "DEVCTL_GITHUB_API_URL" // EnvGitHubOAuthURL is the host of GitHub's device-flow endpoints // (https://github.com). EnvGitHubOAuthURL = "DEVCTL_GITHUB_OAUTH_URL" // EnvCircleCIAPIURL is the CircleCI API v2 (https://circleci.com/api/v2). EnvCircleCIAPIURL = "DEVCTL_CIRCLECI_API_URL" // EnvCircleCIOAuthURL is CircleCI's OAuth issuer (https://app.circleci.com). EnvCircleCIOAuthURL = "DEVCTL_CIRCLECI_OAUTH_URL" // EnvRegistryPublic is the public registry, probed anonymously. EnvRegistryPublic = "DEVCTL_REGISTRY_PUBLIC" // EnvRegistryPrivate is the private registry, read with the docker keychain. EnvRegistryPrivate = "DEVCTL_REGISTRY_PRIVATE" // EnvRegistryInsecure set to 1 talks plain HTTP to the registries (tests only). EnvRegistryInsecure = "DEVCTL_REGISTRY_INSECURE" // EnvMusterURL is the muster MCP endpoint `devctl auth login --muster-only` // logs in to, and the one the repo commands reach giantswarm-repo-manager // through (https://muster.gazelle.awsprod.gigantic.io/mcp). EnvMusterURL = "DEVCTL_MUSTER_URL" // EnvKeyringFile names a 0600 JSON file that replaces the OS keychain // (tests only). EnvKeyringFile = "DEVCTL_KEYRING_FILE" )
The environment variables that point an agent-facing command at another site or at a test double. Every default is the production endpoint.
const ( // ExitOK: the wait ended green, the merge happened, the release is // available or none follows the merge. ExitOK = 0 // ExitRed: a check is red or the tag's CI failed. ExitRed = 1 // ExitTimeout: the deadline passed; the document names what was unfinished. ExitTimeout = 2 // ExitNotApplicable: draft, closed, conflicting, behind a strict base, a // version that does not resolve. ExitNotApplicable = 3 // ExitRequiredMissing: a required context never reported. ExitRequiredMissing = 4 // ExitRefused: the command declines (another author, an opt-out). ExitRefused = 5 // ExitReleaseFailed: merged, and the release the merge triggered failed: // its auto-release run or its tag's CI. ExitReleaseFailed = 6 // ExitUsage: wrong usage or a tooling failure. ExitUsage = 7 // ExitAuthRequired: no usable token; the reason names `devctl auth login`. ExitAuthRequired = 8 // ExitReleaseUnconfirmed: merged, and the release was not confirmed // pullable: the release timeout passed first, or the release wait could // not judge it. ExitReleaseUnconfirmed = 9 )
The exit codes of every agent-facing command. 6 and 9 say that devctl pr merge merged: they are never a reason to merge again.
const ( RetryAttempts = 8 RetryBackoff = 2 * time.Second RetryBackoffCeiling = 60 * time.Second // RetryAttemptTimeout bounds one try, the answer's body included; it is // a network timeout and not scaled. RetryAttemptTimeout = 60 * time.Second )
The retry budget of one read at scale 1: RetryAttempts tries, the pause before the first retry RetryBackoff, doubling up to RetryBackoffCeiling, about three minutes of pauses in all.
const EnvTimeScale = "DEVCTL_TIME_SCALE"
EnvTimeScale multiplies every sleep and timeout of an agent-facing command. Production runs at 1; the e2e suite runs at 0.001 so a five-minute wait takes 300 milliseconds. Timestamps are never scaled.
const SchemaVersion = 1
SchemaVersion is the version of the envelope; a breaking change to any command's document bumps it.
Variables ¶
This section is empty.
Functions ¶
func Exit ¶
Exit maps err to the process exit code: 0 for nil, the code of an ExitCoder anywhere in the chain, ExitUsage for any other error.
func FlagError ¶ added in v8.91.4
FlagError is the error of a flag cobra could not parse, as a command's reason: the parser's message and where the flags are listed. The command reports it with its document, exit 7, like any other wrong call.
func ProgressFlag ¶
ProgressFlag registers --progress on cmd, bound to v.
func Report ¶ added in v8.91.4
Report finishes doc from the command's error, the ok verdict when there is none, writes it on w and returns what the command returns to cobra: nil on exit 0, otherwise the *ExitError the process exit code follows.
Types ¶
type Clock ¶
type Clock struct {
// contains filtered or unexported fields
}
Clock is the time source of a command: the current time, and sleeps and timeouts scaled by EnvTimeScale.
func NewClock ¶
NewClock is a clock with an explicit scale and time source; now nil means the wall clock.
func SystemClock ¶
SystemClock is the wall clock at the scale of EnvTimeScale (1 when unset).
func (Clock) Scaled ¶
Scaled is d at the clock's scale, never below one millisecond for a positive d.
type Document ¶ added in v8.91.4
Document is a command's JSON document: a pointer to a struct that embeds Envelope and adds the command's own fields.
type Endpoints ¶
type Endpoints struct {
GitHubAPIURL string
GitHubOAuthURL string
CircleCIAPIURL string
CircleCIOAuthURL string
RegistryPublic string
RegistryPrivate string
RegistryInsecure bool
// MusterURL is the muster MCP endpoint of the installation that runs
// giantswarm-repo-manager.
MusterURL string
// KeyringFile is empty for the OS keychain.
KeyringFile string
}
Endpoints is where the agent-facing commands talk to.
func DefaultEndpoints ¶
func DefaultEndpoints() Endpoints
DefaultEndpoints are the production endpoints.
func EndpointsFromEnv ¶
func EndpointsFromEnv() Endpoints
EndpointsFromEnv are the defaults with every set variable applied. URLs lose their trailing slash.
type Envelope ¶
type Envelope struct {
Command string `json:"command"`
SchemaVersion int `json:"schemaVersion"`
ExitCode int `json:"exitCode"`
Verdict Verdict `json:"verdict"`
Reason string `json:"reason"`
Warnings []string `json:"warnings"`
StartedAt time.Time `json:"startedAt"`
FinishedAt time.Time `json:"finishedAt"`
}
Envelope is the head of every command's JSON document. A command's document embeds it and adds its own fields.
func NewEnvelope ¶
NewEnvelope starts the envelope of command at now.
func (Envelope) Err ¶
Err is the error a command returns to cobra after emitting its document: nil on exit 0, otherwise an *ExitError carrying the envelope's code. The process exit code follows it; nothing is printed for it, the document was.
type ExitError ¶
ExitError is an outcome with its exit code: what a command returns after its document is written, and what any error of the table can be expressed as.
func NewExitError ¶
NewExitError returns an ExitError with a formatted reason.
func (*ExitError) ExitVerdict ¶
ExitVerdict implements ExitCoder.
type Progress ¶
type Progress struct {
// contains filtered or unexported fields
}
Progress writes one line per step to stderr when --progress is set and nothing otherwise. Stdout stays the document's.
func NewProgress ¶
NewProgress writes to w; a nil w or enabled false discards.
type RetriesExhaustedError ¶ added in v8.91.3
type RetriesExhaustedError struct {
Attempts int
// Last is the last failure: the transport error or the 5xx status.
Last string
}
RetriesExhaustedError is a read that failed on every try. The HTTP client wraps it with the method and URL.
func (*RetriesExhaustedError) Error ¶ added in v8.91.3
func (e *RetriesExhaustedError) Error() string
type Retrying ¶ added in v8.91.3
type Retrying struct {
// Base sends the requests; nil means http.DefaultTransport.
Base http.RoundTripper
// Clock scales the pauses; zero means the wall clock at scale 1.
Clock Clock
// Progress receives one line per retry; nil is silent.
Progress *Progress
// Warn receives one line per retried failure, with its time, for the
// document's warnings; nil drops them.
Warn func(message string)
// Attempts, Backoff, BackoffCeiling and AttemptTimeout default to the
// Retry constants.
Attempts int
Backoff time.Duration
BackoffCeiling time.Duration
AttemptTimeout time.Duration
// contains filtered or unexported fields
}
Retrying is the http.RoundTripper under the API clients of a wait: a read that GitHub or CircleCI did not answer -- a reset connection, an EOF, a timeout, a 5xx -- is sent again after a backoff instead of ending the wait. Every poll reads the same state again, so one such failure is not an outcome; one that persists through RetryAttempts tries in a row is, and the error then names the request, the count and the last failure. The caller's context bounds the retries: the wait's own deadline ends them.
Only GET and HEAD are retried, and a GET's body is read within its try, so a connection that breaks in the middle of an answer is retried too. Other methods pass through untouched: a write is not repeated on a guess.
type Verdict ¶
type Verdict string
Verdict is the one-word outcome of a command.
const ( VerdictGreen Verdict = "green" VerdictRed Verdict = "red" VerdictTimeout Verdict = "timeout" VerdictNotApplicable Verdict = "not_applicable" VerdictRequiredMissing Verdict = "required_missing" VerdictRefused Verdict = "refused" VerdictAvailable Verdict = "available" VerdictCIFailed Verdict = "ci_failed" VerdictNoRelease Verdict = "no_release" VerdictReleaseFailed Verdict = "release_failed" VerdictReleaseUnconfirmed Verdict = "release_unconfirmed" VerdictAuthRequired Verdict = "auth_required" VerdictUsage Verdict = "usage" )
The verdicts a command reports.