tooling

package
v0.60.0 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 20 Imported by: 0

README

External Tool Updater

Purpose

The external tool updater keeps downloaded CLI versions and SHA-256 checksums in build/tools.yaml. manifest.go validates the manifest, updater.go checks release sources, and cmd/tool-updater/main.go exposes the commands used by Make and CI.

The generated build/tools.generated.mk file is committed and supplies the metadata to the installer recipes in build/tools.mk. Do not edit the generated file directly.

Commands

Update pinned versions
make update-tools

This command checks every configured release source, advances enabled tools to newer releases when available, refreshes platform checksums, synchronizes declared versionFiles, and regenerates the committed build/tools.generated.mk file. Tools with update: false remain pinned at their current version.

make update-tools reaches the network and modifies repository files. It does not install tools on the local machine.

Install a pinned tool
make install-yq
make install-kubectl

Use make install-<tool> to download and install the version pinned in build/tools.yaml. Installer targets read versions and checksums from build/tools.generated.mk and install into a user-owned binary directory. They do not update the manifest.

Run the updater binary directly

Make builds the updater into bin/ before executing it. This stable path is important on Windows, where security software may block the temporary executable created by go run.

To invoke the compiled updater directly:

bin/tool-updater.exe update --manifest build/tools.yaml --makefile build/tools.generated.mk

Use bin/tool-updater instead of bin/tool-updater.exe on non-Windows systems. The other subcommand regenerates only the Make include:

bin/tool-updater.exe generate-make --manifest build/tools.yaml --output build/tools.generated.mk

There is no separate Make target for regeneration only. The generate-make subcommand is the binary-level equivalent, and Make runs it automatically when the committed generated include is stale.

Manifest reference

The manifest is YAML with the following top-level properties:

Property Type Allowed or required values Description
schemaVersion integer 1 Manifest schema version.
cooldownDays integer Non-negative integer; omitted or 0 disables the cooldown Minimum age, in days, before a release is adopted.
platforms list of strings One or more unique values matching linux_amd64, linux_arm64, darwin_amd64, or darwin_arm64 Platforms for which checksums and assets are recorded.
tools list of objects One or more tools Tool definitions described below.
Tool properties
Property Type Allowed or required values Description
name string Lowercase letters, numbers, and hyphens; must start with a lowercase letter or number Stable tool identifier.
makePrefix string Uppercase letters, numbers, and underscores; must start with an uppercase letter Prefix used for generated Make variables such as YQ_VERSION.
version string Non-empty Currently pinned release version. The value may include a leading v when the upstream uses one.
update boolean true or false; omitted means true Set to false to check the source while keeping the current version pinned.
notes string Optional Human-readable compatibility or pinning rationale.
source object Required Describes how the latest version is discovered.
downloadTemplate string Required unless checksumSource.type is none URL template for an asset download.
platforms map Required for checksum-bearing tools; must contain every top-level platform Asset and checksum data for each supported platform.
checksumSource object Required Describes how the updater obtains or computes SHA-256 checksums.
versionFiles list Optional Additional repository files whose embedded version must stay synchronized.
source properties
Property Type Allowed or required values Description
type string github-release, stable-text, or hashicorp-checkpoint Version source parser selected by the updater.
repository string owner/repository; required for github-release GitHub repository; stable-text uses it for release dates.
tagPrefix string Optional Prefix added to the pinned version to form a release tag, such as jq-.
latestURL string Non-empty HTTPS URL Endpoint queried for the latest version.

For github-release, the endpoint must return a GitHub release object with tag_name. stable-text reads the trimmed response body, and hashicorp-checkpoint reads current_version from the JSON response.

The cooldown needs a release date. github-release reads published_at and hashicorp-checkpoint reads current_release. A stable-text response carries no date, so the updater reads published_at from the GitHub release matching the resolved tag in repository. When a cooldown is configured, every updatable tool must be able to resolve a date this way or the manifest fails validation.

checksumSource properties
type Required properties Behavior
github-release-file fileTemplate, format; also orderFileTemplate when format is yq Reads a checksum file from the GitHub release.
url-file urlTemplate, format Reads a checksum file from an arbitrary URL.
download None Downloads the asset and hashes its bytes locally.
none integrity Records a non-SHA-256 integrity method, such as go-sumdb; the tool has no platform asset map.

Supported checksum formats are standard (filename in the second column), basename (compare only the filename after a path), first (use the first field), and yq (use checksums_hashes_order to locate the SHA-256 column). Every stored checksum must be exactly 64 lowercase hexadecimal characters.

Platform entries

Each platform entry has these properties:

