#!/usr/bin/env bash # release.sh — update version.yaml, package configs, create Forgejo Release set -euo pipefail TAG="$1" VER="${TAG#v}" echo "==> release: tag=${TAG} version=${VER}" # Extract release notes from CHANGELOG.md (first summary line of the latest section) RELEASE_NOTES=$(python3 - <<'PYEOF' import re, sys try: with open('CHANGELOG.md') as f: content = f.read() parts = re.split(r'\n## ', '\n' + content) if len(parts) > 1: section = parts[1] lines = section.strip().split('\n') notes = [] for line in lines[1:]: stripped = line.strip() # 只在遇到同级 ## 时停止,### 子标题保留 if stripped.startswith('## '): break if stripped: notes.append(stripped) print('\n'.join(notes) if notes else lines[0]) else: print('') except Exception as e: print('', file=sys.stderr) print('') PYEOF ) echo "==> release: release_notes=${RELEASE_NOTES}" # Update backend/config/version.yaml (version, build_number, release_notes, macos/windows URL) python3 - "${VER}" "${RELEASE_NOTES}" "${TAG}" "${FORGEJO_URL}" "${GITEA_REPOSITORY}" <<'PYEOF' import sys ver = sys.argv[1] notes = sys.argv[2] tag = sys.argv[3] furl = sys.argv[4].rstrip('/') repo = sys.argv[5] # Public download URLs are served by jiu.51yanmei.com (same-origin HTTPS via the # pangolin nginx /downloads/ location), NOT the LAN-only HTTP Forgejo instance — # otherwise the HTTPS download page hands the browser an http://192.168.x URL and # Chrome blocks it as insecure / it's unreachable from the public internet. base = "https://jiu.51yanmei.com/downloads" mac_url = f"{base}/jiu-macos-x64.zip" win_url = f"{base}/jiu-windows-x64-setup.exe" android_url = f"{base}/jiu-android.apk" lines = [] with open('backend/config/version.yaml') as f: for line in f: if line.startswith('version:'): lines.append('version: "' + ver + '"\n') elif line.startswith('build_number:'): try: build = int(line.split(':', 1)[1].strip()) + 1 except Exception: build = 1 lines.append('build_number: ' + str(build) + '\n') elif line.startswith('release_notes:'): lines.append('release_notes: "' + notes.replace('\\', '\\\\').replace('"', '\\"') + '"\n') elif line.startswith(' macos:'): lines.append(' macos: "' + mac_url + '"\n') elif line.startswith(' windows:'): lines.append(' windows: "' + win_url + '"\n') elif line.startswith(' android:'): lines.append(' android: "' + android_url + '"\n') else: lines.append(line) with open('backend/config/version.yaml', 'w') as f: f.writelines(lines) print('version.yaml updated to', ver, '| macos:', mac_url, '| windows:', win_url, '| android:', android_url) PYEOF # Package configs.tar.gz (includes updated version.yaml) tar -czf dist/configs.tar.gz \ deploy/nginx-jiu.conf \ deploy/jiu.service \ deploy/production.env.template \ deploy/setup-ec2.sh \ deploy/docker-compose.yml \ deploy/docker-compose.jiu.yml \ backend/config/version.yaml echo "==> release: creating Forgejo Release ${TAG}" # Build release body from CHANGELOG excerpt BODY=$(python3 - "${TAG}" "${RELEASE_NOTES}" <<'PYEOF' import sys, json tag = sys.argv[1] notes = sys.argv[2] body = '## ' + tag + '\n\n' + notes print(json.dumps(body)) PYEOF ) HTTP_CODE=$(curl -k -w "%{http_code}" -o /tmp/release_resp.json \ -X POST "${FORGEJO_URL}/api/v1/repos/${GITEA_REPOSITORY}/releases" \ -H "Authorization: token ${FORGEJO_TOKEN}" \ -H "Content-Type: application/json" \ -d "{\"tag_name\":\"${TAG}\",\"name\":\"Release ${TAG}\",\"body\":${BODY},\"draft\":false,\"prerelease\":false}") RESP=$(cat /tmp/release_resp.json) echo "==> release: API response (HTTP ${HTTP_CODE}): ${RESP}" if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 300 ]; then echo "==> release: FAILED — HTTP ${HTTP_CODE}" exit 1 fi RELEASE_ID=$(python3 -c "import sys,json; print(json.load(sys.stdin)['id'])" <<< "${RESP}") echo "==> release: release_id=${RELEASE_ID}" # Upload assets upload_asset() { local file="$1" local code code=$(curl -k -w "%{http_code}" -o /tmp/upload_resp.json \ -X POST "${FORGEJO_URL}/api/v1/repos/${GITEA_REPOSITORY}/releases/${RELEASE_ID}/assets" \ -H "Authorization: token ${FORGEJO_TOKEN}" \ -F "attachment=@${file}") echo "==> release: uploaded ${file} (HTTP ${code}): $(cat /tmp/upload_resp.json)" if [ "$code" -lt 200 ] || [ "$code" -ge 300 ]; then exit 1; fi } upload_asset dist/jiu-server upload_asset dist/web.tar.gz upload_asset dist/marketing.tar.gz upload_asset dist/configs.tar.gz upload_asset dist/jiu-macos-x64.zip upload_asset dist/jiu-windows-x64-setup.exe upload_asset dist/jiu-android.apk echo "==> release: done — Release ${TAG} created"