Documentation
¶
Overview ¶
Package direct provides a forge.Provider implementation for tools distributed via arbitrary HTTP servers. Asset URLs are constructed from typed Settings and configurable templates; version detection is optional and supports plain text, JSON, YAML, and XML endpoints. GTB config integration lives in SettingsFromConfig.
Where this package sits on the connection ladder ¶
Spec 0008's ladder offers a native-client rung (D5), a constructor taking the platform SDK's own client, for the adapters that have one. This package has no platform SDK and no platform: it fetches from arbitrary HTTP servers, so its native unit IS the net/http.Client and a rung taking one would duplicate gitlab.com/phpboyscout/go/forge.WithHTTPClient. That absence is deliberate.
It honours both transport rungs, and honours them more widely than the four provider modules do. Those refuse to use a supplied CLIENT to fetch a release asset, because an asset URL arrives in author-controlled release metadata. Every URL this package fetches is expanded from a template the OPERATOR wrote in their own configuration, so there is no hop a third party chose and a supplied client is used throughout. See connection.go.
Index ¶
- Constants
- Variables
- type DirectReleaseProvider
- func (p *DirectReleaseProvider) DownloadChecksumManifest(ctx context.Context, rel forge.Release, maxBytes int64) ([]byte, error)
- func (p *DirectReleaseProvider) DownloadReleaseAsset(ctx context.Context, _, _ string, asset forge.ReleaseAsset) (io.ReadCloser, string, error)
- func (p *DirectReleaseProvider) DownloadSignature(ctx context.Context, rel forge.Release, maxBytes int64) ([]byte, error)
- func (p *DirectReleaseProvider) GetLatestRelease(ctx context.Context, _, _ string) (forge.Release, error)
- func (p *DirectReleaseProvider) GetReleaseByTag(_ context.Context, _, _, tag string) (forge.Release, error)
- func (p *DirectReleaseProvider) ListReleases(_ context.Context, _, _ string, _ int) ([]forge.Release, error)
- func (p *DirectReleaseProvider) SetToolName(name string)
- type Settings
Constants ¶
const DefaultTokenEnv = "DIRECT_TOKEN"
DefaultTokenEnv is the well-known environment variable the default credential composition consults last. See SettingsFromConfig.
Variables ¶
var ErrVersionUnknown = errors.New(
"cannot determine latest version: configure version_url or pinned_version in the direct configuration subtree",
)
ErrVersionUnknown is returned when neither version_url nor pinned_version is configured and a version check is requested.
It lives here rather than in the shared contract because it is specific to this provider: it names configuration keys (version_url, pinned_version) that mean nothing to a forge-backed provider, which learns its version by asking the API. A sentinel in the shared package implies every provider might return it.
Functions ¶
This section is empty.
Types ¶
type DirectReleaseProvider ¶
type DirectReleaseProvider struct {
// contains filtered or unexported fields
}
DirectReleaseProvider implements forge.Provider for direct HTTP downloads.
func NewReleaseProvider ¶
func NewReleaseProvider(ctx context.Context, settings Settings) (*DirectReleaseProvider, error)
NewReleaseProvider constructs a DirectReleaseProvider from explicit typed settings.
Settings.URLTemplate is required. Everything else is optional: an empty checksum or signature template disables that capability, and an empty version source leaves the latest version unknown unless PinnedVersion supplies it.
The credential comes from Settings.Credential, or — when that is nil — from the default composition in SettingsFromConfig. Direct is the reference implementation, so it takes the same path a third-party provider should.
The context bounds credential resolution: a forge.CredentialSource the caller supplied may reach a keychain or a remote secret store, and this is where that happens. A source that fails while another succeeds is not an error — see forge.FirstCredential.
func (*DirectReleaseProvider) DownloadChecksumManifest ¶
func (p *DirectReleaseProvider) DownloadChecksumManifest(ctx context.Context, rel forge.Release, maxBytes int64) ([]byte, error)
DownloadChecksumManifest implements forge.ChecksumProvider by fetching the checksums manifest from the URL produced by expanding `checksum_url_template` against the release version. Returns forge.ErrNotSupported when `checksum_url_template` is unset, so callers fall back to the default asset-list lookup (which is pointless for Direct but keeps the fallback path consistent across providers).
Size-capping is enforced here against the caller-supplied maxBytes, identically to DownloadSignature — see forge.ChecksumProvider.
func (*DirectReleaseProvider) DownloadReleaseAsset ¶
func (p *DirectReleaseProvider) DownloadReleaseAsset(ctx context.Context, _, _ string, asset forge.ReleaseAsset) (io.ReadCloser, string, error)
DownloadReleaseAsset downloads the asset at its BrowserDownloadURL.
func (*DirectReleaseProvider) DownloadSignature ¶
func (p *DirectReleaseProvider) DownloadSignature(ctx context.Context, rel forge.Release, maxBytes int64) ([]byte, error)
DownloadSignature implements forge.SignatureProvider by fetching the detached signature from the URL produced by expanding `signature_url_template` against the release version. Returns forge.ErrNotSupported when `signature_url_template` is unset, so callers respect the require_signature policy.
Size-capping is enforced here against the caller-supplied maxBytes, identically to DownloadChecksumManifest — see forge.SignatureProvider.
func (*DirectReleaseProvider) GetLatestRelease ¶
func (p *DirectReleaseProvider) GetLatestRelease(ctx context.Context, _, _ string) (forge.Release, error)
GetLatestRelease fetches the latest version from the version endpoint and returns a synthetic forge. Returns ErrVersionUnknown if no version source is configured.
func (*DirectReleaseProvider) GetReleaseByTag ¶
func (p *DirectReleaseProvider) GetReleaseByTag(_ context.Context, _, _, tag string) (forge.Release, error)
GetReleaseByTag constructs a synthetic release for the given tag without any network call.
func (*DirectReleaseProvider) ListReleases ¶
func (p *DirectReleaseProvider) ListReleases(_ context.Context, _, _ string, _ int) ([]forge.Release, error)
ListReleases is not supported for direct HTTP providers.
func (*DirectReleaseProvider) SetToolName ¶
func (p *DirectReleaseProvider) SetToolName(name string)
SetToolName sets the tool name used in URL template expansion. This is called by the setup package when the Props.Tool.Name is available.
type Settings ¶
type Settings struct {
// Endpoint addresses this source. Type is always [forge.SourceTypeDirect];
// Name selects which configured source this is, and scopes the subtree the
// fields below are read from.
//
// Host is unused: a direct source is addressed entirely by its URL template,
// which is why two of them must differ by Name rather than by Host.
Endpoint forge.Endpoint
// URLTemplate composes the download URL. Required.
//
// Placeholders: {version}, {os}, {arch}, {tool}, {ext}.
URLTemplate string
// ChecksumURLTemplate and SignatureURLTemplate compose the URLs of the
// checksums manifest and its detached signature. Empty disables that
// capability, which the caller sees as [forge.ErrNotSupported].
ChecksumURLTemplate string
SignatureURLTemplate string
// VersionURL, VersionFormat and VersionKey describe where the latest version
// is published and how to read it. PinnedVersion short-circuits them.
VersionURL string
VersionFormat string
VersionKey string
PinnedVersion string
// ToolName fills the {tool} placeholder. A caller that names the tool in
// URLTemplate directly needs none.
ToolName string
// HTTPTransport is the transport this provider builds its client on, so
// several providers share one connection pool. Nil means it builds its own.
// Set through the registry with [forge.WithHTTPTransport].
HTTPTransport http.RoundTripper
// HTTPClient replaces the client this provider would have built, redirect
// policy included. Unlike the four provider modules, it IS used for asset
// downloads here, because every URL this package fetches comes from the
// operator's own template rather than from release metadata. See
// connection.go. Set through the registry with [forge.WithHTTPClient].
HTTPClient *http.Client
// Credential yields the token this provider authenticates with.
//
// Nil is not an error: [NewReleaseProvider] composes the default — the
// configured key, then TokenFallbackEnv — so construction from
// configuration alone keeps working. Set it to take over entirely, which
// is also how a caller holding a token already passes one in:
//
// Credential: forge.StaticCredential(token)
Credential forge.CredentialSource
// TokenFallbackEnv names the environment variable consulted last when
// Credential is nil. Empty means no fallback; the registered factory
// supplies [DefaultTokenEnv].
TokenFallbackEnv string
// Logger receives this provider's diagnostics. Nil discards them, and is
// never [slog.Default]. See [forge.WithLogger] for the registry route.
Logger *slog.Logger
// ConfigWarning describes a configuration problem detected while building
// these settings. It is NOT an error: the settings are usable and the
// provider will build. [NewReleaseProvider] logs it at WARN.
//
// [SettingsFromConfig] sets it when the configuration it was handed looks
// like a pre-scoped subtree rather than the root — a mistake that resolves
// no credential and reports nothing, so a diagnostic is the only way a
// caller learns of it. See [forge.PreScopedConfig] and spec 0011.
ConfigWarning error
}
Settings contains the typed configuration needed to construct a Direct release provider without binding the provider to any config container.
The shape deliberately matches every other provider: a release source, a forge.CredentialSource, and the well-known environment variable to fall back to. Direct is this module's reference implementation, so it demonstrates the same credential path a third-party provider should take rather than a shortcut of its own.
func SettingsFromConfig ¶
SettingsFromConfig adapts the direct config subtree into typed provider settings.
The composition IS the precedence, and it is written here rather than hidden inside a resolution chain: the standard key, then the legacy scalar, then the well-known environment variable. A caller wanting a different order — or a different key entirely — builds their own forge.CredentialSource and assigns Settings.Credential, which takes over completely.
A nil cfg is not special-cased: forge.SubConfig returns nil, and forge.ConfigCredential treats a nil config as contributing nothing, so the environment fallback still applies. That is what a config-free public lookup needs. # Where the source's own settings come from
The URL templates and version keys are read from the endpoint's configuration subtree, not from the endpoint value. They describe what this source IS rather than which connection it addresses, and keeping them in configuration is what lets two direct sources coexist: forge.Endpoint.Section resolves `direct.<name>` for a named source and the bare `direct` subtree for the default one, so each reads its own templates.