diff --git a/.mokogitea/manifest.xml b/.mokogitea/manifest.xml
new file mode 100644
index 0000000..23beccb
--- /dev/null
+++ b/.mokogitea/manifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+ Template-Joomla
+ MokoConsulting
+ Template repository for Joomla extensions (plugins, modules, components, templates)
+ GNU General Public License v3
+
+
+ joomla
+ 05.00.00
+ https://git.mokoconsulting.tech/MokoConsulting/moko-platform
+
+
+ PHP
+ joomla-extension
+ src/
+
+
diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml
index 46ce4b2..787b7a0 100644
--- a/.mokogitea/workflows/auto-release.yml
+++ b/.mokogitea/workflows/auto-release.yml
@@ -79,131 +79,37 @@ jobs:
- name: Detect platform
id: platform
run: |
- # Read platform from manifest.xml element; fallback to generic
- PLATFORM=$(sed -n 's/.*\([^<]*\)<\/platform>.*//p' .mokogitea/manifest.xml 2>/dev/null | head -1 | tr -d '[:space:]')
- [ -z "$PLATFORM" ] && PLATFORM="generic"
- echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
- echo "Platform detected: ${PLATFORM}"
- # 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)
+ php /tmp/moko-platform-api/cli/manifest_read.php --path . --github-output
+ MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1 || true)
+ MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1 || true)
echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "mod_file=${MOD_FILE}" >> "$GITHUB_OUTPUT"
- # -- STEP 1: Read version -----------------------------------------------
- - name: "Step 1: Read version from README.md"
+ - name: "Step 1: Read version"
id: version
run: |
- VERSION=$(php /tmp/moko-platform-api/cli/version_read.php --path . 2>/dev/null)
+ VERSION=$(php /tmp/moko-platform-api/cli/version_read.php --path .)
if [ -z "$VERSION" ]; then
- echo "No VERSION in README.md — skipping release"
+ echo "::error::No VERSION in README.md"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
- # Derive major.minor for branch naming (patches update existing branch)
- MINOR=$(echo "$VERSION" | awk -F. '{printf "%s.%s", $1, $2}')
- PATCH=$(echo "$VERSION" | awk -F. '{print $3}')
-
- MAJOR=$(echo "$VERSION" | awk -F. '{print $1}')
- MINOR_NUM=$(echo "$VERSION" | awk -F. '{print $2}')
-
- echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
- echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
- echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
- echo "release_tag=stable" >> "$GITHUB_OUTPUT"
- echo "stability=stable" >> "$GITHUB_OUTPUT"
- echo "skip=false" >> "$GITHUB_OUTPUT"
- if [ "$PATCH" = "00" ] || [ "$PATCH" = "01" ]; then
- echo "is_minor=true" >> "$GITHUB_OUTPUT"
- echo "Version: $VERSION (first release for this minor — full pipeline)"
- else
- echo "is_minor=false" >> "$GITHUB_OUTPUT"
- echo "Version: $VERSION (patch — platform version + badges only)"
- fi
-
- # -- STEP 1b: Bump minor version (stable = minor bump, reset patch) ------
- - name: "Step 1b: Bump minor version for stable release"
- if: steps.version.outputs.skip != 'true'
- id: bump
- run: |
- CURRENT=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1)
- [ -z "$CURRENT" ] && { echo "skip=true" >> "$GITHUB_OUTPUT"; exit 0; }
-
- MAJOR=$((10#$(echo "$CURRENT" | cut -d. -f1)))
- MINOR=$((10#$(echo "$CURRENT" | cut -d. -f2)))
-
- # Minor bump, reset patch. Rollover if minor > 99
- MINOR=$((MINOR + 1))
- if [ $MINOR -gt 99 ]; then
- MINOR=0
- MAJOR=$((MAJOR + 1))
- fi
-
- VERSION=$(printf "%02d.%02d.00" $MAJOR $MINOR)
- TODAY=$(date +%Y-%m-%d)
-
- echo "Stable bump: ${CURRENT} → ${VERSION} (minor)"
-
- # Update README.md
- sed -i "s/VERSION:[[:space:]]*${CURRENT}/VERSION: ${VERSION}/" README.md
-
- # Update platform-specific manifest
- PLATFORM="${{ steps.platform.outputs.platform }}"
- MANIFEST="${{ steps.platform.outputs.manifest }}"
- MOD_FILE="${{ steps.platform.outputs.mod_file }}"
- case "$PLATFORM" in
- joomla)
- if [ -n "$MANIFEST" ]; then
- MANIFEST_VER=$(sed -n 's/.*\([^<]*\)<\/version>.*/\1/p' "$MANIFEST" | head -1)
- [ -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
- sed -i "s/\$this->version = '[^']*'/\$this->version = '${VERSION}'/" "$MOD_FILE"
- fi
- echo "${VERSION}" > update.txt
- ;;
- *) ;;
- esac
-
- # Promote [Unreleased] section in CHANGELOG.md to new version
- if [ -f "CHANGELOG.md" ] && grep -qi "Unreleased" CHANGELOG.md; then
- sed -i "s|## \[Unreleased\]|## [${VERSION}] --- ${TODAY}|" CHANGELOG.md
- sed -i "s|## Unreleased|## [${VERSION}] --- ${TODAY}|" CHANGELOG.md
- sed -i "2i ## [Unreleased]" CHANGELOG.md
- sed -i "3i \\ " CHANGELOG.md
- echo "CHANGELOG promoted to [${VERSION}]"
- fi
-
- # Commit and push
- 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
- git diff --cached --quiet || {
- git commit -m "chore(version): bump ${CURRENT} → ${VERSION} [skip ci]"
- git push origin HEAD:main 2>&1
- }
-
- # Override version output for rest of pipeline
+ MAJOR=$(echo "$VERSION" | cut -d. -f1)
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
- echo "major=$(printf "%02d" $MAJOR)" >> "$GITHUB_OUTPUT"
+ echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT"
+ echo "skip=false" >> "$GITHUB_OUTPUT"
+ echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
+
+ - name: "Step 1b: Bump version"
+ id: bump
+ if: steps.version.outputs.skip != 'true'
+ run: |
+ MOKO_API="/tmp/moko-platform-api/cli"
+ BUMP=$(php ${MOKO_API}/version_bump.php --path . --minor)
+ VERSION=$(echo "$BUMP" | grep -oP '\d{2}\.\d{2}\.\d{2}$' || true)
+ [ -z "$VERSION" ] && VERSION=$(php ${MOKO_API}/version_read.php --path .)
+ echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
+ echo "Bumped to: ${VERSION}"
- name: Check if already released
if: steps.version.outputs.skip != 'true'
@@ -353,166 +259,22 @@ jobs:
# -- STEP 4: Update version badges ----------------------------------------
- name: "Step 4: Update version badges"
- if: >-
- steps.version.outputs.skip != 'true' &&
- steps.check.outputs.already_released != 'true'
+ if: steps.version.outputs.skip != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
- find . -name "*.md" ! -path "./.git/*" ! -path "./vendor/*" | while read -r f; do
- if grep -q '\[VERSION:' "$f" 2>/dev/null; then
- sed -i "s/\[VERSION:[[:space:]]*[0-9]\{2\}\.[0-9]\{2\}\.[0-9]\{2\}\]/[VERSION: ${VERSION}]/" "$f"
- fi
- done
+ php /tmp/moko-platform-api/cli/badge_update.php --path . --version "${VERSION}" 2>/dev/null || true
- # -- STEP 5: Write updates.xml (Joomla update server) ---------------------
- name: "Step 5: Write update stream"
- id: updates
if: >-
steps.version.outputs.skip != 'true' &&
- steps.check.outputs.already_released != 'true'
+ steps.platform.outputs.platform == 'joomla'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
- REPO="${{ github.repository }}"
+ php /tmp/moko-platform-api/cli/updates_xml_build.php \
+ --path . --version "${VERSION}" --stability stable \
+ --gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
+ --github-output
- # -- Parse extension metadata from XML manifest ----------------
- 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
- fi
-
- # Extract fields using sed (portable — no grep -P)
- 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)
- TARGET_PLATFORM=$(sed -n 's/.*\(\).*/\1/p' "$MANIFEST" | head -1)
- PHP_MINIMUM=$(sed -n 's/.*\([^<]*\)<\/php_minimum>.*/\1/p' "$MANIFEST" | head -1)
-
- # If EXT_NAME is a language key (e.g. PLG_SYSTEM_MOKOJGDPC), resolve from .ini
- if echo "$EXT_NAME" | grep -qE '^[A-Z_]+$'; then
- INI_NAME=$(find . -name "*.sys.ini" -path "*/en-GB/*" -exec grep -h "^${EXT_NAME}=" {} \; 2>/dev/null | head -1 | cut -d'"' -f2)
- [ -z "$INI_NAME" ] && INI_NAME=$(find . -name "*.sys.ini" -exec grep -h "^${EXT_NAME}=" {} \; 2>/dev/null | head -1 | cut -d'"' -f2)
- [ -n "$INI_NAME" ] && EXT_NAME="$INI_NAME"
- fi
-
- # Fallbacks
- [ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
- [ -z "$EXT_TYPE" ] && EXT_TYPE="component"
-
- # Derive element if not in manifest:
- # 1. plugin="xxx" attribute (plugins)
- # 2. module="xxx" attribute (modules)
- # 3. XML filename (components, packages)
- # 4. Repo name fallback (templates, anything else)
- if [ -z "$EXT_ELEMENT" ]; then
- EXT_ELEMENT=$(sed -n 's/.*plugin="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
- fi
- if [ -z "$EXT_ELEMENT" ]; then
- EXT_ELEMENT=$(sed -n 's/.*module="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
- fi
- if [ -z "$EXT_ELEMENT" ]; then
- FNAME=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
- # If filename is generic (templateDetails, manifest), use repo name
- case "$FNAME" in
- templatedetails|manifest) EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
- *) EXT_ELEMENT="$FNAME" ;;
- esac
- fi
- # Final fallback
- [ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
-
- # Save for Steps 7, 8, 8b
- echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
- echo "ext_name=${EXT_NAME}" >> "$GITHUB_OUTPUT"
- echo "ext_type=${EXT_TYPE}" >> "$GITHUB_OUTPUT"
- echo "ext_folder=${EXT_FOLDER}" >> "$GITHUB_OUTPUT"
-
- # Build client tag: plugins and frontend modules need site
- CLIENT_TAG=""
- if [ -n "$EXT_CLIENT" ]; then
- CLIENT_TAG="${EXT_CLIENT}"
- elif [ "$EXT_TYPE" = "module" ] || [ "$EXT_TYPE" = "plugin" ]; then
- CLIENT_TAG="site"
- fi
-
- # Build folder tag for plugins (required for Joomla to match the update)
- FOLDER_TAG=""
- if [ -n "$EXT_FOLDER" ] && [ "$EXT_TYPE" = "plugin" ]; then
- FOLDER_TAG="${EXT_FOLDER}"
- fi
-
- # Build targetplatform (fallback to Joomla 5 if not in manifest)
- if [ -z "$TARGET_PLATFORM" ]; then
- TARGET_PLATFORM=$(printf '' "/")
- fi
-
- # Build php_minimum tag
- PHP_TAG=""
- if [ -n "$PHP_MINIMUM" ]; then
- PHP_TAG="${PHP_MINIMUM}"
- fi
-
- # Build TYPE_PREFIX for download URL
- TYPE_PREFIX=""
- case "${EXT_TYPE}" in
- plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
- module) TYPE_PREFIX="mod_" ;;
- component) TYPE_PREFIX="com_" ;;
- template) TYPE_PREFIX="tpl_" ;;
- library) TYPE_PREFIX="lib_" ;;
- package) TYPE_PREFIX="pkg_" ;;
- esac
-
- DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/stable/${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
- INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/stable"
-
- # -- Build update entry for a given stability tag
- build_entry() {
- local TAG_NAME="$1"
- 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' " ${TAG_NAME}"
- 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' ' '
- }
-
- # -- Write updates.xml with cascading channels
- # Stable release updates ALL channels (development, alpha, beta, rc, stable)
- {
- printf '%s\n' ""
- printf '%s\n' ""
- printf '%s\n' ""
- printf '%s\n' ''
- build_entry "development"
- build_entry "alpha"
- build_entry "beta"
- build_entry "rc"
- build_entry "stable"
- printf '%s\n' ''
- } > updates.xml
-
- echo "updates.xml: ${VERSION} (all channels updated to stable)" >> $GITHUB_STEP_SUMMARY
-
- # -- Commit all changes ---------------------------------------------------
- name: Commit release changes
if: >-
steps.version.outputs.skip != 'true' &&
@@ -633,8 +395,7 @@ jobs:
fi
# Find extension element name from manifest
- 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)
+ MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '/dev/null | head -1 || true)
[ -z "$MANIFEST" ] && exit 0
# Reuse element from Step 5, with same fallback chain
@@ -663,44 +424,19 @@ jobs:
# -- Build install packages from src/ ----------------------------
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
- [ ! -d "$SOURCE_DIR" ] && { echo "No src/ or htdocs/ — skipping package"; exit 0; }
+ [ ! -d "$SOURCE_DIR" ] && { echo "No src/ or htdocs/"; exit 0; }
- EXCLUDES=".ftpignore sftp-config* *.ppk *.pem *.key .env*"
-
- if [ "$EXT_TYPE" = "package" ] && [ -d "${SOURCE_DIR}/packages" ]; then
- echo "=== Building Joomla PACKAGE (multi-extension) ==="
- PKG_STAGE=$(mktemp -d)
-
- # 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*' .
+ # ZIP package (type-aware via moko-platform PHP API)
+ php /tmp/moko-platform-api/cli/joomla_build.php --path . --version "${VERSION}" --output /tmp
+ # Match the expected ZIP_NAME for upload
+ BUILT_ZIP=$(ls /tmp/${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip 2>/dev/null | head -1 || true)
+ if [ -n "$BUILT_ZIP" ] && [ "$BUILT_ZIP" != "/tmp/${ZIP_NAME}" ]; then
+ mv "$BUILT_ZIP" "/tmp/${ZIP_NAME}"
fi
+ # tar.gz package (flat source archive)
+ tar -czf "/tmp/${TAR_NAME}" -C "$SOURCE_DIR" --exclude='.ftpignore' --exclude='sftp-config*' --exclude='*.ppk' --exclude='*.pem' --exclude='*.key' --exclude='.env*' .
+
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")
@@ -952,33 +688,14 @@ jobs:
# -- Clean up lesser pre-releases (cascade) ---------------------------------
# stable → deletes all | rc → beta,alpha,dev | beta → alpha,dev | alpha → dev
- name: "Delete lesser pre-release channels"
- 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 }}"
+ php /tmp/moko-platform-api/cli/release_cascade.php \
+ --stability stable \
+ --token "${{ secrets.GA_TOKEN }}" \
+ --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
+ --gitea-url "${GITEA_URL}" 2>/dev/null || true
- # Stable deletes all pre-release channels
- TAGS_TO_DELETE="development alpha beta release-candidate"
-
- DELETED=0
- for TAG in $TAGS_TO_DELETE; do
- RELEASE_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
- "${API_BASE}/releases/tags/${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
- curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
- "${API_BASE}/releases/${RELEASE_ID}" 2>/dev/null || true
- curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
- "${API_BASE}/tags/${TAG}" 2>/dev/null || true
- echo "Deleted: ${TAG} (id: ${RELEASE_ID})"
- DELETED=$((DELETED + 1))
- fi
- done
- echo "Cleaned up ${DELETED} pre-release channel(s)" >> $GITHUB_STEP_SUMMARY
-
- # -- 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
diff --git a/.mokogitea/workflows/ci-joomla.yml b/.mokogitea/workflows/ci-joomla.yml
index 5c66f14..af1bacc 100644
--- a/.mokogitea/workflows/ci-joomla.yml
+++ b/.mokogitea/workflows/ci-joomla.yml
@@ -48,7 +48,7 @@ jobs:
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
run: |
git clone --depth 1 --branch main --quiet \
- "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
+ "https://${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
/tmp/mokostandards-api
- name: Install dependencies
diff --git a/.mokogitea/workflows/deploy-manual.yml b/.mokogitea/workflows/deploy-manual.yml
deleted file mode 100644
index bb133ed..0000000
--- a/.mokogitea/workflows/deploy-manual.yml
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright (C) 2026 Moko Consulting
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-# FILE INFORMATION
-# DEFGROUP: Gitea.Workflow
-# INGROUP: MokoStandards.Deploy
-# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
-# PATH: /templates/workflows/joomla/deploy-manual.yml.template
-# VERSION: 04.07.00
-# BRIEF: Manual SFTP deploy to dev server for Joomla repos
-
-name: "Universal: Deploy to Dev (Manual)"
-
-on:
- workflow_dispatch:
- inputs:
- clear_remote:
- description: 'Delete all remote files before uploading'
- required: false
- default: 'false'
- type: boolean
-
-env:
- FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
-
-permissions:
- contents: read
-
-jobs:
- deploy:
- name: SFTP Deploy to Dev
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
-
- - name: Setup PHP
- run: |
- php -v && composer --version
-
- - name: Setup MokoStandards tools
- env:
- GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
- MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
- MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
- COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}'
- run: |
- git clone --depth 1 --branch main --quiet \
- "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
- /tmp/mokostandards-api 2>/dev/null || true
- if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then
- cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
- fi
-
- - name: Check FTP configuration
- id: check
- env:
- HOST: ${{ vars.DEV_FTP_HOST }}
- PATH_VAR: ${{ vars.DEV_FTP_PATH }}
- PORT: ${{ vars.DEV_FTP_PORT }}
- run: |
- if [ -z "$HOST" ] || [ -z "$PATH_VAR" ]; then
- echo "DEV_FTP_HOST or DEV_FTP_PATH not configured -- cannot deploy"
- echo "skip=true" >> "$GITHUB_OUTPUT"
- exit 0
- fi
- echo "skip=false" >> "$GITHUB_OUTPUT"
- echo "host=$HOST" >> "$GITHUB_OUTPUT"
-
- REMOTE="${PATH_VAR%/}"
- echo "remote=$REMOTE" >> "$GITHUB_OUTPUT"
-
- [ -z "$PORT" ] && PORT="22"
- echo "port=$PORT" >> "$GITHUB_OUTPUT"
-
- - name: Deploy via SFTP
- if: steps.check.outputs.skip != 'true'
- env:
- SFTP_KEY: ${{ secrets.DEV_FTP_KEY }}
- SFTP_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
- SFTP_USER: ${{ vars.DEV_FTP_USERNAME }}
- run: |
- SOURCE_DIR="src"
- [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
- [ ! -d "$SOURCE_DIR" ] && { echo "No src/ or htdocs/ -- nothing to deploy"; exit 0; }
-
- printf '{"host":"%s","port":%s,"username":"%s","remotePath":"%s"' \
- "${{ steps.check.outputs.host }}" "${{ steps.check.outputs.port }}" "$SFTP_USER" "${{ steps.check.outputs.remote }}" \
- > /tmp/sftp-config.json
-
- if [ -n "$SFTP_KEY" ]; then
- echo "$SFTP_KEY" > /tmp/deploy_key
- chmod 600 /tmp/deploy_key
- printf ',"privateKeyPath":"/tmp/deploy_key"}' >> /tmp/sftp-config.json
- else
- printf ',"password":"%s"}' "$SFTP_PASS" >> /tmp/sftp-config.json
- fi
-
- DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json)
- [ "${{ inputs.clear_remote }}" = "true" ] && DEPLOY_ARGS+=(--clear-remote)
-
- PLATFORM=$(php /tmp/mokostandards-api/cli/platform_detect.php --path . 2>/dev/null || true)
- if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards-api/deploy/deploy-joomla.php" ]; then
- php /tmp/mokostandards-api/deploy/deploy-joomla.php "${DEPLOY_ARGS[@]}"
- else
- php /tmp/mokostandards-api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
- fi
-
- rm -f /tmp/deploy_key /tmp/sftp-config.json
-
- - name: Summary
- if: always()
- run: |
- if [ "${{ steps.check.outputs.skip }}" = "true" ]; then
- echo "### Deploy Skipped -- FTP not configured" >> $GITHUB_STEP_SUMMARY
- else
- echo "### Manual Dev Deploy Complete" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
- echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
- echo "| Host | \`${{ steps.check.outputs.host }}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Remote | \`${{ steps.check.outputs.remote }}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Clear | ${{ inputs.clear_remote }} |" >> $GITHUB_STEP_SUMMARY
- fi
diff --git a/.mokogitea/workflows/pr-check.yml b/.mokogitea/workflows/pr-check.yml
index 014f6b0..7ebc767 100644
--- a/.mokogitea/workflows/pr-check.yml
+++ b/.mokogitea/workflows/pr-check.yml
@@ -192,3 +192,32 @@ jobs:
FILE_COUNT=$(find "$SOURCE_DIR" -type f | wc -l)
echo "Source: ${FILE_COUNT} files"
[ "$FILE_COUNT" -gt 0 ] || { echo "::error::Source directory is empty"; exit 1; }
+
+ # ── Changelog Gate ────────────────────────────────────────────────────
+ changelog:
+ name: Changelog Updated
+ runs-on: ubuntu-latest
+ if: github.base_ref == 'main'
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Check CHANGELOG.md was updated
+ run: |
+ BASE="${{ github.event.pull_request.base.sha }}"
+ HEAD="${{ github.event.pull_request.head.sha }}"
+
+ if git diff --name-only "$BASE" "$HEAD" | grep -q "^CHANGELOG.md$"; then
+ echo "CHANGELOG.md updated"
+ else
+ # Allow [skip changelog] in PR title or body
+ PR_TITLE="${{ github.event.pull_request.title }}"
+ PR_BODY="${{ github.event.pull_request.body }}"
+ if echo "$PR_TITLE $PR_BODY" | grep -qi "\[skip changelog\]"; then
+ echo "::warning::Changelog skip requested via [skip changelog]"
+ exit 0
+ fi
+ echo "::error::CHANGELOG.md must be updated before merging to main. Add [skip changelog] to the PR title to bypass."
+ exit 1
+ fi
diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml
index 3ddd113..57d3380 100644
--- a/.mokogitea/workflows/pre-release.yml
+++ b/.mokogitea/workflows/pre-release.yml
@@ -5,7 +5,7 @@
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
-# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
+# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.00.00
# BRIEF: Manual pre-release — builds dev/alpha/beta/rc packages from any branch
@@ -49,27 +49,26 @@ jobs:
run: |
if ! command -v php &> /dev/null; then
sudo apt-get update -qq
- sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip >/dev/null 2>&1
+ sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl >/dev/null 2>&1
fi
+ - name: Setup moko-platform tools
+ env:
+ MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
+ MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
+ run: |
+ git clone --depth 1 --branch main --quiet "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" /tmp/moko-platform-api
+
- name: Detect platform
id: platform
run: |
- tr -d '[:space:]')| tr -d '[:space:]')
- [ -z "$PLATFORM" ] && PLATFORM="generic"
- echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
- # 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"
+ php /tmp/moko-platform-api/cli/manifest_read.php --path . --github-output
- name: Resolve metadata
id: meta
run: |
STABILITY="${{ inputs.stability }}"
+ MOKO_API="/tmp/moko-platform-api/cli"
case "$STABILITY" in
development) SUFFIX="-dev"; TAG="development" ;;
@@ -78,66 +77,14 @@ jobs:
release-candidate) SUFFIX="-rc"; TAG="release-candidate" ;;
esac
- # Read and bump patch version (with rollover)
- CURRENT=$(sed -n 's/.*VERSION:[[:space:]]*\([0-9][0-9]\.[0-9][0-9]\.[0-9][0-9]\).*/\1/p' README.md 2>/dev/null | head -1)
- [ -z "$CURRENT" ] && CURRENT="00.00.00"
-
- MAJOR=$(echo "$CURRENT" | cut -d. -f1)
- MINOR=$(echo "$CURRENT" | cut -d. -f2)
- PATCH=$(echo "$CURRENT" | cut -d. -f3)
-
- # Patch bump with rollover: ZZ=99 → bump minor, YY=99 → bump major
- NEW_PATCH=$((10#$PATCH + 1))
- NEW_MINOR=$((10#$MINOR))
- NEW_MAJOR=$((10#$MAJOR))
-
- if [ $NEW_PATCH -gt 99 ]; then
- NEW_PATCH=0
- NEW_MINOR=$((NEW_MINOR + 1))
- fi
- if [ $NEW_MINOR -gt 99 ]; then
- NEW_MINOR=0
- NEW_MAJOR=$((NEW_MAJOR + 1))
- fi
-
- VERSION=$(printf "%02d.%02d.%02d" $NEW_MAJOR $NEW_MINOR $NEW_PATCH)
- TODAY=$(date +%Y-%m-%d)
-
- echo "Bumping: ${CURRENT} → ${VERSION} (patch)"
-
- # Update README.md
- sed -i "s/VERSION:[[:space:]]*${CURRENT}/VERSION: ${VERSION}/" README.md
+ # Bump patch version
+ BUMP_OUTPUT=$(php ${MOKO_API}/version_bump.php --path .)
+ VERSION=$(echo "$BUMP_OUTPUT" | grep -oP '\d{2}\.\d{2}\.\d{2}$' || true)
+ [ -z "$VERSION" ] && VERSION=$(php ${MOKO_API}/version_read.php --path .)
+ echo "Version: ${VERSION}"
# Update platform-specific manifest
- PLATFORM="${{ steps.platform.outputs.platform }}"
- MANIFEST="${{ steps.platform.outputs.manifest }}"
- MOD_FILE="${{ steps.platform.outputs.mod_file }}"
- case "$PLATFORM" in
- joomla)
- if [ -n "$MANIFEST" ]; then
- MANIFEST_VER=$(sed -n 's/.*\([^<]*\)<\/version>.*/\1/p' "$MANIFEST" | head -1)
- 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
- sed -i "s/\$this->version = '[^']*'/\$this->version = '${VERSION}'/" "$MOD_FILE"
- fi
- ;;
- *) ;;
- esac
+ php ${MOKO_API}/version_set_platform.php --path . --version "${VERSION}"
# Commit version bump
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
@@ -145,40 +92,22 @@ jobs:
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
git add -A
git diff --cached --quiet || {
- git commit -m "chore(version): bump ${CURRENT} → ${VERSION} [skip ci]"
+ git commit -m "chore(version): bump to ${VERSION} [skip ci]"
git push origin HEAD 2>&1
}
- # Auto-detect element (platform-aware)
- case "$PLATFORM" in
- joomla)
- MANIFEST="${{ steps.platform.outputs.manifest }}"
- EXT_ELEMENT=""
- if [ -n "$MANIFEST" ]; then
- EXT_ELEMENT=$(sed -n 's/.*\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
- if [ -z "$EXT_ELEMENT" ]; then
- EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
- case "$EXT_ELEMENT" in
- templatedetails|manifest) EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
- esac
- fi
- else
- EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
- fi
- ;;
- dolibarr)
- MOD_FILE="${{ steps.platform.outputs.mod_file }}"
- if [ -n "$MOD_FILE" ]; then
- MOD_BASENAME=$(basename "$MOD_FILE" .class.php)
- EXT_ELEMENT=$(echo "$MOD_BASENAME" | sed 's/^mod//' | tr '[:upper:]' '[:lower:]')
- else
- EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
- fi
- ;;
- *)
- EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
- ;;
- esac
+ # Detect element from Joomla/Dolibarr manifest
+ PLATFORM="${{ steps.platform.outputs.platform }}"
+ EXT_ELEMENT=$(php ${MOKO_API}/manifest_read.php --path . --field name 2>/dev/null | tr -d ' ' | tr '[:upper:]' '[:lower:]' || true)
+ # For Joomla, prefer tag
+ if [ "$PLATFORM" = "joomla" ]; then
+ MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '/dev/null | head -1 || true)
+ if [ -n "$MANIFEST" ]; then
+ ELEM=$(grep -oP "\K[^<]+" "$MANIFEST" 2>/dev/null | head -1)
+ [ -n "$ELEM" ] && EXT_ELEMENT="$ELEM"
+ fi
+ fi
+ [ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"
@@ -188,83 +117,42 @@ jobs:
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
- echo "manifest=${MANIFEST}" >> "$GITHUB_OUTPUT"
echo "=== Pre-Release: ${EXT_ELEMENT} ${VERSION}${SUFFIX} ==="
- name: Build package
- run: |
- SOURCE_DIR="src"
- [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
- if [ ! -d "$SOURCE_DIR" ]; then
- echo "::error::No src/ or htdocs/ directory"
- 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
-
- 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
run: |
- ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
- cd build/package
- zip -r "../${ZIP_NAME}" .
- cd ..
+ VERSION="${{ steps.meta.outputs.version }}"
+ SUFFIX="${{ steps.meta.outputs.suffix }}"
+ PLATFORM="${{ steps.platform.outputs.platform }}"
- SHA256=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1)
- echo "sha256=${SHA256}" >> "$GITHUB_OUTPUT"
- echo "ZIP: ${ZIP_NAME} (SHA: ${SHA256:0:16}...)"
+ if [ "$PLATFORM" = "joomla" ]; then
+ php /tmp/moko-platform-api/cli/joomla_build.php --path . --version "${VERSION}" --suffix "${SUFFIX}" --output build --github-output
+ else
+ # Generic build: zip src/ directory
+ SOURCE_DIR="src"
+ [ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
+ [ ! -d "$SOURCE_DIR" ] && { echo "::error::No src/ or htdocs/"; exit 1; }
+ EXT_ELEMENT="${{ steps.meta.outputs.ext_element }}"
+ ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"
+ mkdir -p build
+ cd "$SOURCE_DIR" && zip -r "../build/${ZIP_NAME}" . && cd ..
+ SHA256=$(sha256sum "build/${ZIP_NAME}" | cut -d' ' -f1)
+ echo "zip_name=${ZIP_NAME}" >> "$GITHUB_OUTPUT"
+ echo "zip_path=build/${ZIP_NAME}" >> "$GITHUB_OUTPUT"
+ echo "sha256=${SHA256}" >> "$GITHUB_OUTPUT"
+ fi
- name: Create or replace Gitea release
id: release
+ continue-on-error: true
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
SHA256="${{ steps.zip.outputs.sha256 }}"
- ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
+ ZIP_NAME="${{ steps.zip.outputs.zip_name }}"
EXT_ELEMENT="${{ steps.meta.outputs.ext_element }}"
TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
@@ -302,99 +190,29 @@ jobs:
curl -sS -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/octet-stream" \
"${API}/releases/${RELEASE_ID}/assets?name=${ZIP_NAME}" \
- --data-binary "@build/${ZIP_NAME}"
+ --data-binary "@${{ steps.zip.outputs.zip_path }}"
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
- - name: Update updates.xml
+ - name: "Update updates.xml"
if: steps.platform.outputs.platform == 'joomla'
run: |
- STABILITY="${{ steps.meta.outputs.stability }}"
VERSION="${{ steps.meta.outputs.version }}"
+ STABILITY="${{ steps.meta.outputs.stability }}"
SHA256="${{ steps.zip.outputs.sha256 }}"
- ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
- TAG="${{ steps.meta.outputs.tag }}"
- DATE=$(date +%Y-%m-%d)
-
- if [ ! -f "updates.xml" ]; then
- echo "No updates.xml — skipping"
- exit 0
- fi
-
- export PY_STABILITY="$STABILITY" PY_VERSION="$VERSION" PY_SHA256="$SHA256" \
- PY_ZIP_NAME="$ZIP_NAME" PY_TAG="$TAG" PY_DATE="$DATE" \
- PY_GITEA_ORG="$GITEA_ORG" PY_GITEA_REPO="$GITEA_REPO"
- python3 << 'PYEOF'
- import re, os
-
- stability = os.environ["PY_STABILITY"]
- version = os.environ["PY_VERSION"]
- sha256 = os.environ["PY_SHA256"]
- zip_name = os.environ["PY_ZIP_NAME"]
- tag = os.environ["PY_TAG"]
- date = os.environ["PY_DATE"]
- gitea_org = os.environ["PY_GITEA_ORG"]
- gitea_repo = os.environ["PY_GITEA_REPO"]
- download_url = f"https://git.mokoconsulting.tech/{gitea_org}/{gitea_repo}/releases/download/{tag}/{zip_name}"
-
- with open("updates.xml", "r") as f:
- content = f.read()
-
- # Map stability to XML tag name
- tag_map = {"development": "development", "alpha": "alpha", "beta": "beta", "release-candidate": "rc"}
- xml_tag = tag_map.get(stability, stability)
-
- pattern = r"((?:(?!).)*?" + re.escape(xml_tag) + r".*?)"
- match = re.search(pattern, content, re.DOTALL)
- if match:
- block = match.group(1)
- updated = re.sub(r"[^<]*", f"{version}", block)
- updated = re.sub(r"[^<]*", f"{date}", updated)
- if "" in updated:
- updated = re.sub(r"[^<]*", f"{sha256}", updated)
- else:
- updated = updated.replace("", f"\n {sha256}")
- updated = re.sub(r"(]*>)[^<]*()", rf"\g<1>{download_url}\g<2>", updated)
- content = content.replace(block, updated)
- print(f"Updated {xml_tag} channel: version={version}")
- else:
- print(f"WARNING: No {xml_tag} block in updates.xml")
-
- with open("updates.xml", "w") as f:
- f.write(content)
- PYEOF
-
- # Commit and push to current branch
+ php /tmp/moko-platform-api/cli/updates_xml_build.php --path . --version "$VERSION" --stability "$STABILITY" --sha "$SHA256" --gitea-url "$GITEA_URL" --org "$GITEA_ORG" --repo "$GITEA_REPO"
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 add updates.xml
- git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]"
+ git commit -m "chore: update $STABILITY channel $VERSION [skip ci]"
git push origin HEAD 2>&1 || echo "WARNING: push failed"
fi
- name: "Sync updates.xml to all branches"
if: steps.platform.outputs.platform == 'joomla'
run: |
- CURRENT_BRANCH="${{ github.ref_name }}"
- git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
- git config --local user.name "gitea-actions[bot]"
-
- # Sync updates.xml to main and dev (whichever isn't current)
- for BRANCH in main dev; do
- [ "$BRANCH" = "$CURRENT_BRANCH" ] && continue
-
- echo "Syncing updates.xml → ${BRANCH}"
- git fetch origin "${BRANCH}" 2>/dev/null || continue
- git checkout "origin/${BRANCH}" -- . 2>/dev/null || continue
- git checkout "${CURRENT_BRANCH}" -- updates.xml
- if ! git diff --quiet updates.xml 2>/dev/null; then
- git add updates.xml
- git commit -m "chore: sync updates.xml from ${CURRENT_BRANCH} [skip ci]"
- git push origin HEAD:refs/heads/${BRANCH} 2>&1 || echo "WARNING: push to ${BRANCH} failed"
- fi
- git checkout "${CURRENT_BRANCH}" 2>/dev/null
- done
+ php /tmp/moko-platform-api/cli/updates_xml_sync.php --path . --current "${{ github.ref_name }}" --branches main,dev --version "${{ steps.meta.outputs.version }}" --token "${{ secrets.GA_TOKEN }}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" --gitea-url "${GITEA_URL}"
- name: "Delete lesser pre-release channels (cascade)"
continue-on-error: true
diff --git a/.mokogitea/workflows/update-server.yml b/.mokogitea/workflows/update-server.yml
index 6e617f6..7c1a341 100644
--- a/.mokogitea/workflows/update-server.yml
+++ b/.mokogitea/workflows/update-server.yml
@@ -88,7 +88,7 @@ jobs:
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
git clone --depth 1 --branch main --quiet \
- "https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
+ "https://${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
/tmp/mokostandards-api 2>/dev/null || true
if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then
cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
diff --git a/CLAUDE.md b/CLAUDE.md
index e3569c9..83c432b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -34,7 +34,7 @@ composer install # Install PHP dependencies
This is a project template. Files are copied when creating new repos.
- Edit files here to change defaults for new projects
-- `.gitea/workflows/` -- CI/CD workflow templates
+- `.mokogitea/workflows/` -- CI/CD workflow templates
- `Makefile` -- build targets inherited by new projects
## Rules