name: Release on: push: tags: ["v*"] jobs: release: runs-on: fedora steps: - uses: actions/checkout@v4 - name: Verify tag and extract CHANGELOG section env: VERSION: ${{ gitea.ref_name }} run: | set -euo pipefail 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 "Looking for CHANGELOG section: ${VERSION_NO_V}" sed -n "/^## \[${VERSION_NO_V}\] /,/^## \[/p" CHANGELOG.md \ | sed '$d' \ | tail -n +2 \ > release-body.md if [ ! -s release-body.md ]; then echo "ERROR: no CHANGELOG section found for ${VERSION_NO_V}" echo "Expected a heading like: ## [${VERSION_NO_V}] — YYYY-MM-DD" exit 1 fi echo "Release body preview:" head -n 20 release-body.md - name: Create release env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | set -euo pipefail # JSON-escape the release body with sed: backslashes first, then # quotes, tabs, and carriage returns, and finally fold newlines into # \n. Wrap the result in quotes to form a JSON string. BODY=$(sed -e 's/\\/\\\\/g' \ -e 's/"/\\"/g' \ -e 's/\t/\\t/g' \ -e 's/\r//g' \ release-body.md \ | sed ':a;N;$!ba;s/\n/\\n/g') BODY="\"${BODY}\"" response=$(curl -sS -w '\n%{http_code}' \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -X POST \ "${GITEA_SERVER_URL}/api/v1/repos/${GITEA_REPOSITORY}/releases" \ -d "{ \"tag_name\": \"${GITEA_REF_NAME}\", \"name\": \"${GITEA_REF_NAME}\", \"body\": ${BODY}, \"draft\": false, \"prerelease\": false }") http_code=$(echo "$response" | tail -1) payload=$(echo "$response" | sed '$d') echo "HTTP ${http_code}" if [ "$http_code" != "201" ]; then echo "Failed to create release: ${payload}" exit 1 fi RELEASE_ID=$(echo "$payload" | grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 | grep -oE '[0-9]+') echo "Release ${GITEA_REF_NAME} is live (ID=${RELEASE_ID})."