Files
claude-code-facts/gitea-release-workflow.md
alexei.dolgolyov 9bbe7cb24c docs: add minimal Gitea release workflow document
Standalone workflow: push v* tag → create Gitea release with
optional RELEASE_NOTES.md. No builds or artifacts — just the
release entry. Links to full CI/CD guide for extensions.
2026-03-26 00:34:17 +03:00

3.9 KiB

Gitea Release Workflow (Minimal)

Minimal Gitea Actions workflow: push a v* tag → create a Gitea release with optional release notes from RELEASE_NOTES.md.

No build jobs, no artifacts, no Docker — just a release entry on the Gitea Releases page.

For the full CI/CD pipeline (builds, installers, Docker), see gitea-python-ci-cd.md.

Complete Workflow

.gitea/workflows/release.yml:

name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - name: Fetch RELEASE_NOTES.md only
        uses: actions/checkout@v4
        with:
          sparse-checkout: RELEASE_NOTES.md
          sparse-checkout-cone-mode: false

      - name: Create Gitea release
        env:
          DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
        run: |
          TAG="${{ gitea.ref_name }}"
          VERSION="${TAG#v}"
          BASE_URL="${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}"

          # Detect pre-release (alpha/beta/rc)
          IS_PRE="false"
          if echo "$TAG" | grep -qE '(alpha|beta|rc)'; then
            IS_PRE="true"
          fi

          # Read release notes if present
          if [ -f RELEASE_NOTES.md ]; then
            export RELEASE_NOTES=$(cat RELEASE_NOTES.md)
            echo "Found RELEASE_NOTES.md"
          else
            export RELEASE_NOTES=""
            echo "No RELEASE_NOTES.md found — release will have no body"
          fi

          BODY_JSON=$(python3 -c "
          import json, os
          notes = os.environ.get('RELEASE_NOTES', '')
          print(json.dumps(notes.strip()))
          ")

          # Create release via Gitea API
          RELEASE=$(curl -s -X POST "$BASE_URL/releases" \
            -H "Authorization: token $DEPLOY_TOKEN" \
            -H "Content-Type: application/json" \
            -d "{
              \"tag_name\": \"$TAG\",
              \"name\": \"$VERSION\",
              \"body\": $BODY_JSON,
              \"draft\": false,
              \"prerelease\": $IS_PRE
            }")

          # Fallback: if release already exists for this tag, reuse it
          RELEASE_ID=$(echo "$RELEASE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" 2>/dev/null)
          if [ -z "$RELEASE_ID" ]; then
            echo "::warning::Release already exists for tag $TAG — reusing existing release"
            RELEASE=$(curl -s "$BASE_URL/releases/tags/$TAG" \
              -H "Authorization: token $DEPLOY_TOKEN")
            RELEASE_ID=$(echo "$RELEASE" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
          fi
          echo "Created release $RELEASE_ID for $TAG"

Setup

  1. Create a Gitea token with write:repository permission
  2. Add secret in repo Settings → Secrets: DEPLOY_TOKEN = your token
  3. Tag and push:
git tag v1.0.0
git push origin v1.0.0

Release Notes (Optional)

To include release notes, create RELEASE_NOTES.md in the repo root before tagging:

### What's New

- Added feature X
- Fixed bug Y

If the file is absent, the release is created with an empty body — useful for quick pre-releases.

Why sparse-checkout? The workflow only needs one file. Sparse-checkout skips downloading the full repo, making the step faster — especially in large repos.

Pre-releases

Tags containing alpha, beta, or rc are automatically marked as pre-release:

Tag Pre-release?
v1.0.0 No
v1.0.0-alpha.1 Yes
v1.0.0-beta.2 Yes
v1.0.0-rc.1 Yes

Extending

This workflow is intentionally minimal. Common additions:

  • Build artifacts — add parallel jobs that upload assets to the release (see gitea-python-ci-cd.md)
  • Docker push — build and push images after tagging
  • Portainer webhook — auto-redeploy after docker push
  • Changelog generation — auto-generate from git log between tags