On this page
Toolchain-backed Go project introspection via ``go list``, classifying projects as library or binary and resolving module paths and import dependencies.
#rlsbl.go_introspect
#rlsbl.go_introspect
Toolchain-backed Go project introspection via go list, classifying projects as library or binary and resolving module paths and import dependencies.
Single source of truth for project-level Go classification (library vs binary, entry-point location). Hand-rolled main.go globbing misdetects real layouts: entry files not named main.go (cmd/x/cli.go), _test.go files in package main dirs, and broken-root layouts (a root package main file with no func main next to a real main under cmd/). The go toolchain handles all of these correctly, so it is the source of truth -- callers must never fall back to file scanning.
#GoIntrospectError
Go project introspection failed (missing toolchain, missing go.mod, go list failure, or an unresolvable main-package layout).
#GoPackage
A Go package as reported by go list.
#list_packages
def list_packages(project_dir: str) -> list[GoPackage]Enumerate all packages in the Go module rooted at project_dir.
Runs go list -e -f ... ./.... The -e flag reports packages even when their imports don't resolve (no network or go.sum needed); error pseudo-packages (empty package name) are skipped.
Raises GoIntrospectError if the go binary is missing, project_dir has no go.mod, or go list fails. Never silently returns an empty list for those conditions -- callers decide fatality.
#list_main_packages
def list_main_packages(project_dir: str) -> list[GoPackage]Enumerate package main packages (binaries) in a project.
#_pipeline_entries
def _pipeline_entries(config: dict) -> dictThe config's pipelines map, or {} when it declares none.
A pipelines value that is present but not a map is a config error, not something to iterate: "pipelines": "none" is truthy, and .values() on it raised an AttributeError that named no config key. load_pipelines owns the diagnosis, so this defers to it rather than restating the message.
#go_pipeline_artifact
def go_pipeline_artifact(config: dict) -> str | NoneReturn the artifact declared on the config's go-type pipeline.
None when the config declares no go pipeline, or the pipeline carries no artifact key (only possible before the key is written -- it is mandatory once validated). The declared value is authoritative everywhere: it decides the publish template AND what scaffold writes, so detection never overrides it.
#go_pipeline_install_paths
def go_pipeline_install_paths(config: dict) -> list[str] | NoneRead install_paths declared on the go-type pipeline entry.
Returns the declared list, or None when no go pipeline declares one. Raises GoIntrospectError if the declaration is not a non-empty list of strings.
#_normalize_rel
def _normalize_rel(path: str) -> strNormalize a declared install path to the helper's rel_dir form.
#validate_install_paths
def validate_install_paths(project_dir: str, paths: list[str]) -> list[str]Validate that every declared install path is a main package.
Returns the normalized paths. Raises GoIntrospectError naming the offending path and listing what go list actually detected.
#describe_main_packages
def describe_main_packages(mains: list[GoPackage]) -> strHuman-readable summary of detected main packages for error messages.
#resolve_main_package_dir
def resolve_main_package_dir(project_dir: str, config: dict) -> strResolve THE main package dir for single-binary concerns (goreleaser main:, version.go placement).
Resolution order:
install_pathsdeclared on the go pipeline: must contain exactly
one path, which must be a main package.
- No declaration: exactly one detected main package is used.
Anything else (zero mains, multiple mains without a declaration, multiple declared paths) is a hard error listing what go list detected, so fixing the config is a copy-paste.