diff --git a/.mokogitea/manifest.xml b/.mokogitea/manifest.xml
new file mode 100644
index 0000000..0082fff
--- /dev/null
+++ b/.mokogitea/manifest.xml
@@ -0,0 +1,33 @@
+
+
+
+
+ MokoJoomHero
+ Package - MokoJoomHero
+ MokoConsulting
+ A Joomla Module designed to provide a random image from a folder with content on top as a Hero.
+ 01.21.08
+ GNU General Public License v3
+
+
+ joomla
+ 09.01.00
+ https://git.mokoconsulting.tech/MokoConsulting/moko-platform
+ 2026-05-30T15:00:00+00:00
+
+
+ PHP
+ joomla-extension
+ src/
+
+
+ src/
+ modules/mod_mokojoomhero
+ mokoconsulting_dev@waas.dev.mokoconsulting.tech
+ mokoconsulting_demo@waas.demo.mokoconsulting.tech
+
+
diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml
index a7563e0..ca40435 100644
--- a/.mokogitea/workflows/auto-release.yml
+++ b/.mokogitea/workflows/auto-release.yml
@@ -1,497 +1,324 @@
-# Copyright (C) 2026 Moko Consulting
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-# FILE INFORMATION
-# DEFGROUP: MokoGitea.Workflow
-# INGROUP: mokocli.Release
-# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
-# PATH: /.mokogitea/workflows/auto-release.yml
-# VERSION: 05.01.00
-# BRIEF: Universal build & release � detects platform from manifest.xml
-#
-# +=======================================================================+
-# | UNIVERSAL BUILD & RELEASE PIPELINE |
-# +=======================================================================+
-# | |
-# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
-# | |
-# | Platform-specific: |
-# | joomla: XML manifest, type-prefixed packages |
-# | dolibarr: mod*.class.php, update.txt, dev version reset |
-# | generic: README-only, no update stream |
-# | |
-# +=======================================================================+
-
-name: "Universal: Build & Release"
-
-on:
- pull_request:
- types: [opened, synchronize, closed]
- branches:
- - main
- paths-ignore:
- - '.mokogitea/workflows/**'
- - '*.md'
- - 'wiki/**'
- - '.editorconfig'
- - '.gitignore'
- - '.gitattributes'
- - '.gitmessage'
- - 'LICENSE'
- workflow_dispatch:
- inputs:
- action:
- description: 'Action to perform'
- required: false
- type: choice
- default: release
- options:
- - release
- - promote-rc
-
-env:
- FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
- MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
- GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
- GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
-
-permissions:
- contents: write
-
-jobs:
- # ── PR Opened → Rename branch to RC and build RC release ─────────────────────────
- promote-rc:
- name: Promote to RC
- runs-on: release
- # Skip on template repos (Template-*) — they scaffold other repos and do not release.
- if: >-
- !startsWith(github.event.repository.name, 'Template-') &&
- (
- (github.event.action == 'opened' && github.event.pull_request.merged != true) ||
- (github.event.action == 'synchronize' && github.event.pull_request.merged != true) ||
- (github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
- )
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- with:
- token: ${{ secrets.MOKOGITEA_TOKEN }}
- fetch-depth: 1
- submodules: recursive
-
- - name: Setup mokocli tools
- env:
- MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
- MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
- run: |
- if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
- echo Using pre-installed /opt/mokocli
- echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
- else
- echo Falling back to fresh clone
- if ! command -v composer > /dev/null 2>&1; then
- 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
- rm -rf /tmp/mokocli
- CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
- git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
- cd /tmp/mokocli
- composer install --no-dev --no-interaction --quiet
- echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
- fi
-
- - name: Rename branch to rc
- run: |
- API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- AUTH="Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}"
- FROM="${{ github.event.pull_request.head.ref || 'dev' }}"
- PR="${{ github.event.pull_request.number }}"
-
- # Resolve the source branch HEAD commit.
- SRC_JSON=$(curl -sf -H "$AUTH" "${API_BASE}/branches/${FROM}") \
- || { echo "::error::Source branch ${FROM} not found"; exit 1; }
- SRC_SHA=$(printf '%s' "$SRC_JSON" | python3 -c "import sys, json; print(json.load(sys.stdin)['commit']['id'])" 2>/dev/null || true)
- [ -n "$SRC_SHA" ] || { echo "::error::Could not resolve HEAD of ${FROM}"; exit 1; }
-
- # Point rc at the source commit. If rc already exists (a protected branch that
- # cannot be deleted), force-update its ref in place instead of delete+recreate:
- # deleting a protected branch fails, which then makes the recreate return HTTP 409.
- if curl -sf -o /dev/null -H "$AUTH" "${API_BASE}/branches/rc"; then
- echo "rc exists - force-updating to ${FROM} (${SRC_SHA})"
- curl -sf -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
- "${API_BASE}/git/refs/heads/rc" -d "{\"sha\":\"${SRC_SHA}\",\"force\":true}" \
- || { echo "::error::Failed to force-update rc (CI token needs force-push on the protected rc branch)"; exit 1; }
- else
- echo "Creating rc from ${FROM}"
- curl -sf -X POST -H "$AUTH" -H "Content-Type: application/json" \
- "${API_BASE}/branches" -d "{\"new_branch_name\":\"rc\",\"old_branch_name\":\"${FROM}\"}" \
- || { echo "::error::Failed to create rc from ${FROM}"; exit 1; }
- fi
-
- # Repoint the PR at rc, then delete the old source branch (non-fatal).
- if [ -n "$PR" ]; then
- curl -s -X PATCH -H "$AUTH" -H "Content-Type: application/json" \
- "${API_BASE}/pulls/${PR}" -d '{"head":"rc"}' >/dev/null || true
- fi
- curl -s -X DELETE -H "$AUTH" "${API_BASE}/branches/${FROM}" >/dev/null || true
- echo "Renamed ${FROM} -> rc"
-
- - name: Checkout rc and configure git
- run: |
- git fetch origin rc
- git checkout rc
- git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
- git config --local user.name "mokogitea-actions[bot]"
- git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
-
- - name: Publish RC release
- run: |
- php ${MOKO_CLI}/release_publish.php \
- --path . --stability rc --bump minor --branch rc \
- --token "${{ secrets.MOKOGITEA_TOKEN }}"
-
- - name: Update RC release notes from CHANGELOG.md
- run: |
- API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
-
- # Extract [Unreleased] section from changelog
- NOTES=""
- if [ -f "CHANGELOG.md" ]; then
- NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
- fi
- [ -z "$NOTES" ] && NOTES="Release candidate"
-
- # Find the RC release and update its body
- RELEASE_ID=$(curl -sf -H "Authorization: token ${TOKEN}" \
- "${API_BASE}/releases/tags/release-candidate" \
- | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
-
- if [ -n "$RELEASE_ID" ]; then
- python3 -c "
- import json, urllib.request
- body = open('/dev/stdin').read()
- payload = json.dumps({'body': body}).encode()
- req = urllib.request.Request(
- '${API_BASE}/releases/${RELEASE_ID}',
- data=payload, method='PATCH',
- headers={
- 'Authorization': 'token ${TOKEN}',
- 'Content-Type': 'application/json'
- })
- urllib.request.urlopen(req)
- " <<< "$NOTES"
- echo "RC release notes updated from CHANGELOG.md"
- fi
-
- - name: Summary
- if: always()
- run: |
- echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
- echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
-
- # ── Merged PR → Build & Release (or promote RC to stable) ─────────────────────────
- release:
- name: Build & Release Pipeline
- runs-on: release
- # Skip on template repos (Template-*) — they scaffold other repos and do not release.
- if: >-
- !startsWith(github.event.repository.name, 'Template-') &&
- (
- github.event.pull_request.merged == true ||
- (github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
- )
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- with:
- token: ${{ secrets.MOKOGITEA_TOKEN }}
- fetch-depth: 0
- submodules: recursive
-
- - name: Configure git for bot pushes
- run: |
- git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
- git config --local user.name "mokogitea-actions[bot]"
- git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
-
- - name: Check for merge conflict markers
- run: |
- CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
- if [ -n "$CONFLICTS" ]; then
- echo "::error::Merge conflict markers found — aborting release"
- echo "## Release Blocked: Conflict Markers" >> $GITHUB_STEP_SUMMARY
- echo '```' >> $GITHUB_STEP_SUMMARY
- echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
- echo '```' >> $GITHUB_STEP_SUMMARY
- exit 1
- fi
- echo "No conflict markers found"
-
- - name: Setup mokocli tools
- env:
- MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
- MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
- COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
- run: |
- if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
- echo Using pre-installed /opt/mokocli
- echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
- else
- echo Falling back to fresh clone
- if ! command -v composer > /dev/null 2>&1; then
- 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
- rm -rf /tmp/mokocli
- CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
- git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
- cd /tmp/mokocli
- composer install --no-dev --no-interaction --quiet
- echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
- fi
-
- - name: "Detect platform"
- id: platform
- run: |
- php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
- php ${MOKO_CLI}/manifest_read.php --path . --github-output 2>/dev/null || true
-
- - name: "Determine version bump level"
- id: bump
- run: |
- # Fix/patch branches: version was already bumped by pre-release, just strip suffix
- # Feature/dev branches: bump minor for the new stable release
- HEAD_REF="${{ github.event.pull_request.head.ref || 'dev' }}"
- case "$HEAD_REF" in
- fix/*|patch/*|hotfix/*|bugfix/*) BUMP="none" ;;
- *) BUMP="minor" ;;
- esac
- echo "level=${BUMP}" >> "$GITHUB_OUTPUT"
- echo "Bump level: ${BUMP} (from branch: ${HEAD_REF})"
-
- - name: "Publish stable release"
- run: |
- BUMP_FLAG=""
- if [ "${{ steps.bump.outputs.level }}" != "none" ]; then
- BUMP_FLAG="--bump ${{ steps.bump.outputs.level }}"
- fi
- php ${MOKO_CLI}/release_publish.php \
- --path . --stability stable ${BUMP_FLAG} --branch main \
- --token "${{ secrets.MOKOGITEA_TOKEN }}"
-
- - name: "Read published version"
- id: version
- run: |
- VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "")
- VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
- [ -z "$VERSION" ] && VERSION="00.00.00" && echo "skip=true" >> "$GITHUB_OUTPUT"
- echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
- PLATFORM="${{ steps.platform.outputs.platform }}"
- if [[ "$PLATFORM" == joomla* ]]; then
- echo "tag=stable" >> "$GITHUB_OUTPUT"
- echo "release_tag=stable" >> "$GITHUB_OUTPUT"
- else
- echo "tag=v${VERSION}" >> "$GITHUB_OUTPUT"
- echo "release_tag=v${VERSION}" >> "$GITHUB_OUTPUT"
- fi
- echo "branch=main" >> "$GITHUB_OUTPUT"
- echo "Published version: ${VERSION}"
-
- - name: "Create semver tag for non-Joomla repos"
- id: semver
- if: |
- steps.version.outputs.skip != 'true' &&
- !startsWith(steps.platform.outputs.platform, 'joomla')
- run: |
- VERSION="${{ steps.version.outputs.version }}"
- API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
- SEMVER_TAG="v${VERSION}"
-
- echo "Creating semver tag: ${SEMVER_TAG}"
-
- # Create the git tag via API
- HTTP_CODE=$(curl -sf -o /dev/null -w "%{http_code}" \
- -X POST -H "Authorization: token ${TOKEN}" \
- -H "Content-Type: application/json" \
- "${API_BASE}/tags" \
- -d "{\"tag_name\":\"${SEMVER_TAG}\",\"target\":\"main\",\"message\":\"Release ${VERSION}\"}" 2>/dev/null || echo "000")
-
- if [ "$HTTP_CODE" = "201" ] || [ "$HTTP_CODE" = "200" ]; then
- echo "Created semver tag: ${SEMVER_TAG}"
- elif [ "$HTTP_CODE" = "409" ]; then
- echo "Semver tag ${SEMVER_TAG} already exists (skipped)"
- else
- echo "::warning::Failed to create semver tag ${SEMVER_TAG} (HTTP ${HTTP_CODE})"
- fi
-
- echo "semver_tag=${SEMVER_TAG}" >> "$GITHUB_OUTPUT"
-
- - name: Update release notes and promote changelog
- run: |
- API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
-
- # Get the stable release info (version and ID)
- RELEASE_JSON=$(curl -sf -H "Authorization: token ${TOKEN}" \
- "${API_BASE}/releases/tags/stable" 2>/dev/null || echo '{}')
- RELEASE_ID=$(python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" <<< "$RELEASE_JSON" 2>/dev/null || true)
- # Extract version from release name (e.g. "06.17.00" or "v06.17.00")
- VERSION=$(python3 -c "
- import json, sys, re
- r = json.load(sys.stdin)
- name = r.get('name', '')
- m = re.search(r'(\d+\.\d+\.\d+)', name)
- print(m.group(1) if m else '')
- " <<< "$RELEASE_JSON" 2>/dev/null || true)
-
- # Extract [Unreleased] section from changelog
- NOTES=""
- if [ -f "CHANGELOG.md" ]; then
- NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
- fi
- [ -z "$NOTES" ] && NOTES="Stable release"
-
- # Update release body via API
- if [ -n "$RELEASE_ID" ]; then
- python3 -c "
- import json, urllib.request
- body = open('/dev/stdin').read()
- payload = json.dumps({'body': body}).encode()
- req = urllib.request.Request(
- '${API_BASE}/releases/${RELEASE_ID}',
- data=payload, method='PATCH',
- headers={
- 'Authorization': 'token ${TOKEN}',
- 'Content-Type': 'application/json'
- })
- urllib.request.urlopen(req)
- " <<< "$NOTES"
- echo "Release notes updated from CHANGELOG.md"
- fi
-
- # Promote [Unreleased] → [version] in CHANGELOG.md and reset
- if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then
- DATE=$(date +%Y-%m-%d)
- python3 -c "
- import sys
- version, date = sys.argv[1], sys.argv[2]
- content = open('CHANGELOG.md').read()
- old = '## [Unreleased]'
- new = f'## [Unreleased]\n\n## [{version}] --- {date}'
- content = content if ('## [' + version + ']') in content else content.replace(old, new, 1)
- open('CHANGELOG.md', 'w').write(content)
- " "$VERSION" "$DATE"
- git add CHANGELOG.md
- git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true
- git push origin main || true
- echo "Changelog promoted: [Unreleased] → [${VERSION}]"
- fi
-
- # -- STEP 9: Mirror to GitHub (stable only) --------------------------------
- - name: "Step 9: Mirror release to GitHub"
- if: >-
- steps.version.outputs.skip != 'true' &&
- secrets.GH_MIRROR_TOKEN != ''
- continue-on-error: true
- run: |
- VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
- RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
- GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
- API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- php ${MOKO_CLI}/release_mirror.php \
- --version "$VERSION" --tag "$RELEASE_TAG" \
- --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
- --gh-token "${{ secrets.GH_MIRROR_TOKEN }}" --gh-repo "$GH_REPO" \
- --branch main 2>&1 || true
- echo "GitHub mirror updated" >> $GITHUB_STEP_SUMMARY
-
- # -- STEP 10: Sync main branch to GitHub mirror ----------------------------
- - name: "Step 10: Push main to GitHub mirror"
- if: >-
- steps.version.outputs.skip != 'true' &&
- secrets.GH_MIRROR_TOKEN != ''
- continue-on-error: true
- run: |
- GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
- GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
- GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
- git remote add github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
- git remote set-url github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
- git fetch origin main --depth=1
- git push github origin/main:refs/heads/main --force 2>/dev/null \
- && echo "main branch pushed to GitHub mirror" \
- || echo "WARNING: GitHub mirror push failed"
-
- - name: "Step 11: Delete rc branch (dev reset moved to cascade-dev.yml)"
- if: steps.version.outputs.skip != 'true'
- continue-on-error: true
- run: |
- API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
-
- # Delete rc branch (ephemeral — created by promote-rc)
- curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
- "${API_BASE}/branches/rc" 2>/dev/null \
- && echo "Deleted rc branch" || echo "rc branch not found"
-
- # dev is reset from main by the dedicated "Cascade Main -> Dev" workflow
- # (cascade-dev.yml), which runs after this release completes.
- echo "rc cleaned; dev reset handled by cascade-dev.yml" >> $GITHUB_STEP_SUMMARY
-
- - name: "Step 12: Create version branch from main"
- if: steps.version.outputs.skip != 'true'
- continue-on-error: true
- run: |
- API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- TOKEN="${{ secrets.MOKOGITEA_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
-
-
-
- # -- Dolibarr post-release: Reset dev version -----------------------------
- - name: "Post-release: Reset dev version"
- if: steps.version.outputs.skip != 'true'
- continue-on-error: true
- run: |
- API_BASE="${MOKOGITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
- php ${MOKO_CLI}/version_reset_dev.php \
- --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
- --branch dev --path . 2>&1 || true
-
- # -- Summary --------------------------------------------------------------
- - name: Pipeline Summary
- if: always()
- run: |
- VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
- PLATFORM="${{ steps.platform.outputs.platform }}"
- if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
- echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
- echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
- elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
- echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
- else
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "## Build & Release Complete (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
- echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
- echo "| Platform | \`${PLATFORM}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| Release | [View](${MOKOGITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
- fi
+# Copyright (C) 2026 Moko Consulting
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# FILE INFORMATION
+# DEFGROUP: Gitea.Workflow
+# INGROUP: moko-platform.Release
+# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
+# PATH: /templates/workflows/universal/auto-release.yml.template
+# VERSION: 05.00.00
+# BRIEF: Universal build & release � detects platform from manifest.xml
+#
+# +========================================================================+
+# | UNIVERSAL BUILD & RELEASE PIPELINE |
+# +========================================================================+
+# | |
+# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
+# | |
+# | Platform-specific: |
+# | joomla: XML manifest, type-prefixed packages |
+# | dolibarr: mod*.class.php, update.txt, dev version reset |
+# | generic: README-only, no update stream |
+# | |
+# +========================================================================+
+
+name: "Universal: Build & Release"
+
+on:
+ pull_request:
+ types: [opened, closed]
+ branches:
+ - main
+ workflow_dispatch:
+ inputs:
+ action:
+ description: 'Action to perform'
+ required: false
+ type: choice
+ default: release
+ options:
+ - release
+ - promote-rc
+
+env:
+ FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
+ GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
+ GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
+ GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
+
+permissions:
+ contents: write
+
+jobs:
+ # ── PR Opened → Rename branch to RC and build RC release ─────────────────────
+ promote-rc:
+ name: Promote to RC
+ runs-on: release
+ if: >-
+ (github.event.action == 'opened' && github.event.pull_request.merged != true) ||
+ (github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ token: ${{ secrets.MOKOGITEA_TOKEN }}
+ fetch-depth: 1
+
+ - name: Setup moko-platform tools
+ env:
+ MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
+ MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
+ run: |
+ if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
+ echo Using pre-installed /opt/moko-platform
+ echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
+ else
+ echo Falling back to fresh clone
+ if ! command -v composer > /dev/null 2>&1; then
+ 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
+ rm -rf /tmp/moko-platform-api
+ CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
+ git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
+ cd /tmp/moko-platform-api
+ composer install --no-dev --no-interaction --quiet
+ echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
+ fi
+
+ - name: Rename branch to rc
+ run: |
+ php ${MOKO_CLI}/branch_rename.php \
+ --from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
+ --token "${{ secrets.MOKOGITEA_TOKEN }}" \
+ --api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
+ --pr "${{ github.event.pull_request.number }}"
+
+ - name: Checkout rc and configure git
+ run: |
+ git fetch origin rc
+ git checkout rc
+ git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
+ git config --local user.name "gitea-actions[bot]"
+ git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
+
+ - name: Publish RC release
+ run: |
+ php ${MOKO_CLI}/release_publish.php \
+ --path . --stability rc --bump minor --branch rc \
+ --token "${{ secrets.MOKOGITEA_TOKEN }}"
+
+ - name: Summary
+ if: always()
+ run: |
+ echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
+ echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
+
+ # ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
+ release:
+ name: Build & Release Pipeline
+ runs-on: release
+ if: >-
+ github.event.pull_request.merged == true ||
+ (github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+ with:
+ token: ${{ secrets.MOKOGITEA_TOKEN }}
+ fetch-depth: 0
+
+ - name: Configure git for bot pushes
+ run: |
+ git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
+ git config --local user.name "gitea-actions[bot]"
+ git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
+
+ - name: Check for merge conflict markers
+ run: |
+ CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
+ if [ -n "$CONFLICTS" ]; then
+ echo "::error::Merge conflict markers found — aborting release"
+ echo "## Release Blocked: Conflict Markers" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+ echo "No conflict markers found"
+
+ - name: Setup moko-platform tools
+ env:
+ MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
+ MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
+ COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
+ run: |
+ if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
+ echo Using pre-installed /opt/moko-platform
+ echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
+ else
+ echo Falling back to fresh clone
+ if ! command -v composer > /dev/null 2>&1; then
+ 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
+ rm -rf /tmp/moko-platform-api
+ CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
+ git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
+ cd /tmp/moko-platform-api
+ composer install --no-dev --no-interaction --quiet
+ echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
+ fi
+
+ - name: "Publish stable release"
+ run: |
+ php ${MOKO_CLI}/release_publish.php \
+ --path . --stability stable --bump minor --branch main \
+ --token "${{ secrets.MOKOGITEA_TOKEN }}"
+
+ - name: Update release notes from CHANGELOG.md
+ run: |
+ API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
+
+ # Extract [Unreleased] section from changelog
+ if [ -f "CHANGELOG.md" ]; then
+ NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
+ [ -z "$NOTES" ] && NOTES="Stable release"
+ else
+ NOTES="Stable release"
+ fi
+
+ # Update release body via API
+ RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
+ "${API_BASE}/releases/tags/stable" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
+
+ if [ -n "$RELEASE_ID" ]; then
+ python3 -c "
+ import json, urllib.request
+ body = open('/dev/stdin').read()
+ payload = json.dumps({'body': body}).encode()
+ req = urllib.request.Request(
+ '${API_BASE}/releases/${RELEASE_ID}',
+ data=payload, method='PATCH',
+ headers={
+ 'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
+ 'Content-Type': 'application/json'
+ })
+ urllib.request.urlopen(req)
+ " <<< "$NOTES"
+ echo "Release notes updated from CHANGELOG.md"
+ fi
+
+ # -- STEP 9: Mirror to GitHub (stable only) --------------------------------
+ - name: "Step 9: Mirror release to GitHub"
+ if: >-
+ steps.version.outputs.skip != 'true' &&
+ secrets.GH_MIRROR_TOKEN != ''
+ continue-on-error: true
+ run: |
+ VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
+ RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
+ GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
+ API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
+ php ${MOKO_CLI}/release_mirror.php \
+ --version "$VERSION" --tag "$RELEASE_TAG" \
+ --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
+ --gh-token "${{ secrets.GH_MIRROR_TOKEN }}" --gh-repo "$GH_REPO" \
+ --branch main 2>&1 || true
+ echo "GitHub mirror updated" >> $GITHUB_STEP_SUMMARY
+
+ # -- STEP 10: Sync main branch to GitHub mirror ----------------------------
+ - name: "Step 10: Push main to GitHub mirror"
+ if: >-
+ steps.version.outputs.skip != 'true' &&
+ secrets.GH_MIRROR_TOKEN != ''
+ continue-on-error: true
+ run: |
+ GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
+ GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
+ GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
+ git remote add github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
+ git remote set-url github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
+ git fetch origin main --depth=1
+ git push github origin/main:refs/heads/main --force 2>/dev/null \
+ && echo "main branch pushed to GitHub mirror" \
+ || echo "WARNING: GitHub mirror push failed"
+
+ - name: "Step 11: Delete rc branch and recreate dev 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.MOKOGITEA_TOKEN }}"
+
+ # Delete rc branch (ephemeral — created by promote-rc)
+ curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
+ "${API_BASE}/branches/rc" 2>/dev/null \
+ && echo "Deleted rc branch" || echo "rc branch not found"
+
+ # 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}/branches" \
+ -d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
+
+ echo "Pre-release branches cleaned, dev reset from main" >> $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.MOKOGITEA_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
+
+
+
+ # -- Dolibarr post-release: Reset dev version -----------------------------
+ - name: "Post-release: Reset dev version"
+ if: steps.version.outputs.skip != 'true'
+ continue-on-error: true
+ run: |
+ API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
+ php ${MOKO_CLI}/version_reset_dev.php \
+ --token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
+ --branch dev --path . 2>&1 || true
+
+ # -- Summary --------------------------------------------------------------
+ - name: Pipeline Summary
+ if: always()
+ run: |
+ VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
+ PLATFORM="${{ steps.platform.outputs.platform }}"
+ if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
+ echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
+ echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
+ elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
+ echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "## Build & Release Complete (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
+ echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
+ echo "| Platform | \`${PLATFORM}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
+ echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
+ fi
diff --git a/.mokogitea/workflows/issue-branch.yml b/.mokogitea/workflows/issue-branch.yml
index eb67f8f..20eb493 100644
--- a/.mokogitea/workflows/issue-branch.yml
+++ b/.mokogitea/workflows/issue-branch.yml
@@ -3,9 +3,9 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
-# DEFGROUP: MokoGitea.Workflow
-# INGROUP: mokocli.Automation
-# VERSION: 01.00.00
+# DEFGROUP: Gitea.Workflow
+# INGROUP: moko-platform.Automation
+# VERSION: 01.21.08
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
@@ -19,7 +19,7 @@ permissions:
issues: write
env:
- MOKOGITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
+ GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
create-branch:
@@ -28,8 +28,8 @@ jobs:
steps:
- name: Create branch and comment
run: |
- TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
- API="${MOKOGITEA_URL}/api/v1/repos/${{ github.repository }}"
+ TOKEN="${{ secrets.GA_TOKEN }}"
+ API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
ISSUE_NUM="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
@@ -58,7 +58,7 @@ jobs:
echo "Created branch: ${BRANCH}"
# Comment on issue with branch link
- REPO_URL="${MOKOGITEA_URL}/${{ github.repository }}"
+ REPO_URL="${GITEA_URL}/${{ github.repository }}"
BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`"
curl -sf -X POST \
diff --git a/.mokogitea/workflows/pr-check.yml b/.mokogitea/workflows/pr-check.yml
index 2874d60..ed2c446 100644
--- a/.mokogitea/workflows/pr-check.yml
+++ b/.mokogitea/workflows/pr-check.yml
@@ -7,7 +7,7 @@
# INGROUP: mokocli.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.mokogitea/workflows/pr-check.yml
-# VERSION: 09.23.00
+# VERSION: 09.23.00
# BRIEF: PR gate — branch policy + code validation before merge
name: "Universal: PR Check"
diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml
index b212772..24c47e0 100644
--- a/.mokogitea/workflows/pre-release.yml
+++ b/.mokogitea/workflows/pre-release.yml
@@ -3,11 +3,11 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
-# DEFGROUP: MokoGitea.Workflow
-# INGROUP: mokocli.Release
-# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
-# PATH: /.mokogitea/workflows/pre-release.yml
-# VERSION: 05.02.01
+# DEFGROUP: Gitea.Workflow
+# INGROUP: moko-platform.Release
+# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
+# PATH: /templates/workflows/universal/pre-release.yml.template
+# VERSION: 05.01.00
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
name: "Universal: Pre-Release"
@@ -48,13 +48,9 @@ jobs:
build:
name: "Build Pre-Release (${{ inputs.stability || github.ref_name }})"
runs-on: release
- # Skip on template repos (Template-*) — they scaffold other repos and do not release.
if: >-
- !startsWith(github.event.repository.name, 'Template-') &&
- (
- github.event_name == 'workflow_dispatch' ||
- github.event_name == 'push'
- )
+ github.event_name == 'workflow_dispatch' ||
+ github.event_name == 'push'
steps:
- name: Checkout
@@ -63,31 +59,26 @@ jobs:
fetch-depth: 0
token: ${{ secrets.MOKOGITEA_TOKEN }}
ref: ${{ github.ref_name }}
- submodules: recursive
- - name: Update submodules to main
- run: |
- git submodule foreach --quiet 'git checkout main && git pull --quiet origin main' 2>/dev/null || true
-
- - name: Setup mokocli tools
+ - name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
run: |
- # Use pre-installed /opt/mokocli if available (updated by cron every 6h)
- if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/cli/manifest_element.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
- echo Using pre-installed /opt/mokocli
- echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
+ # Use pre-installed /opt/moko-platform if available (updated by cron every 6h)
+ if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/cli/manifest_element.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
+ echo Using pre-installed /opt/moko-platform
+ echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
else
echo Falling back to fresh clone
if ! command -v composer > /dev/null 2>&1; then
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
- rm -rf /tmp/mokocli
- CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoCLI.git
- git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
- cd /tmp/mokocli && composer install --no-dev --no-interaction --quiet
- echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
+ rm -rf /tmp/moko-platform-api
+ CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
+ git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
+ cd /tmp/moko-platform-api && composer install --no-dev --no-interaction --quiet
+ echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
fi
- name: Detect platform
@@ -97,20 +88,8 @@ jobs:
php ${MOKO_CLI}/platform_detect.php --path . --github-output 2>/dev/null || true
php ${MOKO_CLI}/manifest_read.php --path . --github-output
- - name: Check platform eligibility (Joomla only)
- id: eligibility
- run: |
- PLATFORM="${{ steps.platform.outputs.platform }}"
- if [[ "$PLATFORM" == joomla* ]] || [[ "$PLATFORM" == "joomla" ]]; then
- echo "proceed=true" >> "$GITHUB_OUTPUT"
- else
- echo "proceed=false" >> "$GITHUB_OUTPUT"
- echo "::notice::Platform '$PLATFORM' — non-Joomla, skipping pre-release auto-bump"
- fi
-
- name: Resolve metadata and bump version
id: meta
- if: steps.eligibility.outputs.proceed == 'true'
run: |
# Auto-detect stability from branch name on push, or use input on dispatch
if [ "${{ github.event_name }}" = "push" ]; then
@@ -156,19 +135,13 @@ jobs:
fi
# Commit version bump
- git config --local user.email "mokogitea-actions[bot]@mokoconsulting.tech"
- git config --local user.name "mokogitea-actions[bot]"
+ git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
+ git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
git add -A
git diff --cached --quiet || {
git commit -m "chore(version): pre-release bump to ${VERSION} [skip ci]"
- # Push the bump commit, but do NOT fail the release if the target branch
- # is protected and the release identity is not on the push allowlist.
- # The build proceeds from the in-tree bumped version regardless; if the
- # push is rejected, the next run simply re-bumps from the same base.
- if ! git push origin HEAD 2>&1; then
- echo "::warning::Version-bump commit could not be pushed (protected branch?). Building from in-tree version ${VERSION} anyway."
- fi
+ git push origin HEAD 2>&1
}
# Auto-detect element via manifest_element.php
@@ -193,7 +166,6 @@ jobs:
- name: Create release
id: release
- if: steps.eligibility.outputs.proceed == 'true'
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
@@ -204,7 +176,6 @@ jobs:
--repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease
- name: Update release notes from CHANGELOG.md
- if: steps.eligibility.outputs.proceed == 'true'
run: |
TAG="${{ steps.meta.outputs.tag }}"
VERSION="${{ steps.meta.outputs.version }}"
@@ -241,7 +212,6 @@ jobs:
- name: Build package and upload
id: package
- if: steps.eligibility.outputs.proceed == 'true'
run: |
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
@@ -255,7 +225,6 @@ jobs:
# No need to build, commit, or sync updates.xml from workflows
- name: "Delete lesser pre-release channels (cascade)"
- if: steps.eligibility.outputs.proceed == 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
@@ -280,4 +249,4 @@ jobs:
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Channel | ${STABILITY} |" >> $GITHUB_STEP_SUMMARY
echo "| Package | \`${ZIP_NAME}\` |" >> $GITHUB_STEP_SUMMARY
- echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
\ No newline at end of file
+ echo "| SHA-256 | \`${SHA256:-n/a}\` |" >> $GITHUB_STEP_SUMMARY
diff --git a/CLAUDE.md b/CLAUDE.md
index ef361ea..0f71524 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -60,5 +60,5 @@ This is a Joomla **site module** (`mod_mokojoomhero`).
## Coding Standards
-- PHP 8.1+ minimum
+- PHP 8.3+ minimum
- SPDX license headers on all PHP files
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index a9382df..45d168c 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -14,7 +14,7 @@
DEFGROUP:
INGROUP: Project.Documentation
REPO:
- VERSION: 01.21.01
+ VERSION: 01.21.08
PATH: ./CODE_OF_CONDUCT.md
BRIEF: Reference + packaging repo for Moko Consulting Developer GPT Other Default
-->
diff --git a/README.md b/README.md
index e706865..434027e 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@ A Joomla site module for random hero image slideshows, video backgrounds, solid
## Overview
-MokoJoomHero is a free, open-source Joomla module that creates dynamic hero sections with multiple background modes, configurable content overlays, and advanced features like parallax scrolling, A/B testing, and scheduling. Designed for the MokoOnyx template but works with any Joomla 5/6 template.
+MokoJoomHero is a free, open-source Joomla module that creates dynamic hero sections with multiple background modes, configurable content overlays, and advanced features like parallax scrolling, A/B testing, and scheduling. Designed for the MokoOnyx template but works with any Joomla 6 template.
## Features
@@ -46,8 +46,8 @@ MokoJoomHero is a free, open-source Joomla module that creates dynamic hero sect
## Prerequisites
-- **PHP**: 8.1 or higher
-- **Joomla**: 5.x or 6.x
+- **PHP**: 8.3 or higher
+- **Joomla**: 6.x or higher
## Installation
diff --git a/SECURITY.md b/SECURITY.md
index baf0f55..a51093b 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -23,7 +23,7 @@ DEFGROUP: [PROJECT_NAME]
INGROUP: [PROJECT_NAME].Documentation
REPO: [REPOSITORY_URL]
PATH: /SECURITY.md
-VERSION: 01.21.01
+VERSION: 01.21.08
BRIEF: Security vulnerability reporting and handling policy
-->
diff --git a/composer.json b/composer.json
index 6f30f8b..489c6a7 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
"name": "mokoconsulting/tpl-mokojoomhero",
- "description": "MokoJoomHero — Modern Joomla 5 template by Moko Consulting",
+ "description": "MokoJoomHero — Modern Joomla 6 template by Moko Consulting",
"type": "joomla-template",
"license": "GPL-3.0-or-later",
"authors": [
@@ -11,7 +11,7 @@
}
],
"require": {
- "php": ">=8.1"
+ "php": ">=8.3"
},
"require-dev": {
"squizlabs/php_codesniffer": "^3.7",
diff --git a/src/language/en-GB/mod_mokojoomhero.ini b/src/language/en-GB/mod_mokojoomhero.ini
index 7384cbd..58037a6 100644
--- a/src/language/en-GB/mod_mokojoomhero.ini
+++ b/src/language/en-GB/mod_mokojoomhero.ini
@@ -6,7 +6,7 @@
; INGROUP: MokoJoomHero.Module
; REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
; PATH: /src/language/en-GB/mod_mokojoomhero.ini
-; VERSION: 01.21.01
+; VERSION: 01.21.08
; BRIEF: Language strings for MokoJoomHero module (frontend + admin form fields)
MOD_MOKOJOOMHERO_NO_CONTENT="Add content to this module to display it over the hero image."
diff --git a/src/language/en-GB/mod_mokojoomhero.sys.ini b/src/language/en-GB/mod_mokojoomhero.sys.ini
index 6895e83..44dd23f 100644
--- a/src/language/en-GB/mod_mokojoomhero.sys.ini
+++ b/src/language/en-GB/mod_mokojoomhero.sys.ini
@@ -6,7 +6,7 @@
; INGROUP: MokoJoomHero.Module
; REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
; PATH: /src/language/en-GB/mod_mokojoomhero.sys.ini
-; VERSION: 01.21.01
+; VERSION: 01.21.08
; BRIEF: System language strings — used in admin Extension Manager and Module Manager
MOD_MOKOJOOMHERO="Module - MokoJoomHero"
diff --git a/src/language/en-US/mod_mokojoomhero.ini b/src/language/en-US/mod_mokojoomhero.ini
index d9980ac..dafb6a9 100644
--- a/src/language/en-US/mod_mokojoomhero.ini
+++ b/src/language/en-US/mod_mokojoomhero.ini
@@ -6,7 +6,7 @@
; INGROUP: MokoJoomHero.Module
; REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
; PATH: /src/language/en-US/mod_mokojoomhero.ini
-; VERSION: 01.21.01
+; VERSION: 01.21.08
; BRIEF: Language strings for MokoJoomHero module (en-US, frontend + admin form fields)
MOD_MOKOJOOMHERO_NO_CONTENT="Add content to this module to display it over the hero image."
diff --git a/src/language/en-US/mod_mokojoomhero.sys.ini b/src/language/en-US/mod_mokojoomhero.sys.ini
index 9b84ea1..480804b 100644
--- a/src/language/en-US/mod_mokojoomhero.sys.ini
+++ b/src/language/en-US/mod_mokojoomhero.sys.ini
@@ -6,7 +6,7 @@
; INGROUP: MokoJoomHero.Module
; REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
; PATH: /src/language/en-US/mod_mokojoomhero.sys.ini
-; VERSION: 01.21.01
+; VERSION: 01.21.08
; BRIEF: System language strings — used in admin Extension Manager and Module Manager (en-US)
MOD_MOKOJOOMHERO="Module - MokoJoomHero"
diff --git a/src/media/css/mod_mokojoomhero.css b/src/media/css/mod_mokojoomhero.css
index d0c2898..eeaf213 100644
--- a/src/media/css/mod_mokojoomhero.css
+++ b/src/media/css/mod_mokojoomhero.css
@@ -7,7 +7,7 @@
* INGROUP: MokoJoomHero.Module
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
* PATH: /src/media/css/mod_mokojoomhero.css
- * VERSION: 01.21.01
+ * VERSION: 01.21.08
* BRIEF: Hero module stylesheet — slideshow, video, colour/gradient, overlay, card, mute toggle, responsive
*/
diff --git a/src/media/js/mod_mokojoomhero.js b/src/media/js/mod_mokojoomhero.js
index ce5b1ee..53b718e 100644
--- a/src/media/js/mod_mokojoomhero.js
+++ b/src/media/js/mod_mokojoomhero.js
@@ -8,7 +8,7 @@
* INGROUP: MokoJoomHero.Module
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoJoomHero
* PATH: /src/media/js/mod_mokojoomhero.js
- * VERSION: 01.21.01
+ * VERSION: 01.21.08
* BRIEF: Hero module JavaScript — slideshow crossfade, video viewport control, mute toggle
*/
diff --git a/src/mod_mokojoomhero.xml b/src/mod_mokojoomhero.xml
index 605eea0..8f32be3 100644
--- a/src/mod_mokojoomhero.xml
+++ b/src/mod_mokojoomhero.xml
@@ -22,7 +22,7 @@
https://mokoconsulting.tech
Copyright (C) 2026 Moko Consulting. All rights reserved.
GPL-3.0-or-later
- 01.21.01
+ 01.21.08-dev
Random hero image slideshow, video backgrounds, solid colour/gradient, parallax, content animations, A/B testing, scheduling, and overlay with card support. Free and open source. By Moko Consulting.
script.php