Documentation
¶
Index ¶
- Constants
- func AdjustColumnWidths(cols []TableColumn, prs []PRInfo)
- func AgeColorCode(created, now time.Time) string
- func AgeColorFunc(p PRInfo) string
- func AgeDays(created, now time.Time) int
- func AgeInfoFunc(p PRInfo) string
- func AuthorInfoFunc(p PRInfo) string
- func ChangeID(title string) string
- func ColorizeRescue(m *RescueMarker, now time.Time) string
- func ColorizeStatus(state StatusState, detail string) string
- func DependencyInfoFunc(p PRInfo) string
- func DisableLineWrap(w *os.File)
- func EnableLineWrap(w *os.File)
- func ExtractDependencyName(title string) string
- func ExtractOwnerRepo(htmlURL string) (string, string, error)
- func ExtractTargetVersion(title string) string
- func ExtractVersion(title string) string
- func FormatAge(created, now time.Time) string
- func FormatRescue(m *RescueMarker, now time.Time) string
- func IsDependencyUpdateTitle(title string) bool
- func LabelClass(s StatusState) string
- func MakeHyperlink(text, url string) string
- func NoOpDiff(files []*github.CommitFile) bool
- func PRKey(p PRInfo) string
- func ParsePRURL(htmlURL string) (owner, repo string, number int, err error)
- func PatchID(files []*github.CommitFile, changedFiles int) string
- func PrintPlainResults(w *os.File, status *PRStatus)
- func PrintRow(w *os.File, e StatusEntry, cols []TableColumn)
- func PrintTableHeader(w *os.File, cols []TableColumn)
- func RepoInfoFunc(p PRInfo) string
- func TrustedLogins() []string
- func UpdateTable(w *os.File, entries []StatusEntry, cols []TableColumn)
- func VersionInfoFunc(p PRInfo) string
- type Budget
- type Concurrency
- type Confirm
- type Counts
- type Fingerprint
- type Kind
- type ObsoleteReason
- type PRGroup
- type PRInfo
- type PRStatus
- func (s *PRStatus) ActionRequired() []StatusEntry
- func (s *PRStatus) Add(pr PRInfo) int
- func (s *PRStatus) BlockedEntries() []StatusEntry
- func (s *PRStatus) CancelledEntries() []StatusEntry
- func (s *PRStatus) FormatSummary() string
- func (s *PRStatus) Len() int
- func (s *PRStatus) MarkObsolete(idx int, reason ObsoleteReason, detail string)
- func (s *PRStatus) MergedEntries() []StatusEntry
- func (s *PRStatus) NoVerdictEntries() []StatusEntry
- func (s *PRStatus) ObsoleteEntries() []StatusEntry
- func (s *PRStatus) RefreshedEntries() []StatusEntry
- func (s *PRStatus) RescueAt(idx int) *RescueMarker
- func (s *PRStatus) RetriedEntries() []StatusEntry
- func (s *PRStatus) SecurityFailedEntries() []StatusEntry
- func (s *PRStatus) SetClassification(idx int, kind Kind, updateType UpdateType)
- func (s *PRStatus) SetLabel(idx int, label string)
- func (s *PRStatus) SetPolicy(idx int, policy Policy)
- func (s *PRStatus) SetRescue(idx int, marker *RescueMarker)
- func (s *PRStatus) SetUnhandled(idx int, unhandled *Unhandled)
- func (s *PRStatus) SkippedEntries() []StatusEntry
- func (s *PRStatus) Snapshot() []StatusEntry
- func (s *PRStatus) StaleEntries() []StatusEntry
- func (s *PRStatus) StateAt(idx int) StatusState
- func (s *PRStatus) Summary() Counts
- func (s *PRStatus) UnhandledEntries() []StatusEntry
- func (s *PRStatus) Update(idx int, state StatusState, detail string)
- func (s *PRStatus) WaitingEntries() []StatusEntry
- type Policy
- type RescueMarker
- type RescuePolicy
- type StatusEntry
- type StatusState
- type SupersededBy
- type TableColumn
- type Unhandled
- type UpdateType
Constants ¶
const ( StaleGroupHeader = "Stale (behind base, failing checks green there -- refresh first)" RefreshedGroupHeader = "Refreshed (re-checking)" CancelledGroupHeader = "Cancelled (CircleCI auto-cancelled the build -- retry first)" RetriedGroupHeader = "Retried (re-checking)" // NoVerdictGroupHeader names the bucket for checks that established // nothing about the code. Each entry's detail names its own remedy. NoVerdictGroupHeader = "CI unavailable (no verdict) -- the checks decided nothing, see the detail" // ObsoleteGroupHeader names the bucket for bot PRs that are not worth // fixing. Each entry's detail says whether a higher-version sibling // replaced it or its diff changes nothing that executes. ObsoleteGroupHeader = "Obsolete (nothing to fix -- close these)" )
Section headers shared by the plain-text and TUI summaries for the stale and cancelled buckets, so both outputs name them identically.
const BudgetEnforced = false
BudgetEnforced reports whether this build enforces the rescue budget. It is false until the platform accepts a budget on a run and reports the cost of a finished one. It stays false once RescuesDispatched is true and the budget still needs the platform.
const LabelPrefix = "bot-prs-sweep/"
LabelPrefix is the namespace of the one classification label the sweep keeps on every bot PR it touched. Labels are display only: no guard reads them back.
const MarkerKindEvidence = "evidence"
MarkerKindEvidence marks a comment the sweep wrote as evidence of a guard decision or an action it performed. Evidence carries the head SHA and the fingerprint like a rescue marker so a later sweep can tell whether the same evidence already stands for the current change.
const RescuesDispatched = false
RescuesDispatched reports whether this build dispatches a rescue. It is false until the rescue agent runs on an installation. While it is false every bound in RescuePolicy is declared and none of them applies, so a sweep must say so rather than let a team read its file as a guarantee.
Variables ¶
This section is empty.
Functions ¶
func AdjustColumnWidths ¶
func AdjustColumnWidths(cols []TableColumn, prs []PRInfo)
AdjustColumnWidths widens each column so every value fits without truncation.
func AgeColorCode ¶
AgeColorCode returns the ANSI color prefix for a PR age: "" while the PR is fresh, yellow once it passes ageWarnAfter, red once it passes ageStaleAfter. Callers must reset with \033[0m when non-empty.
func AgeColorFunc ¶
AgeColorFunc is the table-column color accessor for the Age column.
func AgeDays ¶
AgeDays returns the whole number of days since created, or 0 for a zero creation time.
func AgeInfoFunc ¶
AgeInfoFunc is the table-column accessor for the Age column.
func AuthorInfoFunc ¶
func ChangeID ¶
ChangeID fingerprints a dependency-update PR by what it updates: the dependency name and the target version parsed from the PR title, e.g. "typescript@v7" for "chore(deps): update dependency typescript to v7". Titles naming no single dependency or no version ("Update all non-major dependencies", "Lock file maintenance") yield "".
func ColorizeRescue ¶
func ColorizeRescue(m *RescueMarker, now time.Time) string
ColorizeRescue wraps the FormatRescue annotation in ANSI colors: a stale marker renders yellow (retriable -- the change differs from the one attempted), a fresh one bold red (a rescue already failed on exactly this change, whether or not the branch was rebased since; a human is needed).
func ColorizeStatus ¶
func ColorizeStatus(state StatusState, detail string) string
func DependencyInfoFunc ¶
func DisableLineWrap ¶
DisableLineWrap turns off the terminal's auto-wrap (DECAWM) so rows wider than the terminal are clipped at the right edge instead of wrapping onto a second physical line. UpdateTable's cursor-up math counts logical rows, so a wrapped row would desync the redraw and produce the garbled output users see when CI detail strings push a line past the terminal width.
func EnableLineWrap ¶
EnableLineWrap restores the terminal's auto-wrap mode. Always pair it with DisableLineWrap (typically via defer) so an early return does not leave the user's terminal in a clipped state.
func ExtractDependencyName ¶
func ExtractOwnerRepo ¶
ExtractOwnerRepo parses owner and repo from a GitHub HTML URL (e.g. "https://github.com/OWNER/REPO/pull/123").
func ExtractTargetVersion ¶
ExtractTargetVersion returns the version a dependency update moves to, regardless of whether the title also names the version it moves from.
func ExtractVersion ¶
ExtractVersion renders the version change named in a title for display: "4.17.20 -> 4.17.21" for a from/to title, "v1.10.2" for a to-only title, "" when the title names no version.
func FormatAge ¶
FormatAge renders the time since created as a compact human string ("5h", "3d", "2w"). It returns "" for a zero creation time so callers can omit the column value when the discovery path did not provide it.
func FormatRescue ¶
func FormatRescue(m *RescueMarker, now time.Time) string
FormatRescue renders the marker as a short human-readable annotation for status output, e.g. "rescue failed 1d ago (klaus): ESM-only", "rescue failed 3d ago (klaus), stale: new commits since" or "rescue blocked 5d ago (klaus), rebased since: same change: ESM-only".
func IsDependencyUpdateTitle ¶
IsDependencyUpdateTitle returns true if the PR title looks like an automated dependency update (Renovate or Dependabot), regardless of who authored it.
func LabelClass ¶ added in v0.12.0
func LabelClass(s StatusState) string
LabelClass returns the classification label suffix for a final state, or "" for a transient state that never ends a sweep.
func MakeHyperlink ¶
func NoOpDiff ¶ added in v0.11.0
func NoOpDiff(files []*github.CommitFile) bool
NoOpDiff reports whether a PR's changed files carry no semantic change: every changed line is a pinned-SHA `uses:` line in a GitHub workflow whose pinned commit is unchanged and whose trailing version comment is all that moved.
The verdict is conservative, because a wrong "no-op" hides a real change: an empty file list, a file outside .github/workflows or .github/actions, a patch GitHub truncated or omitted, an unequal number of added and removed lines, or one changed line that is not a pinned `uses:` all make it false.
Within a file the removed and added lines are paired by order. A pair of unrelated lines can only make the verdict stricter, because samePinnedAction accepts a pair only when the two lines are equal once the comment is gone.
func ParsePRURL ¶
ParsePRURL parses owner, repo, and PR number from a GitHub pull request URL (e.g. "https://github.com/OWNER/REPO/pull/123").
func PatchID ¶
func PatchID(files []*github.CommitFile, changedFiles int) string
PatchID computes the content fingerprint of a PR from the files of its compare response (GET /repos/{owner}/{repo}/compare/{base}...{head}). changedFiles is the PR's changed_files count. The compare API returns at most 300 files and omits the patch of a file whose diff is too large, so PatchID returns "" whenever the input cannot describe the whole change rather than fingerprinting part of it.
Per file the hash covers status, previous and current path, and every added or removed line of the patch in order. Hunk headers and context lines are skipped: both shift when the base branch changes around the PR's lines, which is exactly what a rebase produces. A file without a patch and without changed lines (binary content, a pure rename, a mode change) contributes its blob SHA instead.
func PrintPlainResults ¶
func PrintRow ¶
func PrintRow(w *os.File, e StatusEntry, cols []TableColumn)
func PrintTableHeader ¶
func PrintTableHeader(w *os.File, cols []TableColumn)
func RepoInfoFunc ¶
func TrustedLogins ¶ added in v0.12.0
func TrustedLogins() []string
TrustedLogins returns the logins of the four trusted bots, sorted.
func UpdateTable ¶
func UpdateTable(w *os.File, entries []StatusEntry, cols []TableColumn)
func VersionInfoFunc ¶
Types ¶
type Budget ¶ added in v0.13.0
Budget is what a team is willing to spend on rescues, in US dollars. Both figures are part of the team contract and neither is enforced yet: a per-rescue budget needs execution_budget_usd on the run, and a weekly budget needs the cost of finished runs to be readable. BudgetEnforced says so in every outcome the sweep records.
type Concurrency ¶ added in v0.13.0
Concurrency bounds how much of a sweep runs at once: PerTeam is the number of repositories swept in parallel, PerRepo the number of PRs of one repository. Two PRs of one repository race for the same base branch, so PerRepo defaults to 1.
type Confirm ¶ added in v0.13.0
type Confirm string
Confirm says who confirms a rescue before it is dispatched: the person confirms every PR, or once for the whole sweep.
type Counts ¶
type Counts struct {
Merged int
Failed int
Blocked int
NoVerdict int
Stale int
Refreshed int
Cancelled int
Retried int
Obsolete int
Remedied int
Waiting int
Skipped int
}
Counts holds the aggregate tallies of a sweep by outcome category.
Failed covers every action-required outcome (plain and security failures, conflicts, untrusted authors). Blocked (CI could not run because of an Actions budget block), NoVerdict (the failing checks established nothing about the code), Stale (failing checks are green on the base branch head and the PR is behind it), Refreshed (a stale branch was just updated from its base), Cancelled (CircleCI auto-cancelled the failing builds), Retried (those builds were just retried) and Obsolete (a sibling PR carries a higher version of the same dependency, or the diff changes nothing that executes) are counted separately from Failed: none of them is a genuine CI failure and none of them belongs in the rescue path.
type Fingerprint ¶
type Fingerprint struct {
PatchID string `json:"patch_id,omitempty"`
ChangeID string `json:"change_id,omitempty"`
}
Fingerprint identifies what a PR changes independently of its head SHA. Renovate force-pushes a rebased branch whenever its base moves, so the head SHA changes while the change itself stays byte-identical; a fingerprint lets a rescue marker survive that.
PatchID is the precise fingerprint: a hash over the PR's compare diff normalised the way `git patch-id --stable` does, minus the context lines -- hunk headers and line numbers are ignored, only file paths and the added/removed lines count. It is empty when the diff could not be fetched or GitHub truncated it (see PatchID).
ChangeID is the cheap approximation for dependency-update PRs: the dependency name and target version parsed from the PR title, e.g. "typescript@v7". A rebase never changes it and a new version always does, but a version update that keeps the title (7.0.1 -> 7.0.2 under "to v7") is invisible to it, so it only decides when no patch ID is available. It is empty when the title is not a recognisable single-dependency update.
func (Fingerprint) Comparable ¶
func (f Fingerprint) Comparable() bool
Comparable reports whether the fingerprint carries anything to compare.
func (Fingerprint) Matches ¶
func (f Fingerprint) Matches(other Fingerprint) bool
Matches reports whether other describes the same change as f. The patch ID decides whenever both sides have one; the title-derived change ID is the fallback for when the diff could not be fingerprinted on either side. Nothing comparable means "not the same" -- a marker is only kept alive on positive evidence.
type Kind ¶ added in v0.12.0
type Kind string
Kind is the bot that authored a PR. The sweep touches PRs of these four kinds and nothing else; a human-authored PR has no kind.
func KindOf ¶ added in v0.12.0
KindOf returns the kind of the bot with the given login, or "" when the login is not one of the four trusted bots.
func (Kind) CarriesVersion ¶ added in v0.13.0
CarriesVersion reports whether a PR of this kind names a dependency version. An Align files or Herald PR does not, so its update type is always UpdateNone.
type ObsoleteReason ¶ added in v0.11.0
type ObsoleteReason string
ObsoleteReason names why a PR is not worth fixing.
const ( // ReasonSuperseded: a sibling PR in the same repository carries a // higher version of the same dependency. ReasonSuperseded ObsoleteReason = "superseded" // ReasonNoOp: the diff changes nothing that executes. ReasonNoOp ObsoleteReason = "no_op" )
type PRStatus ¶
type PRStatus struct {
// contains filtered or unexported fields
}
func NewPRStatus ¶
func NewPRStatus() *PRStatus
func (*PRStatus) ActionRequired ¶
func (s *PRStatus) ActionRequired() []StatusEntry
ActionRequired returns the failure entries, oldest PR first: the longer a dependency PR has been open, the more sweeps it has already survived, so the old ones are the most likely to need manual work. Entries without a known creation time sort last, in insertion order.
func (*PRStatus) BlockedEntries ¶
func (s *PRStatus) BlockedEntries() []StatusEntry
BlockedEntries returns entries whose CI could not run because a GitHub Actions budget / spending-limit block prevented every job from starting. These are deliberately kept out of ActionRequired and the failed counts: the remedy is "raise or await the Actions budget", not "rescue the code".
func (*PRStatus) CancelledEntries ¶
func (s *PRStatus) CancelledEntries() []StatusEntry
CancelledEntries returns entries whose every failing check is a CircleCI build that CircleCI itself cancelled. Like StaleEntries these are kept out of ActionRequired and the failed counts -- the remedy is "retry the build and read the real verdict", not "rescue the code". Oldest PR first.
func (*PRStatus) FormatSummary ¶
func (*PRStatus) MarkObsolete ¶ added in v0.11.0
func (s *PRStatus) MarkObsolete(idx int, reason ObsoleteReason, detail string)
MarkObsolete records an entry as obsolete together with the reason, so a consumer can dispatch on the reason instead of parsing the detail.
func (*PRStatus) MergedEntries ¶
func (s *PRStatus) MergedEntries() []StatusEntry
func (*PRStatus) NoVerdictEntries ¶ added in v0.10.2
func (s *PRStatus) NoVerdictEntries() []StatusEntry
NoVerdictEntries returns entries whose every failing check established nothing about the code. Like BlockedEntries they are kept out of ActionRequired and the failed counts: there is nothing to rescue, and each entry's detail names its own remedy. Oldest PR first.
func (*PRStatus) ObsoleteEntries ¶ added in v0.11.0
func (s *PRStatus) ObsoleteEntries() []StatusEntry
ObsoleteEntries returns entries that are not worth fixing: a sibling PR carries a higher version, or the diff changes nothing that executes. Like StaleEntries they are kept out of ActionRequired and the failed counts: the remedy is to close them, not to rescue them. Oldest PR first.
func (*PRStatus) RefreshedEntries ¶
func (s *PRStatus) RefreshedEntries() []StatusEntry
RefreshedEntries returns the stale entries whose branch was updated from its base during this run. Their CI is running again; the next sweep decides what they are.
func (*PRStatus) RescueAt ¶
func (s *PRStatus) RescueAt(idx int) *RescueMarker
RescueAt returns the rescue marker attached to the entry at idx, or nil when none is attached or idx is out of range.
func (*PRStatus) RetriedEntries ¶
func (s *PRStatus) RetriedEntries() []StatusEntry
RetriedEntries returns the cancelled entries whose builds were retried during this run. Their CI is running again; the next sweep decides what they are.
func (*PRStatus) SecurityFailedEntries ¶
func (s *PRStatus) SecurityFailedEntries() []StatusEntry
SecurityFailedEntries returns entries that failed specifically because a security-related check reported a problem.
func (*PRStatus) SetClassification ¶ added in v0.12.0
func (s *PRStatus) SetClassification(idx int, kind Kind, updateType UpdateType)
SetClassification records what kind of bot PR the entry is and the size of the update it carries.
func (*PRStatus) SetLabel ¶ added in v0.12.0
SetLabel records the classification label that is on the PR.
func (*PRStatus) SetPolicy ¶ added in v0.13.0
SetPolicy records the sweep policy resolved for the entry's repository, so every decision the sweep took can be explained afterwards.
func (*PRStatus) SetRescue ¶
func (s *PRStatus) SetRescue(idx int, marker *RescueMarker)
SetRescue attaches a prior rescue-attempt marker to an entry.
func (*PRStatus) SetUnhandled ¶ added in v0.17.0
SetUnhandled records that no rule recognised this PR's failure.
func (*PRStatus) SkippedEntries ¶
func (s *PRStatus) SkippedEntries() []StatusEntry
func (*PRStatus) Snapshot ¶
func (s *PRStatus) Snapshot() []StatusEntry
func (*PRStatus) StaleEntries ¶
func (s *PRStatus) StaleEntries() []StatusEntry
StaleEntries returns entries whose failure is stale: the PR head is behind its base branch and every failing check is green on the base branch head. Like BlockedEntries these are kept out of ActionRequired and the failed counts -- the remedy is "update the branch and let CI re-run", not "rescue the code". Oldest PR first, like ActionRequired.
func (*PRStatus) StateAt ¶
func (s *PRStatus) StateAt(idx int) StatusState
StateAt returns the current state of the entry at idx, or StatusPending when idx is out of range.
func (*PRStatus) UnhandledEntries ¶ added in v0.17.0
func (s *PRStatus) UnhandledEntries() []StatusEntry
UnhandledEntries returns the entries whose failure no rule recognised.
func (*PRStatus) WaitingEntries ¶ added in v0.12.0
func (s *PRStatus) WaitingEntries() []StatusEntry
WaitingEntries returns entries whose required checks have not all reported. They are kept out of ActionRequired: the remedy is time.
type Policy ¶ added in v0.13.0
type Policy struct {
// Sweep is false when the repository's exception switches the sweep
// off. Every PR of that repository is then skipped.
Sweep bool
// UpdateTypes lists the update types that merge when green, per bot PR
// kind. A kind that is absent merges nothing.
UpdateTypes map[Kind][]UpdateType
// Schedule reports whether the scheduled sweep runs for the team.
Schedule bool
Rescue RescuePolicy
Concurrency Concurrency
ModelConfig string
SlackChannel string
// Sources names every file that produced this policy, in the order the
// files were applied, so one outcome explains its own decision.
Sources []string
}
Policy is the resolved bot PR sweep policy of one repository: the company defaults, the owning team's deviations and the repository's own exception, merged in that order.
func CompanyDefaults ¶ added in v0.13.0
func CompanyDefaults() Policy
CompanyDefaults is the policy that applies where no file says otherwise: patch and minor updates merge when green for Renovate and Dependabot, Align files and Herald PRs carry no version change and always merge, a major and an update whose size could not be read wait for a person. The schedule and the rescues are off.
func (Policy) AllowsUpdate ¶ added in v0.13.0
func (p Policy) AllowsUpdate(updateType UpdateType) bool
AllowsUpdate reports whether any bot PR kind of the policy merges this update type.
func (Policy) Clone ¶ added in v0.13.0
Clone returns a copy that shares nothing with the original, so one repository's exception cannot reach another repository's policy.
func (Policy) DeclaredUnenforced ¶ added in v0.13.0
DeclaredUnenforced names the caps the policy declares that this build does not enforce, so a team is told rather than left to assume. It is empty while the team has the rescues off: a cap on a rescue the team does not want bounds nothing either way.
type RescueMarker ¶
type RescueMarker struct {
Tool string `json:"tool,omitempty"`
Outcome string `json:"outcome"`
// Kind tells a rescue record ("" or "rescue") from a sweep evidence
// record ("evidence"). Evidence never counts as a prior rescue attempt.
Kind string `json:"kind,omitempty"`
Reason string `json:"reason,omitempty"`
HeadSHA string `json:"head_sha,omitempty"`
At time.Time `json:"at,omitempty"`
Fingerprint
// Stale and Rebased are computed by MarkStale, never serialized into
// the marker. Rebased is set when the head moved but the change did not.
Stale bool `json:"-"`
Rebased bool `json:"-"`
}
RescueMarker records a prior automated rescue attempt on a PR. It is embedded as a machine-readable HTML comment inside an ordinary PR comment, so any tool that can comment on a PR (a klaus agent, a Cursor agent, a GitHub Action) can participate without coupling to marge:
<!-- ai-rescue: {"tool":"klaus","outcome":"failed","reason":"...","head_sha":"...","at":"2026-06-09T18:40:00Z"} -->
HeadSHA ties the attempt to the code it was attempted against. Renovate force-pushes on rebase or version change, so a marker whose head_sha no longer matches the PR head describes code that may no longer exist. The embedded Fingerprint (patch_id, change_id; optional, absent from markers written before it existed) tells the two apart: when the head moved but the fingerprint still matches, the branch was only rebased and the attempt still stands; otherwise it is stale and the PR is fair game for another rescue.
func ParseRescueMarker ¶
func ParseRescueMarker(body string) *RescueMarker
ParseRescueMarker extracts the last ai-rescue marker from a comment body. It returns nil when the body contains no parseable marker; a malformed JSON payload is ignored rather than treated as an error so a mangled comment can never break a sweep.
func (*RescueMarker) CommentBody ¶
func (m *RescueMarker) CommentBody() string
CommentBody renders the full PR comment for this marker: a human-readable summary followed by the machine-readable marker.
func (*RescueMarker) IsEvidence ¶ added in v0.12.0
func (m *RescueMarker) IsEvidence() bool
IsEvidence reports whether the marker is sweep evidence rather than the record of a rescue attempt.
func (*RescueMarker) MarkStale ¶
func (m *RescueMarker) MarkStale(currentHeadSHA string, current func() Fingerprint)
MarkStale sets Stale and Rebased by comparing the marker with the PR's current head. Same head (short-vs-full SHA prefixes match): fresh. Head moved: the marker stays fresh, flagged Rebased, when the change it was written for is still the change on the branch -- decided by the marker's fingerprint against the current one, which `current` computes on demand. It is only called when the head moved and the marker carries a fingerprint; nil means none can be computed. Otherwise the marker is stale. A marker without a recorded SHA cannot be aged out, so it stays fresh until a newer marker replaces it.
type RescuePolicy ¶ added in v0.13.0
type RescuePolicy struct {
Enabled bool
Timeout time.Duration
Weekly int
Budget Budget
Confirm Confirm
}
RescuePolicy bounds the rescues of one team. Timeout is the wall-clock budget of a single rescue and is meant to become the run's execution timeout; Weekly is how many rescues the team spends per week. See RescuesDispatched for what this build applies.
type StatusEntry ¶
type StatusEntry struct {
PR PRInfo
State StatusState
Detail string
// Kind and UpdateType are set once the PR has been read; both are
// empty for a PR the sweep could not fetch.
Kind Kind
UpdateType UpdateType
// Label is the bot-prs-sweep/<class> label that is on the PR after the
// sweep; empty when none was written (dry run, or the write failed).
Label string
// Rescue is the most recent prior automated rescue attempt found on
// the PR, if any. Only populated for failure-state entries.
Rescue *RescueMarker
// ObsoleteReason says why an obsolete PR is obsolete, for consumers
// that dispatch on it rather than on Detail. Empty unless State is
// StatusObsolete.
ObsoleteReason ObsoleteReason
// Policy is the sweep policy resolved for this PR's repository. Nil
// for a PR the sweep could not fetch.
Policy *Policy
// Unhandled describes a failure no rule of the catalogue recognised.
// Nil when a rule matched, or when the state is not one a rule acts on.
Unhandled *Unhandled
}
func SplitActionRequired ¶
func SplitActionRequired(entries []StatusEntry) (security, other []StatusEntry)
SplitActionRequired partitions the action-required list into security failures and everything else, preserving the input order in each group.
type StatusState ¶
type StatusState int
const ( StatusPending StatusState = iota StatusChecking StatusApproving StatusMerging StatusRetrying StatusMerged StatusAlreadyMerged StatusAutoMerge StatusFailed StatusFailedSecurity StatusBlockedCI StatusSkipped StatusConflict StatusUntrustedAuthor // StatusStale marks a failing PR whose head is behind its base branch // and whose every failing check is green on the base branch head: the // failure was most likely fixed on the base branch after the PR's last // build, so the first move is to refresh the branch, not to rescue it. StatusStale // StatusRefreshed marks a stale PR whose branch was just updated from // its base (the "Update branch" button); CI is running again and the // next sweep decides. StatusRefreshed // StatusCancelled marks a failing PR whose every failing check is a // CircleCI build that CircleCI itself cancelled (a newer pipeline on the // branch, a redundant workflow) rather than one that failed a step. // There is no verdict on the code yet: the remedy is a retry, not a // rescue. StatusCancelled // StatusRetried marks a cancelled PR whose builds were just retried on // the same commit; CI is running again and the next sweep decides. StatusRetried // StatusNoVerdict marks a failing PR whose every failing check // established nothing about the code: the job was cancelled, or a // CircleCI project setting refused the pipeline. There is nothing to // rescue, and a security check in this shape is not a finding. The // detail names the remedy for each check. StatusNoVerdict // StatusObsolete marks a bot PR that is not worth fixing: either a // sibling PR carries a higher version of the same dependency, or the // diff changes nothing that executes. Both want closing, not rescuing. // The entry's ObsoleteReason says which, and Detail says why. StatusObsolete // StatusWaitingChecks marks a PR whose required status checks have not // all reported: a required context is missing or pending. The sweep // waits; it never merges past a required check. StatusWaitingChecks // StatusAwaitingApproval marks a green PR that GitHub refused to merge // for a review reason the sweep's own approval did not satisfy. StatusAwaitingApproval // StatusHeld marks a green PR the sweep policy leaves to a person, for // instance a major update or one whose update type could not be read. StatusHeld // StatusEligible marks a green eligible PR the sweep did not merge // because the merge action was not selected. StatusEligible // StatusRemedied marks a PR a rule of the catalogue acted on. The // action's evidence names the rule and what it did; the next sweep // classifies the result. StatusRemedied )
func (StatusState) String ¶
func (s StatusState) String() string
type SupersededBy ¶ added in v0.11.0
SupersededBy maps a PR to the detail line naming the sibling that supersedes it, keyed by PRKey. It is computed once per sweep from the PR list and read without locking while the PRs are processed.
func FindSuperseded ¶ added in v0.11.0
func FindSuperseded(prs []PRInfo) SupersededBy
FindSuperseded returns, for every PR that a sibling supersedes, the detail naming the PR that supersedes it. Two PRs are siblings when they are open on the same repository and the same base branch and their titles name the same dependency; the one whose target version is highest wins and every other one is superseded.
A PR is only ever superseded on positive evidence: both titles must name a dependency and a target version, and both versions must parse as semver. Equal versions supersede nothing, because neither is higher.
PRInfo.BaseRef is empty on the PRs that come from a GitHub issue search, which does not report a base branch. Those group together as before, so a repository with a maintenance branch can group two PRs that target different branches. A supersession never suppresses a merge, so the cost of such a group is a mislabelled report line.
type TableColumn ¶
type TableColumn struct {
Label string
Width int
Fn func(PRInfo) string
// Color optionally returns an ANSI color prefix for a value. The
// value is padded to Width first, then wrapped, so colored cells
// stay aligned with the rest of the table.
Color func(PRInfo) string
}
func DependencySelectedColumns ¶
func DependencySelectedColumns() []TableColumn
func FullColumns ¶
func FullColumns() []TableColumn
func RepoSelectedColumns ¶
func RepoSelectedColumns() []TableColumn
type Unhandled ¶ added in v0.17.0
type Unhandled struct {
// Signature identifies the shape of the failure: the failing checks and
// the log excerpt, normalised.
Signature string
// Checks are the failing checks that produced a verdict.
Checks []string
// Excerpt is the log excerpt a rule would match against, when one was
// read. Empty when no rule asked for a log.
Excerpt string
}
Unhandled is a failure the catalogue does not recognise yet. Its signature groups the same failure across PRs, so a pattern worth a rule is visible as a count rather than as one PR at a time.
type UpdateType ¶ added in v0.12.0
type UpdateType string
UpdateType is the semantic size of a dependency update. Align files and Herald PRs carry no version change and are UpdateNone; a Renovate or Dependabot PR whose versions cannot be read is UpdateUnknown.
const ( UpdateMajor UpdateType = "major" UpdateMinor UpdateType = "minor" UpdatePatch UpdateType = "patch" UpdateDigest UpdateType = "digest" UpdatePin UpdateType = "pin" UpdateLockfile UpdateType = "lockfile" UpdateNone UpdateType = "none" UpdateUnknown UpdateType = "unknown" )
func ClassifyUpdate ¶ added in v0.12.0
func ClassifyUpdate(kind Kind, title, body string) UpdateType
ClassifyUpdate derives the update type of a bot PR from what the bot wrote. Dependabot titles name both versions ("from X to Y"); a Dependabot group names them per dependency in the body. Renovate titles name only the target, so the source comes from the body's Change column. Grouped PRs take the largest change of their rows. Anything that cannot be read is UpdateUnknown, never a guess.