name: Release "on": push: tags: - "**" permissions: contents: write releases: write jobs: release: runs-on: ubuntu-latest if: startsWith(github.ref, 'refs/tags/') steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Extract changelog and update CHANGELOG.md id: changelog env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} shell: bash run: | set -euo pipefail current_tag="${GITHUB_REF_NAME}" today=$(date +%Y-%m-%d) # Extract content of [Unreleased] section (non-empty lines) release_notes=$(awk '/^## \[Unreleased\]/{found=1; next} found && /^## \[/{exit} found{print}' CHANGELOG.md | sed '/^[[:space:]]*$/d') if [ -z "${release_notes}" ]; then release_notes="Voir les commits pour le détail des changements." fi printf '%s\n' "${release_notes}" > release_notes.md # For stable releases: rename [Unreleased] and insert a new empty section case "${current_tag}" in *-rc*|*-beta*|*-alpha*) echo "Pre-release tag — CHANGELOG.md non modifié" ;; *) # Rename [Unreleased] → version header sed -i "s/^## \[Unreleased\]$/## [${current_tag}] — ${today}/" CHANGELOG.md # Insert new empty [Unreleased] section after "# Changelog" sed -i "s/^# Changelog$/# Changelog\n\n## [Unreleased]/" CHANGELOG.md # Insert reference link before the first existing [vX...] link awk -v tag="${current_tag}" -v url="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/releases/tag/${current_tag}" ' !inserted && /^\[v/ { print "[" tag "]: " url; inserted=1 } { print } ' CHANGELOG.md > CHANGELOG.tmp && mv CHANGELOG.tmp CHANGELOG.md git config user.name "CI" git config user.email "ci@forge.lclr.dev" scheme="${GITHUB_SERVER_URL%%://*}" host="${GITHUB_SERVER_URL#*://}" git remote set-url origin "${scheme}://x-token:${GITEA_TOKEN}@${host}/${GITHUB_REPOSITORY}.git" git add CHANGELOG.md git commit -m "chore(changelog): release ${current_tag}" git push origin HEAD:main ;; esac - name: Create or update release env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} shell: bash run: | set -euo pipefail current_tag="${GITHUB_REF_NAME}" api_url="${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases" release_by_tag_url="${api_url}/tags/${current_tag}" prerelease=false case "${current_tag}" in *-rc*|*-beta*|*-alpha*) prerelease=true ;; esac # Build commit log since previous stable tag previous_stable_tag="" if previous_stable_tag="$( git describe --tags --abbrev=0 \ --exclude '*-rc*' \ --exclude '*-beta*' \ --exclude '*-alpha*' \ "${current_tag}^" 2>/dev/null )"; then range="${previous_stable_tag}..${current_tag}" else range="${current_tag}" fi { cat release_notes.md printf '\n\n## Commits\n\n' git log --reverse --pretty=format:'- %h %s' "${range}" printf '\n' } > release_body.md json_escape() { sed ':a;N;$!ba;s/\\/\\\\/g;s/"/\\"/g;s/\t/\\t/g;s/\r//g;s/\n/\\n/g' } body="$(json_escape < release_body.md)" payload="$(printf '{"tag_name":"%s","name":"%s","body":"%s","draft":false,"prerelease":%s}' \ "${current_tag}" \ "${current_tag}" \ "${body}" \ "${prerelease}")" http_code="$( curl --silent --show-error --output release.json --write-out '%{http_code}' \ --header "Authorization: token ${GITEA_TOKEN}" \ --header 'Accept: application/json' \ "${release_by_tag_url}" )" case "${http_code}" in 200) release_id="$( tr '{,' '\n' < release.json | sed -n 's/^[[:space:]]*"id":[[:space:]]*\([0-9][0-9]*\)$/\1/p' | head -n1 )" if [ -z "${release_id}" ]; then echo "failed to parse release id from existing release response" >&2 exit 1 fi curl --silent --show-error --fail \ --request PATCH \ --header "Authorization: token ${GITEA_TOKEN}" \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data "${payload}" \ "${api_url}/${release_id}" >/dev/null ;; 404) curl --silent --show-error --fail \ --request POST \ --header "Authorization: token ${GITEA_TOKEN}" \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data "${payload}" \ "${api_url}" >/dev/null ;; *) echo "unexpected status code while looking up release: ${http_code}" >&2 cat release.json >&2 exit 1 ;; esac