From 4a03d58193cd870f2dbab91c0bf6fb06cf1f1328 Mon Sep 17 00:00:00 2001 From: "a.gritsenko" Date: Sat, 3 Oct 2026 10:29:51 +0300 Subject: [PATCH] CI: release every push to main with the next patch tag Pushes to main get the next vX.Y.(Z+1) tag, are built with that version and published as a Gitea release with the deb/rpm and commit subjects as notes. Manual v* tags still release that exact version; already attached assets are skipped so a tag-triggered rerun does not duplicate them. Co-Authored-By: Claude Opus 5.5 --- .gitea/workflows/build.yml | 60 ++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index cada12b..b91e57e 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -1,5 +1,8 @@ name: build +# Every push to main is released: it gets the next patch tag (v0.1.3 -> v0.1.4) +# and a Gitea release with the deb/rpm. Pushing a v* tag by hand releases that +# exact version instead (use it to bump minor/major). on: push: branches: ["**"] @@ -14,6 +17,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: https://gitea.com/actions/checkout@v4 + with: + fetch-depth: 0 # tags + history for the version and release notes - uses: https://gitea.com/actions/setup-go@v5 with: @@ -24,6 +29,27 @@ jobs: go vet ./... go test ./... + - name: release version + id: ver + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) + run: | + set -euo pipefail + git fetch --tags --force -q + if [[ "$GITHUB_REF" == refs/tags/* ]]; then + tag="${GITHUB_REF#refs/tags/}" + else + # re-run of an already released commit keeps its tag + tag=$(git tag --points-at HEAD | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1 || true) + if [ -z "$tag" ]; then + last=$(git tag | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -1 || true) + IFS=. read -r major minor patch <<<"${last:-v0.0.0}" + tag="${major}.${minor}.$((patch + 1))" + fi + fi + echo "release $tag" + echo "tag=$tag" >> "$GITHUB_OUTPUT" + echo "VERSION=${tag#v}" >> "$GITHUB_ENV" + - name: install nfpm run: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest @@ -42,31 +68,41 @@ jobs: dist/*.rpm - name: publish release - if: startsWith(github.ref, 'refs/tags/') + if: steps.ver.outputs.tag != '' env: GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} API: ${{ github.api_url }}/repos/${{ github.repository }} + TAG: ${{ steps.ver.outputs.tag }} run: | set -euo pipefail - tag="${GITHUB_REF#refs/tags/}" + auth="Authorization: token $GITEA_TOKEN" - release_id=$(curl -sf -X POST "$API/releases" \ - -H "Authorization: token $GITEA_TOKEN" \ - -H "Content-Type: application/json" \ - -d "{\"tag_name\":\"$tag\",\"name\":\"$tag\"}" \ + # release notes: commit subjects since the previous release tag + prev=$(git tag --merged HEAD | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | grep -vx "$TAG" | sort -V | tail -1 || true) + git log --no-merges --pretty='- %s' ${prev:+"$prev"..}HEAD > notes.md + body=$(python3 -c 'import json,os,sys; print(json.dumps({"tag_name": os.environ["TAG"], "name": os.environ["TAG"], "target_commitish": os.environ["GITHUB_SHA"], "body": open("notes.md").read()}))') + + # creating the release also creates the tag on this commit + release_id=$(curl -sf -X POST "$API/releases" -H "$auth" \ + -H "Content-Type: application/json" -d "$body" \ | grep -oP '"id":\s*\K[0-9]+' | head -1) || \ - release_id=$(curl -sf "$API/releases/tags/$tag" \ - -H "Authorization: token $GITEA_TOKEN" \ + release_id=$(curl -sf "$API/releases/tags/$TAG" -H "$auth" \ | grep -oP '"id":\s*\K[0-9]+' | head -1) if [ -z "$release_id" ]; then - echo "could not create or find a release for tag $tag" >&2 + echo "could not create or find a release for tag $TAG" >&2 exit 1 fi + existing=$(curl -sf "$API/releases/$release_id/assets" -H "$auth" || true) for f in dist/*.deb dist/*.rpm; do [ -e "$f" ] || continue - curl -sf -X POST "$API/releases/$release_id/assets?name=$(basename "$f")" \ - -H "Authorization: token $GITEA_TOKEN" \ - -F "attachment=@${f}" + name=$(basename "$f") + if grep -q "\"name\":\"$name\"" <<<"$existing"; then + echo "$name already attached" + continue + fi + curl -sf -X POST "$API/releases/$release_id/assets?name=$name" \ + -H "$auth" -F "attachment=@${f}" done + echo "released $TAG: ${{ github.server_url }}/${{ github.repository }}/releases/tag/$TAG"