Merge pull request 'Release 02.09.00: CI fixes, update server standard, Joomla skill' (#44) from dev into main
Universal: Cascade Main → Dev / Cascade main → branches (push) Has been cancelled
Joomla: Repo Health / Access control (push) Has been cancelled
Joomla: Repo Health / Release configuration (push) Has been cancelled
Joomla: Repo Health / Scripts governance (push) Has been cancelled
Joomla: Repo Health / Repository health (push) Has been cancelled

This commit was merged in pull request #44.
This commit is contained in:
2026-05-26 04:37:36 +00:00
8 changed files with 1038 additions and 1141 deletions
+67 -162
View File
@@ -26,7 +26,8 @@
name: "Universal: Build & Release" name: "Universal: Build & Release"
on: on:
push: pull_request:
types: [closed]
branches: branches:
- main - main
paths: paths:
@@ -47,7 +48,8 @@ jobs:
release: release:
name: Build & Release Pipeline name: Build & Release Pipeline
runs-on: release runs-on: release
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' if: >-
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch'
steps: steps:
- name: Checkout repository - name: Checkout repository
@@ -94,9 +96,9 @@ jobs:
fi fi
MAJOR=$(echo "$VERSION" | cut -d. -f1) MAJOR=$(echo "$VERSION" | cut -d. -f1)
echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT" echo "release_tag=stable" >> "$GITHUB_OUTPUT"
echo "skip=false" >> "$GITHUB_OUTPUT" echo "skip=false" >> "$GITHUB_OUTPUT"
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT" echo "branch=main" >> "$GITHUB_OUTPUT"
- name: "Step 1b: Bump version" - name: "Step 1b: Bump version"
id: bump id: bump
@@ -261,6 +263,7 @@ jobs:
run: | run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}" VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
php /tmp/moko-platform-api/cli/badge_update.php --path . --version "${VERSION}" 2>/dev/null || true php /tmp/moko-platform-api/cli/badge_update.php --path . --version "${VERSION}" 2>/dev/null || true
php /tmp/moko-platform-api/cli/version_check.php --path . --fix 2>/dev/null || true
- name: "Step 5: Write update stream" - name: "Step 5: Write update stream"
if: >- if: >-
@@ -268,6 +271,15 @@ jobs:
steps.platform.outputs.platform == 'joomla' steps.platform.outputs.platform == 'joomla'
run: | run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}" VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
# Fetch latest updates.xml from main so preserve logic has all channels
GA_TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
curl -sf -H "Authorization: token ${GA_TOKEN}" \
"${API}/contents/updates.xml?ref=main" 2>/dev/null | \
python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin)['content']).decode())" \
> updates.xml 2>/dev/null || true
php /tmp/moko-platform-api/cli/updates_xml_build.php \ php /tmp/moko-platform-api/cli/updates_xml_build.php \
--path . --version "${VERSION}" --stability stable \ --path . --version "${VERSION}" --stability stable \
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \ --gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
@@ -295,9 +307,7 @@ jobs:
# -- STEP 6: Create tag --------------------------------------------------- # -- STEP 6: Create tag ---------------------------------------------------
- name: "Step 6: Create git tag" - name: "Step 6: Create git tag"
if: >- if: >-
steps.version.outputs.skip != 'true' && steps.version.outputs.skip != 'true'
steps.check.outputs.tag_exists != 'true' &&
steps.version.outputs.is_minor == 'true'
run: | run: |
RELEASE_TAG="${{ steps.version.outputs.release_tag }}" RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
# Only create the major release tag if it doesn't exist yet # Only create the major release tag if it doesn't exist yet
@@ -337,6 +347,8 @@ jobs:
[ -z "$NOTES" ] && NOTES="Release ${VERSION}" [ -z "$NOTES" ] && NOTES="Release ${VERSION}"
# Build release name: "Pretty Name VERSION (type_element-VERSION)" # Build release name: "Pretty Name VERSION (type_element-VERSION)"
# Strip existing type prefix to prevent duplication
EXT_ELEMENT=$(echo "$EXT_ELEMENT" | sed -E 's/^(pkg_|com_|mod_|plg_[a-z]+_|tpl_|lib_)//')
TYPE_PREFIX="" TYPE_PREFIX=""
case "${EXT_TYPE}" in case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;; plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
@@ -407,6 +419,13 @@ jobs:
# ZIP name: type_folder_element-VERSION (e.g. plg_system_mokojgdpc-01.01.00.zip) # ZIP name: type_folder_element-VERSION (e.g. plg_system_mokojgdpc-01.01.00.zip)
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1) EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
EXT_FOLDER=$(sed -n 's/.*<extension[^>]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1) EXT_FOLDER=$(sed -n 's/.*<extension[^>]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
# For packages, prefer <packagename> over filename-derived element
if [ "$EXT_TYPE" = "package" ]; then
PKG_NAME=$(sed -n 's/.*<packagename>\([^<]*\)<\/packagename>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
[ -n "$PKG_NAME" ] && EXT_ELEMENT="$PKG_NAME"
fi
# Strip existing type prefix to prevent duplication (e.g. pkg_mokowaas → mokowaas)
EXT_ELEMENT=$(echo "$EXT_ELEMENT" | sed -E 's/^(pkg_|com_|mod_|plg_[a-z]+_|tpl_|lib_)//')
TYPE_PREFIX="" TYPE_PREFIX=""
case "${EXT_TYPE}" in case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;; plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
@@ -442,110 +461,35 @@ jobs:
SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1) SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1) SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
# -- Delete existing assets with same name before uploading ------ # -- Get existing assets for cleanup --------------------------------
ASSETS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \ ASSETS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/${RELEASE_ID}/assets" 2>/dev/null || echo "[]") "${API_BASE}/releases/${RELEASE_ID}/assets" 2>/dev/null || echo "[]")
for ASSET_NAME in "$ZIP_NAME" "$TAR_NAME"; do
# -- Create per-file .sha256 checksum files -------------------------
echo "${SHA256_ZIP} ${ZIP_NAME}" > "/tmp/${ZIP_NAME}.sha256"
echo "${SHA256_TAR} ${TAR_NAME}" > "/tmp/${TAR_NAME}.sha256"
# -- Upload packages + checksums to release tag --------------------
for ASSET in "${ZIP_NAME}" "${TAR_NAME}" "${ZIP_NAME}.sha256" "${TAR_NAME}.sha256"; do
[ ! -f "/tmp/${ASSET}" ] && continue
# Delete existing asset with same name
ASSET_ID=$(echo "$ASSETS" | python3 -c " ASSET_ID=$(echo "$ASSETS" | python3 -c "
import sys,json import sys,json
assets = json.load(sys.stdin) assets = json.load(sys.stdin)
for a in assets: for a in assets:
if a['name'] == '${ASSET_NAME}': if a['name'] == '${ASSET}':
print(a['id']); break print(a['id']); break
" 2>/dev/null || true) " 2>/dev/null || true)
if [ -n "$ASSET_ID" ]; then [ -n "$ASSET_ID" ] && curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \ "${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true
"${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true # Upload
fi curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"/tmp/${ASSET}" \
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${ASSET}" > /dev/null 2>&1 || true
done done
# -- Upload both to release tag ---------------------------------- # updates.xml already handled by Step 5 (updates_xml_build.php with preserve logic)
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"/tmp/${ZIP_NAME}" \
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" > /dev/null 2>&1 || true
curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"/tmp/${TAR_NAME}" \
"${API_BASE}/releases/${RELEASE_ID}/assets?name=${TAR_NAME}" > /dev/null 2>&1 || true
# -- Update updates.xml with both download formats ---------------
if [ -f "updates.xml" ]; then
ZIP_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}"
TAR_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${TAR_NAME}"
# Use Python to update only the stable entry's downloads + sha256
export PY_ZIP_URL="$ZIP_URL" PY_TAR_URL="$TAR_URL" PY_SHA="$SHA256_ZIP"
python3 << 'PYEOF'
import re, os
with open("updates.xml") as f:
content = f.read()
zip_url = os.environ["PY_ZIP_URL"]
tar_url = os.environ["PY_TAR_URL"]
sha = os.environ["PY_SHA"]
# Find the stable update block and replace its downloads + sha256
def replace_stable(m):
block = m.group(0)
# Replace downloads block
new_downloads = (
" <downloads>\n"
f" <downloadurl type=\"full\" format=\"zip\">{zip_url}</downloadurl>\n"
" </downloads>"
)
block = re.sub(r' <downloads>.*?</downloads>', new_downloads, block, flags=re.DOTALL)
# Add or replace sha256
if '<sha256>' in block:
block = re.sub(r' <sha256>.*?</sha256>', f' <sha256>{sha}</sha256>', block)
else:
block = block.replace('</downloads>', f'</downloads>\n <sha256>{sha}</sha256>')
return block
content = re.sub(
r' <update>.*?<tag>stable</tag>.*?</update>',
replace_stable,
content,
flags=re.DOTALL
)
with open("updates.xml", "w") as f:
f.write(content)
PYEOF
CURRENT_BRANCH="${{ github.ref_name }}"
git add updates.xml
git commit -m "chore(release): ZIP + tar.gz for ${VERSION} [skip ci]" \
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" || true
git push || true
# Sync updates.xml to main via direct API (always runs — may be on version/XX branch)
GA_TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}"
FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
"${API}/contents/updates.xml?ref=main" | jq -r '.sha // empty')
if [ -n "$FILE_SHA" ]; then
CONTENT=$(base64 -w0 updates.xml)
curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/contents/updates.xml" \
-d "$(jq -n \
--arg content "$CONTENT" \
--arg sha "$FILE_SHA" \
--arg msg "chore: sync updates.xml ${VERSION} [skip ci]" \
--arg branch "main" \
'{content: $content, sha: $sha, message: $msg, branch: $branch}'
)" > /dev/null 2>&1 \
&& echo "updates.xml synced to main via API" \
|| echo "WARNING: failed to sync updates.xml to main"
else
echo "WARNING: could not get updates.xml SHA from main"
fi
fi
echo "### Packages" >> $GITHUB_STEP_SUMMARY echo "### Packages" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
@@ -556,72 +500,33 @@ jobs:
echo "| Release | \`${RELEASE_TAG}\` | |" >> $GITHUB_STEP_SUMMARY echo "| Release | \`${RELEASE_TAG}\` | |" >> $GITHUB_STEP_SUMMARY
echo "| Download | [${ZIP_NAME}](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}) |" >> $GITHUB_STEP_SUMMARY echo "| Download | [${ZIP_NAME}](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}) |" >> $GITHUB_STEP_SUMMARY
# -- STEP 8b: Update release description with changelog + SHA ---------------- # -- STEP 8b: Update release description with changelog ----------------------
- name: "Step 8b: Update release body with changelog and SHA" - name: "Step 8b: Update release body"
if: steps.version.outputs.skip != 'true' if: steps.version.outputs.skip != 'true'
run: | run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}" VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}" RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" MOKO_CLI="/tmp/moko-platform-api/cli"
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
EXT_TYPE="${{ steps.updates.outputs.ext_type }}"
EXT_FOLDER="${{ steps.updates.outputs.ext_folder }}"
# Build TYPE_PREFIX to match Step 8's ZIP naming php ${MOKO_CLI}/release_body_update.php \
TYPE_PREFIX="" --path . --version "${VERSION}" --tag "${RELEASE_TAG}" \
case "${EXT_TYPE}" in --token "${{ secrets.GA_TOKEN }}" \
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;; --gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
module) TYPE_PREFIX="mod_" ;; 2>/dev/null || {
component) TYPE_PREFIX="com_" ;; # Fallback: simple body update if CLI not available
template) TYPE_PREFIX="tpl_" ;; API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
library) TYPE_PREFIX="lib_" ;; RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
package) TYPE_PREFIX="pkg_" ;; "${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null | \
esac python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
ZIP_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip" if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ]; then
TAR_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.tar.gz" BODY="## ${VERSION} ($(date +%Y-%m-%d))\n\nChecksum files attached as \`*.sha256\` assets."
curl -sf -X PATCH -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
# Get SHA from the built files -H "Content-Type: application/json" \
SHA256_ZIP="" "${API_BASE}/releases/${RELEASE_ID}" \
[ -f "/tmp/${ZIP_NAME}" ] && SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1) -d "{\"body\":\"${BODY}\"}" > /dev/null 2>&1
SHA256_TAR="" fi
[ -f "/tmp/${TAR_NAME}" ] && SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1) }
echo "Release body updated" >> $GITHUB_STEP_SUMMARY
# Extract latest changelog entry (strip the ## header to avoid duplicate)
CHANGELOG=""
if [ -f "CHANGELOG.md" ]; then
CHANGELOG=$(sed -n "/^## \[*${VERSION}/,/^## \[*[0-9]/p" CHANGELOG.md | sed '$d' | sed '1d')
[ -z "$CHANGELOG" ] && CHANGELOG=$(sed -n '/^## /,/^## /p' CHANGELOG.md | sed '$d' | sed '1d' | head -30)
fi
# Build release body (single header, no duplicate from changelog)
BODY="## ${VERSION} ($(date +%Y-%m-%d))\n\n"
if [ -n "$CHANGELOG" ]; then
BODY="${BODY}${CHANGELOG}\n\n"
fi
BODY="${BODY}---\n\n### Checksums\n\n"
BODY="${BODY}| File | SHA-256 |\n|------|--------|\n"
[ -n "$SHA256_ZIP" ] && BODY="${BODY}| \`${ZIP_NAME}\` | \`${SHA256_ZIP}\` |\n"
[ -n "$SHA256_TAR" ] && BODY="${BODY}| \`${TAR_NAME}\` | \`${SHA256_TAR}\` |\n"
# Get release ID and update body
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null | \
python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ]; then
python3 -c "
import json, urllib.request
body = '''$(printf '%b' "$BODY")'''
data = json.dumps({'body': body}).encode()
req = urllib.request.Request(
'${API_BASE}/releases/${RELEASE_ID}',
data=data,
headers={'Authorization': 'token ${{ secrets.GA_TOKEN }}', 'Content-Type': 'application/json'},
method='PATCH'
)
urllib.request.urlopen(req)
" 2>/dev/null && echo "Release body updated with changelog + SHA" >> $GITHUB_STEP_SUMMARY
fi
# -- STEP 9: Mirror to GitHub (stable only) -------------------------------- # -- STEP 9: Mirror to GitHub (stable only) --------------------------------
- name: "Step 9: Mirror release to GitHub" - name: "Step 9: Mirror release to GitHub"
+26 -40
View File
@@ -107,6 +107,9 @@ jobs:
php ${MOKO_CLI}/version_set_platform.php \ php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch "${{ github.ref_name }}" 2>/dev/null || true --path . --version "$VERSION" --branch "${{ github.ref_name }}" 2>/dev/null || true
# Verify version consistency across all files
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
# Commit version bump # Commit version bump
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]" git config --local user.name "gitea-actions[bot]"
@@ -177,6 +180,8 @@ jobs:
mkdir -p build/package mkdir -p build/package
REPO_ROOT=$(pwd)
if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then
echo "=== Building Joomla PACKAGE (multi-extension) ===" echo "=== Building Joomla PACKAGE (multi-extension) ==="
for ext_dir in "${SOURCE_DIR}"/packages/*/; do for ext_dir in "${SOURCE_DIR}"/packages/*/; do
@@ -184,8 +189,8 @@ jobs:
EXT_NAME=$(basename "$ext_dir") EXT_NAME=$(basename "$ext_dir")
echo " Packaging sub-extension: ${EXT_NAME}" echo " Packaging sub-extension: ${EXT_NAME}"
cd "$ext_dir" cd "$ext_dir"
zip -r "../../build/package/${EXT_NAME}.zip" . -x $EXCLUDES zip -r "${REPO_ROOT}/build/package/${EXT_NAME}.zip" . -x $EXCLUDES
cd "$OLDPWD" cd "${REPO_ROOT}"
done done
for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do
[ -f "$f" ] && cp "$f" build/package/ [ -f "$f" ] && cp "$f" build/package/
@@ -231,7 +236,7 @@ jobs:
BODY="## ${VERSION} ($(date +%Y-%m-%d)) BODY="## ${VERSION} ($(date +%Y-%m-%d))
**Channel:** ${STABILITY} **Channel:** ${STABILITY}
**SHA-256:** \`${SHA256}\`" Checksum file attached as \`${ZIP_NAME}.sha256\`."
# Delete existing release # Delete existing release
EXISTING_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \ EXISTING_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
@@ -263,6 +268,13 @@ jobs:
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \ "${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
--data-binary "@build/${ZIP_NAME}" --data-binary "@build/${ZIP_NAME}"
# Upload per-file checksum
echo "${SHA256} ${ZIP_NAME}" > "build/${ZIP_NAME}.sha256"
curl -sS -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/octet-stream" \
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}.sha256" \
--data-binary "@build/${ZIP_NAME}.sha256"
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})" echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
- name: Update updates.xml - name: Update updates.xml
@@ -279,43 +291,17 @@ jobs:
exit 0 exit 0
fi fi
# Map stability to XML tag name # Use moko-platform CLI to build/update updates.xml (preserves other channels)
case "$STABILITY" in MOKO_CLI="/tmp/moko-platform-api/cli"
development) XML_TAG="development" ;; if [ -f "${MOKO_CLI}/updates_xml_build.php" ]; then
alpha) XML_TAG="alpha" ;; php "${MOKO_CLI}/updates_xml_build.php" \
beta) XML_TAG="beta" ;; --path . --version "${VERSION}" --stability "${STABILITY}" \
release-candidate) XML_TAG="rc" ;; --sha "${SHA256}" \
*) XML_TAG="$STABILITY" ;; --gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}"
esac echo "Updated ${STABILITY} channel via CLI: version=${VERSION}"
else
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${TAG}/${ZIP_NAME}" echo "WARNING: updates_xml_build.php not found — skipping"
fi
# Use PHP to update the channel in updates.xml
php -r '
$xml_tag = $argv[1];
$version = $argv[2];
$sha256 = $argv[3];
$url = $argv[4];
$date = date("Y-m-d");
$content = file_get_contents("updates.xml");
$pattern = "/(<update>(?:(?!<\/update>).)*?<tag>" . preg_quote($xml_tag) . "<\/tag>.*?<\/update>)/s";
$content = preg_replace_callback($pattern, function($m) use ($version, $sha256, $url, $date) {
$block = $m[0];
$block = preg_replace("/<version>[^<]*<\/version>/", "<version>{$version}</version>", $block);
if (strpos($block, "<sha256>") !== false) {
$block = preg_replace("/<sha256>[^<]*<\/sha256>/", "<sha256>{$sha256}</sha256>", $block);
} else {
$block = str_replace("</downloads>", "</downloads>\n <sha256>{$sha256}</sha256>", $block);
}
$block = preg_replace("/(<downloadurl[^>]*>)[^<]*(<\/downloadurl>)/", "\${1}{$url}\${2}", $block);
return $block;
}, $content);
file_put_contents("updates.xml", $content);
echo "Updated {$xml_tag} channel: version={$version}\n";
' "$XML_TAG" "$VERSION" "$SHA256" "$DOWNLOAD_URL"
# Commit and push # Commit and push
if ! git diff --quiet updates.xml 2>/dev/null; then if ! git diff --quiet updates.xml 2>/dev/null; then
+6
View File
@@ -42,6 +42,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Install API endpoint: extract ZIP to temp directory before passing to Joomla Installer (was passing ZIP path directly) - Install API endpoint: extract ZIP to temp directory before passing to Joomla Installer (was passing ZIP path directly)
- Clean up extracted temp directory on success or failure - Clean up extracted temp directory on success or failure
- Update site disabled by Joomla when protected=1 — ensureProtectedFlag() now re-enables it - Update site disabled by Joomla when protected=1 — ensureProtectedFlag() now re-enables it
- CI: auto-release fetches updates.xml from main before building (preserves all channels)
- CI: version_check.php --fix runs after version bump in both workflows
- CI: checksums attached as `[filename].sha256` files instead of in release body
- CI: auto-release cleaned up — removed duplicate asset loops, inline Python updater, dead code
- CI: Step 8b uses `release_body_update.php` CLI instead of inline Python
- CI: Step 6 tag creation no longer gated by `is_minor` (was never set)
### Changed ### Changed
- CI: auto-release uses stream tag `stable` instead of version tag `vXX` - CI: auto-release uses stream tag `stable` instead of version tag `vXX`
+1 -1
View File
@@ -9,7 +9,7 @@
DEFGROUP: Joomla.Plugin DEFGROUP: Joomla.Plugin
INGROUP: MokoWaaS INGROUP: MokoWaaS
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS
VERSION: 02.06.04 VERSION: 02.08.03
PATH: /README.md PATH: /README.md
BRIEF: MokoWaaS platform plugin for Joomla BRIEF: MokoWaaS platform plugin for Joomla
--> -->
+1 -1
View File
@@ -7,7 +7,7 @@
<license>GPL-3.0-or-later</license> <license>GPL-3.0-or-later</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl> <authorUrl>https://mokoconsulting.tech</authorUrl>
<version>02.06.04</version> <version>02.08.03</version>
<description>Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.</description> <description>Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.</description>
<namespace path="api/src">Moko\Component\MokoWaaS\Api</namespace> <namespace path="api/src">Moko\Component\MokoWaaS\Api</namespace>
<administration> <administration>
@@ -30,7 +30,7 @@
<license>GNU General Public License version 3 or later; see LICENSE.md</license> <license>GNU General Public License version 3 or later; see LICENSE.md</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl> <authorUrl>https://mokoconsulting.tech</authorUrl>
<version>02.06.04</version> <version>02.08.03</version>
<description>This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.</description> <description>This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.</description>
<namespace path=".">Moko\Plugin\System\MokoWaaS</namespace> <namespace path=".">Moko\Plugin\System\MokoWaaS</namespace>
<scriptfile>script.php</scriptfile> <scriptfile>script.php</scriptfile>
@@ -7,7 +7,7 @@
<license>GPL-3.0-or-later</license> <license>GPL-3.0-or-later</license>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>
<authorUrl>https://mokoconsulting.tech</authorUrl> <authorUrl>https://mokoconsulting.tech</authorUrl>
<version>02.06.04</version> <version>02.08.03</version>
<description>Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.</description> <description>Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.</description>
<namespace path="src">Moko\Plugin\WebServices\MokoWaaS</namespace> <namespace path="src">Moko\Plugin\WebServices\MokoWaaS</namespace>
<files> <files>
+1 -1
View File
@@ -2,7 +2,7 @@
<extension type="package" method="upgrade"> <extension type="package" method="upgrade">
<name>MokoWaaS</name> <name>MokoWaaS</name>
<packagename>mokowaas</packagename> <packagename>mokowaas</packagename>
<version>02.06.04</version> <version>02.08.03</version>
<creationDate>2026-05-23</creationDate> <creationDate>2026-05-23</creationDate>
<author>Moko Consulting</author> <author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail> <authorEmail>hello@mokoconsulting.tech</authorEmail>