Make the tagged-release path work on Gitea (closes #65)
All checks were successful
check / check (push) Successful in 3m7s
All checks were successful
check / check (push) Successful in 3m7s
No tag could be cut at all: .goreleaser.yaml had no gitea_urls block, so
goreleaser defaulted to the GitHub API, and the repo has zero tags.
.goreleaser.yaml now points at git.eeqj.de. Version derives from git via
a new script/version - exact tag with any leading v stripped, else
dev-<12-char sha>, with a -dirty suffix when tracked files are modified -
replacing the hardcoded 1.0.0-rc.1 that every local build was stamping
regardless of git state. A tag-triggered .gitea/workflows/release.yml
runs goreleaser with a scoped token (RELEASE_TOKEN); script/bootstrap
installs a sha256-verified goreleaser, and make release / release-snapshot
become script shims like every other target.
Two fabrications were removed rather than merely replaced. goreleaser's
snapshot.version_template was `{{ incpatch .Version }}-next`, which
invents a release number from the last tag - and with no tags, from
goreleaser's own fabricated v0.0.0. And internal/cli/version.go gated its
development-build notice on Version == "dev" exactly, so the moment
untagged builds carried a sha that notice would have gone silent and an
unreleased binary would have read as a release. Replaced with a tested
IsDevVersion predicate, and closed at both layers: the Makefile now
refuses to build when script/version yields nothing, and an empty version
counts as a development build - reachable today via
`docker build --build-arg VERSION=`.
The release workflow installs Go from a sha-pinned actions/setup-go
(v5.6.0) using go-version-file, so the compiler that produces released
binaries is pinned like every other external reference. Without it the
first tag push would either fail at goreleaser's before-hook or compile
the published artifacts with whatever unpinned Go the runner happened to
carry - the one unpinned thing in a release path that already refuses an
unpinned goreleaser.
Known gap: the Go tarball setup-go fetches is version-pinned but not
checksum-verified against a value in this repo, unlike the goreleaser
install and the Dockerfile digest.
This commit was merged in pull request #104.
This commit is contained in:
92
script/release
Executable file
92
script/release
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/bin/sh
|
||||
# script/release: build and publish the release artifacts with the
|
||||
# pinned goreleaser. Our own extension to scripts-to-rule-them-all.
|
||||
#
|
||||
# Normally invoked by a tag push through .gitea/workflows/release.yml,
|
||||
# not by hand: a release cut from a workstation is a release nobody can
|
||||
# reproduce. Any arguments are passed through to `goreleaser release`,
|
||||
# which is how script/release-snapshot adds --snapshot.
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
|
||||
ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
||||
|
||||
# Keep in sync with script/install-goreleaser, which owns the pin.
|
||||
GORELEASER_VERSION="2.17.1"
|
||||
|
||||
goreleaser_version() {
|
||||
[ -x "$1" ] || return 0
|
||||
"$1" --version 2>/dev/null |
|
||||
sed -n 's/^ *GitVersion: *//p' |
|
||||
head -n 1
|
||||
}
|
||||
|
||||
# Resolve the goreleaser to run, on the same rule script/lint uses for
|
||||
# golangci-lint: a binary on PATH is accepted only when it is exactly
|
||||
# the pinned version, because a differently versioned tool would
|
||||
# produce a differently built release from the same tag. Anything else
|
||||
# comes from .tool/bin, and a missing one is a loud failure naming the
|
||||
# script that installs it rather than a silent fallback.
|
||||
resolve_goreleaser() {
|
||||
path_bin="$(command -v goreleaser || true)"
|
||||
if [ -n "$path_bin" ] &&
|
||||
[ "$(goreleaser_version "$path_bin")" = "$GORELEASER_VERSION" ]; then
|
||||
echo "$path_bin"
|
||||
return 0
|
||||
fi
|
||||
if [ "$(goreleaser_version "$ROOT/.tool/bin/goreleaser")" \
|
||||
= "$GORELEASER_VERSION" ]; then
|
||||
echo "$ROOT/.tool/bin/goreleaser"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
main() {
|
||||
cd "$ROOT"
|
||||
|
||||
if ! bin="$(resolve_goreleaser)"; then
|
||||
cat >&2 <<EOF
|
||||
release: goreleaser $GORELEASER_VERSION is not available.
|
||||
|
||||
Run script/bootstrap (or script/install-goreleaser directly) to install
|
||||
it. A goreleaser already on PATH is used only when it reports exactly
|
||||
$GORELEASER_VERSION; any other version is refused rather than used,
|
||||
because the released binaries must come from a known build of a known
|
||||
tool.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
snapshot=0
|
||||
for arg in "$@"; do
|
||||
[ "$arg" = "--snapshot" ] && snapshot=1
|
||||
done
|
||||
|
||||
if [ "$snapshot" -eq 0 ]; then
|
||||
# Publishing needs a Gitea token. Check it here so the failure
|
||||
# names the secret, rather than after several minutes of
|
||||
# cross-compiling.
|
||||
if [ -z "${GITEA_TOKEN:-}" ]; then
|
||||
cat >&2 <<'EOF'
|
||||
release: GITEA_TOKEN is not set.
|
||||
|
||||
Publishing needs a Gitea API token with write access to this
|
||||
repository's releases. In CI it comes from the RELEASE_TOKEN repository
|
||||
secret (see .gitea/workflows/release.yml and the Releasing section of
|
||||
README.md). To build without publishing, use script/release-snapshot.
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
# goreleaser picks its forge from whichever token variable is
|
||||
# set and refuses to run when it finds more than one. A CI
|
||||
# runner may export a GITHUB_TOKEN of its own; this repo lives
|
||||
# on Gitea and releases only there, so an unrelated token must
|
||||
# not be allowed to decide where the artifacts are published.
|
||||
unset GITHUB_TOKEN GITLAB_TOKEN
|
||||
fi
|
||||
|
||||
exec "$bin" release --clean "$@"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user