diff --git a/.gitea/workflows/auto-tag.yml b/.gitea/workflows/auto-tag.yml index 68fe05c4..d6f09447 100644 --- a/.gitea/workflows/auto-tag.yml +++ b/.gitea/workflows/auto-tag.yml @@ -134,24 +134,43 @@ jobs: env: RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }} run: | - set -eu + set -euo pipefail API="http://172.0.0.29:3000/api/v1/repos/$GITHUB_REPOSITORY" TAG=$(git describe --tags --abbrev=0) - # Get current file SHA from master (required by API if the file already exists) - CURRENT_SHA=$(curl -sf "$API/contents/CHANGELOG.md?ref=master" \ - -H "Authorization: token $RELEASE_TOKEN" | jq -r '.sha // empty') - # Base64-encode the generated file (no line wrapping) + # Validate tag format to prevent shell injection in commit message / JSON + if ! echo "$TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then + echo "ERROR: Unexpected tag format: $TAG" + exit 1 + fi + # Fetch current blob SHA from master; empty if file doesn't exist yet + CURRENT_SHA=$(curl -sf \ + -H "Accept: application/json" \ + -H "Authorization: token $RELEASE_TOKEN" \ + "$API/contents/CHANGELOG.md?ref=master" 2>/dev/null \ + | jq -r '.sha // empty' 2>/dev/null || true) + # Base64-encode content (no line wrapping) CONTENT=$(base64 -w 0 CHANGELOG.md) + # Build JSON payload — omit "sha" when file doesn't exist yet (new repo) + PAYLOAD=$(jq -n \ + --arg msg "chore: update CHANGELOG.md for ${TAG} [skip ci]" \ + --arg body "$CONTENT" \ + --arg sha "$CURRENT_SHA" \ + 'if $sha == "" + then {message: $msg, content: $body, branch: "master"} + else {message: $msg, content: $body, sha: $sha, branch: "master"} + end') # PUT atomically updates (or creates) the file on master — no fast-forward needed - curl -sf -X PUT "$API/contents/CHANGELOG.md" \ + RESP_FILE=$(mktemp) + HTTP_CODE=$(curl -s -o "$RESP_FILE" -w "%{http_code}" -X PUT \ -H "Authorization: token $RELEASE_TOKEN" \ -H "Content-Type: application/json" \ - -d "{ - \"message\": \"chore: update CHANGELOG.md for ${TAG} [skip ci]\", - \"content\": \"$CONTENT\", - \"sha\": \"$CURRENT_SHA\", - \"branch\": \"master\" - }" + -d "$PAYLOAD" \ + "$API/contents/CHANGELOG.md") + if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then + echo "ERROR: Failed to update CHANGELOG.md (HTTP $HTTP_CODE)" + cat "$RESP_FILE" >&2 + exit 1 + fi echo "✓ CHANGELOG.md committed to master" - name: Upload CHANGELOG.md as release asset