Property Type Allowed or required values Description
asset string Non-empty; may contain template variables Release asset name.
checksum string Lowercase 64-character SHA-256 value Expected checksum for the asset.
os string Optional Overrides the operating-system value used in templates.
arch string Optional Overrides the architecture value used in templates.
Templates

Asset, download, checksum-file, and checksum-URL templates may use these variables:

Variable Value
{repository} source.repository
{tag} source.tagPrefix plus the requested version
{version} Requested version, including its leading v when present
{version_no_v} Requested version without a leading v
{asset} Expanded platform asset name
{os} Platform OS, or the entry's os override
{arch} Platform architecture, or the entry's arch override

Unknown or unterminated template variables are errors.

Version files

A versionFiles entry keeps another repository file synchronized when a tool version changes:

Property Type Allowed or required values Description
path string Repository-relative path File to update. Paths outside the repository are rejected.
format string plain or replace Replace the whole file with the version, or replace text between markers.
prefix string Required for replace; empty for plain Text immediately before the embedded version.
suffix string Required for replace; empty for plain Text immediately after the embedded version.

The replace prefix must occur exactly once. Terraform uses versionFiles for .terraform-version, the Go fallback, and the Helm chart default.

Update behavior

  • The updater checks the latest version source for every tool.
  • A version changes only when the source is a greater semantic version; downgrades are ignored.
  • A newer release is adopted only once it is at least cooldownDays old. A younger release is reported as held and the current version stays pinned until a later run.
  • A tool with update: false remains pinned, but its source and current-version checks still run.
  • Checksums are refreshed for every configured platform at the selected version.
  • The manifest, generated Make include, Terraform compatibility file, and declared version consumers are updated only after source checks succeed.

Verification

Run the focused tests and static checks after changing the updater or manifest:

go test ./internal/tooling ./cmd/tool-updater
go vet ./internal/tooling ./cmd/tool-updater
make --no-print-directory -n update-tools

The Make dry run should invoke bin/tool-updater or bin/tool-updater.exe, not go run.

Troubleshooting

  • Windows reports an elevation error for go run. Use make update-tools, or build and run bin/tool-updater.exe directly. The Make target avoids Go's temporary executable directory.
  • A newer release is reported as held. The release is younger than cooldownDays. Wait for it to age, or change cooldownDays in the manifest.
  • The updater reports that a source has no release date. The source stopped returning published_at or current_release. Confirm the release exists upstream, and check that a stable-text source names a repository that publishes GitHub releases for its tags.
  • A checksum is not found. Check the release asset name, version/tag prefix, checksum-file template, and checksum format together. The updater matches the expanded asset name exactly.
  • Manifest validation fails. Ensure every checksum-bearing tool defines every platform listed at the manifest's top level, every checksum is 64 lowercase hexadecimal characters, and any versionFiles path stays inside the repository.

Documentation

Overview

Package tooling manages the pinned command-line tools used by Radius builds.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExpandTemplate

func ExpandTemplate(template string, values map[string]string) (string, error)

ExpandTemplate expands the small, explicit template language used by the manifest and rejects unknown variables instead of silently producing a bad URL.

func GenerateMake

func GenerateMake(m Manifest) ([]byte, error)

GenerateMake returns the generated Make include containing only metadata values. Tool installation recipes remain in build/tools.mk.

func SyncVersionFiles

func SyncVersionFiles(root string, tool Tool) error

SyncVersionFiles updates the declared consumers of a tool version. Plain files are replaced completely; replace files update the value between their declared prefix and suffix exactly once.

func WriteMakeFile

func WriteMakeFile(path string, manifest Manifest) (bool, error)

WriteMakeFile writes generated Make metadata only when its contents change.

func WriteManifest

func WriteManifest(path string, manifest Manifest) (bool, error)

WriteManifest patches tool versions and checksums into the manifest, preserving its existing formatting, and writes only when contents change.

func WriteTextFile

func WriteTextFile(path, contents string) (bool, error)

WriteTextFile writes a text file only when its contents change.

Types

type ChecksumSource

type ChecksumSource struct {
	Type              string `yaml:"type"`
	FileTemplate      string `yaml:"fileTemplate,omitempty"`
	OrderFileTemplate string `yaml:"orderFileTemplate,omitempty"`
	URLTemplate       string `yaml:"urlTemplate,omitempty"`
	Format            string `yaml:"format,omitempty"`
	Integrity         string `yaml:"integrity,omitempty"`
}

ChecksumSource describes where a release asset's SHA-256 checksum comes from.

type Client

type Client struct {
	HTTP      HTTPClient
	Token     string
	UserAgent string
	// contains filtered or unexported fields
}

Client retrieves release metadata and checksum sources.

func NewClient

func NewClient(token string) *Client

