Documentation
¶
Overview ¶
Package goprogram is the one go/packages front end for the gates that type-check this repository's own source.
Ten packages load through it. cmd/audit_md_escaping walks the calls that interpolate a GitLab-authored value into Markdown, cmd/internal/actionrequests walks the calls an action can reach, for cmd/audit_readonly_graphql and for the request derivation, cmd/internal/graphqldocs folds every raw GraphQL document to the one string GitLab would receive, and cmd/audit_graphql_shapes pairs each of those documents with the struct that decodes it. cmd/audit_action_ids folds the action IDs the server publishes to a model, cmd/audit_catalog_first resolves the calls that aggregate each package's ActionSpecs, cmd/audit_dead_consts holds every unexported constant to something that reads it, cmd/audit_sdk_context holds every call into client-go to the caller's context, cmd/audit_tenancy holds the tenant policy register to the code that enforces it, and cmd/audit_e2e_coverage's static check reads the end-to-end test packages. They ask different questions of the loaded program and index it different ways, which is why only the front end lives here: the load mode, the config, and the rule that a package which did not type-check stops the run.
That last rule is why this package exists rather than being a copy per gate. Every gate here answers "cannot tell" for anything it cannot resolve, and a partially typed package resolves nothing: the escaping audit would classify every value as unfollowable, the read-only audit would find no handlers, and the document collector and the shape audit would fold no constants. Each would then report a clean run over source it never understood, which is the one failure mode a gate must not have. The first four gates wrote the refusal four times with four wordings, so a change to it was a four-file edit with one file easy to forget.
What stays with each gate is everything above the load: its own indexers, its own detectors, its own question and its own binary.
Four of them load test variants: cmd/audit_e2e_coverage's static check and cmd/audit_action_ids read test packages that exist only behind the e2e build tag, which those two pass, and cmd/audit_dead_consts and cmd/audit_catalog_first read the test variants of production packages without one. LoadWith takes the Options those loads need, test variants and build tags, and Load is the same call with neither, so the loads that read production source alone are unchanged.
Options.Env is there for the one load that is not of this repository at all: cmd/internal/graphqldocs reads the GraphQL documents client-go builds, which means loading a module directory in the module cache, and two toolchain settings decide whether that works. The settings and their reasons stay with that caller, since they are a property of loading somebody else's module rather than of this front end.
github.com/jmrplens/gitlab-mcp-server/v3/cmd/audit_1to1/internal/shared.LoadToolPackages is deliberately not folded in. Its mode is now this one less NeedCompiledGoFiles, which it has no reader for, but its contract is not this one: it refuses more widely than Load does, collecting every error of every package it loaded and aborting on all of them at once where Load stops at the first error of a package the caller asked for; it returns a subset rather than what it loaded, keeping the packages under internal/tools and dropping the rest; and it memoizes that result per root. That is a different contract, not a different wording of this one.
It did load with NeedDeps, and the reason it no longer does is the one written above: nothing in the audit reads a dependency's syntax, so type-checking the tree from source cost about half of every load and changed no answer in any of the six reports.
Index ¶
Constants ¶
const LoadMode = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports | packages.NeedForTest
LoadMode is what the gates need from the loader: syntax to walk, types so an identifier resolves to the object it names and a constant expression folds to the one string it denotes, and imports so an object has one identity across the packages that share it.
NeedDeps is deliberately absent, for one reason that holds for every caller: each of them only ever reads bodies written inside the patterns it loads, so type-checking the dependency tree from source would cost minutes and change no answer. What a dependency's function returns is judged by its name and its signature, both of which come in through export data, which also gives each of its objects the same identity the packages using them see. NeedForTest is here for a gate that loads test variants and has to tell the test main the go tool synthesizes from a package this repository wrote. The only thing that distinguishes them on the path is a ".test" suffix, which a real package whose directory is named that way carries too, and skipping such a package would drop its declarations and read as clean. ForTest names the package under test and is empty for everything else, so it answers the question the path cannot. It is metadata `go list` already produces for a load that asks for tests: no extra type-checking, and no cost at all for the callers that load none.
const ModulePath = "github.com/jmrplens/gitlab-mcp-server/v3"
ModulePath is this repository's module path, the prefix every gate trims off an import path so a report names a package the way the repository does, and the prefix it resolves the shared packages under.
It is spelled here once. Two gates used to carry their own copy, one built from a module constant and one written out in full, and a module path that moves (it did, at v3) is a change that has to land in every copy at once or a gate goes on resolving a package that no longer exists.
const ToolutilPath = ModulePath + "/internal/toolutil"
ToolutilPath is the import path of the package that owns the escaping helpers, ActionSpec, the route constructors and the shared GraphQL executors: the one package every gate resolves calls into. Resolution keys on the path rather than on the package name so an import alias cannot fool it.
Variables ¶
This section is empty.
Functions ¶
func Load ¶
Load type-checks the packages named by patterns, rooted at dir, and returns them in the loader's order. Every returned package type-checked without error, so a caller may read TypesInfo without checking it first.
The overlay is how a test supplies source that is not on disk: a fixture package written in the test file itself type-checks against the real packages it imports, so a gate is exercised on the shapes it has to handle rather than on a mock of them. Production passes nil.
A pattern that matches nothing is an error rather than an empty result. A gate that audited no package would otherwise pass, which is the same silence [packageLoadError] refuses one package at a time.
Types ¶
type Options ¶ added in v3.1.0
type Options struct {
// Tests includes each package's test variants, type-checked from source,
// so a gate over _test.go files sees them as the test binary would.
Tests bool
// BuildTags are the build constraints the load satisfies, as -tags would.
// Empty means the default constraints, which is what every earlier caller
// loads under.
BuildTags []string
// Overlay supplies source that is not on disk, as [Load]'s parameter
// does.
Overlay map[string][]byte
// Env is the whole environment the toolchain runs under, as
// [os/exec.Cmd.Env] takes it. Empty inherits this process's, which is what
// every caller reading this repository's own source wants.
//
// It exists for the one load that is not of this repository: reading the
// GraphQL documents client-go builds means loading a module directory in
// the module cache, which this process neither owns nor configured, and
// two settings decide whether that works at all. The reasons are written
// down beside the caller that needs them, in cmd/internal/graphqldocs,
// because they are a property of loading somebody else's module rather
// than of this front end; all this does is carry them through.
Env []string
}
Options is what a load may ask for beyond what every gate shares.
The four gates that existed first load production source with no build tag and no test files, and Load still gives them exactly that. The e2e coverage gate reads test packages that only exist behind the e2e tag, which is a different load and not a different wording of the same one, so it asks for both here rather than every caller gaining two parameters it passes as zero.