ci

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 28, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

Package ci holds the checks that are about the REPO rather than about any one binary: properties every command under cmd/ must have, asserted by walking the directory rather than by listing the commands, so that a binary added tomorrow is held to them on the day it appears rather than on the day somebody remembers to add it to a list.

It has no exported API. See onboarding_test.go, and docs/ONBOARDING.md for the standard it enforces.

Index

Constants

View Source
const (
	// GoEnvRemedy is the one thing to do about a go command that inherits the
	// caller's environment.
	GoEnvRemedy = "set cmd.Env = goenv.Clean(os.Environ())"
	// GoEnvRemedyAllow is the one thing to do about an allowlist entry that
	// names no offender: the list only shrinks.
	GoEnvRemedyAllow = "delete the stale row; the allowlist only shrinks"
)
View Source
const (
	// NetRemedy is the one thing to do about a real host in a unit test.
	NetRemedy = "mock the endpoint with httptest or a local fake"
	// NetRemedyAllow is the one thing to do about an allowlist entry that names
	// no offender: the file only shrinks.
	NetRemedyAllow = "fix the host; the allowlist only shrinks"
)
View Source
const (
	// TemplateRemedyJoin is the one thing to do about a raw filepath.Join.
	TemplateRemedyJoin = "wrap the path in strconv.Quote"
	// TemplateRemedyLiteral is the one thing to do about an OS path literal.
	TemplateRemedyLiteral = "wrap the path in strconv.Quote; a backslash there is an escape the literal does not have"
	// TemplateRemedyAllow is the one thing to do about an allowlist entry that
	// names no offender: the file only shrinks.
	TemplateRemedyAllow = "quote the path; the allowlist only shrinks"
)
View Source
const (
	// TestbinRemedyCopy is the one thing to do about a copied built binary.
	TestbinRemedyCopy = "place built binaries with testbin.Place: link, never copy"
	// TestbinRemedyAllow is the one thing to do about an allowlist entry that
	// names no offender: the file only shrinks.
	TestbinRemedyAllow = "fix the copy; the allowlist only shrinks"
)
View Source
const (
	// WaitRemedySleep is the one thing to do about a fixed sleep.
	WaitRemedySleep = "poll for the event up to NOVA_TEST_WAIT, not a fixed sleep"
	// WaitRemedyBound is the one thing to do about a short context or timer bound.
	WaitRemedyBound = "raise the bound to thirty seconds or more, or inject a fake clock"
	// WaitRemedyElapsed is the one thing to do about an elapsed-time assertion.
	WaitRemedyElapsed = "assert the event, not the clock; use a fake clock if the code needs one"
	// WaitRemedyAllow is the one thing to do about an allowlist entry that
	// names no offender: the file only shrinks.
	WaitRemedyAllow = "fix the wait; the allowlist only shrinks"
)
View Source
const (
	RedNamedTest     = "named-test"
	RedOwnBuildBreak = "own-build-break"
	RedCancelledLeg  = "cancelled-leg"
	RedKnownFlake    = "known-flake"
	RedInfra         = "infra"
)

The closed class set of the CI-red reading. own-build-break is a decider's label: the rule table can never license it, because a build that does not compile is the change's.

View Source
const BenchRunnerAllowPath = "testdata/bench-runners.allow"

BenchRunnerAllowPath is the allow file, relative to internal/ci.

View Source
const CardTemplatesVerbLine = "cardtemplates  read every shipped card template; refuse a command only one of the estate's platforms has"

CardTemplatesVerbLine is the help line the class test is entered under, word for word as docs/SPEC-CI.md prints it.

View Source
const DefaultFailedMaxLines = 8

DefaultFailedMaxLines is how many of a test's own message lines print before the rest are counted rather than shown. Cap and count: the count is the truth about the test whether or not the lines printed.

View Source
const FailedVerbLine = "failed  read a run's failing jobs; print the failing tests, their file and line"

FailedVerbLine is the help line this verb is entered under, word for word as docs/SPEC-CI.md prints it.

View Source
const GoEnvVerbLine = "goenv   read every .go under cmd/ and internal/; refuse a child `go` that inherits the caller's environment"

GoEnvVerbLine is the help line the class test is entered under.

View Source
const NetVerbLine = "net     read every _test.go on the CI path; refuse a real network host or host:port"

NetVerbLine is the help line the class test is entered under, word for word as docs/SPEC-CI.md prints it.

View Source
const TemplatesVerbLine = "templates   read every _test.go; refuse a filesystem path unquoted in a JSON or template literal"

TemplatesVerbLine is the help line the class test is entered under, word for word as docs/SPEC-CI.md prints it.

View Source
const TestbinVerbLine = "testbins   read every _test.go on the CI path; refuse copying a built executable into a fixture"

TestbinVerbLine is the help line the class test is entered under, word for word as docs/SPEC-CI.md prints it.