NewClient constructs a source client. GITHUB_TOKEN and GH_TOKEN are honored to keep local and GitHub Actions runs equivalent.

func (*Client) Checksum

func (client *Client) Checksum(ctx context.Context, tool Tool, platform, version string) (string, error)

Checksum reads or computes the checksum for one target platform.

func (*Client) LatestVersion

func (client *Client) LatestVersion(ctx context.Context, tool Tool) (Release, error)

LatestVersion resolves the latest stable release for a tool source.

type HTTPClient

type HTTPClient interface {
	Do(request *http.Request) (*http.Response, error)
}

HTTPClient is the subset of http.Client used by the updater.

type Manifest

type Manifest struct {
	SchemaVersion int      `yaml:"schemaVersion"`
	CooldownDays  int      `yaml:"cooldownDays,omitempty"`
	Platforms     []string `yaml:"platforms"`
	Tools         []Tool   `yaml:"tools"`
}

Manifest is the source of truth for the versions, release sources, assets, and checksums of the external tools used by the repository.

func LoadManifest

func LoadManifest(path string) (Manifest, error)

LoadManifest reads and validates a tool manifest.

func (Manifest) Cooldown

func (m Manifest) Cooldown() time.Duration

Cooldown returns the minimum age a release must reach before the updater adopts it. A zero duration disables the cooldown.

func (Manifest) Validate

func (m Manifest) Validate() error

Validate checks that a manifest contains enough information for both Make generation and source verification.

type Platform

type Platform struct {
	Asset    string `yaml:"asset"`
	Checksum string `yaml:"checksum"`
	OS       string `yaml:"os,omitempty"`
	Arch     string `yaml:"arch,omitempty"`
}

Platform describes a release asset and its pinned checksum for one target platform. Asset names may contain manifest template variables.

type Release

type Release struct {
	Version     string
	PublishedAt time.Time
}

Release is the newest version advertised by a tool's source, with the time it was published when the source reports one.

type Source

type Source struct {
	Type       string `yaml:"type"`
	Repository string `yaml:"repository,omitempty"`
	TagPrefix  string `yaml:"tagPrefix,omitempty"`
	LatestURL  string `yaml:"latestURL"`
}

Source describes how the updater discovers a tool's latest version.

func (Source) ReportsReleaseDate

func (s Source) ReportsReleaseDate() bool

ReportsReleaseDate reports whether the updater can determine when a source's latest release was published, which the cooldown requires. A stable-text source carries no timestamp, so it needs a repository to resolve one.

type Tool

type Tool struct {
	Name             string              `yaml:"name"`
	MakePrefix       string              `yaml:"makePrefix"`
	Version          string              `yaml:"version"`
	Update           *bool               `yaml:"update,omitempty"`
	Notes            string              `yaml:"notes,omitempty"`
	Source           Source              `yaml:"source"`
	DownloadTemplate string              `yaml:"downloadTemplate,omitempty"`
	Platforms        map[string]Platform `yaml:"platforms,omitempty"`
	ChecksumSource   ChecksumSource      `yaml:"checksumSource"`
	VersionFiles     []VersionFile       `yaml:"versionFiles,omitempty"`
}

Tool describes one pinned external tool.

func (Tool) Platform

func (t Tool) Platform(name string) (Platform, bool)

Platform returns a platform entry by name.

func (Tool) TagForVersion

func (t Tool) TagForVersion(version string) string

TagForVersion converts a manifest version into its release tag.

func (Tool) TemplateValues

func (t Tool) TemplateValues(platform, version string) (map[string]string, error)

TemplateValues builds the values used by asset and URL templates.

func (Tool) UpdatesEnabled

func (t Tool) UpdatesEnabled() bool

UpdatesEnabled reports whether the updater may advance the tool's version.

func (Tool) VersionFromTag

func (t Tool) VersionFromTag(tag string) string

VersionFromTag converts a release tag into the manifest's version format.

type UpdateResult

type UpdateResult struct {
	Changes []string
	Held    []string
}

UpdateResult reports the manifest values the updater changed and the newer releases it deferred because they are still inside the cooldown.

func UpdateManifest

func UpdateManifest(ctx context.Context, manifest *Manifest, client *Client) (UpdateResult, error)

UpdateManifest refreshes versions and checksums in memory. It writes no files, so a failed source lookup cannot leave a partially updated manifest.

type VersionFile

type VersionFile struct {
	Path   string `yaml:"path"`
	Format string `yaml:"format"`
	Prefix string `yaml:"prefix,omitempty"`
	Suffix string `yaml:"suffix,omitempty"`
}

VersionFile describes a repository file that must stay synchronized with a tool version when the tool is not only consumed through Make.

Jump to

Keyboard shortcuts

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