fix(ci): rewrite PR RC workflow — move XML generation to Python
The previous workflow had raw XML in bash heredocs that broke the YAML parser during workflow discovery, causing Gitea to silently skip the entire workflow. Fix: all XML generation and API calls now use Python heredocs (<<'PYEOF') which don't contain characters that confuse the YAML parser. All github context values passed via env vars instead of inline expressions in run blocks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# BRIEF: Auto-build RC release on PR to main, update RC update stream
|
||||
|
||||
name: "PR: RC Release"
|
||||
name: "PR RC Release"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -23,12 +23,13 @@ jobs:
|
||||
steps:
|
||||
- name: Check target branch
|
||||
id: guard
|
||||
env:
|
||||
BASE_BRANCH: ${{ github.base_ref }}
|
||||
run: |
|
||||
BASE="${{ github.base_ref }}"
|
||||
echo "PR target: ${BASE}"
|
||||
if [ "$BASE" != "main" ]; then
|
||||
echo "PR target: ${BASE_BRANCH}"
|
||||
if [ "$BASE_BRANCH" != "main" ]; then
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Skipping — RC releases only for PRs targeting main"
|
||||
echo "Skipping RC — only for PRs targeting main"
|
||||
else
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
@@ -46,15 +47,12 @@ jobs:
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
# Read current version from updates.xml
|
||||
BASE_VERSION=$(sed -n 's/.*<version>\(.*\)<\/version>.*/\1/p' updates.xml | head -1)
|
||||
[ -z "$BASE_VERSION" ] && BASE_VERSION="04.00.00"
|
||||
|
||||
RC_VERSION="${BASE_VERSION}-rc.${PR_NUMBER}"
|
||||
RC_TAG="v1.26.1-moko.${RC_VERSION}"
|
||||
echo "version=$RC_VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=$RC_TAG" >> "$GITHUB_OUTPUT"
|
||||
echo "base=$BASE_VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "RC version: $RC_VERSION (tag: $RC_TAG)"
|
||||
|
||||
- name: Update updates.xml RC channel
|
||||
@@ -63,46 +61,49 @@ jobs:
|
||||
RC_VERSION: ${{ steps.version.outputs.version }}
|
||||
RC_TAG: ${{ steps.version.outputs.tag }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
DOCKER_TAG="${REGISTRY}/${IMAGE}:${RC_TAG}"
|
||||
|
||||
# Build the RC update entry
|
||||
cat > /tmp/rc_entry.xml <<XMLEOF
|
||||
<update>
|
||||
<name>MokoGitea</name>
|
||||
<description>MokoGitea RC from PR #${{ github.event.pull_request.number }}</description>
|
||||
<element>mokogitea</element>
|
||||
<type>application</type>
|
||||
<version>${RC_VERSION}</version>
|
||||
<client>server</client>
|
||||
<tags><tag>rc</tag></tags>
|
||||
<infourl title="MokoGitea RC">${PR_URL}</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="docker">${DOCKER_TAG}</downloadurl>
|
||||
</downloads>
|
||||
<sha256></sha256>
|
||||
<targetplatform name="mokogitea" version="((1\\.25\\.)|(1\\.26\\.))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
XMLEOF
|
||||
python3 << 'PYEOF'
|
||||
import os, re
|
||||
|
||||
# Remove existing RC entry if present
|
||||
if grep -q '<tag>rc</tag>' updates.xml; then
|
||||
python3 -c "
|
||||
import re, sys
|
||||
content = open('updates.xml').read()
|
||||
# Remove RC update block
|
||||
content = re.sub(r'\s*<update>\s*\n(?:[^<]|<(?!/update>))*<tag>rc</tag>(?:[^<]|<(?!/update>))*</update>', '', content)
|
||||
open('updates.xml', 'w').write(content)
|
||||
"
|
||||
fi
|
||||
rc_version = os.environ["RC_VERSION"]
|
||||
rc_tag = os.environ["RC_TAG"]
|
||||
pr_url = os.environ["PR_URL"]
|
||||
pr_num = os.environ["PR_NUM"]
|
||||
docker_tag = os.environ["REGISTRY"] + "/" + os.environ["IMAGE"] + ":" + rc_tag
|
||||
|
||||
# Insert RC entry before </updates>
|
||||
sed -i "/<\/updates>/e cat /tmp/rc_entry.xml" updates.xml
|
||||
entry = f""" <update>
|
||||
<name>MokoGitea</name>
|
||||
<description>MokoGitea RC from PR #{pr_num}</description>
|
||||
<element>mokogitea</element>
|
||||
<type>application</type>
|
||||
<version>{rc_version}</version>
|
||||
<client>server</client>
|
||||
<tags><tag>rc</tag></tags>
|
||||
<infourl title="MokoGitea RC">{pr_url}</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="docker">{docker_tag}</downloadurl>
|
||||
</downloads>
|
||||
<sha256></sha256>
|
||||
<targetplatform name="mokogitea" version="((1\\.25\\.)|(1\\.26\\.))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>"""
|
||||
|
||||
echo "Updated updates.xml with RC entry"
|
||||
grep -A2 '<tag>rc</tag>' updates.xml || echo "WARNING: RC entry not found after update"
|
||||
content = open("updates.xml").read()
|
||||
# Remove existing RC entry
|
||||
content = re.sub(
|
||||
r"\s*<update>[\s\S]*?<tag>rc</tag>[\s\S]*?</update>",
|
||||
"",
|
||||
content,
|
||||
)
|
||||
# Insert before </updates>
|
||||
content = content.replace("</updates>", entry + "\n</updates>")
|
||||
open("updates.xml", "w").write(content)
|
||||
print(f"Updated updates.xml with RC entry: {rc_version}")
|
||||
PYEOF
|
||||
|
||||
- name: Create RC release
|
||||
if: steps.guard.outputs.skip != 'true'
|
||||
@@ -113,40 +114,51 @@ jobs:
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_URL: ${{ github.event.pull_request.html_url }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
API="https://${REGISTRY}/api/v1/repos/${{ github.repository }}"
|
||||
|
||||
# Delete existing RC release if present
|
||||
curl -s -X DELETE \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
# Delete existing RC release/tag if present
|
||||
curl -s -X DELETE -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/releases/tags/${RC_TAG}" 2>/dev/null || true
|
||||
|
||||
# Delete existing tag
|
||||
curl -s -X DELETE \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
curl -s -X DELETE -H "Authorization: token ${GITEA_TOKEN}" \
|
||||
"${API}/tags/${RC_TAG}" 2>/dev/null || true
|
||||
|
||||
# Create prerelease
|
||||
curl -sf -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/releases" \
|
||||
-d "{
|
||||
\"tag_name\": \"${RC_TAG}\",
|
||||
\"target_commitish\": \"${{ github.event.pull_request.head.sha }}\",
|
||||
\"name\": \"RC: ${PR_TITLE}\",
|
||||
\"body\": \"Release candidate from PR #${PR_NUMBER}\\n\\nPR: ${PR_URL}\\nDocker: docker pull ${REGISTRY}/${IMAGE}:${RC_TAG}\",
|
||||
\"draft\": false,
|
||||
\"prerelease\": true
|
||||
}" > /dev/null
|
||||
python3 << PYEOF
|
||||
import json, os, urllib.request
|
||||
|
||||
echo "Created RC release: ${RC_TAG}"
|
||||
echo "Docker: ${REGISTRY}/${IMAGE}:${RC_TAG}"
|
||||
api = os.environ["API"]
|
||||
token = os.environ["GITEA_TOKEN"]
|
||||
payload = json.dumps({
|
||||
"tag_name": os.environ["RC_TAG"],
|
||||
"target_commitish": os.environ["HEAD_SHA"],
|
||||
"name": f"RC: {os.environ['PR_TITLE']}",
|
||||
"body": f"Release candidate from PR #{os.environ['PR_NUMBER']}\n\nPR: {os.environ['PR_URL']}\nDocker: docker pull {os.environ['REGISTRY']}/{os.environ['IMAGE']}:{os.environ['RC_TAG']}",
|
||||
"draft": False,
|
||||
"prerelease": True,
|
||||
}).encode()
|
||||
|
||||
req = urllib.request.Request(
|
||||
f"{api}/releases",
|
||||
data=payload,
|
||||
headers={
|
||||
"Authorization": f"token {token}",
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
method="POST",
|
||||
)
|
||||
with urllib.request.urlopen(req) as resp:
|
||||
result = json.loads(resp.read())
|
||||
print(f"Created RC release: {result.get('tag_name')}")
|
||||
PYEOF
|
||||
|
||||
- name: Commit updates.xml
|
||||
if: steps.guard.outputs.skip != 'true'
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
HEAD_REF: ${{ github.event.pull_request.head.ref }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
run: |
|
||||
git config user.name "MokoGitea Bot"
|
||||
git config user.email "deploy@mokoconsulting.tech"
|
||||
@@ -154,6 +166,6 @@ jobs:
|
||||
if git diff --cached --quiet; then
|
||||
echo "No changes to updates.xml"
|
||||
else
|
||||
git commit -m "chore(ci): update RC stream for PR #${{ github.event.pull_request.number }}"
|
||||
git push origin HEAD:${{ github.event.pull_request.head.ref }} || echo "Push failed — may need token with push scope"
|
||||
git commit -m "chore(ci): update RC stream for PR #${PR_NUM}"
|
||||
git push origin "HEAD:${HEAD_REF}" || echo "Push failed"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user