View Source
const UnexecutedListPath = "internal/ci/testdata/unexecuted_examples.txt"

UnexecutedListPath is the shrink-only list, relative to the repo root.

View Source
const WaitsVerbLine = "waits   read every _test.go on the CI path; refuse a fixed wall-clock wait or bound"

WaitsVerbLine is the help line the class test is entered under, word for word as docs/SPEC-CI.md prints it.

Variables

View Source
var CardTemplateDirs = []string{
	"docs/templates",
	"tools/templates",
}

CardTemplateDirs are the directories this repository ships card templates in, relative to the repository root. A directory that is not there is not an error: the list names where a template MAY live, and the estate grows its directories before it grows its templates.

View Source
var FileLineListOptions = allowlist.Options{Key: allowlist.Fields(2), Ceiling: true, MissingIsEmpty: true}

FileLineListOptions are the options of the `file:line kind date reason` lists (waits, net, goenv, testbins, templates) and of the `file spell date reason` card template list: a row is keyed by its first two fields, every list only shrinks, and a missing file is an empty list -- a tree with nothing parked in it is the goal (nova-tools#4339).

View Source
var PastedDocs = []string{
	"README.md",
	filepath.Join("docs", "USAGE.md"),
	filepath.Join("docs", "CLI.md"),
}

PastedDocs are the documents a stranger pastes from, per SPEC-TOOLWORK.md documents rule 6, relative to the repo root.

Functions

func AddedListRows

func AddedListRows(base, head string) []string

AddedListRows returns the rows of head that base does not carry: for a shrink-only list, every one is a row the change adds, and each fails the class test (SPEC-TOOLWORK.md documents rule 6, "a new unexecuted example fails the class test on the change that adds it").

func BannerExampleLines

func BannerExampleLines(banner string) ([]string, error)

BannerExampleLines returns every line of a help banner's `example:` block, whatever program leads it: the block is the run of non-blank indented lines directly under the heading, and it ends at the first blank or unindented line (the prose that follows). A line after one ending in ` \\` continues that command and is not an example of its own, so a command is one row, its first physical line, as the $ lines of the docs are. Whitespace inside a line is collapsed, so a banner may align its flags. onboarding.ExampleLines is the first-run reader and stops at the first line its tool does not lead; counting with it cut cmd/nova-redis's block short at its second line (`nova-secrets exec ... -- nova-redis serve ...`), and the two nova-redis lines under it went uncounted. A block with no indented line under the heading is an error.

func CILegsFromYAML

func CILegsFromYAML(yaml string) map[string]bool

CILegsFromYAML reads the ci.yml workflow text and returns the GOOS values for which it runs legs. A leg is declared by the value of a `runs-on:` key or of a matrix key that feeds one (`os:`, `runner:`, `labels:`), because a darwin leg is usually a matrix value behind a `runs-on: ${{ ... }}` expression. The labels are self-hosted linux -> "linux", self-hosted macOS -> "darwin", and the GitHub-hosted ubuntu-latest -> "linux" and macos-latest -> "darwin". A comment never declares a leg. There is no native Windows leg since 2026-09-18.

func ChangeBase

func ChangeBase(root string, getenv func(string) string) (string, error)

ChangeBase returns the commit a change is compared against: in a GitHub Actions run, the event's own base (pull_request.base.sha, merge_group's base_sha, a push's before); otherwise the merge base of HEAD and origin/<GITHUB_BASE_REF> (dev when unset), falling back to the local branch of that name. The commit is fetched once from origin when the clone lacks it (a --depth=1 checkout).

func ComparedEntryProblem

func ComparedEntryProblem(root string, c ComparedEntry, docs []string) string

ComparedEntryProblem says why a compared_examples.txt entry is not a comparator test FOR ITS EXAMPLE, or "" when it is. docs are the docs the example is pasted in (none for a help-only example). The test must:

  • be declared in a _test.go file of the example's tool's package, cmd/<tool>/;
  • reach the comparator (onboarding.CompareTranscript, Compare, Execute or ExecuteWith) from its own body or a test helper it calls;
  • carry the example's command text: a string literal naming at least the tool and its verb that the example is, word for word, or begins with (`"$ nova-wake presence "` names `$ nova-wake presence --store ...`), or, for a $ line, an onboarding.FirstRun/Transcript of that tool whose transcript in a doc the test reads holds that exact line;
  • for an example pasted in a doc, read one of those docs.

func FailedStepName

func FailedStepName(job FailedJob) string

FailedStepName is the first step of a job whose conclusion was failure, and "" when the forge named none: a step is never guessed, the way a file:line never is.

func FileLineKey

func FileLineKey(file string, line int, kind string) string

FileLineKey is a finding's key in those lists, the first two fields of the row that would name it.

func ForgeAttemptOf

func ForgeAttemptOf(r FailedReport) (attempt int, sha string, err error)

ForgeAttemptOf is where the spent-rerun count comes from, and the only place it comes from: the forge's own run_attempt and head_sha for the red jobs this report read. It FAILS CLOSED. A report whose red jobs carry no attempt, or whose red jobs disagree with each other about the attempt or the sha, yields an error and no count, because a licence granted without knowing whether this is already the second attempt is the manufactured green the whole reading exists to refuse. A report with nothing red asks nothing of the forge: there is no licence to grant and no attempt to check.

func HelpBannerExamples

func HelpBannerExamples(root string) (map[string]string, error)

HelpBannerExamples returns every `example:` line of every `help` banner a tool under root/cmd carries, keyed "example: <line>" and mapped to the source file that carries it, per SPEC-TOOLWORK.md documents rule 6 ("every `example:` line of every `help`"). A banner is a string literal (or a `+` chain of them) in a non-test .go file of cmd/<tool>/ holding the `\nexample:\n` heading; its lines are read through BannerExampleLines, every line of the block whatever tool leads it. A literal that is only the heading (a splice point such as nova-sprint's registry.go) carries no lines; any other banner whose example block holds no command is an error naming its file, so a banner is never silently left out of the count.

func HelpExampleLines

func HelpExampleLines(usage, tool string) ([]string, error)

HelpExampleLines wraps onboarding.ExampleLines: the `example:` lines of a help banner pasted in one of the PastedDocs are pasted examples too.

func ListAtCommit

func ListAtCommit(root, commit, rel string) (string, bool, error)

ListAtCommit returns the file at rel as it stands at commit, and false when the commit does not carry it (the change introduces it).

func ListRows

func ListRows(list string) []string

ListRows returns the entries of a one-entry-per-line list (blank lines and '#' lines skipped, each entry trimmed), in order, without repeats.

func LogErrorLines

func LogErrorLines(text string) []string

LogErrorLines is the lines of one job's log the RUNNER itself marked as errors, in the order it wrote them, with its annotation and its wrapper taken off. It is what a job that went red outside `go test` has instead of a failing test: the compiler's own diagnosis, already picked out of the log by the forge that recorded it.

func ParseInfraSteps

func ParseInfraSteps(text string) []string

ParseInfraSteps reads the infra-steps table: one step NAME a line, blank lines and lines beginning '#' skipped. The names are the caller's data and there is no default.

func ParseJobLog

func ParseJobLog(job, text string) ([]TestFailure, []Timeout)

ParseJobLog reads one job's raw log -- a self-hosted runner's plain `go test` output, a hosted runner's `go test -json` frames, or a log holding both -- and returns the failing tests and the timeouts it names, in the order the log named them.

func PastedDocExamples

func PastedDocExamples(root string) ([]string, error)

PastedDocExamples returns every pasted example of the PastedDocs: each $ line inside a fenced code block, and each line of a help banner's `example:` block pasted inside one (as "example: <line>"). A missing doc is an error naming it, so the scan never silently covers fewer documents.

func PlatformLinesFromTESTSmd

func PlatformLinesFromTESTSmd(md string) ([]string, error)

PlatformLinesFromTESTSmd reads docs/TESTS.md and returns the GOOS values named by `Platform:` lines that appear within `## nova-*` sections. A platform line may be written as `Platform: darwin` or `Platform: recorded on macOS (darwin) — prose...`; in either case every GOOS the line names as a whole word, in any case ("Linux" names linux), is extracted. A Platform line in a `## nova-*` section that names no recognised GOOS is an error naming its line number, so a typo or an unsupported platform is never silently left out of the CI-leg check.

func StripLogLine

func StripLogLine(line string) string

StripLogLine turns one raw line of a GitHub Actions log into the line `go test` wrote: no carriage return, no ANSI colour, no runner timestamp.

Types

type BenchRunnerSite

type BenchRunnerSite struct {
	File string
	Func string
	Line int
}

BenchRunnerSite is one ssh exec site: its file (slash, from the repo root) and its function key (Recv.Name or Name).

func BenchRunnersInSource

func BenchRunnersInSource(rel string, src []byte) ([]BenchRunnerSite, error)

BenchRunnersInSource finds the sites in one file's source.

func FindBenchRunners

func FindBenchRunners(root string) ([]BenchRunnerSite, error)

FindBenchRunners walks cmd/ and internal/ under root.

func (BenchRunnerSite) Key

func (s BenchRunnerSite) Key() string

Key is the allow row key: `<file> <func>` (lines move; the key does not).

type Cancellation

type Cancellation struct {
	Job   string
	Step  string
	After time.Duration
}

Cancellation is one step a run cancelled out from under, with how long it had been running. A cancelled sibling is not a failure, but a reader who does not see it will look for a red that is not there.

func CancelledSteps

func CancelledSteps(job FailedJob) []Cancellation

CancelledSteps reads a job's own steps rather than its log: a cancellation leaves nothing in the text, and the step record carries both the name and the clock.

type CardTemplateFinding

type CardTemplateFinding struct {
	File   string // path relative to the repository root, slashes
	Line   int    // 1-based
	Spell  string // the rule's name, which is also the allowlist's key
	Only   string // "linux", "darwin" or "wrong-tool"
	Text   string // the offending line, trimmed and bounded
	Remedy string // the portable spelling
}

CardTemplateFinding is one refused spelling: where it is, what was spelt, the platform it belongs to, and the one thing to do about it.

func (CardTemplateFinding) Key

func (f CardTemplateFinding) Key() string

Key is the finding's key in the card template list: `file spell`, the first two fields of the row that would allow it.

func (CardTemplateFinding) Render

func (f CardTemplateFinding) Render() string

Render is the one-line refusal for this finding.

type CardTemplatesResult

type CardTemplatesResult struct {
	Templates   int
	Allowlisted int
	Findings    []CardTemplateFinding
	Stale       []CardTemplateFinding
	// Measured is the set the allowlist must hold (allowlist.Check): the key of
	// every row a finding used and of every finding no row allows.
	Measured map[string]bool
}

CardTemplatesResult is one run: the templates read, the entries the allowlist still honours, the offenders left, and the entries that name no offender.

func CheckCardTemplates

func CheckCardTemplates(root string, dirs []string, allowlistPath string) (CardTemplatesResult, error)

CheckCardTemplates reads every card template under the given directories and returns the offenders, the allowlist rows honoured, and any row that names no offender. The directories come from the caller, never from a walk of the repository, so a test drives it with a fixture tree. A directory that does not exist is skipped.

func (CardTemplatesResult) ExitCode

func (r CardTemplatesResult) ExitCode() int

ExitCode is 2 when anything is refused and 0 when the tree is clean.

func (CardTemplatesResult) FailLine

func (r CardTemplatesResult) FailLine() string

FailLine closes a refusal with the counts.

func (CardTemplatesResult) OKLine

func (r CardTemplatesResult) OKLine() string

OKLine is the one line a clean run prints.

func (CardTemplatesResult) Refused

func (r CardTemplatesResult) Refused() int

Refused is the number of lines a run would print: offenders plus stale rows.

type ComparedEntry

type ComparedEntry struct {
	File string // test file, relative to the repo root
	Test string // test function name
	Ex   string // the example, exactly as listed: "$ ..." or "example: ..."
}

ComparedEntry is one entry of testdata/compared_examples.txt: the test that executes a pasted example through the comparator.

type DocExample

type DocExample struct {
	Doc  string // relative to the repo root, as in PastedDocs
	Line string // "$ ..." or "example: ..."
}

DocExample is one pasted example and the doc it is pasted in.

func PastedDocExamplesByDoc

func PastedDocExamplesByDoc(root string) ([]DocExample, error)

PastedDocExamplesByDoc is PastedDocExamples with the doc each example is pasted in.

type FailForge

type FailForge interface {
	// ResolveRun turns the caller's words into one run id.
	ResolveRun(sel RunSelector) (int64, error)
	// Jobs lists the run's jobs, in the forge's own order.
	Jobs(runID int64) ([]FailedJob, error)
	// JobLog is one job's whole log, raw: timestamps, ANSI and all.
	JobLog(jobID int64) (string, error)
}

FailForge is what `nova-ci failed` needs from a forge, and all of it.

type FailedJob

type FailedJob struct {
	ID         int64
	Name       string
	Conclusion string // success, failure, cancelled, timed_out, skipped, ...
	Attempt    int    // the forge's run_attempt for this job; 1 is the first, 0 is absent
	HeadSHA    string // the forge's head_sha for the run this job ran in
	Steps      []FailedStep
}

FailedJob is one job of a run. Attempt and HeadSHA are the forge's own provenance for this job: which attempt of the run it ran in, and the commit it ran against. They are what the CI-red reading counts spent reruns from (attempt N means N-1 reruns already spent), and they are read from the same job listing as the name and the conclusion, so no second call and no caller's word stands between the forge and the licence.

func (FailedJob) Cancelled

func (j FailedJob) Cancelled() bool

Cancelled is true for a job the run cut down rather than one that went red of its own. The forge spells it both ways, and the two are the same job.

func (FailedJob) Failed

func (j FailedJob) Failed() bool

Failed is true for a job whose conclusion is worth reading the log of. A skipped or successful job has nothing to say.

type FailedReport

type FailedReport struct {
	Jobs      int      // failing jobs this report looked at, read or not
	Cancelled int      // of those jobs, the ones cancelled rather than red of their own
	RedJobs   []RedJob // of those jobs, name, forge conclusion and failed step: the CI-red reading's mechanical facts
	Failures  []TestFailure
	NoTests   []NoTest
	Cancels   []Cancellation
	Timeouts  []Timeout
	Unread    []Unread
}

FailedReport is everything one run's failing jobs said.

func ReadFailedRun

func ReadFailedRun(f FailForge, sel RunSelector, jobFilter string) (int64, FailedReport, error)

ReadFailedRun is the verb's whole engine: resolve the run, read every job that did not succeed, and fold the logs into one report. jobFilter keeps only the jobs whose name contains it; empty keeps them all.

func (FailedReport) Empty

func (r FailedReport) Empty() bool

Empty is true when the run's failing jobs held nothing to report. A log this tool could not read is NOT nothing, and neither is a job that went red with no test event in it: those are the two a reader must be told about, or they will read a short report as a small failure.

func (FailedReport) ExitCode

func (r FailedReport) ExitCode() int

ExitCode is 1 when the run said anything red, 0 when it said nothing. A refusal is the caller's exit 2 and never reaches here.

func (FailedReport) Lines

func (r FailedReport) Lines(maxLines int) []string

Lines renders the whole report: one block per failing test, then one per job that went red with no test event in its log, then the cancellations, the timeouts and the logs it could not read, then the summary. maxLines bounds each test's own output; zero or less means the default rather than unlimited, because an unbounded log is the thing this tool exists to replace.

A NOTEST block is bounded the same way but from the END: the errors that ended the step are its last annotated lines, and the earlier ones in a long log may belong to a negative control that was supposed to be red. The lines dropped are counted above the ones shown, so the block reads in the order the runner wrote it.

A job name and a step name are QUOTED, not escaped as fields: `test (3/4 studio)` is what the reader pastes back into --job, and oneline.Field would hand them `test\x20(3/4\x20studio)`, which the forge has never heard of. A package, a test name and a file:line hold no space, so they are fields and stay bare for a grep.

func (FailedReport) SummaryLine

func (r FailedReport) SummaryLine() string

SummaryLine is the closing line: the failing jobs looked at and the failing tests found, whether or not every line printed. The verdict word is OK only when the run said nothing red, so it agrees with the exit code rather than heading a report of reds. The jobs are split into the ones red of their own and the cancelled=<n> cut down with them, because a reader chases the first kind; a job whose log could not be read is counted in unread=. Each split field is omitted when there is nothing to say.

type FailedStep

type FailedStep struct {
	Name       string
	Conclusion string
	Started    time.Time
	Completed  time.Time
}

FailedStep is one step of a job: enough to say what a cancellation cut short.

type FlakeRow

type FlakeRow struct {
	Test   string
	Issue  string
	Expiry time.Time
}

FlakeRow is one row of the flake table: a test name, the issue that tracks it and the date the row expires. A row past its expiry matches nothing.

func ParseFlakeTable

func ParseFlakeTable(text string) ([]FlakeRow, error)

ParseFlakeTable reads the flake table: one row a line, TAB-separated test, issue and expiry (YYYY-MM-DD). Blank lines and lines beginning '#' are skipped. A row that is not the shape it wants is refused by line rather than silently dropped, so an expired row can never hide behind a parse this code guessed at.

type GHFailForge

type GHFailForge struct {
	Repo    string // <owner>/<name>
	GH      string // the gh executable, "gh" unless the caller names another
	Timeout time.Duration
}

GHFailForge is the one FailForge that shells to gh. Every invocation it makes is in this file, so a reader can check them all at once, and none of them writes: this verb reads a run and says what it found.

func NewGHFailForge

func NewGHFailForge(repo, ghPath string, timeout time.Duration) *GHFailForge

NewGHFailForge returns a forge over one repository.

func (*GHFailForge) JobLog

func (g *GHFailForge) JobLog(jobID int64) (string, error)

JobLog fetches one job's whole log. gh refuses to hand over a log holding terminal escape sequences unless it is told to, and a CI log always holds them, so the flag is the normal call; a gh too old to know it is asked again without.

func (*GHFailForge) Jobs

func (g *GHFailForge) Jobs(runID int64) ([]FailedJob, error)

Jobs lists the run's jobs, paging until the forge's own total_count is met.

func (*GHFailForge) ResolveRun

func (g *GHFailForge) ResolveRun(sel RunSelector) (int64, error)

ResolveRun turns the selector into a run id.

type GoEnvFinding

type GoEnvFinding struct {
	File   string
	Line   int
	Func   string
	Kind   string
	Remedy string
}

GoEnvFinding is one child `go` that inherits the caller's environment, with its file, line, the function it stands in and the one thing to do about it. Kind is "inherit" for a go command with no sanitized environment, or "allowlist" for a row that names no offender.

func (GoEnvFinding) Render

func (f GoEnvFinding) Render() string

Render is the one-line refusal for this finding.

type GoEnvResult

type GoEnvResult struct {
	Files       int
	Allowlisted int
	Findings    []GoEnvFinding
	Stale       []GoEnvFinding
	// Measured is the set the allowlist must hold (allowlist.Check): the key of
	// every row a finding used and of every finding no row allows.
	Measured map[string]bool
}

GoEnvResult is one run of the checker: the files read, the allowlist entries still honored, the offenders left, and the entries that name no offender.

func CheckGoEnv

func CheckGoEnv(root, allowlistPath string) (GoEnvResult, error)

CheckGoEnv reads every .go file under root/internal and root/cmd and returns the go commands that inherit the caller's environment, the allowlist entries honored, and any entry that names no offender. The tree comes from the caller, never from a walk of the repository; testdata directories and internal/goenv itself are skipped.

func (GoEnvResult) ExitCode

func (r GoEnvResult) ExitCode() int

ExitCode is the status the check would exit with: 2 when anything is refused, 0 when the tree is clean.

func (GoEnvResult) FailLine

func (r GoEnvResult) FailLine() string

FailLine closes a refusal with the counts.

func (GoEnvResult) OKLine

func (r GoEnvResult) OKLine() string

OKLine is the one line a clean run prints.

func (GoEnvResult) Refused

func (r GoEnvResult) Refused() int

Refused is the number of lines the run would print: offenders plus stale allowlist entries.

type NetFinding

type NetFinding struct {
	File   string
	Line   int
	Host   string
	Kind   string
	Remedy string
}

NetFinding is one real host, with its file, line, host, kind and the one thing to do about it. Kind is "url" for an http(s) URL, "hostport" for a bare host:port, or "allowlist" for a stale entry.

func (NetFinding) Render

func (f NetFinding) Render() string

Render is the one-line refusal for this finding.

type NetResult

type NetResult struct {
	Tests       int
	Allowlisted int
	Findings    []NetFinding
	Stale       []NetFinding
	// Measured is the set the allowlist must hold (allowlist.Check): the key of
	// every row a finding used and of every finding no row allows.
	Measured map[string]bool
}

NetResult is one run of the checker: the tests read, the allowlist entries still honored, the real hosts left, and the allowlist entries that name no offender.

func CheckNet

func CheckNet(root, allowlistPath string) (NetResult, error)

CheckNet reads every _test.go under root/internal and root/cmd and returns the real hosts, the allowlist entries honored, and any allowlist entry that names no offender. The tree comes from the caller, never from a walk of the repository; it reuses the waits checker's file walk (testdata directories are skipped so the fixtures are never read as offenders) and its allowlist reader, whose `file:line kind date reason` rows are general enough for both.

func (NetResult) ExitCode

func (r NetResult) ExitCode() int

ExitCode is the status the check would exit with: 2 when anything is refused, 0 when the path is clean.

func (NetResult) FailLine

func (r NetResult) FailLine() string

FailLine closes a refusal with the counts.

func (NetResult) OKLine

func (r NetResult) OKLine() string

OKLine is the one line a clean run prints.

func (NetResult) Refused

func (r NetResult) Refused() int

Refused is the number of lines the run would print: offenders plus stale allowlist entries. The count is the truth about the CI path whether or not the lines printed.

type NoTest

type NoTest struct {
	Job   string
	Step  string   // the step whose conclusion was failure, "" when the forge named none
	Lines []string // the log lines the runner annotated as errors, in the order it wrote them
}

NoTest is one red job whose log held no test event at all, so there is no failing test to name: the job went red outside `go test`, and a C compiler error under -Werror inside a `make test` step is the specimen. The job's own failed step says where, and the lines the runner itself marked as errors say why.

type RedJob

type RedJob struct {
	Name       string
	Conclusion string
	Step       string
	Attempt    int    // the forge's run_attempt: 1 is the first run, 0 is the forge saying nothing
	SHA        string // the forge's head_sha for the run this job ran in
}

RedJob is one failed job as the reading sees it: the forge's own conclusion, the name of the step that failed, and the forge's provenance for the job -- which attempt of the run it ran in and the commit it ran against. All of them are mechanical facts, never a reading of the log and never a caller's assertion.

type RedOptions

type RedOptions struct {
	Flakes     []FlakeRow
	InfraSteps []string
	Now        time.Time
	Attempt    int
	Floor      int
	Withdrawn  bool
}

RedOptions is the caller's data and the clock for one reading. Attempt is the FORGE's own attempt number for this job at this sha, fetched by ForgeAttemptOf and never asserted by the caller: attempt N means N-1 reruns are already spent. Floor is the caller's --reruns, which can only RAISE the spent count, so an assertion withholds a licence and can never grant one the forge's count denies. Withdrawn is set when a decider took the licence back.

func (RedOptions) Reruns

func (o RedOptions) Reruns() int

Reruns is the count the licence is decided on: the forge's attempt number less one, never below the caller's floor and never below zero. An absent attempt reads as no reruns spent here and is refused before this point (ForgeAttemptOf), so nothing licences off a zero this function invented.

type RedReading

type RedReading struct {
	Class   string
	Rerun   string // "licensed" or "no"
	Finding string // "yes" or "no"
	Reruns  int
	Attempt int    // the forge's attempt number, 0 when the run had nothing red to ask about
	Why     string // "withdrawn" when a decider took the licence back; else ""
}

RedReading is the reading's whole answer: the class the rule table found ("" when it found no row at all), the licence, the spent-rerun count it was decided on, the forge's attempt number behind that count, and why the licence was withheld.

func ClassifyRed

func ClassifyRed(r FailedReport, opt RedOptions) RedReading

ClassifyRed runs the rule table over one report and returns the class and the licence. The table carries the whole licence: the rerunnable classes are cancelled-leg, known-flake and infra, and rerun=licensed needs one of them, no withdrawal, and zero reruns already spent for this job at this sha -- spent being the FORGE's attempt number less one (ForgeAttemptOf), raised but never lowered by the caller's floor. Both the grant and the refusal are therefore the forge's, not the caller's. Everything else -- a named failing test, a class the table cannot place, a second red at the same sha, a withdrawn licence -- is a finding at once, because a rerun that turns a real red green is manufactured green.

func (RedReading) Fields

func (rr RedReading) Fields() string

Fields is the tail the closing line gains under --decide, in one fixed shape:

red=<class> rerun=<licensed|no> finding=<yes|no> reruns=<n> attempt=<n|->

A red with no rule row prints red=unknown, the absence of a class rather than a guessed one. attempt= is the forge's own attempt number the reruns= count was derived from, so a reader of the line can check the licence against the run rather than take it on trust; it is `-`, never 0, on a run with nothing red to ask the forge about. The field names, their order and their spelling are the output grammar other lines parse and do not change.

type RunSelector

type RunSelector struct {
	Run        int64
	PR         int
	Branch     string
	MergeGroup bool
}

RunSelector is the one run the caller means, in the words they used: a run id, a pull request, that pull request's merge-queue run, or a branch.

type TemplateFinding

type TemplateFinding struct {
	File   string
	Line   int
	Kind   string // "join", "literal", or "allowlist" for a stale entry
	Remedy string
}

TemplateFinding is one unquoted path, with its file, line, kind and the one thing to do about it.

func (TemplateFinding) Render

func (f TemplateFinding) Render() string

Line renders the one-line refusal for this finding.

type TemplatesResult

type TemplatesResult struct {
	Tests       int
	Allowlisted int
	Findings    []TemplateFinding
	Stale       []TemplateFinding
	// Measured is the set the allowlist must hold (allowlist.Check): the key of
	// every row a finding used and of every finding no row allows.
	Measured map[string]bool
}

TemplatesResult is one run of the checker: the tests read, the allowlist entries still honored, the offenders left, and the allowlist entries that name no offender.

func CheckTemplates

func CheckTemplates(root, allowlistPath string) (TemplatesResult, error)

CheckTemplates reads every _test.go under root and returns the offenders, the allowlist entries honored, and any allowlist entry that names no offender. The tree comes from the caller, never from a walk of the repository; testdata directories are skipped so the fixtures are never read as offenders.

func (TemplatesResult) ExitCode

func (r TemplatesResult) ExitCode() int

ExitCode is the status the check would exit with: 2 when anything is refused, 0 when the tree is clean.

func (TemplatesResult) FailLine

func (r TemplatesResult) FailLine() string

FailLine closes a refusal with the counts.

func (TemplatesResult) OKLine

func (r TemplatesResult) OKLine() string

OKLine is the one line a clean run prints.

func (TemplatesResult) Refused

func (r TemplatesResult) Refused() int

Refused is the number of lines the run would print: offenders plus stale allowlist entries. The count is the truth about the tree whether or not the lines printed.

type TestFailure

type TestFailure struct {
	Job     string
	Package string
	Test    string
	At      string   // "file_test.go:73", or "" when the test printed no position
	Lines   []string // the test's own message lines, in the order it printed them
}

TestFailure is one failing test: the job it failed in, its package, its name, the first file:line its own output named, and that output.

type TestbinFinding

type TestbinFinding struct {
	File   string
	Line   int
	Kind   string
	Remedy string
}

TestbinFinding is one copied built binary, with its file, line, kind and the one thing to do about it. Kind is always "copy" for an offender; "allowlist" marks a stale allowlist entry.

func (TestbinFinding) Render

func (f TestbinFinding) Render() string

Render is the one-line refusal for this finding.

type TestbinsResult

type TestbinsResult struct {
	Tests       int
	Allowlisted int
	Findings    []TestbinFinding
	Stale       []TestbinFinding
	// Measured is the set the allowlist must hold (allowlist.Check): the key of
	// every row a finding used and of every finding no row allows.
	Measured map[string]bool
}

TestbinsResult is one run of the checker: the tests read, the allowlist entries still honored, the copies left, and the allowlist entries that name no offender.

func CheckTestbins

func CheckTestbins(root, allowlistPath string) (TestbinsResult, error)

CheckTestbins reads every _test.go under root/internal and root/cmd and returns the copied built binaries, the allowlist entries honored, and any allowlist entry that names no offender. The tree comes from the caller, never from a walk of the repository; testdata directories are skipped so the fixtures are never read as offenders.

func (TestbinsResult) ExitCode

func (r TestbinsResult) ExitCode() int

ExitCode is the status the check would exit with: 2 when anything is refused, 0 when the path is clean.

func (TestbinsResult) FailLine

func (r TestbinsResult) FailLine() string

FailLine closes a refusal with the counts.

func (TestbinsResult) OKLine

func (r TestbinsResult) OKLine() string

OKLine is the one line a clean run prints.

func (TestbinsResult) Refused

func (r TestbinsResult) Refused() int

Refused is the number of lines the run would print: offenders plus stale allowlist entries. The count is the truth about the CI path whether or not the lines printed.

type Timeout

type Timeout struct {
	Job     string
	Package string
	After   time.Duration
	Running []string
}

Timeout is one `panic: test timed out after <d>` with the tests that were still running when the alarm went off. Those tests are suspects, not verdicts.

type Unread

type Unread struct {
	Job    string
	Reason string
}

Unread is one job whose log the forge would not hand over, with the reason it gave. It is a LINE, never a refusal that sinks the run: everything the other jobs said is still what the caller asked for. The specimen is a job cancelled while its run is still in progress, whose log blob the forge answers 404 for until the run finishes.

type WaitFinding

type WaitFinding struct {
	File   string
	Line   int
	Kind   string
	Remedy string
}

WaitFinding is one fixed wait, with its file, line, kind and the one thing to do about it. Kind is "sleep", "bound", "elapsed", or "allowlist" for a stale entry.

func (WaitFinding) Render

func (f WaitFinding) Render() string

Render is the one-line refusal for this finding.

type WaitsResult

type WaitsResult struct {
	Tests       int
	Allowlisted int
	Findings    []WaitFinding
	Stale       []WaitFinding
	// Measured is the set the allowlist must hold (allowlist.Check): the key of
	// every row a finding used and of every finding no row allows.
	Measured map[string]bool
}

WaitsResult is one run of the checker: the tests read, the allowlist entries still honored, the fixed waits left, and the allowlist entries that name no offender.

func CheckWaits

func CheckWaits(root, allowlistPath string) (WaitsResult, error)

CheckWaits reads every _test.go under root/internal and root/cmd and returns the fixed waits, the allowlist entries honored, and any allowlist entry that names no offender. The tree comes from the caller, never from a walk of the repository; testdata directories are skipped so the fixtures are never read as offenders.

func (WaitsResult) ExitCode

func (r WaitsResult) ExitCode() int

ExitCode is the status the check would exit with: 2 when anything is refused, 0 when the path is clean.

func (WaitsResult) FailLine

func (r WaitsResult) FailLine() string

FailLine closes a refusal with the counts.

func (WaitsResult) OKLine

func (r WaitsResult) OKLine() string

OKLine is the one line a clean run prints.

func (WaitsResult) Refused

func (r WaitsResult) Refused() int

Refused is the number of lines the run would print: offenders plus stale allowlist entries. The count is the truth about the CI path whether or not the lines printed.

Directories

Path Synopsis
Package allowlist is the one reader and the one writer of the exception lists the class tests in internal/ci keep under internal/ci/testdata (nova-tools#4339).
Package allowlist is the one reader and the one writer of the exception lists the class tests in internal/ci keep under internal/ci/testdata (nova-tools#4339).
Package functional is the machine behind cmd/nova-ci's `functional` verb: which of a change's packages carry functional tests, and which tests those are.
Package functional is the machine behind cmd/nova-ci's `functional` verb: which of a change's packages carry functional tests, and which tests those are.
Package slowtests is the machine behind cmd/nova-ci's `slowtests` verb in docs/SPEC-CI.md, "The per-package test time budget".
Package slowtests is the machine behind cmd/nova-ci's `slowtests` verb in docs/SPEC-CI.md, "The per-package test time budget".
Package timing is the machine behind the committed script cmd/nova-ci/timing.go, which prints one pull request's time from open to all-green split into queue, setup and test per job, for the last 200 pull requests of mas-bandwidth/schema and mas-bandwidth/nova-tools (ideas #791).
Package timing is the machine behind the committed script cmd/nova-ci/timing.go, which prints one pull request's time from open to all-green split into queue, setup and test per job, for the last 200 pull requests of mas-bandwidth/schema and mas-bandwidth/nova-tools (ideas #791).

Jump to

Keyboard shortcuts

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