From 2ede62b8b9f75174809290e6cc7f6fc163b15ba8 Mon Sep 17 00:00:00 2001
From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech>
Date: Thu, 28 May 2026 15:44:09 +0000
Subject: [PATCH 1/4] fix: updates.xml with all 5 channels at 02.12.00 [skip
ci]
---
updates.xml | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 82 insertions(+), 4 deletions(-)
diff --git a/updates.xml b/updates.xml
index f24b524e..bc02405e 100644
--- a/updates.xml
+++ b/updates.xml
@@ -1,25 +1,103 @@
- MokoWaaS
+ Package - MokoWaaS
MokoWaaS stable build.
pkg_mokowaas
package
site
- 02.09.00
+ 02.12.00
+ 2026-05-28
https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/stable
- https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.09.00.zip
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.12.00.zip
+ 4dfa0a615dacdc0476b8da8580e2b1c0c362235bc55185937804c1190a6b2758
stable
Moko Consulting
https://mokoconsulting.tech
+
+ Package - MokoWaaS
+ MokoWaaS rc build.
+ pkg_mokowaas
+ package
+ site
+ 02.12.00
+ 2026-05-28
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/stable
+
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.12.00.zip
+
+ 4dfa0a615dacdc0476b8da8580e2b1c0c362235bc55185937804c1190a6b2758
+ rc
+ Moko Consulting
+ https://mokoconsulting.tech
+
+
+
+
+ Package - MokoWaaS
+ MokoWaaS beta build.
+ pkg_mokowaas
+ package
+ site
+ 02.12.00
+ 2026-05-28
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/stable
+
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.12.00.zip
+
+ 4dfa0a615dacdc0476b8da8580e2b1c0c362235bc55185937804c1190a6b2758
+ beta
+ Moko Consulting
+ https://mokoconsulting.tech
+
+
+
+
+ Package - MokoWaaS
+ MokoWaaS alpha build.
+ pkg_mokowaas
+ package
+ site
+ 02.12.00
+ 2026-05-28
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/stable
+
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.12.00.zip
+
+ 4dfa0a615dacdc0476b8da8580e2b1c0c362235bc55185937804c1190a6b2758
+ alpha
+ Moko Consulting
+ https://mokoconsulting.tech
+
+
+
+
+ Package - MokoWaaS
+ MokoWaaS development build.
+ pkg_mokowaas
+ package
+ site
+ 02.12.00
+ 2026-05-28
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/tag/stable
+
+ https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/releases/download/stable/pkg_mokowaas-02.12.00.zip
+
+ 4dfa0a615dacdc0476b8da8580e2b1c0c362235bc55185937804c1190a6b2758
+ development
+ Moko Consulting
+ https://mokoconsulting.tech
+
+
+
--
2.52.0
From 62788853eac2aeacc49a10ccff10b4cdf9ec929a Mon Sep 17 00:00:00 2001
From: Jonathan Miller
Date: Thu, 28 May 2026 10:59:38 -0500
Subject: [PATCH 2/4] fix: rewrite release workflows to use CLI and fix version
propagation
auto-release.yml:
- Defer commit until AFTER updates.xml is written so version bump +
manifests + updates.xml all go in one atomic push
- Add final version_check.php --fix before commit to catch missed files
- Remove || true from critical git push
update-server.yml:
- Replace ~400 lines of inline bash/python with CLI tool calls
- Use updates_xml_build.php for XML generation (handles name prefix,
SHA cascade, creationDate, all 5 channels)
- Use release_create.php + release_package.php for Gitea releases
- Keep SFTP deploy and main sync as-is
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context)
---
.mokogitea/workflows/auto-release.yml | 103 +++--
.mokogitea/workflows/update-server.yml | 562 +++++--------------------
2 files changed, 151 insertions(+), 514 deletions(-)
diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml
index 9544f963..1c9dc6fc 100644
--- a/.mokogitea/workflows/auto-release.yml
+++ b/.mokogitea/workflows/auto-release.yml
@@ -259,26 +259,8 @@ jobs:
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
- # Step 5 (updates.xml) moved after Step 8 to include SHA-256 checksum
-
- - name: Commit release changes
- if: >-
- steps.version.outputs.skip != 'true' &&
- steps.check.outputs.already_released != 'true'
- run: |
- if git diff --quiet && git diff --cached --quiet; then
- echo "No changes to commit"
- exit 0
- fi
- VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
- git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
- git config --local user.name "gitea-actions[bot]"
- # Set push URL with token for branch-protected repos
- git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
- git add -A
- git commit -m "chore(release): build ${VERSION} [skip ci]" \
- --author="gitea-actions[bot] "
- git push -u origin HEAD
+ # NOTE: Commit is deferred until after updates.xml is written (after Step 8)
+ # so all changes (version bump + manifests + updates.xml) go in one atomic push.
# -- STEP 6: Create tag ---------------------------------------------------
- name: "Step 6: Create git tag"
@@ -348,13 +330,10 @@ jobs:
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
SHA256="${{ steps.package.outputs.sha256_zip }}"
- # 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
+ if [ ! -f "updates.xml" ]; then
+ echo "No updates.xml — skipping"
+ exit 0
+ fi
SHA_FLAG=""
[ -n "$SHA256" ] && SHA_FLAG="--sha ${SHA256}"
@@ -364,17 +343,31 @@ jobs:
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
${SHA_FLAG} --github-output
- # Commit updates.xml if changed
- if ! git diff --quiet updates.xml 2>/dev/null; then
- git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
- git config --local user.name "gitea-actions[bot]"
- git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
- git add updates.xml
- git commit -m "chore: update stable channel ${VERSION} [skip ci]" \
- --author="gitea-actions[bot] "
- git push origin HEAD 2>&1 || true
+ # -- Commit all release changes (version bump + manifests + updates.xml) --
+ - name: "Commit release changes"
+ if: >-
+ steps.version.outputs.skip != 'true' &&
+ steps.check.outputs.already_released != 'true'
+ run: |
+ VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
+
+ # Final version consistency check before commit
+ php /tmp/moko-platform-api/cli/version_check.php --path . --fix 2>/dev/null || true
+
+ git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
+ git config --local user.name "gitea-actions[bot]"
+ git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
+ git add -A
+
+ if git diff --cached --quiet; then
+ echo "No changes to commit"
+ exit 0
fi
+ git commit -m "chore(release): build ${VERSION} [skip ci]" \
+ --author="gitea-actions[bot] "
+ git push -u origin HEAD
+
# -- STEP 8b: Update release description with changelog ----------------------
- name: "Step 8b: Update release body"
if: steps.version.outputs.skip != 'true'
@@ -454,25 +447,25 @@ jobs:
"${API_BASE}/branches" \
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
- echo "Dev branch reset from main (keeps dev ahead after release)" >> $GITHUB_STEP_SUMMARY
-
- - name: "Step 12: Create version branch from main"
- if: steps.version.outputs.skip != 'true'
- continue-on-error: true
- run: |
- API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- TOKEN="${{ secrets.GA_TOKEN }}"
- VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
- BRANCH_NAME="version/${VERSION}"
- MAIN_SHA=$(git rev-parse HEAD)
-
- # Delete old version branch if it exists (same version re-release)
- curl -sf -X DELETE -H "Authorization: token ${TOKEN}" "${API_BASE}/branches/${BRANCH_NAME}" 2>/dev/null && echo "Deleted old ${BRANCH_NAME}"
-
- # Create version/XX.YY.ZZ from main
- curl -sf -X POST -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API_BASE}/branches" -d "{\"new_branch_name\":\"${BRANCH_NAME}\",\"old_branch_name\":\"main\"}" 2>/dev/null && echo "Created ${BRANCH_NAME} from main (${MAIN_SHA})" || echo "WARNING: ${BRANCH_NAME} creation failed"
-
- echo "Version branch created: ${BRANCH_NAME} (${MAIN_SHA})" >> $GITHUB_STEP_SUMMARY
+ echo "Dev branch reset from main (keeps dev ahead after release)" >> $GITHUB_STEP_SUMMARY
+
+ - name: "Step 12: Create version branch from main"
+ if: steps.version.outputs.skip != 'true'
+ continue-on-error: true
+ run: |
+ API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
+ TOKEN="${{ secrets.GA_TOKEN }}"
+ VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
+ BRANCH_NAME="version/${VERSION}"
+ MAIN_SHA=$(git rev-parse HEAD)
+
+ # Delete old version branch if it exists (same version re-release)
+ curl -sf -X DELETE -H "Authorization: token ${TOKEN}" "${API_BASE}/branches/${BRANCH_NAME}" 2>/dev/null && echo "Deleted old ${BRANCH_NAME}"
+
+ # Create version/XX.YY.ZZ from main
+ curl -sf -X POST -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API_BASE}/branches" -d "{\"new_branch_name\":\"${BRANCH_NAME}\",\"old_branch_name\":\"main\"}" 2>/dev/null && echo "Created ${BRANCH_NAME} from main (${MAIN_SHA})" || echo "WARNING: ${BRANCH_NAME} creation failed"
+
+ echo "Version branch created: ${BRANCH_NAME} (${MAIN_SHA})" >> $GITHUB_STEP_SUMMARY
diff --git a/.mokogitea/workflows/update-server.yml b/.mokogitea/workflows/update-server.yml
index 8660a431..c8a01942 100644
--- a/.mokogitea/workflows/update-server.yml
+++ b/.mokogitea/workflows/update-server.yml
@@ -4,18 +4,16 @@
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
-# INGROUP: MokoStandards.Universal
+# INGROUP: moko-platform.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /templates/workflows/update-server.yml
-# VERSION: 04.07.00
-# BRIEF: Update server XML feed with stable/rc/beta/alpha/dev entries (universal)
+# VERSION: 05.00.00
+# BRIEF: Pre-release build + update server XML for dev/alpha/beta/rc branches
#
-# Writes updates.xml with multiple entries:
-# - stable on push to main (from auto-release)
-# - rc on push to rc/**
-# - development on push to dev or dev/**
+# Thin wrapper around moko-platform CLI tools.
+# Builds packages, updates updates.xml, and optionally deploys via SFTP.
#
-# Joomla filters by user's "Minimum Stability" setting.
+# Joomla filters update entries by the user's "Minimum Stability" setting.
name: "Update Server"
@@ -66,7 +64,7 @@ permissions:
jobs:
update-xml:
- name: Update updates.xml
+ name: Update Server
runs-on: release
if: >-
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' || github.event_name == 'push'
@@ -97,28 +95,29 @@ jobs:
if [ -d "/tmp/moko-platform" ] && [ -f "/tmp/moko-platform/composer.json" ]; then
cd /tmp/moko-platform && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
fi
+ echo "MOKO_CLI=/tmp/moko-platform/cli" >> "$GITHUB_ENV"
- - name: Generate updates.xml entry
- id: update
+ - name: Detect platform
+ id: platform
+ run: php ${MOKO_CLI}/manifest_read.php --path . --github-output
+
+ - name: Resolve stability and bump version
+ id: meta
run: |
BRANCH="${{ github.ref_name }}"
- REPO="${{ github.repository }}"
- API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- VERSION=$(php /tmp/moko-platform/cli/version_read.php --path . 2>/dev/null || echo "0.0.0")
- # Auto-bump patch on all branches (dev, alpha, beta, rc)
+ # Auto-bump patch version
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
- BUMPED=$(php /tmp/moko-platform/cli/version_bump.php --path . 2>/dev/null || true)
- if [ -n "$BUMPED" ]; then
- VERSION=$(php /tmp/moko-platform/cli/version_read.php --path . 2>/dev/null || echo "$VERSION")
- git add -A
- git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
- --author="gitea-actions[bot] " 2>/dev/null || true
- git push 2>/dev/null || true
- fi
+ php ${MOKO_CLI}/version_bump.php --path . 2>/dev/null || true
- # Determine stability from branch or input
+ VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "0.0.0")
+
+ # Propagate version to all manifest files
+ php ${MOKO_CLI}/version_set_platform.php --path . --version "$VERSION" --branch "$BRANCH" 2>/dev/null || true
+ php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
+
+ # Determine stability from branch or manual input
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
STABILITY="${{ inputs.stability }}"
elif [[ "$BRANCH" == rc/* ]]; then
@@ -127,258 +126,83 @@ jobs:
STABILITY="beta"
elif [[ "$BRANCH" == alpha/* ]]; then
STABILITY="alpha"
- elif [[ "$BRANCH" == dev/* ]] || [[ "$BRANCH" == "dev" ]]; then
+ else
STABILITY="development"
- else
- STABILITY="stable"
fi
+ # Version suffix
+ case "$STABILITY" in
+ development) SUFFIX="-dev"; TAG="development" ;;
+ alpha) SUFFIX="-alpha"; TAG="alpha" ;;
+ beta) SUFFIX="-beta"; TAG="beta" ;;
+ rc) SUFFIX="-rc"; TAG="release-candidate" ;;
+ *) SUFFIX=""; TAG="stable" ;;
+ esac
+
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
+ echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
+ echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
+ echo "display_version=${VERSION}${SUFFIX}" >> "$GITHUB_OUTPUT"
- # Parse manifest (portable — no grep -P)
- MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "./build/*" -exec grep -l '/dev/null | head -1)
- if [ -z "$MANIFEST" ]; then
- echo "No Joomla manifest found — skipping"
- exit 0
- fi
-
- # Extract fields using sed (works on all runners)
- EXT_NAME=$(sed -n 's/.*\([^<]*\)<\/name>.*/\1/p' "$MANIFEST" | head -1)
- EXT_TYPE=$(sed -n 's/.*]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
- EXT_ELEMENT=$(sed -n 's/.*\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" | head -1)
- EXT_CLIENT=$(sed -n 's/.*]*client="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
- EXT_FOLDER=$(sed -n 's/.*]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
- EXT_VERSION=$(sed -n 's/.*\([^<]*\)<\/version>.*/\1/p' "$MANIFEST" | head -1)
- TARGET_PLATFORM=$(sed -n 's/.*\(\).*/\1/p' "$MANIFEST" | head -1)
- PHP_MINIMUM=$(sed -n 's/.*\([^<]*\)<\/php_minimum>.*/\1/p' "$MANIFEST" | head -1)
-
- # Fallbacks
- [ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
- [ -z "$EXT_TYPE" ] && EXT_TYPE="component"
-
- # Derive element if not in manifest: try XML filename, then repo name
- if [ -z "$EXT_ELEMENT" ]; then
- EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
- case "$EXT_ELEMENT" in
- templatedetails|manifest|*.xml) EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
- esac
- fi
-
- # Use manifest version if README version is empty
- [ "$VERSION" = "0.0.0" ] && [ -n "$EXT_VERSION" ] && VERSION="$EXT_VERSION"
-
- [ -z "$TARGET_PLATFORM" ] && TARGET_PLATFORM=$(printf '' "/")
-
- # Joomla requires on ALL extension types for update matching
- if [ -n "$EXT_CLIENT" ]; then
- CLIENT_TAG="${EXT_CLIENT}"
- else
- CLIENT_TAG="site"
- fi
-
- FOLDER_TAG=""
- [ -n "$EXT_FOLDER" ] && [ "$EXT_TYPE" = "plugin" ] && FOLDER_TAG="${EXT_FOLDER}"
-
- PHP_TAG=""
- [ -n "$PHP_MINIMUM" ] && PHP_TAG="${PHP_MINIMUM}"
-
- # Version suffix for non-stable
- DISPLAY_VERSION="$VERSION"
- 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}')
-
- # 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="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${PACKAGE_NAME}"
- INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}"
-
- # -- Build install packages (ZIP + tar.gz) --------------------
- SOURCE_DIR="src"
- [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
- if [ -d "$SOURCE_DIR" ]; then
- EXCLUDES=".ftpignore sftp-config* *.ppk *.pem *.key .env*"
- TAR_NAME="${EXT_ELEMENT}-${DISPLAY_VERSION}.tar.gz"
-
- cd "$SOURCE_DIR"
- zip -r "/tmp/${PACKAGE_NAME}" . -x $EXCLUDES
- cd ..
- tar -czf "/tmp/${TAR_NAME}" -C "$SOURCE_DIR" \
- --exclude='.ftpignore' --exclude='sftp-config*' \
- --exclude='*.ppk' --exclude='*.pem' --exclude='*.key' --exclude='.env*' .
-
- SHA256=$(sha256sum "/tmp/${PACKAGE_NAME}" | cut -d' ' -f1)
-
- # Ensure release exists on Gitea
- RELEASE_JSON=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
- "${API_BASE}/releases/tags/${RELEASE_TAG}" 2>/dev/null || true)
- RELEASE_ID=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
-
- if [ -z "$RELEASE_ID" ]; then
- # Create release
- RELEASE_JSON=$(curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
- -H "Content-Type: application/json" \
- "${API_BASE}/releases" \
- -d "$(python3 -c "import json; print(json.dumps({
- 'tag_name': '${RELEASE_TAG}',
- 'name': '${RELEASE_TAG} (${DISPLAY_VERSION})',
- 'body': '${STABILITY} release',
- 'prerelease': True,
- 'target_commitish': 'main'
- }))")" 2>/dev/null || true)
- RELEASE_ID=$(echo "$RELEASE_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
- fi
-
- if [ -n "$RELEASE_ID" ]; then
- # Delete existing assets with same name before uploading
- ASSETS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
- "${API_BASE}/releases/${RELEASE_ID}/assets" 2>/dev/null || echo "[]")
- for ASSET_FILE in "$PACKAGE_NAME" "$TAR_NAME"; do
- ASSET_ID=$(echo "$ASSETS" | python3 -c "
- import sys,json
- assets = json.load(sys.stdin)
- for a in assets:
- if a['name'] == '${ASSET_FILE}':
- print(a['id']); break
- " 2>/dev/null || true)
- if [ -n "$ASSET_ID" ]; then
- curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
- "${API_BASE}/releases/${RELEASE_ID}/assets/${ASSET_ID}" 2>/dev/null || true
- fi
- done
-
- # Upload both formats
- curl -sf -X POST -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
- -H "Content-Type: application/octet-stream" \
- --data-binary @"/tmp/${PACKAGE_NAME}" \
- "${API_BASE}/releases/${RELEASE_ID}/assets?name=${PACKAGE_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
- fi
-
- echo "Packages: ${PACKAGE_NAME} + ${TAR_NAME} (SHA: ${SHA256})" >> $GITHUB_STEP_SUMMARY
- else
- SHA256=""
- fi
-
- # -- Build the new entry (canonical format matching release.yml) --
- NEW_ENTRY=""
- NEW_ENTRY="${NEW_ENTRY} \n"
- NEW_ENTRY="${NEW_ENTRY} ${EXT_NAME}\n"
- NEW_ENTRY="${NEW_ENTRY} ${EXT_NAME} ${STABILITY} build.\n"
- NEW_ENTRY="${NEW_ENTRY} ${EXT_ELEMENT}\n"
- NEW_ENTRY="${NEW_ENTRY} ${EXT_TYPE}\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} ${VERSION}\n"
- NEW_ENTRY="${NEW_ENTRY} $(date +%Y-%m-%d)\n"
- NEW_ENTRY="${NEW_ENTRY} https://git.mokoconsulting.tech/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${RELEASE_TAG}\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}\n"
- NEW_ENTRY="${NEW_ENTRY} ${STABILITY}\n"
- NEW_ENTRY="${NEW_ENTRY} Moko Consulting\n"
- NEW_ENTRY="${NEW_ENTRY} https://mokoconsulting.tech\n"
- NEW_ENTRY="${NEW_ENTRY} \n"
- [ -n "$PHP_MINIMUM" ] && NEW_ENTRY="${NEW_ENTRY} ${PHP_MINIMUM}\n"
- NEW_ENTRY="${NEW_ENTRY} "
-
- # -- Write new entry to temp file --------------------------------
- printf '%b' "$NEW_ENTRY" > /tmp/new_entry.xml
-
- # -- Merge into updates.xml ----------------------------------------
- # Cascade: stable→all | rc→rc+lower | beta→beta+lower | alpha→alpha+dev | dev→dev
- CASCADE_MAP="stable:development,alpha,beta,rc,stable rc:development,alpha,beta,rc beta:development,alpha,beta alpha:development,alpha development:development"
- TARGETS=""
- for entry in $CASCADE_MAP; do
- key="${entry%%:*}"
- vals="${entry#*:}"
- if [ "$key" = "${STABILITY}" ]; then
- TARGETS="$vals"
- break
- fi
- done
- [ -z "$TARGETS" ] && TARGETS="${STABILITY}"
-
- echo "Cascade: ${STABILITY} → ${TARGETS}"
-
- # Create updates.xml if missing
- if [ ! -f "updates.xml" ]; then
- printf '%s\n' "" > updates.xml
- printf '%s\n' "" >> updates.xml
- printf '%s\n' "" >> updates.xml
- printf '%s\n' "" >> updates.xml
- fi
-
- # Update existing blocks or create missing ones
- export PY_TARGETS="$TARGETS" PY_VERSION="$VERSION" PY_DATE="$(date +%Y-%m-%d)"
- python3 << 'PYEOF'
- import re, os
-
- targets = os.environ["PY_TARGETS"].split(",")
- version = os.environ["PY_VERSION"]
- date = os.environ["PY_DATE"]
-
- with open("updates.xml") as f:
- content = f.read()
- with open("/tmp/new_entry.xml") as f:
- new_entry_template = f.read()
-
- for tag in targets:
- tag = tag.strip()
- # Build entry with this tag's name
- new_entry = re.sub(r"[^<]*", f"{tag}", new_entry_template)
-
- # Try to find existing block (handles both single-line and multi-line )
- block_pattern = r"((?:(?!).)*?" + re.escape(tag) + r".*?)"
- match = re.search(block_pattern, content, re.DOTALL)
-
- if match:
- # Update in place — replace entire block
- content = content.replace(match.group(1), new_entry.strip())
- print(f" UPDATED: {tag} → {version}")
- else:
- # Create — insert before
- content = content.replace("", "\n" + new_entry.strip() + "\n\n")
- print(f" CREATED: {tag} → {version}")
-
- # Clean up excessive blank lines
- content = re.sub(r"\n{3,}", "\n\n", content)
-
- with open("updates.xml", "w") as f:
- f.write(content)
- PYEOF
-
- # Commit
- git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
- git config --local user.name "gitea-actions[bot]"
- git add updates.xml
+ # Commit version bump if changed
+ git add -A
git diff --cached --quiet || {
- git commit -m "chore: update updates.xml (${STABILITY}: ${DISPLAY_VERSION}) [skip ci]" \
+ git commit -m "chore(version): auto-bump ${VERSION} [skip ci]" \
--author="gitea-actions[bot] "
git push
}
- # -- Sync updates.xml to main (for non-main branches) ----------------------
+ - name: Create release and upload package
+ id: package
+ run: |
+ VERSION="${{ steps.meta.outputs.version }}"
+ TAG="${{ steps.meta.outputs.tag }}"
+ API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
+
+ # Create or update Gitea release
+ php ${MOKO_CLI}/release_create.php \
+ --path . --version "$VERSION" --tag "$TAG" \
+ --token "${{ secrets.GA_TOKEN }}" --api-base "$API_BASE" \
+ --repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease
+
+ # Build package and upload
+ php ${MOKO_CLI}/release_package.php \
+ --path . --version "$VERSION" --tag "$TAG" \
+ --token "${{ secrets.GA_TOKEN }}" --api-base "$API_BASE" \
+ --repo "${GITEA_REPO}" --output /tmp || true
+
+ - name: Update updates.xml
+ if: steps.platform.outputs.platform == 'joomla'
+ run: |
+ VERSION="${{ steps.meta.outputs.version }}"
+ STABILITY="${{ steps.meta.outputs.stability }}"
+ SHA256="${{ steps.package.outputs.sha256_zip }}"
+
+ if [ ! -f "updates.xml" ]; then
+ echo "No updates.xml — skipping"
+ exit 0
+ fi
+
+ SHA_FLAG=""
+ [ -n "$SHA256" ] && SHA_FLAG="--sha ${SHA256}"
+
+ php ${MOKO_CLI}/updates_xml_build.php \
+ --path . --version "${VERSION}" --stability "${STABILITY}" \
+ --gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
+ ${SHA_FLAG}
+
+ # Commit and push updates.xml
+ git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
+ git config --local user.name "gitea-actions[bot]"
+ git add updates.xml
+ git diff --cached --quiet || {
+ git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]"
+ git push
+ }
+
- name: Sync updates.xml to main
- if: github.ref_name != 'main'
+ if: github.ref_name != 'main' && steps.platform.outputs.platform == 'joomla'
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
GA_TOKEN="${{ secrets.GA_TOKEN }}"
@@ -394,7 +218,7 @@ jobs:
payload = json.dumps({
'content': content,
'sha': '${FILE_SHA}',
- 'message': 'chore: sync updates.xml from ${STABILITY} [skip ci]',
+ 'message': 'chore: sync updates.xml from ${{ steps.meta.outputs.stability }} [skip ci]',
'branch': 'main'
}).encode()
req = urllib.request.Request(
@@ -408,13 +232,8 @@ jobs:
urllib.request.urlopen(req)
print('updates.xml synced to main')
except Exception as e:
- print(f'ERROR: failed to sync updates.xml to main: {e}', file=sys.stderr)
- sys.exit(1)
- " \
- && echo "updates.xml synced to main (${STABILITY})" >> $GITHUB_STEP_SUMMARY \
- || echo "::error::failed to sync updates.xml to main" >> $GITHUB_STEP_SUMMARY
- else
- echo "::error::could not get updates.xml SHA from main — file may not exist on main yet" >> $GITHUB_STEP_SUMMARY
+ print(f'WARNING: sync to main failed: {e}', file=sys.stderr)
+ "
fi
- name: SFTP deploy to dev server
@@ -428,9 +247,8 @@ jobs:
DEV_KEY: ${{ secrets.DEV_FTP_KEY }}
DEV_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
run: |
- # -- Permission check: admin or maintain role required --------
+ # Permission check: admin or maintain role required
ACTOR="${{ github.actor }}"
- REPO="${{ github.repository }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
@@ -463,198 +281,24 @@ jobs:
printf ',"password":"%s"}' "$DEV_PASS" >> /tmp/sftp-config.json
fi
- PLATFORM=$(php /tmp/moko-platform/cli/platform_detect.php --path . 2>/dev/null || true)
- if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/moko-platform/deploy/deploy-joomla.php" ]; then
- php /tmp/moko-platform/deploy/deploy-joomla.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
- elif [ -f "/tmp/moko-platform/deploy/deploy-sftp.php" ]; then
- php /tmp/moko-platform/deploy/deploy-sftp.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
+ PLATFORM=$(php ${MOKO_CLI}/platform_detect.php --path . 2>/dev/null || true)
+ if [ "$PLATFORM" = "waas-component" ] && [ -f "${MOKO_CLI}/../deploy/deploy-joomla.php" ]; then
+ php ${MOKO_CLI}/../deploy/deploy-joomla.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
+ elif [ -f "${MOKO_CLI}/../deploy/deploy-sftp.php" ]; then
+ php ${MOKO_CLI}/../deploy/deploy-sftp.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
fi
rm -f /tmp/deploy_key /tmp/sftp-config.json
echo "SFTP deploy to dev complete" >> $GITHUB_STEP_SUMMARY
- - name: Validate updates.xml integrity
- run: |
- ERRORS=0
-
- if [ ! -f "updates.xml" ]; then
- echo "::error::updates.xml not found"
- exit 1
- fi
-
- # Well-formed XML
- if ! python3 -c "import xml.etree.ElementTree as ET; ET.parse('updates.xml')" 2>/dev/null; then
- echo "::error::updates.xml is not valid XML"
- ERRORS=$((ERRORS+1))
- fi
-
- python3 << 'PYEOF'
- import xml.etree.ElementTree as ET, sys, re, os
-
- tree = ET.parse("updates.xml")
- root = tree.getroot()
- updates = root.findall("update")
- errors = 0
- warnings = 0
- seen_tags = set()
-
- # All 5 channels MUST be present
- REQUIRED_CHANNELS = {"stable", "rc", "beta", "alpha", "dev"}
- VALID_TAGS = REQUIRED_CHANNELS | {"development"} # accept legacy alias
- REPO = os.environ.get("GITEA_REPO", "")
- ORG = os.environ.get("GITEA_ORG", "MokoConsulting")
- REPO_BASE = f"https://git.mokoconsulting.tech/{ORG}/"
-
- # Gitea release tag names per channel (Moko standard)
- RELEASE_TAG_MAP = {
- "stable": "stable",
- "rc": "release-candidate",
- "beta": "beta",
- "alpha": "alpha",
- "dev": "development",
- "development": "development",
- }
-
- # Joomla update XML required fields per
- # https://docs.joomla.org/Deploying_an_Update_Server
- REQUIRED_FIELDS = ["name", "element", "type", "version", "infourl"]
-
- for i, u in enumerate(updates):
- tag_el = u.find("tags/tag")
- tag = tag_el.text.strip() if tag_el is not None and tag_el.text else None
- label = f"Entry {i+1} ({tag or '?'})"
-
- # -- Required Joomla fields --
- for field in REQUIRED_FIELDS:
- el = u.find(field)
- if el is None or not (el.text or "").strip():
- print(f"::error::{label}: missing required <{field}>")
- errors += 1
-
- # -- --
- dl = u.find("downloads/downloadurl")
- if dl is None or not (dl.text or "").strip():
- print(f"::error::{label}: missing ")
- errors += 1
- else:
- dl_url = dl.text.strip()
- # Must point to org repo
- if REPO_BASE not in dl_url:
- print(f"::error::{label}: download URL not under {REPO_BASE}: {dl_url}")
- errors += 1
- # Must end in .zip
- if not dl_url.endswith(".zip"):
- print(f"::error::{label}: download URL must end in .zip: {dl_url}")
- errors += 1
- # Must use correct Gitea release tag in path
- if tag and tag in RELEASE_TAG_MAP:
- expected_tag = RELEASE_TAG_MAP[tag]
- if f"/download/{expected_tag}/" not in dl_url:
- print(f"::error::{label}: download URL should contain /download/{expected_tag}/ but got: {dl_url}")
- errors += 1
-
- # -- (required for Joomla to match update) --
- client = u.find("client")
- if client is None or not (client.text or "").strip():
- print(f"::error::{label}: missing (required for Joomla update matching)")
- errors += 1
-
- # -- --
- tp = u.find("targetplatform")
- if tp is None:
- print(f"::error::{label}: missing ")
- errors += 1
- else:
- tp_name = tp.get("name", "")
- tp_ver = tp.get("version", "")
- if tp_name != "joomla":
- print(f"::error::{label}: targetplatform name should be 'joomla', got '{tp_name}'")
- errors += 1
- if not tp_ver:
- print(f"::error::{label}: targetplatform missing version regex")
- errors += 1
- elif "5" not in tp_ver or "6" not in tp_ver:
- print(f"::warning::{label}: targetplatform version may not cover Joomla 5+6: {tp_ver}")
- warnings += 1
-
- # -- must be valid Joomla type --
- type_el = u.find("type")
- if type_el is not None and type_el.text:
- valid_types = {"component", "module", "plugin", "template", "library", "package", "file"}
- if type_el.text.strip() not in valid_types:
- print(f"::error::{label}: invalid type '{type_el.text}' (expected: {valid_types})")
- errors += 1
-
- # -- format (XX.YY.ZZ with optional suffix) --
- ver_el = u.find("version")
- if ver_el is not None and ver_el.text:
- if not re.match(r"^\d{2}\.\d{2}\.\d{2}(-\w+)?$", ver_el.text.strip()):
- print(f"::warning::{label}: version '{ver_el.text}' does not match XX.YY.ZZ format")
- warnings += 1
-
- # -- and --
- for field in ["maintainer", "maintainerurl"]:
- el = u.find(field)
- if el is None or not (el.text or "").strip():
- print(f"::warning::{label}: missing <{field}>")
- warnings += 1
-
- # -- Valid stability tag --
- if tag is None:
- print(f"::error::{label}: missing ")
- errors += 1
- elif tag not in VALID_TAGS:
- print(f"::error::{label}: invalid tag '{tag}' (expected: {VALID_TAGS})")
- errors += 1
-
- # -- Duplicate tag check --
- norm_tag = "dev" if tag == "development" else tag
- if norm_tag in seen_tags:
- print(f"::error::{label}: duplicate channel '{tag}'")
- errors += 1
- if norm_tag:
- seen_tags.add(norm_tag)
-
- # -- All 5 channels must exist --
- missing = REQUIRED_CHANNELS - seen_tags
- if missing:
- print(f"::error::Missing required update channels: {', '.join(sorted(missing))}")
- errors += 1
-
- # -- Version ordering: higher stability must not exceed dev version --
- channel_versions = {}
- for u in updates:
- tag_el = u.find("tags/tag")
- ver_el = u.find("version")
- if tag_el is not None and ver_el is not None and tag_el.text and ver_el.text:
- norm = "dev" if tag_el.text.strip() == "development" else tag_el.text.strip()
- # Strip suffix for comparison (01.00.18-dev -> 01.00.18)
- base_ver = re.sub(r"-\w+$", "", ver_el.text.strip())
- channel_versions[norm] = base_ver
-
- # Cascade check: dev >= alpha >= beta >= rc >= stable
- ORDER = ["dev", "alpha", "beta", "rc", "stable"]
- for j in range(1, len(ORDER)):
- current = ORDER[j]
- previous = ORDER[j - 1]
- if current in channel_versions and previous in channel_versions:
- if channel_versions[current] > channel_versions[previous]:
- print(f"::error::{current} version ({channel_versions[current]}) is ahead of {previous} ({channel_versions[previous]})")
- errors += 1
-
- # -- Summary --
- print(f"\nupdates.xml validation: {len(updates)} entries, {errors} error(s), {warnings} warning(s)")
- if errors > 0:
- sys.exit(1)
- PYEOF
-
- name: Summary
if: always()
run: |
- echo "## Joomla Update Server" >> $GITHUB_STEP_SUMMARY
+ VERSION="${{ steps.meta.outputs.version }}"
+ STABILITY="${{ steps.meta.outputs.stability }}"
+ DISPLAY="${{ steps.meta.outputs.display_version }}"
+ echo "## Update Server" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Stability | \`${STABILITY}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Version | \`${DISPLAY_VERSION}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Element | \`${EXT_ELEMENT}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Download | [ZIP](${DOWNLOAD_URL}) |" >> $GITHUB_STEP_SUMMARY
+ echo "| Version | \`${DISPLAY}\` |" >> $GITHUB_STEP_SUMMARY
--
2.52.0
From 167a7c0dfd44cec98a098a34c316286165ff7c4a Mon Sep 17 00:00:00 2001
From: "gitea-actions[bot]"
Date: Thu, 28 May 2026 15:59:48 +0000
Subject: [PATCH 3/4] chore(version): patch bump to 02.12.01 [skip ci]
---
README.md | 2 +-
src/packages/com_mokowaas/mokowaas.xml | 2 +-
src/packages/plg_system_mokowaas/mokowaas.xml | 2 +-
src/packages/plg_webservices_mokowaas/mokowaas.xml | 2 +-
src/pkg_mokowaas.xml | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index bb2e6841..fc3f3b62 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
DEFGROUP: Joomla.Plugin
INGROUP: MokoWaaS
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS
- VERSION: 02.11.04
+ VERSION: 02.12.01
PATH: /README.md
BRIEF: MokoWaaS platform plugin for Joomla
-->
diff --git a/src/packages/com_mokowaas/mokowaas.xml b/src/packages/com_mokowaas/mokowaas.xml
index 9c795d34..1e509aea 100644
--- a/src/packages/com_mokowaas/mokowaas.xml
+++ b/src/packages/com_mokowaas/mokowaas.xml
@@ -7,7 +7,7 @@
GPL-3.0-or-later
hello@mokoconsulting.tech
https://mokoconsulting.tech
- 02.11.04
+ 02.12.01
Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.
Moko\Component\MokoWaaS\Api
diff --git a/src/packages/plg_system_mokowaas/mokowaas.xml b/src/packages/plg_system_mokowaas/mokowaas.xml
index 9c32a44d..d3ac0aa0 100644
--- a/src/packages/plg_system_mokowaas/mokowaas.xml
+++ b/src/packages/plg_system_mokowaas/mokowaas.xml
@@ -30,7 +30,7 @@
GNU General Public License version 3 or later; see LICENSE.md
hello@mokoconsulting.tech
https://mokoconsulting.tech
- 02.11.04
+ 02.12.01
This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.
Moko\Plugin\System\MokoWaaS
script.php
diff --git a/src/packages/plg_webservices_mokowaas/mokowaas.xml b/src/packages/plg_webservices_mokowaas/mokowaas.xml
index 4966ed7c..c5de2197 100644
--- a/src/packages/plg_webservices_mokowaas/mokowaas.xml
+++ b/src/packages/plg_webservices_mokowaas/mokowaas.xml
@@ -7,7 +7,7 @@
GPL-3.0-or-later
hello@mokoconsulting.tech
https://mokoconsulting.tech
- 02.11.04
+ 02.12.01
Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.
Moko\Plugin\WebServices\MokoWaaS
diff --git a/src/pkg_mokowaas.xml b/src/pkg_mokowaas.xml
index 8386ddbd..3653607a 100644
--- a/src/pkg_mokowaas.xml
+++ b/src/pkg_mokowaas.xml
@@ -2,7 +2,7 @@
MokoWaaS
mokowaas
- 02.11.04
+ 02.12.01
2026-05-23
Moko Consulting
hello@mokoconsulting.tech
--
2.52.0
From 56abe3af7f27df4167e67642d2ef4212a43e2d27 Mon Sep 17 00:00:00 2001
From: "gitea-actions[bot]"
Date: Thu, 28 May 2026 16:01:25 +0000
Subject: [PATCH 4/4] chore(version): patch bump to 02.12.01 [skip ci]
---
README.md | 2 +-
src/packages/com_mokowaas/mokowaas.xml | 2 +-
src/packages/plg_system_mokowaas/mokowaas.xml | 2 +-
src/packages/plg_webservices_mokowaas/mokowaas.xml | 2 +-
src/pkg_mokowaas.xml | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/README.md b/README.md
index 1233cead..fc3f3b62 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
DEFGROUP: Joomla.Plugin
INGROUP: MokoWaaS
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS
- VERSION: 02.12.00
+ VERSION: 02.12.01
PATH: /README.md
BRIEF: MokoWaaS platform plugin for Joomla
-->
diff --git a/src/packages/com_mokowaas/mokowaas.xml b/src/packages/com_mokowaas/mokowaas.xml
index 4900e4c0..1e509aea 100644
--- a/src/packages/com_mokowaas/mokowaas.xml
+++ b/src/packages/com_mokowaas/mokowaas.xml
@@ -7,7 +7,7 @@
GPL-3.0-or-later
hello@mokoconsulting.tech
https://mokoconsulting.tech
- 02.12.00
+ 02.12.01
Minimal API-only component for MokoWaaS. Provides REST endpoints for site health, cache, updates, and backups.
Moko\Component\MokoWaaS\Api
diff --git a/src/packages/plg_system_mokowaas/mokowaas.xml b/src/packages/plg_system_mokowaas/mokowaas.xml
index 73474e9e..d3ac0aa0 100644
--- a/src/packages/plg_system_mokowaas/mokowaas.xml
+++ b/src/packages/plg_system_mokowaas/mokowaas.xml
@@ -30,7 +30,7 @@
GNU General Public License version 3 or later; see LICENSE.md
hello@mokoconsulting.tech
https://mokoconsulting.tech
- 02.12.00
+ 02.12.01
This plugin rebrands the Joomla system interface with MokoWaaS identity. It applies language overrides and ensures consistent branding across the platform.
Moko\Plugin\System\MokoWaaS
script.php
diff --git a/src/packages/plg_webservices_mokowaas/mokowaas.xml b/src/packages/plg_webservices_mokowaas/mokowaas.xml
index a0629941..c5de2197 100644
--- a/src/packages/plg_webservices_mokowaas/mokowaas.xml
+++ b/src/packages/plg_webservices_mokowaas/mokowaas.xml
@@ -7,7 +7,7 @@
GPL-3.0-or-later
hello@mokoconsulting.tech
https://mokoconsulting.tech
- 02.12.00
+ 02.12.01
Joomla Web Services API routes for MokoWaaS site management — health checks, cache, updates, backups, and site info.
Moko\Plugin\WebServices\MokoWaaS
diff --git a/src/pkg_mokowaas.xml b/src/pkg_mokowaas.xml
index 9b58fa4b..3653607a 100644
--- a/src/pkg_mokowaas.xml
+++ b/src/pkg_mokowaas.xml
@@ -2,7 +2,7 @@
MokoWaaS
mokowaas
- 02.12.00
+ 02.12.01
2026-05-23
Moko Consulting
hello@mokoconsulting.tech
--
2.52.0