Documentation
¶
Overview ¶
Package releasetest provides an in-memory forge.Provider test double and asset builders for exercising the self-update pipeline without network or disk access. It serves releases, tar.gz binary assets, checksum manifests and detached signatures entirely from memory, including the security-relevant corrupt-checksum and bad-signature variants.
The double is public (pkg/) so downstream tools building on GTB can test their own self-update wiring hermetically — the same reasoning that keeps forge.Provider public. It is usable both from tests and at runtime (the builders take no *testing.T), which lets the e2e binary inject a stub release source behind an env gate.
A Source always satisfies forge.ChecksumProvider and forge.SignatureProvider, but returns forge.ErrNotSupported unless configured with WithChecksumManifest / WithSignatureManifest. Per the provider contract, the update flow treats forge.ErrNotSupported exactly like "provider does not implement this interface" and falls back to locating checksums.txt / checksums.txt.sig by filename in the asset list — so a Source exercises both the manifest-provider path and the asset-by-name fallback.
See docs/development/specs/2026-06-19-injectable-release-source.md.
Index ¶
- func AssetName(toolName string) string
- func Manifest(corrupt bool, over ...Asset) []byte
- func RunProviderConformance(t *testing.T, cfg ConformanceConfig)
- type Asset
- type Capabilities
- type ConformanceConfig
- type Option
- type Source
- func (s *Source) DownloadChecksumManifest(_ context.Context, _ forge.Release, _ int64) ([]byte, error)
- func (s *Source) DownloadReleaseAsset(_ context.Context, _, _ string, a forge.ReleaseAsset) (io.ReadCloser, string, error)
- func (s *Source) DownloadSignature(_ context.Context, _ forge.Release, _ int64) ([]byte, error)
- func (s *Source) GetLatestRelease(_ context.Context, _, _ string) (forge.Release, error)
- func (s *Source) GetReleaseByTag(_ context.Context, _, _, tag string) (forge.Release, error)
- func (s *Source) ListReleases(_ context.Context, _, _ string, limit int) ([]forge.Release, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssetName ¶
AssetName returns the OS/arch release-asset name the updater's findReleaseAsset expects for toolName on the current platform — e.g. "mytool_Linux_x86_64.tar.gz". It mirrors the naming convention in pkg/setup so a built asset is the one Update will look for.
func Manifest ¶
Manifest builds a GoReleaser-style checksums.txt over the given assets (one "sha256 name" line each). When corrupt is true the recorded hashes intentionally cover a different payload, so verification against the real asset bodies fails.
func RunProviderConformance ¶
func RunProviderConformance(t *testing.T, cfg ConformanceConfig)
RunProviderConformance asserts that a forge.Provider honours the parts of the contract that are otherwise documented only in prose.
It exists because the contract has two halves, and only one is checkable by the compiler. The method set is enforced by the type system; the *protocol* — which error to return when an operation does not apply, that a nil result and a nil error may never be returned together, that a caller-supplied size bound is actually enforced — is enforced by nothing at all. A provider can satisfy forge.Provider completely and still be wrong in every way that matters to a caller.
Run it from the provider's own test suite:
func TestConformance(t *testing.T) {
forgetest.RunProviderConformance(t, forgetest.ConformanceConfig{
NewProvider: func() forge.Provider { return newTestProvider(t) },
Capabilities: forgetest.Capabilities{GetReleaseByTag: true, ListReleases: true},
Owner: "acme", Repo: "tool", Tag: "v1.0.0",
})
}
The harness never asserts on payload contents — that is the provider's own business — only on the contract every caller relies upon.
Types ¶
type Asset ¶
Asset is a single downloadable release asset served verbatim by a Source.
func ChecksumsAsset ¶
ChecksumsAsset wraps Manifest as a "checksums.txt" asset.
func SignatureAsset ¶
SignatureAsset builds a "checksums.txt.sig" ASCII-armored detached signature over manifest using entity. When bad is true it signs a different payload, so the signature does not verify against the served manifest.
func TarGzAsset ¶
TarGzAsset builds the platform release-binary asset for toolName: its Name is AssetName(toolName) and its Body is a .tar.gz archive whose single entry is binName with binBody as its contents.
type Capabilities ¶
type Capabilities struct {
// GetReleaseByTag is false for platforms with no addressable tag concept.
GetReleaseByTag bool
// ListReleases is false for platforms that expose no release listing.
ListReleases bool
// Checksums is true when the provider implements [forge.ChecksumProvider]
// AND is configured such that it will serve a manifest.
Checksums bool
// Signatures is true when the provider implements
// [forge.SignatureProvider] AND is configured to serve one.
Signatures bool
}
Capabilities declares what a provider under test supports, so the harness can tell "correctly reports it cannot do this" apart from "is broken".
Declare capabilities honestly. Claiming support the provider lacks makes the harness assert real behaviour it cannot deliver; claiming less than it supports means the harness checks the opt-out protocol instead, which is weaker but never wrong.
type ConformanceConfig ¶
type ConformanceConfig struct {
// NewProvider returns a provider ready to serve the fixtures below. It is
// called once per check, so each gets an independent instance. Close over
// *testing.T if construction needs it for cleanup.
NewProvider func() forge.Provider
// Capabilities describes what this provider can do.
Capabilities Capabilities
// Owner, Repo and Tag are passed to the provider's methods. Tag must name
// a release the provider will find when GetReleaseByTag is supported.
Owner, Repo, Tag string
// MissingTag names a tag the provider will NOT find. Optional: when empty,
// the not-found check is skipped rather than guessed at.
MissingTag string
}
ConformanceConfig parameterises RunProviderConformance.
type Option ¶
type Option func(*Source)
Option configures a Source.
func WithChecksumManifest ¶
WithChecksumManifest puts the Source in checksum manifest-provider mode: it implements forge.ChecksumProvider by returning these bytes instead of the default asset-by-name fallback.
func WithDownloadError ¶
WithDownloadError makes Source.DownloadReleaseAsset fail with err.
func WithLatestTag ¶
WithLatestTag sets which registered tag Source.GetLatestRelease returns.
func WithMissingTag ¶
WithMissingTag makes Source.GetReleaseByTag(tag) return a not-found error wrapping forge.ErrReleaseNotFound.
func WithRelease ¶
WithRelease registers a release at tag exposing the given assets. The first registered release becomes the "latest" unless WithLatestTag overrides it.
func WithSignatureManifest ¶
WithSignatureManifest puts the Source in signature manifest-provider mode: it implements forge.SignatureProvider by returning these bytes instead of the default asset-by-name fallback.
type Source ¶
type Source struct {
// contains filtered or unexported fields
}
Source is a fully in-memory forge.Provider for tests and the e2e stub. Construct it with New and one or more [Option]s.
func (*Source) DownloadChecksumManifest ¶
func (s *Source) DownloadChecksumManifest(_ context.Context, _ forge.Release, _ int64) ([]byte, error)
DownloadChecksumManifest implements forge.ChecksumProvider. It returns forge.ErrNotSupported unless the Source was built with WithChecksumManifest, so the default Source uses the asset-by-name fallback.
func (*Source) DownloadReleaseAsset ¶
func (s *Source) DownloadReleaseAsset(_ context.Context, _, _ string, a forge.ReleaseAsset) (io.ReadCloser, string, error)
DownloadReleaseAsset returns the in-memory body registered for the asset.
func (*Source) DownloadSignature ¶
DownloadSignature implements forge.SignatureProvider. It returns forge.ErrNotSupported unless the Source was built with WithSignatureManifest, so the default Source uses the asset-by-name fallback.
func (*Source) GetLatestRelease ¶
GetLatestRelease returns the release at the configured latest tag.
func (*Source) GetReleaseByTag ¶
GetReleaseByTag returns the release registered at tag, or a not-found error when the tag is unknown or was marked missing.