Documentation
¶
Overview ¶
Package props defines the Props dependency container, the central type-safe dependency injection mechanism used throughout GTB.
Props is a concrete struct that aggregates tool metadata, logger, configuration, filesystem (afero.Fs), embedded assets, version info, and error handler into a single value threaded through commands and services. It replaces context.Context-based DI with compile-time type safety.
The package also provides the feature flag system via SetFeatures, Enable, and Disable functional options, controlling which built-in commands (update, init, docs, mcp) are registered at startup. Tool release source metadata for GitHub and GitLab backends is managed through ReleaseSource.
Index ¶
- Constants
- Variables
- func ConfigFileSources(snap *config.Snapshot) []string
- func SlogLogger(p *Props) *slog.Logger
- func ViewOrNil(p *Props) config.Reader
- type AssetMap
- type AssetProvider
- type Assets
- type BootstrapPolicy
- type ConfigFSProvider
- type ConfigProvider
- type ConfigReader
- type CoreProvider
- type DeliveryMode
- type ErrorHandlerProvider
- type EventType
- type Feature
- type FeatureCmd
- type FeatureState
- type FileSystemProvider
- type LoggerProvider
- type LoggingConfigProvider
- type NoopCollector
- func (NoopCollector) BackendInfo() string
- func (NoopCollector) Close(context.Context) error
- func (NoopCollector) Drop() error
- func (NoopCollector) Enabled() bool
- func (NoopCollector) Flush(context.Context) error
- func (NoopCollector) Track(EventType, string, map[string]string)
- func (NoopCollector) TrackCommand(string, int64, int, map[string]string)
- func (NoopCollector) TrackCommandExtended(string, []string, int64, int, string, map[string]string)
- type Props
- func (p *Props) GetAssets() Assets
- func (p *Props) GetCollector() TelemetryCollector
- func (p *Props) GetConfig() *config.Store
- func (p *Props) GetConfigFS() config.FS
- func (p *Props) GetConfigView() *config.View
- func (p *Props) GetErrorHandler() errorhandling.ErrorHandler
- func (p *Props) GetFS() afero.Fs
- func (p *Props) GetLogger() logger.Logger
- func (p *Props) GetTool() Tool
- func (p *Props) GetVersion() version.Version
- type ReleaseSource
- type SigningConfig
- type SlackHelp
- type TeamsHelp
- type TelemetryCollector
- type TelemetryConfig
- type TelemetryProvider
- type Tool
- type ToolMetadataProvider
- type UpdatePolicy
- type VersionProvider
Examples ¶
Constants ¶
const ( EventCommandInvocation = telemetrytypes.EventCommandInvocation EventCommandError = telemetrytypes.EventCommandError EventFeatureUsed = telemetrytypes.EventFeatureUsed EventUpdateCheck = telemetrytypes.EventUpdateCheck EventUpdateApplied = telemetrytypes.EventUpdateApplied EventDeletionRequest = telemetrytypes.EventDeletionRequest )
const ( // DeliveryAtLeastOnce deletes spill files after successful send. // Possible duplicates if the ack is lost; no data loss. DeliveryAtLeastOnce = telemetrytypes.DeliveryAtLeastOnce // DeliveryAtMostOnce deletes spill files before sending. // Possible data loss; no duplicates. DeliveryAtMostOnce = telemetrytypes.DeliveryAtMostOnce )
const ( UpdateCmd = FeatureCmd("update") InitCmd = FeatureCmd("init") McpCmd = FeatureCmd("mcp") DocsCmd = FeatureCmd("docs") AiCmd = FeatureCmd("ai") DoctorCmd = FeatureCmd("doctor") ConfigCmd = FeatureCmd("config") ChangelogCmd = FeatureCmd("changelog") ManCmd = FeatureCmd("man") )
const FrameworkBundle = "framework"
FrameworkBundle is the name under which the framework's baseline asset bundle (log defaults, the framework init template) registers.
const TelemetryCmd = FeatureCmd("telemetry")
TelemetryCmd is the feature flag for the telemetry command group. Default disabled — tool authors must explicitly enable it.
Variables ¶
var AllFeatures = []FeatureCmd{ UpdateCmd, InitCmd, McpCmd, DocsCmd, AiCmd, DoctorCmd, ConfigCmd, ChangelogCmd, ManCmd, TelemetryCmd, }
AllFeatures is the canonical, ordered enumeration of every built-in feature flag. It is the single source of truth for "the full feature matrix" — e.g. the doctor report bundle ranges over it via IsEnabled. Keep it in sync with the FeatureCmd const block above (and TelemetryCmd from telemetry.go).
var DefaultFeatures = []FeatureState{ Enable(UpdateCmd), Enable(InitCmd), Enable(McpCmd), Enable(DocsCmd), Enable(DoctorCmd), Enable(ChangelogCmd), }
DefaultFeatures is the list of features enabled by default.
Functions ¶
func ConfigFileSources ¶ added in v0.32.0
ConfigFileSources returns the paths of the loaded file layers in snapshot precedence order, deduplicating multi-document entries. The last element is the highest-precedence loaded file — the same answer Viper's ConfigFileUsed() gave (it reported the last file it loaded), which several consumers (doctor's report, telemetry's data dir, the config command's writable-target resolution) depend on for parity.
func SlogLogger ¶ added in v0.32.0
SlogLogger adapts p's logger to a *slog.Logger, falling back to a discarding logger when p is nil. The config adapters in pkg/chat and pkg/telemetry both need a slog handle from possibly-nil Props; hosting the conversion here keeps them from carrying identical copies (compare ViewOrNil).
func ViewOrNil ¶ added in v0.32.0
ViewOrNil pins a view of p's store, or returns a true-nil Reader when p or its store is absent. The nil handling is the point: returning a typed (*config.View)(nil) would box a nil pointer into a non-nil interface and silently defeat the cfg == nil guards the read adapters rely on.
Types ¶
type AssetProvider ¶
type AssetProvider interface {
GetAssets() Assets
}
AssetProvider provides access to embedded assets.
type Assets ¶
type Assets interface {
fs.FS
fs.ReadDirFS
fs.GlobFS
fs.StatFS
Slice() []fs.FS
Names() []string
Get(name string) fs.FS
Register(name string, fs fs.FS)
For(names ...string) Assets
Merge(others ...Assets) Assets
Exists(name string) (fs.FS, error)
Mount(f fs.FS, prefix string)
}
Assets is an interface that wraps a map of fs.FS pointers and implements the standard fs interfaces.
type BootstrapPolicy ¶ added in v0.29.0
type BootstrapPolicy struct {
// AutoInitialise, when true and the init feature is enabled, runs a
// non-interactive init (writing the default config) instead of failing when
// no config file is found, then continues with the freshly written config.
AutoInitialise bool `json:"auto_initialise,omitempty" yaml:"auto_initialise,omitempty"`
// SkipConfigCheck lists commands whose missing-config hard-fail is relaxed
// to a tolerant load: the pre-run falls back to the embedded default config
// rather than erroring, so the command's own PreRunE can manage bootstrap.
// An entry matches a command when it equals either the command's Name() or
// its full CommandPath() (e.g. "studio" or "krites studio") — the latter
// disambiguates same-named commands at different tree levels. A command may
// also be marked via the setup.SkipConfigCheck annotation; either mechanism
// relaxes the check.
SkipConfigCheck []string `json:"skip_config_check,omitempty" yaml:"skip_config_check,omitempty"`
// AuxiliaryCommands lists commands that take the root pre-run's auxiliary
// fast path: the framework bootstrap — config load, telemetry consent,
// collector wiring, update check — is skipped entirely (only the --debug
// flag is still honoured for logging). Cobra's own generated help,
// completion and __complete commands take this path automatically; the
// list lets a downstream tool extend the set (e.g. for its own
// bootstrap-free plumbing commands) without a framework release.
//
// This is stronger than SkipConfigCheck: an auxiliary command runs with
// props.Config left nil, so it must read nothing from configuration.
// Entries match a command's Name() or full CommandPath(), the same
// semantics as SkipConfigCheck.
AuxiliaryCommands []string `json:"auxiliary_commands,omitempty" yaml:"auxiliary_commands,omitempty"`
}
BootstrapPolicy governs how the framework treats configuration bootstrap and the missing-config gate in the root pre-run. The zero value reproduces the historical behaviour: a missing config file is a hard error when the init feature is enabled.
Neither knob skips the framework bootstrap itself (config load, telemetry, update check) — they only relax the missing-config *outcome*, preserving the "bootstrap always runs" invariant established by the 2026-06-12-bootstrap-prerun-traversal spec.
func (BootstrapPolicy) MatchesAuxiliaryList ¶ added in v0.33.0
func (b BootstrapPolicy) MatchesAuxiliaryList(name, path string) bool
MatchesAuxiliaryList reports whether a command identified by name and path is listed in AuxiliaryCommands, using the same Name()/CommandPath() equality semantics as MatchesSkipList.
func (BootstrapPolicy) MatchesSkipList ¶ added in v0.29.0
func (b BootstrapPolicy) MatchesSkipList(name, path string) bool
MatchesSkipList reports whether a command identified by name and path is listed in SkipConfigCheck. An entry may be a bare Name() or a full CommandPath(); either equality relaxes the missing-config check. Empty entries never match. The annotation half (setup.SkipConfigCheck) is evaluated separately by the root pre-run to avoid a props->setup import cycle.
type ConfigFSProvider ¶ added in v0.32.0
ConfigFSProvider adapts the application filesystem for the configuration store, bridging afero to the narrower interface config defines.
type ConfigProvider ¶
ConfigProvider provides access to the live configuration store.
Take this when you need to write configuration, observe changes, or hold a reference across a reload. Code that only reads should take ConfigReader instead, which cannot do any of those things and says so in its signature.
type ConfigReader ¶ added in v0.32.0
ConfigReader provides read access to resolved configuration.
A view is pinned to one snapshot, so every value read through it comes from the same resolved configuration — reads cannot straddle a reload. Call it per logical operation rather than holding the result: a view kept across a reload keeps serving the values it was pinned to.
type CoreProvider ¶
type CoreProvider interface {
LoggerProvider
ConfigProvider
FileSystemProvider
}
CoreProvider provides the three most commonly needed capabilities.
type DeliveryMode ¶
type DeliveryMode = telemetrytypes.DeliveryMode
DeliveryMode controls the delivery guarantee for telemetry events. It is an alias for telemetrytypes.DeliveryMode; see EventType for why the canonical type lives in the leaf package.
type ErrorHandlerProvider ¶
type ErrorHandlerProvider interface {
GetErrorHandler() errorhandling.ErrorHandler
}
ErrorHandlerProvider provides access to the error handler.
type EventType ¶
type EventType = telemetrytypes.EventType
EventType identifies the category of telemetry event. It is an alias for telemetrytypes.EventType — the canonical type lives in the dependency-free pkg/telemetrytypes leaf so that pkg/telemetry can share it without importing pkg/props. Re-exported here (with the constants below) so commands can reference event types through props without importing pkg/telemetry.
type Feature ¶
type Feature struct {
Cmd FeatureCmd `json:"cmd" yaml:"cmd"`
Enabled bool `json:"enabled" yaml:"enabled"`
}
Feature represents the state of a feature (Enabled/Disabled).
func SetFeatures ¶
func SetFeatures(mutators ...FeatureState) []Feature
SetFeatures applies a series of mutators to the standard default set.
Example ¶
package main
import (
"fmt"
"gitlab.com/phpboyscout/go-tool-base/pkg/props"
)
func main() {
features := props.SetFeatures(
props.Disable(props.InitCmd),
props.Enable(props.AiCmd),
props.Enable(props.TelemetryCmd),
)
for _, f := range features {
if f.Enabled {
fmt.Println("enabled:", f.Cmd)
}
}
}
Output:
type FeatureCmd ¶
type FeatureCmd string
FeatureCmd identifies a built-in feature that can be enabled or disabled.
type FeatureState ¶
FeatureState is a functional option that mutates the list of features.
func Disable ¶
func Disable(cmd FeatureCmd) FeatureState
Disable returns a FeatureState that disables the given command.
func Enable ¶
func Enable(cmd FeatureCmd) FeatureState
Enable returns a FeatureState that enables the given command.
type FileSystemProvider ¶
FileSystemProvider provides access to the application filesystem.
type LoggerProvider ¶
LoggerProvider provides access to the application logger.
type LoggingConfigProvider ¶
type LoggingConfigProvider interface {
LoggerProvider
ConfigProvider
}
LoggingConfigProvider is the most common combination — logging and configuration.
type NoopCollector ¶ added in v0.17.0
type NoopCollector struct{}
NoopCollector is a zero-behaviour TelemetryCollector. It is the default value of Props.Collector so the "always non-nil" invariant holds even before the root bootstrap resolves the real collector (e.g. on the init and help paths) and for Props constructed directly as a struct literal (tests, cmd/e2e).
The concrete *telemetry.Collector from pkg/telemetry supersedes it once the root PersistentPreRunE runs; NoopCollector reports Enabled() == false so the telemetry flush is correctly skipped while it is in place.
func (NoopCollector) BackendInfo ¶ added in v0.17.0
func (NoopCollector) BackendInfo() string
BackendInfo reports the disabled noop backend.
func (NoopCollector) Close ¶ added in v0.17.0
func (NoopCollector) Close(context.Context) error
Close is a no-op and never errors.
func (NoopCollector) Drop ¶ added in v0.17.0
func (NoopCollector) Drop() error
Drop is a no-op and never errors.
func (NoopCollector) Enabled ¶ added in v0.17.0
func (NoopCollector) Enabled() bool
Enabled always reports false: a noop collector never actively collects.
func (NoopCollector) Flush ¶ added in v0.17.0
func (NoopCollector) Flush(context.Context) error
Flush is a no-op and never errors.
func (NoopCollector) Track ¶ added in v0.17.0
func (NoopCollector) Track(EventType, string, map[string]string)
Track is a no-op.
func (NoopCollector) TrackCommand ¶ added in v0.17.0
TrackCommand is a no-op.
func (NoopCollector) TrackCommandExtended ¶ added in v0.17.0
TrackCommandExtended is a no-op.
type Props ¶
type Props struct {
Tool Tool
Logger logger.Logger
// Config is the live configuration store. It owns reloads, so it is the
// thing to hold; a *config.View taken from it is pinned to one snapshot and
// goes stale the moment the file changes.
//
// Read through Config.View(), which is the read surface. Where several
// values must agree with each other, use Config.With so they all resolve
// against the same snapshot rather than straddling a reload.
Config *config.Store
Assets Assets
FS afero.Fs
Version version.Version
ErrorHandler errorhandling.ErrorHandler
// Collector is always non-nil once the root command tree is built: the
// bootstrap defaults it to a NoopCollector and later replaces it with the
// resolved *telemetry.Collector. Consumers may call it unconditionally.
Collector TelemetryCollector
}
Props is the primary dependency injection container for GTB applications. When writing functions that accept Props, consider whether a narrow interface (LoggerProvider, ConfigProvider, etc.) would suffice.
func (*Props) GetCollector ¶ added in v0.18.0
func (p *Props) GetCollector() TelemetryCollector
GetCollector returns the telemetry collector. It is always non-nil once the root command tree is built, so consumers may call it unconditionally.
func (*Props) GetConfigFS ¶ added in v0.32.0
GetConfigFS adapts the application filesystem for the config store.
Props.FS stays a full afero.Fs — OsFs live, MemMapFs under test — because that is how the rest of GTB operates. config defines its own narrower interface rather than depending on afero, so the two are bridged here in one place instead of at every construction site.
func (*Props) GetConfigView ¶ added in v0.32.0
GetConfigView returns a read surface pinned to the current snapshot.
Named GetConfigView rather than Config because Props already has a Config field and Go forbids a method sharing its name.
Take one per logical operation and let it go — holding one across a reload silently serves stale values. Reading several related keys from one view is the point: they are guaranteed to come from the same snapshot.
func (*Props) GetErrorHandler ¶
func (p *Props) GetErrorHandler() errorhandling.ErrorHandler
GetErrorHandler returns the error handler.
func (*Props) GetVersion ¶
GetVersion returns the version information.
type ReleaseSource ¶
type ReleaseSource struct {
Type string `json:"type" yaml:"type"`
Host string `json:"host" yaml:"host"`
Owner string `json:"owner" yaml:"owner"`
Repo string `json:"repo" yaml:"repo"`
Private bool `json:"private" yaml:"private"`
// Params holds provider-specific configuration key/value pairs.
// Keys use snake_case. Valid keys are documented per provider.
Params map[string]string `json:"params,omitempty" yaml:"params,omitempty"`
}
ReleaseSource identifies the platform and repository where the tool's releases are published. Used by the self-update system to check for and download new versions. Supported types: "github", "gitlab", "bitbucket", "gitea", "codeberg", "direct".
type SigningConfig ¶ added in v0.12.0
type SigningConfig struct {
// EmbeddedKeys are ASCII-armored public keys baked into the binary,
// typically via //go:embed in an internal trustkeys package. They are
// the embedded trust anchor the SelfUpdater uses to verify the
// signature over checksums.txt. Not serialised — keys are compile-time
// build artefacts, never runtime config.
EmbeddedKeys [][]byte `json:"-" yaml:"-"`
// RequireChecksum is the tool author's baseline for checksum enforcement,
// consulted when neither config nor environment supplies one. It is a
// pointer so "unset" is distinguishable from "explicitly false": nil
// leaves the framework default (permissive), and a tool wanting
// fail-closed verification from day one sets it true.
//
// It lives here, beside the other tool-author baselines, rather than as a
// package variable in pkg/setup. The framework constructs the updater, so
// a tool cannot pass an option to it — but it does own its Props, and
// process-wide mutable state is not a configuration mechanism. Runtime
// config (`update.require_checksum`) still overrides it.
RequireChecksum *bool `json:"-" yaml:"-"`
}
SigningConfig holds tool-author configuration for self-update signature verification (Phase 2 of the remote-update-checksum spec). The zero value is safe: with no embedded keys and no external key email configured, signature verification is governed entirely by setup.DefaultRequireSignature (default false) and stays dormant.
type SlackHelp ¶ added in v0.32.0
type SlackHelp struct {
Team string `json:"team" yaml:"team"`
Channel string `json:"channel" yaml:"channel"`
}
SlackHelp provides Slack channel contact details as a support message. It implements the errorhandling.HelpConfig interface, which the go/errorhandling module defines but deliberately ships no implementations for — where a team's support channel lives is a framework/tool concern, not something an error-reporting library should have an opinion about.
Assign it to Tool.Help; the scaffolded root command does this for tools generated with `--help-type slack`.
func (SlackHelp) SupportMessage ¶ added in v0.32.0
SupportMessage renders the Slack contact line, or an empty string when the channel is not fully configured (an empty message suppresses help output).
type TeamsHelp ¶ added in v0.32.0
type TeamsHelp struct {
Team string `json:"team" yaml:"team"`
Channel string `json:"channel" yaml:"channel"`
}
TeamsHelp provides Microsoft Teams channel contact details as a support message. See SlackHelp for the rationale behind these living in GTB rather than in the errorhandling module.
func (TeamsHelp) SupportMessage ¶ added in v0.32.0
SupportMessage renders the Teams contact line, or an empty string when the channel is not fully configured (an empty message suppresses help output).
type TelemetryCollector ¶
type TelemetryCollector interface {
// Track records a telemetry event. No-op when the collector is disabled.
Track(eventType EventType, name string, extra map[string]string)
// TrackCommand records a command invocation with duration and exit code.
TrackCommand(name string, durationMs int64, exitCode int, extra map[string]string)
// TrackCommandExtended records a command invocation with full context including
// arguments and error message. When ExtendedCollection is disabled on the
// collector, args and errMsg are silently dropped — callers do not need to
// check the flag themselves.
TrackCommandExtended(name string, args []string, durationMs int64, exitCode int, errMsg string, extra map[string]string)
// Flush sends all buffered events to the backend and clears the buffer.
// Checks for and sends spill files before flushing the current buffer.
Flush(ctx context.Context) error
// BackendInfo returns a human-readable description of the active backend
// (e.g. "otlp (otlp-gateway-prod-gb-south-1.grafana.net)", "noop", "file").
BackendInfo() string
// Close flushes pending events and shuts down the backend gracefully.
// Must be called on process exit to ensure backends like OTLP flush
// their internal batch queues.
Close(ctx context.Context) error
// Drop clears all buffered events and deletes any spill files without sending.
Drop() error
// Enabled reports whether the collector is actively collecting (as opposed
// to a no-op disabled collector). Reflects the resolved decision from
// config, env override, or tool-author ForceEnabled.
Enabled() bool
}
TelemetryCollector is the interface through which commands emit telemetry events. Defined here (not in pkg/telemetry) to avoid an import cycle. The concrete implementation is *telemetry.Collector from pkg/telemetry. Props.Collector is always non-nil — when telemetry is disabled it is a noop.
type TelemetryConfig ¶
type TelemetryConfig struct {
// Endpoint is the HTTP JSON endpoint to POST events to.
// Ignored when OTelEndpoint is set or when Backend is non-nil.
Endpoint string `json:"endpoint,omitempty" yaml:"endpoint,omitempty"`
// OTelEndpoint is the OTLP/HTTP base URL (e.g. "https://collector:4318").
// Takes precedence over Endpoint when set.
OTelEndpoint string `json:"otel_endpoint,omitempty" yaml:"otel_endpoint,omitempty"`
// OTelHeaders are HTTP headers sent with every OTLP request (e.g. auth tokens).
OTelHeaders map[string]string `json:"otel_headers,omitempty" yaml:"otel_headers,omitempty"`
// OTelInsecure disables TLS for the OTLP endpoint — use only for local collectors.
OTelInsecure bool `json:"otel_insecure,omitempty" yaml:"otel_insecure,omitempty"`
// Backend is an optional factory for a custom telemetry backend.
// Typed as func(*Props) any to avoid importing pkg/telemetry from pkg/props.
// The returned value must implement telemetry.Backend — pkg/cmd/root performs
// the type assertion. Takes precedence over Endpoint and OTelEndpoint when set.
// Not serialisable — set programmatically in tool setup.
Backend func(*Props) any `json:"-" yaml:"-"`
// DeletionRequestor is an optional factory for a custom GDPR deletion requestor.
// Typed as func(*Props) any to avoid importing pkg/telemetry from pkg/props.
// The returned value must implement telemetry.DeletionRequestor — pkg/cmd/root
// performs the type assertion. If nil, falls back to sending a
// data.deletion_request event through the existing backend.
// Not serialisable — set programmatically in tool setup.
DeletionRequestor func(*Props) any `json:"-" yaml:"-"`
// ForceEnabled bypasses the user consent prompt and enables telemetry
// unconditionally. The telemetry enable/disable/reset commands remain
// functional so users can still inspect status, but collection cannot be
// turned off. Intended for enterprise tools deployed in controlled
// environments where telemetry is a contractual requirement.
// When set, the first-run consent prompt is suppressed.
ForceEnabled bool `json:"force_enabled,omitempty" yaml:"force_enabled,omitempty"`
// ExtendedCollection enables collection of command arguments and error messages
// in telemetry events. Default: false. When false, args and errors are never
// recorded regardless of what callers pass to TrackCommandExtended.
//
// Enable this only in closed enterprise environments where users are
// contractually bound by security policies. In public-facing tools, leave
// this disabled to preserve user privacy.
ExtendedCollection bool `json:"extended_collection,omitempty" yaml:"extended_collection,omitempty"`
// DeliveryMode controls the delivery guarantee. Default: DeliveryAtLeastOnce.
DeliveryMode DeliveryMode `json:"delivery_mode,omitempty" yaml:"delivery_mode,omitempty"`
// Metadata is additional key/value pairs included in every event.
// Useful for custom dimensions like environment name or deployment tier.
Metadata map[string]string `json:"metadata,omitempty" yaml:"metadata,omitempty"`
}
TelemetryConfig holds tool-author telemetry declarations. It is embedded in Tool and specifies where and how to send telemetry. The end-user's opt-in state is stored in the config file under telemetry.enabled and telemetry.local_only — endpoints are not user-configurable.
type TelemetryProvider ¶ added in v0.18.0
type TelemetryProvider interface {
GetCollector() TelemetryCollector
}
TelemetryProvider provides access to the telemetry collector.
type Tool ¶
type Tool struct {
Name string `json:"name" yaml:"name"`
Summary string `json:"summary" yaml:"summary"`
Description string `json:"description" yaml:"description"`
Features []Feature `json:"features" yaml:"features"`
Help errorhandling.HelpConfig `json:"-" yaml:"-"`
// Bootstrap groups config-bootstrap lifecycle policy — auto-initialisation
// and per-command relaxation of the missing-config gate. Zero value is
// safe and reproduces historical behaviour. See BootstrapPolicy.
Bootstrap BootstrapPolicy `json:"bootstrap,omitempty" yaml:"bootstrap,omitempty"`
// ReleaseSource is the source of truth for the tool's releases (GitHub or GitLab)
ReleaseSource ReleaseSource `json:"release_source" yaml:"release_source"`
// ReleaseProvider, when non-nil, is the release backend the self-update
// subsystem uses, taking precedence over ReleaseSource.Type registry
// lookup. It is a runtime-only dependency-injection seam — for tests
// (see go/forge/test) and custom/embedded providers — and is
// never serialised. Production tools leave it nil and are resolved from the
// release registry by ReleaseSource.Type as before. An explicit
// setup.WithReleaseProvider option takes precedence over this field.
ReleaseProvider forge.Provider `json:"-" yaml:"-"`
// UpdatePolicy is the tool author's baseline self-update posture
// (disabled / prompt / enabled). The zero value normalises to
// UpdatePolicyDisabled — the framework default — so a tool does not
// force updates out of the box. Overridable at runtime by the
// `update.policy` config key. See ResolveUpdatePolicy.
UpdatePolicy UpdatePolicy `json:"update_policy,omitempty" yaml:"update_policy,omitempty"`
// UpdateCheckInterval is the tool author's baseline throttle between
// self-update checks. The zero value means "use the framework default"
// (setup.DefaultCheckInterval, 24h) — it is NOT interpreted as
// "check every run". Overridable at runtime by the `update.check_interval`
// config key (where "0"/"0s" does mean every run). See
// setup.ResolveCheckInterval.
UpdateCheckInterval time.Duration `json:"update_check_interval,omitempty" yaml:"update_check_interval,omitempty"`
// Telemetry holds tool-author telemetry configuration.
// Zero-value is safe — tools that don't set it are unaffected.
Telemetry TelemetryConfig `json:"telemetry" yaml:"telemetry"`
// Signing holds tool-author self-update signature configuration.
// Zero-value is safe — verification stays dormant until keys and/or
// require_signature are configured.
Signing SigningConfig `json:"-" yaml:"-"`
// EnvPrefix is the environment variable prefix used by the config package.
// When set, only env vars starting with this prefix (e.g., "GTB_") are
// considered for config overrides. Empty means no prefix (all env vars match).
EnvPrefix string `json:"env_prefix,omitempty" yaml:"env_prefix,omitempty"`
// InstallHint is shown when a feature requires a full release binary
// (e.g. embedded docs) that the running binary lacks. Set it to your
// tool's recommended installation command. When empty, a generic
// message referencing Name is shown — the framework never assumes a
// particular installer.
InstallHint string `json:"install_hint,omitempty" yaml:"install_hint,omitempty"`
}
Tool holds metadata about the CLI tool: its identity, feature flags, release source for self-updates, help channel configuration, and telemetry settings. It is embedded in Props and passed to all commands.
func (Tool) GetReleaseSource ¶
GetReleaseSource returns the release source type, owner, and repo.
func (Tool) IsDisabled ¶
func (t Tool) IsDisabled(cmd FeatureCmd) bool
IsDisabled checks if a feature is disabled.
func (Tool) IsEnabled ¶
func (t Tool) IsEnabled(cmd FeatureCmd) bool
IsEnabled checks if a feature is enabled. It checks the Features slice first, falling back to built-in defaults.
Example ¶
package main
import (
"fmt"
"gitlab.com/phpboyscout/go-tool-base/pkg/props"
)
func main() {
tool := props.Tool{
Name: "mytool",
Features: props.SetFeatures(
props.Enable(props.AiCmd),
),
}
fmt.Println("AI:", tool.IsEnabled(props.AiCmd))
fmt.Println("Init:", tool.IsEnabled(props.InitCmd))
}
Output: AI: true Init: true
type ToolMetadataProvider ¶
type ToolMetadataProvider interface {
GetTool() Tool
}
ToolMetadataProvider provides access to tool configuration and metadata.
type UpdatePolicy ¶ added in v0.18.0
type UpdatePolicy string
UpdatePolicy governs how the self-update check behaves when a newer release is found. It is the tool author's baseline (the Tool.UpdatePolicy field), overridable at runtime by the `update.policy` config key. See docs/development/specs/2026-06-16-forced-update-feature.md.
const ( // UpdatePolicyDisabled never auto-updates or prompts: it only logs that an // update is available (and a persistent out-of-date WARN). This is the // framework default (the zero value normalises to it), so a tool built on // GTB does nothing surprising out of the box. UpdatePolicyDisabled UpdatePolicy = "disabled" // UpdatePolicyPrompt asks the user to update when one is available; they may // decline and continue with their command. The GTB CLI itself uses this. UpdatePolicyPrompt UpdatePolicy = "prompt" // UpdatePolicyEnabled blocks every command until the tool is updated when an // update is available (the historical forced-update behaviour, now explicit // and opt-in). UpdatePolicyEnabled UpdatePolicy = "enabled" )
func ResolveUpdatePolicy ¶ added in v0.18.0
func ResolveUpdatePolicy(toolDefault UpdatePolicy, configValue string) UpdatePolicy
ResolveUpdatePolicy computes the effective update policy. A valid `update.policy` config value wins over the tool's baseline; an empty or invalid config value falls back to the baseline; an empty or invalid baseline falls back to the framework default (UpdatePolicyDisabled). Resolution is case-insensitive. `--ci` bypass is handled by the caller and is out of scope here.
func (UpdatePolicy) Normalize ¶ added in v0.18.0
func (p UpdatePolicy) Normalize() UpdatePolicy
Normalize trims, lowercases, and maps the empty policy (the zero value / framework default) to UpdatePolicyDisabled. An unknown non-empty value is returned trimmed/lowercased so UpdatePolicy.Valid can reject it.
func (UpdatePolicy) Valid ¶ added in v0.18.0
func (p UpdatePolicy) Valid() bool
Valid reports whether p is one of the three defined policies. The empty string is NOT valid (it is a sentinel for "unset"); callers wanting the default-applied value use UpdatePolicy.Normalize.
type VersionProvider ¶
VersionProvider provides access to version information.