All checks were successful
check / check (pull_request) Successful in 2m37s
No tag could be cut from this repo at all. Three independent blockers. goreleaser was configured for GitHub while the repo lives on Gitea: .goreleaser.yaml had a release: block but no gitea_urls:, so goreleaser defaulted to the GitHub API and a release would have failed or published somewhere nobody is looking. It now points at https://git.eeqj.de/api/v1. The version was a hardcoded Makefile constant, VERSION := 1.0.0-rc.1, so every local build claimed to be a release candidate that had never been tagged and did not exist, while git tag -l was empty and internal/globals defaulted to dev. The version now comes from git, via the new script/version: the exact tag with a leading v stripped when HEAD is on one (so a make build and a goreleaser build of the same commit report the same string, and it matches the archive names), otherwise dev-<12-char sha>, with -dirty appended in either case when tracked files are modified. Untracked files are not counted, matching git describe --dirty. goreleaser's snapshot template gets the same treatment: it was {{ incpatch .Version }}-next, which manufactures a release number from the last tag and, with no tags at all, from goreleaser's fabricated v0.0.0. That change had one non-obvious consequence. internal/cli/version.go gated its "this is a development build" notice on the version being exactly "dev", so as soon as untagged builds carried a commit sha the notice would have gone silent and an unreleased binary would have read as a release. The gate is now globals.IsDevVersion, a predicate over a string rather than a comparison against a global so that it can be tested, and it is tested at the boundary that matters: dev-<sha> and its -dirty variant are development builds, 1.0.0-dev and 1.0.0-rc.1 are not. The command writes to cmd.OutOrStdout() so its output can be asserted on at all. Releases now come from CI rather than a workstation: a tag-triggered .gitea/workflows/release.yml, with fetch-depth: 0 because a shallow checkout has no tags and would silently mislabel the release, and with the RELEASE_TOKEN repository secret passed as GITEA_TOKEN (documented in README.md; the runner's automatic token is deliberately not used, since it is not guaranteed to carry release write scope). script/release unsets any GITHUB_TOKEN or GITLAB_TOKEN it finds, because goreleaser picks its forge from whichever token variable is set and refuses to run when it sees more than one -- an unrelated runner token must not get to decide where these artifacts are published. make release and make release-snapshot were the last two Makefile targets that were not shims; they now call script/release and script/release-snapshot, which resolve goreleaser the way script/lint resolves the linter -- a PATH binary is accepted only at the pinned version, never as a silent fallback. script/bootstrap installs it from a sha256-verified GitHub release archive per REPO_POLICIES.md, through a separate script/install-goreleaser: separate because script/bootstrap hard-fails without a usable Docker daemon by design, and the release runner needs goreleaser without needing Docker. dist/ and .tool/ are gitignored and excluded from the Docker build context. Verified by running it: make release-snapshot produces the four linux,darwin x amd64,arm64 archives plus checksums.txt, and the binary from dist/ reports dev-<sha> with the development-build notice. Tag handling was exercised in a throwaway repository; no tag was created here, since that is the owner's call. Signing, SBOM, reproducible builds, shell completions and a man page remain out of scope.
145 lines
5.1 KiB
Bash
Executable File
145 lines
5.1 KiB
Bash
Executable File
#!/bin/sh
|
|
# script/install-goreleaser: install the pinned goreleaser into the
|
|
# repo-local tool directory. Our own extension to
|
|
# scripts-to-rule-them-all. Idempotent: exits immediately when the
|
|
# pinned version is already available.
|
|
#
|
|
# script/bootstrap calls this, and so does .gitea/workflows/release.yml.
|
|
# It is a separate script rather than an inline block in bootstrap
|
|
# because bootstrap deliberately hard-fails on a machine without a
|
|
# usable Docker daemon (Docker gates script/lint, and therefore
|
|
# script/check), while the release runner needs goreleaser and does not
|
|
# need Docker. One script, two callers, no duplicated pin.
|
|
#
|
|
# The install is a specific GitHub release archive verified against the
|
|
# sha256 hardcoded below, per REPO_POLICIES.md: no `curl | sh`, no
|
|
# `@latest`, no version tag that a server can move. Bumping goreleaser
|
|
# means editing GORELEASER_VERSION *and* the four checksums, which are
|
|
# taken from the checksums.txt published with that release.
|
|
set -eu
|
|
|
|
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
|
|
|
|
# goreleaser v2.17.1, 2026-08-05. Checksums are from
|
|
# https://github.com/goreleaser/goreleaser/releases/download/v2.17.1/checksums.txt
|
|
GORELEASER_VERSION="2.17.1"
|
|
SHA256_LINUX_X86_64="a99bbc7ae0d8d897b07c4c497a9b62f222558804715ef219d1af05a7e417bc80"
|
|
SHA256_LINUX_ARM64="702f03769ac8bcb0e47839c82243cc614ae995633599a98c63062e13ea85f829"
|
|
SHA256_DARWIN_X86_64="a92a68c61a6833ff67748f532cbebc7b8e49ba30de062ab463b221211ee6368f"
|
|
SHA256_DARWIN_ARM64="b65624885c25da9a677b7ad11cf86a02123cc5a56af66f6b4ebb574658eada2e"
|
|
|
|
TOOLBIN="$ROOT/.tool/bin"
|
|
|
|
# Print the version of the goreleaser at $1, or nothing if it is not
|
|
# usable. `goreleaser --version` prints a multi-line banner; the version
|
|
# is on the line beginning "GitVersion:".
|
|
goreleaser_version() {
|
|
[ -x "$1" ] || return 0
|
|
"$1" --version 2>/dev/null |
|
|
sed -n 's/^ *GitVersion: *//p' |
|
|
head -n 1
|
|
}
|
|
|
|
verify_sha256() {
|
|
file="$1"
|
|
want="$2"
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
got="$(sha256sum "$file" | cut -d' ' -f1)"
|
|
elif command -v shasum >/dev/null 2>&1; then
|
|
got="$(shasum -a 256 "$file" | cut -d' ' -f1)"
|
|
else
|
|
echo "install-goreleaser: no sha256sum or shasum available" >&2
|
|
return 1
|
|
fi
|
|
if [ "$got" != "$want" ]; then
|
|
echo "install-goreleaser: checksum mismatch for $file" >&2
|
|
echo " expected: $want" >&2
|
|
echo " actual: $got" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
cd "$ROOT"
|
|
|
|
# Already have it, either on PATH or from a previous run? Then stop.
|
|
# An arbitrary PATH goreleaser is NOT accepted: the config uses
|
|
# version-2 schema features, and the whole point of pinning is that
|
|
# a release is cut by a known build of a known tool.
|
|
if [ "$(goreleaser_version "$(command -v goreleaser || true)")" \
|
|
= "$GORELEASER_VERSION" ]; then
|
|
echo "goreleaser $GORELEASER_VERSION already on PATH"
|
|
return 0
|
|
fi
|
|
if [ "$(goreleaser_version "$TOOLBIN/goreleaser")" \
|
|
= "$GORELEASER_VERSION" ]; then
|
|
echo "goreleaser $GORELEASER_VERSION already installed in .tool/bin"
|
|
return 0
|
|
fi
|
|
|
|
os="$(uname -s)"
|
|
arch="$(uname -m)"
|
|
case "$os" in
|
|
Linux) ;;
|
|
Darwin) ;;
|
|
*)
|
|
echo "install-goreleaser: unsupported OS $os" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
case "$arch" in
|
|
x86_64 | amd64) arch="x86_64" ;;
|
|
arm64 | aarch64) arch="arm64" ;;
|
|
*)
|
|
echo "install-goreleaser: unsupported architecture $arch" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
case "${os}_${arch}" in
|
|
Linux_x86_64) sum="$SHA256_LINUX_X86_64" ;;
|
|
Linux_arm64) sum="$SHA256_LINUX_ARM64" ;;
|
|
Darwin_x86_64) sum="$SHA256_DARWIN_X86_64" ;;
|
|
Darwin_arm64) sum="$SHA256_DARWIN_ARM64" ;;
|
|
*)
|
|
echo "install-goreleaser: no pinned checksum for ${os}_${arch}" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
archive="goreleaser_${os}_${arch}.tar.gz"
|
|
url="https://github.com/goreleaser/goreleaser/releases/download/v${GORELEASER_VERSION}/${archive}"
|
|
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
echo "install-goreleaser: curl is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
tmp="$(mktemp -d)"
|
|
# shellcheck disable=SC2064 # expand $tmp now, not at trap time
|
|
trap "rm -rf '$tmp'" EXIT INT TERM
|
|
|
|
echo "installing goreleaser $GORELEASER_VERSION for ${os}_${arch}"
|
|
curl -fsSL --retry 3 -o "$tmp/$archive" "$url"
|
|
verify_sha256 "$tmp/$archive" "$sum"
|
|
|
|
tar -xzf "$tmp/$archive" -C "$tmp" goreleaser
|
|
mkdir -p "$TOOLBIN"
|
|
# Move into place via a temp name in the destination directory so a
|
|
# concurrent run never observes a half-written binary.
|
|
mv "$tmp/goreleaser" "$TOOLBIN/.goreleaser.$$"
|
|
chmod 0755 "$TOOLBIN/.goreleaser.$$"
|
|
mv "$TOOLBIN/.goreleaser.$$" "$TOOLBIN/goreleaser"
|
|
|
|
installed="$(goreleaser_version "$TOOLBIN/goreleaser")"
|
|
if [ "$installed" != "$GORELEASER_VERSION" ]; then
|
|
echo "install-goreleaser: installed binary reports '$installed'," \
|
|
"expected '$GORELEASER_VERSION'" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "goreleaser $GORELEASER_VERSION installed to .tool/bin"
|
|
}
|
|
|
|
main "$@"
|