diff --git a/.mokogitea/manifest.xml b/.mokogitea/manifest.xml
new file mode 100644
index 0000000..eeac3cb
--- /dev/null
+++ b/.mokogitea/manifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ MokoWaaS
+ MokoConsulting
+ White-label identity, security hardening, and tenant restriction layer for WaaS-managed Joomla environments
+ GNU General Public License v3
+
+
+ joomla
+ 05.00.00
+ https://git.mokoconsulting.tech/MokoConsulting/moko-platform
+ 2026-05-21T20:48:00+00:00
+
+
+ PHP
+ plugin
+ src/
+
+
diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml
index dbaf151..c863ce2 100644
--- a/.mokogitea/workflows/auto-release.yml
+++ b/.mokogitea/workflows/auto-release.yml
@@ -8,13 +8,13 @@
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
# PATH: /templates/workflows/universal/auto-release.yml.template
# VERSION: 05.00.00
-# BRIEF: Universal build & release � detects platform from manifest.xml
+# BRIEF: Universal build & release � detects platform from .moko-platform
#
# +========================================================================+
# | UNIVERSAL BUILD & RELEASE PIPELINE |
# +========================================================================+
# | |
-# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
+# | Reads .moko-platform (joomla|dolibarr|generic) to branch logic. |
# | |
# | Platform-specific: |
# | joomla: XML manifest, updates.xml, type-prefixed packages |
@@ -79,16 +79,15 @@ jobs:
- name: Detect platform
id: platform
run: |
- # Parse .manifest.xml via manifest_read.php — outputs all fields to GITHUB_OUTPUT
- php /tmp/mokostandards-api/cli/manifest_read.php --path . --github-output 2>/dev/null || true
- PLATFORM=$(php /tmp/mokostandards-api/cli/manifest_read.php --path . --field platform 2>/dev/null)
+ PLATFORM=$(cat .mokogitea/.moko-platform 2>/dev/null | tr -d '[:space:]')
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
echo "Platform detected: ${PLATFORM}"
- # entry-point from manifest, find as fallback
- MOD_FILE=$(php /tmp/mokostandards-api/cli/manifest_read.php --path . --field entry-point 2>/dev/null)
- [ -z "$MOD_FILE" ] && MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
- MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1)
+ # For packages: prefer pkg_*.xml in src/; fallback to any manifest
+ MANIFEST=$(find ./src -maxdepth 1 -name "pkg_*.xml" -exec grep -l '/dev/null | head -1)
+ [ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "*/packages/*" -exec grep -l '/dev/null | head -1)
+ [ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1)
+ MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
@@ -161,6 +160,17 @@ jobs:
[ -n "$MANIFEST_VER" ] && sed -i "s|${MANIFEST_VER}|${VERSION}|" "$MANIFEST"
sed -i "s|[^<]*|${TODAY}|" "$MANIFEST"
fi
+ # For packages: also bump version in all sub-extension manifests
+ if [ -d "src/packages" ]; then
+ for SUB_MANIFEST in $(find src/packages -maxdepth 2 -name "*.xml" -exec grep -l '/dev/null); do
+ SUB_VER=$(sed -n 's/.*\([^<]*\)<\/version>.*/\1/p' "$SUB_MANIFEST" | head -1)
+ if [ -n "$SUB_VER" ]; then
+ sed -i "s|${SUB_VER}|${VERSION}|" "$SUB_MANIFEST"
+ sed -i "s|[^<]*|${TODAY}|" "$SUB_MANIFEST"
+ echo " Bumped sub-extension: $(basename $SUB_MANIFEST) ${SUB_VER} → ${VERSION}"
+ fi
+ done
+ fi
;;
dolibarr)
if [ -n "$MOD_FILE" ]; then
@@ -187,7 +197,7 @@ jobs:
git add -A
git diff --cached --quiet || {
git commit -m "chore(version): bump ${CURRENT} → ${VERSION} [skip ci]"
- git push origin HEAD:dev 2>&1 || git push origin HEAD:main 2>&1
+ git push origin HEAD:main 2>&1
}
# Override version output for rest of pipeline
@@ -364,7 +374,8 @@ jobs:
REPO="${{ github.repository }}"
# -- Parse extension metadata from XML manifest ----------------
- MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '/dev/null | head -1)
+ MANIFEST=$(find ./src -maxdepth 1 -name "pkg_*.xml" -exec grep -l '/dev/null | head -1)
+ [ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 2 -name "*.xml" ! -path "*/packages/*" -exec grep -l '/dev/null | head -1)
if [ -z "$MANIFEST" ]; then
echo "Warning: No Joomla XML manifest found — skipping updates.xml" >> $GITHUB_STEP_SUMMARY
exit 0
@@ -621,7 +632,8 @@ jobs:
fi
# Find extension element name from manifest
- MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '/dev/null | head -1 || true)
+ MANIFEST=$(find ./src -maxdepth 1 -name "pkg_*.xml" -exec grep -l '/dev/null | head -1)
+ [ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 2 -name "*.xml" ! -path "*/packages/*" -exec grep -l '/dev/null | head -1 || true)
[ -z "$MANIFEST" ] && exit 0
# Reuse element from Step 5, with same fallback chain
@@ -654,15 +666,39 @@ jobs:
EXCLUDES=".ftpignore sftp-config* *.ppk *.pem *.key .env*"
- # ZIP package
- cd "$SOURCE_DIR"
- zip -r "/tmp/${ZIP_NAME}" . -x $EXCLUDES
- cd ..
+ if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then
+ echo "=== Building Joomla PACKAGE (multi-extension) ==="
+ PKG_STAGE=$(mktemp -d)
- # tar.gz package
- tar -czf "/tmp/${TAR_NAME}" -C "$SOURCE_DIR" \
- --exclude='.ftpignore' --exclude='sftp-config*' \
- --exclude='*.ppk' --exclude='*.pem' --exclude='*.key' --exclude='.env*' .
+ # ZIP each sub-extension
+ for ext_dir in "${SOURCE_DIR}"/packages/*/; do
+ [ ! -d "$ext_dir" ] && continue
+ SUB_NAME=$(basename "$ext_dir")
+ echo " Packaging sub-extension: ${SUB_NAME}"
+ (cd "$ext_dir" && zip -r "${PKG_STAGE}/${SUB_NAME}.zip" . -x $EXCLUDES)
+ done
+
+ # Copy package-level files (manifest, script, etc.)
+ for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do
+ [ -f "$f" ] && cp "$f" "${PKG_STAGE}/"
+ done
+
+ # Create ZIP and tar.gz from staged package
+ (cd "$PKG_STAGE" && zip -r "/tmp/${ZIP_NAME}" .)
+ tar -czf "/tmp/${TAR_NAME}" -C "$PKG_STAGE" .
+
+ rm -rf "$PKG_STAGE"
+ echo "Package contents built with sub-extension ZIPs"
+ else
+ # Standard extension: flat ZIP from src/
+ cd "$SOURCE_DIR"
+ zip -r "/tmp/${ZIP_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*' .
+ fi
ZIP_SIZE=$(stat -c%s "/tmp/${ZIP_NAME}" 2>/dev/null || stat -f%z "/tmp/${ZIP_NAME}" 2>/dev/null || echo "unknown")
TAR_SIZE=$(stat -c%s "/tmp/${TAR_NAME}" 2>/dev/null || stat -f%z "/tmp/${TAR_NAME}" 2>/dev/null || echo "unknown")
@@ -941,30 +977,25 @@ jobs:
done
echo "Cleaned up ${DELETED} pre-release channel(s)" >> $GITHUB_STEP_SUMMARY
- # -- STEP 11: Sync dev branch with main + version bump ----------------------
- - name: "Step 11: Merge main into dev (version bump lands on dev)"
+ # -- STEP 11: Reset dev branch from main ------------------------------------
+ - name: "Step 11: Delete and recreate dev 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 }}"
- # Merge main into dev so dev has the release + version bump
+ # Delete dev branch
+ curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
+ "${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
+
+ # Recreate dev from main (now includes version bump + changelog promotion)
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
- "${API_BASE}/merges" \
- -d "{\"base\":\"dev\",\"head\":\"main\",\"message\":\"chore: sync main into dev after release [skip ci]\"}" \
- 2>/dev/null && echo "Merged main into dev"
+ "${API_BASE}/branches" \
+ -d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
- # If dev doesn't exist, create it from main
- if [ $? -ne 0 ]; then
- curl -sf -X POST -H "Authorization: token ${TOKEN}" \
- -H "Content-Type: application/json" \
- "${API_BASE}/branches" \
- -d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Created dev from main"
- fi
-
- echo "Dev branch synced with main (version bump on dev)" >> $GITHUB_STEP_SUMMARY
+ echo "Dev branch reset from main (keeps dev ahead after release)" >> $GITHUB_STEP_SUMMARY
# -- Dolibarr post-release: Reset dev version -----------------------------
diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml
index c70ea7d..8a7a766 100644
--- a/.mokogitea/workflows/pre-release.yml
+++ b/.mokogitea/workflows/pre-release.yml
@@ -55,12 +55,13 @@ jobs:
- name: Detect platform
id: platform
run: |
- # Read platform from XML manifest ( tag) or plain text fallback
- PLATFORM=$(sed -n 's/.*\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1)
- [ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]')
+ PLATFORM=$(cat .mokogitea/.moko-platform 2>/dev/null | tr -d '[:space:]')
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
- MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1)
+ # For packages: prefer pkg_*.xml in src/; fallback to any manifest
+ MANIFEST=$(find ./src -maxdepth 1 -name "pkg_*.xml" -exec grep -l '/dev/null | head -1)
+ [ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "*/packages/*" -exec grep -l '/dev/null | head -1)
+ [ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1)
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
@@ -118,6 +119,17 @@ jobs:
sed -i "s|${MANIFEST_VER}|${VERSION}|" "$MANIFEST"
sed -i "s|[^<]*|${TODAY}|" "$MANIFEST"
fi
+ # For packages: also bump version in all sub-extension manifests
+ if [ -d "src/packages" ]; then
+ for SUB_MANIFEST in $(find src/packages -maxdepth 2 -name "*.xml" -exec grep -l '/dev/null); do
+ SUB_VER=$(sed -n 's/.*\([^<]*\)<\/version>.*/\1/p' "$SUB_MANIFEST" | head -1)
+ if [ -n "$SUB_VER" ]; then
+ sed -i "s|${SUB_VER}|${VERSION}|" "$SUB_MANIFEST"
+ sed -i "s|[^<]*|${TODAY}|" "$SUB_MANIFEST"
+ echo " Bumped sub-extension: $(basename $SUB_MANIFEST) ${SUB_VER} → ${VERSION}"
+ fi
+ done
+ fi
;;
dolibarr)
if [ -n "$MOD_FILE" ]; then
@@ -189,17 +201,49 @@ jobs:
exit 1
fi
+ MANIFEST="${{ steps.meta.outputs.manifest }}"
+ EXT_TYPE=""
+ if [ -n "$MANIFEST" ]; then
+ EXT_TYPE=$(sed -n 's/.*]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
+ fi
+
+ EXCLUDES="sftp-config* .ftpignore *.ppk *.pem *.key .env* *.local .build-trigger"
+
mkdir -p build/package
- rsync -a \
- --exclude='sftp-config*' \
- --exclude='.ftpignore' \
- --exclude='*.ppk' \
- --exclude='*.pem' \
- --exclude='*.key' \
- --exclude='.env*' \
- --exclude='*.local' \
- --exclude='.build-trigger' \
- "${SOURCE_DIR}/" build/package/
+
+ if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then
+ echo "=== Building Joomla PACKAGE (multi-extension) ==="
+
+ # 1) ZIP each sub-extension in src/packages/
+ for ext_dir in "${SOURCE_DIR}"/packages/*/; do
+ [ ! -d "$ext_dir" ] && continue
+ EXT_NAME=$(basename "$ext_dir")
+ echo " Packaging sub-extension: ${EXT_NAME}"
+ cd "$ext_dir"
+ zip -r "../../build/package/${EXT_NAME}.zip" . -x $EXCLUDES
+ cd "$OLDPWD"
+ done
+
+ # 2) Copy package-level files (manifest, script, etc.)
+ for f in "${SOURCE_DIR}"/*.xml "${SOURCE_DIR}"/*.php; do
+ [ -f "$f" ] && cp "$f" build/package/
+ done
+
+ echo "Package contents:"
+ ls -la build/package/
+ else
+ echo "=== Building standard Joomla extension ==="
+ rsync -a \
+ --exclude='sftp-config*' \
+ --exclude='.ftpignore' \
+ --exclude='*.ppk' \
+ --exclude='*.pem' \
+ --exclude='*.key' \
+ --exclude='.env*' \
+ --exclude='*.local' \
+ --exclude='.build-trigger' \
+ "${SOURCE_DIR}/" build/package/
+ fi
- name: Create ZIP
id: zip