Documentation
¶
Overview ¶
Package templates provides Go template definitions and data structures used by the generator to produce CLI command scaffolding, registration code (cmd.go), and implementation stubs (main.go). Template data types like CommandData carry the resolved configuration for each generated command.
Index ¶
- Constants
- Variables
- func CommandConfigValidation(data CommandData) string
- func CommandExecution(data CommandData) string
- func CommandInitializer(data CommandData) *jen.File
- func CommandRegistration(data CommandData) *jen.File
- func ConfigLayerConstName(name string) string
- func ExternalArgExpr(token string) jen.Code
- func IsExternalArgToken(tok string) bool
- func SkeletonExternalAdapter() string
- func SkeletonInternalVersion(modulePath string) *jen.File
- func SkeletonKeychain() *jen.File
- func SkeletonMain(modulePath string) *jen.File
- func SkeletonRoot(data SkeletonRootData) *jen.File
- func SkeletonSigning(data SkeletonSigningData) *jen.File
- func SkeletonTrustKeys() *jen.File
- type CommandData
- type CommandFlag
- type FeatureDescriptor
- type SkeletonExternalCommand
- type SkeletonRootData
- type SkeletonSigningData
- type SkeletonSubcommand
Constants ¶
const SkeletonConfig = `` /* 625-byte string literal not displayed */
const SkeletonGoMod = `` /* 286-byte string literal not displayed */
Variables ¶
var ExternalArgTokens = []string{"logger", "props", "config", "fs", "version"}
ExternalArgTokens is the closed injection vocabulary for the declarative external-command channel. Each token names a well-known dependency the generator can derive from the *props.Props value (p) when rendering an external constructor call onto the generated root.
The set is deliberately CLOSED (see https://gitlab.com/phpboyscout/go-tool-base/-/wikis/specs/0182-external-command-attachment): keeping it a fixed vocabulary — rather than a free-form Go expression — keeps the generated root type-safe and reviewable and prevents the manifest from becoming an arbitrary-code injection vector. Anything the vocabulary cannot express uses the adapter channel instead.
It is the SINGLE source of truth for the valid token set: the manifest validator (generator.validateExternalAttach) checks membership against it, and ExternalArgExpr renders each token, so the two sides cannot drift.
var FeatureCatalogue = []FeatureDescriptor{ {props.UpdateCmd, props.PackagePath, "UpdateCmd", true}, {props.InitCmd, props.PackagePath, "InitCmd", true}, {props.McpCmd, props.PackagePath, "McpCmd", true}, {props.DocsCmd, props.PackagePath, "DocsCmd", true}, {props.DoctorCmd, props.PackagePath, "DoctorCmd", true}, {props.ChangelogCmd, props.PackagePath, "ChangelogCmd", true}, {props.AiCmd, props.PackagePath, "AiCmd", false}, {props.ConfigCmd, props.PackagePath, "ConfigCmd", false}, {props.TelemetryCmd, props.PackagePath, "TelemetryCmd", false}, {props.ManCmd, props.PackagePath, "ManCmd", false}, {forge.GithubFeature, forge.PackagePath, "GithubFeature", false}, {forge.GitlabFeature, forge.PackagePath, "GitlabFeature", false}, {forge.GiteaFeature, forge.PackagePath, "GiteaFeature", false}, {forge.CodebergFeature, forge.PackagePath, "CodebergFeature", false}, {forge.BitbucketFeature, forge.PackagePath, "BitbucketFeature", false}, }
FeatureCatalogue is the ordered, canonical name<->constant<->default table for every scaffoldable props.FeatureID feature. It is generator-internal tooling (not public API): the SetFeatures renderer and the manifest scanner both derive from it, so the mapping has a single origin and the two sides cannot drift. The historical bug it fixes: the scanner froze at the original four features while the set grew. A test guards this list against the props registry so a new framework feature cannot silently omit its generator handling.
The table is written out rather than derived from the props registry, and it duplicates data props.FeatureDescriptor already carries — the guard test asserts the two agree field by field. That is a known cost, not a claim the duplication is free. Deriving it needs three things this package does not do yet:
- Lazy evaluation. props.FeatureDescriptors seals the registry on read, so computing this at package init would make any later RegisterFeature panic with ErrRegistrySealed.
- A Kind filter. The registry answers what this binary linked; the generator needs the complete set a scaffolded tool may select, and a downstream tool's own registrations are not GTB's to scaffold.
- Somewhere for keychain, which has no FeatureID to derive from.
Note the ordering argument does NOT hold: FeatureDescriptors guarantees a stable total order derived from data, and names this generator's golden files as the reason it does. Whether the duplication is worth collapsing is being settled separately — see go-tool-base#11, which asks whether feature management belongs in a module of its own rather than split between props and the generator.
keychain is intentionally absent: it has no FeatureID and is a build-time blank-import decision, recovered from its artefact rather than SetFeatures.
Functions ¶
func CommandConfigValidation ¶
func CommandConfigValidation(data CommandData) string
CommandConfigValidation generates the content for a config.go file containing a Config struct stub and a ValidateConfig function for per-package schema validation.
func CommandExecution ¶
func CommandExecution(data CommandData) string
func CommandInitializer ¶
func CommandInitializer(data CommandData) *jen.File
func CommandRegistration ¶
func CommandRegistration(data CommandData) *jen.File
func ConfigLayerConstName ¶
ConfigLayerConstName maps a manifest layer name to its exported props constant. Exported so the mapping can be asserted directly rather than only through rendered output.
func ExternalArgExpr ¶
ExternalArgExpr renders one injection token to the Go expression, derived from the props value p, that is passed to an external constructor. It is the render counterpart of ExternalArgTokens; an unknown token (which the manifest validator rejects before render) falls back to p so the render can never panic. The token set here and in ExternalArgTokens must stay in lockstep — guarded by a test.
func IsExternalArgToken ¶
IsExternalArgToken reports whether tok is a member of the closed vocabulary.
func SkeletonExternalAdapter ¶
func SkeletonExternalAdapter() string
SkeletonExternalAdapter returns the source of the external-command adapter escape hatch (pkg/cmd/external/attach.go). Unlike most generated files this is author-owned: gtb scaffolds it once and never overwrites it (it is preserved across regenerate), so the author can attach external command trees of any shape the declarative vocabulary cannot express. The generated root spreads external.Commands(p) into NewCmdRoot, so returned commands still pick up the framework middleware pipeline.
func SkeletonInternalVersion ¶
SkeletonInternalVersion generates the internal/version/version.go file for scaffolded projects, mirroring gtb's own internal/version pattern.
func SkeletonKeychain ¶
SkeletonKeychain generates cmd/<name>/keychain.go for scaffolded projects, blank-importing pkg/credentials/keychain so the tool activates OS keychain support by default. Deleting this single file produces a regulated-build variant with no IPC-to-keychain code linked — verifiable via SBOM against the linked artefact.
Skipped when the "keychain" feature is opted out during `gtb generate` (--features=...without keychain, or the interactive multi-select).
func SkeletonMain ¶
SkeletonMain generates the cmd/<name>/main.go for scaffolded projects. It uses the internal/version package to retrieve version info and passes it to the root command constructor. Execution is delegated to gtbRoot.Execute, which runs the command tree with a signal-aware context: SIGINT/SIGTERM cancel cmd.Context() for graceful shutdown, a second signal force-exits, and a signal-terminated run exits 128+signum.
func SkeletonRoot ¶
func SkeletonRoot(data SkeletonRootData) *jen.File
func SkeletonSigning ¶
func SkeletonSigning(data SkeletonSigningData) *jen.File
SkeletonSigning generates pkg/cmd/root/signing.go for scaffolded projects with signing enabled. It mirrors go-tool-base's own internal/cmd/root/signing.go split: an init() that sets the pkg/setup enforcement defaults, kept in a sibling file to the templated root command. The values come from the manifest signing block rather than being hand-written, so the author tunes posture via `gtb enable signing` flags, not by editing generated code.
Only non-default values are emitted, so a freshly enabled project (no email, require_signature off, default key source) produces an init() that does nothing until the author configures a posture.
func SkeletonTrustKeys ¶
SkeletonTrustKeys generates internal/trustkeys/trustkeys.go for scaffolded projects with signing enabled. It mirrors go-tool-base's own internal/trustkeys/trustkeys.go: a //go:embed of the keys directory plus a Keys() [][]byte accessor that walks keys/*.asc.
The package is generated and regeneration-protected; the author adds their minted release public key(s) as files under keys/, never by editing this .go. With no keys present Keys returns nil, so signature verification stays dormant until a real key is dropped in.
Types ¶
type CommandData ¶
type CommandData struct {
Package string
PascalName string
Name string
Aliases []string
Args string
Short string
Long string
Hidden bool
WithAssets bool
Flags []CommandFlag
PersistentFlags []CommandFlag
AncestralPersistentFlags []CommandFlag
MutuallyExclusive [][]string
RequiredTogether [][]string
Logic string
Imports []string
FullFileContent string
TestCode string
Recommendations []string
PersistentPreRun bool
PreRun bool
HasSubcommands bool
// PureGroup marks a command that only groups its subcommands and so has no
// run logic of its own — see Generator.pureGroup for how it is decided.
// Such a command gets no Run<Name>, and its RunE is the framework's.
PureGroup bool
WithInitializer bool
WithConfigValidation bool
Hashes map[string]string
// MCPExposure controls whether the generated command stamps a
// setup.ExcludeFromMCP / setup.IncludeInMCP marker. The zero value
// (Inherit) emits nothing.
MCPExposure setup.MCPExposure
}
type CommandFlag ¶
type FeatureDescriptor ¶
type FeatureDescriptor struct {
// Cmd is the feature's props.FeatureID; its string value is the
// config/manifest name (e.g. "ai").
Cmd props.FeatureID
// ConstPackage is the import path of the package declaring ConstName.
// Built-ins live in props; forge features live in pkg/setup/forge. The
// emitter qualifies against this rather than assuming props, which is what
// previously made forge features unemittable.
ConstPackage string
// ConstName is the exported Go identifier of the constant as it appears in
// generated source, e.g. "AiCmd". It cannot be derived reliably from the
// value (mcp -> McpCmd), so it is recorded explicitly.
ConstName string
// Default is the framework default-enabled state, mirroring
// props.DefaultFeatures. Forge features are never default-enabled: a blank
// import changes what is available, never what is on.
Default bool
}
FeatureDescriptor carries the four facts the generator needs to round-trip a feature between its config/manifest name, the Go source token that names its props FeatureID constant, the package that declares that constant, and its default-enabled state.
type SkeletonExternalCommand ¶
type SkeletonExternalCommand struct {
ImportPath string // e.g. "gitlab.com/phpboyscout/go/signing-cli"
PkgAlias string // e.g. "signingcli"
Constructor string // e.g. "NewCmdSign"
Args []string // injection tokens, e.g. ["logger"]
Wrap bool // wrap in setup.Wrap("", …)
}
SkeletonExternalCommand describes one external constructor (the declarative attachment channel) to render as an argument to NewCmdRoot. Args are injection tokens from the closed vocabulary (ExternalArgTokens); the template resolves each via ExternalArgExpr. When Wrap is true the constructor returns *cobra.Command and is wrapped in setup.Wrap("", …); otherwise it returns *setup.Command and is attached directly. Declarative attachments are un-gated, so the wrap label is always the empty string.
type SkeletonRootData ¶
type SkeletonRootData struct {
Name string
Description string
ReleaseProvider string
Host string
Org string
RepoName string
Private bool
DisabledFeatures []string
EnabledFeatures []string
HelpType string // "slack", "teams", or ""
SlackChannel string
SlackTeam string
TeamsChannel string
TeamsTeam string
TelemetryEndpoint string
TelemetryOTelEndpoint string
EnvPrefix string
// ConfigLayers wires props.Tool.ConfigLayers in the generated root. Empty
// means the project states nothing and inherits the framework default, so
// no field is emitted — keeping generated output byte-identical for every
// project that does not care.
ConfigLayers []string
// UpdatePolicy wires props.Tool.UpdatePolicy in the generated root. Empty
// (or "disabled") leaves the field off so the framework default applies;
// "prompt"/"enabled" emit the matching props.UpdatePolicy* constant.
UpdatePolicy string
// UpdateCheckInterval wires props.Tool.UpdateCheckInterval as a Go duration
// string (e.g. "24h"). Empty, unparseable, or non-positive values leave the
// field off so the framework default (24h) applies.
UpdateCheckInterval string
// SigningEnabled gates the Signing: props.SigningConfig{...} block.
// When true the generated tool wires trustkeys.Keys() as its embedded
// trust anchor; ModulePath supplies the import path for that package.
SigningEnabled bool
ModulePath string
// AutoInitialise wires props.Tool.Bootstrap.AutoInitialise. When true the
// generated tool auto-runs a non-interactive init if config is missing.
AutoInitialise bool
// SkipConfigCheck wires props.Tool.Bootstrap.SkipConfigCheck — commands
// (by Name() or full CommandPath()) whose missing-config gate is relaxed.
SkipConfigCheck []string
Subcommands []SkeletonSubcommand
// ExternalCommands are declarative external-module attachments rendered as
// additional NewCmdRoot arguments (see the external-command-attachment spec).
ExternalCommands []SkeletonExternalCommand
// ExternalAdapter, when true, spreads external.Commands(p) — the user-owned
// adapter escape hatch at <ModulePath>/pkg/cmd/external — into NewCmdRoot.
ExternalAdapter bool
}
type SkeletonSigningData ¶
type SkeletonSigningData struct {
ExternalKeyEmail string
RequireSignature bool
KeySource string // "embedded" | "external" | "both"; empty → framework default
RequireExternalCrosscheck bool
}
SkeletonSigningData carries the manifest signing posture into the generated signing.go enforcement defaults.
type SkeletonSubcommand ¶
type SkeletonSubcommand struct {
ImportPath string // e.g. "github.com/org/repo/pkg/cmd/serve"
PkgAlias string // e.g. "serve"
Constructor string // e.g. "NewCmdServe"
}
SkeletonSubcommand describes a top-level command that must be registered in the generated NewCmdRoot function.