182 Commits

Author SHA1 Message Date
jmiller 2eda6cd6e7 chore: rename Setup step to moko-platform [skip ci] 2026-05-16 22:19:23 +00:00
jmiller f95e678ebf feat(ci): deploy auto-release to dev [skip ci] 2026-05-16 18:58:36 +00:00
jmiller 6081964659 chore: force-sync .mokogitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-12 19:16:24 +00:00
jmiller 28a1f7d0d2 chore: force-sync .mokogitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-12 19:16:24 +00:00
jmiller 746222d7ea chore: force-sync .mokogitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-12 19:16:23 +00:00
jmiller f529968422 chore: force-sync .mokogitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-12 19:16:23 +00:00
jmiller 17aaad19b1 chore: force-sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md [skip ci] 2026-05-12 19:16:23 +00:00
jmiller d7a677c7f7 chore: force-sync .mokogitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-12 19:16:22 +00:00
jmiller 074f9eebd4 chore: force-sync .mokogitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-12 19:16:22 +00:00
jmiller 7098976087 chore: force-sync .mokogitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-12 19:16:21 +00:00
jmiller e5b05a4537 chore: force-sync .mokogitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-12 19:16:21 +00:00
jmiller 649e836466 chore: force-sync .mokogitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-12 19:16:21 +00:00
jmiller d646372198 chore: force-sync .mokogitea/workflows/update-server.yml [skip ci] 2026-05-12 19:16:20 +00:00
jmiller 5b0e8e39bd chore: force-sync .mokogitea/workflows/security-audit.yml [skip ci] 2026-05-12 19:16:20 +00:00
jmiller 2c490887a4 chore: force-sync .mokogitea/workflows/repo-health.yml [skip ci] 2026-05-12 19:16:19 +00:00
jmiller 486ed44198 chore: force-sync .mokogitea/workflows/pre-release.yml [skip ci] 2026-05-12 19:16:19 +00:00
jmiller 8f7cf59d4b chore: force-sync .mokogitea/workflows/pr-check.yml [skip ci] 2026-05-12 19:16:19 +00:00
jmiller f3940bb772 chore: force-sync .mokogitea/workflows/notify.yml [skip ci] 2026-05-12 19:16:18 +00:00
jmiller 94244f3a5f chore: force-sync .mokogitea/workflows/gitleaks.yml [skip ci] 2026-05-12 19:16:18 +00:00
jmiller 39ff440973 chore: force-sync .mokogitea/workflows/deploy-manual.yml [skip ci] 2026-05-12 19:16:18 +00:00
jmiller 391f5f4260 chore: force-sync .mokogitea/workflows/cleanup.yml [skip ci] 2026-05-12 19:16:17 +00:00
jmiller 8583ecf003 chore: force-sync .mokogitea/workflows/ci-joomla.yml [skip ci] 2026-05-12 19:16:17 +00:00
jmiller fdd07d7666 chore: force-sync .mokogitea/workflows/cascade-dev.yml [skip ci] 2026-05-12 19:16:16 +00:00
jmiller 0c80a9d2db chore: force-sync .mokogitea/workflows/auto-release.yml [skip ci] 2026-05-12 19:16:16 +00:00
jmiller 152a8b5550 chore: force-sync .mokogitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-12 19:11:31 +00:00
jmiller f80f3fc663 chore: force-sync .mokogitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-12 19:11:31 +00:00
jmiller 80dbfd7bf1 chore: force-sync .mokogitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-12 19:11:31 +00:00
jmiller fa615788d5 chore: force-sync .mokogitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-12 19:11:30 +00:00
jmiller f764b5553a chore: force-sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md [skip ci] 2026-05-12 19:11:30 +00:00
jmiller cda7ca51e5 chore: force-sync .mokogitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-12 19:11:29 +00:00
jmiller d7d3f16426 chore: force-sync .mokogitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-12 19:11:29 +00:00
jmiller 946368ff91 chore: force-sync .mokogitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-12 19:11:29 +00:00
jmiller a22f4d8734 chore: force-sync .mokogitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-12 19:11:28 +00:00
jmiller 398ff8721d chore: force-sync .mokogitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-12 19:11:28 +00:00
jmiller 1f6fcffd90 chore: force-sync .mokogitea/workflows/update-server.yml [skip ci] 2026-05-12 19:11:27 +00:00
jmiller 0dab58606b chore: force-sync .mokogitea/workflows/security-audit.yml [skip ci] 2026-05-12 19:11:27 +00:00
jmiller 2dc044303c chore: force-sync .mokogitea/workflows/repo-health.yml [skip ci] 2026-05-12 19:11:27 +00:00
jmiller c800438ab5 chore: force-sync .mokogitea/workflows/pre-release.yml [skip ci] 2026-05-12 19:11:26 +00:00
jmiller 371e97de26 chore: force-sync .mokogitea/workflows/pr-check.yml [skip ci] 2026-05-12 19:11:26 +00:00
jmiller 9122a144d4 chore: force-sync .mokogitea/workflows/notify.yml [skip ci] 2026-05-12 19:11:26 +00:00
jmiller 530064b656 chore: force-sync .mokogitea/workflows/gitleaks.yml [skip ci] 2026-05-12 19:11:25 +00:00
jmiller d9d5a5ec63 chore: force-sync .mokogitea/workflows/deploy-manual.yml [skip ci] 2026-05-12 19:11:25 +00:00
jmiller 5b526fef26 chore: force-sync .mokogitea/workflows/cleanup.yml [skip ci] 2026-05-12 19:11:24 +00:00
jmiller 6d76b4addc chore: force-sync .mokogitea/workflows/ci-joomla.yml [skip ci] 2026-05-12 19:11:24 +00:00
jmiller b0dadfd48f chore: force-sync .mokogitea/workflows/cascade-dev.yml [skip ci] 2026-05-12 19:11:24 +00:00
jmiller 31bd7cd606 chore: force-sync .mokogitea/workflows/auto-release.yml [skip ci] 2026-05-12 19:11:23 +00:00
jmiller d1a8d99585 chore: remove .mokogitea/.moko-platform [skip ci] 2026-05-12 19:08:36 +00:00
jmiller 07f3b7dea8 chore: force-sync .mokogitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-12 19:08:36 +00:00
jmiller 9d376f8585 chore: force-sync .mokogitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-12 19:08:36 +00:00
jmiller c62cf89d46 chore: force-sync .mokogitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-12 19:08:35 +00:00
jmiller bca73294a3 chore: force-sync .mokogitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-12 19:08:35 +00:00
jmiller e3f7a5e2a1 chore: force-sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md [skip ci] 2026-05-12 19:08:34 +00:00
jmiller aad25c4bc4 chore: force-sync .mokogitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-12 19:08:34 +00:00
jmiller 0d3d0f8739 chore: force-sync .mokogitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-12 19:08:34 +00:00
jmiller 612314e68a chore: force-sync .mokogitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-12 19:08:33 +00:00
jmiller 6b81591e37 chore: force-sync .mokogitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-12 19:08:33 +00:00
jmiller edb3163bfb chore: force-sync .mokogitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-12 19:08:32 +00:00
jmiller 9e5ef23a4d chore: force-sync .mokogitea/workflows/update-server.yml [skip ci] 2026-05-12 19:08:32 +00:00
jmiller 4bbdf09374 chore: force-sync .mokogitea/workflows/security-audit.yml [skip ci] 2026-05-12 19:08:32 +00:00
jmiller 74f137cd67 chore: force-sync .mokogitea/workflows/repo-health.yml [skip ci] 2026-05-12 19:08:31 +00:00
jmiller a092a47264 chore: force-sync .mokogitea/workflows/pre-release.yml [skip ci] 2026-05-12 19:08:31 +00:00
jmiller d4d5f202c2 chore: force-sync .mokogitea/workflows/pr-check.yml [skip ci] 2026-05-12 19:08:30 +00:00
jmiller 555d2768cf chore: force-sync .mokogitea/workflows/notify.yml [skip ci] 2026-05-12 19:08:30 +00:00
jmiller e126014418 chore: force-sync .mokogitea/workflows/gitleaks.yml [skip ci] 2026-05-12 19:08:30 +00:00
jmiller 0c0ed62a86 chore: force-sync .mokogitea/workflows/deploy-manual.yml [skip ci] 2026-05-12 19:08:29 +00:00
jmiller 4433106729 chore: force-sync .mokogitea/workflows/cleanup.yml [skip ci] 2026-05-12 19:08:29 +00:00
jmiller 0a1b3cad4f chore: force-sync .mokogitea/workflows/ci-joomla.yml [skip ci] 2026-05-12 19:08:29 +00:00
jmiller e912310752 chore: force-sync .mokogitea/workflows/cascade-dev.yml [skip ci] 2026-05-12 19:08:28 +00:00
jmiller b9923c5fa6 chore: force-sync .mokogitea/workflows/auto-release.yml [skip ci] 2026-05-12 19:08:28 +00:00
jmiller 196cbd580c chore: sync .mokogitea/ISSUE_TEMPLATE/version.md from template [skip ci] 2026-05-12 18:47:05 +00:00
jmiller ac7494b522 chore: sync .mokogitea/ISSUE_TEMPLATE/security.md from template [skip ci] 2026-05-12 18:47:04 +00:00
jmiller 68680f9239 chore: sync .mokogitea/ISSUE_TEMPLATE/rfc.md from template [skip ci] 2026-05-12 18:47:04 +00:00
jmiller e33fda2ccf chore: sync .mokogitea/ISSUE_TEMPLATE/question.md from template [skip ci] 2026-05-12 18:47:03 +00:00
jmiller 7ad5e1970b chore: sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md from template [skip ci] 2026-05-12 18:47:03 +00:00
jmiller ec25a87b7a chore: sync .mokogitea/ISSUE_TEMPLATE/feature_request.md from template [skip ci] 2026-05-12 18:47:03 +00:00
jmiller 496e18d57e chore: sync .mokogitea/ISSUE_TEMPLATE/documentation.md from template [skip ci] 2026-05-12 18:47:02 +00:00
jmiller 1fa7968dd9 chore: sync .mokogitea/ISSUE_TEMPLATE/config.yml from template [skip ci] 2026-05-12 18:47:02 +00:00
jmiller 6e6a51f03b chore: sync .mokogitea/ISSUE_TEMPLATE/bug_report.md from template [skip ci] 2026-05-12 18:47:02 +00:00
jmiller b831b8f5af chore: sync .mokogitea/ISSUE_TEMPLATE/adr.md from template [skip ci] 2026-05-12 18:47:01 +00:00
jmiller ac1e7d71be chore: sync .mokogitea/workflows/update-server.yml from template [skip ci] 2026-05-12 18:47:01 +00:00
jmiller c654e00a84 chore: sync .mokogitea/workflows/security-audit.yml from template [skip ci] 2026-05-12 18:47:00 +00:00
jmiller cdbbf4d796 chore: sync .mokogitea/workflows/repo-health.yml from template [skip ci] 2026-05-12 18:47:00 +00:00
jmiller b0b4e3a10d chore: sync .mokogitea/workflows/pre-release.yml from template [skip ci] 2026-05-12 18:47:00 +00:00
jmiller fb99c2e6d1 chore: sync .mokogitea/workflows/pr-check.yml from template [skip ci] 2026-05-12 18:46:59 +00:00
jmiller 86a42278bf chore: sync .mokogitea/workflows/notify.yml from template [skip ci] 2026-05-12 18:46:59 +00:00
jmiller ebaedd5ff7 chore: sync .mokogitea/workflows/gitleaks.yml from template [skip ci] 2026-05-12 18:46:59 +00:00
jmiller a8c30ae72a chore: sync .mokogitea/workflows/deploy-manual.yml from template [skip ci] 2026-05-12 18:46:58 +00:00
jmiller 5931fd5c28 chore: sync .mokogitea/workflows/cleanup.yml from template [skip ci] 2026-05-12 18:46:58 +00:00
jmiller a57ea2f326 chore: sync .mokogitea/workflows/ci-joomla.yml from template [skip ci] 2026-05-12 18:46:57 +00:00
jmiller 328b688b5a chore: sync .mokogitea/workflows/cascade-dev.yml from template [skip ci] 2026-05-12 18:46:57 +00:00
jmiller 7691cb8e0a chore: sync .mokogitea/workflows/auto-release.yml from template [skip ci] 2026-05-12 18:46:57 +00:00
jmiller 5ced9404dc chore: sync .mokogitea/ISSUE_TEMPLATE/version.md from template [skip ci] 2026-05-12 18:37:17 +00:00
jmiller 75720bb92a chore: sync .mokogitea/ISSUE_TEMPLATE/security.md from template [skip ci] 2026-05-12 18:37:16 +00:00
jmiller b2487dcafd chore: sync .mokogitea/ISSUE_TEMPLATE/rfc.md from template [skip ci] 2026-05-12 18:37:16 +00:00
jmiller 9617ec71f9 chore: sync .mokogitea/ISSUE_TEMPLATE/question.md from template [skip ci] 2026-05-12 18:37:16 +00:00
jmiller 449b1cecb6 chore: sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md from template [skip ci] 2026-05-12 18:37:15 +00:00
jmiller 4ddb2c31d3 chore: sync .mokogitea/ISSUE_TEMPLATE/feature_request.md from template [skip ci] 2026-05-12 18:37:15 +00:00
jmiller afa5783396 chore: sync .mokogitea/ISSUE_TEMPLATE/documentation.md from template [skip ci] 2026-05-12 18:37:15 +00:00
jmiller 5b4c25ce4c chore: sync .mokogitea/ISSUE_TEMPLATE/config.yml from template [skip ci] 2026-05-12 18:37:14 +00:00
jmiller 73b378a84f chore: sync .mokogitea/ISSUE_TEMPLATE/bug_report.md from template [skip ci] 2026-05-12 18:37:14 +00:00
jmiller 96fc14668a chore: sync .mokogitea/ISSUE_TEMPLATE/adr.md from template [skip ci] 2026-05-12 18:37:13 +00:00
jmiller ef1336c9df chore: sync .mokogitea/workflows/update-server.yml from template [skip ci] 2026-05-12 18:37:13 +00:00
jmiller 1a6936ba0f chore: sync .mokogitea/workflows/security-audit.yml from template [skip ci] 2026-05-12 18:37:13 +00:00
jmiller cbead82256 chore: sync .mokogitea/workflows/repo-health.yml from template [skip ci] 2026-05-12 18:37:12 +00:00
jmiller 2722e468f5 chore: sync .mokogitea/workflows/pre-release.yml from template [skip ci] 2026-05-12 18:37:12 +00:00
jmiller db0ddc0a3e chore: sync .mokogitea/workflows/pr-check.yml from template [skip ci] 2026-05-12 18:37:12 +00:00
jmiller 474e687e77 chore: sync .mokogitea/workflows/notify.yml from template [skip ci] 2026-05-12 18:37:11 +00:00
jmiller 188e94bf34 chore: sync .mokogitea/workflows/gitleaks.yml from template [skip ci] 2026-05-12 18:37:11 +00:00
jmiller 2237820a09 chore: sync .mokogitea/workflows/deploy-manual.yml from template [skip ci] 2026-05-12 18:37:11 +00:00
jmiller c3aca21494 chore: sync .mokogitea/workflows/cleanup.yml from template [skip ci] 2026-05-12 18:37:10 +00:00
jmiller 45e2deef52 chore: sync .mokogitea/workflows/ci-joomla.yml from template [skip ci] 2026-05-12 18:37:10 +00:00
jmiller bfdbe96fee chore: sync .mokogitea/workflows/cascade-dev.yml from template [skip ci] 2026-05-12 18:37:09 +00:00
jmiller 40fa7ebdc6 chore: sync .mokogitea/workflows/auto-release.yml from template [skip ci] 2026-05-12 18:37:09 +00:00
jmiller 9744bf735c chore: sync .mokogitea/workflows/update-server.yml from template [skip ci] 2026-05-12 05:31:11 +00:00
jmiller 2a1d26e92d chore: sync .mokogitea/workflows/security-audit.yml from template [skip ci] 2026-05-12 05:31:10 +00:00
jmiller f1cfce8f05 chore: sync .mokogitea/workflows/repo-health.yml from template [skip ci] 2026-05-12 05:31:10 +00:00
jmiller ed6f771a1e chore: sync .mokogitea/workflows/pre-release.yml from template [skip ci] 2026-05-12 05:31:10 +00:00
jmiller 5dfc1c9476 chore: sync .mokogitea/workflows/pr-check.yml from template [skip ci] 2026-05-12 05:31:09 +00:00
jmiller b611aaa7e0 chore: sync .mokogitea/workflows/notify.yml from template [skip ci] 2026-05-12 05:31:09 +00:00
jmiller 0c3a11f524 chore: sync .mokogitea/workflows/gitleaks.yml from template [skip ci] 2026-05-12 05:31:09 +00:00
jmiller fa267ebcb9 chore: sync .mokogitea/workflows/deploy-manual.yml from template [skip ci] 2026-05-12 05:31:08 +00:00
jmiller cce326f5c8 chore: sync .mokogitea/workflows/cleanup.yml from template [skip ci] 2026-05-12 05:31:08 +00:00
jmiller 41d674001c chore: sync .mokogitea/workflows/ci-joomla.yml from template [skip ci] 2026-05-12 05:31:08 +00:00
jmiller 2bb6daa405 chore: sync .mokogitea/workflows/cascade-dev.yml from template [skip ci] 2026-05-12 05:31:07 +00:00
jmiller 53d2487fe8 chore: sync .mokogitea/workflows/auto-release.yml from template [skip ci] 2026-05-12 05:31:07 +00:00
jmiller 99a6a14964 chore: sync .mokogitea/ISSUE_TEMPLATE/version.md from template [skip ci] 2026-05-12 05:31:06 +00:00
jmiller b3c4d5102c chore: sync .mokogitea/ISSUE_TEMPLATE/security.md from template [skip ci] 2026-05-12 05:31:06 +00:00
jmiller f901431532 chore: sync .mokogitea/ISSUE_TEMPLATE/rfc.md from template [skip ci] 2026-05-12 05:31:06 +00:00
jmiller c9431fe31e chore: sync .mokogitea/ISSUE_TEMPLATE/question.md from template [skip ci] 2026-05-12 05:31:05 +00:00
jmiller 77e9449e75 chore: sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md from template [skip ci] 2026-05-12 05:31:05 +00:00
jmiller 648daeaa88 chore: sync .mokogitea/ISSUE_TEMPLATE/feature_request.md from template [skip ci] 2026-05-12 05:31:05 +00:00
jmiller fafcfe688c chore: sync .mokogitea/ISSUE_TEMPLATE/documentation.md from template [skip ci] 2026-05-12 05:31:04 +00:00
jmiller 7c544f1a9b chore: sync .mokogitea/ISSUE_TEMPLATE/config.yml from template [skip ci] 2026-05-12 05:31:04 +00:00
jmiller ce494add2e chore: sync .mokogitea/ISSUE_TEMPLATE/bug_report.md from template [skip ci] 2026-05-12 05:31:04 +00:00
jmiller 51527073ab chore: sync .mokogitea/ISSUE_TEMPLATE/adr.md from template [skip ci] 2026-05-12 05:31:03 +00:00
jmiller 13fcc87e0f chore: sync .mokogitea/.moko-platform from template [skip ci] 2026-05-12 05:31:03 +00:00
jmiller 512faf4874 chore: remove .gitea/workflows/update-server.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:57 +00:00
jmiller ab3527ccbc chore: move .gitea/workflows/update-server.yml to .mokogitea/update-server.yml [skip ci] 2026-05-12 04:57:57 +00:00
jmiller 3c67fb586f chore: remove .gitea/workflows/sync-roadmap-wiki.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:56 +00:00
jmiller cf77d37c53 chore: move .gitea/workflows/sync-roadmap-wiki.yml to .mokogitea/sync-roadmap-wiki.yml [skip ci] 2026-05-12 04:57:56 +00:00
jmiller 06ad85e702 chore: remove .gitea/workflows/security-audit.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:56 +00:00
jmiller a633671fe4 chore: move .gitea/workflows/security-audit.yml to .mokogitea/security-audit.yml [skip ci] 2026-05-12 04:57:55 +00:00
jmiller 2f6965c0d9 chore: remove .gitea/workflows/repo-health.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:55 +00:00
jmiller 50d9dc1262 chore: move .gitea/workflows/repo-health.yml to .mokogitea/repo-health.yml [skip ci] 2026-05-12 04:57:55 +00:00
jmiller 5c9b18917c chore: remove .gitea/workflows/pre-release.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:54 +00:00
jmiller 9581a9327e chore: move .gitea/workflows/pre-release.yml to .mokogitea/pre-release.yml [skip ci] 2026-05-12 04:57:54 +00:00
jmiller 6cbf36872e chore: remove .gitea/workflows/pr-check.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:53 +00:00
jmiller 2b265fb21f chore: move .gitea/workflows/pr-check.yml to .mokogitea/pr-check.yml [skip ci] 2026-05-12 04:57:53 +00:00
jmiller 1a6f834a73 chore: remove .gitea/workflows/pr-branch-check.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:53 +00:00
jmiller a715f5ef9c chore: move .gitea/workflows/pr-branch-check.yml to .mokogitea/pr-branch-check.yml [skip ci] 2026-05-12 04:57:52 +00:00
jmiller 21f87c4b9c chore: remove .gitea/workflows/notify.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:52 +00:00
jmiller e7c594f608 chore: move .gitea/workflows/notify.yml to .mokogitea/notify.yml [skip ci] 2026-05-12 04:57:52 +00:00
jmiller eaad4ddde9 chore: remove .gitea/workflows/gitleaks.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:51 +00:00
jmiller 87b22a9c21 chore: move .gitea/workflows/gitleaks.yml to .mokogitea/gitleaks.yml [skip ci] 2026-05-12 04:57:51 +00:00
jmiller 869032a02f chore: remove .gitea/workflows/deploy-manual.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:51 +00:00
jmiller cc02beb68a chore: move .gitea/workflows/deploy-manual.yml to .mokogitea/deploy-manual.yml [skip ci] 2026-05-12 04:57:50 +00:00
jmiller 3ea20894e4 chore: remove .gitea/workflows/cleanup.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:50 +00:00
jmiller 395fee0ac3 chore: move .gitea/workflows/cleanup.yml to .mokogitea/cleanup.yml [skip ci] 2026-05-12 04:57:50 +00:00
jmiller 1a43531baf chore: remove .gitea/workflows/ci-joomla.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:49 +00:00
jmiller e5dd118b30 chore: move .gitea/workflows/ci-joomla.yml to .mokogitea/ci-joomla.yml [skip ci] 2026-05-12 04:57:49 +00:00
jmiller b3e9dce02d chore: remove .gitea/workflows/cascade-dev.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:49 +00:00
jmiller 9cb1aa9507 chore: move .gitea/workflows/cascade-dev.yml to .mokogitea/cascade-dev.yml [skip ci] 2026-05-12 04:57:48 +00:00
jmiller 51dcca076b chore: remove .gitea/workflows/auto-release.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:48 +00:00
jmiller 91b2ee2fd5 chore: move .gitea/workflows/auto-release.yml to .mokogitea/auto-release.yml [skip ci] 2026-05-12 04:57:47 +00:00
jmiller c3077e5509 chore: remove .gitea/.moko-platform (moved to .mokogitea/) [skip ci] 2026-05-12 04:57:47 +00:00
jmiller 65df448186 chore: move .gitea/.moko-platform to .mokogitea/.moko-platform [skip ci] 2026-05-12 04:57:47 +00:00
jmiller 15480eefb4 chore: sync pr-branch-check.yml from Template-Joomla [skip ci] 2026-05-11 21:28:24 +00:00
jmiller 16c0669db7 chore: sync repo-health.yml from Template-Joomla [skip ci] 2026-05-11 21:23:22 +00:00
jmiller 55b6d29c87 chore: sync pre-release.yml from Template-Joomla [skip ci] 2026-05-11 21:23:20 +00:00
jmiller 29fd0d1456 chore: sync notify.yml from Template-Joomla [skip ci] 2026-05-11 21:23:16 +00:00
jmiller a431e8395e chore: sync auto-release.yml from Template-Joomla [skip ci] 2026-05-11 21:23:09 +00:00
jmiller 8d0bcf8378 chore: remove renovate.json [skip ci] 2026-05-10 19:57:27 +00:00
jmiller 0c6657a2f2 Merge pull request 'chore: cascade main → dev (73691de) [skip ci]' (#13) from main into dev 2026-05-10 19:14:24 +00:00
jmiller 73691de227 docs: comprehensive README with full endpoint tables, examples, and query params
Cascade Main → Dev / Cascade main → branches (push) Successful in 2s
Repo Health / Access control (push) Successful in 0s
Repo Health / Release configuration (push) Successful in 2s
Repo Health / Scripts governance (push) Successful in 2s
Repo Health / Repository health (push) Failing after 3s
Repository Cleanup / Clean Merged Branches (push) Successful in 5s
Secret Scanning / Gitleaks Secret Scan (push) Failing after 12s
Sync Roadmap to Wiki / Generate Roadmap Wiki (push) Successful in 4s
Security Audit / Dependency Audit (push) Successful in 3s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-10 19:14:19 +00:00
jmiller d65eee67fa Merge pull request 'chore: cascade main → dev (6e86799) [skip ci]' (#12) from main into dev 2026-05-10 18:44:23 +00:00
jmiller 6e86799bb0 docs: update README from wiki Home
Repo Health / Access control (push) Successful in 1s
Cascade Main → Dev / Cascade main → branches (push) Successful in 2s
Repo Health / Release configuration (push) Successful in 3s
Repo Health / Scripts governance (push) Successful in 3s
Repo Health / Repository health (push) Failing after 3s
2026-05-10 18:39:22 +00:00
jmiller 7f121512b2 chore: sync updates.xml 03.02.00 [skip ci] 2026-05-10 00:34:11 +00:00
gitea-actions[bot] 2da34f3376 chore(release): ZIP + tar.gz for 03.02.00 [skip ci] 2026-05-10 00:34:11 +00:00
gitea-actions[bot] 53dd1a7afa chore(release): build 03.02.00 [skip ci] 2026-05-10 00:34:10 +00:00
jmiller b945deacfb Merge pull request 'chore: cascade main → dev (5a5637f) [skip ci]' (#11) from main into dev 2026-05-09 22:14:38 +00:00
jmiller 83bfce3ec4 Merge pull request 'chore: cascade main → dev (2effa61) [skip ci]' (#10) from main into dev 2026-05-09 18:27:00 +00:00
jmiller 8fc692adc7 Merge pull request 'chore: cascade main → dev (d3dc424) [skip ci]' (#9) from main into dev 2026-05-09 18:20:32 +00:00
9 changed files with 1596 additions and 137 deletions
File diff suppressed because it is too large Load Diff
+181 -19
View File
@@ -151,13 +151,22 @@ jobs:
sed -i "s|<creationDate>[^<]*</creationDate>|<creationDate>${TODAY}</creationDate>|" "$MANIFEST"
fi
# Promote [Unreleased] section in CHANGELOG.md to new version
if [ -f "CHANGELOG.md" ] && grep -qi "Unreleased" CHANGELOG.md; then
sed -i "s|## \[Unreleased\]|## [${VERSION}] --- ${TODAY}|" CHANGELOG.md
sed -i "s|## Unreleased|## [${VERSION}] --- ${TODAY}|" CHANGELOG.md
sed -i "2i ## [Unreleased]" CHANGELOG.md
sed -i "3i \\ " CHANGELOG.md
echo "CHANGELOG promoted to [${VERSION}]"
fi
# Commit and push
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
git add -A
git diff --cached --quiet || {
git commit -m "chore(version): bump ${CURRENT} → ${VERSION} (minor) [skip ci]"
git commit -m "chore(version): bump ${CURRENT} → ${VERSION} [skip ci]"
git push origin HEAD:main 2>&1
}
@@ -311,6 +320,7 @@ jobs:
# -- STEP 5: Write updates.xml (Joomla update server) ---------------------
- name: "Step 5: Write updates.xml"
id: updates
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.already_released != 'true'
@@ -334,20 +344,44 @@ jobs:
TARGET_PLATFORM=$(sed -n 's/.*\(<targetplatform[^/]*\/>\).*/\1/p' "$MANIFEST" | head -1)
PHP_MINIMUM=$(sed -n 's/.*<php_minimum>\([^<]*\)<\/php_minimum>.*/\1/p' "$MANIFEST" | head -1)
# If EXT_NAME is a language key (e.g. PLG_SYSTEM_MOKOJGDPC), resolve from .ini
if echo "$EXT_NAME" | grep -qE '^[A-Z_]+$'; then
INI_NAME=$(find . -name "*.sys.ini" -path "*/en-GB/*" -exec grep -h "^${EXT_NAME}=" {} \; 2>/dev/null | head -1 | cut -d'"' -f2)
[ -z "$INI_NAME" ] && INI_NAME=$(find . -name "*.sys.ini" -exec grep -h "^${EXT_NAME}=" {} \; 2>/dev/null | head -1 | cut -d'"' -f2)
[ -n "$INI_NAME" ] && EXT_NAME="$INI_NAME"
fi
# Fallbacks
[ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
[ -z "$EXT_TYPE" ] && EXT_TYPE="component"
# Derive element if not in manifest:
# 1. Try XML filename (e.g. mokowaas.xml → mokowaas)
# 2. Fall back to repo name (lowercased)
# 1. plugin="xxx" attribute (plugins)
# 2. module="xxx" attribute (modules)
# 3. XML filename (components, packages)
# 4. Repo name fallback (templates, anything else)
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
EXT_ELEMENT=$(sed -n 's/.*plugin="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
fi
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(sed -n 's/.*module="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
fi
if [ -z "$EXT_ELEMENT" ]; then
FNAME=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
# If filename is generic (templateDetails, manifest), use repo name
case "$EXT_ELEMENT" in
templatedetails|manifest|*.xml) EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
case "$FNAME" in
templatedetails|manifest) EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
*) EXT_ELEMENT="$FNAME" ;;
esac
fi
# Final fallback
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
# Save for Steps 7, 8, 8b
echo "ext_element=${EXT_ELEMENT}" >> "$GITHUB_OUTPUT"
echo "ext_name=${EXT_NAME}" >> "$GITHUB_OUTPUT"
echo "ext_type=${EXT_TYPE}" >> "$GITHUB_OUTPUT"
echo "ext_folder=${EXT_FOLDER}" >> "$GITHUB_OUTPUT"
# Build client tag: plugins and frontend modules need <client>site</client>
CLIENT_TAG=""
@@ -374,7 +408,18 @@ jobs:
PHP_TAG="<php_minimum>${PHP_MINIMUM}</php_minimum>"
fi
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/stable/${EXT_ELEMENT}-${VERSION}.zip"
# Build TYPE_PREFIX for download URL
TYPE_PREFIX=""
case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
module) TYPE_PREFIX="mod_" ;;
component) TYPE_PREFIX="com_" ;;
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
esac
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/stable/${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/stable"
# -- Build update entry for a given stability tag
@@ -469,21 +514,32 @@ jobs:
MAJOR="${{ steps.version.outputs.major }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# Auto-detect extension element for release naming
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
EXT_ELEMENT=""
if [ -n "$MANIFEST" ]; then
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
[ -z "$EXT_ELEMENT" ] && 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
else
# Reuse metadata from Step 5 (single source of truth)
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
EXT_NAME="${{ steps.updates.outputs.ext_name }}"
EXT_TYPE="${{ steps.updates.outputs.ext_type }}"
EXT_FOLDER="${{ steps.updates.outputs.ext_folder }}"
# Fallbacks if Step 5 was skipped
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
fi
[ -z "$EXT_NAME" ] && EXT_NAME="${GITEA_REPO}"
NOTES=$(php /tmp/mokostandards-api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
RELEASE_NAME="${EXT_ELEMENT} ${VERSION} (stable)"
# Build release name: "Pretty Name VERSION (type_element-VERSION)"
TYPE_PREFIX=""
case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
module) TYPE_PREFIX="mod_" ;;
component) TYPE_PREFIX="com_" ;;
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
esac
RELEASE_NAME="${EXT_NAME} ${VERSION} (${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION})"
# Delete existing release if present (overwrite, not append)
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
@@ -533,9 +589,28 @@ jobs:
MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)
[ -z "$MANIFEST" ] && exit 0
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1 || basename "$MANIFEST" .xml)
ZIP_NAME="${EXT_ELEMENT}-${VERSION}.zip"
TAR_NAME="${EXT_ELEMENT}-${VERSION}.tar.gz"
# Reuse element from Step 5, with same fallback chain
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(sed -n 's/.*<element>\([^<]*\)<\/element>.*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(sed -n 's/.*plugin="\([^"]*\)".*/\1/p' "$MANIFEST" 2>/dev/null | head -1)
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
[ -z "$EXT_ELEMENT" ] && EXT_ELEMENT=$(echo "${GITEA_REPO}" | tr '[:upper:]' '[:lower:]' | tr -d ' -')
fi
# ZIP name: type_folder_element-VERSION (e.g. plg_system_mokojgdpc-01.01.00.zip)
EXT_TYPE=$(sed -n 's/.*<extension[^>]*type="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
EXT_FOLDER=$(sed -n 's/.*<extension[^>]*group="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
TYPE_PREFIX=""
case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
module) TYPE_PREFIX="mod_" ;;
component) TYPE_PREFIX="com_" ;;
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
esac
ZIP_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
TAR_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.tar.gz"
# -- Build install packages from src/ ----------------------------
SOURCE_DIR="src"
@@ -675,6 +750,73 @@ jobs:
echo "| Release | \`${RELEASE_TAG}\` | |" >> $GITHUB_STEP_SUMMARY
echo "| Download | [${ZIP_NAME}](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/${RELEASE_TAG}/${ZIP_NAME}) |" >> $GITHUB_STEP_SUMMARY
# -- STEP 8b: Update release description with changelog + SHA ----------------
- name: "Step 8b: Update release body with changelog and SHA"
if: steps.version.outputs.skip != 'true'
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
EXT_ELEMENT="${{ steps.updates.outputs.ext_element }}"
EXT_TYPE="${{ steps.updates.outputs.ext_type }}"
EXT_FOLDER="${{ steps.updates.outputs.ext_folder }}"
# Build TYPE_PREFIX to match Step 8's ZIP naming
TYPE_PREFIX=""
case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
module) TYPE_PREFIX="mod_" ;;
component) TYPE_PREFIX="com_" ;;
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
esac
ZIP_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
TAR_NAME="${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.tar.gz"
# Get SHA from the built files
SHA256_ZIP=""
[ -f "/tmp/${ZIP_NAME}" ] && SHA256_ZIP=$(sha256sum "/tmp/${ZIP_NAME}" | cut -d' ' -f1)
SHA256_TAR=""
[ -f "/tmp/${TAR_NAME}" ] && SHA256_TAR=$(sha256sum "/tmp/${TAR_NAME}" | cut -d' ' -f1)
# Extract latest changelog entry (strip the ## header to avoid duplicate)
CHANGELOG=""
if [ -f "CHANGELOG.md" ]; then
CHANGELOG=$(sed -n "/^## \[*${VERSION}/,/^## \[*[0-9]/p" CHANGELOG.md | sed '$d' | sed '1d')
[ -z "$CHANGELOG" ] && CHANGELOG=$(sed -n '/^## /,/^## /p' CHANGELOG.md | sed '$d' | sed '1d' | head -30)
fi
# Build release body (single header, no duplicate from changelog)
BODY="## ${VERSION} ($(date +%Y-%m-%d))\n\n"
if [ -n "$CHANGELOG" ]; then
BODY="${BODY}${CHANGELOG}\n\n"
fi
BODY="${BODY}---\n\n### Checksums\n\n"
BODY="${BODY}| File | SHA-256 |\n|------|--------|\n"
[ -n "$SHA256_ZIP" ] && BODY="${BODY}| \`${ZIP_NAME}\` | \`${SHA256_ZIP}\` |\n"
[ -n "$SHA256_TAR" ] && BODY="${BODY}| \`${TAR_NAME}\` | \`${SHA256_TAR}\` |\n"
# Get release ID and update body
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
"${API_BASE}/releases/tags/${RELEASE_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
python3 -c "
import json, urllib.request
body = '''$(printf '%b' "$BODY")'''
data = json.dumps({'body': body}).encode()
req = urllib.request.Request(
'${API_BASE}/releases/${RELEASE_ID}',
data=data,
headers={'Authorization': 'token ${{ secrets.GA_TOKEN }}', 'Content-Type': 'application/json'},
method='PATCH'
)
urllib.request.urlopen(req)
" 2>/dev/null && echo "Release body updated with changelog + SHA" >> $GITHUB_STEP_SUMMARY
fi
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
- name: "Step 9: Mirror release to GitHub"
if: >-
@@ -764,6 +906,26 @@ jobs:
done
echo "Cleaned up ${DELETED} pre-release channel(s)" >> $GITHUB_STEP_SUMMARY
# -- STEP 11: Reset dev branch from main ------------------------------------
- name: "Step 11: Delete and recreate dev branch from main"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.GA_TOKEN }}"
# Delete dev branch
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
# Recreate dev from main (now includes version bump + changelog promotion)
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API_BASE}/branches" \
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
echo "Dev branch reset from main (keeps dev ahead after release)" >> $GITHUB_STEP_SUMMARY
# -- Summary --------------------------------------------------------------
- name: Pipeline Summary
if: always()
+1
View File
@@ -18,6 +18,7 @@ on:
- "Joomla Build & Release"
- "Joomla Extension CI"
- "Deploy"
- "Cascade Main → Dev"
types:
- completed
+90
View File
@@ -0,0 +1,90 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Enforces branch merge policy:
# feature/* → dev only
# fix/* → dev only
# hotfix/* → dev or main (emergency)
# dev → main only
# alpha/* → dev only
# beta/* → dev only
# rc/* → main only
name: Branch Policy Check
on:
pull_request:
types: [opened, synchronize, reopened, edited]
jobs:
check-target:
name: Verify merge target
runs-on: ubuntu-latest
steps:
- name: Check branch policy
run: |
HEAD="${{ github.head_ref }}"
BASE="${{ github.base_ref }}"
echo "PR: ${HEAD} → ${BASE}"
ALLOWED=true
REASON=""
case "$HEAD" in
feature/*|feat/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Feature branches must target 'dev', not '${BASE}'"
fi
;;
fix/*|bugfix/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Fix branches must target 'dev', not '${BASE}'"
fi
;;
hotfix/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'"
fi
;;
alpha/*|beta/*)
if [ "$BASE" != "dev" ]; then
ALLOWED=false
REASON="Pre-release branches must target 'dev', not '${BASE}'"
fi
;;
rc/*)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Release candidate branches must target 'main', not '${BASE}'"
fi
;;
dev)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Dev branch can only merge into 'main', not '${BASE}'"
fi
;;
esac
if [ "$ALLOWED" = false ]; then
echo "::error::${REASON}"
echo ""
echo "## Branch Policy Violation" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
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
exit 1
fi
echo "Branch policy: OK (${HEAD} → ${BASE})"
echo "## Branch Policy: Passed" >> $GITHUB_STEP_SUMMARY
+23 -1
View File
@@ -278,7 +278,7 @@ jobs:
f.write(content)
PYEOF
# Commit and push
# Commit and push to current branch
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]"
@@ -287,6 +287,28 @@ jobs:
git push origin HEAD 2>&1 || echo "WARNING: push failed"
fi
- name: "Sync updates.xml to all branches"
run: |
CURRENT_BRANCH="${{ github.ref_name }}"
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
# Sync updates.xml to main and dev (whichever isn't current)
for BRANCH in main dev; do
[ "$BRANCH" = "$CURRENT_BRANCH" ] && continue
echo "Syncing updates.xml → ${BRANCH}"
git fetch origin "${BRANCH}" 2>/dev/null || continue
git checkout "origin/${BRANCH}" -- . 2>/dev/null || continue
git checkout "${CURRENT_BRANCH}" -- updates.xml
if ! git diff --quiet updates.xml 2>/dev/null; then
git add updates.xml
git commit -m "chore: sync updates.xml from ${CURRENT_BRANCH} [skip ci]"
git push origin HEAD:refs/heads/${BRANCH} 2>&1 || echo "WARNING: push to ${BRANCH} failed"
fi
git checkout "${CURRENT_BRANCH}" 2>/dev/null
done
- name: "Delete lesser pre-release channels (cascade)"
continue-on-error: true
run: |
+5 -4
View File
@@ -54,7 +54,7 @@ env:
# Repo health policy
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.gitea/workflows/
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
REPO_DISALLOWED_DIRS:
REPO_DISALLOWED_FILES: TODO.md,todo.md
@@ -62,7 +62,7 @@ env:
EXTENDED_CHECKS: "true"
# File / directory variables
DOCS_INDEX: ""
DOCS_INDEX: docs/docs-index.md
SCRIPT_DIR: scripts
WORKFLOWS_DIR: .gitea/workflows
SHELLCHECK_PATTERN: '*.sh'
@@ -450,11 +450,12 @@ jobs:
fi
done < <(git branch -r --list 'origin/dev*' | sed 's/^ *//')
if [ "${#dev_paths[@]}" -eq 0 ] && [ "${#dev_branches[@]}" -eq 0 ]; then
missing_required+=("dev branch")
if [ "${#dev_paths[@]}" -eq 0 ]; then
missing_required+=("dev/* branch (e.g. dev/01.00.00)")
fi
if [ "${#dev_branches[@]}" -gt 0 ]; then
missing_required+=("invalid branch dev (must be dev/<version>)")
fi
content_warnings=()
+246 -71
View File
@@ -1,94 +1,269 @@
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
# FILE INFORMATION
DEFGROUP: MokoDPCalendarAPI.Documentation
INGROUP: MokoDPCalendarAPI
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI
VERSION: 03.02.00
PATH: ./README.md
BRIEF: Joomla Web Services plugin for DPCalendar
-->
[![Version](https://img.shields.io/badge/version-01.00.00-blue.svg?logo=v&logoColor=white)](https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/tag/stable)
[![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green.svg?logo=gnu&logoColor=white)](LICENSE)
[![PHP](https://img.shields.io/badge/PHP-8.1%2B-777BB4.svg?logo=php&logoColor=white)](https://www.php.net)
# MokoDPCalendarAPI
A Joomla 5/6 Web Services plugin that exposes DPCalendar events, calendars, and locations through the Joomla REST API (`/api/index.php/v1`).
Joomla Web Services plugin exposing **18 REST endpoints** for DPCalendar events, calendars, locations, bookings, and tickets.
Enables AI assistants (via joomla-api-mcp) and external integrations to create, read, update, and delete DPCalendar content programmatically.
![PHP 8.1+](https://img.shields.io/badge/PHP-8.1%2B-777BB4?style=flat-square&logo=php&logoColor=white) ![Joomla 5.x/6.x](https://img.shields.io/badge/Joomla-5.x%20%7C%206.x-5091CD?style=flat-square&logo=joomla&logoColor=white) ![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green?style=flat-square) ![Version](https://img.shields.io/badge/version-03.01.00-blue?style=flat-square) ![Wiki](https://img.shields.io/badge/wiki-MokoDPCalendarAPI-blue?style=flat-square)
## Table of Contents
---
- [Background](#background)
- [Install](#install)
- [API Endpoints](#api-endpoints)
- [Contributing](#contributing)
- [License](#license)
## Features
## Background
- **18 REST endpoints** across 5 resources (events, calendars, locations, bookings, tickets)
- **CRUD operations** for events including bulk creation
- **iCal export** for events and calendars (`.ics` format)
- **Recurring event expansion** -- RRULE processing with EXDATE support
- **Pagination** with `limit`/`offset` (max 100 per page)
- **Sorting** by 6 fields with ascending/descending order
- **Filtering** by date range, category, search term, featured, access level, language
- **Field selection** -- request only the fields you need
- **Location expansion** -- inline location data with events via `expand=locations`
- **ETag caching** with HTTP 304 Not Modified support
- **CORS headers** for cross-origin requests
DPCalendar does not ship with a Web Services plugin. This plugin fills that gap by registering REST API routes for:
---
- **Events** — CRUD with date filtering, category scoping, and recurrence support
- **Calendars** — List and manage calendar categories
- **Locations** — List and manage event locations
## Requirements
## Install
| Requirement | Version |
|---|---|
| **PHP** | 8.1+ |
| **Joomla** | 5.x or 6.x |
| **DPCalendar** | Required (component must be installed) |
1. Download the latest release ZIP
2. **System > Install > Extensions** in Joomla admin
3. Upload and install the ZIP
4. **System > Manage > Plugins** — enable **Web Services - DPCalendar**
---
## API Endpoints
## Installation
All endpoints require `Authorization: Bearer <token>`.
1. Download the latest release package from [Releases](https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases)
2. In Joomla Admin, go to **System > Install > Extensions**
3. Upload the `.zip` package
4. Navigate to **System > Plugins** and search for `"Web Services - DPCalendar"`
5. Enable the plugin
### Events
See the [INSTALLATION](https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/wiki/INSTALLATION) wiki page for detailed instructions.
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/v1/dpcalendar/events` | List events |
| GET | `/v1/dpcalendar/events/{id}` | Get event |
| POST | `/v1/dpcalendar/events` | Create event |
| PATCH | `/v1/dpcalendar/events/{id}` | Update event |
| DELETE | `/v1/dpcalendar/events/{id}` | Delete event |
---
### Calendars
## Authentication
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/v1/dpcalendar/calendars` | List calendars |
| GET | `/v1/dpcalendar/calendars/{id}` | Get calendar |
All API requests require a Joomla API token passed via the `Authorization` header:
### Locations
```
Authorization: Bearer <your-joomla-api-token>
```
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/v1/dpcalendar/locations` | List locations |
| GET | `/v1/dpcalendar/locations/{id}` | Get location |
| POST | `/v1/dpcalendar/locations` | Create location |
| PATCH | `/v1/dpcalendar/locations/{id}` | Update location |
| DELETE | `/v1/dpcalendar/locations/{id}` | Delete location |
Generate a token in **Joomla Admin > Users > Manage > [User] > Joomla API Token tab**.
---
## Endpoints
Base path: `/api/index.php/v1`
### Events (8 endpoints)
| Method | Path | Description |
|---|---|---|
| `GET` | `/dpcalendar/events` | List events with filtering, sorting, pagination |
| `GET` | `/dpcalendar/events/{id}` | Get a single event by ID |
| `POST` | `/dpcalendar/events` | Create a new event |
| `POST` | `/dpcalendar/events/bulk` | Bulk create multiple events |
| `PATCH` | `/dpcalendar/events/{id}` | Update an existing event |
| `DELETE` | `/dpcalendar/events/{id}` | Trash an event (soft delete) |
| `GET` | `/dpcalendar/events/{id}/ical` | Export event as iCal (.ics) |
| `GET` | `/dpcalendar/events/{id}/occurrences` | List occurrences of a recurring event |
### Calendars (3 endpoints)
| Method | Path | Description |
|---|---|---|
| `GET` | `/dpcalendar/calendars` | List all calendars |
| `GET` | `/dpcalendar/calendars/{id}` | Get a single calendar by ID |
| `GET` | `/dpcalendar/calendars/{id}/ical` | Export calendar as iCal (.ics) |
### Locations (2 endpoints)
| Method | Path | Description |
|---|---|---|
| `GET` | `/dpcalendar/locations` | List all locations |
| `GET` | `/dpcalendar/locations/{id}` | Get a single location by ID |
### Bookings (2 endpoints)
| Method | Path | Description |
|---|---|---|
| `GET` | `/dpcalendar/bookings` | List all bookings |
| `GET` | `/dpcalendar/bookings/{id}` | Get a single booking (with tickets) |
### Tickets (2 endpoints)
| Method | Path | Description |
|---|---|---|
| `GET` | `/dpcalendar/tickets` | List all tickets |
| `GET` | `/dpcalendar/tickets/{id}` | Get a single ticket |
---
## Query Parameters
### Pagination
| Parameter | Type | Default | Description |
|---|---|---|---|
| `page[limit]` | integer | 20 | Results per page (max 100) |
| `page[offset]` | integer | 0 | Number of results to skip |
### Sorting
| Parameter | Type | Description |
|---|---|---|
| `sort` | string | Sort field. Prefix with `-` for descending. |
**Supported sort fields:** `id`, `title`, `start_date`, `end_date`, `catid`, `created`
Example: `?sort=-start_date` (newest first)
### Filtering
| Parameter | Type | Description |
|---|---|---|
| `filter[search]` | string | Search events by title or description |
| `filter[start_date]` | string | Events starting on or after this date (ISO 8601) |
| `filter[end_date]` | string | Events ending on or before this date (ISO 8601) |
| `filter[catid]` | integer | Filter by calendar/category ID |
| `filter[featured]` | integer | `1` = featured only, `0` = non-featured only |
| `filter[access]` | integer | Filter by Joomla access level |
| `filter[language]` | string | Filter by language tag (e.g., `en-GB`) |
### Field Selection
| Parameter | Type | Description |
|---|---|---|
| `fields[events]` | string | Comma-separated list of fields to return |
Example: `?fields[events]=id,title,start_date,end_date`
### Expansion
| Parameter | Type | Description |
|---|---|---|
| `expand` | string | Include related data. Supported: `locations` |
---
## Examples
### List upcoming events
```bash
curl -s \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.api+json" \
"https://example.com/api/index.php/v1/dpcalendar/events?filter[start_date]=2026-01-01&sort=start_date&page[limit]=10"
```
### Get a single event
```bash
curl -s \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.api+json" \
"https://example.com/api/index.php/v1/dpcalendar/events/42"
```
### Create an event
```bash
curl -s -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.api+json" \
-d '{
"title": "Monthly Meetup",
"catid": 8,
"start_date": "2026-06-15 18:00:00",
"end_date": "2026-06-15 20:00:00",
"description": "<p>Join us for the monthly meetup!</p>"
}' \
"https://example.com/api/index.php/v1/dpcalendar/events"
```
### Bulk create events
```bash
curl -s -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/vnd.api+json" \
-d '[
{"title": "Event A", "catid": 8, "start_date": "2026-07-01 10:00:00", "end_date": "2026-07-01 12:00:00"},
{"title": "Event B", "catid": 8, "start_date": "2026-07-02 10:00:00", "end_date": "2026-07-02 12:00:00"}
]' \
"https://example.com/api/index.php/v1/dpcalendar/events/bulk"
```
### Export calendar as iCal
```bash
curl -s \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: text/calendar" \
"https://example.com/api/index.php/v1/dpcalendar/calendars/8/ical"
```
### Get recurring event occurrences
```bash
curl -s \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.api+json" \
"https://example.com/api/index.php/v1/dpcalendar/events/42/occurrences"
```
### List events with location expansion
```bash
curl -s \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.api+json" \
"https://example.com/api/index.php/v1/dpcalendar/events?expand=locations"
```
### ETag caching (conditional request)
```bash
# First request -- note the ETag in response headers
curl -sI \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.api+json" \
"https://example.com/api/index.php/v1/dpcalendar/events"
# Subsequent request -- returns 304 if unchanged
curl -s \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/vnd.api+json" \
-H 'If-None-Match: "etag-value-from-previous-response"' \
"https://example.com/api/index.php/v1/dpcalendar/events"
```
---
## Documentation
Full documentation is available on the [Wiki](https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/wiki), including:
| Page | Description |
|---|---|
| [Home](https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/wiki/Home) | Overview and quick reference |
| [INSTALLATION](https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/wiki/INSTALLATION) | Installation guide for Joomla 5.x/6.x |
| [API-Reference](https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/wiki/API-Reference) | Complete endpoint documentation |
---
## License
GPL-3.0-or-later see [LICENSE](LICENSE).
This project is licensed under the GNU General Public License v3.0 or later -- see the [LICENSE](LICENSE) file.
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
---
## Maintainers
[@jmiller](https://git.mokoconsulting.tech/jmiller)
## Revision History
| Date | Version | Author | Notes |
| --- | --- | --- | --- |
| 2026-04-26 | 1.0.0 | jmiller | Initial Web Services plugin for DPCalendar |
*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
-26
View File
@@ -1,26 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
"schedule:weekly",
":disableDependencyDashboard"
],
"labels": ["dependencies"],
"automerge": false,
"platformAutomerge": false,
"rangeStrategy": "bump",
"packageRules": [
{
"matchUpdateTypes": ["patch"],
"automerge": true
},
{
"matchManagers": ["composer"],
"enabled": true
},
{
"matchManagers": ["npm"],
"enabled": true
}
]
}
+16 -16
View File
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
VERSION: 03.01.00
VERSION: 03.02.00
-->
<updates>
@@ -10,15 +10,15 @@
<description>Moko Web Services - DPCalendar API update</description>
<element>mokodpcalendarapi</element>
<type>plugin</type>
<version>03.01.00</version>
<version>03.02.00</version>
<client>site</client>
<folder>webservices</folder>
<tags><tag>development</tag></tags>
<infourl title="Moko Web Services - DPCalendar API">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/-03.02.00.zip</downloadurl>
</downloads>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</sha256>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
@@ -28,15 +28,15 @@
<description>Moko Web Services - DPCalendar API update</description>
<element>mokodpcalendarapi</element>
<type>plugin</type>
<version>03.01.00</version>
<version>03.02.00</version>
<client>site</client>
<folder>webservices</folder>
<tags><tag>alpha</tag></tags>
<infourl title="Moko Web Services - DPCalendar API">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/-03.02.00.zip</downloadurl>
</downloads>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</sha256>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
@@ -46,15 +46,15 @@
<description>Moko Web Services - DPCalendar API update</description>
<element>mokodpcalendarapi</element>
<type>plugin</type>
<version>03.01.00</version>
<version>03.02.00</version>
<client>site</client>
<folder>webservices</folder>
<tags><tag>beta</tag></tags>
<infourl title="Moko Web Services - DPCalendar API">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/-03.02.00.zip</downloadurl>
</downloads>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</sha256>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
@@ -64,15 +64,15 @@
<description>Moko Web Services - DPCalendar API update</description>
<element>mokodpcalendarapi</element>
<type>plugin</type>
<version>03.01.00</version>
<version>03.02.00</version>
<client>site</client>
<folder>webservices</folder>
<tags><tag>rc</tag></tags>
<infourl title="Moko Web Services - DPCalendar API">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/-03.02.00.zip</downloadurl>
</downloads>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</sha256>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
@@ -82,15 +82,15 @@
<description>Moko Web Services - DPCalendar API update</description>
<element>mokodpcalendarapi</element>
<type>plugin</type>
<version>03.01.00</version>
<version>03.02.00</version>
<client>site</client>
<folder>webservices</folder>
<tags><tag>stable</tag></tags>
<infourl title="Moko Web Services - DPCalendar API">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/tag/stable</infourl>
<downloads>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/-03.02.00.zip</downloadurl>
</downloads>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</sha256>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>