Compare commits

..

121 Commits

Author SHA1 Message Date
gitea-actions[bot] d026ce727d chore: update stable channel 02.08.00 [skip ci] 2026-05-29 05:38:36 +00:00
gitea-actions[bot] 431fe41fd9 chore(release): build 02.08.00 [skip ci] 2026-05-29 05:38:34 +00:00
jmiller 000fbdb24d Merge pull request 'fix: align all version numbers to 02.08.00' (#91) from dev into main
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Cascade Main → Dev / Cascade main → branches (push) Failing after 1s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-29 05:38:24 +00:00
jmiller 2377aac953 chore: sync updates.xml from development [skip ci] 2026-05-29 05:38:14 +00:00
gitea-actions[bot] c1c9ea3ce3 chore: update development channel 02.08.00-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 12s
2026-05-29 05:38:13 +00:00
gitea-actions[bot] e74b053931 chore(version): auto-bump 02.08.00-dev [skip ci] 2026-05-29 05:38:12 +00:00
Jonathan Miller 2cfe54b85d fix: align templateDetails.xml version to 02.08.00 (remove -dev suffix) [skip bump]
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Update Server / Update Server (push) Successful in 9s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
All version sources must match for Joomla update detection:
templateDetails.xml, manifest.xml, and updates.xml.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 00:37:59 -05:00
Jonathan Miller 5670850258 fix: point dev stream to stable 02.08.00 (highest release) [skip ci]
When stable is higher than dev, the development stream must also
point to the stable release. Otherwise Joomla sees the lower dev
version, picks stable as upgrade, installs it, but dev stream still
shows lower version causing an update loop.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 00:33:35 -05:00
Jonathan Miller 8d1468ffae fix: update SHA256 checksum to match rebuilt release ZIP [skip ci]
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 00:28:55 -05:00
gitea-actions[bot] f21e9169e3 chore: update stable channel 02.08.00 [skip ci] 2026-05-29 05:13:10 +00:00
gitea-actions[bot] a3c3b56655 chore(release): build 02.08.00 [skip ci] 2026-05-29 05:13:09 +00:00
jmiller f18fb7ce4a Merge pull request 'feat: distinct menu overrides for mainmenu, horizontal, default' (#90) from dev into main
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Cascade Main → Dev / Cascade main → branches (push) Failing after 2s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-29 05:13:01 +00:00
jmiller 9c8487492c chore: sync updates.xml from development [skip ci] 2026-05-29 05:11:35 +00:00
gitea-actions[bot] 4f56bb0563 chore: update development channel 02.08.00-dev [skip ci]
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 12s
2026-05-29 05:11:34 +00:00
Jonathan Miller 3cbeb7c96e feat: add distinct menu overrides for three layout types [skip bump]
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Update Server / Update Server (push) Successful in 8s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
- mainmenu: collapsible navbar behind hamburger (primary nav)
- horizontal: always-visible wrapping links (Quick Links, utility nav)
- default: vertical list with title support (sidebar, footer)

Each set has its own BEM prefix and sub-layouts (url, component,
heading, separator).

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 00:11:21 -05:00
Jonathan Miller d727fefa57 fix: correct element to mokoonyx in updates.xml (no tpl_ prefix) [skip ci]
Joomla stores templates as bare element name in #__extensions.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-29 00:06:18 -05:00
gitea-actions[bot] 1b6dafa88a chore: update stable channel 02.08.00 [skip ci] 2026-05-29 00:09:53 +00:00
gitea-actions[bot] 7d8c112cb7 chore(release): build 02.08.00 [skip ci] 2026-05-29 00:09:51 +00:00
jmiller d5436a58f4 Merge pull request 'fix: remove duplicate hamburger from mainmenu override' (#89) from dev into main
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Cascade Main → Dev / Cascade main → branches (push) Failing after 1s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-29 00:09:40 +00:00
gitea-actions[bot] 06468b4393 chore: update development channel 02.08.00-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 13s
2026-05-29 00:09:25 +00:00
jmiller a4c6d59f35 chore: sync updates.xml from development [skip ci] 2026-05-29 00:09:25 +00:00
Jonathan Miller 61823554d4 fix: remove duplicate hamburger from mainmenu override [skip bump]
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Update Server / Update Server (push) Successful in 11s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
The mainmenu.php layout had its own navbar-toggler button, creating
a second hamburger on mobile. Now delegates to the single hamburger
in index.php like horizontal.php does.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 19:09:14 -05:00
gitea-actions[bot] ae3992fe44 chore: update stable channel 02.08.00 [skip ci] 2026-05-28 22:37:37 +00:00
gitea-actions[bot] b7d1e5407f chore(release): build 02.08.00 [skip ci] 2026-05-28 22:37:34 +00:00
jmiller d4a8858226 Merge pull request 'fix: update manifest.xml name and version' (#88) from dev into main
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: Cascade Main → Dev / Cascade main → branches (push) Failing after 3s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-28 22:37:17 +00:00
Jonathan Miller c52f7e7624 fix: update manifest.xml name and version [skip bump]
Generic: Repo Health / Site Health (push) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Access control (pull_request) Successful in 3s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Successful in 10s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 34s
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 21s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Generic: Repo Health / Release configuration (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 17:36:36 -05:00
gitea-actions[bot] 3d4596bad7 chore: update stable channel 02.08.01 [skip ci] 2026-05-28 22:04:22 +00:00
gitea-actions[bot] eb1e5eaa24 chore(release): build 02.08.01 [skip ci] 2026-05-28 22:04:19 +00:00
jmiller af25f3ead2 Merge pull request 'fix: clean updates.xml - correct names, versions, paths' (#87) from dev into main
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Cascade Main → Dev / Cascade main → branches (push) Failing after 2s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-28 22:04:10 +00:00
Jonathan Miller e538ec6348 Merge branch 'dev' of https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx into dev
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Access control (pull_request) Successful in 2s
Universal: Auto Version Bump / Version Bump (push) Successful in 7s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 7s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Successful in 9s
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 13s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 28s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Generic: Repo Health / Release configuration (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
2026-05-28 17:03:54 -05:00
Jonathan Miller 5729a2334c chore: merge main into dev, keep dev updates.xml [skip ci]
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 17:02:56 -05:00
gitea-actions[bot] d730ce8deb chore(version): auto-bump patch 02.08.00-dev [skip ci] 2026-05-28 22:00:41 +00:00
Jonathan Miller 3aaa22ecce fix: align updates.xml and manifest to stable 02.08.00
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Auto Version Bump / Version Bump (push) Successful in 6s
Update Server / Update Server (push) Failing after 11s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Remove -dev suffix from version and filenames. Add all update streams
(alpha, beta, rc, stable) pointing to stable release. Fix release name
on Gitea.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 16:59:07 -05:00
jmiller d8e6938021 chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-28 20:53:11 +00:00
jmiller e621b4d901 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-28 20:50:39 +00:00
jmiller 8263cbd5c9 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-28 20:48:21 +00:00
jmiller 346f031075 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:45:57 +00:00
jmiller f95ac86875 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:43:09 +00:00
jmiller 6dce03b3ed chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:37:46 +00:00
jmiller 23d0affc18 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:27:49 +00:00
jmiller c110c2ceca chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-28 20:08:53 +00:00
jmiller 22dcdb90df chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-28 20:05:35 +00:00
jmiller c0e1cebe18 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:02:12 +00:00
jmiller 17b2a0d7be chore: sync updates.xml from development [skip ci] 2026-05-28 19:52:28 +00:00
gitea-actions[bot] 8002c6cddf chore: update development channel 02.08.01-dev-dev [skip ci] 2026-05-28 19:52:27 +00:00
gitea-actions[bot] 6495a74f75 chore(version): auto-bump 02.08.01-dev-dev [skip ci] 2026-05-28 19:52:25 +00:00
Jonathan Miller 277082114f fix: correct updates.xml paths, names, and version alignment
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: Auto Version Bump / Version Bump (push) Successful in 4s
Update Server / Update Server (push) Successful in 13s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Resolve stash conflicts, fix doubled "Template - Template -" prefix,
tripled -dev-dev-dev suffix, and stale 02.07.x versions. Align
manifest and updates.xml to 02.08.00-dev with correct tpl_mokoonyx-
download prefix.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 14:51:53 -05:00
Moko Consulting 25054e1273 fix(workflows): rename remaining old secrets in repo-specific workflows [skip bump]
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-28 14:50:02 -05:00
jmiller 6fa45b8c98 Merge pull request 'Rename template to Template - MokoOnyx' (#86) from dev into main
Universal: Cascade Main → Dev / Cascade main → branches (push) Failing after 3s
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-28 19:43:00 +00:00
jmiller b2bf5dda7e chore: sync updates.xml from development [skip ci] 2026-05-28 19:41:13 +00:00
gitea-actions[bot] 1c56349833 chore: update development channel 02.07.03-dev-dev [skip ci]
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 20s
2026-05-28 19:41:12 +00:00
gitea-actions[bot] 07e904a0b4 chore(version): auto-bump 02.07.03-dev-dev [skip ci] 2026-05-28 19:41:10 +00:00
Jonathan Miller 48b3e8099b style: rename template to "Template - MokoOnyx"
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Auto Version Bump / Version Bump (push) Successful in 5s
Update Server / Update Server (push) Successful in 13s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 14:40:43 -05:00
jmiller 5c8859ac29 Merge pull request 'Merge dev into main - CI updates and icon spacing' (#85) from dev into main
Universal: Cascade Main → Dev / Cascade main → branches (push) Failing after 3s
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 4s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-28 19:34:19 +00:00
gitea-actions[bot] 5c3600b358 chore(version): auto-bump patch 02.07.02-dev [skip ci]
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Branch Cleanup / Delete merged branch (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Successful in 47s
2026-05-28 19:34:16 +00:00
Jonathan Miller 569979c1b8 chore: resolve merge conflicts from main into dev
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Generic: Repo Health / Access control (pull_request) Successful in 3s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 6s
Universal: Auto Version Bump / Version Bump (push) Successful in 7s
Universal: PR Check / Validate PR (pull_request) Successful in 9s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 37s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Generic: Repo Health / Release configuration (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 14:33:39 -05:00
Moko Consulting 159ad30ec7 chore(workflows): sync all universal workflows from moko-platform [skip bump]
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Generic: Repo Health / Access control (pull_request) Successful in 3s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 5s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 5s
Universal: PR Check / Validate PR (pull_request) Successful in 7s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 30s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Generic: Repo Health / Release configuration (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
2026-05-28 14:25:38 -05:00
Moko Consulting 1d807ca7a8 refactor(workflows): rename secrets MOKOGITEA_TOKEN/GITHUB_TOKEN, use x-access-token [skip bump]
Generic: Repo Health / Site Health (push) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Access control (pull_request) Successful in 3s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 4s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Successful in 7s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 25s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Generic: Repo Health / Release configuration (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
2026-05-28 14:24:07 -05:00
Moko Consulting f76b24de13 fix(workflows): proper suffix handling — use version_set_platform instead of sed [skip bump]
Generic: Repo Health / Site Health (push) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: Build & Release / Promote Pre-Release to RC (pull_request) Has been skipped
Universal: Build & Release / Build & Release Pipeline (pull_request) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 2s
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 6s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 6s
Universal: PR Check / Validate PR (pull_request) Successful in 8s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 31s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Generic: Repo Health / Release configuration (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
2026-05-28 14:16:01 -05:00
jmiller 00a4fd7b46 chore: sync updates.xml from [skip ci] 2026-05-28 19:09:34 +00:00
gitea-actions[bot] 79ce5f4a49 chore: update updates.xml (development: 02.07.02-dev) [skip ci] 2026-05-28 19:09:33 +00:00
gitea-actions[bot] d5e2018540 chore(version): auto-bump patch 02.07.02 [skip ci] 2026-05-28 19:09:32 +00:00
Jonathan Miller 37317288cc style: add margin-right to .fa-solid icons
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Universal: Auto Version Bump / Version Bump (push) Successful in 3s
Update Server / Update updates.xml (push) Failing after 9s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-28 14:09:10 -05:00
jmiller 797abc928a chore: sync updates.xml from [skip ci] 2026-05-28 19:03:02 +00:00
gitea-actions[bot] e6543251d8 chore: update updates.xml (development: 02.07.01-dev) [skip ci] 2026-05-28 19:03:02 +00:00
gitea-actions[bot] 6f940be6d2 chore(version): auto-bump patch 02.07.01 [skip ci] 2026-05-28 19:03:01 +00:00
Moko Consulting 9aa01cccc5 chore: trigger update-server workflow for version suffix [skip bump]
Generic: Repo Health / Site Health (push) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Update Server / Update updates.xml (push) Failing after 8s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-28 14:02:48 -05:00
Moko Consulting 13f29a0df8 feat(workflows): append stability suffix to manifest versions [skip bump]
Generic: Repo Health / Site Health (push) Has been skipped
Universal: Auto Version Bump / Version Bump (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
2026-05-28 13:42:18 -05:00
jmiller 70e8f621f7 docs: add infrastructure changes to CHANGELOG [skip ci] 2026-05-27 05:46:07 +00:00
jmiller 2b370497d1 docs: update CHANGELOG with infrastructure changes [skip ci] 2026-05-27 05:32:49 +00:00
jmiller f6aef1959e chore: add branch-cleanup workflow [skip ci] 2026-05-27 03:52:40 +00:00
gitea-actions[bot] b53bba53ac feat(ci): add version branch creation on stable release [skip ci] 2026-05-27 02:19:24 +00:00
jmiller 9c9db876d0 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:50:54 +00:00
jmiller 7d2ea3e04f chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:50:53 +00:00
jmiller 130bd2c05f chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:49:41 +00:00
jmiller 654b27925c chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:49:41 +00:00
jmiller 708c70de33 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:48:29 +00:00
jmiller f383462d05 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:48:28 +00:00
jmiller 6810cdc537 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:36:57 +00:00
jmiller a293ac6a69 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:36:57 +00:00
jmiller e3e4f351c6 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:35:36 +00:00
jmiller e83f5631fb chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:35:35 +00:00
jmiller 3d0e1f91fe chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:25:12 +00:00
jmiller 5f1599d64c chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:25:12 +00:00
jmiller 7922ca3e67 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:23:56 +00:00
jmiller e2871bc5c6 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:23:55 +00:00
jmiller 0bb0b99701 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:13:19 +00:00
jmiller be47d213f3 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:13:19 +00:00
jmiller 1e353f5519 chore(ci): add auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:12:07 +00:00
jmiller 4929cb0d0e chore(ci): add auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:12:07 +00:00
jmiller 9d04e22852 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-26 20:12:37 +00:00
jmiller ec859bcc06 chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-26 20:10:42 +00:00
jmiller e321e0f824 fix(ci): use release_package.php for Joomla package builds [skip ci] 2026-05-26 19:54:38 +00:00
jmiller b7de171730 fix(ci): use release_package.php for Joomla package builds [skip ci] 2026-05-26 19:54:38 +00:00
jmiller 4150b26712 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 19:36:21 +00:00
jmiller c9a7627d29 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 19:36:21 +00:00
jmiller d30698b826 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 19:36:20 +00:00
jmiller 6f808fe91d chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 19:36:20 +00:00
jmiller 42cd991bf4 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-26 19:04:01 +00:00
jmiller 19ac79b3e7 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 17:36:26 +00:00
jmiller 7fe73aced2 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 17:35:09 +00:00
jmiller 192e1a0b0b feat: add update-server.yml with updates.xml integrity check [skip ci] 2026-05-26 04:49:18 +00:00
jmiller ec812da933 feat: add update-server.yml with updates.xml integrity check [skip ci] 2026-05-26 04:49:17 +00:00
gitea-actions[bot] 4beb399689 fix(ci): update workflows — tag dev, client site, version_check [skip ci] 2026-05-25 22:56:06 -05:00
jmiller 5bf23b3f21 fix: updates.xml tag dev not development + client site [skip ci] 2026-05-26 03:54:03 +00:00
jmiller d5dd5f316d fix(updates): broaden targetplatform to match Joomla 5.x and 6.x [skip ci] 2026-05-26 03:42:58 +00:00
jmiller 19178728b9 fix(updates): broaden targetplatform to match Joomla 5.x and 6.x [skip ci] 2026-05-26 03:42:36 +00:00
jmiller fa5b0a5163 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-26 03:07:25 +00:00
jmiller e78cffa0a9 chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-26 03:05:31 +00:00
Jonathan Miller a6bba8559c feat(ci): auto-create feature branch on issue open
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Release configuration (push) Failing after 4s
Generic: Repo Health / Scripts governance (push) Successful in 4s
Generic: Repo Health / Repository health (push) Failing after 5s
Creates feature/<number>-<slug> from dev when an issue is opened.
Comments on the issue with the branch name and checkout command.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-25 00:05:14 -05:00
jmiller 6034b4b150 Merge pull request 'chore: pre-release.yml rewrite + changelog update' (#74) from dev into main
Generic: Repo Health / Site Health (push) Has been skipped
Universal: Cascade Main -> Dev / Cascade main -> branches (push) Failing after 1s
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Release configuration (push) Failing after 3s
Generic: Repo Health / Scripts governance (push) Successful in 4s
Generic: Repo Health / Repository health (push) Failing after 4s
2026-05-25 04:20:49 +00:00
Jonathan Miller 6125f945be docs: update CHANGELOG with session work
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Release configuration (push) Failing after 3s
Generic: Repo Health / Scripts governance (push) Successful in 3s
Generic: Repo Health / Repository health (push) Failing after 4s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 1s
Generic: Repo Health / Access control (pull_request) Failing after 1s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Universal: PR Check / Build RC Package (pull_request) Has been skipped
Generic: Repo Health / Release configuration (pull_request) Has been skipped
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 3s
Generic: Repo Health / Scripts governance (pull_request) Has been skipped
Generic: Repo Health / Repository health (pull_request) Has been skipped
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 3s
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 8s
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been skipped
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been skipped
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been skipped
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been skipped
Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-24 23:17:08 -05:00
Jonathan Miller 2b0f0a3704 fix(ci): rewrite pre-release.yml with PHP CLI tools
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Release configuration (push) Failing after 3s
Generic: Repo Health / Scripts governance (push) Successful in 3s
Generic: Repo Health / Repository health (push) Failing after 3s
- Fix broken platform detection (mangled sed pipeline on line 58)
- Replace inline Python updates.xml manipulation with PHP
- Use moko-platform CLI tools (version_bump, version_set_platform,
  release_cascade) instead of inline reimplementations
- Support pre-installed /opt/moko-platform with fallback to git clone
- Add summary step for job output

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-24 23:10:56 -05:00
jmiller f26ddb1ef8 Merge pull request 'chore: cascade main -> dev (583af12) [skip ci]' (#73) from main into dev
chore: cascade main -> dev [skip ci]
2026-05-24 22:57:56 +00:00
jmiller 257ecb688a Add RC pre-release trigger to CI workflow
Generic: Repo Health / Site Health (push) Has been skipped
Universal: Cascade Main -> Dev / Cascade main -> branches (push) Successful in 2s
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Release configuration (push) Failing after 5s
Generic: Repo Health / Scripts governance (push) Successful in 5s
Generic: Repo Health / Repository health (push) Failing after 5s
Automatically triggers a release-candidate build when CI lint+tests
pass on a pull request.

Authored-by: Moko Consulting
2026-05-24 22:55:29 +00:00
jmiller 583af12dce Add RC pre-release trigger to PR check workflow
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: Cascade Main -> Dev / Cascade main -> branches (push) Successful in 5s
Generic: Repo Health / Release configuration (push) Failing after 7s
Generic: Repo Health / Scripts governance (push) Successful in 7s
Generic: Repo Health / Repository health (push) Failing after 8s
Automatically triggers a release-candidate build when a PR passes
branch policy and validation checks.

Authored-by: Moko Consulting
2026-05-24 22:54:39 +00:00
jmiller f73563d6ee Merge pull request 'chore: cascade main -> dev [skip ci]' (#72) from main into dev 2026-05-24 09:18:01 +00:00
jmiller f83fca9e31 chore: sync updates.xml 02.07.00 [skip ci] 2026-05-24 09:06:37 +00:00
gitea-actions[bot] 4ef655bce3 chore(release): ZIP + tar.gz for 02.07.00 [skip ci] 2026-05-24 09:06:37 +00:00
gitea-actions[bot] a1ce2f91a9 chore(release): build 02.07.00 [skip ci] 2026-05-24 09:06:35 +00:00
jmiller 4365a5ab4a Merge pull request 'chore: cascade main -> dev (c349458) [skip ci]' (#71) from main into dev
chore: cascade main -> dev [skip ci]
2026-05-24 09:05:44 +00:00
29 changed files with 1266 additions and 1946 deletions
+2 -1
View File
@@ -5,9 +5,10 @@
-->
<moko-platform xmlns="https://standards.mokoconsulting.tech/moko-platform/1.0" schema-version="1.0">
<identity>
<name>MokoOnyx</name>
<name>Template - MokoOnyx</name>
<org>MokoConsulting</org>
<description>MokoOnyx - Joomla site template (successor to MokoCassiopeia)</description>
<version>02.08.00</version>
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
</identity>
<governance>
+85
View File
@@ -0,0 +1,85 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
name: "Universal: Auto Version Bump"
on:
push:
branches:
- dev
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
jobs:
bump:
name: Version Bump
runs-on: release
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup moko-platform tools
run: |
if ! command -v composer &> /dev/null; 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
if [ -d "/opt/moko-platform/cli" ]; then
echo "MOKO_CLI=/opt/moko-platform/cli" >> "$GITHUB_ENV"
else
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/moko-platform.git" \
/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: Bump version
run: |
BUMP=$(php ${MOKO_CLI}/version_bump.php --path . 2>&1) || true
echo "$BUMP"
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null) || true
[ -z "$VERSION" ] && { echo "No version found — skipping"; exit 0; }
# Propagate to platform manifests with -dev suffix
php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch dev --stability dev 2>/dev/null || true
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
VERSION="${VERSION}-dev"
# Commit if anything changed
if git diff --quiet && git diff --cached --quiet; then
echo "No version changes to commit"
exit 0
fi
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 commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
git push origin dev
echo "Bumped to ${VERSION}" >> $GITHUB_STEP_SUMMARY
File diff suppressed because it is too large Load Diff
+48
View File
@@ -0,0 +1,48 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.mokogitea/workflows/branch-cleanup.yml
# VERSION: 01.00.00
# BRIEF: Delete feature branches after PR merge
name: "Branch Cleanup"
on:
pull_request:
types: [closed]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
cleanup:
name: Delete merged branch
runs-on: ubuntu-latest
if: >-
github.event.pull_request.merged == true &&
github.event.pull_request.head.ref != 'dev' &&
github.event.pull_request.head.ref != 'main'
steps:
- name: Delete source branch
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('${BRANCH}', safe=''))")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
"${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
elif [ "$STATUS" = "404" ]; then
echo "Branch already deleted: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::warning::Failed to delete branch ${BRANCH} (HTTP ${STATUS})"
fi
+33 -33
View File
@@ -8,21 +8,21 @@
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/cascade-dev.yml.template
# VERSION: 02.00.00
# BRIEF: Forward-merge main -> all open branches after every push to main
# BRIEF: Forward-merge main all open branches after every push to main
#
# +========================================================================+
# | CASCADE MAIN -> ALL BRANCHES |
# | CASCADE MAIN ALL BRANCHES |
# +========================================================================+
# | |
# | Triggers on every push to main (PR merges, bot commits, etc.) |
# | |
# | 1. List all branches matching: dev, rc/*, beta/*, alpha/* |
# | 2. For each: create PR (main -> branch), auto-merge if clean |
# | 2. For each: create PR (main branch), auto-merge if clean |
# | 3. On conflict: leave PR open for manual resolution |
# | |
# +========================================================================+
name: "Universal: Cascade Main -> Dev"
name: "Universal: Cascade Main Dev"
on:
push:
@@ -42,7 +42,7 @@ permissions:
jobs:
cascade:
name: Cascade main -> branches
name: Cascade main branches
runs-on: ubuntu-latest
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
@@ -52,7 +52,7 @@ jobs:
- name: Discover target branches
id: branches
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
@@ -61,7 +61,7 @@ jobs:
ALL_BRANCHES=""
while true; do
BATCH=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/branches?page=${PAGE}&limit=50" \
| jq -r '.[].name // empty')
[ -z "$BATCH" ] && break
@@ -83,17 +83,17 @@ jobs:
if [ -z "$TARGETS" ]; then
echo "targets=" >> "$GITHUB_OUTPUT"
echo " No cascade target branches found"
echo " No cascade target branches found"
else
echo "targets=$TARGETS" >> "$GITHUB_OUTPUT"
COUNT=$(echo "$TARGETS" | wc -w)
echo " Found ${COUNT} target branch(es): ${TARGETS}"
echo "📋 Found ${COUNT} target branch(es): ${TARGETS}"
fi
- name: Cascade to all target branches
if: steps.branches.outputs.targets != ''
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
SHORT_SHA="${GITHUB_SHA:0:7}"
@@ -106,27 +106,27 @@ jobs:
for BRANCH in $TARGETS; do
echo ""
echo " main -> ${BRANCH} "
echo "═══ main ${BRANCH} ═══"
# Check if branch is already up to date
ENCODED_BRANCH=$(echo "$BRANCH" | sed 's|/|%2F|g')
RESPONSE=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/compare/${ENCODED_BRANCH}...main")
AHEAD=$(echo "$RESPONSE" | jq '.total_commits // 0')
if [ "$AHEAD" -eq 0 ]; then
echo " Already up to date"
echo " Already up to date"
SKIPPED=$((SKIPPED + 1))
continue
fi
echo " main is ${AHEAD} commit(s) ahead"
echo " main is ${AHEAD} commit(s) ahead"
# Check for existing cascade PR
EXISTING=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/pulls?state=open&head=${GITEA_ORG}:main&base=${ENCODED_BRANCH}&limit=1")
EXISTING_COUNT=$(echo "$EXISTING" | jq 'length')
@@ -134,16 +134,16 @@ jobs:
if [ "$EXISTING_COUNT" -gt 0 ]; then
PR_NUMBER=$(echo "$EXISTING" | jq -r '.[0].number')
echo " Reusing existing PR #${PR_NUMBER}"
echo " Reusing existing PR #${PR_NUMBER}"
else
# Create cascade PR
PR_RESPONSE=$(curl -sS -w "\n%{http_code}" \
-X POST \
-H "Authorization: token ${GA_TOKEN}" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"chore: cascade main -> ${BRANCH} (${SHORT_SHA}) [skip ci]\",
\"body\": \"## Automatic cascade\\n\\nForward-merging \`main\` (${SHORT_SHA}) into \`${BRANCH}\`.\\n\\nIf conflicts exist, resolve manually and merge.\\n\\n> Auto-created by **Cascade Main -> Dev**.\",
\"title\": \"chore: cascade main ${BRANCH} (${SHORT_SHA}) [skip ci]\",
\"body\": \"## Automatic cascade\\n\\nForward-merging \`main\` (${SHORT_SHA}) into \`${BRANCH}\`.\\n\\nIf conflicts exist, resolve manually and merge.\\n\\n> Auto-created by **Cascade Main Dev**.\",
\"head\": \"main\",
\"base\": \"${BRANCH}\"
}" \
@@ -155,34 +155,34 @@ jobs:
if [ "$HTTP_CODE" != "201" ] || [ -z "$PR_NUMBER" ]; then
MSG=$(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)
echo " Failed to create PR (HTTP ${HTTP_CODE}): ${MSG}"
echo " Failed to create PR (HTTP ${HTTP_CODE}): ${MSG}"
FAILED=$((FAILED + 1))
continue
fi
echo " Created PR #${PR_NUMBER}"
echo " Created PR #${PR_NUMBER}"
fi
# Try auto-merge
PR_DATA=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/pulls/${PR_NUMBER}")
MERGEABLE=$(echo "$PR_DATA" | jq -r '.mergeable // false')
if [ "$MERGEABLE" != "true" ]; then
echo " Conflicts -- PR #${PR_NUMBER} left open"
echo " ⚠️ Conflicts PR #${PR_NUMBER} left open"
CONFLICTS=$((CONFLICTS + 1))
continue
fi
MERGE_RESPONSE=$(curl -sS -w "\n%{http_code}" \
-X POST \
-H "Authorization: token ${GA_TOKEN}" \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"Do\": \"merge\",
\"merge_message_field\": \"chore: cascade main -> ${BRANCH} [skip ci]\",
\"merge_message_field\": \"chore: cascade main ${BRANCH} [skip ci]\",
\"delete_branch_after_merge\": false
}" \
"${API}/pulls/${PR_NUMBER}/merge")
@@ -190,23 +190,23 @@ jobs:
MERGE_HTTP=$(echo "$MERGE_RESPONSE" | tail -1)
if [ "$MERGE_HTTP" = "200" ] || [ "$MERGE_HTTP" = "204" ]; then
echo " Merged -- ${BRANCH} is in sync"
echo " Merged ${BRANCH} is in sync"
SUCCESS=$((SUCCESS + 1))
else
MERGE_BODY=$(echo "$MERGE_RESPONSE" | sed '$d')
echo " Merge failed (HTTP ${MERGE_HTTP}) -- PR #${PR_NUMBER} left open"
echo " ⚠️ Merge failed (HTTP ${MERGE_HTTP}) PR #${PR_NUMBER} left open"
CONFLICTS=$((CONFLICTS + 1))
fi
done
# Summary
echo ""
echo ""
echo " Merged: ${SUCCESS}"
echo " Conflicts: ${CONFLICTS}"
echo " Up to date: ${SKIPPED}"
echo " Failed: ${FAILED}"
echo ""
echo "════════════════════════════════════════"
echo " Merged: ${SUCCESS}"
echo " ⚠️ Conflicts: ${CONFLICTS}"
echo " ⏭️ Up to date: ${SKIPPED}"
echo " Failed: ${FAILED}"
echo "════════════════════════════════════════"
if [ "$FAILED" -gt 0 ]; then
exit 1
+23 -6
View File
@@ -43,9 +43,9 @@ jobs:
- name: Clone MokoStandards
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' }}
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }}
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.MOKOGITEA_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" \
@@ -53,7 +53,7 @@ jobs:
- name: Install dependencies
env:
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}'
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.MOKOGITEA_TOKEN || github.token }}"}}'
run: |
if [ -f "composer.json" ]; then
composer install \
@@ -346,7 +346,7 @@ jobs:
- name: Install dependencies
env:
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}'
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.MOKOGITEA_TOKEN || github.token }}"}}'
run: |
if [ -f "composer.json" ]; then
composer install \
@@ -391,7 +391,7 @@ jobs:
- name: Install dependencies
env:
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}'
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.MOKOGITEA_TOKEN || github.token }}"}}'
run: |
if [ -f "composer.json" ]; then
composer install --no-interaction --prefer-dist --optimize-autoloader
@@ -448,3 +448,20 @@ jobs:
echo '```' >> $GITHUB_STEP_SUMMARY
fi
exit $EXIT
pre-release:
name: Build RC Pre-Release
runs-on: ubuntu-latest
needs: [lint-and-validate, test]
if: github.event_name == 'pull_request'
steps:
- name: Trigger pre-release build
env:
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: ${{ github.head_ref }}
run: |
curl -s -X POST "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY
echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY
+8 -8
View File
@@ -8,7 +8,7 @@
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.gitea/workflows/cleanup.yml
# VERSION: 01.00.00
# BRIEF: Scheduled cleanup -- delete merged branches and old workflow runs
# BRIEF: Scheduled cleanup delete merged branches and old workflow runs
name: "Universal: Repository Cleanup"
@@ -33,17 +33,17 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GA_TOKEN }}
token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Delete merged branches
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
echo "=== Merged Branch Cleanup ==="
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
# List branches via API
BRANCHES=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
BRANCHES=$(curl -sS -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/branches?limit=50" | jq -r '.[].name')
DELETED=0
@@ -56,7 +56,7 @@ jobs:
# Check if branch is merged into main
if git merge-base --is-ancestor "origin/${BRANCH}" origin/main 2>/dev/null; then
echo " Deleting merged branch: ${BRANCH}"
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/branches/${BRANCH}" 2>/dev/null || true
DELETED=$((DELETED + 1))
fi
@@ -66,20 +66,20 @@ jobs:
- name: Clean old workflow runs
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
run: |
echo "=== Workflow Run Cleanup ==="
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
CUTOFF=$(date -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-30d +%Y-%m-%dT%H:%M:%SZ)
# Get old completed runs
RUNS=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
RUNS=$(curl -sS -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/actions/runs?status=completed&limit=50" | \
jq -r ".workflow_runs[] | select(.created_at < \"${CUTOFF}\") | .id" 2>/dev/null)
DELETED=0
for RUN_ID in $RUNS; do
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
curl -sS -X DELETE -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
DELETED=$((DELETED + 1))
done
+2 -2
View File
@@ -8,7 +8,7 @@
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/gitleaks.yml.template
# VERSION: 01.00.00
# BRIEF: Secret scanning -- detect leaked credentials, API keys, and tokens
# BRIEF: Secret scanning detect leaked credentials, API keys, and tokens
#
# +========================================================================+
# | SECRET SCANNING |
@@ -89,7 +89,7 @@ jobs:
run: |
REPO="${{ github.event.repository.name }}"
curl -sS \
-H "Title: ${REPO} -- secrets detected in code" \
-H "Title: ${REPO} secrets detected in code" \
-H "Tags: rotating_light,key" \
-H "Priority: urgent" \
-d "Gitleaks found potential secrets. Review and rotate credentials immediately." \
+73
View File
@@ -0,0 +1,73 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Automation
# VERSION: 01.00.00
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
on:
issues:
types: [opened]
permissions:
contents: write
issues: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
create-branch:
name: Create feature branch
runs-on: ubuntu-latest
steps:
- name: Create branch and comment
run: |
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
ISSUE_NUM="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
# Build slug from title: lowercase, replace non-alnum with dash, trim
SLUG=$(echo "${ISSUE_TITLE}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//' | cut -c1-40)
BRANCH="feature/${ISSUE_NUM}-${SLUG}"
# Check dev branch exists
DEV_EXISTS=$(curl -sf -o /dev/null -w '%{http_code}' \
-H "Authorization: token ${TOKEN}" \
"${API}/branches/dev" 2>/dev/null || echo "000")
if [ "${DEV_EXISTS}" != "200" ]; then
echo "No dev branch -- skipping"
exit 0
fi
# Create branch from dev
HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API}/branches" \
-d "{\"new_branch_name\":\"${BRANCH}\",\"old_branch_name\":\"dev\"}" 2>/dev/null || echo "000")
if [ "${HTTP}" = "201" ]; then
echo "Created branch: ${BRANCH}"
# Comment on issue with branch link
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 \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues/${ISSUE_NUM}/comments" \
-d "{\"body\":\"${BODY}\"}" > /dev/null 2>&1
echo "Commented on issue #${ISSUE_NUM}"
else
echo "Failed to create branch (HTTP ${HTTP}) -- may already exist"
fi
+29 -11
View File
@@ -8,7 +8,7 @@
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/universal/pr-check.yml.template
# VERSION: 05.00.00
# BRIEF: PR gate -- branch policy + code validation before merge
# BRIEF: PR gate branch policy + code validation before merge
name: "Universal: PR Check"
@@ -24,7 +24,7 @@ env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
# Branch Policy
# ── Branch Policy ──────────────────────────────────────────────────────
branch-policy:
name: Branch Policy
runs-on: ubuntu-latest
@@ -34,7 +34,7 @@ jobs:
HEAD="${{ github.head_ref }}"
BASE="${{ github.base_ref }}"
echo "PR: ${HEAD} -> ${BASE}"
echo "PR: ${HEAD} ${BASE}"
ALLOWED=true
REASON=""
@@ -85,18 +85,18 @@ jobs:
echo "${REASON}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Allowed merge paths:" >> $GITHUB_STEP_SUMMARY
echo "- \`feature/*\` -> \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` -> \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`hotfix/*\` -> \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`dev\` -> \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc/*\` -> \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`feature/*\` \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`fix/*\` \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- \`hotfix/*\` \`dev\` or \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`dev\` \`main\`" >> $GITHUB_STEP_SUMMARY
echo "- \`rc/*\` \`main\`" >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "Branch policy: OK (${HEAD} -> ${BASE})"
echo "Branch policy: OK (${HEAD} ${BASE})"
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
# Code Validation
# ── Code Validation ────────────────────────────────────────────────────
validate:
name: Validate PR
runs-on: ubuntu-latest
@@ -162,7 +162,7 @@ jobs:
echo "Dolibarr module: ${MOD_FILE}"
;;
*)
echo "Generic platform -- no manifest validation"
echo "Generic platform no manifest validation"
;;
esac
@@ -194,3 +194,21 @@ 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; }
# ── Pre-Release RC Build ─────────────────────────────────────────────────
pre-release:
name: Build RC Package
runs-on: ubuntu-latest
needs: [branch-policy, validate]
steps:
- name: Trigger RC pre-release
env:
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: ${{ github.head_ref }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
curl -s -X POST "${GITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY
echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY
+98 -293
View File
@@ -5,14 +5,18 @@
# 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
# VERSION: 05.01.00
# BRIEF: Manual pre-release -- builds dev/alpha/beta/rc packages from any branch
name: "Universal: Pre-Release"
on:
pull_request:
types: [closed]
branches:
- dev
workflow_dispatch:
inputs:
stability:
@@ -35,41 +39,44 @@ env:
jobs:
build:
name: "Build Pre-Release (${{ inputs.stability }})"
name: "Build Pre-Release (${{ inputs.stability || 'development' }})"
runs-on: release
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'dev')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GA_TOKEN }}
token: ${{ secrets.MOKOGITEA_TOKEN }}
- name: Setup PHP
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
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
if ! command -v composer &> /dev/null; 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
# Always fetch latest CLI tools — never use stale cache from previous runs
rm -rf /tmp/moko-platform-api
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
/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"
- 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 '<extension' {} \; 2>/dev/null | head -1)
[ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" ! -path "*/packages/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
[ -z "$MANIFEST" ] && MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/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 ${MOKO_CLI}/manifest_read.php --path . --github-output
- name: Resolve metadata
- name: Resolve metadata and bump version
id: meta
run: |
STABILITY="${{ inputs.stability }}"
STABILITY="${{ inputs.stability || 'development' }}"
case "$STABILITY" in
development) SUFFIX="-dev"; TAG="development" ;;
@@ -78,109 +85,44 @@ 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"
# Read current version (bump already handled by push workflow)
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null)
[ -z "$VERSION" ] && VERSION="00.00.01"
MAJOR=$(echo "$CURRENT" | cut -d. -f1)
MINOR=$(echo "$CURRENT" | cut -d. -f2)
PATCH=$(echo "$CURRENT" | cut -d. -f3)
# Strip any existing suffix from version before applying stability
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
# 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))
php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch "${{ github.ref_name }}" --stability "$STABILITY" 2>/dev/null || true
if [ $NEW_PATCH -gt 99 ]; then
NEW_PATCH=0
NEW_MINOR=$((NEW_MINOR + 1))
# Verify version consistency across all files
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
# Update VERSION variable with suffix
if [ -n "$SUFFIX" ]; then
VERSION="${VERSION}${SUFFIX}"
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
# 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>\([^<]*\)<\/version>.*/\1/p' "$MANIFEST" | head -1)
sed -i "s|<version>${MANIFEST_VER}</version>|<version>${VERSION}</version>|" "$MANIFEST"
sed -i "s|<creationDate>[^<]*</creationDate>|<creationDate>${TODAY}</creationDate>|" "$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 '<extension' {} \; 2>/dev/null); do
SUB_VER=$(sed -n 's/.*<version>\([^<]*\)<\/version>.*/\1/p' "$SUB_MANIFEST" | head -1)
if [ -n "$SUB_VER" ]; then
sed -i "s|<version>${SUB_VER}</version>|<version>${VERSION}</version>|" "$SUB_MANIFEST"
sed -i "s|<creationDate>[^<]*</creationDate>|<creationDate>${TODAY}</creationDate>|" "$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
# Commit version bump
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 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): bump ${CURRENT} -> ${VERSION} [skip ci]"
git commit -m "chore(version): pre-release 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>\([^<]*\)<\/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
# Auto-detect element via manifest_element.php
php ${MOKO_CLI}/manifest_element.php \
--path . --version "$VERSION" --stability "$STABILITY" \
--repo "${GITEA_REPO}" --github-output
ZIP_NAME="${EXT_ELEMENT}-${VERSION}${SUFFIX}.zip"
# Read back element outputs
EXT_ELEMENT=$(grep '^ext_element=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)
ZIP_NAME=$(grep '^zip_name=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
[ -z "$ZIP_NAME" ] && ZIP_NAME="${EXT_ELEMENT}-${VERSION}.zip"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
@@ -188,183 +130,52 @@ 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/.*<extension[^>]*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 ..
SHA256=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1)
echo "sha256=${SHA256}" >> "$GITHUB_OUTPUT"
echo "ZIP: ${ZIP_NAME} (SHA: ${SHA256:0:16}...)"
- name: Create or replace Gitea release
- name: Create release
id: release
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 }}"
EXT_ELEMENT="${{ steps.meta.outputs.ext_element }}"
TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
BRANCH=$(git branch --show-current)
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_create.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --branch dev --prerelease
BODY="## ${VERSION} ($(date +%Y-%m-%d))
**Channel:** ${STABILITY}
**SHA-256:** \`${SHA256}\`"
# Delete existing release
EXISTING_ID=$(curl -sS -H "Authorization: token ${TOKEN}" \
"${API}/releases/tags/${TAG}" | jq -r '.id // empty' 2>/dev/null)
if [ -n "$EXISTING_ID" ]; then
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
"${API}/releases/${EXISTING_ID}" 2>/dev/null || true
curl -sS -X DELETE -H "Authorization: token ${TOKEN}" \
"${API}/tags/${TAG}" 2>/dev/null || true
fi
# Create release
RELEASE_ID=$(curl -sS -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API}/releases" \
-d "$(jq -n \
--arg tag "$TAG" \
--arg target "$BRANCH" \
--arg name "${EXT_ELEMENT} ${VERSION} (${STABILITY})" \
--arg body "$BODY" \
'{tag_name: $tag, target_commitish: $target, name: $name, body: $body, prerelease: true}'
)" | jq -r '.id')
echo "release_id=${RELEASE_ID}" >> "$GITHUB_OUTPUT"
# Upload ZIP
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}"
echo "Released: ${EXT_ELEMENT} ${VERSION} (${STABILITY})"
- name: Build package and upload
id: package
run: |
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_package.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --output /tmp || true
- name: Update updates.xml
if: steps.platform.outputs.platform == 'joomla'
run: |
STABILITY="${{ steps.meta.outputs.stability }}"
VERSION="${{ steps.meta.outputs.version }}"
SHA256="${{ steps.zip.outputs.sha256 }}"
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
TAG="${{ steps.meta.outputs.tag }}"
DATE=$(date +%Y-%m-%d)
STABILITY="${{ steps.meta.outputs.stability }}"
SHA256="${{ steps.package.outputs.sha256_zip }}"
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
SHA_FLAG=""
[ -n "$SHA256" ] && SHA_FLAG="--sha ${SHA256}"
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}"
php ${MOKO_CLI}/updates_xml_build.php \
--path . --version "${VERSION}" --stability "${STABILITY}" \
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
${SHA_FLAG}
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"(<update>(?:(?!</update>).)*?<tag>" + re.escape(xml_tag) + r"</tag>.*?</update>)"
match = re.search(pattern, content, re.DOTALL)
if match:
block = match.group(1)
updated = re.sub(r"<version>[^<]*</version>", f"<version>{version}</version>", block)
updated = re.sub(r"<creationDate>[^<]*</creationDate>", f"<creationDate>{date}</creationDate>", updated)
if "<sha256>" in updated:
updated = re.sub(r"<sha256>[^<]*</sha256>", f"<sha256>{sha256}</sha256>", updated)
else:
updated = updated.replace("</downloads>", f"</downloads>\n <sha256>{sha256}</sha256>")
updated = re.sub(r"(<downloadurl[^>]*>)[^<]*(</downloadurl>)", 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 <tag>{xml_tag}</tag> block in updates.xml")
with open("updates.xml", "w") as f:
f.write(content)
PYEOF
# Commit and push to current branch
# Commit and push
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]"
@@ -380,13 +191,11 @@ jobs:
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 "origin/${BRANCH}" -- updates.xml 2>/dev/null || continue
git checkout "${CURRENT_BRANCH}" -- updates.xml
if ! git diff --quiet updates.xml 2>/dev/null; then
git add updates.xml
@@ -400,29 +209,25 @@ jobs:
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.GA_TOKEN }}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
php ${MOKO_CLI}/release_cascade.php \
--stability "${{ steps.meta.outputs.stability }}" \
--token "${TOKEN}" \
--api-base "${API_BASE}"
- name: Summary
if: always()
run: |
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
# Cascade: rc -> beta,alpha,dev | beta -> alpha,dev | alpha -> dev | dev -> nothing
case "$STABILITY" in
release-candidate) TAGS_TO_DELETE="beta alpha development" ;;
beta) TAGS_TO_DELETE="alpha development" ;;
alpha) TAGS_TO_DELETE="development" ;;
*) TAGS_TO_DELETE="" ;;
esac
[ -z "$TAGS_TO_DELETE" ] && exit 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})"
fi
done
ZIP_NAME="${{ steps.meta.outputs.zip_name }}"
SHA256="${{ steps.package.outputs.sha256_zip }}"
echo "## Pre-Release Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
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
+5 -77
View File
@@ -49,22 +49,18 @@ env:
SCRIPTS_ALLOWED_DIRS: scripts,scripts/fix,scripts/lib,scripts/release,scripts/run,scripts/validate
# Repo health policy
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,.gitea/workflows/
REPO_OPTIONAL_FILES: SECURITY.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.mokogitea/workflows/
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
REPO_DISALLOWED_DIRS:
REPO_DISALLOWED_FILES: TODO.md,todo.md
# Wiki-preferred documentation -- wiki is full credit, repo file is advisory
# Format: filename:WikiPageName (Gitea wiki page slug)
WIKI_PREFERRED_DOCS: CONTRIBUTING.md:Contributing,CODE_OF_CONDUCT.md:Code-of-Conduct,GOVERNANCE.md:Governance
# Extended checks toggles
EXTENDED_CHECKS: "true"
# File / directory variables
DOCS_INDEX: docs/docs-index.md
SCRIPT_DIR: scripts
WORKFLOWS_DIR: .gitea/workflows
WORKFLOWS_DIR: .mokogitea/workflows
SHELLCHECK_PATTERN: '*.sh'
SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml'
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
@@ -85,7 +81,7 @@ jobs:
- name: Check actor permission (admin only)
id: perm
env:
TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }}
REPO: ${{ github.repository }}
ACTOR: ${{ github.actor }}
run: |
@@ -94,7 +90,7 @@ jobs:
PERMISSION=unknown
METHOD=""
# Hardcoded authorized users -- always allowed
# Hardcoded authorized users always allowed
case "$ACTOR" in
jmiller|gitea-actions[bot])
ALLOWED=true
@@ -369,10 +365,6 @@ jobs:
- name: Repository health checks
env:
PROFILE_RAW: ${{ github.event.inputs.profile }}
GA_TOKEN: ${{ secrets.GA_TOKEN }}
GITHUB_TOKEN: ${{ github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_SERVER_URL: ${{ github.server_url }}
run: |
set -euo pipefail
@@ -530,63 +522,6 @@ jobs:
} >> "${GITHUB_STEP_SUMMARY}"
fi
# -- Wiki-preferred documentation checks --
# Docs that belong in the wiki; repo-file fallback is accepted but advisory
wiki_findings=()
wiki_ok=()
wiki_file_fallback=()
wiki_missing=()
API_BASE="${GITHUB_SERVER_URL:-https://git.mokoconsulting.tech}"
WIKI_TOKEN="${WIKI_TOKEN:-${GA_TOKEN:-${GITHUB_TOKEN}}}"
REPO_FULL="${GITHUB_REPOSITORY}"
IFS=',' read -r -a wiki_docs <<< "${WIKI_PREFERRED_DOCS}"
for entry in "${wiki_docs[@]}"; do
file="${entry%%:*}"
page="${entry##*:}"
# Check wiki via Gitea API
wiki_exists=false
http_code=$(curl -sf -o /dev/null -w '%{http_code}' \
-H "Authorization: token ${WIKI_TOKEN}" \
"${API_BASE}/api/v1/repos/${REPO_FULL}/wiki/page/${page}" 2>/dev/null || echo "000")
[ "${http_code}" = "200" ] && wiki_exists=true
# Check repo file
file_exists=false
[ -f "${file}" ] && file_exists=true
if [ "${wiki_exists}" = true ]; then
wiki_ok+=("${file} -> wiki/${page}")
elif [ "${file_exists}" = true ]; then
wiki_file_fallback+=("${file}")
content_warnings+=("${file} found in repo root (preferred location: wiki/${page})")
else
wiki_missing+=("${file} (wiki/${page})")
missing_optional+=("${file} (not in wiki or repo)")
fi
done
{
printf '%s\n' '### Wiki-preferred documentation'
printf '%s\n' '| Document | Location | Status |'
printf '%s\n' '|---|---|---|'
for item in "${wiki_ok[@]:-}"; do
[ -z "${item}" ] && continue
printf '%s\n' "| ${item%%->*}| Wiki | OK |"
done
for item in "${wiki_file_fallback[@]:-}"; do
[ -z "${item}" ] && continue
printf '%s\n' "| ${item} | Repo file | Advisory -- migrate to wiki |"
done
for item in "${wiki_missing[@]:-}"; do
[ -z "${item}" ] && continue
printf '%s\n' "| ${item%%(*}| Missing | Warning |"
done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
# -- Joomla-specific checks --
joomla_findings=()
@@ -772,13 +707,6 @@ jobs:
printf '%s\n' '| Release variables | OK | Repository variables validation |'
printf '%s\n' '| Scripts governance | OK | Directory policy and advisory reporting |'
printf '%s\n' '| Repo required artifacts | OK | Required, optional, disallowed enforcement |'
if [ "${#wiki_file_fallback[@]}" -gt 0 ]; then
printf '%s\n' "| Wiki-preferred docs | Advisory | ${#wiki_file_fallback[@]} doc(s) in repo, prefer wiki |"
elif [ "${#wiki_missing[@]}" -gt 0 ]; then
printf '%s\n' "| Wiki-preferred docs | Warning | ${#wiki_missing[@]} doc(s) missing from wiki and repo |"
else
printf '%s\n' '| Wiki-preferred docs | OK | All docs found in wiki |'
fi
printf '%s\n' '| Repo content heuristics | OK | Brand, license, changelog structure |'
if [ "${extended_enabled}" = 'true' ]; then
if [ "${#extended_findings[@]}" -gt 0 ]; then
+312
View File
@@ -0,0 +1,312 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /templates/workflows/update-server.yml
# VERSION: 05.00.00
# BRIEF: Pre-release build + update server XML for dev/alpha/beta/rc branches
#
# Thin wrapper around moko-platform CLI tools.
# Builds packages, updates updates.xml, and optionally deploys via SFTP.
#
# Joomla filters update entries by the user's "Minimum Stability" setting.
name: "Update Server"
on:
push:
branches:
- 'dev'
- 'dev/**'
- 'alpha/**'
- 'beta/**'
- 'rc/**'
paths:
- 'src/**'
- 'htdocs/**'
pull_request:
types: [closed]
branches:
- 'dev'
- 'dev/**'
- 'alpha/**'
- 'beta/**'
- 'rc/**'
paths:
- 'src/**'
- 'htdocs/**'
workflow_dispatch:
inputs:
stability:
description: 'Stability tag'
required: true
default: 'development'
type: choice
options:
- development
- alpha
- beta
- rc
- stable
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:
update-xml:
name: Update Server
runs-on: release
if: >-
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' || github.event_name == 'push'
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 0
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
COMPOSER_AUTH: '{"http-basic":{"git.mokoconsulting.tech":{"username":"token","password":"${{ secrets.MOKOGITEA_TOKEN }}"}}}'
run: |
if ! command -v composer &> /dev/null; 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
# Always fetch latest CLI tools — never use stale cache from previous runs
rm -rf /tmp/moko-platform
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
/tmp/moko-platform 2>/dev/null || true
if [ -d "/tmp/moko-platform" ] && [ -f "/tmp/moko-platform/composer.json" ]; then
cd /tmp/moko-platform && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
fi
echo "MOKO_CLI=/tmp/moko-platform/cli" >> "$GITHUB_ENV"
- name: Detect platform
id: platform
run: php ${MOKO_CLI}/manifest_read.php --path . --github-output
- name: Resolve stability and bump version
id: meta
run: |
BRANCH="${{ github.ref_name }}"
# Configure git for bot pushes
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"
# Auto-bump patch version
php ${MOKO_CLI}/version_bump.php --path . 2>/dev/null || true
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "0.0.0")
# Strip any existing suffix before applying stability
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
# Determine stability from branch or manual input
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
STABILITY="${{ inputs.stability }}"
elif [[ "$BRANCH" == rc/* ]]; then
STABILITY="rc"
elif [[ "$BRANCH" == beta/* ]]; then
STABILITY="beta"
elif [[ "$BRANCH" == alpha/* ]]; then
STABILITY="alpha"
else
STABILITY="development"
fi
# Version suffix per stability stream
case "$STABILITY" in
development) SUFFIX="-dev"; TAG="development" ;;
alpha) SUFFIX="-alpha"; TAG="alpha" ;;
beta) SUFFIX="-beta"; TAG="beta" ;;
rc) SUFFIX="-rc"; TAG="release-candidate" ;;
*) SUFFIX=""; TAG="stable" ;;
esac
# Propagate version with stability suffix to all manifest files
php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch "$BRANCH" --stability "$STABILITY" 2>/dev/null || true
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
# Re-read version (now includes suffix from version_set_platform)
if [ -n "$SUFFIX" ]; then
VERSION="${VERSION}${SUFFIX}"
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "display_version=${VERSION}" >> "$GITHUB_OUTPUT"
# Commit version bump if changed
git add -A
git diff --cached --quiet || {
git commit -m "chore(version): auto-bump ${VERSION} [skip ci]" \
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
git push
}
- name: Create release and upload package
id: package
run: |
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# Create or update Gitea release
php ${MOKO_CLI}/release_create.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease
# Build package and upload
php ${MOKO_CLI}/release_package.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --output /tmp || true
- name: Update updates.xml
if: steps.platform.outputs.platform == 'joomla'
run: |
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
SHA256="${{ steps.package.outputs.sha256_zip }}"
if [ ! -f "updates.xml" ]; then
echo "No updates.xml — skipping"
exit 0
fi
SHA_FLAG=""
[ -n "$SHA256" ] && SHA_FLAG="--sha ${SHA256}"
php ${MOKO_CLI}/updates_xml_build.php \
--path . --version "${VERSION}" --stability "${STABILITY}" \
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
${SHA_FLAG}
# Commit and push updates.xml
git add updates.xml
git diff --cached --quiet || {
git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]"
git push
}
- name: Sync updates.xml to main
if: github.ref_name != 'main' && steps.platform.outputs.platform == 'joomla'
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
GITEA_TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
FILE_SHA=$(curl -sf -H "Authorization: token ${GITEA_TOKEN}" \
"${API_BASE}/contents/updates.xml?ref=main" | python3 -c "import sys,json; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true)
if [ -n "$FILE_SHA" ] && [ -f "updates.xml" ]; then
python3 -c "
import base64, json, urllib.request, sys
with open('updates.xml', 'rb') as f:
content = base64.b64encode(f.read()).decode()
payload = json.dumps({
'content': content,
'sha': '${FILE_SHA}',
'message': 'chore: sync updates.xml from ${{ steps.meta.outputs.stability }} [skip ci]',
'branch': 'main'
}).encode()
req = urllib.request.Request(
'${API_BASE}/contents/updates.xml',
data=payload, method='PUT',
headers={
'Authorization': 'token ${GITEA_TOKEN}',
'Content-Type': 'application/json'
})
try:
urllib.request.urlopen(req)
print('updates.xml synced to main')
except Exception as e:
print(f'WARNING: sync to main failed: {e}', file=sys.stderr)
"
fi
- name: SFTP deploy to dev server
if: contains(github.ref, 'dev/') || github.ref == 'refs/heads/dev'
env:
DEV_HOST: ${{ vars.DEV_FTP_HOST }}
DEV_PATH: ${{ vars.DEV_FTP_PATH }}
DEV_SUFFIX: ${{ vars.DEV_FTP_SUFFIX }}
DEV_USER: ${{ vars.DEV_FTP_USERNAME }}
DEV_PORT: ${{ vars.DEV_FTP_PORT }}
DEV_KEY: ${{ secrets.DEV_FTP_KEY }}
DEV_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
run: |
# Permission check: admin or maintain role required
ACTOR="${{ github.actor }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
"${API_BASE}/collaborators/${ACTOR}/permission" 2>/dev/null | \
python3 -c "import sys,json; print(json.load(sys.stdin).get('permission','read'))" 2>/dev/null || echo "read")
case "$PERMISSION" in
admin|maintain|write) ;;
*)
echo "Deploy denied: ${ACTOR} has '${PERMISSION}' — requires admin, maintain, or write"
exit 0
;;
esac
[ -z "$DEV_HOST" ] || [ -z "$DEV_PATH" ] && { echo "DEV FTP not configured — skipping SFTP"; exit 0; }
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
[ ! -d "$SOURCE_DIR" ] && exit 0
PORT="${DEV_PORT:-22}"
REMOTE="${DEV_PATH%/}"
[ -n "$DEV_SUFFIX" ] && REMOTE="${REMOTE}/${DEV_SUFFIX#/}"
printf '{"host":"%s","port":%s,"username":"%s","remotePath":"%s"' \
"$DEV_HOST" "$PORT" "$DEV_USER" "$REMOTE" > /tmp/sftp-config.json
if [ -n "$DEV_KEY" ]; then
echo "$DEV_KEY" > /tmp/deploy_key && chmod 600 /tmp/deploy_key
printf ',"privateKeyPath":"/tmp/deploy_key"}' >> /tmp/sftp-config.json
else
printf ',"password":"%s"}' "$DEV_PASS" >> /tmp/sftp-config.json
fi
PLATFORM=$(php ${MOKO_CLI}/platform_detect.php --path . 2>/dev/null || true)
if [ "$PLATFORM" = "waas-component" ] && [ -f "${MOKO_CLI}/../deploy/deploy-joomla.php" ]; then
php ${MOKO_CLI}/../deploy/deploy-joomla.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
elif [ -f "${MOKO_CLI}/../deploy/deploy-sftp.php" ]; then
php ${MOKO_CLI}/../deploy/deploy-sftp.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
fi
rm -f /tmp/deploy_key /tmp/sftp-config.json
echo "SFTP deploy to dev complete" >> $GITHUB_STEP_SUMMARY
- name: Summary
if: always()
run: |
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
DISPLAY="${{ steps.meta.outputs.display_version }}"
echo "## Update Server" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Stability | \`${STABILITY}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${DISPLAY}\` |" >> $GITHUB_STEP_SUMMARY
+33 -662
View File
@@ -13,676 +13,47 @@
-->
# Changelog — MokoOnyx (VERSION: 03.09.03)
## [Unreleased]
## [02.08.00] --- 2026-05-29
## [02.08.00] --- 2026-05-29
## [02.08.00] --- 2026-05-29
## [02.08.00] --- 2026-05-28
All notable changes to the MokoOnyx Joomla template are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [02.08.01] --- 2026-05-28
### Changed
- Migrated all workflow and template paths from `.github/` to `.mokogitea/`
- Template source paths updated: `templates/gitea/` to `templates/mokogitea/`
- HCL definition files removed -- Template repos are now the canonical source
### Added
- `branch-cleanup.yml`: auto-delete merged feature branches after PR merge
### Removed
- Removed deploy-manual.yml workflow switching to Joomla update server method for extension distribution
- Removed deploy-manual.yml workflow -- switching to Joomla update server method for extension distribution
- Removed deploy variables and secrets (DEV_FTP_*)
- **Theme preview removed** -- Removed unused language strings for theme preview feature (never wired into config)
- **Repo cleanup** -- Removed 38 unused files: Fredoka/Pacifico fonts, dead npm tooling (package.json, scripts/), tmp-overrides/, placeholder tests, orphaned workflow copies, stale READMEs
- **Broken font options removed** -- Removed Noto Sans and Fira Sans from font selector (CSS files never existed)
- **Docs moved to wiki** -- CONTRIBUTING.md, CODE_OF_CONDUCT.md, GOVERNANCE.md migrated to Gitea wiki
### Changed
- **repo-health.yml** -- Wiki-preferred documentation checks via Gitea API (wiki = full credit, repo file = advisory)
- **auto-release.yml Step 8b** -- Replaced inline Python with release_body_update.php CLI tool (fixes SIGPIPE exit 141)
- **pre-release.yml rewritten** -- Uses moko-platform CLI tools, PHP instead of Python, fixed broken platform detection
- **All workflow YAML files** -- Stripped non-ASCII characters (em dashes, arrows, emoji) for Gitea YAML parser compatibility
### Fixed
- **Menu icon padding removed** Removed hardcoded `p-2` class from all mod_menu icon spans (horizontal + mainmenu layouts); icons now inherit spacing from the parent link
## [02.06.00] - 2026-05-16
### Added
- **Community Builder plugin type** — Auto-release detects `<cbplugin>` manifests and uses `cb_` prefix
- **Platform auto-sense** — Workflow detects Joomla/Dolibarr/generic from file structure without manifest
- **Font Awesome + Bootstrap in component view** — Print/modal view now loads FA7 and Bootstrap 5
### Changed
- **Release workflow dispatch-only removed** — Auto-release triggers on PR merge to main (src/htdocs paths) + manual dispatch
- **Version bump protocol** — Releases use version as-is from main; dev bumped to next minor after release (Step 11)
- **GitHub mirror removed** — Gitea is the sole release platform
- **update-server.yml removed** — Merged into auto-release (stable) and pre-release (dev/rc) workflows
- **`.mokogitea/manifest.xml` precedence** — Platform detection reads .mokogitea first, falls back to .gitea
### Fixed
- **CSS variable fallbacks** — 341 `var()` calls now have explicit light theme fallback values
- **Dropdown menu background** — Uses `--nav-bg-color` instead of `--body-bg`
## [02.02.00] - 2026-05-16
### Fixed
- **template.css fallback values** — All var() fallbacks aligned with light.standard.css values
- **background-color mismatches** — Fixed 20+ properties incorrectly using `--body-color` as background
## [02.01.06] - 2026-05-16
### Added
- **Article metadata footer** — Renders Joomla custom fields (`jcfields`) as a styled metadata footer on article layouts, grouped by field group with responsive grid and BEM styling
- **Smart Visitor Detection** — Pushes anonymised visitor properties (login status, user group, page type) to the dataLayer for Google Analytics / Tag Manager. Sets GA4 `user_properties` for persistent session-scoped dimensions. No PII is sent. Default enabled when GTM or GA4 is active.
- **Auto-cascade workflow** — Forward-merges `main``dev` after every push; auto-creates a PR on conflict
- **Component/print-view stylesheet** — Dedicated `component.css` replaces `template.css` in the component view with print-optimised styles using theme variables
- **Print-view GA4 tracking** — Component view sends `content_group=print_view` to Google Analytics for tracking print/modal usage
- **Custom light theme in component view** — Component view now loads `light.custom.css` when configured
- **Auto-minification** — `user.css`, `user.js`, and custom theme files are automatically minified on page load via `MokoMinifyHelper`
- **Media folder cleanup on install/update** — `script.php` now removes stale `.min` files, deprecated assets, and unminified vendor files during install or update
- **Changelog auto-bump in auto-release** — `[Unreleased]` is automatically promoted to the release version on stable release, with a fresh `[Unreleased]` section inserted above
- **CI: PHPStan static analysis** — Added to CI pipeline
- **CI: Gitleaks secret scanning** — Added to CI pipeline
- **CI: CSS sync workflow** — Syncs CSS to template repo and checks client variable coverage
### Changed
- **Custom head params replaced with user files** — Removed `custom_head_start` / `custom_head_end` template params in favour of `user.css` and `user.js` (loaded via Web Asset Manager)
- **User override files added to .gitignore** — `user.css` and `user.js` are client-repo only; not committed to the template repo
- **Asset registry simplified** — Removed duplicate `.min` entries from `joomla.asset.json`; Joomla's Web Asset Manager auto-resolves `.min` variants when debug is off
- **Font Awesome vendor ships minified only** — Removed unminified FA7 Free CSS (saves ~21 kLOC); asset entries now point to `.min.css` directly
- **Workflows restructured — CI/CD workflows and issue templates reorganized under `.gitea/` with template sync
### Removed
- **Migration tab** — Removed MokoCassiopeia migration fieldset and associated language strings from template params
- **Migration description** — Removed migration callout and "formerly MokoCassiopeia" reference from template description
- **Custom head fields** — Removed `custom_head_start` / `custom_head_end` fields and `Custom Code` fieldset from template configuration
- **Footer from component view** — Removed footer module positions from `component.php` (print/modal view)
- **Unminified vendor CSS** — Removed `all.css`, `brands.css`, `fontawesome.css`, `regular.css`, `solid.css` from FA7 Free (21k+ lines)
## [03.10.00] - 2026-04-18
### Important
- **Template Consolidation** — This release finalised the MokoOnyx identity, adding automatic migration from legacy MokoCassiopeia installations. Settings, menu assignments, and files are imported on first page load.
### Added
- **Offline page redesign** — Full-viewport background from Joomla offline_image or header background, glass card overlay, centered logo with glow, login accordion, copyright footer
- **CSS variable click-to-copy** — Text containing `--variable-name` patterns is wrapped in clickable chips that copy to clipboard with toast notification
- **Brand-aside 3-column layout** — Flex columns like top-a with card style
- **mod_stats table layout** — Converted from definition list to semantic table
- **Favicon multi-format support** — Now handles PNG, JPEG, GIF, WebP, BMP (not just PNG)
- **Theme variables** — `--theme-fab-bg`, `--theme-fab-color`, `--theme-fab-btn-bg`, `--theme-fab-border`, `--offline-card-bg`
- **Footer CSS variables** — Added to CSS Variables reference tab
- **Bridge migration script** — `helper/bridge.php` handles automatic MokoCassiopeia → MokoOnyx migration
- **Dedicated release runner** — Release workflows run on isolated `release` label runner
- **Runner fleet** — 3 CI + 1 release runner (12 concurrent jobs)
### Changed
- **Gitea-primary CI/CD** — All workflows use Gitea API, GitHub is backup for stable/RC only
- **Theme switcher** — Larger, bordered, theme-aware colors (off-white on dark, primary on light)
- **Auto switch** — Red when off, green when on
- **A11y toolbar** — Theme-aware colors for dark mode visibility
- **Search button border** — Matches input border (`--input-border-color`)
- **Offline message** — 0=hidden, 1=custom message, 2=system language string
- **Light theme fonts** — Fixed trailing `)` syntax error, normalized quote style to match dark
- **`--accent-color-secondary`** — Unified to `#6fb3ff` across both themes
- **`--alert-color`** — Set to `#000` in light theme
### Removed
- Brand showcase tab (redundant with theme preview)
- Position selectors for a11y/theme FAB (forced to bottom-right)
- Custom theme CSS from git tracking (site-specific, gitignored)
### Fixed
- SHA-256 checksum format — Removed `sha256:` prefix (Joomla expects raw hex)
- Favicon path resolution — Strips `#joomlaImage://` fragment, tries multiple path candidates
- `REQUIRE_SIGNIN_VIEW` — Set to `false` for public release downloads
- Release workflow — Uses Gitea API to update `updates.xml` on main (bypasses branch protection)
- Language loading on offline page — `com_users` and core language files loaded explicitly
---
## [03.09.03] - 2026-04-02
### Added
- **Favicon configuration** — New "Favicon" tab in template config; upload a PNG and all favicon sizes are auto-generated via PHP GD (ICO, Apple Touch Icon 180px, Android Chrome 192/512px, site.webmanifest)
- **Module overrides** — 11 new `default.php` layout overrides for Joomla core modules: `mod_custom`, `mod_articles_latest`, `mod_articles_popular`, `mod_articles_news`, `mod_articles_category`, `mod_breadcrumbs`, `mod_footer`, `mod_login`, `mod_finder`, `mod_tags_popular`, `mod_tags_similar`, `mod_related_items`
- **Module title support** — All module overrides respect `$module->showtitle`, `header_tag`, `header_class`, and `moduleclass_sfx` parameters
- **Module CSS** — BEM-scoped styles for module titles, article lists, tag badges, search forms, login forms, breadcrumbs, and footer content
- **Hero card variables** — Full variable-driven hero system: `--hero-card-bg`, `--hero-card-color`, `--hero-card-overlay`, `--hero-card-border-radius`, `--hero-card-padding-x/y`, `--hero-card-max-width`, plus `--hero-alt-card-*` for secondary variant
- **Hero mobile breakpoint** — Photo background hidden on mobile (≤767.98px), hero card becomes full-bleed (100dvh, no border-radius)
- **CSS fallback values** — 1365 `var()` calls in template.css now include inline fallback values
- **Card border-radius** — `.card` now has `.25rem` fallback on `var(--card-border-radius)`
### Changed
- **Button backgrounds** — `--btn-bg: transparent` changed to `var(--body-bg)` in dark and light themes
- **Offcanvas close button** — `.offcanvas-header .btn-close` now gets `background-color` from `--offcanvas-bg`
- **Custom template sync** — Both `dark.custom.css` and `light.custom.css` now contain all variables from their standard counterparts (was missing 223 variables)
- **Overlay layer** — Added `--hero-overlay-bg-position` and `--hero-overlay-bg-size` variables
- **Legacy CSS cleanup** — Removed vendor prefixes (`-webkit-box`, `-ms-flexbox`) from `.overlay` rules, replaced with modern flexbox
### Removed
- **FILE INFORMATION headers** — Stripped DEFGROUP/INGROUP/PATH/VERSION/BRIEF metadata from all PHP, CSS, JS, INI, and HTML files (kept in XML and README per policy)
- **Mobile overrides** — Deleted 26 `mobile.php` layout files and their empty parent directories
- **Joomla-specific gitignore entries** — Removed ~700 lines of Joomla CMS core paths from `.gitignore` (not applicable to a template repository)
### Fixed
- **CI: composer install** — Workflow `standards-compliance.yml` now conditionally runs `composer install` only when `composer.json` exists
- **CI: YAML syntax** — Fixed invalid YAML in `auto-update-sha.yml` caused by multiline commit message in run block
---
## [03.09.02] - 2026-03-26
### Added - Hero Variant System & Block Color System
#### Hero Variants
- **`.hero#primary`** and **`.hero#secondary`** CSS variant system for visually distinct hero treatments
- Shared `.hero` base class with `background-size: cover`, `border-radius: .5rem`, and `overflow: hidden`
- Six new CSS variables (`--hero-primary-bg-color`, `--hero-primary-overlay`, `--hero-primary-color`, and secondary equivalents)
- Light and dark mode defaults in custom palette templates
#### Block Color System
- Automatic `:nth-child()` slot palette for `top-a`, `top-b`, `bottom-a`, `bottom-b` module positions
- Four color slots (`--block-color-1` through `--block-color-4`) with matching text variables
- Named per-module overrides: `#block-highlight`, `#block-cta`, `#block-alert`
- ID specificity wins over `:nth-child()` — no `!important` needed
#### Files Modified
- `src/media/css/template.css` — hero variant rules, block color `:nth-child()` rules, named override rules
- `src/media/css/theme/light.standard.css` — hero and block color variables (light standard)
- `src/media/css/theme/dark.standard.css` — hero and block color variables (dark standard)
- `src/templates/light.custom.css` — hero and block color variables (light custom starter)
- `src/templates/dark.custom.css` — hero and block color variables (dark custom starter)
- `src/templateDetails.xml` — Theme Preview tab, hero/block note fields, scriptfile registration, version bump to 03.09.02
- `src/language/en-GB/tpl_mokoonyx.ini` — language strings for new admin fields (British English)
- `src/language/en-US/tpl_mokoonyx.ini` — language strings for new admin fields (American English)
- `docs/CSS_VARIABLES.md` — full variable reference for both systems, sync script documentation
- `CHANGELOG.md` — this entry
#### Files Added
- `src/templates/theme-test.html` — Bootstrap-style test page with branded showcase, CSS variable swatches, hero demos, block color demos, and color test image
- `src/script.php` — Joomla install/update lifecycle script (runs CSS variable sync on upgrade, checks PHP/Joomla minimum versions)
- `src/sync_custom_vars.php` — CLI/library utility that detects missing CSS variables in user custom palettes and injects them
- `src/templates/brand-showcase.html` — Interactive color system gradients with hover pixel sampler, Bootstrap component showcase
#### Variable Audit
- All 20 hero/block variables confirmed present in all 4 theme files (light/dark standard + custom)
- No duplicate variable declarations found across any theme file
- `--gutter-x` references in template.css are self-scoped to grid containers (standard Bootstrap 5 behavior, not a `:root` variable)
---
## [03.08.03] - 2026-02-27
### Added - Main Menu Collapsible Dropdown Override
**New feature**: Added responsive "Main Menu" mod_menu override with Bootstrap 5 collapsible dropdown functionality.
#### What's New
- **Main Menu module override** with full Bootstrap 5 responsive navbar
- Collapsible hamburger menu for mobile devices
- Multi-level dropdown support with hover on desktop, tap on mobile
- WCAG 2.1 compliant touch targets (48px on mobile, 44px on desktop)
- BEM naming convention: `.mod-menu-main__*`
- **Appears as "Mainmenu" layout option** in Joomla admin module settings
#### Files Added
- `src/templates/html/mod_menu/mainmenu.php` - Main layout with Bootstrap navbar
- `src/templates/html/mod_menu/mainmenu_component.php` - Component menu items
- `src/templates/html/mod_menu/mainmenu_heading.php` - Heading menu items
- `src/templates/html/mod_menu/mainmenu_separator.php` - Separator menu items
- `src/templates/html/mod_menu/mainmenu_url.php` - URL menu items
- `src/templates/html/mod_menu/index.html` - Security file
#### Features
- **Bootstrap 5 Navbar**: Uses Bootstrap's native navbar-nav structure
- **Collapsible on Mobile**: Hamburger menu with smooth collapse animation
- **Dropdown Menus**: Multi-level dropdown support with caret indicators
- **Responsive Breakpoints**: Mobile-first design adapting at 768px and 992px
- **Touch-Friendly**: 48px minimum touch targets on mobile
- **Accessible**: ARIA labels and keyboard navigation support
- **Active States**: Visual indicators for current and active menu items
- **Alternative Layout**: Named `mainmenu.php` (not `default.php`) to appear as selectable layout option in Joomla admin
#### CSS Architecture
- 200+ lines of responsive CSS in template.css
- BEM naming: `.mod-menu-main`, `.mod-menu-main__list`, `.mod-menu-main__link`
- CSS variables integration for colors and borders
- Hover effects on desktop, tap effects on mobile
- Smooth transitions and animations
#### Module Count Update
- **Before**: 16 module overrides
- **After**: 17 module overrides (added mod_menu "Main Menu")
- **Component overrides**: Still 7 (unchanged)
### Removed - mod_search Override
**Cassiopeia approach**: Removed mod_search override to align with Cassiopeia template philosophy of not overriding standard Joomla modules.
#### Reason for Removal
- mod_search is a standard Joomla core module
- Following Cassiopeia template approach: use core layouts for standard modules
- Prevents potential language loading issues
- Ensures compatibility with future Joomla updates
- Core mod_search already includes responsive design and accessibility features
#### Files Removed
- `src/templates/html/mod_search/default.php` - Custom search module layout
- `src/templates/html/mod_search/index.html` - Security file
#### Module Count Update (After Removal)
- **Before**: 17 module overrides
- **After**: 16 module overrides (removed mod_search)
- **Component overrides**: Still 7 (unchanged)
### Removed - Documentation Cleanup
**Documentation policy**: Removed all markdown files from `src/templates/html/` directory. All documentation belongs in `docs/` folder only.
#### Files Removed (9 markdown files)
- `src/templates/html/STANDARD_MODULES_README.md`
- `src/templates/html/INDUSTRY_MODULES_README.md`
- `src/templates/html/VIRTUEMART_MODULES_README.md`
- `src/templates/html/mod_virtuemart_cart/README.md`
- `src/templates/html/mod_virtuemart_category/README.md`
- `src/templates/html/mod_virtuemart_currencies/README.md`
- `src/templates/html/mod_virtuemart_manufacturer/README.md`
- `src/templates/html/mod_virtuemart_product/README.md`
- `src/templates/html/mod_search/README.md`
**Note**: All module override documentation is consolidated in `docs/MODULE_OVERRIDES.md`. The `src/templates/html/` directory now contains only PHP override files and `index.html` security files.
**Note**: Unlike the previously removed mod_menu override (v03.08.01), this new "Main Menu" override is properly structured based on Joomla core layouts and Bootstrap 5, ensuring language strings load correctly and menu functionality works as expected. The layout is named `mainmenu.php` (not `default.php`) to appear as an alternative layout option "Mainmenu" in the Joomla admin module dropdown selector, preserving Joomla's core default menu layout.
## [03.08.02] - 2026-02-27
### Removed - Fix Language Loading in All Module Overrides
**Critical fix**: Removed standard Joomla module overrides to fix language string loading issues. Following Cassiopeia template approach.
#### Problem
- Default language strings not loading in module overrides (mod_breadcrumbs, mod_login, mod_articles_latest)
- Language constants displayed instead of translated text (e.g., "MOD_LOGIN_VALUE_USERNAME" instead of "Username")
- Custom overrides interfered with Joomla's module initialization and language loading process
#### Solution - Cassiopeia Approach
- **Removed** standard Joomla module overrides:
- `src/templates/html/mod_breadcrumbs/` (2 files)
- `src/templates/html/mod_login/` (2 files)
- `src/templates/html/mod_articles_latest/` (2 files)
- Template now uses Joomla's core module layouts for standard modules
- Language files load automatically via Joomla's module system
- Custom styling can still be applied via CSS using module-specific classes
- **Retained** third-party extension overrides where they add mobile-responsive value:
- VirtueMart modules (5): mod_virtuemart_cart, _category, _currencies, _manufacturer, _product
- Community Builder modules (2): mod_cblogin, mod_comprofilerOnline
- Other extensions (9): mod_acymailing, mod_hikashop_cart, mod_k2_content, mod_kunena*, mod_osmembership, mod_search
#### Cassiopeia Template Philosophy
- Cassiopeia (Joomla's default template) does NOT override standard module layouts
- It relies on core Joomla module files and applies styling via CSS
- Overrides are only created when structural changes are absolutely necessary
- This ensures compatibility, automatic language loading, and easier maintenance
#### Module Count Update
- **Before**: 19 module overrides
- **After**: 16 module overrides
- **Removed**: 3 standard Joomla modules (breadcrumbs, login, articles_latest)
- **Component overrides**: Still 7 (unchanged)
#### Files Removed
- `src/templates/html/mod_breadcrumbs/default.php`
- `src/templates/html/mod_breadcrumbs/index.html`
- `src/templates/html/mod_login/default.php`
- `src/templates/html/mod_login/index.html`
- `src/templates/html/mod_articles_latest/default.php`
- `src/templates/html/mod_articles_latest/index.html`
**Note**: This follows Joomla best practices by using core layouts for standard modules. Styling is handled via CSS. Third-party extension overrides remain for mobile responsiveness.
## [03.08.01] - 2026-02-27
### Removed - Fix Breaking Overrides
**Critical fix**: Removed mod_menu override that was causing menu links to break and language strings not to load.
#### Problem
- mod_menu override files (default.php, default_component.php, default_url.php) were attempting to load menu-specific layouts that don't exist in the template
- This broke Joomla's core menu rendering system
- Menu links were not functional
- Language strings were not loading properly in menus
#### Solution
- **Removed** entire `src/templates/html/mod_menu/` directory (4 files)
- Template now uses Joomla's default menu rendering
- Custom styling can still be applied via CSS using `.mod-menu` class
- All menu functionality restored to standard Joomla behavior
#### Documentation Updates
- Updated MODULE_OVERRIDES.md: Changed count from 20 to 19 module overrides, removed mod_menu section, added note about removal
- Updated STANDARD_MODULES_README.md: Removed mod_menu documentation, renumbered remaining modules, updated file structure
- Updated testing checklists to remove mod_menu references
- **Added clarification**: MokoOnyx is a standalone template extension (not a package)
- Updated updates.xml to version 03.08.01
#### Files Removed
- `src/templates/html/mod_menu/default.php`
- `src/templates/html/mod_menu/default_component.php`
- `src/templates/html/mod_menu/default_url.php`
- `src/templates/html/mod_menu/index.html`
**Note**: This is a patch release that removes problematic overrides to restore core functionality. Menu styling via CSS remains intact. MokoOnyx remains a standalone Joomla template extension (type="template"), not bundled as a package.
## [03.08.00] - 2026-02-22
### Added - Community Builder Component Overrides
Minor version bump adding **4 Community Builder component view overrides** to complement the existing CB module overrides (mod_cblogin, mod_comprofilerOnline).
#### Community Builder Components (4 views)
- **com_comprofiler/userprofile**: User profile display with avatar, tabs, and custom fields in responsive layout
- **com_comprofiler/userslist**: User directory with search functionality and responsive grid (1-3 columns)
- **com_comprofiler/registers**: User registration form with multi-step fieldsets, validation, captcha support
- **com_comprofiler/login**: Login page with remember me checkbox, registration and password recovery links
#### CSS Architecture (600+ lines)
- Mobile-first responsive design with Bootstrap breakpoints (576px, 768px, 992px)
- BEM naming convention (`.cb-profile__`, `.cb-userslist__`, `.cb-register__`, `.cb-login__`)
- Integrated with template CSS variables for consistent theming
- 48px touch targets on mobile, 44px on desktop (WCAG 2.1 Level AA)
- 16px input font size on mobile to prevent iOS zoom
- Responsive grids adapting from 1 column (mobile) to 2-3 columns (desktop)
#### Accessibility Features
- Full ARIA labels and descriptions for screen readers
- Semantic HTML5 structure with proper landmarks
- Keyboard navigation support throughout
- Required field indicators with visually-hidden labels
- Focus states with visible outlines
#### Security Best Practices
- Proper output escaping with htmlspecialchars() and ENT_QUOTES
- _JEXEC security checks in all PHP files
- index.html protection files in all directories (6 files)
- CSRF token support in forms
- Input validation and error display
### Technical Details
- **Files Added**: 11 (4 component view files + 6 index.html + 1 root index.html)
- **CSS Lines Added**: 600+ lines of responsive styles
- **PHP Validation**: All files pass syntax validation
- **Component Views**: userprofile, userslist, registers, login
- **Documentation**: Ready for MODULE_OVERRIDES.md update
## [03.07.00] - 2026-02-22
### Added - Mobile-Responsive Module & Component Overrides
This major release introduces **20 mobile-responsive module overrides** and **3 component overrides** designed to enhance the mobile user experience across standard Joomla, VirtueMart, Community Builder, and popular third-party extensions.
#### Search Module
- **mod_search**: Mobile-responsive search with multiple button positions (left, right, top, bottom), 48px touch targets, 16px input font to prevent iOS zoom
#### VirtueMart E-Commerce Modules (5 modules)
- **mod_virtuemart_cart**: Shopping cart with responsive product cards, remove buttons, price display
- **mod_virtuemart_product**: Product showcase with responsive grid (1-4 columns), hover effects, ratings
- **mod_virtuemart_currencies**: Currency selector dropdown with accessible styling
- **mod_virtuemart_category**: Category navigation with hierarchical display, product counts
- **mod_virtuemart_manufacturer**: Manufacturer/brand display with responsive grid (2-4 columns)
- **VIRTUEMART_MODULES_README.md**: Comprehensive master documentation for all VirtueMart overrides
#### Standard Joomla & Community Builder Modules (6 modules)
- **mod_menu**: Main navigation with multiple layout files (default, component, URL), responsive horizontal/vertical layouts
- **mod_breadcrumbs**: Breadcrumb navigation with Schema.org markup for SEO
- **mod_login**: User login/logout form with 2FA support, remember me checkbox
- **mod_articles_latest**: Latest articles with responsive cards, metadata, featured badges
- **mod_cblogin**: Community Builder login with avatar display, profile links
- **mod_comprofilerOnline**: CB online users with avatar grid, online status indicators
- **STANDARD_MODULES_README.md**: Comprehensive master documentation for standard module overrides
#### Industry Extension Modules (8 modules + 2 components)
- **mod_k2_content**: K2 content display with responsive grid (1-3 columns), featured images, metadata
- **mod_acymailing**: Newsletter subscription form with validation, GDPR compliance
- **mod_hikashop_cart**: HikaShop shopping cart with product list, quantity adjustment
- **mod_kunenalatest**: Kunena forum latest posts with excerpts, avatars, reply counts
- **mod_kunenalogin**: Kunena forum login with user avatar, statistics, quick login
- **mod_kunenasearch**: Kunena forum search with multiple button positions
- **mod_kunenastats**: Kunena forum statistics with visual cards, member/topic counts
- **mod_osmembership**: OS Membership Pro plans with pricing cards, feature lists, badges
- **com_kunena/category**: Kunena forum category list component view
- **com_osmembership/plans**: OS Membership Pro responsive pricing table component view
- **INDUSTRY_MODULES_README.md**: Comprehensive master documentation for industry extensions
#### CSS & Styling
- Added **2,000+ lines** of mobile-responsive CSS to `src/media/css/template.css`
- Four dedicated CSS sections for organized styling:
- MOD_SEARCH MOBILE RESPONSIVE STYLES
- VIRTUEMART MODULE MOBILE RESPONSIVE STYLES
- STANDARD JOOMLA & COMMUNITY BUILDER MODULE STYLES
- INDUSTRY EXTENSION MODULE STYLES
- ADDITIONAL KUNENA & MEMBERSHIP PRO MODULE STYLES
- BEM naming convention for all CSS classes (`.mod-search__button`, `.mod-vm-product__grid`, etc.)
- Integration with existing template CSS variables for seamless theming
- Responsive grids with Bootstrap-aligned breakpoints (sm, md, lg, xl, xxl)
#### Documentation
- **docs/MODULE_OVERRIDES.md**: Comprehensive guide covering all 23 overrides
- Feature descriptions and specifications
- CSS architecture and customization guide
- Accessibility features documentation
- Troubleshooting guide
- Best practices and usage examples
- Individual README.md files for VirtueMart module groups (5 modules)
- Master README files for each category (VirtueMart, Standard, Industry)
- Security index.html files in all override directories (23 files)
### Key Features Across All Overrides
#### Mobile-First Responsive Design
- Touch targets: 48px on mobile, 44px on desktop (WCAG 2.1 compliant)
- 16px minimum input font size on mobile (prevents iOS zoom)
- Responsive layouts: 1-4 columns based on screen size
- Mobile-first CSS with progressive enhancement
- Bootstrap-aligned breakpoints: 576px, 768px, 992px, 1200px, 1400px
#### Accessibility
- Full ARIA labels and descriptions on all interactive elements
- Keyboard navigation support throughout
- Screen reader compatible with semantic HTML5
- WCAG 2.1 Level AA compliance
- Proper heading hierarchy and focus management
- Alternative text for images and icons
#### Security
- Proper output escaping with Joomla escapeHtml()
- _JEXEC security checks in all PHP files
- index.html protection files in all directories
- Input validation where applicable
- CSRF token support in forms
#### Maintainability
- BEM naming convention for CSS classes
- Consistent code structure across all overrides
- Comprehensive inline documentation
- Modular, reusable components
- Integration with template CSS variables
### Changed
- **Version**: Updated to 03.07.00 across all files
### Technical Details
- **Total Files**: 66 new files created
- 42 PHP override files
- 23 index.html security files
- 1 comprehensive MODULE_OVERRIDES.md documentation
- **CSS Added**: 2,000+ lines of responsive styles
- **Documentation**: 15,000+ words across all README files
### Migration Notes
- All overrides are opt-in and non-breaking
- Existing sites will continue to work without changes
- Overrides automatically apply when modules are used
- No database changes or migration required
- Custom overrides can coexist with template overrides
### Testing
- All PHP syntax validated
- Code review completed (all issues resolved)
- CodeQL security scan passed
- Responsive design tested across breakpoints
- Accessibility validated with ARIA compliance
---
## [03.06.03] - 2026-01-30
### Added
- **Templates Directory**: Created `/templates/` directory with ready-to-use color palette templates
- `colors_custom_light.css` - Comprehensive light mode color template with all available variables
- `colors_custom_dark.css` - Comprehensive dark mode color template with all available variables
- **CSS Variables Documentation**: Added complete CSS variables reference guide (`docs/CSS_VARIABLES.md`)
- Complete list of all customizable CSS variables
- Organized by category (colors, typography, borders, etc.)
- Usage examples and tips for customization
- Light and dark mode variable differences documented
### Changed
- **README**: Updated title to "README - MokoOnyx (VERSION: 03.09.03)"
- **README**: Fixed custom color variables instructions with correct file paths
- **README**: Updated example CSS variables to use actual template variable names (e.g., `--color-link` instead of `--cassiopeia-color-link`)
- **README**: Added note that custom color files are excluded from version control via `.gitignore`
- **README**: Enhanced Custom Color Palettes section with step-by-step instructions
- **README**: Added link to CSS Variables documentation for complete reference
- **TOC CSS**: Updated bootstrap-toc.css to use template color variables for proper theme integration
- **Version**: Updated version to 03.06.03 across all files
### Documentation
- **docs/README.md**: Added CSS Variables Reference to developer documentation section
- **docs/README.md**: Updated project structure to include `/templates/` directory
- **docs/README.md**: Updated version to 03.06.03
- Clarified that `colors_custom.css` files are gitignored to prevent fork-specific customizations from being committed
## [03.06.02] - 2026-01-30
### Major Rebrand
This release includes a complete rebrand from "Moko-Cassiopeia" (hyphenated) to "MokoOnyx" (camelCase).
### Changed
- **Naming Convention**: Changed template identifier from `moko-cassiopeia` to `mokoonyx` across all files
- **Display Name**: Updated from "Moko-Cassiopeia" to "MokoOnyx" in all documentation and language files
- **Language Constants**: Renamed all language keys from `TPL_MOKO-CASSIOPEIA_*` to `TPL_MOKOONYX_*`
- **Language Files**: Renamed from `tpl_moko-cassiopeia.*` to `tpl_mokoonyx.*` (4 files)
- **Media Paths**: Updated from `media/templates/site/moko-cassiopeia/` to `media/templates/site/mokoonyx/`
- **Repository URLs**: Updated all references to use `MokoOnyx` casing
- **Template Element**: Changed Joomla extension element name from `moko-cassiopeia` to `mokoonyx`
- **Documentation**: Updated all markdown files, XML manifests, and code comments
### Removed
- **Default Assets**: Removed `logo.svg` and `favicon.ico` to allow clean installations
- **Template Overrides**: Removed all template override files (48 files, ~4,500 lines)
- Removed `src/templates/html/` folder entirely
- Removed overrides for: com_content, com_contact, com_engage, mod_menu, mod_custom, mod_gabble, layouts/chromes
- Template now inherits all rendering from Joomla Cassiopeia defaults
- Updated `templateDetails.xml` to remove html folder reference
### Breaking Changes
⚠️ **Important**: This release contains breaking changes:
- Existing installations will see template name change in Joomla admin
- Custom code referencing old language constants (`TPL_MOKO-CASSIOPEIA_*`) will need updates
- Custom code referencing old media paths will need updates
- Sites relying on custom template overrides will revert to Cassiopeia defaults
- Extension element name changed (may require reinstallation in some cases)
### Migration Notes
- Backup your site before upgrading
- Review any custom code for references to old naming convention
- Test thoroughly after upgrade, especially if using custom overrides
## [03.06.00] - 2026-01-28
### Changed
- Updated version to 03.06.00 across all files
- Standardized version numbering format
## [03.05.01] - 2026-01-09
### Added
- Added `dependency-review.yml` workflow for dependency vulnerability scanning
- Added `standards-compliance.yml` workflow for MokoStandards validation
- Added `.github/dependabot.yml` configuration for automated security updates
- Added `docs/README.md` as documentation index
### Changed
- Removed custom `codeql-analysis.yml` workflow (repository uses GitHub's default CodeQL setup)
- Enforced repository compliance with MokoStandards requirements
- Improved security posture with automated scanning and dependency management
## [03.05.00] - 2026-01-04
### Added
- Created `.github/workflows` directory structure
### Changed
- Replaced `./CODE_OF_CONDUCT.md` from `MokoStandards`
- Replaced `./CONTRIBUTING.md` from `MokoStandards`
- TODO split to own file
## [03.01.00] - 2025-12-16
### Added
- Created `.github/workflows/` directory for GitHub Actions
## [03.00.00] - 2025-12-09
### Changed
- Copyright Headers updated to MokoCodingDefaults standards
- Fixed `./templates/mokoonyx/index.php` color style injection
- Upgraded Font Awesome 6 to Font Awesome 7 Free
- Added Font Awesome 7 Free style fallback
### Removed
- Removed `./CODE_OF_CONDUCT.md` (replaced with MokoStandards version)
- Removed `./CONTRIBUTING.md` (replaced with MokoStandards version)
## [02.01.05] - 2025-09-04
### Changed
- Repaired template.css and colors_standard.css
### Removed
- Removed vmbasic.css
## [02.00.00] - 2025-08-30
### Added - Dark Mode Toggle
- Frontend toggle switch included in template
- JavaScript handles switching between light/dark modes
- Dark mode CSS rules applied across template styles
- Automatic persistence of user choice (via localStorage)
- Admins can override default mode in template settings
### Added - Header Parameters Update
- Added logo parameter support in template settings
- Updated metadata & copyright header
### Added - Expanded TOC (Table of Contents)
- Automatic TOC injection when enabled
- User selects placement via article > options > layout (`toc-left` or `toc-right`)
### Changed
- Cleaned up `index.php` by removing skip-to-content duplicate calls
- Consolidated JavaScript asset loading (ensuring dark-mode script is loaded correctly from external JS file)
- Streamlined CSS for toggle switch, ensuring it inherits Bootstrap/Cassiopeia defaults
- General accessibility refinements in typography and color contrast
- Fixed missing logo param in header output
- Corrected stylesheet inconsistencies between Bootstrap 5 helpers and template overrides
- Patched redundant calls in script includes
## [01.00.00] - 2025-01-01
### Added - Initial Public Release
- Font Awesome 6 integration (later upgraded to FA7)
- Bootstrap 5 helpers (grid, utility classes)
- Automatic Table of Contents (TOC) utility
- Moko Expansions: Google Tag Manager / GA4 hooks
- Built on top of Joomla's default Cassiopeia template
- Minimal core template overrides for maximum upgrade compatibility
---
## Links
- **Full Roadmap**: [MokoOnyx Roadmap](https://mokoconsulting.tech/support/joomla-cms/mokoonyx-roadmap)
- **Repository**: [GitHub](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx)
- **Issue Tracker**: [GitHub Issues](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/issues)
## Version Format
This project uses semantic versioning: `MAJOR.MINOR.PATCH`
- **MAJOR**: Incompatible API changes or major overhauls
- **MINOR**: New features, backwards-compatible
- **PATCH**: Bug fixes, backwards-compatible
- **Menu icon padding removed** -- Removed hardcoded `p-2` class from all mod_menu icon spans (horizontal + mainmenu layouts); icons now inherit spacing from the parent link
- **Runner checkout failures** -- Fixed MySQL deadlocks in Gitea actions scheduler by restarting Gitea and recreating runners with --privileged flag
- **workflow_dispatch 500 error** -- Stripped UTF-8 multibyte characters from all YAML files that Gitea's Go parser rejected as control characters
+53
View File
@@ -0,0 +1,53 @@
<?php
/**
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default menu — Component item layout (sidebar/footer vertical lists)
*/
defined('_JEXEC') or die;
use Joomla\CMS\Filter\OutputFilter;
use Joomla\CMS\HTML\HTMLHelper;
$attributes = [];
if ($item->anchor_title) {
$attributes['title'] = $item->anchor_title;
}
if ($item->anchor_css) {
$attributes['class'] = $item->anchor_css;
}
if ($item->anchor_rel) {
$attributes['rel'] = $item->anchor_rel;
}
$linktype = $item->title;
if ($item->menu_icon) {
if ($itemParams->get('menu_text', 1)) {
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
} else {
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
}
}
if ($item->browserNav == 1) {
$attributes['target'] = '_blank';
$attributes['rel'] = 'noopener noreferrer';
} elseif ($item->browserNav == 2) {
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
}
$attributes['class'] = 'nav-link mod-menu__link';
echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
+30
View File
@@ -0,0 +1,30 @@
<?php
/**
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default menu — Heading item layout (sidebar/footer vertical lists)
*/
defined('_JEXEC') or die;
$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : '';
$anchor_css = $item->anchor_css ?: '';
$linktype = $item->title;
if ($item->menu_icon) {
if ($itemParams->get('menu_text', 1)) {
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
} else {
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
}
}
?>
<span class="nav-link mod-menu__heading <?php echo $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
+30
View File
@@ -0,0 +1,30 @@
<?php
/**
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default menu — Separator item layout (sidebar/footer vertical lists)
*/
defined('_JEXEC') or die;
$title = $item->anchor_title ? ' title="' . $item->anchor_title . '"' : '';
$anchor_css = $item->anchor_css ?: '';
$linktype = $item->title;
if ($item->menu_icon) {
if ($itemParams->get('menu_text', 1)) {
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
} else {
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
}
}
?>
<hr class="mod-menu__separator <?php echo $anchor_css; ?>"<?php echo $title; ?> />
+59
View File
@@ -0,0 +1,59 @@
<?php
/**
* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
*
* This file is part of a Moko Consulting project.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/**
* Default menu — URL item layout (sidebar/footer vertical lists)
*/
defined('_JEXEC') or die;
use Joomla\CMS\Filter\OutputFilter;
use Joomla\CMS\HTML\HTMLHelper;
$attributes = [];
if ($item->anchor_title) {
$attributes['title'] = $item->anchor_title;
}
if ($item->anchor_css) {
$attributes['class'] = $item->anchor_css;
}
if ($item->anchor_rel) {
$attributes['rel'] = $item->anchor_rel;
}
$linktype = $item->title;
if ($item->menu_icon) {
if ($itemParams->get('menu_text', 1)) {
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
} else {
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
}
}
if ($item->browserNav == 1) {
$attributes['target'] = '_blank';
$attributes['rel'] = 'noopener noreferrer';
} elseif ($item->browserNav == 2) {
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
}
$linkClass = 'nav-link mod-menu__link';
if (isset($attributes['class'])) {
$attributes['class'] .= ' ' . $linkClass;
} else {
$attributes['class'] = $linkClass;
}
echo HTMLHelper::_('link', OutputFilter::ampReplace(htmlspecialchars($item->flink, ENT_COMPAT, 'UTF-8', false)), $linktype, $attributes);
+6 -17
View File
@@ -8,8 +8,8 @@
*/
/**
* Main Menu - Mobile responsive collapsible dropdown menu override
* Bootstrap 5 responsive navbar with hamburger menu
* Horizontal menu — always-visible inline links that wrap on mobile.
* No hamburger, no collapse. Suitable for Quick Links, utility nav, topbar menus.
*/
defined('_JEXEC') or die;
@@ -22,19 +22,13 @@ if ($tagId = $params->get('tag_id', '')) {
$id = ' id="' . $tagId . '"';
}
// Get module class suffix
$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COMPAT, 'UTF-8');
// The menu class is deprecated. Use mod-menu instead
?>
<nav class="mod-menu mod-menu-main navbar navbar-expand-lg<?php echo $moduleclass_sfx; ?>"<?php echo $id; ?>>
<div class="container-fluid p-0">
<!-- Collapsible menu content — toggle controlled by .nav-mobile-bar in index.php -->
<div class="collapse navbar-collapse" id="moko-main-menu-collapse">
<ul class="navbar-nav mod-menu-main__list">
<nav class="mod-menu mod-menu-horizontal<?php echo $moduleclass_sfx; ?>"<?php echo $id; ?> aria-label="<?php echo htmlspecialchars($module->title, ENT_COMPAT, 'UTF-8'); ?>">
<ul class="nav mod-menu-horizontal__list flex-wrap">
<?php foreach ($list as $i => &$item) :
$itemParams = $item->getParams();
$class = 'nav-item mod-menu-main__item item-' . $item->id;
$class = 'nav-item mod-menu-horizontal__item item-' . $item->id;
if ($item->id == $default_id) {
$class .= ' default';
@@ -83,19 +77,14 @@ $moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COM
break;
endswitch;
// The next item is deeper.
if ($item->deeper) {
echo '<ul class="dropdown-menu mod-menu-main__dropdown">';
echo '<ul class="dropdown-menu mod-menu-horizontal__dropdown">';
} elseif ($item->shallower) {
// The next item is shallower.
echo '</li>';
echo str_repeat('</ul></li>', $item->level_diff);
} else {
// The next item is on the same level.
echo '</li>';
}
endforeach;
?></ul>
</div>
</div>
</nav>
+2 -7
View File
@@ -8,7 +8,7 @@
*/
/**
* Main Menu - Component item layout
* Horizontal menu Component item layout
*/
defined('_JEXEC') or die;
@@ -33,12 +33,9 @@ if ($item->anchor_rel) {
$linktype = $item->title;
if ($item->menu_icon) {
// The link is an icon
if ($itemParams->get('menu_text', 1)) {
// If the link text is to be displayed, the icon is added with aria-hidden
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
} else {
// If the icon itself is the link, it needs a visually hidden text
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
}
}
@@ -48,12 +45,10 @@ if ($item->browserNav == 1) {
$attributes['rel'] = 'noopener noreferrer';
} elseif ($item->browserNav == 2) {
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
}
// Add dropdown toggle for items with children
$linkClass = 'nav-link mod-menu-main__link';
$linkClass = 'nav-link mod-menu-horizontal__link';
if ($item->deeper) {
$linkClass .= ' dropdown-toggle';
$attributes['data-bs-toggle'] = 'dropdown';
+2 -6
View File
@@ -8,7 +8,7 @@
*/
/**
* Main Menu - Heading item layout
* Horizontal menu Heading item layout
*/
defined('_JEXEC') or die;
@@ -19,18 +19,14 @@ $anchor_css = $item->anchor_css ?: '';
$linktype = $item->title;
if ($item->menu_icon) {
// The link is an icon
if ($itemParams->get('menu_text', 1)) {
// If the link text is to be displayed, the icon is added with aria-hidden
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
} else {
// If the icon itself is the link, it needs a visually hidden text
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
}
}
// Add dropdown toggle for items with children
$headingClass = 'nav-link mod-menu-main__heading';
$headingClass = 'nav-link mod-menu-horizontal__heading';
if ($item->deeper) {
$headingClass .= ' dropdown-toggle';
}
+2 -5
View File
@@ -8,7 +8,7 @@
*/
/**
* Main Menu - Separator item layout
* Horizontal menu Separator item layout
*/
defined('_JEXEC') or die;
@@ -19,15 +19,12 @@ $anchor_css = $item->anchor_css ?: '';
$linktype = $item->title;
if ($item->menu_icon) {
// The link is an icon
if ($itemParams->get('menu_text', 1)) {
// If the link text is to be displayed, the icon is added with aria-hidden
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
} else {
// If the icon itself is the link, it needs a visually hidden text
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
}
}
?>
<span class="dropdown-divider mod-menu-main__separator <?php echo $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
<span class="dropdown-divider mod-menu-horizontal__separator <?php echo $anchor_css; ?>"<?php echo $title; ?>><?php echo $linktype; ?></span>
+2 -8
View File
@@ -8,7 +8,7 @@
*/
/**
* Main Menu - URL item layout
* Horizontal menu URL item layout
*/
defined('_JEXEC') or die;
@@ -33,12 +33,9 @@ if ($item->anchor_rel) {
$linktype = $item->title;
if ($item->menu_icon) {
// The link is an icon
if ($itemParams->get('menu_text', 1)) {
// If the link text is to be displayed, the icon is added with aria-hidden
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span>' . $item->title;
} else {
// If the icon itself is the link, it needs a visually hidden text
$linktype = '<span class="' . $item->menu_icon . '" aria-hidden="true"></span><span class="visually-hidden">' . $item->title . '</span>';
}
}
@@ -48,12 +45,10 @@ if ($item->browserNav == 1) {
$attributes['rel'] = 'noopener noreferrer';
} elseif ($item->browserNav == 2) {
$options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,' . $params->get('window_open');
$attributes['onclick'] = "window.open(this.href, 'targetWindow', '" . $options . "'); return false;";
}
// Add dropdown toggle for items with children
$linkClass = 'nav-link mod-menu-main__link';
$linkClass = 'nav-link mod-menu-horizontal__link';
if ($item->deeper) {
$linkClass .= ' dropdown-toggle';
$attributes['data-bs-toggle'] = 'dropdown';
@@ -61,7 +56,6 @@ if ($item->deeper) {
$attributes['aria-expanded'] = 'false';
}
// Merge existing class with our class
if (isset($attributes['class'])) {
$attributes['class'] .= ' ' . $linkClass;
} else {
+3 -8
View File
@@ -28,14 +28,9 @@ $moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx', ''), ENT_COM
// The menu class is deprecated. Use mod-menu instead
?>
<nav class="mod-menu mod-menu-main navbar navbar-expand-lg<?php echo $moduleclass_sfx; ?>"<?php echo $id; ?>>
<div class="container-fluid">
<!-- Hamburger toggle button for mobile -->
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainMenuCollapse-<?php echo $module->id; ?>" aria-controls="mainMenuCollapse-<?php echo $module->id; ?>" aria-expanded="false" aria-label="Toggle Main Menu">
<span class="fa-solid fa-bars" aria-hidden="true"></span>
</button>
<!-- Collapsible menu content -->
<div class="collapse navbar-collapse" id="mainMenuCollapse-<?php echo $module->id; ?>">
<div class="container-fluid p-0">
<!-- Collapsible menu content — toggle controlled by .nav-mobile-bar in index.php -->
<div class="collapse navbar-collapse" id="moko-main-menu-collapse">
<ul class="navbar-nav mod-menu-main__list">
<?php foreach ($list as $i => &$item) :
$itemParams = $item->getParams();
+1 -1
View File
@@ -4,7 +4,7 @@
;
; SPDX-License-Identifier: GPL-3.0-or-later
;
TPL_MOKOONYX="MokoOnyx"
TPL_MOKOONYX="Template - MokoOnyx"
TPL_MOKOONYX_GOOGLE_FIELDSET_LABEL="Google"
TPL_MOKOONYX_DRAWERS_FIELDSET_LABEL="Drawers"
TPL_MOKOONYX_MOD_MENU_LAYOUT_COLLAPSE_METISMENU="Collapsible Dropdown"
+1 -1
View File
@@ -4,7 +4,7 @@
;
; SPDX-License-Identifier: GPL-3.0-or-later
;
TPL_MOKOONYX="MokoOnyx"
TPL_MOKOONYX="Template - MokoOnyx"
TPL_MOKOONYX_GOOGLE_FIELDSET_LABEL="Google"
TPL_MOKOONYX_DRAWERS_FIELDSET_LABEL="Drawers"
TPL_MOKOONYX_MOD_MENU_LAYOUT_COLLAPSE_METISMENU="Collapsible Dropdown"
+4
View File
@@ -23506,3 +23506,7 @@ padding: 0.25rem;
font-size: 0.8125rem;
}
}
.fa-solid {
margin-right: 0.25rem;
}
+3 -2
View File
@@ -35,8 +35,8 @@
https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/raw/branch/main/updates.xml
</server>
</updateservers>
<name>MokoOnyx</name>
<version>02.07.00</version>
<name>Template - MokoOnyx</name>
<version>02.08.00</version>
<scriptfile>script.php</scriptfile>
<creationDate>2026-05-16</creationDate>
<author>Jonathan Miller || Moko Consulting</author>
@@ -366,3 +366,4 @@
</config>
</extension>
<!-- dev release 01.00.26 -->
+49 -44
View File
@@ -1,93 +1,98 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
VERSION: 02.07.00
VERSION: 02.08.00
-->
<updates>
<update>
<name>MokoOnyx</name>
<description>MokoOnyx update</description>
<name>Template - MokoOnyx</name>
<description>Template - MokoOnyx development build.</description>
<element>mokoonyx</element>
<type>template</type>
<version>02.07.00</version>
<client>site</client>
<tags><tag>development</tag></tags>
<infourl title="MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<version>02.08.00</version>
<creationDate>2026-05-29</creationDate>
<infourl title='Template - MokoOnyx'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.07.00.zip</downloadurl>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.08.00.zip</downloadurl>
</downloads>
<sha256>8961a292d1f230b3870a54106b0dc823ca2f33477cc09fe079370efb7ffe2ab1</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<sha256>a36b32b3f2df027ff11dc6b79c1c4ae98d684e2683bc2db25d303fe6c96ca644</sha256>
<tags><tag>dev</tag></tags>
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
<targetplatform name="joomla" version="(5|6)\..*" />
</update>
<update>
<name>MokoOnyx</name>
<description>MokoOnyx update</description>
<name>Template - MokoOnyx</name>
<description>Template - MokoOnyx alpha build.</description>
<element>mokoonyx</element>
<type>template</type>
<version>02.07.00</version>
<client>site</client>
<version>02.08.00</version>
<creationDate>2026-05-29</creationDate>
<infourl title='Template - MokoOnyx'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.08.00.zip</downloadurl>
</downloads>
<sha256>a36b32b3f2df027ff11dc6b79c1c4ae98d684e2683bc2db25d303fe6c96ca644</sha256>
<tags><tag>alpha</tag></tags>
<infourl title="MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.07.00.zip</downloadurl>
</downloads>
<sha256>8961a292d1f230b3870a54106b0dc823ca2f33477cc09fe079370efb7ffe2ab1</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
<targetplatform name="joomla" version="(5|6)\..*" />
</update>
<update>
<name>MokoOnyx</name>
<description>MokoOnyx update</description>
<name>Template - MokoOnyx</name>
<description>Template - MokoOnyx beta build.</description>
<element>mokoonyx</element>
<type>template</type>
<version>02.07.00</version>
<client>site</client>
<version>02.08.00</version>
<creationDate>2026-05-29</creationDate>
<infourl title='Template - MokoOnyx'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.08.00.zip</downloadurl>
</downloads>
<sha256>a36b32b3f2df027ff11dc6b79c1c4ae98d684e2683bc2db25d303fe6c96ca644</sha256>
<tags><tag>beta</tag></tags>
<infourl title="MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.07.00.zip</downloadurl>
</downloads>
<sha256>8961a292d1f230b3870a54106b0dc823ca2f33477cc09fe079370efb7ffe2ab1</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
<targetplatform name="joomla" version="(5|6)\..*" />
</update>
<update>
<name>MokoOnyx</name>
<description>MokoOnyx update</description>
<name>Template - MokoOnyx</name>
<description>Template - MokoOnyx rc build.</description>
<element>mokoonyx</element>
<type>template</type>
<version>02.07.00</version>
<client>site</client>
<version>02.08.00</version>
<creationDate>2026-05-29</creationDate>
<infourl title='Template - MokoOnyx'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<downloads>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.08.00.zip</downloadurl>
</downloads>
<sha256>a36b32b3f2df027ff11dc6b79c1c4ae98d684e2683bc2db25d303fe6c96ca644</sha256>
<tags><tag>rc</tag></tags>
<infourl title="MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.07.00.zip</downloadurl>
</downloads>
<sha256>8961a292d1f230b3870a54106b0dc823ca2f33477cc09fe079370efb7ffe2ab1</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
<targetplatform name="joomla" version="(5|6)\..*" />
</update>
<update>
<name>MokoOnyx</name>
<description>MokoOnyx update</description>
<name>Template - MokoOnyx</name>
<description>Template - MokoOnyx stable build.</description>
<element>mokoonyx</element>
<type>template</type>
<version>02.07.00</version>
<client>site</client>
<tags><tag>stable</tag></tags>
<infourl title="MokoOnyx">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<version>02.08.00</version>
<creationDate>2026-05-29</creationDate>
<infourl title='Template - MokoOnyx'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.07.00.zip</downloadurl>
<downloadurl type='full' format='zip'>https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/releases/download/stable/tpl_mokoonyx-02.08.00.zip</downloadurl>
</downloads>
<sha256>8961a292d1f230b3870a54106b0dc823ca2f33477cc09fe079370efb7ffe2ab1</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<sha256>a36b32b3f2df027ff11dc6b79c1c4ae98d684e2683bc2db25d303fe6c96ca644</sha256>
<tags><tag>stable</tag></tags>
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
<targetplatform name="joomla" version="(5|6)\..*" />
</update>
</updates>