Files
sherlock/.gitea/workflows/release.yaml
T
amacocian 53b0d025f5
Release / release (push) Successful in 24s
Shared infra for installer
2026-06-13 14:25:40 +02:00

166 lines
5.9 KiB
YAML

name: Release
# Single pipeline: lint + test + build, then (only on push to main and
# only if every gate passed) tag the release from the VERSION file.
# A tag is therefore never created unless the build and tests are green.
#
# Why no actions/checkout + actions/setup-go:
# act_runner re-clones every third-party JS action from github.com per
# job. setup-go is large and that clone routinely hangs / times out on
# the homelab runner. We avoid the failure mode entirely by doing the
# checkout with plain git and downloading Go directly from go.dev.
# /usr/local/go persists across jobs in the host-executor runner
# container, so subsequent runs are no-ops.
#
# Tagging token:
# Pushing a tag needs write access. Gitea injects a per-job
# `github.token`; this workflow uses it, so the repository's
# Settings → Actions → General → "Workflow permissions" must allow
# read/write. If your instance restricts the auto token, set a PAT
# secret named RELEASE_TAG_PAT (repo write) and it is used instead.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
env:
GO_VERSION: "1.26.3"
ERRCHECK_VERSION: "v1.20.0"
STATICCHECK_VERSION: "v0.7.0"
jobs:
release:
runs-on: self-hosted
defaults:
run:
shell: sh
env:
# Gitea auto-generates a per-job read-scoped token for git fetch;
# RELEASE_TAG_PAT (if set) is preferred for the tag push.
GITHUB_TOKEN: ${{ github.token }}
RELEASE_TAG_PAT: ${{ secrets.RELEASE_TAG_PAT }}
steps:
- name: Install Go and toolchain
run: |
set -eu
missing=""
command -v curl >/dev/null 2>&1 || missing="$missing curl"
command -v gcc >/dev/null 2>&1 || missing="$missing build-base"
command -v git >/dev/null 2>&1 || missing="$missing git"
if [ -n "$missing" ]; then
apk add --no-cache $missing
fi
want="go${GO_VERSION}"
have="$(/usr/local/go/bin/go env GOVERSION 2>/dev/null || echo none)"
if [ "$have" != "$want" ]; then
echo "installing Go ${GO_VERSION} (had: ${have})"
curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o /tmp/go.tgz
rm -rf /usr/local/go
tar -C /usr/local -xzf /tmp/go.tgz
rm -f /tmp/go.tgz
else
echo "Go ${GO_VERSION} already installed"
fi
echo "/usr/local/go/bin" >> "$GITHUB_PATH"
echo "$HOME/go/bin" >> "$GITHUB_PATH"
echo "CGO_ENABLED=1" >> "$GITHUB_ENV"
- name: Checkout
run: |
set -eu
cd "$GITHUB_WORKSPACE"
rm -rf ./* ./.[!.]* 2>/dev/null || true
git init -q
git remote add origin "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git"
auth=$(printf '%s' "x-access-token:${GITHUB_TOKEN}" | base64 -w0)
git -c "http.extraheader=Authorization: Basic ${auth}" \
fetch --depth=1 origin "${GITHUB_SHA}"
git checkout -q FETCH_HEAD
- name: Install linters (errcheck, staticcheck)
run: |
set -eu
if ! command -v errcheck >/dev/null 2>&1; then
echo "installing errcheck ${ERRCHECK_VERSION}"
go install "github.com/kisielk/errcheck@${ERRCHECK_VERSION}"
else
echo "errcheck already installed"
fi
if ! command -v staticcheck >/dev/null 2>&1; then
echo "installing staticcheck ${STATICCHECK_VERSION}"
go install "honnef.co/go/tools/cmd/staticcheck@${STATICCHECK_VERSION}"
else
echo "staticcheck already installed: $(staticcheck -version)"
fi
- name: gofmt
run: |
set -eu
diff=$(gofmt -l $(find . -name '*.go' -not -path './vendor/*'))
if [ -n "$diff" ]; then
echo "gofmt would reformat:"
echo "$diff"
exit 1
fi
- name: go vet
run: go vet ./...
- name: errcheck
run: errcheck ./...
- name: staticcheck
run: staticcheck ./...
- name: go test -race
run: go test ./... -race
- name: go build
run: go build ./...
# ── Release: only on push to main, and only after every gate above
# passed (steps run sequentially and fail-fast). ──────────────
- name: Tag release from VERSION
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
run: |
set -eu
cd "$GITHUB_WORKSPACE"
token="${RELEASE_TAG_PAT:-$GITHUB_TOKEN}"
if [ -z "$token" ]; then
echo "no token available to push tags" >&2
exit 1
fi
auth=$(printf '%s' "x-access-token:${token}" | base64 -w0)
# Fetch existing tags so we can check the target tag.
git -c "http.extraheader=Authorization: Basic ${auth}" \
fetch --quiet --tags origin || true
version="$(tr -d ' \t\r\n' < VERSION)"
if [ -z "$version" ]; then
echo "VERSION file is empty" >&2
exit 1
fi
tag="v${version}"
if git rev-parse -q --verify "refs/tags/${tag}" >/dev/null; then
echo "Tag ${tag} already exists — nothing to release."
exit 0
fi
if git -c "http.extraheader=Authorization: Basic ${auth}" \
ls-remote --tags origin "refs/tags/${tag}" | grep -q "${tag}"; then
echo "Tag ${tag} already exists on the remote — nothing to release."
exit 0
fi
echo "Creating tag ${tag} at ${GITHUB_SHA}"
git config user.name "sherlock-release"
git config user.email "release@sherlock.local"
git tag -a "${tag}" -m "Release ${tag}"
git -c "http.extraheader=Authorization: Basic ${auth}" \
push origin "refs/tags/${tag}"
echo "Pushed ${tag}."