Documentation
¶
Overview ¶
Package goprogram is the one go/packages front end for the gates that type-check this repository's own source.
Twelve packages load through it. cmd/audit_md_escaping walks the calls that interpolate a GitLab-authored value into Markdown, cmd/audit_i18n holds every text shown to a person directly to the message catalog, 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, cmd/audit_test_closed_servers holds every httptest server to being closed only once its address is no longer used, 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, the rule that a package which did not type-check stops the run, and the few facts of a load that every gate reading them has to read the same way.
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. The scaffolding several gates share above it, their command line, their exit codes and their declaration table, is cmd/internal/sourcegate.
Five 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, cmd/audit_test_closed_servers reads every package's tests under each end-to-end suite's tag, 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.
The facts of a load ¶
A gate names what it finds by package and file, and six gates had each written, in a copy of its own, some of the same answers to the questions a load raises before any rule is applied: cmd/audit_dead_consts, cmd/audit_sdk_context and cmd/audit_test_closed_servers most of them, and cmd/audit_action_ids, cmd/audit_md_escaping and cmd/audit_tenancy the name of a package or of a file. Those answers live here now:
- which loaded package is the test executable the go tool synthesizes rather than source of this repository (PackagesUnderTest, IsTestMain), and which package a test variant is (VariantName);
- how a package and a file are named the way the repository names them (TrimModulePath, RelativePath), below a root made absolute before the load (LoadRooted);
- and which files a build constraint hid from the load (IgnoredGoFiles), and which of those could hold what a gate looks for (FilesImporting), so a gate can say what it did not read instead of passing over it in silence.
Options.Env is there for the loads that are not of this repository at all: cmd/internal/graphqldocs reads the GraphQL documents client-go builds, and cmd/audit_graphql_shapes -sdk pairs them with the structs client-go decodes them into, 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 graphqldocs (ForeignModuleEnv), 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
- func FilesImporting(paths []string, importPath string, overlay map[string][]byte) []string
- func IgnoredGoFiles(pkg *packages.Package) []string
- func IsTestMain(pkg *packages.Package, underTest map[string]struct{}) bool
- func Load(dir string, patterns []string, overlay map[string][]byte) ([]*packages.Package, error)
- func LoadRooted(dir string, patterns []string, opts Options) (string, []*packages.Package, error)
- func LoadWith(dir string, patterns []string, opts Options) ([]*packages.Package, error)
- func PackagesUnderTest(loaded []*packages.Package) map[string]struct{}
- func RelativePath(path, root string) string
- func TrimModulePath(pkgPath string) string
- func VariantName(pkgPath string) string
- type Options
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 = "github.com/jmrplens/gitlab-mcp-server/v3/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.
It is written out whole rather than joined onto ModulePath, because the mutation tool cannot see a package-level declaration and reads the plus of a joined one as never covered, a mutant no test can kill since a string minus a string does not compile. TestToolutilPath_UnderTheModulePath_MovesWithIt holds it to ModulePath, so a module move still has one place to land.
Variables ¶
This section is empty.
Functions ¶
func FilesImporting ¶ added in v3.4.0
FilesImporting returns, in the order given, the files among paths that import importPath under any name, and the ones that cannot be read at all.
It is how a gate says what a load hid from it. A file a build constraint left out holds source the gate never judged, and a gate that said nothing about it would be clean over source it never read; but most such files hold nothing the gate looks for, and naming every one would bury the few that matter. Only the imports are read, which is all the question needs: whether the hidden file could hold what the gate would judge. A file that cannot be read is kept, since nothing can be said about what it holds. A file the overlay supplies is read from the overlay, as the load itself read it.
func IgnoredGoFiles ¶ added in v3.4.0
IgnoredGoFiles returns the Go files a load left out of a package, which is what a build constraint the load did not satisfy looks like from the platform and the tags it was made under. A file that is not Go, such as an assembly file a constraint left out beside them, is not part of the answer.
The slice is the caller's own, so a gate may narrow it in place without touching the package the loader returned.
func IsTestMain ¶ added in v3.4.0
IsTestMain reports whether a loaded package is the test executable the go tool synthesizes for a package under test, "q.test", which is neither source of this repository nor a name a second load can be asked for. Its one generated file is nobody's source, so a gate passes over it.
The path alone does not answer it. A directory may be named "foo.test", and the package in it then carries a path ending exactly as the synthesized executable does while being source somebody wrote; passing over it would drop everything it declares and report the package clean. So the path is only believed when the loader also produced a test variant for the package the suffix claims this was built for, which is a fact about the load rather than a guess about a name. PackagesUnderTest collects those, and LoadMode carries NeedForTest so a load that asks for tests has them.
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.
func LoadRooted ¶ added in v3.4.0
LoadRooted is LoadWith for a gate that names what it finds below the root it loads: it returns that root made absolute beside the packages.
The root is made absolute before anything is loaded, so a run whose working directory is gone stops on that error instead of naming files against wherever the process happens to be. The error is the one filepath.Abs gave, unwrapped, since it already says what could not be resolved.
func LoadWith ¶ added in v3.1.0
LoadWith is Load with the options a caller states: test variants, build tags, an overlay. Everything Load refuses, this refuses on the same terms.
func PackagesUnderTest ¶ added in v3.4.0
PackagesUnderTest collects, from one load, the import paths the loader says a test executable was built for. `go list` reports a test variant as "p [q.test]" and fills packages.Package.ForTest with q for it; the executable itself arrives as plain "q.test" with ForTest empty, so the variants are where the name of the package under test can be read.
func RelativePath ¶ added in v3.4.0
RelativePath renders a file below the repository root, so a finding reads the same wherever the audit was run from. A file the root does not contain is named in full rather than climbed to, and so is one that cannot be made relative to the root at all, because one of the two is relative and the other is not; either way the separators are slashes. A climb is a ".." path element, so a file below the root whose first directory merely begins with two dots is still named relative to it.
func TrimModulePath ¶ added in v3.4.0
TrimModulePath names a package the way the repository does: its import path with ModulePath taken off, so a report says internal/oauth, and a package of any other module keeps its path whole. The module path is matched as a whole path element, so a module whose path merely begins with the same characters is another module rather than a package of this one.
func VariantName ¶ added in v3.4.0
VariantName is a package's import path with the test-variant decoration the loader adds taken off, so "p" and "p [p.test]" are one package. The suffix is decoration on the path rather than part of it, and the external test package keeps its own "_test" name because it really is a different package.
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 loads that are not of this repository: reading the
// GraphQL documents client-go builds (cmd/internal/graphqldocs) and pairing
// them with the structs client-go decodes them into (cmd/audit_graphql_shapes
// -sdk) each mean 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 states
// them, in cmd/internal/graphqldocs (ForeignModuleEnv), 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.