diff --git a/.github/workflows/auto-dev-issue.yml b/.github/workflows/auto-dev-issue.yml index 38730aba..38c6a538 100644 --- a/.github/workflows/auto-dev-issue.yml +++ b/.github/workflows/auto-dev-issue.yml @@ -156,30 +156,22 @@ jobs: done fi - # ── RC: Create or update draft release ──────────────────────────── + # ── RC: Create or update release-candidate release ────────────── if [[ "$BRANCH" == rc/* ]]; then - MAJOR=$(echo "$VERSION" | awk -F. '{print $1}') - RELEASE_TAG="v${MAJOR}" - DRAFT_EXISTS=$(gh release view "$RELEASE_TAG" --json isDraft -q .isDraft 2>/dev/null || true) + RELEASE_TAG="release-candidate" + EXISTING=$(gh release view "$RELEASE_TAG" --json tagName -q .tagName 2>/dev/null || true) - if [ -z "$DRAFT_EXISTS" ]; then - # No release exists — create draft + if [ -z "$EXISTING" ]; then gh release create "$RELEASE_TAG" \ - --title "v${MAJOR} (RC: ${VERSION})" \ + --title "release-candidate (${VERSION})" \ --notes "## Release Candidate ${VERSION}\n\nRC branch: \`${BRANCH}\`\nTracking issue: ${PARENT_URL}" \ - --draft \ + --prerelease \ --target main 2>/dev/null || true - echo "Draft release created: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY - elif [ "$DRAFT_EXISTS" = "true" ]; then - # Draft exists — update title - gh release edit "$RELEASE_TAG" \ - --title "v${MAJOR} (RC: ${VERSION})" --draft 2>/dev/null || true - echo "Draft release updated: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY + echo "RC release created: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY else - # Release exists and is published — set back to draft for RC gh release edit "$RELEASE_TAG" \ - --title "v${MAJOR} (RC: ${VERSION})" --draft 2>/dev/null || true - echo "Release ${RELEASE_TAG} set to draft for RC" >> $GITHUB_STEP_SUMMARY + --title "release-candidate (${VERSION})" --prerelease 2>/dev/null || true + echo "RC release updated: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY fi fi diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index 3e1caf3f..7564b6fa 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -316,54 +316,47 @@ jobs: DOWNLOAD_URL="https://github.com/${REPO}/releases/download/v${VERSION}/${EXT_ELEMENT}-${VERSION}.zip" INFO_URL="https://github.com/${REPO}/releases/tag/v${VERSION}" - # -- Build stable entry ────────────────────────────────────── - STABLE_ENTRY=$(cat < - ${EXT_NAME} - ${EXT_NAME} update - ${EXT_ELEMENT} - ${EXT_TYPE} - ${VERSION} - $([ -n "$CLIENT_TAG" ] && echo " ${CLIENT_TAG}") - $([ -n "$FOLDER_TAG" ] && echo " ${FOLDER_TAG}") - - stable - - ${INFO_URL} - - ${DOWNLOAD_URL} - - ${TARGET_PLATFORM} - $([ -n "$PHP_TAG" ] && echo " ${PHP_TAG}") - Moko Consulting - https://mokoconsulting.tech - -XMLEOF -) + # -- Build stable entry to temp file ───────────────────────── + { + printf '%s\n' ' ' + printf '%s\n' " ${EXT_NAME}" + printf '%s\n' " ${EXT_NAME} update" + printf '%s\n' " ${EXT_ELEMENT}" + printf '%s\n' " ${EXT_TYPE}" + printf '%s\n' " ${VERSION}" + [ -n "$CLIENT_TAG" ] && printf '%s\n' " ${CLIENT_TAG}" + [ -n "$FOLDER_TAG" ] && printf '%s\n' " ${FOLDER_TAG}" + printf '%s\n' ' ' + printf '%s\n' ' stable' + printf '%s\n' ' ' + printf '%s\n' " ${INFO_URL}" + printf '%s\n' ' ' + printf '%s\n' " ${DOWNLOAD_URL}" + printf '%s\n' ' ' + printf '%s\n' " ${TARGET_PLATFORM}" + [ -n "$PHP_TAG" ] && printf '%s\n' " ${PHP_TAG}" + printf '%s\n' ' Moko Consulting' + printf '%s\n' ' https://mokoconsulting.tech' + printf '%s\n' ' ' + } > /tmp/stable_entry.xml # -- Write updates.xml preserving dev/rc entries ────────────── - # Extract existing dev and rc entries if present RC_ENTRY="" DEV_ENTRY="" if [ -f "updates.xml" ]; then - RC_ENTRY=$(python3 -c " -import re -with open('updates.xml') as f: c = f.read() -m = re.search(r'( .*?rc.*?)', c, re.DOTALL) -if m: print(m.group(1)) -" 2>/dev/null || true) - DEV_ENTRY=$(python3 -c " -import re -with open('updates.xml') as f: c = f.read() -m = re.search(r'( .*?development.*?)', c, re.DOTALL) -if m: print(m.group(1)) -" 2>/dev/null || true) + printf 'import re\n' > /tmp/extract.py + printf 'with open("updates.xml") as f: c = f.read()\n' >> /tmp/extract.py + printf 'import sys; tag = sys.argv[1]\n' >> /tmp/extract.py + printf 'm = re.search(r"( .*?" + re.escape(tag) + r".*?)", c, re.DOTALL)\n' >> /tmp/extract.py + printf 'if m: print(m.group(1))\n' >> /tmp/extract.py + RC_ENTRY=$(python3 /tmp/extract.py rc 2>/dev/null || true) + DEV_ENTRY=$(python3 /tmp/extract.py development 2>/dev/null || true) fi { printf '%s\n' '' printf '%s\n' '' - echo "$STABLE_ENTRY" + cat /tmp/stable_entry.xml [ -n "$RC_ENTRY" ] && echo "$RC_ENTRY" [ -n "$DEV_ENTRY" ] && echo "$DEV_ENTRY" printf '%s\n' '' diff --git a/.github/workflows/update-server.yml b/.github/workflows/update-server.yml index fad30ff3..d8bf2566 100644 --- a/.github/workflows/update-server.yml +++ b/.github/workflows/update-server.yml @@ -23,6 +23,8 @@ on: push: branches: - 'dev/**' + - 'alpha/**' + - 'beta/**' - 'rc/**' paths: - 'src/**' @@ -30,12 +32,14 @@ on: workflow_dispatch: inputs: stability: - description: 'Stability tag (development, rc, stable)' + description: 'Stability tag' required: true default: 'development' type: choice options: - development + - alpha + - beta - rc - stable @@ -80,6 +84,10 @@ jobs: STABILITY="${{ inputs.stability }}" elif [[ "$BRANCH" == rc/* ]]; then STABILITY="rc" + elif [[ "$BRANCH" == beta/* ]]; then + STABILITY="beta" + elif [[ "$BRANCH" == alpha/* ]]; then + STABILITY="alpha" elif [[ "$BRANCH" == dev/* ]]; then STABILITY="development" else @@ -116,11 +124,24 @@ jobs: # Version suffix for non-stable DISPLAY_VERSION="$VERSION" - [ "$STABILITY" = "rc" ] && DISPLAY_VERSION="${VERSION}-rc" - [ "$STABILITY" = "development" ] && DISPLAY_VERSION="${VERSION}-dev" + case "$STABILITY" in + development) DISPLAY_VERSION="${VERSION}-dev" ;; + alpha) DISPLAY_VERSION="${VERSION}-alpha" ;; + beta) DISPLAY_VERSION="${VERSION}-beta" ;; + rc) DISPLAY_VERSION="${VERSION}-rc" ;; + esac MAJOR=$(echo "$VERSION" | awk -F. '{print $1}') - RELEASE_TAG="v${MAJOR}" + + # Each stability level has its own release tag + case "$STABILITY" in + development) RELEASE_TAG="development" ;; + alpha) RELEASE_TAG="alpha" ;; + beta) RELEASE_TAG="beta" ;; + rc) RELEASE_TAG="release-candidate" ;; + *) RELEASE_TAG="v${MAJOR}" ;; + esac + PACKAGE_NAME="${EXT_ELEMENT}-${DISPLAY_VERSION}.zip" DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${RELEASE_TAG}/${PACKAGE_NAME}" INFO_URL="https://github.com/${REPO}" @@ -137,7 +158,7 @@ jobs: # Ensure draft release exists for this major gh release view "$RELEASE_TAG" --json tagName > /dev/null 2>&1 || \ - gh release create "$RELEASE_TAG" --title "v${MAJOR}" --notes "Development release" --draft --target main 2>/dev/null || true + gh release create "$RELEASE_TAG" --title "${RELEASE_TAG} (${DISPLAY_VERSION})" --notes "${STABILITY} release" --prerelease --target main 2>/dev/null || true # Upload ZIP to the major release gh release upload "$RELEASE_TAG" "/tmp/${PACKAGE_NAME}" --clobber 2>/dev/null || true @@ -148,95 +169,63 @@ jobs: fi # ── Build the new entry ─────────────────────────────────────── - NEW_ENTRY=$(cat < - ${EXT_NAME} - ${EXT_NAME} (${STABILITY}) - ${EXT_ELEMENT} - ${EXT_TYPE} - ${DISPLAY_VERSION} - $([ -n "$CLIENT_TAG" ] && echo " ${CLIENT_TAG}") - $([ -n "$FOLDER_TAG" ] && echo " ${FOLDER_TAG}") - - ${STABILITY} - - ${INFO_URL} - - ${DOWNLOAD_URL} - - $([ -n "$SHA256" ] && echo " sha256:${SHA256}") - ${TARGET_PLATFORM} - $([ -n "$PHP_TAG" ] && echo " ${PHP_TAG}") - Moko Consulting - https://mokoconsulting.tech - -XMLEOF -) + NEW_ENTRY="" + NEW_ENTRY="${NEW_ENTRY} \n" + NEW_ENTRY="${NEW_ENTRY} ${EXT_NAME}\n" + NEW_ENTRY="${NEW_ENTRY} ${EXT_NAME} (${STABILITY})\n" + NEW_ENTRY="${NEW_ENTRY} ${EXT_ELEMENT}\n" + NEW_ENTRY="${NEW_ENTRY} ${EXT_TYPE}\n" + NEW_ENTRY="${NEW_ENTRY} ${DISPLAY_VERSION}\n" + [ -n "$CLIENT_TAG" ] && NEW_ENTRY="${NEW_ENTRY} ${CLIENT_TAG}\n" + [ -n "$FOLDER_TAG" ] && NEW_ENTRY="${NEW_ENTRY} ${FOLDER_TAG}\n" + NEW_ENTRY="${NEW_ENTRY} \n" + NEW_ENTRY="${NEW_ENTRY} ${STABILITY}\n" + NEW_ENTRY="${NEW_ENTRY} \n" + NEW_ENTRY="${NEW_ENTRY} ${INFO_URL}\n" + NEW_ENTRY="${NEW_ENTRY} \n" + NEW_ENTRY="${NEW_ENTRY} ${DOWNLOAD_URL}\n" + NEW_ENTRY="${NEW_ENTRY} \n" + [ -n "$SHA256" ] && NEW_ENTRY="${NEW_ENTRY} sha256:${SHA256}\n" + NEW_ENTRY="${NEW_ENTRY} ${TARGET_PLATFORM}\n" + [ -n "$PHP_TAG" ] && NEW_ENTRY="${NEW_ENTRY} ${PHP_TAG}\n" + NEW_ENTRY="${NEW_ENTRY} Moko Consulting\n" + NEW_ENTRY="${NEW_ENTRY} https://mokoconsulting.tech\n" + NEW_ENTRY="${NEW_ENTRY} " + + # ── Write new entry to temp file ─────────────────────────────── + printf '%b' "$NEW_ENTRY" > /tmp/new_entry.xml # ── Merge into updates.xml ───────────────────────────────────── if [ ! -f "updates.xml" ]; then - # Create fresh printf '%s\n' '' > updates.xml printf '%s\n' '' >> updates.xml - echo "$NEW_ENTRY" >> updates.xml - printf '%s\n' '' >> updates.xml + cat /tmp/new_entry.xml >> updates.xml + printf '\n%s\n' '' >> updates.xml else - # Remove existing entry for this stability, add new one - # Use python for reliable XML manipulation - python3 -c " -import re, sys - -with open('updates.xml', 'r') as f: - content = f.read() - -# Remove existing entry with this stability tag -pattern = r' .*?${STABILITY}.*?\n?' -content = re.sub(pattern, '', content, flags=re.DOTALL) - -# Insert new entry before -new_entry = '''${NEW_ENTRY}''' -content = content.replace('', new_entry + '\n') - -# Clean up empty lines -content = re.sub(r'\n{3,}', '\n\n', content) - -with open('updates.xml', 'w') as f: - f.write(content) -" 2>/dev/null || { - # Fallback: just rewrite the whole file if python fails - # Keep existing stable entry if present - STABLE_ENTRY="" - if [ "$STABILITY" != "stable" ] && grep -q 'stable' updates.xml; then - STABLE_ENTRY=$(sed -n '//,/<\/update>/{ /stable<\/tag>/,/<\/update>/p; //,/stable<\/tag>/p }' updates.xml | sort -u) - fi - RC_ENTRY="" - if [ "$STABILITY" != "rc" ] && grep -q 'rc' updates.xml; then - RC_ENTRY=$(python3 -c " -import re -with open('updates.xml') as f: c = f.read() -m = re.search(r'(.*?rc.*?)', c, re.DOTALL) -if m: print(m.group(1)) -" 2>/dev/null || true) - fi - DEV_ENTRY="" - if [ "$STABILITY" != "development" ] && grep -q 'development' updates.xml; then - DEV_ENTRY=$(python3 -c " -import re -with open('updates.xml') as f: c = f.read() -m = re.search(r'(.*?development.*?)', c, re.DOTALL) -if m: print(m.group(1)) -" 2>/dev/null || true) - fi - + # Remove existing entry for this stability, insert new one + printf 'import re\nstability = "%s"\n' "${STABILITY}" > /tmp/merge_xml.py + printf 'with open("updates.xml") as f: content = f.read()\n' >> /tmp/merge_xml.py + printf 'with open("/tmp/new_entry.xml") as f: new_entry = f.read()\n' >> /tmp/merge_xml.py + printf 'pattern = r" .*?" + re.escape(stability) + r".*?\\n?"\n' >> /tmp/merge_xml.py + printf 'content = re.sub(pattern, "", content, flags=re.DOTALL)\n' >> /tmp/merge_xml.py + printf 'content = content.replace("", new_entry + "\\n")\n' >> /tmp/merge_xml.py + printf 'content = re.sub(r"\\n{3,}", "\\n\\n", content)\n' >> /tmp/merge_xml.py + printf 'with open("updates.xml", "w") as f: f.write(content)\n' >> /tmp/merge_xml.py + python3 /tmp/merge_xml.py 2>/dev/null || { + # Fallback: rebuild keeping other stability entries { printf '%s\n' '' printf '%s\n' '' - [ -n "$STABLE_ENTRY" ] && echo "$STABLE_ENTRY" - [ -n "$RC_ENTRY" ] && echo "$RC_ENTRY" - [ -n "$DEV_ENTRY" ] && echo "$DEV_ENTRY" - echo "$NEW_ENTRY" - printf '%s\n' '' - } > updates.xml + for TAG in stable rc development; do + [ "$TAG" = "${STABILITY}" ] && continue + if grep -q "${TAG}" updates.xml 2>/dev/null; then + sed -n "//,/<\/update>/{ /${TAG}<\/tag>/p; }" updates.xml + fi + done + cat /tmp/new_entry.xml + printf '\n%s\n' '' + } > /tmp/updates_new.xml + mv /tmp/updates_new.xml updates.xml } fi