From 88f0e24b465a28470ce49e99ebc1cbb95342cf04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Balv=C3=ADn?= Date: Sun, 26 Jul 2026 23:29:55 +0200 Subject: [PATCH] ci(release): simplify tag pattern and bump action versions --- .gitea/workflows/release.yml | 33 ++++++++++++++++-------------- .gitea/workflows/test.yml | 39 ++++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 072c45b..a213748 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -1,8 +1,10 @@ +# Release — Go binaries. Runs on version tags (v1.2.3) pushed to main. +# Builds the platform matrix, creates the Gitea release, uploads binaries. name: Release on: push: - tags: ["v*.*.*"] + tags: ["v*"] jobs: build: @@ -26,33 +28,31 @@ jobs: - goos: freebsd goarch: riscv64 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: "1.26" - name: Download dependencies run: go mod download - - name: Build + - name: Validate tag and build id: build env: - REF: ${{ gitea.ref }} - + VERSION: ${{ gitea.ref_name }} run: | set -euo pipefail - VERSION="${REF##*/}" - - if [[ ! "$VERSION" =~ ^v[0-9]+(\.[0-9]+){0,2}([-+].*)?$ ]]; then - echo "ERROR: expected a semver tag like v1.2.3, got: '$VERSION' (ref: '$REF')" + if ! echo "$VERSION" | grep -qE '^v[0-9]+(\.[0-9]+){0,2}([-+].*)?$'; then + echo "ERROR: expected a semver tag like v1.2.3, got: '$VERSION'" exit 1 fi VERSION_NO_V="${VERSION#v}" echo "version_no_v=${VERSION_NO_V}" >> "$GITEA_OUTPUT" + # The tag is the source of truth — inject it into the binary. LDFLAGS="-s -w -X sourcedock.dev/petrbalvin/nuntius/internal/version.Version=${VERSION_NO_V}" mkdir -p bin GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} CGO_ENABLED=0 \ @@ -60,6 +60,7 @@ jobs: -o "bin/nuntius-${VERSION_NO_V}-${{ matrix.goos }}-${{ matrix.goarch }}" \ ./cmd/server + # Artifacts stay on v3 — v4 detects Gitea as GHES and aborts. - name: Upload artifact uses: actions/upload-artifact@v3 with: @@ -67,6 +68,7 @@ jobs: path: bin/nuntius-${{ steps.build.outputs.version_no_v }}-${{ matrix.goos }}-${{ matrix.goarch }} if-no-files-found: error + # Only binaries matching the runner can be smoke-tested. - name: Smoke test if: matrix.goos == 'linux' && matrix.goarch == 'amd64' run: | @@ -76,8 +78,10 @@ jobs: release: runs-on: fedora needs: build + permissions: + releases: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - name: Download all artifacts uses: actions/download-artifact@v3 @@ -125,16 +129,15 @@ jobs: -d "{\"tag_name\":\"${GITEA_REF_NAME}\",\"name\":\"${GITEA_REF_NAME}\",\"body\":${BODY},\"draft\":false,\"prerelease\":false}") http_code=$(echo "$response" | tail -1) - body=$(echo "$response" | sed '$d') + payload=$(echo "$response" | sed '$d') echo "HTTP ${http_code}" - if [ "$http_code" != "201" ]; then - echo "Failed to create release: ${body}" + echo "Failed to create release: ${payload}" exit 1 fi - RELEASE_ID=$(echo "$body" | grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 | grep -oE '[0-9]+') + RELEASE_ID=$(echo "$payload" | grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 | grep -oE '[0-9]+') echo "Created release ID=${RELEASE_ID}" printf '%s' "${RELEASE_ID}" > release-id.txt diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index f042599..6e84ab3 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -1,3 +1,4 @@ +# Test — Go. Runs on push and pull request to development. Never on main. name: Test on: @@ -10,9 +11,9 @@ jobs: vet: runs-on: fedora steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: "1.26" @@ -20,12 +21,11 @@ jobs: run: go mod download - name: gofmt - # `gofmt -l` prints the names of unformatted files. An empty - # output is the only acceptable result. + # gofmt -l prints unformatted files; an empty output is the only pass. run: | - unformatted=$(gofmt -l cmd internal pkg) + unformatted=$(gofmt -l .) if [ -n "$unformatted" ]; then - echo "The following files need gofmt:" + echo "These files need gofmt:" echo "$unformatted" exit 1 fi @@ -37,36 +37,44 @@ jobs: runs-on: fedora needs: vet steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: "1.26" - name: Download dependencies run: go mod download - - name: Install build tools + # The runner images have no gcc; the race detector needs CGO. + - name: Install gcc run: dnf install -y gcc - name: go test -race run: go test -race -count=1 ./... - - name: Check coverage threshold + # Coverage is measured over the library packages; cmd/ is thin glue. + - name: Coverage gate — 80 % minimum run: | + set -euo pipefail go test -coverprofile=coverage.out ./internal/... ./pkg/... - go tool cover -func=coverage.out | grep '^total:' | python3 -c "import sys; pct=float(sys.stdin.read().split()[2].rstrip('%')); sys.exit(0 if pct >= 80 else 1)" || (echo "ERROR: coverage < 80%"; exit 1) + coverage=$(go tool cover -func=coverage.out | awk '/^total:/ { gsub("%", "", $3); print $3 }') + echo "Total coverage: ${coverage}%" + if awk -v c="$coverage" 'BEGIN { exit !(c+0 < 80) }'; then + echo "ERROR: coverage ${coverage}% is below the 80% threshold" + exit 1 + fi - - name: go test ./examples + - name: Build examples run: go build ./examples/... build: runs-on: fedora needs: test steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: "1.26" @@ -76,8 +84,5 @@ jobs: - name: Build run: go build -ldflags="-s -w" -o bin/nuntius ./cmd/server - - name: Test - run: go test ./... - - name: Smoke test run: ./bin/nuntius --version