ci

package
v1.2.7 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 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 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 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{}

CardTemplateDirs are the directories this repository ships card templates in, relative to the repository root. The templates the estate cuts are the embedded ones read through swarm.Template (docs/SPEC-CI.md, `cardtemplates`), and no directory of loose template files is shipped, so the list is empty until a template is written into one. A directory that is not there is skipped, not an error.

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.

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

PastedDocs are the documents a stranger pastes from, the set SPEC-TOOLWORK.md counts, 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, as SPEC-TOOLWORK.md holds: 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.

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 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 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, which counts 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 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.

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 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 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 pkg/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 SourceSeams

type SourceSeams struct {
	WalkDir   func(root string, fn fs.WalkDirFunc) error
	ReadFile  func(name string) ([]byte, error)
	ParseFile func(name string, src []byte, mode parser.Mode) (*token.FileSet, *ast.File, error)
}

SourceSeams groups the file operations the source checkers read through: walking the tree, reading file bytes, and parsing Go ASTs.

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 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 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.
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.
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 the project's own repositories.
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 the project's own repositories.

Jump to

Keyboard shortcuts

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