toolversions

package
v0.2.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package toolversions compares the tool versions a devvault project pins in its .devvault/config.yaml against the current upstream releases, and rewrites those pins in place.

The pins rot silently. A project that was generated a year ago still builds its container with the Terraform, Trivy and Checkov releases of that day, and a stale Terraform is a security problem rather than a cosmetic one — so the comparison is a command instead of a chore.

Trust boundary: every endpoint this package talks to is a compile-time constant, and the repository coordinates are unexported. Neither the repository config, nor the environment, nor a command line flag can redirect a request. A repository that could choose the update source could also choose which version string devvault writes back into that repository's own config. For the same reason, every version string an upstream returns is matched against a strict major.minor.patch pattern before it is compared, displayed or written.

Index

Constants

This section is empty.

Variables

View Source
var ErrRateLimited = errors.New("upstream rate limit reached")

ErrRateLimited reports that the upstream refused the request because the caller is over its rate limit. It is a sentinel so callers can turn it into a helpful message instead of matching on strings.

Functions

func Bump

func Bump(root string, changes []Change, before config.Config, reload func() (config.Config, error)) (string, error)

Bump writes the new pins into the project config and verifies the result.

Verification is the point of this function. After the rewrite the config is loaded again through the caller's loader — which runs config.Validate — and the result is compared against `before` with only the requested pins applied. If the file no longer loads, no longer validates, or differs in any other field, the original bytes are put back and the error is returned. A partial or corrupted config is never left behind.

func Compare

func Compare(a, b string) (int, error)

Compare orders two major.minor.patch versions numerically and returns -1, 0 or 1. It exists because a string comparison gets this wrong in exactly the case that matters: "0.9.0" sorts after "0.10.0" lexically, which would hide a pending update.

func ConfigPath

func ConfigPath(root string) (string, error)

ConfigPath returns the devvault config file of a project.

func Names

func Names() []string

Names lists the command line names of every known tool.

func Normalize

func Normalize(tag string) string

Normalize strips the single leading "v" that GitHub release tags carry. It does not validate; Parse does that.

func Parse

func Parse(version string) ([3]uint64, error)

Parse validates a major.minor.patch version and returns its three numbers.

func Preview

func Preview(root string, changes []Change) (path, diff string, err error)

Preview renders the change as a unified diff without touching the file.

func Rewrite

func Rewrite(content []byte, changes []Change) ([]byte, error)

Rewrite replaces the version pins in a devvault config file.

It edits the file as text rather than unmarshalling and re-marshalling it: the config file belongs to the repository, it is reviewed in pull requests, and a round trip through yaml.Marshal would drop every comment, reorder the keys and rewrite quoting and booleans across the whole document. Only the matched value token of a targeted key is exchanged; indentation, quoting style, trailing comments, line endings and every other line are preserved byte for byte.

A key that is absent is inserted into its block — a config may legitimately omit a pin and rely on the built-in default. A key that appears more than once in its block is an error: devvault does not guess which of them the build uses.

Types

type Change

type Change struct {
	Tool Tool
	From string
	To   string
}

Change is one pin devvault is about to rewrite.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client queries the upstream release feeds over HTTPS.

func NewClient

func NewClient() *Client

NewClient returns a client for the real upstream endpoints. A GITHUB_TOKEN or GH_TOKEN in the environment is used as a bearer token for api.github.com, which raises the anonymous rate limit; without one the client still works.

func (*Client) GitHubTokenConfigured

func (c *Client) GitHubTokenConfigured() bool

GitHubTokenConfigured reports whether a token was picked up from the environment, so a rate limit message can tell the user whether adding one would even help.

func (*Client) Latest

func (c *Client) Latest(ctx context.Context, tool Tool) (string, error)

Latest returns the current upstream version of tool, already validated as major.minor.patch.

type Fetcher

type Fetcher interface {
	Latest(ctx context.Context, tool Tool) (string, error)
}

Fetcher resolves the latest upstream version of a tool. Check takes this interface rather than *Client so tests can run without a network.

type Result

type Result struct {
	Tool   Tool
	Pinned string
	Latest string
	Status Status
	// Err explains a StatusUnknown. One tool failing must never discard the
	// results of the others, so the error is carried per tool instead of being
	// returned from Check.
	Err error
}

Result is the comparison of one pinned version against its upstream release.

func Check

func Check(ctx context.Context, fetcher Fetcher, cfg config.Config, tools []Tool) []Result

Check resolves the upstream version of every tool concurrently and compares it against what cfg pins. The returned slice has the same order and length as tools; a tool whose lookup failed is reported as StatusUnknown with the reason in Err.

func Outdated

func Outdated(results []Result) []Result

Outdated returns the results that call for a bump, in input order.

type Status

type Status string

Status is the verdict for a single tool.

const (
	StatusUpToDate Status = "up-to-date"
	StatusOutdated Status = "outdated"
	// StatusUnknown means devvault could not establish a verdict — the request
	// failed, the upstream answered something unusable, or the config does not
	// pin this tool. Result.Err carries the reason.
	StatusUnknown Status = "unknown"
)

type Tool

type Tool struct {
	// Name is how the tool is addressed on the command line.
	Name string
	// Section is the top-level key of the config file the pin lives under.
	Section string
	// Key is the key inside Section that holds the version.
	Key string
	// contains filtered or unexported fields
}

Tool describes one version pin devvault keeps in a project config.

The upstream coordinates (kind, repo, product) are deliberately unexported: only Catalog can construct a Tool that points somewhere, so no caller — least of all a repository-owned config — can make the client fetch from an address of its choosing.

func Catalog

func Catalog() []Tool

Catalog lists every tool whose version devvault pins, including both Terraform distributions. Use ForConfig to get the set that actually applies to a project.

func Find

func Find(name string) (Tool, error)

Find looks a tool up by its command line name.

func ForConfig

func ForConfig(cfg config.Config) []Tool

ForConfig returns the tools whose pins this project actually builds with. The config carries a version for both Terraform and OpenTofu but only one of them ends up in the container, so reporting the unused pin as outdated would be noise. The inactive distribution stays reachable through Find.

func (Tool) ConfigKey

func (t Tool) ConfigKey() string

ConfigKey is the dotted path of the version field, e.g. "tools.tflint".

func (Tool) Pinned

func (t Tool) Pinned(cfg config.Config) string

Pinned reads the version cfg pins for this tool. An unknown tool yields the empty string, which Check reports as "unknown" instead of comparing garbage.

func (Tool) WithPinned

func (t Tool) WithPinned(cfg config.Config, version string) config.Config

WithPinned returns a copy of cfg with this tool's version replaced. It is the counterpart of Pinned and gives Bump an expected config to compare the rewritten file against, so a rewrite that changed anything else is caught.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL