162 Commits

Author SHA1 Message Date
jmiller f0f3aee10d chore: force-sync .mokogitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-12 19:16:43 +00:00
jmiller bb7140f170 chore: force-sync .mokogitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-12 19:16:42 +00:00
jmiller a4e9e651c0 chore: force-sync .mokogitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-12 19:16:42 +00:00
jmiller bde393330a chore: force-sync .mokogitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-12 19:16:42 +00:00
jmiller e12637abf4 chore: force-sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md [skip ci] 2026-05-12 19:16:41 +00:00
jmiller b92679c8f8 chore: force-sync .mokogitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-12 19:16:41 +00:00
jmiller 36b97cf029 chore: force-sync .mokogitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-12 19:16:40 +00:00
jmiller 729880ea7a chore: force-sync .mokogitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-12 19:16:40 +00:00
jmiller a9588965ad chore: force-sync .mokogitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-12 19:16:39 +00:00
jmiller 519820e93e chore: force-sync .mokogitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-12 19:16:39 +00:00
jmiller 1372dd1c32 chore: force-sync .mokogitea/workflows/update-server.yml [skip ci] 2026-05-12 19:16:38 +00:00
jmiller 53729796b8 chore: force-sync .mokogitea/workflows/security-audit.yml [skip ci] 2026-05-12 19:16:38 +00:00
jmiller ac150020fb chore: force-sync .mokogitea/workflows/repo-health.yml [skip ci] 2026-05-12 19:16:38 +00:00
jmiller b49afdde6d chore: force-sync .mokogitea/workflows/pre-release.yml [skip ci] 2026-05-12 19:16:37 +00:00
jmiller 468e8a0695 chore: force-sync .mokogitea/workflows/pr-check.yml [skip ci] 2026-05-12 19:16:37 +00:00
jmiller 6aedeb4979 chore: force-sync .mokogitea/workflows/notify.yml [skip ci] 2026-05-12 19:16:36 +00:00
jmiller 9bb63d3c23 chore: force-sync .mokogitea/workflows/gitleaks.yml [skip ci] 2026-05-12 19:16:36 +00:00
jmiller 4b4f7687f5 chore: force-sync .mokogitea/workflows/deploy-manual.yml [skip ci] 2026-05-12 19:16:36 +00:00
jmiller 803c38bc53 chore: force-sync .mokogitea/workflows/cleanup.yml [skip ci] 2026-05-12 19:16:35 +00:00
jmiller da665c4d08 chore: force-sync .mokogitea/workflows/ci-joomla.yml [skip ci] 2026-05-12 19:16:35 +00:00
jmiller beaaa8f26f chore: force-sync .mokogitea/workflows/cascade-dev.yml [skip ci] 2026-05-12 19:16:34 +00:00
jmiller ad0cac5342 chore: force-sync .mokogitea/workflows/auto-release.yml [skip ci] 2026-05-12 19:16:34 +00:00
jmiller 3eb7aac2d8 chore: force-sync .mokogitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-12 19:11:13 +00:00
jmiller 3f71a03a61 chore: force-sync .mokogitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-12 19:11:13 +00:00
jmiller 2ca3196058 chore: force-sync .mokogitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-12 19:11:13 +00:00
jmiller 0095c87682 chore: force-sync .mokogitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-12 19:11:12 +00:00
jmiller ddd1e974aa chore: force-sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md [skip ci] 2026-05-12 19:11:12 +00:00
jmiller cdb9b882f7 chore: force-sync .mokogitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-12 19:11:11 +00:00
jmiller 839ca4028a chore: force-sync .mokogitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-12 19:11:11 +00:00
jmiller 7587be2086 chore: force-sync .mokogitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-12 19:11:11 +00:00
jmiller 59cdbc3017 chore: force-sync .mokogitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-12 19:11:10 +00:00
jmiller 4f159f8134 chore: force-sync .mokogitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-12 19:11:10 +00:00
jmiller 3032b3753f chore: force-sync .mokogitea/workflows/update-server.yml [skip ci] 2026-05-12 19:11:10 +00:00
jmiller c2e6fe8983 chore: force-sync .mokogitea/workflows/security-audit.yml [skip ci] 2026-05-12 19:11:09 +00:00
jmiller d64715a485 chore: force-sync .mokogitea/workflows/repo-health.yml [skip ci] 2026-05-12 19:11:09 +00:00
jmiller 4a29ed7a27 chore: force-sync .mokogitea/workflows/pre-release.yml [skip ci] 2026-05-12 19:11:08 +00:00
jmiller 89ca0d7be4 chore: force-sync .mokogitea/workflows/pr-check.yml [skip ci] 2026-05-12 19:11:08 +00:00
jmiller 47ba4dd6c9 chore: force-sync .mokogitea/workflows/notify.yml [skip ci] 2026-05-12 19:11:08 +00:00
jmiller 89406b96be chore: force-sync .mokogitea/workflows/gitleaks.yml [skip ci] 2026-05-12 19:11:07 +00:00
jmiller 314156b985 chore: force-sync .mokogitea/workflows/deploy-manual.yml [skip ci] 2026-05-12 19:11:07 +00:00
jmiller 9fe3d72ac8 chore: force-sync .mokogitea/workflows/cleanup.yml [skip ci] 2026-05-12 19:11:06 +00:00
jmiller df6c37490f chore: force-sync .mokogitea/workflows/ci-joomla.yml [skip ci] 2026-05-12 19:11:06 +00:00
jmiller 168bcc54d4 chore: force-sync .mokogitea/workflows/cascade-dev.yml [skip ci] 2026-05-12 19:11:06 +00:00
jmiller 16bccd24ac chore: force-sync .mokogitea/workflows/auto-release.yml [skip ci] 2026-05-12 19:11:05 +00:00
jmiller 910f587387 chore: remove .mokogitea/.moko-platform [skip ci] 2026-05-12 19:08:55 +00:00
jmiller 7d647e549d chore: force-sync .mokogitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-12 19:08:54 +00:00
jmiller eee4aa0453 chore: force-sync .mokogitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-12 19:08:54 +00:00
jmiller 4519a9bb4e chore: force-sync .mokogitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-12 19:08:54 +00:00
jmiller 1041a65e61 chore: force-sync .mokogitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-12 19:08:53 +00:00
jmiller a496a5ec56 chore: force-sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md [skip ci] 2026-05-12 19:08:53 +00:00
jmiller 791e33f8c1 chore: force-sync .mokogitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-12 19:08:52 +00:00
jmiller 6db20c0a08 chore: force-sync .mokogitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-12 19:08:52 +00:00
jmiller f1e9c44ffd chore: force-sync .mokogitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-12 19:08:52 +00:00
jmiller 56b63e91d3 chore: force-sync .mokogitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-12 19:08:51 +00:00
jmiller 9abb8865a8 chore: force-sync .mokogitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-12 19:08:51 +00:00
jmiller ddfad0d05d chore: force-sync .mokogitea/workflows/update-server.yml [skip ci] 2026-05-12 19:08:50 +00:00
jmiller 7f82cd0800 chore: force-sync .mokogitea/workflows/security-audit.yml [skip ci] 2026-05-12 19:08:50 +00:00
jmiller 4df61b589f chore: force-sync .mokogitea/workflows/repo-health.yml [skip ci] 2026-05-12 19:08:50 +00:00
jmiller ed96db882d chore: force-sync .mokogitea/workflows/pre-release.yml [skip ci] 2026-05-12 19:08:49 +00:00
jmiller e6c972a457 chore: force-sync .mokogitea/workflows/pr-check.yml [skip ci] 2026-05-12 19:08:49 +00:00
jmiller 0748bc2e8a chore: force-sync .mokogitea/workflows/notify.yml [skip ci] 2026-05-12 19:08:48 +00:00
jmiller d621878fb1 chore: force-sync .mokogitea/workflows/gitleaks.yml [skip ci] 2026-05-12 19:08:48 +00:00
jmiller 5c3b216e06 chore: force-sync .mokogitea/workflows/deploy-manual.yml [skip ci] 2026-05-12 19:08:48 +00:00
jmiller 29f4c19ff3 chore: force-sync .mokogitea/workflows/cleanup.yml [skip ci] 2026-05-12 19:08:47 +00:00
jmiller f07c471d47 chore: force-sync .mokogitea/workflows/ci-joomla.yml [skip ci] 2026-05-12 19:08:47 +00:00
jmiller 551ae8bb86 chore: force-sync .mokogitea/workflows/cascade-dev.yml [skip ci] 2026-05-12 19:08:46 +00:00
jmiller 79477e93c1 chore: force-sync .mokogitea/workflows/auto-release.yml [skip ci] 2026-05-12 19:08:46 +00:00
jmiller 8135e67b3f chore: sync .mokogitea/ISSUE_TEMPLATE/version.md from template [skip ci] 2026-05-12 18:46:48 +00:00
jmiller 11efd7164a chore: sync .mokogitea/ISSUE_TEMPLATE/security.md from template [skip ci] 2026-05-12 18:46:47 +00:00
jmiller 28f9c272d8 chore: sync .mokogitea/ISSUE_TEMPLATE/rfc.md from template [skip ci] 2026-05-12 18:46:47 +00:00
jmiller 5f55b56c41 chore: sync .mokogitea/ISSUE_TEMPLATE/question.md from template [skip ci] 2026-05-12 18:46:46 +00:00
jmiller 79138f8dbe chore: sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md from template [skip ci] 2026-05-12 18:46:46 +00:00
jmiller f48e69bc1c chore: sync .mokogitea/ISSUE_TEMPLATE/feature_request.md from template [skip ci] 2026-05-12 18:46:46 +00:00
jmiller 6b396dae98 chore: sync .mokogitea/ISSUE_TEMPLATE/documentation.md from template [skip ci] 2026-05-12 18:46:45 +00:00
jmiller 136b3a3f2f chore: sync .mokogitea/ISSUE_TEMPLATE/config.yml from template [skip ci] 2026-05-12 18:46:45 +00:00
jmiller f9d2ea2a24 chore: sync .mokogitea/ISSUE_TEMPLATE/bug_report.md from template [skip ci] 2026-05-12 18:46:45 +00:00
jmiller 83c35b77d1 chore: sync .mokogitea/ISSUE_TEMPLATE/adr.md from template [skip ci] 2026-05-12 18:46:44 +00:00
jmiller 5ca204d64e chore: sync .mokogitea/workflows/update-server.yml from template [skip ci] 2026-05-12 18:46:44 +00:00
jmiller df46eefb7a chore: sync .mokogitea/workflows/security-audit.yml from template [skip ci] 2026-05-12 18:46:43 +00:00
jmiller 1075ec5bd8 chore: sync .mokogitea/workflows/repo-health.yml from template [skip ci] 2026-05-12 18:46:43 +00:00
jmiller a2780380be chore: sync .mokogitea/workflows/pre-release.yml from template [skip ci] 2026-05-12 18:46:43 +00:00
jmiller 085513e5e7 chore: sync .mokogitea/workflows/pr-check.yml from template [skip ci] 2026-05-12 18:46:42 +00:00
jmiller 0c55d230a8 chore: sync .mokogitea/workflows/notify.yml from template [skip ci] 2026-05-12 18:46:42 +00:00
jmiller fafbdde5bb chore: sync .mokogitea/workflows/gitleaks.yml from template [skip ci] 2026-05-12 18:46:42 +00:00
jmiller 5e17e91f36 chore: sync .mokogitea/workflows/deploy-manual.yml from template [skip ci] 2026-05-12 18:46:41 +00:00
jmiller cf5f4ca3bc chore: sync .mokogitea/workflows/cleanup.yml from template [skip ci] 2026-05-12 18:46:41 +00:00
jmiller 030ec319be chore: sync .mokogitea/workflows/ci-joomla.yml from template [skip ci] 2026-05-12 18:46:40 +00:00
jmiller c16711f088 chore: sync .mokogitea/workflows/cascade-dev.yml from template [skip ci] 2026-05-12 18:46:40 +00:00
jmiller 8aedb2b041 chore: sync .mokogitea/workflows/auto-release.yml from template [skip ci] 2026-05-12 18:46:40 +00:00
jmiller f399abd068 chore: sync .mokogitea/ISSUE_TEMPLATE/version.md from template [skip ci] 2026-05-12 18:37:34 +00:00
jmiller b67de3c69f chore: sync .mokogitea/ISSUE_TEMPLATE/security.md from template [skip ci] 2026-05-12 18:37:34 +00:00
jmiller 3da378bed8 chore: sync .mokogitea/ISSUE_TEMPLATE/rfc.md from template [skip ci] 2026-05-12 18:37:33 +00:00
jmiller 1574d32d3e chore: sync .mokogitea/ISSUE_TEMPLATE/question.md from template [skip ci] 2026-05-12 18:37:33 +00:00
jmiller d9bb41acb1 chore: sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md from template [skip ci] 2026-05-12 18:37:33 +00:00
jmiller 15614a1410 chore: sync .mokogitea/ISSUE_TEMPLATE/feature_request.md from template [skip ci] 2026-05-12 18:37:32 +00:00
jmiller f1638f5b43 chore: sync .mokogitea/ISSUE_TEMPLATE/documentation.md from template [skip ci] 2026-05-12 18:37:32 +00:00
jmiller 0a0590307d chore: sync .mokogitea/ISSUE_TEMPLATE/config.yml from template [skip ci] 2026-05-12 18:37:32 +00:00
jmiller d0e73ba415 chore: sync .mokogitea/ISSUE_TEMPLATE/bug_report.md from template [skip ci] 2026-05-12 18:37:31 +00:00
jmiller dae546daf9 chore: sync .mokogitea/ISSUE_TEMPLATE/adr.md from template [skip ci] 2026-05-12 18:37:31 +00:00
jmiller 2cc010fb81 chore: sync .mokogitea/workflows/update-server.yml from template [skip ci] 2026-05-12 18:37:31 +00:00
jmiller 86132382ea chore: sync .mokogitea/workflows/security-audit.yml from template [skip ci] 2026-05-12 18:37:30 +00:00
jmiller 1f74a6cfe0 chore: sync .mokogitea/workflows/repo-health.yml from template [skip ci] 2026-05-12 18:37:30 +00:00
jmiller a1eea18661 chore: sync .mokogitea/workflows/pre-release.yml from template [skip ci] 2026-05-12 18:37:29 +00:00
jmiller 1ad1d09f81 chore: sync .mokogitea/workflows/pr-check.yml from template [skip ci] 2026-05-12 18:37:29 +00:00
jmiller 5a8f2c400f chore: sync .mokogitea/workflows/notify.yml from template [skip ci] 2026-05-12 18:37:29 +00:00
jmiller 1a03b335ab chore: sync .mokogitea/workflows/gitleaks.yml from template [skip ci] 2026-05-12 18:37:28 +00:00
jmiller a26d76d65c chore: sync .mokogitea/workflows/deploy-manual.yml from template [skip ci] 2026-05-12 18:37:28 +00:00
jmiller fb121a14bd chore: sync .mokogitea/workflows/cleanup.yml from template [skip ci] 2026-05-12 18:37:27 +00:00
jmiller 73ef3e7b48 chore: sync .mokogitea/workflows/ci-joomla.yml from template [skip ci] 2026-05-12 18:37:27 +00:00
jmiller 1cf3ae4b28 chore: sync .mokogitea/workflows/cascade-dev.yml from template [skip ci] 2026-05-12 18:37:27 +00:00
jmiller 60a081be9d chore: sync .mokogitea/workflows/auto-release.yml from template [skip ci] 2026-05-12 18:37:26 +00:00
jmiller be5d24d31a chore: sync .mokogitea/workflows/update-server.yml from template [skip ci] 2026-05-12 05:30:54 +00:00
jmiller 3de6e123d5 chore: sync .mokogitea/workflows/security-audit.yml from template [skip ci] 2026-05-12 05:30:54 +00:00
jmiller 523b7fbbfa chore: sync .mokogitea/workflows/repo-health.yml from template [skip ci] 2026-05-12 05:30:53 +00:00
jmiller 017b83b425 chore: sync .mokogitea/workflows/pre-release.yml from template [skip ci] 2026-05-12 05:30:53 +00:00
jmiller a8d6c5ff7f chore: sync .mokogitea/workflows/pr-check.yml from template [skip ci] 2026-05-12 05:30:53 +00:00
jmiller 5dea2be227 chore: sync .mokogitea/workflows/notify.yml from template [skip ci] 2026-05-12 05:30:52 +00:00
jmiller 9d880d07e4 chore: sync .mokogitea/workflows/gitleaks.yml from template [skip ci] 2026-05-12 05:30:52 +00:00
jmiller 2865e9e53a chore: sync .mokogitea/workflows/deploy-manual.yml from template [skip ci] 2026-05-12 05:30:52 +00:00
jmiller fc1846869f chore: sync .mokogitea/workflows/cleanup.yml from template [skip ci] 2026-05-12 05:30:51 +00:00
jmiller da644d1760 chore: sync .mokogitea/workflows/ci-joomla.yml from template [skip ci] 2026-05-12 05:30:51 +00:00
jmiller 23254ef974 chore: sync .mokogitea/workflows/cascade-dev.yml from template [skip ci] 2026-05-12 05:30:51 +00:00
jmiller 46f44aea84 chore: sync .mokogitea/workflows/auto-release.yml from template [skip ci] 2026-05-12 05:30:50 +00:00
jmiller fdbc00e17c chore: sync .mokogitea/ISSUE_TEMPLATE/version.md from template [skip ci] 2026-05-12 05:30:50 +00:00
jmiller fcec62e7d1 chore: sync .mokogitea/ISSUE_TEMPLATE/security.md from template [skip ci] 2026-05-12 05:30:50 +00:00
jmiller 38b68cdc64 chore: sync .mokogitea/ISSUE_TEMPLATE/rfc.md from template [skip ci] 2026-05-12 05:30:49 +00:00
jmiller 9c0bef2167 chore: sync .mokogitea/ISSUE_TEMPLATE/question.md from template [skip ci] 2026-05-12 05:30:49 +00:00
jmiller f0db4b2f45 chore: sync .mokogitea/ISSUE_TEMPLATE/joomla_issue.md from template [skip ci] 2026-05-12 05:30:48 +00:00
jmiller 1a343e77ad chore: sync .mokogitea/ISSUE_TEMPLATE/feature_request.md from template [skip ci] 2026-05-12 05:30:48 +00:00
jmiller 3db3a59484 chore: sync .mokogitea/ISSUE_TEMPLATE/documentation.md from template [skip ci] 2026-05-12 05:30:48 +00:00
jmiller 8420c94d78 chore: sync .mokogitea/ISSUE_TEMPLATE/config.yml from template [skip ci] 2026-05-12 05:30:47 +00:00
jmiller 646bfaa5f5 chore: sync .mokogitea/ISSUE_TEMPLATE/bug_report.md from template [skip ci] 2026-05-12 05:30:47 +00:00
jmiller a6acc7e0c0 chore: sync .mokogitea/ISSUE_TEMPLATE/adr.md from template [skip ci] 2026-05-12 05:30:47 +00:00
jmiller fe8c03b5b6 chore: sync .mokogitea/.moko-platform from template [skip ci] 2026-05-12 05:30:46 +00:00
jmiller 3eff73c79e chore: remove .gitea/workflows/update-server.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:19 +00:00
jmiller 44cd1fc19c chore: move .gitea/workflows/update-server.yml to .mokogitea/update-server.yml [skip ci] 2026-05-12 04:58:19 +00:00
jmiller b05b4733f0 chore: remove .gitea/workflows/sync-roadmap-wiki.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:18 +00:00
jmiller 9897d366b5 chore: move .gitea/workflows/sync-roadmap-wiki.yml to .mokogitea/sync-roadmap-wiki.yml [skip ci] 2026-05-12 04:58:18 +00:00
jmiller 96960abdc8 chore: remove .gitea/workflows/security-audit.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:17 +00:00
jmiller 022eb48ec9 chore: move .gitea/workflows/security-audit.yml to .mokogitea/security-audit.yml [skip ci] 2026-05-12 04:58:17 +00:00
jmiller 18dbb0f82b chore: remove .gitea/workflows/repo-health.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:17 +00:00
jmiller c899394f3f chore: move .gitea/workflows/repo-health.yml to .mokogitea/repo-health.yml [skip ci] 2026-05-12 04:58:16 +00:00
jmiller 9d85696bb3 chore: remove .gitea/workflows/pre-release.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:16 +00:00
jmiller c04bd40b6a chore: move .gitea/workflows/pre-release.yml to .mokogitea/pre-release.yml [skip ci] 2026-05-12 04:58:16 +00:00
jmiller 815d45d186 chore: remove .gitea/workflows/pr-check.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:15 +00:00
jmiller 80a22a7965 chore: move .gitea/workflows/pr-check.yml to .mokogitea/pr-check.yml [skip ci] 2026-05-12 04:58:15 +00:00
jmiller 6c30630431 chore: remove .gitea/workflows/notify.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:14 +00:00
jmiller f9a656423e chore: move .gitea/workflows/notify.yml to .mokogitea/notify.yml [skip ci] 2026-05-12 04:58:14 +00:00
jmiller ea4160c9d0 chore: remove .gitea/workflows/gitleaks.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:14 +00:00
jmiller 0e49c0deae chore: move .gitea/workflows/gitleaks.yml to .mokogitea/gitleaks.yml [skip ci] 2026-05-12 04:58:13 +00:00
jmiller 6cc7b35268 chore: remove .gitea/workflows/deploy-manual.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:13 +00:00
jmiller a3b3c55216 chore: move .gitea/workflows/deploy-manual.yml to .mokogitea/deploy-manual.yml [skip ci] 2026-05-12 04:58:13 +00:00
jmiller c7ab9a38e2 chore: remove .gitea/workflows/cleanup.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:12 +00:00
jmiller 667b5b6eac chore: move .gitea/workflows/cleanup.yml to .mokogitea/cleanup.yml [skip ci] 2026-05-12 04:58:12 +00:00
jmiller cb9a4ffc07 chore: remove .gitea/workflows/ci-joomla.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:11 +00:00
jmiller ce59c59f0e chore: move .gitea/workflows/ci-joomla.yml to .mokogitea/ci-joomla.yml [skip ci] 2026-05-12 04:58:11 +00:00
jmiller 93a3ccc5de chore: remove .gitea/workflows/cascade-dev.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:11 +00:00
jmiller 7be5249161 chore: move .gitea/workflows/cascade-dev.yml to .mokogitea/cascade-dev.yml [skip ci] 2026-05-12 04:58:10 +00:00
jmiller 54231e130b chore: remove .gitea/workflows/auto-release.yml (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:10 +00:00
jmiller 0e332dc0bb chore: move .gitea/workflows/auto-release.yml to .mokogitea/auto-release.yml [skip ci] 2026-05-12 04:58:10 +00:00
jmiller c7b912fd28 chore: remove .gitea/.moko-platform (moved to .mokogitea/) [skip ci] 2026-05-12 04:58:09 +00:00
jmiller 5c5cfb40cf chore: move .gitea/.moko-platform to .mokogitea/.moko-platform [skip ci] 2026-05-12 04:58:09 +00:00
9 changed files with 137 additions and 1596 deletions
File diff suppressed because it is too large Load Diff
+19 -181
View File
@@ -151,22 +151,13 @@ 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} [skip ci]"
git commit -m "chore(version): bump ${CURRENT} → ${VERSION} (minor) [skip ci]"
git push origin HEAD:main 2>&1
}
@@ -320,7 +311,6 @@ 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'
@@ -344,44 +334,20 @@ 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. plugin="xxx" attribute (plugins)
# 2. module="xxx" attribute (modules)
# 3. XML filename (components, packages)
# 4. Repo name fallback (templates, anything else)
# 1. Try XML filename (e.g. mokowaas.xml → mokowaas)
# 2. Fall back to repo name (lowercased)
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(sed -n 's/.*plugin="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
fi
if [ -z "$EXT_ELEMENT" ]; then
EXT_ELEMENT=$(sed -n 's/.*module="\([^"]*\)".*/\1/p' "$MANIFEST" | head -1)
fi
if [ -z "$EXT_ELEMENT" ]; then
FNAME=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
# If filename is generic (templateDetails, manifest), use repo name
case "$FNAME" in
templatedetails|manifest) EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
*) EXT_ELEMENT="$FNAME" ;;
case "$EXT_ELEMENT" in
templatedetails|manifest|*.xml) EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
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=""
@@ -408,18 +374,7 @@ jobs:
PHP_TAG="<php_minimum>${PHP_MINIMUM}</php_minimum>"
fi
# Build TYPE_PREFIX for download URL
TYPE_PREFIX=""
case "${EXT_TYPE}" in
plugin) TYPE_PREFIX="plg_${EXT_FOLDER}_" ;;
module) TYPE_PREFIX="mod_" ;;
component) TYPE_PREFIX="com_" ;;
template) TYPE_PREFIX="tpl_" ;;
library) TYPE_PREFIX="lib_" ;;
package) TYPE_PREFIX="pkg_" ;;
esac
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/stable/${TYPE_PREFIX}${EXT_ELEMENT}-${VERSION}.zip"
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/stable/${EXT_ELEMENT}-${VERSION}.zip"
INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/stable"
# -- Build update entry for a given stability tag
@@ -514,32 +469,21 @@ jobs:
MAJOR="${{ steps.version.outputs.major }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# 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
# 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
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}"
# 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})"
RELEASE_NAME="${EXT_ELEMENT} ${VERSION} (stable)"
# Delete existing release if present (overwrite, not append)
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" \
@@ -589,28 +533,9 @@ jobs:
MANIFEST=$(find . -maxdepth 2 -name "*.xml" -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)
[ -z "$MANIFEST" ] && exit 0
# 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"
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"
# -- Build install packages from src/ ----------------------------
SOURCE_DIR="src"
@@ -750,73 +675,6 @@ 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: >-
@@ -906,26 +764,6 @@ 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,7 +18,6 @@ on:
- "Joomla Build & Release"
- "Joomla Extension CI"
- "Deploy"
- "Cascade Main → Dev"
types:
- completed
-90
View File
@@ -1,90 +0,0 @@
# 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
+1 -23
View File
@@ -278,7 +278,7 @@ jobs:
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]"
@@ -287,28 +287,6 @@ 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: |
+4 -5
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,docs/
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md
REPO_DISALLOWED_DIRS:
REPO_DISALLOWED_FILES: TODO.md,todo.md
@@ -62,7 +62,7 @@ env:
EXTENDED_CHECKS: "true"
# File / directory variables
DOCS_INDEX: docs/docs-index.md
DOCS_INDEX: ""
SCRIPT_DIR: scripts
WORKFLOWS_DIR: .gitea/workflows
SHELLCHECK_PATTERN: '*.sh'
@@ -450,12 +450,11 @@ jobs:
fi
done < <(git branch -r --list 'origin/dev*' | sed 's/^ *//')
if [ "${#dev_paths[@]}" -eq 0 ]; then
missing_required+=("dev/* branch (e.g. dev/01.00.00)")
if [ "${#dev_paths[@]}" -eq 0 ] && [ "${#dev_branches[@]}" -eq 0 ]; then
missing_required+=("dev branch")
fi
if [ "${#dev_branches[@]}" -gt 0 ]; then
missing_required+=("invalid branch dev (must be dev/<version>)")
fi
content_warnings=()
+71 -246
View File
@@ -1,269 +1,94 @@
<!-- 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
Joomla Web Services plugin exposing **18 REST endpoints** for DPCalendar events, calendars, locations, bookings, and tickets.
A Joomla 5/6 Web Services plugin that exposes DPCalendar events, calendars, and locations through the Joomla REST API (`/api/index.php/v1`).
![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)
Enables AI assistants (via joomla-api-mcp) and external integrations to create, read, update, and delete DPCalendar content programmatically.
---
## Table of Contents
## Features
- [Background](#background)
- [Install](#install)
- [API Endpoints](#api-endpoints)
- [Contributing](#contributing)
- [License](#license)
- **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
## Background
---
DPCalendar does not ship with a Web Services plugin. This plugin fills that gap by registering REST API routes for:
## Requirements
- **Events** — CRUD with date filtering, category scoping, and recurrence support
- **Calendars** — List and manage calendar categories
- **Locations** — List and manage event locations
| Requirement | Version |
|---|---|
| **PHP** | 8.1+ |
| **Joomla** | 5.x or 6.x |
| **DPCalendar** | Required (component must be installed) |
## Install
---
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**
## Installation
## API Endpoints
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
All endpoints require `Authorization: Bearer <token>`.
See the [INSTALLATION](https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/wiki/INSTALLATION) wiki page for detailed instructions.
### Events
---
| 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 |
## Authentication
### Calendars
All API requests require a Joomla API token passed via the `Authorization` header:
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | `/v1/dpcalendar/calendars` | List calendars |
| GET | `/v1/dpcalendar/calendars/{id}` | Get calendar |
```
Authorization: Bearer <your-joomla-api-token>
```
### Locations
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 |
---
| 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 |
## License
This project is licensed under the GNU General Public License v3.0 or later -- see the [LICENSE](LICENSE) file.
GPL-3.0-or-later see [LICENSE](LICENSE).
---
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
## 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 |
+26
View File
@@ -0,0 +1,26 @@
{
"$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.02.00
VERSION: 03.01.00
-->
<updates>
@@ -10,15 +10,15 @@
<description>Moko Web Services - DPCalendar API update</description>
<element>mokodpcalendarapi</element>
<type>plugin</type>
<version>03.02.00</version>
<version>03.01.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/-03.02.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
</downloads>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</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.02.00</version>
<version>03.01.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/-03.02.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
</downloads>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</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.02.00</version>
<version>03.01.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/-03.02.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
</downloads>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</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.02.00</version>
<version>03.01.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/-03.02.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
</downloads>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</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.02.00</version>
<version>03.01.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/-03.02.00.zip</downloadurl>
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MokoDPCalendarAPI/releases/download/stable/mokodpcalendarapi-03.01.00.zip</downloadurl>
</downloads>
<sha256>652b87468d39eb4a513b6b0aae3a563abf7662f0ee3b837b724ee3b6e19a08fb</sha256>
<sha256>a432136701334f79c34b44ce86accaf607c7569f43dd96f67249094a0506d402</sha256>
<targetplatform name="joomla" version="((5.[0-9])|(6.[0-9]))" />
<maintainer>Moko Consulting</maintainer>
<maintainerurl>https://mokoconsulting.tech</maintainerurl>