538 Commits

Author SHA1 Message Date
jmiller cbe5dfb6c0 fix: update stale repository URL (joomla-api-mcp → mcp-mokowaas-api)
Generic: Project CI / Tests (push) Blocked by required conditions
Universal: CodeQL Analysis / Security Scan Summary (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Generic: Repo Health / Report Issues (push) Blocked by required conditions
MCP: Standards Compliance / Compliance Summary (push) Blocked by required conditions
Universal: Changelog Validation / Validate CHANGELOG.md (push) Failing after 3s
MCP: Build & Validate / build (20) (push) Failing after 9s
MCP: Build & Validate / build (22) (push) Failing after 5s
Generic: Repo Health / Access control (push) Successful in 2s
Generic: Repo Health / Site Health (push) Has been skipped
Publish to npm / publish (push) Failing after 9s
MCP: Standards Compliance / Secret Scanning (push) Successful in 5s
MCP: Standards Compliance / License Header Validation (push) Successful in 4s
MCP: Standards Compliance / Repository Structure Validation (push) Failing after 4s
Generic: Project CI / Lint & Validate (push) Successful in 37s
MCP: Standards Compliance / Coding Standards Check (push) Failing after 4s
MCP: Build & Release / Build, Validate & Release (push) Failing after 33s
MCP: Standards Compliance / Workflow Configuration Check (push) Failing after 4s
MCP: Standards Compliance / Documentation Quality Check (push) Successful in 3s
MCP: Standards Compliance / README Completeness Check (push) Failing after 4s
MCP: Standards Compliance / Git Repository Hygiene (push) Successful in 3s
MCP: Standards Compliance / Script Integrity Validation (push) Successful in 5s
MCP: Standards Compliance / File Naming Standards (push) Successful in 3s
MCP: Standards Compliance / Line Length Check (push) Failing after 3s
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Successful in 3s
MCP: Standards Compliance / Dead Code Detection (push) Successful in 4s
MCP: Standards Compliance / File Size Limits (push) Successful in 3s
Universal: CodeQL Analysis / Analyze (actions) (push) Failing after 57s
MCP: Standards Compliance / Binary File Detection (push) Successful in 5s
Universal: CodeQL Analysis / Analyze (javascript) (push) Failing after 57s
MCP: Standards Compliance / TODO/FIXME Tracking (push) Successful in 3s
MCP: Standards Compliance / Broken Link Detection (push) Successful in 3s
MCP: Standards Compliance / API Documentation Coverage (push) Successful in 4s
MCP: Standards Compliance / Accessibility Check (push) Successful in 3s
MCP: Standards Compliance / Performance Metrics (push) Successful in 3s
MCP: Standards Compliance / Version Consistency Check (push) Successful in 46s
MCP: Standards Compliance / Code Duplication Detection (push) Successful in 46s
MCP: Standards Compliance / Code Complexity Analysis (push) Successful in 51s
MCP: Standards Compliance / Terraform Configuration Validation (push) Successful in 8s
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 50s
MCP: Standards Compliance / Unused Dependencies Check (push) Successful in 51s
MCP: Standards Compliance / Enterprise Readiness Check (push) Failing after 40s
MCP: Standards Compliance / Repository Health Check (push) Failing after 40s
Universal: Sync Version on Merge / Propagate README version (push) Failing after 32s
2026-06-18 14:51:23 +00:00
jmiller 42e669bd7c ci: add npm publish workflow on merge to main
Universal: Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Generic: Project CI / Lint & Validate (push) Has been cancelled
Generic: Project CI / Tests (push) Has been cancelled
Universal: CodeQL Analysis / Analyze (actions) (push) Has been cancelled
Universal: CodeQL Analysis / Analyze (javascript) (push) Has been cancelled
Universal: CodeQL Analysis / Security Scan Summary (push) Has been cancelled
Publish to npm / publish (push) Has been cancelled
Generic: Repo Health / Access control (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Site Health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
MCP: Standards Compliance / Secret Scanning (push) Has been cancelled
MCP: Standards Compliance / License Header Validation (push) Has been cancelled
MCP: Standards Compliance / Repository Structure Validation (push) Has been cancelled
MCP: Standards Compliance / Coding Standards Check (push) Has been cancelled
MCP: Standards Compliance / Version Consistency Check (push) Has been cancelled
MCP: Standards Compliance / Workflow Configuration Check (push) Has been cancelled
MCP: Standards Compliance / Documentation Quality Check (push) Has been cancelled
MCP: Standards Compliance / README Completeness Check (push) Has been cancelled
MCP: Standards Compliance / Git Repository Hygiene (push) Has been cancelled
MCP: Standards Compliance / Script Integrity Validation (push) Has been cancelled
MCP: Standards Compliance / Line Length Check (push) Has been cancelled
MCP: Standards Compliance / File Naming Standards (push) Has been cancelled
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
MCP: Standards Compliance / Code Complexity Analysis (push) Has been cancelled
MCP: Standards Compliance / Code Duplication Detection (push) Has been cancelled
MCP: Standards Compliance / Dead Code Detection (push) Has been cancelled
MCP: Standards Compliance / File Size Limits (push) Has been cancelled
MCP: Standards Compliance / Binary File Detection (push) Has been cancelled
MCP: Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
MCP: Standards Compliance / Unused Dependencies Check (push) Has been cancelled
MCP: Standards Compliance / Broken Link Detection (push) Has been cancelled
MCP: Standards Compliance / API Documentation Coverage (push) Has been cancelled
MCP: Standards Compliance / Accessibility Check (push) Has been cancelled
MCP: Standards Compliance / Performance Metrics (push) Has been cancelled
MCP: Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
MCP: Standards Compliance / Repository Health Check (push) Has been cancelled
MCP: Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
MCP: Standards Compliance / Compliance Summary (push) Has been cancelled
Universal: Sync Version on Merge / Propagate README version (push) Has been cancelled
2026-06-09 16:40:34 +00:00
jmiller d89358daa7 chore: sync security-audit.yml from Template-Generic [skip ci] 2026-06-07 17:55:47 +00:00
jmiller f1ca84ede5 chore: sync pre-release.yml from Template-Generic [skip ci] 2026-06-07 17:55:45 +00:00
jmiller d5cb0f6d6d chore: sync notify.yml from Template-Generic [skip ci] 2026-06-07 17:55:44 +00:00
jmiller b376c867a6 chore: sync gitleaks.yml from Template-Generic [skip ci] 2026-06-07 17:55:43 +00:00
jmiller c4581bac1f chore: sync deploy-manual.yml from Template-Generic [skip ci] 2026-06-07 17:55:41 +00:00
jmiller 42d265b0d7 chore: sync cleanup.yml from Template-Generic [skip ci] 2026-06-07 17:55:40 +00:00
jmiller 9f3dec1547 chore: sync ci-generic.yml from Template-Generic [skip ci] 2026-06-07 17:55:39 +00:00
jmiller db0d608aaf chore: sync auto-release.yml from Template-Generic [skip ci] 2026-06-07 17:55:37 +00:00
jmiller 394c63f7a3 chore: sync .mokogitea/workflows/pr-check.yml from moko-platform [skip ci] 2026-06-04 15:58:10 +00:00
jmiller 6c187ed182 chore: sync .mokogitea/workflows/pr-check.yml from moko-platform [skip ci] 2026-06-04 15:40:36 +00:00
jmiller 09dedec339 chore: sync .mokogitea/workflows/pr-check.yml from moko-platform [skip ci] 2026-06-04 15:31:57 +00:00
jmiller 0b9ae8b83b chore: sync .mokogitea/workflows/pr-check.yml from moko-platform [skip ci] 2026-06-04 15:18:47 +00:00
jmiller c01471e65e chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-06-04 14:23:12 +00:00
jmiller d13a511b5e chore: sync .mokogitea/workflows/repo-health.yml from moko-platform [skip ci] 2026-06-04 13:46:59 +00:00
Moko Consulting 2748f6666b chore(ci): sync CI issue reporter from Template-Joomla
Universal: Changelog Validation / Validate CHANGELOG.md (push) Failing after 4s
Generic: Repo Health / Access control (push) Successful in 5s
Generic: Repo Health / Site Health (push) Has been skipped
MCP: Standards Compliance / Secret Scanning (push) Successful in 4s
MCP: Standards Compliance / License Header Validation (push) Successful in 4s
MCP: Standards Compliance / Repository Structure Validation (push) Failing after 3s
MCP: Standards Compliance / Coding Standards Check (push) Failing after 3s
MCP: Standards Compliance / Workflow Configuration Check (push) Failing after 3s
MCP: Standards Compliance / Documentation Quality Check (push) Successful in 2s
MCP: Standards Compliance / README Completeness Check (push) Failing after 3s
MCP: Standards Compliance / Git Repository Hygiene (push) Successful in 3s
MCP: Standards Compliance / Script Integrity Validation (push) Successful in 3s
MCP: Standards Compliance / Line Length Check (push) Failing after 2s
MCP: Standards Compliance / File Naming Standards (push) Successful in 2s
Universal: CodeQL Analysis / Analyze (actions) (push) Failing after 43s
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Successful in 3s
Universal: CodeQL Analysis / Analyze (javascript) (push) Failing after 46s
MCP: Standards Compliance / Dead Code Detection (push) Successful in 5s
MCP: Standards Compliance / File Size Limits (push) Successful in 3s
MCP: Standards Compliance / Version Consistency Check (push) Successful in 35s
MCP: Standards Compliance / TODO/FIXME Tracking (push) Successful in 3s
MCP: Standards Compliance / Binary File Detection (push) Successful in 4s
MCP: Standards Compliance / Code Complexity Analysis (push) Successful in 35s
MCP: Standards Compliance / Code Duplication Detection (push) Successful in 36s
MCP: Standards Compliance / Broken Link Detection (push) Successful in 2s
MCP: Standards Compliance / API Documentation Coverage (push) Successful in 2s
MCP: Standards Compliance / Accessibility Check (push) Successful in 2s
MCP: Standards Compliance / Performance Metrics (push) Successful in 3s
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 37s
MCP: Standards Compliance / Unused Dependencies Check (push) Successful in 39s
MCP: Standards Compliance / Terraform Configuration Validation (push) Successful in 5s
MCP: Standards Compliance / Enterprise Readiness Check (push) Failing after 34s
MCP: Standards Compliance / Repository Health Check (push) Failing after 36s
Universal: Sync Version on Merge / Propagate README version (push) Failing after 27s
Universal: CodeQL Analysis / Security Scan Summary (push) Has been cancelled
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
MCP: Standards Compliance / Compliance Summary (push) Has been cancelled
2026-06-02 21:34:09 +00:00
Moko Consulting 4bbf2c3994 chore(ci): sync CI issue reporter from Template-Joomla
Universal: Changelog Validation / Validate CHANGELOG.md (push) Failing after 3s
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Site Health (push) Has been skipped
MCP: Standards Compliance / Secret Scanning (push) Successful in 3s
MCP: Standards Compliance / License Header Validation (push) Successful in 3s
MCP: Standards Compliance / Repository Structure Validation (push) Failing after 2s
Universal: CodeQL Analysis / Analyze (actions) (push) Failing after 43s
MCP: Standards Compliance / Coding Standards Check (push) Failing after 4s
MCP: Standards Compliance / Workflow Configuration Check (push) Failing after 2s
MCP: Standards Compliance / Documentation Quality Check (push) Successful in 2s
MCP: Standards Compliance / README Completeness Check (push) Failing after 3s
MCP: Standards Compliance / Git Repository Hygiene (push) Successful in 2s
MCP: Standards Compliance / Line Length Check (push) Failing after 3s
Universal: CodeQL Analysis / Analyze (javascript) (push) Failing after 42s
MCP: Standards Compliance / Script Integrity Validation (push) Successful in 4s
MCP: Standards Compliance / File Naming Standards (push) Successful in 3s
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Successful in 2s
MCP: Standards Compliance / Dead Code Detection (push) Successful in 3s
MCP: Standards Compliance / File Size Limits (push) Successful in 2s
MCP: Standards Compliance / Binary File Detection (push) Successful in 3s
MCP: Standards Compliance / TODO/FIXME Tracking (push) Successful in 2s
MCP: Standards Compliance / Version Consistency Check (push) Successful in 37s
MCP: Standards Compliance / Code Complexity Analysis (push) Successful in 36s
MCP: Standards Compliance / Code Duplication Detection (push) Successful in 36s
MCP: Standards Compliance / Broken Link Detection (push) Successful in 4s
MCP: Standards Compliance / API Documentation Coverage (push) Successful in 3s
MCP: Standards Compliance / Accessibility Check (push) Successful in 2s
MCP: Standards Compliance / Performance Metrics (push) Successful in 2s
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 38s
MCP: Standards Compliance / Terraform Configuration Validation (push) Successful in 5s
MCP: Standards Compliance / Unused Dependencies Check (push) Successful in 39s
MCP: Standards Compliance / Enterprise Readiness Check (push) Failing after 33s
MCP: Standards Compliance / Repository Health Check (push) Failing after 33s
Universal: Sync Version on Merge / Propagate README version (push) Failing after 32s
Universal: CodeQL Analysis / Security Scan Summary (push) Has been cancelled
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
MCP: Standards Compliance / Compliance Summary (push) Has been cancelled
2026-06-02 21:34:08 +00:00
Moko Consulting 6330b0855c chore(ci): sync CI issue reporter from Template-Joomla
Universal: Changelog Validation / Validate CHANGELOG.md (push) Failing after 4s
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 1s
MCP: Standards Compliance / Secret Scanning (push) Successful in 3s
MCP: Standards Compliance / License Header Validation (push) Successful in 5s
MCP: Standards Compliance / Repository Structure Validation (push) Failing after 4s
MCP: Standards Compliance / Coding Standards Check (push) Failing after 5s
MCP: Standards Compliance / Workflow Configuration Check (push) Failing after 6s
MCP: Standards Compliance / Documentation Quality Check (push) Successful in 6s
MCP: Standards Compliance / README Completeness Check (push) Failing after 5s
MCP: Standards Compliance / Git Repository Hygiene (push) Successful in 3s
MCP: Standards Compliance / Script Integrity Validation (push) Successful in 4s
MCP: Standards Compliance / File Naming Standards (push) Successful in 3s
MCP: Standards Compliance / Line Length Check (push) Failing after 4s
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Successful in 3s
Universal: CodeQL Analysis / Analyze (actions) (push) Failing after 48s
MCP: Standards Compliance / Version Consistency Check (push) Successful in 43s
Universal: CodeQL Analysis / Analyze (javascript) (push) Failing after 54s
MCP: Standards Compliance / File Size Limits (push) Successful in 3s
MCP: Standards Compliance / Dead Code Detection (push) Successful in 5s
MCP: Standards Compliance / TODO/FIXME Tracking (push) Successful in 3s
MCP: Standards Compliance / Binary File Detection (push) Successful in 5s
MCP: Standards Compliance / Code Complexity Analysis (push) Successful in 37s
MCP: Standards Compliance / Broken Link Detection (push) Successful in 3s
MCP: Standards Compliance / Code Duplication Detection (push) Successful in 38s
MCP: Standards Compliance / API Documentation Coverage (push) Successful in 3s
MCP: Standards Compliance / Accessibility Check (push) Successful in 2s
MCP: Standards Compliance / Performance Metrics (push) Successful in 2s
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 36s
MCP: Standards Compliance / Unused Dependencies Check (push) Successful in 37s
MCP: Standards Compliance / Terraform Configuration Validation (push) Successful in 5s
MCP: Standards Compliance / Enterprise Readiness Check (push) Failing after 34s
MCP: Standards Compliance / Repository Health Check (push) Failing after 37s
Universal: Sync Version on Merge / Propagate README version (push) Failing after 38s
Universal: CodeQL Analysis / Security Scan Summary (push) Has been cancelled
Generic: Repo Health / Release configuration (push) Has been cancelled
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
MCP: Standards Compliance / Compliance Summary (push) Has been cancelled
2026-06-02 21:34:08 +00:00
jmiller 1e626cb4c5 chore: sync .mokogitea/workflows/cascade-dev.yml from moko-platform [skip ci] 2026-05-31 01:41:50 +00:00
jmiller 3d23f007f3 chore: sync CONTRIBUTING.md from moko-platform [skip ci] 2026-05-31 01:10:02 +00:00
jmiller 6623a361f2 chore: sync .mokogitea/workflows/pr-check.yml from moko-platform [skip ci] 2026-05-30 16:01:30 +00:00
jmiller c1480afbed chore: sync CONTRIBUTING.md from moko-platform [skip ci] 2026-05-30 14:59:29 +00:00
jmiller eba25bc61b chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 14:55:58 +00:00
jmiller 42f8003b91 chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-30 14:54:07 +00:00
jmiller 700be6f345 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 05:53:06 +00:00
jmiller d39230057b chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-30 05:51:10 +00:00
jmiller 4133a111fb chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 03:40:56 +00:00
jmiller 4d9b79392e chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-30 01:14:51 +00:00
jmiller e4aa46a507 chore: add .mokogitea/branch-protection.yml from moko-platform [skip ci] 2026-05-29 10:30:07 +00:00
jmiller a9c842be58 chore: sync CONTRIBUTING.md from moko-platform [skip ci] 2026-05-29 10:27:35 +00:00
jmiller 3344acfa3d chore: sync .mokogitea/workflows/branch-cleanup.yml from moko-platform [skip ci] 2026-05-29 10:25:58 +00:00
jmiller 033ca2664f chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-29 10:24:29 +00:00
jmiller 316eb5fb3e chore: sync .mokogitea/workflows/auto-bump.yml from moko-platform [skip ci] 2026-05-29 10:23:00 +00:00
jmiller 25a1e4fdc1 chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-28 20:53:12 +00:00
jmiller 1acb452633 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-28 20:48:23 +00:00
jmiller 30f1957f09 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:43:11 +00:00
jmiller 046c7b36d7 chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-28 20:37:48 +00:00
jmiller 68e98f10eb docs: add infrastructure changes to CHANGELOG [skip ci] 2026-05-27 05:46:10 +00:00
jmiller 32573fb7b5 chore: add branch-cleanup workflow [skip ci] 2026-05-27 03:52:42 +00:00
gitea-actions[bot] 5b8cbae24a feat(ci): add version branch creation on stable release [skip ci] 2026-05-27 02:19:39 +00:00
jmiller 7df68cfac9 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:50:55 +00:00
jmiller 7558966faf chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:49:42 +00:00
jmiller 96bf175ec6 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:48:29 +00:00
jmiller d1239c1629 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:36:59 +00:00
jmiller f824d60fe3 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:35:36 +00:00
jmiller 1b448e7092 chore(ci): update auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:25:13 +00:00
jmiller 7ce56a9c8c chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 22:23:57 +00:00
jmiller 82ddea060c chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 22:13:20 +00:00
jmiller 1b7ef1cad0 chore(ci): add auto-bump.yml from moko-platform [skip ci] 2026-05-26 22:12:08 +00:00
jmiller c5e423e0c9 chore: sync .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-26 20:12:38 +00:00
jmiller 83c3a6518d chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-26 20:10:43 +00:00
jmiller f277c0b766 chore(ci): add update-server.yml universal workflow [skip ci] 2026-05-26 19:57:11 +00:00
jmiller 0e9e1ae052 chore(ci): update pre-release.yml from moko-platform [skip ci] 2026-05-26 19:36:49 +00:00
jmiller d2e058bb96 chore(ci): update auto-release.yml from moko-platform [skip ci] 2026-05-26 19:36:48 +00:00
jmiller 8e89f57182 chore: add .mokogitea/workflows/update-server.yml from moko-platform [skip ci] 2026-05-26 19:04:03 +00:00
jmiller 516b441a9c chore: sync .mokogitea/workflows/auto-release.yml from moko-platform [skip ci] 2026-05-26 03:07:26 +00:00
jmiller a40ceb8d1b chore: sync .mokogitea/workflows/pre-release.yml from moko-platform [skip ci] 2026-05-26 03:05:33 +00:00
jmiller 9fdaa06bea feat(ci): add issue-branch.yml [skip ci] 2026-05-25 05:12:36 +00:00
jmiller 2c77c11405 fix(ci): update pre-release.yml - PHP CLI tools, fix broken platform detection [skip ci] 2026-05-25 04:13:03 +00:00
jmiller 9fd215e4ed fix(ci): add branch output to auto-release [skip ci] 2026-05-23 19:47:57 +00:00
jmiller fc9df44275 Merge pull request 'chore: merge dev to main' (#16) from dev into main
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 2s
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: Changelog Validation / Validate CHANGELOG.md (push) Failing after 3s
MCP: Standards Compliance / Secret Scanning (push) Successful in 3s
MCP: Standards Compliance / License Header Validation (push) Successful in 3s
MCP: Standards Compliance / Repository Structure Validation (push) Failing after 3s
MCP: Standards Compliance / Coding Standards Check (push) Failing after 3s
MCP: Standards Compliance / Workflow Configuration Check (push) Failing after 3s
MCP: Standards Compliance / Documentation Quality Check (push) Successful in 9s
MCP: Standards Compliance / README Completeness Check (push) Failing after 11s
MCP: Standards Compliance / Git Repository Hygiene (push) Successful in 2s
MCP: Standards Compliance / Line Length Check (push) Failing after 3s
MCP: Standards Compliance / Script Integrity Validation (push) Successful in 5s
MCP: Standards Compliance / File Naming Standards (push) Successful in 3s
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Successful in 3s
Universal: CodeQL Analysis / Analyze (actions) (push) Failing after 44s
MCP: Standards Compliance / Version Consistency Check (push) Successful in 40s
Universal: CodeQL Analysis / Analyze (javascript) (push) Failing after 48s
MCP: Standards Compliance / File Size Limits (push) Successful in 4s
MCP: Standards Compliance / Dead Code Detection (push) Successful in 5s
MCP: Standards Compliance / TODO/FIXME Tracking (push) Successful in 3s
MCP: Standards Compliance / Binary File Detection (push) Successful in 4s
MCP: Standards Compliance / Broken Link Detection (push) Successful in 4s
MCP: Standards Compliance / API Documentation Coverage (push) Successful in 3s
MCP: Standards Compliance / Accessibility Check (push) Successful in 3s
MCP: Standards Compliance / Performance Metrics (push) Successful in 3s
MCP: Standards Compliance / Code Complexity Analysis (push) Successful in 39s
MCP: Standards Compliance / Code Duplication Detection (push) Successful in 40s
MCP: Standards Compliance / Terraform Configuration Validation (push) Successful in 9s
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 42s
MCP: Standards Compliance / Unused Dependencies Check (push) Successful in 42s
MCP: Standards Compliance / Repository Health Check (push) Failing after 39s
MCP: Standards Compliance / Enterprise Readiness Check (push) Failing after 40s
Universal: Sync Version on Merge / Propagate README version (push) Failing after 47s
Generic: Repo Health / Release configuration (push) Failing after 4s
Generic: Repo Health / Scripts governance (push) Successful in 3s
Generic: Repo Health / Repository health (push) Failing after 3s
Universal: CodeQL Analysis / Security Scan Summary (push) Successful in 1s
MCP: Standards Compliance / Compliance Summary (push) Failing after 1s
2026-05-23 01:09:49 +00:00
jmiller 649c2628e8 Merge pull request 'chore: cascade main → dev (dd0efe0) [skip ci]' (#15) from main into dev
chore: cascade main → dev [skip ci]
2026-05-23 01:02:28 +00:00
jmiller dd0efe0029 feat: new MCP tools (#14)
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 4s
Universal: Changelog Validation / Validate CHANGELOG.md (push) Failing after 3s
MCP: Build & Validate / build (20) (push) Failing after 4s
Generic: Repo Health / Access control (push) Successful in 1s
Generic: Repo Health / Site Health (push) Has been skipped
MCP: Build & Validate / build (22) (push) Failing after 4s
MCP: Standards Compliance / Secret Scanning (push) Successful in 3s
MCP: Standards Compliance / License Header Validation (push) Successful in 3s
MCP: Standards Compliance / Repository Structure Validation (push) Failing after 3s
MCP: Standards Compliance / Coding Standards Check (push) Failing after 2s
MCP: Standards Compliance / Workflow Configuration Check (push) Failing after 2s
MCP: Build & Release / Build, Validate & Release (push) Failing after 30s
MCP: Tool Inventory / inventory (push) Failing after 15s
MCP: Standards Compliance / Documentation Quality Check (push) Successful in 3s
MCP: Standards Compliance / README Completeness Check (push) Failing after 2s
MCP: Standards Compliance / Git Repository Hygiene (push) Successful in 2s
Universal: CodeQL Analysis / Analyze (javascript) (push) Failing after 44s
MCP: Standards Compliance / Line Length Check (push) Failing after 4s
MCP: Standards Compliance / File Naming Standards (push) Successful in 3s
MCP: Standards Compliance / Script Integrity Validation (push) Successful in 4s
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Successful in 4s
MCP: Standards Compliance / Dead Code Detection (push) Successful in 4s
MCP: Standards Compliance / File Size Limits (push) Successful in 3s
MCP: Standards Compliance / TODO/FIXME Tracking (push) Successful in 3s
MCP: Standards Compliance / Binary File Detection (push) Successful in 4s
MCP: Standards Compliance / Version Consistency Check (push) Successful in 39s
MCP: Standards Compliance / Broken Link Detection (push) Successful in 3s
MCP: Standards Compliance / API Documentation Coverage (push) Successful in 2s
MCP: Standards Compliance / Accessibility Check (push) Successful in 3s
MCP: Standards Compliance / Performance Metrics (push) Successful in 3s
MCP: Standards Compliance / Code Complexity Analysis (push) Successful in 40s
MCP: Standards Compliance / Code Duplication Detection (push) Successful in 40s
MCP: Standards Compliance / Terraform Configuration Validation (push) Successful in 7s
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 40s
MCP: Standards Compliance / Unused Dependencies Check (push) Successful in 42s
MCP: Standards Compliance / Enterprise Readiness Check (push) Failing after 40s
MCP: Standards Compliance / Repository Health Check (push) Failing after 40s
Universal: Sync Version on Merge / Propagate README version (push) Failing after 43s
Generic: Repo Health / Release configuration (push) Failing after 3s
Generic: Repo Health / Scripts governance (push) Successful in 3s
Generic: Repo Health / Repository health (push) Failing after 3s
MCP: Standards Compliance / Compliance Summary (push) Failing after 1s
Universal: CodeQL Analysis / Analyze (actions) (push) Failing after 13m40s
Universal: CodeQL Analysis / Security Scan Summary (push) Successful in 1s
2026-05-23 00:58:37 +00:00
Jonathan Miller 9809e85e42 feat: add health_check, heartbeat_status, extensions_list, system_info (#9, #10, #12, #13)
Universal: Changelog Validation / Validate CHANGELOG.md (pull_request) Failing after 3s
MCP: Copilot Agent / Run Copilot Coding Agent (pull_request) Failing after 4s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Failing after 3s
Universal: CodeQL Analysis / Analyze (actions) (pull_request) Failing after 44s
MCP: Build & Validate / build (20) (pull_request) Failing after 6s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
MCP: Build & Validate / build (22) (pull_request) Failing after 6s
Universal: PR Check / Validate PR (pull_request) Failing after 3s
MCP: Standards Compliance / Secret Scanning (pull_request) Successful in 4s
MCP: Standards Compliance / License Header Validation (pull_request) Successful in 3s
MCP: Standards Compliance / Repository Structure Validation (pull_request) Failing after 4s
MCP: Standards Compliance / Coding Standards Check (pull_request) Failing after 5s
MCP: Standards Compliance / Workflow Configuration Check (pull_request) Failing after 4s
MCP: Standards Compliance / Documentation Quality Check (pull_request) Successful in 4s
MCP: Standards Compliance / README Completeness Check (pull_request) Failing after 3s
MCP: Standards Compliance / Git Repository Hygiene (pull_request) Successful in 3s
MCP: Standards Compliance / Script Integrity Validation (pull_request) Successful in 5s
MCP: Standards Compliance / File Naming Standards (pull_request) Successful in 3s
MCP: Standards Compliance / Line Length Check (pull_request) Failing after 3s
MCP: Standards Compliance / Insecure Code Pattern Detection (pull_request) Successful in 3s
MCP: Standards Compliance / File Size Limits (pull_request) Successful in 3s
MCP: Standards Compliance / Dead Code Detection (pull_request) Successful in 5s
MCP: Standards Compliance / Binary File Detection (pull_request) Successful in 5s
MCP: Standards Compliance / TODO/FIXME Tracking (pull_request) Successful in 3s
MCP: Standards Compliance / Broken Link Detection (pull_request) Successful in 3s
MCP: Standards Compliance / API Documentation Coverage (pull_request) Successful in 2s
MCP: Standards Compliance / Accessibility Check (pull_request) Successful in 3s
MCP: Standards Compliance / Performance Metrics (pull_request) Successful in 3s
MCP: Standards Compliance / Version Consistency Check (pull_request) Successful in 42s
MCP: Standards Compliance / Code Complexity Analysis (pull_request) Successful in 40s
MCP: Standards Compliance / Code Duplication Detection (pull_request) Successful in 40s
MCP: Standards Compliance / Terraform Configuration Validation (pull_request) Successful in 6s
Universal: Auto-Assign / Assign unassigned issues and PRs (pull_request_target) Successful in 1s
MCP: Standards Compliance / Dependency Vulnerability Scanning (pull_request) Successful in 42s
MCP: Standards Compliance / Unused Dependencies Check (pull_request) Successful in 43s
MCP: Standards Compliance / Enterprise Readiness Check (pull_request) Failing after 38s
MCP: Standards Compliance / Repository Health Check (pull_request) Failing after 38s
Universal: Build & Release / Build & Release Pipeline (pull_request) Failing after 29s
MCP: Standards Compliance / Compliance Summary (pull_request) Failing after 2s
Universal: CodeQL Analysis / Analyze (javascript) (pull_request) Failing after 16m24s
Universal: CodeQL Analysis / Security Scan Summary (pull_request) Successful in 1s
New tools:
- joomla_health_check — call /?mokowaas=health on any site
- joomla_heartbeat_status — check Grafana registration
- joomla_extensions_list — list installed extensions
- joomla_system_info — get Joomla config

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-22 06:15:12 -05:00
jmiller b58ee80198 fix(ci): pre-release php-curl + continue-on-error + CLI updates.xml [skip ci] 2026-05-22 03:31:18 +00:00
jmiller dbc163faa5 refactor(ci): sync auto-release.yml — CLI-based workflow [skip ci] 2026-05-22 02:56:20 +00:00
jmiller f6a535bd5b refactor(ci): pre-release uses CLI tools [skip ci] 2026-05-22 02:49:47 +00:00
jmiller ae9d38731c fix(ci): sync pre-release.yml — CLI-based updates.xml sync [skip ci] 2026-05-22 02:40:14 +00:00
jmiller 82bdd3442f fix(ci): sync pre-release.yml — updates.xml API sync (#34) [skip ci] 2026-05-22 02:36:00 +00:00
jmiller 66c149d64f chore: sync security-audit.yml from moko-platform [skip ci] 2026-05-21 22:31:00 +00:00
jmiller 59dc59c049 chore: sync repo-health.yml from moko-platform [skip ci] 2026-05-21 22:31:00 +00:00
jmiller 20e854376e chore: sync pre-release.yml from moko-platform [skip ci] 2026-05-21 22:30:59 +00:00
jmiller ba5221f58e chore: sync pr-check.yml from moko-platform [skip ci] 2026-05-21 22:30:58 +00:00
jmiller 0cb6814ca2 chore: sync notify.yml from moko-platform [skip ci] 2026-05-21 22:30:58 +00:00
jmiller 50e6e8e320 chore: sync gitleaks.yml from moko-platform [skip ci] 2026-05-21 22:30:57 +00:00
jmiller cd05983abe chore: sync deploy-manual.yml from moko-platform [skip ci] 2026-05-21 22:30:56 +00:00
jmiller 8ff5c944a8 chore: sync cleanup.yml from moko-platform [skip ci] 2026-05-21 22:30:56 +00:00
jmiller 789d69c5d2 chore: sync cascade-dev.yml from moko-platform [skip ci] 2026-05-21 22:30:55 +00:00
jmiller b9259ca7fa chore: sync auto-release.yml from moko-platform [skip ci] 2026-05-21 22:30:54 +00:00
jmiller 6a75500593 chore: update CLAUDE.md to reference .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 20:09:17 +00:00
jmiller 041b70a296 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:42 +00:00
jmiller 479f5be516 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:42 +00:00
jmiller 59fecbafdc chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:41 +00:00
jmiller c7eda18c47 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:41 +00:00
jmiller 022cac4b99 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:41 +00:00
jmiller 8c9f2cbf14 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:40 +00:00
jmiller 358a4a6000 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:40 +00:00
jmiller 2029cf6999 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:40 +00:00
jmiller d229f6fa18 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:39 +00:00
jmiller 27415afce8 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:39 +00:00
jmiller feacb79752 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:39 +00:00
jmiller 954e2250ed chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:38 +00:00
jmiller 92c9813b2e chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:38 +00:00
jmiller d32c50bfe5 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:38 +00:00
jmiller 706adedbe6 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:37 +00:00
jmiller bef76abc9f chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:37 +00:00
jmiller bd548cd1cb chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:37 +00:00
jmiller c335a3f451 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:36 +00:00
jmiller 2cc8bc9639 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:36 +00:00
jmiller 7a3fd0e40c chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:36 +00:00
jmiller 0625bc9e7e chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:36 +00:00
jmiller b7e5b9abe0 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:35 +00:00
jmiller 6d8beed12d chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:35 +00:00
jmiller da20b814b9 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:35 +00:00
jmiller d2fd5167c7 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:34 +00:00
jmiller a1a01fbe3b chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:34 +00:00
jmiller 247b2b9710 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:34 +00:00
jmiller 03bcca6b8c chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:33 +00:00
jmiller e71a47687d chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:33 +00:00
jmiller 4099b45b83 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:33 +00:00
jmiller 39c58e7a87 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:32 +00:00
jmiller 97c9490238 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:32 +00:00
jmiller 103246413a chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:32 +00:00
jmiller 3aff660885 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:32 +00:00
jmiller 22be873c79 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:31 +00:00
jmiller 32ce878a62 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:31 +00:00
jmiller 77c643ccc9 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:31 +00:00
jmiller 39e4b4a4d3 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:30 +00:00
jmiller 9fbc4060b9 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:30 +00:00
jmiller c26a8f664f chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:30 +00:00
jmiller 9ac51e0490 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:29 +00:00
jmiller 28fcac2371 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:29 +00:00
jmiller 1a753b805e chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:29 +00:00
jmiller 23ef7532ef chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:28 +00:00
jmiller d04a4fefed chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:28 +00:00
jmiller 1c87dca5fc chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:28 +00:00
jmiller b322acca8b chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:27 +00:00
jmiller 03a1ae3697 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:27 +00:00
jmiller cf0cceacf1 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:27 +00:00
jmiller 5eba97790a chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:26 +00:00
jmiller 9c2a269053 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:26 +00:00
jmiller 2351c92c79 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:26 +00:00
jmiller 8f3a1a16ac chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:25 +00:00
jmiller 1ec4ca7087 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:25 +00:00
jmiller a0e0ff3420 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:25 +00:00
jmiller ea973565ad chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:24 +00:00
jmiller f12dffa339 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:24 +00:00
jmiller 21e67efe81 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:24 +00:00
jmiller 055bcfcea9 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:23 +00:00
jmiller 232bf77cbf chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:23 +00:00
jmiller 3cb1b7b228 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:23 +00:00
jmiller 1e9c246ff5 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:22 +00:00
jmiller 0e300c4859 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:22 +00:00
jmiller 98333c124a chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:22 +00:00
jmiller da71973fae chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:21 +00:00
jmiller c13dc3be1d chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:21 +00:00
jmiller 31aa281717 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:21 +00:00
jmiller 1fb91a9059 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:20 +00:00
jmiller dff3a8ae8c chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:20 +00:00
jmiller 43a03968b9 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:20 +00:00
jmiller 10c19f5315 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:19 +00:00
jmiller ed00b190a4 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:19 +00:00
jmiller 6fe827f389 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:19 +00:00
jmiller 3766f7484f chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:18 +00:00
jmiller 73599c2843 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:18 +00:00
jmiller 3c3949bbf8 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:18 +00:00
jmiller 7dba4aa16a chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:17 +00:00
jmiller 97c190b598 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:17 +00:00
jmiller 00fe90d586 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:17 +00:00
jmiller 43334b320e chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:16 +00:00
jmiller b874764e4e chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:16 +00:00
jmiller d189c2e71a chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:16 +00:00
jmiller 35817df622 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:15 +00:00
jmiller 4ef533d9b4 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:15 +00:00
jmiller 0a35f32815 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:15 +00:00
jmiller b8778dc44f chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:14 +00:00
jmiller 6d07191967 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:14 +00:00
jmiller 13917ed430 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:14 +00:00
jmiller c7b691e13d chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:13 +00:00
jmiller 65f4c033cc chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:13 +00:00
jmiller e1b65cff69 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:13 +00:00
jmiller 830c665bd4 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:12 +00:00
jmiller e241cf1e88 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:12 +00:00
jmiller 32916d535b chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:12 +00:00
jmiller d139358fc0 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:11 +00:00
jmiller 74d4ae0bbe chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:11 +00:00
jmiller a873e15a39 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:11 +00:00
jmiller 5cd9132e60 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:11 +00:00
jmiller f62cf51cbe chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:10 +00:00
jmiller de925cd70e chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:10 +00:00
jmiller 1acef83112 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:10 +00:00
jmiller 0baf1d36c4 chore: rename .gitea/ to .mokogitea/ [skip ci]
Authored-by: Moko Consulting
2026-05-21 17:25:09 +00:00
jmiller 179942adc2 chore: add issue templates [skip ci] 2026-05-20 00:36:37 +00:00
jmiller d3b3552b74 chore: add issue templates [skip ci] 2026-05-20 00:36:37 +00:00
jmiller 9f8151f0eb chore: add issue templates [skip ci] 2026-05-20 00:36:36 +00:00
jmiller e3a15c15e2 chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:36 +00:00
jmiller a027e30bb4 chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:35 +00:00
jmiller 46556024dd chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:34 +00:00
jmiller 892c5938a3 chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:33 +00:00
jmiller 44431c9d6c chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:31 +00:00
jmiller 78bf1bf4e4 chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:27 +00:00
jmiller 09348e7fb1 chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:26 +00:00
jmiller 8e4b70a6bb chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:25 +00:00
jmiller cc4aa7a6fc chore: sync issue templates from template repo [skip ci] 2026-05-20 00:32:23 +00:00
jmiller 5dfdccaf26 Merge pull request 'chore: merge dev into main � MCP underscore convention + new features' (#8) from dev into main
Universal: Changelog Validation / Validate CHANGELOG.md (push) Failing after 3s
MCP: Standards Compliance / Secret Scanning (push) Successful in 3s
MCP: Standards Compliance / License Header Validation (push) Successful in 3s
MCP: Standards Compliance / Repository Structure Validation (push) Failing after 2s
MCP: Standards Compliance / Coding Standards Check (push) Failing after 2s
Universal: CodeQL Analysis / Analyze (javascript) (push) Failing after 37s
MCP: Standards Compliance / Version Consistency Check (push) Successful in 32s
MCP: Standards Compliance / Workflow Configuration Check (push) Failing after 34s
Universal: CodeQL Analysis / Analyze (actions) (push) Failing after 1m14s
MCP: Standards Compliance / Documentation Quality Check (push) Successful in 3s
MCP: Standards Compliance / Git Repository Hygiene (push) Successful in 3s
MCP: Standards Compliance / Script Integrity Validation (push) Successful in 5s
MCP: Standards Compliance / Line Length Check (push) Failing after 3s
MCP: Standards Compliance / File Naming Standards (push) Successful in 2s
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Successful in 2s
MCP: Standards Compliance / README Completeness Check (push) Failing after 30s
MCP: Standards Compliance / Code Complexity Analysis (push) Successful in 32s
MCP: Standards Compliance / Code Duplication Detection (push) Successful in 32s
MCP: Standards Compliance / File Size Limits (push) Successful in 3s
MCP: Standards Compliance / Binary File Detection (push) Successful in 3s
MCP: Standards Compliance / TODO/FIXME Tracking (push) Successful in 2s
MCP: Standards Compliance / Dead Code Detection (push) Failing after 37s
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 37s
MCP: Standards Compliance / Unused Dependencies Check (push) Successful in 38s
MCP: Standards Compliance / API Documentation Coverage (push) Successful in 3s
MCP: Standards Compliance / Accessibility Check (push) Successful in 3s
MCP: Standards Compliance / Performance Metrics (push) Successful in 2s
MCP: Standards Compliance / Broken Link Detection (push) Failing after 34s
MCP: Standards Compliance / Enterprise Readiness Check (push) Failing after 34s
MCP: Standards Compliance / Repository Health Check (push) Failing after 35s
MCP: Standards Compliance / Terraform Configuration Validation (push) Failing after 37s
Universal: Sync Version on Merge / Propagate README version (push) Failing after 35s
Universal: CodeQL Analysis / Security Scan Summary (push) Successful in 1s
MCP: Standards Compliance / Compliance Summary (push) Failing after 2s
Universal: Auto-Assign / Assign unassigned issues and PRs (push) Successful in 1s
2026-05-19 19:59:49 +00:00
Jonathan Miller cdf005c7b3 chore: rename config to .mcp_mokowaas.json (underscore convention)
Universal: Changelog Validation / Validate CHANGELOG.md (pull_request) Failing after 2s
MCP: Copilot Agent / Run Copilot Coding Agent (pull_request) Failing after 2s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Failing after 34s
MCP: Build & Validate / build (20) (pull_request) Failing after 25s
Universal: CodeQL Analysis / Analyze (actions) (pull_request) Failing after 1m14s
Universal: PR Check / Branch Policy (pull_request) Successful in 1s
Universal: PR Check / Validate PR (pull_request) Failing after 3s
Universal: CodeQL Analysis / Analyze (javascript) (pull_request) Failing after 1m16s
MCP: Standards Compliance / Secret Scanning (pull_request) Successful in 3s
MCP: Standards Compliance / License Header Validation (pull_request) Successful in 3s
MCP: Standards Compliance / Repository Structure Validation (pull_request) Failing after 3s
MCP: Standards Compliance / Coding Standards Check (pull_request) Failing after 4s
MCP: Standards Compliance / Workflow Configuration Check (pull_request) Failing after 2s
MCP: Standards Compliance / Documentation Quality Check (pull_request) Successful in 3s
MCP: Standards Compliance / README Completeness Check (pull_request) Failing after 2s
MCP: Standards Compliance / Git Repository Hygiene (pull_request) Successful in 3s
MCP: Standards Compliance / Script Integrity Validation (pull_request) Successful in 4s
MCP: Standards Compliance / Line Length Check (pull_request) Failing after 3s
MCP: Standards Compliance / File Naming Standards (pull_request) Successful in 3s
MCP: Standards Compliance / Insecure Code Pattern Detection (pull_request) Successful in 3s
MCP: Build & Validate / build (22) (pull_request) Failing after 39s
MCP: Standards Compliance / Version Consistency Check (pull_request) Successful in 35s
MCP: Standards Compliance / Dead Code Detection (pull_request) Successful in 5s
MCP: Standards Compliance / File Size Limits (pull_request) Successful in 2s
MCP: Standards Compliance / Binary File Detection (pull_request) Successful in 3s
MCP: Standards Compliance / TODO/FIXME Tracking (pull_request) Successful in 3s
MCP: Standards Compliance / Code Complexity Analysis (pull_request) Successful in 33s
MCP: Standards Compliance / Code Duplication Detection (pull_request) Failing after 45s
MCP: Standards Compliance / Dependency Vulnerability Scanning (pull_request) Successful in 34s
MCP: Standards Compliance / API Documentation Coverage (pull_request) Successful in 3s
MCP: Standards Compliance / Accessibility Check (pull_request) Successful in 3s
MCP: Standards Compliance / Performance Metrics (pull_request) Successful in 2s
MCP: Standards Compliance / Unused Dependencies Check (pull_request) Successful in 36s
MCP: Standards Compliance / Broken Link Detection (pull_request) Failing after 35s
MCP: Standards Compliance / Enterprise Readiness Check (pull_request) Failing after 34s
Universal: Auto-Assign / Assign unassigned issues and PRs (pull_request_target) Successful in 1s
MCP: Standards Compliance / Repository Health Check (pull_request) Failing after 34s
MCP: Standards Compliance / Terraform Configuration Validation (pull_request) Failing after 43s
Universal: CodeQL Analysis / Security Scan Summary (pull_request) Successful in 1s
MCP: Standards Compliance / Compliance Summary (pull_request) Failing after 1s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-19 14:55:32 -05:00
Jonathan Miller ed2af44103 chore: rename config to .mcp_mokowaas.json (underscore convention)
Universal: Changelog Validation / Validate CHANGELOG.md (push) Failing after 3s
Universal: CodeQL Analysis / Analyze (actions) (push) Failing after 1m13s
Universal: CodeQL Analysis / Analyze (javascript) (push) Failing after 1m14s
MCP: Build & Release / Build, Validate & Release (push) Failing after 29s
MCP: Build & Validate / build (22) (push) Failing after 5s
MCP: Build & Validate / build (20) (push) Failing after 5s
MCP: Standards Compliance / Secret Scanning (push) Successful in 3s
MCP: Standards Compliance / License Header Validation (push) Successful in 3s
MCP: Standards Compliance / Repository Structure Validation (push) Failing after 3s
MCP: Standards Compliance / Coding Standards Check (push) Failing after 4s
MCP: Standards Compliance / Workflow Configuration Check (push) Failing after 3s
MCP: Standards Compliance / Documentation Quality Check (push) Successful in 3s
MCP: Standards Compliance / README Completeness Check (push) Failing after 3s
MCP: Standards Compliance / Git Repository Hygiene (push) Successful in 4s
MCP: Standards Compliance / Script Integrity Validation (push) Successful in 5s
MCP: Standards Compliance / Line Length Check (push) Failing after 4s
MCP: Standards Compliance / File Naming Standards (push) Successful in 3s
Universal: CodeQL Analysis / Security Scan Summary (push) Has been cancelled
MCP: Standards Compliance / Code Complexity Analysis (push) Has been cancelled
MCP: Standards Compliance / Code Duplication Detection (push) Has been cancelled
MCP: Standards Compliance / Dead Code Detection (push) Has been cancelled
MCP: Standards Compliance / File Size Limits (push) Has been cancelled
MCP: Standards Compliance / Binary File Detection (push) Has been cancelled
MCP: Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
MCP: Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
MCP: Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
MCP: Standards Compliance / Unused Dependencies Check (push) Has been cancelled
MCP: Standards Compliance / Broken Link Detection (push) Has been cancelled
MCP: Standards Compliance / API Documentation Coverage (push) Has been cancelled
MCP: Standards Compliance / Accessibility Check (push) Has been cancelled
MCP: Standards Compliance / Performance Metrics (push) Has been cancelled
MCP: Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
MCP: Standards Compliance / Repository Health Check (push) Has been cancelled
MCP: Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
MCP: Standards Compliance / Compliance Summary (push) Has been cancelled
Universal: Sync Version on Merge / Propagate README version (push) Has been cancelled
MCP: Standards Compliance / Version Consistency Check (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-19 14:12:06 -05:00
jmiller 95863871b7 chore: remove docs/ — documentation lives in wiki [skip ci] 2026-05-16 22:21:05 +00:00
jmiller 50636074a3 chore: remove docs/ — documentation lives in wiki [skip ci] 2026-05-16 22:21:05 +00:00
jmiller 8d09a65701 chore: remove docs/ — documentation lives in wiki [skip ci] 2026-05-16 22:21:05 +00:00
jmiller aaa3ff7463 chore: remove docs/ — documentation lives in wiki [skip ci] 2026-05-16 22:21:04 +00:00
jmiller 218fbfa4f0 chore: remove docs/ — documentation lives in wiki [skip ci] 2026-05-16 22:21:04 +00:00
jmiller 9da204bb68 Merge pull request 'chore: sync main to dev (.mokogitea -> .gitea rename) [skip ci]' (#7) from main into dev 2026-05-16 19:00:22 +00:00
jmiller 1e1a8d04e0 chore: remove .mokogitea/workflows/sync-version-on-merge.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:29 +00:00
jmiller f36b202cc4 chore: move .mokogitea/workflows/sync-version-on-merge.yml to .gitea/workflows/sync-version-on-merge.yml [skip ci] 2026-05-16 18:58:29 +00:00
jmiller 8a84068d38 chore: remove .mokogitea/workflows/standards-compliance.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:28 +00:00
jmiller 35bf804f9d chore: move .mokogitea/workflows/standards-compliance.yml to .gitea/workflows/standards-compliance.yml [skip ci] 2026-05-16 18:58:28 +00:00
jmiller 83921824ae chore: remove .mokogitea/workflows/security-audit.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:27 +00:00
jmiller 32ba1153cd chore: move .mokogitea/workflows/security-audit.yml to .gitea/workflows/security-audit.yml [skip ci] 2026-05-16 18:58:27 +00:00
jmiller 5f362fe1b9 chore: remove .mokogitea/workflows/repository-cleanup.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:26 +00:00
jmiller 7990d2fcfc chore: move .mokogitea/workflows/repository-cleanup.yml to .gitea/workflows/repository-cleanup.yml [skip ci] 2026-05-16 18:58:26 +00:00
jmiller b759e2a303 chore: remove .mokogitea/workflows/pr-check.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:26 +00:00
jmiller b3306c0951 chore: move .mokogitea/workflows/pr-check.yml to .gitea/workflows/pr-check.yml [skip ci] 2026-05-16 18:58:25 +00:00
jmiller 391ff1463a chore: remove .mokogitea/workflows/notify.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:25 +00:00
jmiller 5e52fb6463 chore: move .mokogitea/workflows/notify.yml to .gitea/workflows/notify.yml [skip ci] 2026-05-16 18:58:24 +00:00
jmiller 77248351a1 chore: remove .mokogitea/workflows/mcp-tool-inventory.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:24 +00:00
jmiller 0cd2bbf781 chore: move .mokogitea/workflows/mcp-tool-inventory.yml to .gitea/workflows/mcp-tool-inventory.yml [skip ci] 2026-05-16 18:58:23 +00:00
jmiller aadf76daef chore: remove .mokogitea/workflows/mcp-sdk-check.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:23 +00:00
jmiller b279cccd61 chore: move .mokogitea/workflows/mcp-sdk-check.yml to .gitea/workflows/mcp-sdk-check.yml [skip ci] 2026-05-16 18:58:22 +00:00
jmiller 929aa6c4c8 chore: remove .mokogitea/workflows/mcp-build-test.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:22 +00:00
jmiller 14074a857a chore: move .mokogitea/workflows/mcp-build-test.yml to .gitea/workflows/mcp-build-test.yml [skip ci] 2026-05-16 18:58:21 +00:00
jmiller ec4fbe0bce chore: remove .mokogitea/workflows/mcp-auto-release.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:21 +00:00
jmiller 27f0ae08d4 chore: move .mokogitea/workflows/mcp-auto-release.yml to .gitea/workflows/mcp-auto-release.yml [skip ci] 2026-05-16 18:58:20 +00:00
jmiller f5affdc5ff chore: remove .mokogitea/workflows/gitleaks.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:20 +00:00
jmiller 70ebb4a080 chore: move .mokogitea/workflows/gitleaks.yml to .gitea/workflows/gitleaks.yml [skip ci] 2026-05-16 18:58:19 +00:00
jmiller c79efa4e18 chore: remove .mokogitea/workflows/enterprise-firewall-setup.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:19 +00:00
jmiller 6f18eef8ac chore: move .mokogitea/workflows/enterprise-firewall-setup.yml to .gitea/workflows/enterprise-firewall-setup.yml [skip ci] 2026-05-16 18:58:19 +00:00
jmiller 792655b5ef chore: remove .mokogitea/workflows/copilot-agent.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:18 +00:00
jmiller 84d9241856 chore: move .mokogitea/workflows/copilot-agent.yml to .gitea/workflows/copilot-agent.yml [skip ci] 2026-05-16 18:58:18 +00:00
jmiller a1e9955527 chore: remove .mokogitea/workflows/codeql-analysis.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:17 +00:00
jmiller 516be97fa2 chore: move .mokogitea/workflows/codeql-analysis.yml to .gitea/workflows/codeql-analysis.yml [skip ci] 2026-05-16 18:58:16 +00:00
jmiller 7d1945b5e4 chore: remove .mokogitea/workflows/changelog-validation.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:16 +00:00
jmiller 785a677682 chore: move .mokogitea/workflows/changelog-validation.yml to .gitea/workflows/changelog-validation.yml [skip ci] 2026-05-16 18:58:15 +00:00
jmiller 235f53e82c chore: remove .mokogitea/workflows/auto-dev-issue.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:14 +00:00
jmiller 19381f6327 chore: move .mokogitea/workflows/auto-dev-issue.yml to .gitea/workflows/auto-dev-issue.yml [skip ci] 2026-05-16 18:58:14 +00:00
jmiller 1aa3646014 chore: remove .mokogitea/workflows/auto-assign.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:13 +00:00
jmiller 8b89ed5764 chore: move .mokogitea/workflows/auto-assign.yml to .gitea/workflows/auto-assign.yml [skip ci] 2026-05-16 18:58:13 +00:00
jmiller 69d2646336 chore: remove .mokogitea/sync-version-on-merge.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:12 +00:00
jmiller d460fea5bb chore: move .mokogitea/sync-version-on-merge.yml to .gitea/sync-version-on-merge.yml [skip ci] 2026-05-16 18:58:12 +00:00
jmiller 8d9dff3951 chore: remove .mokogitea/standards-compliance.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:11 +00:00
jmiller 42323ccc7f chore: move .mokogitea/standards-compliance.yml to .gitea/standards-compliance.yml [skip ci] 2026-05-16 18:58:10 +00:00
jmiller 4af3aaf818 chore: remove .mokogitea/repository-cleanup.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:10 +00:00
jmiller c01bed6ab1 chore: move .mokogitea/repository-cleanup.yml to .gitea/repository-cleanup.yml [skip ci] 2026-05-16 18:58:09 +00:00
jmiller b8123642ef chore: remove .mokogitea/pr-branch-check.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:09 +00:00
jmiller a0867144b4 chore: move .mokogitea/pr-branch-check.yml to .gitea/pr-branch-check.yml [skip ci] 2026-05-16 18:58:08 +00:00
jmiller fc699603a1 chore: remove .mokogitea/mcp-tool-inventory.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:07 +00:00
jmiller 867acd7a37 chore: move .mokogitea/mcp-tool-inventory.yml to .gitea/mcp-tool-inventory.yml [skip ci] 2026-05-16 18:58:07 +00:00
jmiller ca82b43736 chore: remove .mokogitea/mcp-sdk-check.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:06 +00:00
jmiller 5a345ed639 chore: move .mokogitea/mcp-sdk-check.yml to .gitea/mcp-sdk-check.yml [skip ci] 2026-05-16 18:58:06 +00:00
jmiller bd74826a00 chore: remove .mokogitea/mcp-build-test.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:05 +00:00
jmiller 0b0154aa54 chore: move .mokogitea/mcp-build-test.yml to .gitea/mcp-build-test.yml [skip ci] 2026-05-16 18:58:04 +00:00
jmiller 59ec74d316 chore: remove .mokogitea/mcp-auto-release.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:04 +00:00
jmiller ac1d1d5f00 chore: move .mokogitea/mcp-auto-release.yml to .gitea/mcp-auto-release.yml [skip ci] 2026-05-16 18:58:03 +00:00
jmiller 7d065a5a6d chore: remove .mokogitea/manifest.xml (moved to .gitea/) [skip ci] 2026-05-16 18:58:03 +00:00
jmiller 838ea7cfd3 chore: move .mokogitea/manifest.xml to .gitea/manifest.xml [skip ci] 2026-05-16 18:58:02 +00:00
jmiller 8b2f080d82 chore: remove .mokogitea/gitleaks.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:02 +00:00
jmiller a6ef9853dc chore: move .mokogitea/gitleaks.yml to .gitea/gitleaks.yml [skip ci] 2026-05-16 18:58:01 +00:00
jmiller 92be2c806b chore: remove .mokogitea/enterprise-firewall-setup.yml (moved to .gitea/) [skip ci] 2026-05-16 18:58:00 +00:00
jmiller 23ac94800a chore: move .mokogitea/enterprise-firewall-setup.yml to .gitea/enterprise-firewall-setup.yml [skip ci] 2026-05-16 18:58:00 +00:00
jmiller c80fe52994 chore: remove .mokogitea/deploy-dev.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:59 +00:00
jmiller 7ac12d04a8 chore: move .mokogitea/deploy-dev.yml to .gitea/deploy-dev.yml [skip ci] 2026-05-16 18:57:59 +00:00
jmiller 9ab7fb560a chore: remove .mokogitea/deploy-demo.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:58 +00:00
jmiller 61471c8fc5 chore: move .mokogitea/deploy-demo.yml to .gitea/deploy-demo.yml [skip ci] 2026-05-16 18:57:58 +00:00
jmiller 5d9994013f chore: remove .mokogitea/copilot-agent.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:57 +00:00
jmiller 0dda151184 chore: move .mokogitea/copilot-agent.yml to .gitea/copilot-agent.yml [skip ci] 2026-05-16 18:57:57 +00:00
jmiller 5397fbabb7 chore: remove .mokogitea/codeql-analysis.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:56 +00:00
jmiller f0206bba50 chore: move .mokogitea/codeql-analysis.yml to .gitea/codeql-analysis.yml [skip ci] 2026-05-16 18:57:56 +00:00
jmiller d3be34ebe9 chore: remove .mokogitea/changelog-validation.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:55 +00:00
jmiller bef5080125 chore: move .mokogitea/changelog-validation.yml to .gitea/changelog-validation.yml [skip ci] 2026-05-16 18:57:55 +00:00
jmiller bde97c32c5 chore: remove .mokogitea/cascade-dev.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:54 +00:00
jmiller c749d458fe chore: move .mokogitea/cascade-dev.yml to .gitea/cascade-dev.yml [skip ci] 2026-05-16 18:57:54 +00:00
jmiller f5e3b5ce78 chore: remove .mokogitea/auto-release.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:53 +00:00
jmiller 5604c03626 chore: move .mokogitea/auto-release.yml to .gitea/auto-release.yml [skip ci] 2026-05-16 18:57:53 +00:00
jmiller 968dc5ea37 chore: remove .mokogitea/auto-dev-issue.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:52 +00:00
jmiller 528f8c5e94 chore: move .mokogitea/auto-dev-issue.yml to .gitea/auto-dev-issue.yml [skip ci] 2026-05-16 18:57:52 +00:00
jmiller 7c6d6a04e6 chore: remove .mokogitea/auto-assign.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:51 +00:00
jmiller b9fe5fe90e chore: move .mokogitea/auto-assign.yml to .gitea/auto-assign.yml [skip ci] 2026-05-16 18:57:51 +00:00
jmiller 34c302c90d chore: remove .mokogitea/ISSUE_TEMPLATE/version.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:50 +00:00
jmiller be6f03f9b7 chore: move .mokogitea/ISSUE_TEMPLATE/version.md to .gitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-16 18:57:50 +00:00
jmiller 7a0cd25c6b chore: remove .mokogitea/ISSUE_TEMPLATE/security.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:50 +00:00
jmiller a86e2f774f chore: move .mokogitea/ISSUE_TEMPLATE/security.md to .gitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-16 18:57:49 +00:00
jmiller 8bac730846 chore: remove .mokogitea/ISSUE_TEMPLATE/rfc.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:49 +00:00
jmiller 0cf88aa345 chore: move .mokogitea/ISSUE_TEMPLATE/rfc.md to .gitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-16 18:57:48 +00:00
jmiller 712a1dfc71 chore: remove .mokogitea/ISSUE_TEMPLATE/question.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:48 +00:00
jmiller 880b251945 chore: move .mokogitea/ISSUE_TEMPLATE/question.md to .gitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-16 18:57:48 +00:00
jmiller 07d71c1c78 chore: remove .mokogitea/ISSUE_TEMPLATE/firewall-request.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:47 +00:00
jmiller f4c3d3f9a4 chore: move .mokogitea/ISSUE_TEMPLATE/firewall-request.md to .gitea/ISSUE_TEMPLATE/firewall-request.md [skip ci] 2026-05-16 18:57:47 +00:00
jmiller 374f7e150f chore: remove .mokogitea/ISSUE_TEMPLATE/feature_request.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:46 +00:00
jmiller 4ef0b40b3c chore: move .mokogitea/ISSUE_TEMPLATE/feature_request.md to .gitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-16 18:57:46 +00:00
jmiller 3bc2539ebb chore: remove .mokogitea/ISSUE_TEMPLATE/enterprise_support.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:45 +00:00
jmiller 2cc2017e08 chore: move .mokogitea/ISSUE_TEMPLATE/enterprise_support.md to .gitea/ISSUE_TEMPLATE/enterprise_support.md [skip ci] 2026-05-16 18:57:45 +00:00
jmiller e2a873ed59 chore: remove .mokogitea/ISSUE_TEMPLATE/documentation.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:44 +00:00
jmiller 3ba28dfeac chore: move .mokogitea/ISSUE_TEMPLATE/documentation.md to .gitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-16 18:57:44 +00:00
jmiller 0160d3ceab chore: remove .mokogitea/ISSUE_TEMPLATE/config.yml (moved to .gitea/) [skip ci] 2026-05-16 18:57:43 +00:00
jmiller 319c53f43a chore: move .mokogitea/ISSUE_TEMPLATE/config.yml to .gitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-16 18:57:43 +00:00
jmiller 3027ae4add chore: remove .mokogitea/ISSUE_TEMPLATE/bug_report.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:42 +00:00
jmiller 1a974ae8ff chore: move .mokogitea/ISSUE_TEMPLATE/bug_report.md to .gitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-16 18:57:42 +00:00
jmiller a2072cb392 chore: remove .mokogitea/ISSUE_TEMPLATE/adr.md (moved to .gitea/) [skip ci] 2026-05-16 18:57:41 +00:00
jmiller 56d277747d chore: move .mokogitea/ISSUE_TEMPLATE/adr.md to .gitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-16 18:57:40 +00:00
jmiller 5cb47a3a11 Merge pull request 'chore: merge dev into main [skip ci]' (#6) from dev into main 2026-05-16 14:16:12 +00:00
Jonathan Miller 6506ebe91f chore: rename package to @mokoconsulting/mcp-mokowaas-api
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-16 08:19:21 -05:00
jmiller ee63f345ed chore: remove .mokogitea/.moko-platform [skip ci] 2026-05-12 19:30:01 +00:00
jmiller 51af98c7e9 chore: move .mokogitea/manifest.xml to .mokogitea/ [skip ci] 2026-05-12 19:30:00 +00:00
jmiller 42f8183ff5 chore: force-sync .mokogitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-12 19:30:00 +00:00
jmiller d522fc729d chore: force-sync .mokogitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-12 19:30:00 +00:00
jmiller 225180beb9 chore: force-sync .mokogitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-12 19:29:59 +00:00
jmiller ef712ca0ba chore: force-sync .mokogitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-12 19:29:59 +00:00
jmiller 3e88731742 chore: force-sync .mokogitea/ISSUE_TEMPLATE/firewall-request.md [skip ci] 2026-05-12 19:29:59 +00:00
jmiller 76ae6dff12 chore: force-sync .mokogitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-12 19:29:58 +00:00
jmiller db2bed371e chore: force-sync .mokogitea/ISSUE_TEMPLATE/enterprise_support.md [skip ci] 2026-05-12 19:29:58 +00:00
jmiller 92470542ec chore: force-sync .mokogitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-12 19:29:58 +00:00
jmiller 2296ae90f9 chore: force-sync .mokogitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-12 19:29:57 +00:00
jmiller 8debddbb19 chore: force-sync .mokogitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-12 19:29:57 +00:00
jmiller 6008bae389 chore: force-sync .mokogitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-12 19:29:56 +00:00
jmiller 9a2435d07b chore: force-sync .mokogitea/workflows/sync-version-on-merge.yml [skip ci] 2026-05-12 19:29:56 +00:00
jmiller 4f68f4b6da chore: force-sync .mokogitea/workflows/standards-compliance.yml [skip ci] 2026-05-12 19:29:56 +00:00
jmiller 48920f7c95 chore: force-sync .mokogitea/workflows/security-audit.yml [skip ci] 2026-05-12 19:29:55 +00:00
jmiller abe74ba364 chore: force-sync .mokogitea/workflows/repository-cleanup.yml [skip ci] 2026-05-12 19:29:55 +00:00
jmiller 7c76719802 chore: force-sync .mokogitea/workflows/pr-check.yml [skip ci] 2026-05-12 19:29:55 +00:00
jmiller e851e27ee0 chore: force-sync .mokogitea/workflows/notify.yml [skip ci] 2026-05-12 19:29:54 +00:00
jmiller d646fbd1c2 chore: force-sync .mokogitea/workflows/mcp-tool-inventory.yml [skip ci] 2026-05-12 19:29:54 +00:00
jmiller 4f42802084 chore: force-sync .mokogitea/workflows/mcp-sdk-check.yml [skip ci] 2026-05-12 19:29:54 +00:00
jmiller 8811819ed3 chore: force-sync .mokogitea/workflows/mcp-build-test.yml [skip ci] 2026-05-12 19:29:53 +00:00
jmiller 3eaa682485 chore: force-sync .mokogitea/workflows/mcp-auto-release.yml [skip ci] 2026-05-12 19:29:53 +00:00
jmiller d0bbe1d87d chore: force-sync .mokogitea/workflows/gitleaks.yml [skip ci] 2026-05-12 19:29:52 +00:00
jmiller b593a3c573 chore: force-sync .mokogitea/workflows/enterprise-firewall-setup.yml [skip ci] 2026-05-12 19:29:52 +00:00
jmiller ee63182514 chore: force-sync .mokogitea/workflows/copilot-agent.yml [skip ci] 2026-05-12 19:29:52 +00:00
jmiller 28790a305d chore: force-sync .mokogitea/workflows/codeql-analysis.yml [skip ci] 2026-05-12 19:29:51 +00:00
jmiller 03bbac3d94 chore: force-sync .mokogitea/workflows/changelog-validation.yml [skip ci] 2026-05-12 19:29:51 +00:00
jmiller 3fb3fff984 chore: force-sync .mokogitea/workflows/auto-dev-issue.yml [skip ci] 2026-05-12 19:29:51 +00:00
jmiller 66fda0b1ba chore: remove .mokogitea/.moko-platform [skip ci] 2026-05-12 19:29:50 +00:00
jmiller c0de26787c chore: force-sync .mokogitea/workflows/auto-assign.yml [skip ci] 2026-05-12 19:29:50 +00:00
jmiller 08c71092fc chore: move .mokogitea/manifest.xml to .mokogitea/ [skip ci] 2026-05-12 19:29:49 +00:00
jmiller fa328dca21 chore: force-sync .mokogitea/ISSUE_TEMPLATE/version.md [skip ci] 2026-05-12 19:29:49 +00:00
jmiller 7f5f201278 chore: force-sync .mokogitea/ISSUE_TEMPLATE/security.md [skip ci] 2026-05-12 19:29:49 +00:00
jmiller e1b808792a chore: force-sync .mokogitea/ISSUE_TEMPLATE/rfc.md [skip ci] 2026-05-12 19:29:48 +00:00
jmiller 3f070cfa4d chore: force-sync .mokogitea/ISSUE_TEMPLATE/question.md [skip ci] 2026-05-12 19:29:48 +00:00
jmiller 6608bcd98e chore: force-sync .mokogitea/ISSUE_TEMPLATE/firewall-request.md [skip ci] 2026-05-12 19:29:48 +00:00
jmiller 5b8191ee50 chore: force-sync .mokogitea/ISSUE_TEMPLATE/feature_request.md [skip ci] 2026-05-12 19:29:47 +00:00
jmiller 2925f6b5cf chore: force-sync .mokogitea/ISSUE_TEMPLATE/enterprise_support.md [skip ci] 2026-05-12 19:29:47 +00:00
jmiller 3ce45baeed chore: force-sync .mokogitea/ISSUE_TEMPLATE/documentation.md [skip ci] 2026-05-12 19:29:46 +00:00
jmiller 2a9ca24da4 chore: force-sync .mokogitea/ISSUE_TEMPLATE/config.yml [skip ci] 2026-05-12 19:29:46 +00:00
jmiller 9e3bac35b8 chore: force-sync .mokogitea/ISSUE_TEMPLATE/bug_report.md [skip ci] 2026-05-12 19:29:46 +00:00
jmiller 4dc48d3bd0 chore: force-sync .mokogitea/ISSUE_TEMPLATE/adr.md [skip ci] 2026-05-12 19:29:45 +00:00
jmiller 920153e8aa chore: force-sync .mokogitea/workflows/sync-version-on-merge.yml [skip ci] 2026-05-12 19:29:45 +00:00
jmiller f0079b6918 chore: force-sync .mokogitea/workflows/standards-compliance.yml [skip ci] 2026-05-12 19:29:45 +00:00
jmiller 522e6f7400 chore: force-sync .mokogitea/workflows/security-audit.yml [skip ci] 2026-05-12 19:29:44 +00:00
jmiller a160574f92 chore: force-sync .mokogitea/workflows/repository-cleanup.yml [skip ci] 2026-05-12 19:29:44 +00:00
jmiller 8bcea5ad07 chore: force-sync .mokogitea/workflows/pr-check.yml [skip ci] 2026-05-12 19:29:43 +00:00
jmiller 2e91f3a578 chore: force-sync .mokogitea/workflows/notify.yml [skip ci] 2026-05-12 19:29:43 +00:00
jmiller db3c80d5b3 chore: force-sync .mokogitea/workflows/mcp-tool-inventory.yml [skip ci] 2026-05-12 19:29:43 +00:00
jmiller 577b93a330 chore: force-sync .mokogitea/workflows/mcp-sdk-check.yml [skip ci] 2026-05-12 19:29:42 +00:00
jmiller 0c7369d68e chore: force-sync .mokogitea/workflows/mcp-build-test.yml [skip ci] 2026-05-12 19:29:42 +00:00
jmiller 88810dd92b chore: force-sync .mokogitea/workflows/mcp-auto-release.yml [skip ci] 2026-05-12 19:29:42 +00:00
jmiller 8a7d803560 chore: force-sync .mokogitea/workflows/gitleaks.yml [skip ci] 2026-05-12 19:29:41 +00:00
jmiller 859728b1e1 chore: force-sync .mokogitea/workflows/enterprise-firewall-setup.yml [skip ci] 2026-05-12 19:29:41 +00:00
jmiller 10c5b174c1 chore: force-sync .mokogitea/workflows/copilot-agent.yml [skip ci] 2026-05-12 19:29:41 +00:00
jmiller f274e3a7b3 chore: force-sync .mokogitea/workflows/codeql-analysis.yml [skip ci] 2026-05-12 19:29:40 +00:00
jmiller e6784fb96a chore: force-sync .mokogitea/workflows/changelog-validation.yml [skip ci] 2026-05-12 19:29:40 +00:00
jmiller d32f7b404d chore: force-sync .mokogitea/workflows/auto-dev-issue.yml [skip ci] 2026-05-12 19:29:40 +00:00
jmiller 9d71d863be chore: force-sync .mokogitea/workflows/auto-assign.yml [skip ci] 2026-05-12 19:29:39 +00:00
jmiller a03ad3c8e5 chore: sync .mokogitea/ISSUE_TEMPLATE/version.md from template [skip ci] 2026-05-12 18:59:06 +00:00
jmiller b5cea63e7c chore: sync .mokogitea/ISSUE_TEMPLATE/security.md from template [skip ci] 2026-05-12 18:59:06 +00:00
jmiller 1244e32329 chore: sync .mokogitea/ISSUE_TEMPLATE/rfc.md from template [skip ci] 2026-05-12 18:59:06 +00:00
jmiller 66a477aa43 chore: sync .mokogitea/ISSUE_TEMPLATE/question.md from template [skip ci] 2026-05-12 18:59:05 +00:00
jmiller 8147d89cbb chore: sync .mokogitea/ISSUE_TEMPLATE/firewall-request.md from template [skip ci] 2026-05-12 18:59:05 +00:00
jmiller 2a9881d315 chore: sync .mokogitea/ISSUE_TEMPLATE/feature_request.md from template [skip ci] 2026-05-12 18:59:05 +00:00
jmiller 5d35207d34 chore: sync .mokogitea/ISSUE_TEMPLATE/enterprise_support.md from template [skip ci] 2026-05-12 18:59:04 +00:00
jmiller 1ef41025d6 chore: sync .mokogitea/ISSUE_TEMPLATE/documentation.md from template [skip ci] 2026-05-12 18:59:04 +00:00
jmiller d9eb102135 chore: sync .mokogitea/ISSUE_TEMPLATE/config.yml from template [skip ci] 2026-05-12 18:59:04 +00:00
jmiller 26610c5a05 chore: sync .mokogitea/ISSUE_TEMPLATE/bug_report.md from template [skip ci] 2026-05-12 18:59:03 +00:00
jmiller 4dc7792d63 chore: sync .mokogitea/ISSUE_TEMPLATE/adr.md from template [skip ci] 2026-05-12 18:59:03 +00:00
jmiller 5ccf23a61e chore: sync .mokogitea/workflows/sync-version-on-merge.yml from template [skip ci] 2026-05-12 18:59:03 +00:00
jmiller c8cc3c48f3 chore: sync .mokogitea/workflows/standards-compliance.yml from template [skip ci] 2026-05-12 18:59:02 +00:00
jmiller 5e36ab2e41 chore: sync .mokogitea/workflows/security-audit.yml from template [skip ci] 2026-05-12 18:59:02 +00:00
jmiller 362f93b0be chore: sync .mokogitea/workflows/repository-cleanup.yml from template [skip ci] 2026-05-12 18:59:02 +00:00
jmiller 70004ab833 chore: sync .mokogitea/workflows/pr-check.yml from template [skip ci] 2026-05-12 18:59:01 +00:00
jmiller 66274758fb chore: sync .mokogitea/workflows/notify.yml from template [skip ci] 2026-05-12 18:59:01 +00:00
jmiller 7811df4f62 chore: sync .mokogitea/workflows/mcp-tool-inventory.yml from template [skip ci] 2026-05-12 18:59:01 +00:00
jmiller 697e4b4dbb chore: sync .mokogitea/workflows/mcp-sdk-check.yml from template [skip ci] 2026-05-12 18:59:00 +00:00
jmiller 4e60a2e0b4 chore: sync .mokogitea/workflows/mcp-build-test.yml from template [skip ci] 2026-05-12 18:59:00 +00:00
jmiller 3519b0bbef chore: sync .mokogitea/workflows/mcp-auto-release.yml from template [skip ci] 2026-05-12 18:58:59 +00:00
jmiller f8a3771f7d chore: sync .mokogitea/workflows/gitleaks.yml from template [skip ci] 2026-05-12 18:58:59 +00:00
jmiller 1319cbf5a5 chore: sync .mokogitea/workflows/enterprise-firewall-setup.yml from template [skip ci] 2026-05-12 18:58:59 +00:00
jmiller 809c864024 chore: sync .mokogitea/workflows/copilot-agent.yml from template [skip ci] 2026-05-12 18:58:58 +00:00
jmiller 005b29901d chore: sync .mokogitea/workflows/codeql-analysis.yml from template [skip ci] 2026-05-12 18:58:58 +00:00
jmiller daef5653d9 chore: sync .mokogitea/workflows/changelog-validation.yml from template [skip ci] 2026-05-12 18:58:58 +00:00
jmiller ecdbfd9d22 chore: sync .mokogitea/ISSUE_TEMPLATE/version.md from template [skip ci] 2026-05-12 18:58:57 +00:00
jmiller 63b6bf8768 chore: sync .mokogitea/workflows/auto-dev-issue.yml from template [skip ci] 2026-05-12 18:58:57 +00:00
jmiller 92bc541b08 chore: sync .mokogitea/workflows/auto-assign.yml from template [skip ci] 2026-05-12 18:58:57 +00:00
jmiller 5f6897f81c chore: sync .mokogitea/ISSUE_TEMPLATE/security.md from template [skip ci] 2026-05-12 18:58:56 +00:00
jmiller a2df8fd353 chore: sync .mokogitea/ISSUE_TEMPLATE/rfc.md from template [skip ci] 2026-05-12 18:58:56 +00:00
jmiller 5262415589 chore: sync .mokogitea/ISSUE_TEMPLATE/question.md from template [skip ci] 2026-05-12 18:58:55 +00:00
jmiller c36d6449ee chore: sync .mokogitea/ISSUE_TEMPLATE/firewall-request.md from template [skip ci] 2026-05-12 18:58:55 +00:00
jmiller 3d2fa57574 chore: sync .mokogitea/ISSUE_TEMPLATE/feature_request.md from template [skip ci] 2026-05-12 18:58:55 +00:00
jmiller c4a0290cd7 chore: sync .mokogitea/ISSUE_TEMPLATE/enterprise_support.md from template [skip ci] 2026-05-12 18:58:54 +00:00
jmiller fc34ce75a7 chore: sync .mokogitea/ISSUE_TEMPLATE/documentation.md from template [skip ci] 2026-05-12 18:58:54 +00:00
jmiller 4fae6658f3 chore: sync .mokogitea/ISSUE_TEMPLATE/config.yml from template [skip ci] 2026-05-12 18:58:54 +00:00
jmiller cd619c6e04 chore: sync .mokogitea/ISSUE_TEMPLATE/bug_report.md from template [skip ci] 2026-05-12 18:58:53 +00:00
jmiller 341fa45e89 chore: sync .mokogitea/ISSUE_TEMPLATE/adr.md from template [skip ci] 2026-05-12 18:58:53 +00:00
jmiller 23ad8dc843 chore: sync .mokogitea/workflows/sync-version-on-merge.yml from template [skip ci] 2026-05-12 18:58:53 +00:00
jmiller 68756ec570 chore: sync .mokogitea/workflows/standards-compliance.yml from template [skip ci] 2026-05-12 18:58:52 +00:00
jmiller ba43b805d4 chore: sync .mokogitea/workflows/security-audit.yml from template [skip ci] 2026-05-12 18:58:52 +00:00
jmiller 06b8142391 chore: sync .mokogitea/workflows/repository-cleanup.yml from template [skip ci] 2026-05-12 18:58:51 +00:00
jmiller 18c31a6a53 chore: sync .mokogitea/workflows/pr-check.yml from template [skip ci] 2026-05-12 18:58:51 +00:00
jmiller a3aad2adf8 chore: sync .mokogitea/workflows/notify.yml from template [skip ci] 2026-05-12 18:58:51 +00:00
jmiller 8fba4e7c3d chore: sync .mokogitea/workflows/mcp-tool-inventory.yml from template [skip ci] 2026-05-12 18:58:50 +00:00
jmiller 7dbd99ade1 chore: sync .mokogitea/workflows/mcp-sdk-check.yml from template [skip ci] 2026-05-12 18:58:50 +00:00
jmiller a76a79b49c chore: sync .mokogitea/workflows/mcp-build-test.yml from template [skip ci] 2026-05-12 18:58:50 +00:00
jmiller bc132a1e5b chore: sync .mokogitea/workflows/mcp-auto-release.yml from template [skip ci] 2026-05-12 18:58:49 +00:00
jmiller 0fdefa75ca chore: sync .mokogitea/workflows/gitleaks.yml from template [skip ci] 2026-05-12 18:58:49 +00:00
jmiller ac91f28deb chore: sync .mokogitea/workflows/enterprise-firewall-setup.yml from template [skip ci] 2026-05-12 18:58:49 +00:00
jmiller 7f63ba3d2f chore: sync .mokogitea/workflows/copilot-agent.yml from template [skip ci] 2026-05-12 18:58:48 +00:00
jmiller 064946b9e1 chore: sync .mokogitea/workflows/codeql-analysis.yml from template [skip ci] 2026-05-12 18:58:48 +00:00
jmiller b1743893ad chore: sync .mokogitea/workflows/changelog-validation.yml from template [skip ci] 2026-05-12 18:58:48 +00:00
jmiller 6f0e1b47a0 chore: sync .mokogitea/workflows/auto-dev-issue.yml from template [skip ci] 2026-05-12 18:58:47 +00:00
jmiller c42f1017c3 chore: sync .mokogitea/workflows/auto-assign.yml from template [skip ci] 2026-05-12 18:58:47 +00:00
jmiller 4bb13e3fbd chore: remove .gitea/workflows/sync-version-on-merge.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:42 +00:00
jmiller a39ea2f6ca chore: move .gitea/workflows/sync-version-on-merge.yml to .mokogitea/sync-version-on-merge.yml [skip ci] 2026-05-12 05:14:41 +00:00
jmiller 950730f5a9 chore: remove .gitea/workflows/standards-compliance.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:41 +00:00
jmiller 7375b5fe58 chore: move .gitea/workflows/standards-compliance.yml to .mokogitea/standards-compliance.yml [skip ci] 2026-05-12 05:14:41 +00:00
jmiller 33581716cb chore: remove .gitea/workflows/repository-cleanup.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:40 +00:00
jmiller 2b27a798be chore: move .gitea/workflows/repository-cleanup.yml to .mokogitea/repository-cleanup.yml [skip ci] 2026-05-12 05:14:40 +00:00
jmiller 4eb54ae62a chore: remove .gitea/workflows/pr-branch-check.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:39 +00:00
jmiller 1aa6382274 chore: move .gitea/workflows/pr-branch-check.yml to .mokogitea/pr-branch-check.yml [skip ci] 2026-05-12 05:14:39 +00:00
jmiller 5ca34eaca3 chore: remove .gitea/workflows/mcp-tool-inventory.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:39 +00:00
jmiller 6b359c44ce chore: move .gitea/workflows/mcp-tool-inventory.yml to .mokogitea/mcp-tool-inventory.yml [skip ci] 2026-05-12 05:14:38 +00:00
jmiller 151c808c59 chore: remove .gitea/workflows/mcp-sdk-check.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:38 +00:00
jmiller 401ff59483 chore: move .gitea/workflows/mcp-sdk-check.yml to .mokogitea/mcp-sdk-check.yml [skip ci] 2026-05-12 05:14:38 +00:00
jmiller d5e0202bf6 chore: remove .gitea/workflows/mcp-build-test.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:37 +00:00
jmiller 10c1f5f7b6 chore: move .gitea/workflows/mcp-build-test.yml to .mokogitea/mcp-build-test.yml [skip ci] 2026-05-12 05:14:37 +00:00
jmiller ba269af964 chore: remove .gitea/workflows/mcp-auto-release.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:37 +00:00
jmiller 51f4091388 chore: move .gitea/workflows/mcp-auto-release.yml to .mokogitea/mcp-auto-release.yml [skip ci] 2026-05-12 05:14:36 +00:00
jmiller aee58c0f5a chore: remove .gitea/workflows/gitleaks.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:36 +00:00
jmiller b607d4181b chore: move .gitea/workflows/gitleaks.yml to .mokogitea/gitleaks.yml [skip ci] 2026-05-12 05:14:35 +00:00
jmiller 0fb6523941 chore: remove .gitea/workflows/enterprise-firewall-setup.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:35 +00:00
jmiller 013924b699 chore: move .gitea/workflows/enterprise-firewall-setup.yml to .mokogitea/enterprise-firewall-setup.yml [skip ci] 2026-05-12 05:14:35 +00:00
jmiller d5c38b390b chore: remove .gitea/workflows/deploy-dev.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:34 +00:00
jmiller 9f3e43f8ef chore: move .gitea/workflows/deploy-dev.yml to .mokogitea/deploy-dev.yml [skip ci] 2026-05-12 05:14:34 +00:00
jmiller 2a32530f47 chore: remove .gitea/workflows/deploy-demo.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:34 +00:00
jmiller 39473e1490 chore: move .gitea/workflows/deploy-demo.yml to .mokogitea/deploy-demo.yml [skip ci] 2026-05-12 05:14:33 +00:00
jmiller a6d5b885e3 chore: remove .gitea/workflows/copilot-agent.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:33 +00:00
jmiller 8173681e89 chore: move .gitea/workflows/copilot-agent.yml to .mokogitea/copilot-agent.yml [skip ci] 2026-05-12 05:14:32 +00:00
jmiller b07ed5302b chore: remove .gitea/workflows/codeql-analysis.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:32 +00:00
jmiller c23a0ef66f chore: move .gitea/workflows/codeql-analysis.yml to .mokogitea/codeql-analysis.yml [skip ci] 2026-05-12 05:14:32 +00:00
jmiller 3e7439a067 chore: remove .gitea/workflows/changelog-validation.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:31 +00:00
jmiller 760d398dee chore: move .gitea/workflows/changelog-validation.yml to .mokogitea/changelog-validation.yml [skip ci] 2026-05-12 05:14:31 +00:00
jmiller e9cb01d723 chore: remove .gitea/workflows/cascade-dev.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:31 +00:00
jmiller 095c01d98f chore: move .gitea/workflows/cascade-dev.yml to .mokogitea/cascade-dev.yml [skip ci] 2026-05-12 05:14:30 +00:00
jmiller edb53bb6b7 chore: remove .gitea/workflows/auto-release.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:30 +00:00
jmiller ed1d3acbe9 chore: move .gitea/workflows/auto-release.yml to .mokogitea/auto-release.yml [skip ci] 2026-05-12 05:14:30 +00:00
jmiller 8d3900e423 chore: remove .gitea/workflows/auto-dev-issue.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:29 +00:00
jmiller f7212d2895 chore: move .gitea/workflows/auto-dev-issue.yml to .mokogitea/auto-dev-issue.yml [skip ci] 2026-05-12 05:14:29 +00:00
jmiller 8e29ee1a1b chore: remove .gitea/workflows/auto-assign.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:28 +00:00
jmiller ba27e29e02 chore: move .gitea/workflows/auto-assign.yml to .mokogitea/auto-assign.yml [skip ci] 2026-05-12 05:14:28 +00:00
jmiller ff6d081829 chore: remove .gitea/workflows/sync-version-on-merge.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:27 +00:00
jmiller a56a3f6f45 chore: remove .gitea/.moko-platform (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:27 +00:00
jmiller b245de09b8 chore: move .gitea/.moko-platform to .mokogitea/.moko-platform [skip ci] 2026-05-12 05:14:27 +00:00
jmiller c766ac5c66 chore: move .gitea/workflows/sync-version-on-merge.yml to .mokogitea/sync-version-on-merge.yml [skip ci] 2026-05-12 05:14:26 +00:00
jmiller 13fb62b9a1 chore: remove .gitea/workflows/standards-compliance.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:26 +00:00
jmiller 6b6367220b chore: move .gitea/workflows/standards-compliance.yml to .mokogitea/standards-compliance.yml [skip ci] 2026-05-12 05:14:25 +00:00
jmiller f8b2bd1cde chore: remove .gitea/workflows/repository-cleanup.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:25 +00:00
jmiller 8f54dd9fe9 chore: move .gitea/workflows/repository-cleanup.yml to .mokogitea/repository-cleanup.yml [skip ci] 2026-05-12 05:14:25 +00:00
jmiller b94a7e4fbe chore: remove .gitea/workflows/pr-branch-check.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:24 +00:00
jmiller 066b9c59ac chore: move .gitea/workflows/pr-branch-check.yml to .mokogitea/pr-branch-check.yml [skip ci] 2026-05-12 05:14:24 +00:00
jmiller bc041ef97b chore: remove .gitea/workflows/mcp-tool-inventory.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:24 +00:00
jmiller 1281e7eecf chore: move .gitea/workflows/mcp-tool-inventory.yml to .mokogitea/mcp-tool-inventory.yml [skip ci] 2026-05-12 05:14:23 +00:00
jmiller 67c11ac20b chore: remove .gitea/workflows/mcp-sdk-check.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:23 +00:00
jmiller 8c8f9a56d2 chore: move .gitea/workflows/mcp-sdk-check.yml to .mokogitea/mcp-sdk-check.yml [skip ci] 2026-05-12 05:14:22 +00:00
jmiller 6437669abf chore: remove .gitea/workflows/mcp-build-test.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:22 +00:00
jmiller 587a2af752 chore: move .gitea/workflows/mcp-build-test.yml to .mokogitea/mcp-build-test.yml [skip ci] 2026-05-12 05:14:22 +00:00
jmiller 91e0380b3d chore: remove .gitea/workflows/mcp-auto-release.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:21 +00:00
jmiller 43d8ceec87 chore: move .gitea/workflows/mcp-auto-release.yml to .mokogitea/mcp-auto-release.yml [skip ci] 2026-05-12 05:14:21 +00:00
jmiller f3f9d8b7a4 chore: remove .gitea/workflows/gitleaks.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:21 +00:00
jmiller 54e5874277 chore: move .gitea/workflows/gitleaks.yml to .mokogitea/gitleaks.yml [skip ci] 2026-05-12 05:14:20 +00:00
jmiller 655fc4e488 chore: remove .gitea/workflows/enterprise-firewall-setup.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:20 +00:00
jmiller c7e7ed01c5 chore: move .gitea/workflows/enterprise-firewall-setup.yml to .mokogitea/enterprise-firewall-setup.yml [skip ci] 2026-05-12 05:14:20 +00:00
jmiller f3821a4882 chore: remove .gitea/workflows/deploy-dev.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:19 +00:00
jmiller f2906c5923 chore: move .gitea/workflows/deploy-dev.yml to .mokogitea/deploy-dev.yml [skip ci] 2026-05-12 05:14:19 +00:00
jmiller ca87e6e523 chore: remove .gitea/workflows/deploy-demo.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:18 +00:00
jmiller 037a35ba80 chore: move .gitea/workflows/deploy-demo.yml to .mokogitea/deploy-demo.yml [skip ci] 2026-05-12 05:14:18 +00:00
jmiller 3cb2e7f079 chore: remove .gitea/workflows/copilot-agent.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:18 +00:00
jmiller 6a8869520e chore: move .gitea/workflows/copilot-agent.yml to .mokogitea/copilot-agent.yml [skip ci] 2026-05-12 05:14:17 +00:00
jmiller a335eca50e chore: remove .gitea/workflows/codeql-analysis.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:17 +00:00
jmiller a26f2a2528 chore: move .gitea/workflows/codeql-analysis.yml to .mokogitea/codeql-analysis.yml [skip ci] 2026-05-12 05:14:17 +00:00
jmiller b5e3f79b02 chore: remove .gitea/workflows/changelog-validation.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:16 +00:00
jmiller 84507f1403 chore: move .gitea/workflows/changelog-validation.yml to .mokogitea/changelog-validation.yml [skip ci] 2026-05-12 05:14:16 +00:00
jmiller 61e1d3fd2b chore: remove .gitea/workflows/cascade-dev.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:15 +00:00
jmiller ac6fa96eeb chore: move .gitea/workflows/cascade-dev.yml to .mokogitea/cascade-dev.yml [skip ci] 2026-05-12 05:14:15 +00:00
jmiller c002f7499c chore: remove .gitea/workflows/auto-release.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:15 +00:00
jmiller e2ca60cbf9 chore: move .gitea/workflows/auto-release.yml to .mokogitea/auto-release.yml [skip ci] 2026-05-12 05:14:14 +00:00
jmiller 88e97f410d chore: remove .gitea/workflows/auto-dev-issue.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:14 +00:00
jmiller 2a31162223 chore: move .gitea/workflows/auto-dev-issue.yml to .mokogitea/auto-dev-issue.yml [skip ci] 2026-05-12 05:14:14 +00:00
jmiller 22051a3d32 chore: remove .gitea/workflows/auto-assign.yml (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:13 +00:00
jmiller 85c6749c46 chore: move .gitea/workflows/auto-assign.yml to .mokogitea/auto-assign.yml [skip ci] 2026-05-12 05:14:13 +00:00
jmiller bbd3c3e37b chore: remove .gitea/.moko-platform (moved to .mokogitea/) [skip ci] 2026-05-12 05:14:12 +00:00
jmiller 4dac035b92 chore: move .gitea/.moko-platform to .mokogitea/.moko-platform [skip ci] 2026-05-12 05:14:12 +00:00
jmiller 6c2a87508e Merge pull request 'chore: cascade main → dev (db487fd) [skip ci]' (#5) from main into dev 2026-05-11 21:18:45 +00:00
jmiller db487fdd57 chore: remove ROADMAP.md — moved to issues-based roadmap
Cascade Main → Dev / Cascade main → branches (push) Successful in 2s
Changelog Validation / Validate CHANGELOG.md (push) Failing after 3s
Standards Compliance / Secret Scanning (push) Successful in 3s
Standards Compliance / License Header Validation (push) Successful in 2s
Standards Compliance / Repository Structure Validation (push) Failing after 2s
Standards Compliance / Coding Standards Check (push) Failing after 3s
Standards Compliance / Workflow Configuration Check (push) Failing after 3s
Standards Compliance / Documentation Quality Check (push) Successful in 3s
Standards Compliance / README Completeness Check (push) Failing after 3s
Standards Compliance / Git Repository Hygiene (push) Successful in 2s
Standards Compliance / Script Integrity Validation (push) Successful in 4s
Standards Compliance / Line Length Check (push) Failing after 7s
Standards Compliance / File Naming Standards (push) Successful in 3s
Standards Compliance / Insecure Code Pattern Detection (push) Successful in 3s
Standards Compliance / Version Consistency Check (push) Successful in 38s
Standards Compliance / Code Complexity Analysis (push) Successful in 32s
Standards Compliance / Dead Code Detection (push) Successful in 4s
Standards Compliance / File Size Limits (push) Successful in 2s
Standards Compliance / Binary File Detection (push) Successful in 3s
Standards Compliance / Code Duplication Detection (push) Successful in 33s
Standards Compliance / TODO/FIXME Tracking (push) Successful in 3s
Standards Compliance / Broken Link Detection (push) Successful in 3s
Standards Compliance / API Documentation Coverage (push) Successful in 3s
Standards Compliance / Accessibility Check (push) Successful in 3s
Standards Compliance / Performance Metrics (push) Successful in 3s
Standards Compliance / Dependency Vulnerability Scanning (push) Successful in 36s
Standards Compliance / Unused Dependencies Check (push) Successful in 37s
Standards Compliance / Terraform Configuration Validation (push) Successful in 6s
Standards Compliance / Enterprise Readiness Check (push) Failing after 34s
Standards Compliance / Repository Health Check (push) Failing after 34s
Sync Version from README / Propagate README version (push) Failing after 32s
Standards Compliance / Compliance Summary (push) Failing after 1s
Repository Cleanup / Repository Maintenance (push) Failing after 30s
Secret Scanning / Gitleaks Secret Scan (push) Successful in 4s
CodeQL Security Scanning / Analyze (actions) (push) Failing after 13m8s
CodeQL Security Scanning / Analyze (javascript) (push) Failing after 13m6s
CodeQL Security Scanning / Security Scan Summary (push) Successful in 1s
MCP SDK Version Check / check-sdk (push) Failing after 9s
Auto-Assign Issues & PRs / Assign unassigned issues and PRs (push) Successful in 1s
2026-05-11 21:18:15 +00:00
jmiller 2d2442f9ae chore: remove ROADMAP.md — moved to issues-based roadmap 2026-05-11 21:18:15 +00:00
jmiller 7072493fe2 chore: add PR branch policy check workflow [skip ci] 2026-05-11 17:16:03 +00:00
jmiller 57ba1053f5 security: add permissions block to mcp-tool-inventory.yml [skip ci] 2026-05-11 16:36:16 +00:00
jmiller 0144e1e440 security: add permissions block to mcp-sdk-check.yml [skip ci] 2026-05-11 16:36:16 +00:00
jmiller cf88c15a1b security: add permissions block to mcp-build-test.yml [skip ci] 2026-05-11 16:36:16 +00:00
jmiller e043d02078 chore: remove renovate.json [skip ci] 2026-05-10 19:57:25 +00:00
jmiller c47b1afd84 chore: remove renovate.json [skip ci] 2026-05-10 19:57:25 +00:00
jmiller 42b471c7fe docs: add CLAUDE.md for Claude Code context [skip ci] 2026-05-10 19:55:22 +00:00
jmiller 2093b9f651 chore: add .moko-platform manifest [skip ci] 2026-05-10 19:51:10 +00:00
jmiller 788c82ba6f chore: remove deprecated .mokostandards (now .moko-platform) [skip ci] 2026-05-10 19:48:58 +00:00
jmiller ac0b3d01ac Merge pull request 'chore: cascade main → dev (5c16823) [skip ci]' (#4) from main into dev 2026-05-10 18:41:58 +00:00
jmiller 5c16823219 docs: update README from wiki Home
Secret Scanning / Gitleaks Secret Scan (push) Successful in 4s
MCP SDK Version Check / check-sdk (push) Failing after 6s
Auto-Assign Issues & PRs / Assign unassigned issues and PRs (push) Successful in 1s
Cascade Main → Dev / Cascade main → branches (push) Has been cancelled
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
2026-05-10 18:39:20 +00:00
jmiller bdf0020f9d Merge pull request 'chore: cascade main → dev (3f89873) [skip ci]' (#3) from main into dev 2026-05-07 20:25:19 +00:00
Jonathan Miller 3f89873f19 ci(mcp): add MCP auto-release workflow with build, tool inventory, and dist artifact
Auto-Assign Issues & PRs / Assign unassigned issues and PRs (push) Successful in 1s
Cascade Main → Dev / Cascade main → branches (push) Has been cancelled
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 15:25:04 -05:00
Jonathan Miller 8cdb543b05 ci(mcp): add MCP-specific workflows — build validation, SDK check, tool inventory
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 15:25:03 -05:00
Jonathan Miller e28a2cc4dc docs: update API reference and README for 67 tools
Expand API.md with full parameter tables for all new tools: contacts,
banners, newsfeeds, tags, custom fields, menu items, messages, media,
redirects, associations, checkin, and content history. Update README
tool listing to match.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 15:25:03 -05:00
Moko Standards Bot eae854a9b5 ci: add Gitleaks secret scanning + Renovate dependency config [skip ci] 2026-05-07 15:00:18 -05:00
Jonathan Miller 512364e46d ci: cascade v2 — forward-merge main to all open branches [skip ci] 2026-05-07 14:35:32 -05:00
jmiller f01529627f Merge pull request 'chore: cascade main → dev (222c343) [skip ci]' (#2) from main into dev 2026-05-07 19:23:54 +00:00
Jonathan Miller 222c343df8 fix: resolve mokostandards merge conflict, set platform to mcp-server
Cascade Main → Dev / Merge main → dev (push) Has been cancelled
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 14:23:41 -05:00
jmiller f809f8d069 Merge pull request 'chore: cascade main → dev (b28f3be) [skip ci]' (#1) from main into dev 2026-05-07 19:23:22 +00:00
Jonathan Miller b28f3bea96 feat(tools): expand to 67 tools — full CRUD for contacts, banners, newsfeeds, tags, fields, menu items, messages, media, redirects, associations, checkin, and content history
Cascade Main → Dev / Merge main → dev (push) Has been cancelled
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Build & Release / Build & Release Pipeline (push) Has been cancelled
Deploy to Demo Server (SFTP) / Verify Deployment Permission (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
Deploy to Demo Server (SFTP) / SFTP Deploy → Demo (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-07 14:22:54 -05:00
jmiller a97a072be4 ci: add cascade main → dev workflow [skip ci] 2026-05-05 16:55:56 -05:00
gitea-actions[bot] 67ea51a256 chore: enrich .mokostandards with build/deploy/scripts
Auto-Assign Issues & PRs / Assign unassigned issues and PRs (push) Successful in 1s
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
2026-05-02 18:13:19 -05:00
gitea-actions[bot] 551934f76b chore: add XML .mokostandards manifest
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
2026-05-02 18:06:11 -05:00
gitea-actions[bot] 770deb1fb5 chore: remove .github/ — all workflows in .gitea/ [skip ci] 2026-04-26 22:55:11 -05:00
Jonathan Miller 61dce0abac chore: replace jmiller-moko with jmiller, move .mokostandards to .gitea/
Repository Cleanup / Repository Maintenance (push) Failing after 38s
Auto-Assign Issues & PRs / Assign unassigned issues and PRs (push) Successful in 1s
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
2026-04-26 22:35:29 -05:00
Jonathan Miller 00302af06d chore: remove copilot-agent.yml (GitHub-only, not needed on Gitea)
Auto-Assign Issues & PRs / Assign unassigned issues and PRs (push) Successful in 1s
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
2026-04-26 18:44:01 -05:00
Jonathan Miller 1a63ed6722 chore: add profile.ps1 to .gitignore
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
2026-04-26 16:03:11 -05:00
Jonathan Miller e6e90d30bc chore: add .mokostandards platform definition (default-repository)
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
2026-04-26 13:38:45 -05:00
jmiller 920d82e151 chore: add TODO.md from MokoStandards 2026-04-26 16:35:57 +00:00
jmiller d7fddb49d3 chore: add TODO.md from MokoStandards
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
2026-04-26 16:35:57 +00:00
Jonathan Miller 07504255f6 release: v1.0.0 — stable release
Auto-Assign Issues & PRs / Assign unassigned issues and PRs (push) Successful in 1s
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Build & Release / Build & Release Pipeline (push) Has been cancelled
Deploy to Demo Server (SFTP) / Verify Deployment Permission (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Deploy to Demo Server (SFTP) / SFTP Deploy → Demo (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
Joomla Web Services API MCP server with:
- 30+ tools for articles, categories, users, menus, plugins, modules,
  templates, tags, contacts, banners, media, config, and raw API access
- Multi-site support with per-connection API tokens
- Node 24 TLS compatibility (node:https for self-signed certs)
- Dirty JSON recovery for Joomla responses with HTML fragments
- Interactive setup wizard (npm run setup)
- JOOMLA_API_MCP_CONFIG env var for custom config path

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 15:09:32 -05:00
Jonathan Miller 17f5ce7342 fix: deploy-dev passes silently without path, add env config override
- deploy-dev.yml: skip silently when DEV_FTP_PATH is missing instead of failing
- config.ts: support JOOMLA_API_MCP_CONFIG env var for custom config path
- Clean up stale template files from src/
- Update sftp-config template with per-repo deploy key paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 15:06:21 -05:00
Jonathan Miller ea0a028128 docs: add installation guide, architecture overview, and API reference
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
- docs/INSTALLATION.md: setup instructions, config format, troubleshooting
- docs/ARCHITECTURE.md: component overview and design decisions
- docs/API.md: complete MCP tool reference with all parameters

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 12:36:31 -05:00
Jonathan Miller f8b07e5f38 feat: implement Joomla Web Services API MCP server
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Deploy to Demo Server (SFTP) / Verify Deployment Permission (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Build & Release / Build & Release Pipeline (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Deploy to Demo Server (SFTP) / SFTP Deploy → Demo (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
Replace template scaffold with a working MCP server that connects
to Joomla 4/5/6 sites via the REST API. Includes tools for articles,
categories, users, menus, plugins, modules, templates, tags, contacts,
banners, media, config, and a raw API passthrough.

- Use node:https for proper self-signed cert support on Node 24+
- Handle Joomla responses that append HTML after valid JSON
- Add interactive setup wizard (npm run setup) for multi-site config
- Support multiple named connections with per-site API tokens

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-23 11:38:34 -05:00
jmiller 4c8ce365e0 docs: update all documentation to current standards
Changelog Validation / Validate CHANGELOG.md (push) Has been cancelled
Standards Compliance / Secret Scanning (push) Has been cancelled
Standards Compliance / License Header Validation (push) Has been cancelled
Standards Compliance / Repository Structure Validation (push) Has been cancelled
Standards Compliance / Coding Standards Check (push) Has been cancelled
Standards Compliance / Workflow Configuration Check (push) Has been cancelled
Standards Compliance / Documentation Quality Check (push) Has been cancelled
Standards Compliance / README Completeness Check (push) Has been cancelled
Standards Compliance / Git Repository Hygiene (push) Has been cancelled
Standards Compliance / Script Integrity Validation (push) Has been cancelled
Standards Compliance / Line Length Check (push) Has been cancelled
Standards Compliance / File Naming Standards (push) Has been cancelled
Standards Compliance / Insecure Code Pattern Detection (push) Has been cancelled
Standards Compliance / Version Consistency Check (push) Has been cancelled
CodeQL Security Scanning / Analyze (javascript) (push) Has been cancelled
CodeQL Security Scanning / Analyze (actions) (push) Has been cancelled
Standards Compliance / Code Complexity Analysis (push) Has been cancelled
Standards Compliance / Dead Code Detection (push) Has been cancelled
Standards Compliance / File Size Limits (push) Has been cancelled
Standards Compliance / Binary File Detection (push) Has been cancelled
Standards Compliance / TODO/FIXME Tracking (push) Has been cancelled
Standards Compliance / Broken Link Detection (push) Has been cancelled
Standards Compliance / API Documentation Coverage (push) Has been cancelled
Standards Compliance / Accessibility Check (push) Has been cancelled
Standards Compliance / Performance Metrics (push) Has been cancelled
Standards Compliance / Code Duplication Detection (push) Has been cancelled
Standards Compliance / Dependency Vulnerability Scanning (push) Has been cancelled
Standards Compliance / Unused Dependencies Check (push) Has been cancelled
Standards Compliance / Terraform Configuration Validation (push) Has been cancelled
CodeQL Security Scanning / Security Scan Summary (push) Has been cancelled
Standards Compliance / Enterprise Readiness Check (push) Has been cancelled
Standards Compliance / Repository Health Check (push) Has been cancelled
Standards Compliance / Compliance Summary (push) Has been cancelled
Sync Version from README / Propagate README version (push) Has been cancelled
- Copyright year 2025 -> 2026
- Primary URLs: GitHub -> Gitea
- CONTRIBUTING.md: add Infrastructure Standards section
- SECURITY.md: add Gitea issue reporting
- README.md: update badge URLs to Gitea
- Issue templates: update URLs to Gitea

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-22 09:10:09 +00:00
jmiller d22e05765f chore: sync template with latest standards
- Add .gitea/workflows mirroring .github/workflows
- Add release and infrastructure standards to CLAUDE.md
- Add standards to copilot-instructions.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-22 09:05:57 +00:00
96 changed files with 11558 additions and 2069 deletions
-309
View File
@@ -1,309 +0,0 @@
<!--
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: MokoStandards.Templates.GitHub
INGROUP: MokoStandards.Templates
REPO: https://github.com/mokoconsulting-tech/MokoStandards
PATH: /templates/github/copilot-instructions.md.template
VERSION: XX.YY.ZZ
BRIEF: Standard GitHub Copilot custom instructions template for Moko Consulting governed repositories
NOTE: Synced to .github/copilot-instructions.md in all governed repositories via bulk sync.
Tokens replaced at sync time: MokoStandards-Template-Generic, https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic, PHP, Generic project
-->
> [!IMPORTANT]
> **🔧 AI Self-Update Required on First Use**
>
> This file may contain unfilled `{{TOKEN}}` placeholders. The MokoStandards bulk-sync system
> replaces them automatically at sync time; if you can still see them, sync has not yet run for
> this repository — or this is a brand-new repo.
>
> **On your very first interaction in this repository, before answering any other question:**
>
> 1. Check whether any `{{TOKEN}}` placeholders remain in this file.
> 2. If they do, locate the values as described in the table below and replace every occurrence
> in **both** `.github/copilot-instructions.md` and `.github/CLAUDE.md`.
> 3. After replacing all tokens, **delete this entire notice block** (from `> [!IMPORTANT]`
> through the closing `> ---` line) in both files.
> 4. Tell the developer: *"I've self-updated the AI context files with this repository's
> values — all set."*
>
> | Placeholder | Where to find the value |
> |---|---|
> | `MokoStandards-Template-Generic` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) |
> | `https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/<repo-name>` |
> | `PHP` | The dominant programming language (check file extensions in the repository) |
> | `Generic project` | The project type: `PHP library`, `Joomla extension`, `Dolibarr module`, `WaaS site`, etc. — infer from repo structure |
>
> ---
# MokoStandards-Template-Generic — GitHub Copilot Custom Instructions
## What This Repo Is
This is a **Moko Consulting** repository governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). All coding standards, workflows, and policies are defined there and enforced here via bulk sync.
Repository URL: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic
Primary language: **PHP**
Platform type: **Generic project**
---
## Primary Language
**PHP is the primary language for this repository.** Follow the conventions documented in [MokoStandards coding-style-guide](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md).
YAML uses 2-space indentation (spaces, not tabs). All other text files use tabs per `.editorconfig`.
---
## File Header — Always Required on New Files
Every new file needs a copyright header as its first content. Use the minimal form unless the file is a policy doc, README, or public API.
**PHP:**
```php
<?php
/* 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: MokoStandards-Template-Generic.Module
* INGROUP: MokoStandards-Template-Generic
* REPO: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic
* PATH: /path/to/file.php
* VERSION: XX.YY.ZZ
* BRIEF: One-line description of purpose
*/
declare(strict_types=1);
```
**Markdown:**
```markdown
<!--
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: MokoStandards-Template-Generic.Documentation
INGROUP: MokoStandards-Template-Generic
REPO: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic
PATH: /docs/file.md
VERSION: XX.YY.ZZ
BRIEF: One-line description
-->
```
**YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt.
---
## Version Management
**`README.md` is the single source of truth for the repository version.**
- **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03``01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`.
- The `VERSION: XX.YY.ZZ` field in the README.md `FILE INFORMATION` block governs all other version references.
- Update the version in `README.md` only — the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`.
- Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `04.00.04`).
- Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only.
---
## GitHub Actions — Token Usage
Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). This applies to all `actions/checkout`, `gh` CLI calls, and any step that talks to the GitHub API.
```yaml
# ✅ Correct
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.GH_TOKEN }}
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
```
```yaml
# ❌ Wrong — never use these in workflows
token: ${{ github.token }}
token: ${{ secrets.GITHUB_TOKEN }}
```
PHP scripts read the token with: `getenv('GH_TOKEN') ?: getenv('GITHUB_TOKEN')``GH_TOKEN` is always preferred; `GITHUB_TOKEN` is accepted only as a local-dev fallback.
---
## Composer Package (PHP repositories)
This repository requires the MokoStandards enterprise library. The `composer.json` must include:
```json
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/mokoconsulting-tech/MokoStandards"
}
],
"require": {
"mokoconsulting/mokostandards": "^4.0"
}
}
```
Run `composer install` after adding the dependency. See [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) for full instructions.
---
## PHP Script Pattern
All PHP scripts **must** extend `MokoStandards\Enterprise\CliFramework`. Never write standalone classes or extend the legacy `CliBase`.
```php
#!/usr/bin/env php
<?php
/* … file header … */
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use MokoStandards\Enterprise\CliFramework;
class MyScript extends CliFramework
{
protected function configure(): void
{
$this->setDescription('One-line description');
$this->addArgument('--path', 'Repository root', '.');
$this->addArgument('--dry-run', 'Preview without writing', false);
}
protected function run(): int
{
$path = $this->getArgument('--path');
$dryRun = (bool) $this->getArgument('--dry-run');
$this->log('INFO', "Processing: {$path}");
return 0;
}
}
$script = new MyScript('my_script', 'One-line description');
exit($script->execute());
```
**Key rules:**
- Abstract methods to implement: `configure()` and `run()`**not** `execute()`
- `execute()` is the **public entry point** that orchestrates setup (arg parsing, `initialize()`) and then calls your `run()` implementation; call it at the bottom with `exit($script->execute())`
- Entry point at the bottom: `$script->execute()`**not** `$script->run()`
- Constructor always takes `(string $name, string $description = '')`; pass the description here — `setDescription()` inside `configure()` is only needed to override it
- `log(string $level, string $message)` — level is the **first** argument (INFO / SUCCESS / WARNING / ERROR)
- `$this->dryRun` and `$this->verbose` are set automatically from `--dry-run` / `--verbose`
---
## Naming Conventions
| Context | Convention | Example |
|---------|-----------|---------|
| PHP class | `PascalCase` | `MyService` |
| PHP method / function | `camelCase` | `getUserData()` |
| PHP variable | `$snake_case` | `$repo_path` |
| PHP constant | `UPPER_SNAKE_CASE` | `DEFAULT_THRESHOLD` |
| PHP class file | `PascalCase.php` | `ApiClient.php` |
| PHP script file | `snake_case.php` | `check_health.php` |
| YAML workflow | `kebab-case.yml` | `bulk-repo-sync.yml` |
| Markdown doc | `kebab-case.md` | `coding-style-guide.md` |
---
## Commit Messages
Format: `<type>(<scope>): <subject>` — imperative, lower-case subject, no trailing period.
Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build`
Examples:
- `feat(module): add user preference caching`
- `fix(api): handle null response from external service`
- `docs(readme): update installation instructions`
- `chore(deps): bump phpunit to 11.x`
---
## Branch Naming
Approved prefixes: `dev/` · `rc/` · `version/` · `copilot/` · `dependabot/`
- `dev/XX.YY` or `dev/feature-name` — development (version optional)
- `rc/XX.YY.ZZ` — release candidate (three-part required)
- `version/XX.YY` — archive branch (auto-created, two-part)
- Release tags: `vXX` (major only — one release per major version)
- Patch `00` = development (no release), first release = `01`
Examples:
-`dev/04.06` · `dev/new-dashboard` · `rc/04.06.01`
-`feature/my-thing` — rejected by branch protection
---
## Keeping Documentation Current
Whenever you make code changes, update the corresponding documentation in the same commit or PR. Do not leave docs stale.
| Change type | Documentation to update |
|-------------|------------------------|
| New or renamed public PHP method | PHPDoc block on the method; `docs/api/` index for that class |
| New or changed CLI script argument | Script's own `--help` text; `docs/api/` or equivalent |
| New or changed GitHub Actions workflow | `docs/workflows/<workflow-name>.md` |
| New or changed policy | Corresponding file under `docs/policy/` |
| New library class or major feature | `CHANGELOG.md` entry under `Added` |
| Bug fix | `CHANGELOG.md` entry under `Fixed` |
| Breaking change | `CHANGELOG.md` entry under `Changed`; update `CONTRIBUTING.md` if contributor steps change |
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
| **Every PR** | **Bump the patch version** — increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it to all headers and badges on merge |
If your code change makes any existing doc sentence false or incomplete, fix the doc before closing the PR.
---
## Key Constraints
- Never commit directly to `main` — all changes go via PR, squash-merged
- Never skip the FILE INFORMATION block on a new file
- Never use bare `catch (\Throwable $e) {}` without logging or re-throwing
- Never hardcode version numbers in body text — update `README.md` and let automation propagate
- Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows — always use `secrets.GH_TOKEN`
- Never extend `CliBase` in PHP scripts — extend `MokoStandards\Enterprise\CliFramework`
- Never call `$script->run()` as the entry point — call `$script->execute()`
- Policy documents and guides must not be mixed
---
## MokoStandards Reference
This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). Authoritative policies:
| Document | Purpose |
|----------|---------|
| [file-header-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type |
| [coding-style-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions |
| [branching-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow |
| [merge-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR title/body conventions |
| [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md |
| [scripting-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/scripting-standards.md) | PHP script requirements and CliFramework usage |
| [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) | Installing `mokoconsulting/mokostandards` via Composer |
-54
View File
@@ -1,54 +0,0 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# CODEOWNERS — require approval from jmiller-moko for protected paths
# Synced from MokoStandards. Do not edit manually.
#
# Changes to these paths require review from the listed owners before merge.
# Combined with branch protection (require PR reviews), this prevents
# unauthorized modifications to workflows, configs, and governance files.
# ── Synced workflows (managed by MokoStandards — do not edit manually) ────
/.github/workflows/deploy-dev.yml @jmiller-moko
/.github/workflows/deploy-demo.yml @jmiller-moko
/.github/workflows/deploy-manual.yml @jmiller-moko
/.github/workflows/auto-release.yml @jmiller-moko
/.github/workflows/auto-dev-issue.yml @jmiller-moko
/.github/workflows/auto-assign.yml @jmiller-moko
/.github/workflows/sync-version-on-merge.yml @jmiller-moko
/.github/workflows/enterprise-firewall-setup.yml @jmiller-moko
/.github/workflows/repository-cleanup.yml @jmiller-moko
/.github/workflows/standards-compliance.yml @jmiller-moko
/.github/workflows/codeql-analysis.yml @jmiller-moko
/.github/workflows/repo_health.yml @jmiller-moko
/.github/workflows/ci-joomla.yml @jmiller-moko
/.github/workflows/update-server.yml @jmiller-moko
/.github/workflows/deploy-manual.yml @jmiller-moko
/.github/workflows/ci-dolibarr.yml @jmiller-moko
/.github/workflows/publish-to-mokodolimods.yml @jmiller-moko
/.github/workflows/changelog-validation.yml @jmiller-moko
# Custom workflows in .github/workflows/ not listed above are repo-owned.
# ── GitHub configuration ─────────────────────────────────────────────────
/.github/ISSUE_TEMPLATE/ @jmiller-moko
/.github/CODEOWNERS @jmiller-moko
/.github/copilot.yml @jmiller-moko
/.github/copilot-instructions.md @jmiller-moko
/.github/CLAUDE.md @jmiller-moko
/.github/.mokostandards @jmiller-moko
# ── Build and config files ───────────────────────────────────────────────
/composer.json @jmiller-moko
/phpstan.neon @jmiller-moko
/Makefile @jmiller-moko
/.ftpignore @jmiller-moko
/.gitignore @jmiller-moko
/.gitattributes @jmiller-moko
/.editorconfig @jmiller-moko
# ── Governance documents ─────────────────────────────────────────────────
/LICENSE @jmiller-moko
/CONTRIBUTING.md @jmiller-moko
/SECURITY.md @jmiller-moko
/GOVERNANCE.md @jmiller-moko
/CODE_OF_CONDUCT.md @jmiller-moko
-120
View File
@@ -1,120 +0,0 @@
---
name: License Request
about: Request an organization license for Sublime Text
title: '[LICENSE REQUEST] Sublime Text - [Your Name]'
labels: ['license-request', 'admin']
assignees: []
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/request-license.md
Description: Issue template for organization software license requests
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-03-11: Added SPDX header and version to match MokoStandards 03.02.00
-->
## License Request
### Tool Information
**Tool Name**: Sublime Text
**License Type Requested**: Organization Pool
**Personal Purchase**:
- [ ] I prefer to purchase my own license ($99 USD - recommended, immediate access)
- [ ] I prefer an organization license (1-2 business days, organization use only)
- [ ] I have already purchased my own license (registration only for support)
### Requestor Information
**Name**:
**GitHub Username**: @
**Email**: @mokoconsulting.tech
**Team/Department**:
**Manager**: @
### Justification
**Why do you need this license?**
**Primary use case**:
- [ ] Remote development (SFTP to servers)
- [ ] Local development
- [ ] Code review
- [ ] Documentation editing
- [ ] Other (specify):
**Which projects/repositories will you work on?**
**Have you evaluated the free trial?**
- [ ] Yes, I've used the trial and Sublime Text meets my needs
- [ ] No, requesting license before trial
**Alternative tools considered**:
- [ ] VS Code (free alternative)
- [ ] Vim/Neovim (free, terminal-based)
- [ ] Other: _______________
### Platform
- [ ] Windows
- [ ] macOS
- [ ] Linux (distribution: ________)
### Urgency
- [ ] Urgent (needed within 24 hours - please justify)
- [ ] Normal (1-2 business days)
- [ ] Low priority (when available)
**If urgent, please explain why:**
### SFTP Plugin
**Note**: Sublime SFTP plugin ($16 USD) is a **separate personal purchase** and is NOT provided by the organization.
- [ ] I understand SFTP plugin requires separate personal purchase
- [ ] I have already purchased SFTP plugin
- [ ] I will purchase SFTP plugin if needed for my work
- [ ] I don't need SFTP plugin (local development only)
### Acknowledgments
- [ ] I have read the License Management Policy (/docs/github-private/LICENSE_MANAGEMENT.md)
- [ ] I understand organization licenses are for work use only
- [ ] I understand organization licenses must be returned upon leaving
- [ ] I understand personal purchases ($99) are an alternative with lifetime access
- [ ] I understand SFTP plugin ($16) requires separate personal purchase
- [ ] I agree to the terms of use
### Additional Information
**Expected daily usage hours**: _____ hours/day
**Duration of need**:
- [ ] Permanent (ongoing role)
- [ ] Temporary project (_____ months)
- [ ] Trial/Evaluation (_____ weeks)
**Comments/Questions**:
---
## For Admin Use Only
**Do not edit below this line**
- [ ] Manager approval received (@manager-username)
- [ ] License available in pool (current: __/20)
- [ ] License type confirmed (Organization / Personal registration)
- [ ] License key sent via encrypted email
- [ ] Activation confirmed by user
- [ ] Added to license tracking sheet
- [ ] User notified of SFTP plugin requirement
**License Key ID**: _____________
**Date Issued**: _____________
**Issued By**: @_____________
**Notes**:
-309
View File
@@ -1,309 +0,0 @@
<!--
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: MokoStandards.Templates.GitHub
INGROUP: MokoStandards.Templates
REPO: https://github.com/mokoconsulting-tech/MokoStandards
PATH: /templates/github/copilot-instructions.md.template
VERSION: XX.YY.ZZ
BRIEF: Standard GitHub Copilot custom instructions template for Moko Consulting governed repositories
NOTE: Synced to .github/copilot-instructions.md in all governed repositories via bulk sync.
Tokens replaced at sync time: MokoStandards-Template-Generic, https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic, PHP, Generic project
-->
> [!IMPORTANT]
> **🔧 AI Self-Update Required on First Use**
>
> This file may contain unfilled `{{TOKEN}}` placeholders. The MokoStandards bulk-sync system
> replaces them automatically at sync time; if you can still see them, sync has not yet run for
> this repository — or this is a brand-new repo.
>
> **On your very first interaction in this repository, before answering any other question:**
>
> 1. Check whether any `{{TOKEN}}` placeholders remain in this file.
> 2. If they do, locate the values as described in the table below and replace every occurrence
> in **both** `.github/copilot-instructions.md` and `.github/CLAUDE.md`.
> 3. After replacing all tokens, **delete this entire notice block** (from `> [!IMPORTANT]`
> through the closing `> ---` line) in both files.
> 4. Tell the developer: *"I've self-updated the AI context files with this repository's
> values — all set."*
>
> | Placeholder | Where to find the value |
> |---|---|
> | `MokoStandards-Template-Generic` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) |
> | `https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/<repo-name>` |
> | `PHP` | The dominant programming language (check file extensions in the repository) |
> | `Generic project` | The project type: `PHP library`, `Joomla extension`, `Dolibarr module`, `WaaS site`, etc. — infer from repo structure |
>
> ---
# MokoStandards-Template-Generic — GitHub Copilot Custom Instructions
## What This Repo Is
This is a **Moko Consulting** repository governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). All coding standards, workflows, and policies are defined there and enforced here via bulk sync.
Repository URL: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic
Primary language: **PHP**
Platform type: **Generic project**
---
## Primary Language
**PHP is the primary language for this repository.** Follow the conventions documented in [MokoStandards coding-style-guide](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md).
YAML uses 2-space indentation (spaces, not tabs). All other text files use tabs per `.editorconfig`.
---
## File Header — Always Required on New Files
Every new file needs a copyright header as its first content. Use the minimal form unless the file is a policy doc, README, or public API.
**PHP:**
```php
<?php
/* 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: MokoStandards-Template-Generic.Module
* INGROUP: MokoStandards-Template-Generic
* REPO: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic
* PATH: /path/to/file.php
* VERSION: XX.YY.ZZ
* BRIEF: One-line description of purpose
*/
declare(strict_types=1);
```
**Markdown:**
```markdown
<!--
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: MokoStandards-Template-Generic.Documentation
INGROUP: MokoStandards-Template-Generic
REPO: https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic
PATH: /docs/file.md
VERSION: XX.YY.ZZ
BRIEF: One-line description
-->
```
**YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt.
---
## Version Management
**`README.md` is the single source of truth for the repository version.**
- **Bump the patch version on every PR** — increment `XX.YY.ZZ` (e.g. `01.02.03``01.02.04`) in `README.md` before opening the PR; the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`.
- The `VERSION: XX.YY.ZZ` field in the README.md `FILE INFORMATION` block governs all other version references.
- Update the version in `README.md` only — the `sync-version-on-merge` workflow propagates it automatically to all badges and `FILE INFORMATION` headers on merge to `main`.
- Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `04.00.04`).
- Never hardcode a specific version in document body text — use the badge or FILE INFORMATION header only.
---
## GitHub Actions — Token Usage
Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). This applies to all `actions/checkout`, `gh` CLI calls, and any step that talks to the GitHub API.
```yaml
# ✅ Correct
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.GH_TOKEN }}
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
```
```yaml
# ❌ Wrong — never use these in workflows
token: ${{ github.token }}
token: ${{ secrets.GITHUB_TOKEN }}
```
PHP scripts read the token with: `getenv('GH_TOKEN') ?: getenv('GITHUB_TOKEN')``GH_TOKEN` is always preferred; `GITHUB_TOKEN` is accepted only as a local-dev fallback.
---
## Composer Package (PHP repositories)
This repository requires the MokoStandards enterprise library. The `composer.json` must include:
```json
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/mokoconsulting-tech/MokoStandards"
}
],
"require": {
"mokoconsulting/mokostandards": "^4.0"
}
}
```
Run `composer install` after adding the dependency. See [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) for full instructions.
---
## PHP Script Pattern
All PHP scripts **must** extend `MokoStandards\Enterprise\CliFramework`. Never write standalone classes or extend the legacy `CliBase`.
```php
#!/usr/bin/env php
<?php
/* … file header … */
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use MokoStandards\Enterprise\CliFramework;
class MyScript extends CliFramework
{
protected function configure(): void
{
$this->setDescription('One-line description');
$this->addArgument('--path', 'Repository root', '.');
$this->addArgument('--dry-run', 'Preview without writing', false);
}
protected function run(): int
{
$path = $this->getArgument('--path');
$dryRun = (bool) $this->getArgument('--dry-run');
$this->log('INFO', "Processing: {$path}");
return 0;
}
}
$script = new MyScript('my_script', 'One-line description');
exit($script->execute());
```
**Key rules:**
- Abstract methods to implement: `configure()` and `run()`**not** `execute()`
- `execute()` is the **public entry point** that orchestrates setup (arg parsing, `initialize()`) and then calls your `run()` implementation; call it at the bottom with `exit($script->execute())`
- Entry point at the bottom: `$script->execute()`**not** `$script->run()`
- Constructor always takes `(string $name, string $description = '')`; pass the description here — `setDescription()` inside `configure()` is only needed to override it
- `log(string $level, string $message)` — level is the **first** argument (INFO / SUCCESS / WARNING / ERROR)
- `$this->dryRun` and `$this->verbose` are set automatically from `--dry-run` / `--verbose`
---
## Naming Conventions
| Context | Convention | Example |
|---------|-----------|---------|
| PHP class | `PascalCase` | `MyService` |
| PHP method / function | `camelCase` | `getUserData()` |
| PHP variable | `$snake_case` | `$repo_path` |
| PHP constant | `UPPER_SNAKE_CASE` | `DEFAULT_THRESHOLD` |
| PHP class file | `PascalCase.php` | `ApiClient.php` |
| PHP script file | `snake_case.php` | `check_health.php` |
| YAML workflow | `kebab-case.yml` | `bulk-repo-sync.yml` |
| Markdown doc | `kebab-case.md` | `coding-style-guide.md` |
---
## Commit Messages
Format: `<type>(<scope>): <subject>` — imperative, lower-case subject, no trailing period.
Valid types: `feat` · `fix` · `docs` · `chore` · `ci` · `refactor` · `style` · `test` · `perf` · `revert` · `build`
Examples:
- `feat(module): add user preference caching`
- `fix(api): handle null response from external service`
- `docs(readme): update installation instructions`
- `chore(deps): bump phpunit to 11.x`
---
## Branch Naming
Approved prefixes: `dev/` · `rc/` · `version/` · `copilot/` · `dependabot/`
- `dev/XX.YY` or `dev/feature-name` — development (version optional)
- `rc/XX.YY.ZZ` — release candidate (three-part required)
- `version/XX.YY` — archive branch (auto-created, two-part)
- Release tags: `vXX` (major only — one release per major version)
- Patch `00` = development (no release), first release = `01`
Examples:
-`dev/04.06` · `dev/new-dashboard` · `rc/04.06.01`
-`feature/my-thing` — rejected by branch protection
---
## Keeping Documentation Current
Whenever you make code changes, update the corresponding documentation in the same commit or PR. Do not leave docs stale.
| Change type | Documentation to update |
|-------------|------------------------|
| New or renamed public PHP method | PHPDoc block on the method; `docs/api/` index for that class |
| New or changed CLI script argument | Script's own `--help` text; `docs/api/` or equivalent |
| New or changed GitHub Actions workflow | `docs/workflows/<workflow-name>.md` |
| New or changed policy | Corresponding file under `docs/policy/` |
| New library class or major feature | `CHANGELOG.md` entry under `Added` |
| Bug fix | `CHANGELOG.md` entry under `Fixed` |
| Breaking change | `CHANGELOG.md` entry under `Changed`; update `CONTRIBUTING.md` if contributor steps change |
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
| **Every PR** | **Bump the patch version** — increment `XX.YY.ZZ` in `README.md`; `sync-version-on-merge` propagates it to all headers and badges on merge |
If your code change makes any existing doc sentence false or incomplete, fix the doc before closing the PR.
---
## Key Constraints
- Never commit directly to `main` — all changes go via PR, squash-merged
- Never skip the FILE INFORMATION block on a new file
- Never use bare `catch (\Throwable $e) {}` without logging or re-throwing
- Never hardcode version numbers in body text — update `README.md` and let automation propagate
- Never use `github.token` or `secrets.GITHUB_TOKEN` in workflows — always use `secrets.GH_TOKEN`
- Never extend `CliBase` in PHP scripts — extend `MokoStandards\Enterprise\CliFramework`
- Never call `$script->run()` as the entry point — call `$script->execute()`
- Policy documents and guides must not be mixed
---
## MokoStandards Reference
This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). Authoritative policies:
| Document | Purpose |
|----------|---------|
| [file-header-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type |
| [coding-style-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions |
| [branching-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow |
| [merge-strategy.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR title/body conventions |
| [changelog-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md |
| [scripting-standards.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/scripting-standards.md) | PHP script requirements and CliFramework usage |
| [package-installation.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/package-installation.md) | Installing `mokoconsulting/mokostandards` via Composer |
-126
View File
@@ -1,126 +0,0 @@
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License (./LICENSE).
# FILE INFORMATION
DEFGROUP:
INGROUP: Project.Infrastructure
REPO: mokoconsulting-tech/MokoStandards-Template-Generic
VERSION: 00.00.01
PATH: ./.github/copilot/README.md
BRIEF: GitHub Copilot firewall configuration documentation
-->
# GitHub Copilot Firewall Configuration
This directory contains firewall configuration files for GitHub Copilot coding agent to access enterprise-ready sites and external resources.
## Files
### firewall-allowlist.json
JSON configuration file defining domains and URLs that should be accessible through the firewall. This includes:
- **License Sources**: gnu.org, opensource.org, apache.org, creativecommons.org
- **Standards Organizations**: fsf.org, spdx.org
- **Code Repositories**: github.com, raw.githubusercontent.com
The configuration is organized into categories with priority levels for better management.
### setup-firewall.sh
Bash script that reads the `firewall-allowlist.json` configuration and exports the allowlist as an environment variable for GitHub Actions workflows.
## Usage in GitHub Actions
To use this firewall configuration in your GitHub Actions workflows, add the following step **before** the Copilot agent runs:
```yaml
- name: Configure Copilot Firewall
run: |
bash .github/copilot/setup-firewall.sh
```
This will:
1. Read the firewall allowlist configuration
2. Export `COPILOT_FIREWALL_ALLOWLIST` environment variable
3. Make the domains accessible to the Copilot agent
## Example Workflow
```yaml
name: Copilot Agent
on:
pull_request:
types: [opened, synchronize]
jobs:
copilot:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure Copilot Firewall
run: bash .github/copilot/setup-firewall.sh
- name: Run Copilot Agent
uses: github/copilot-swe-agent@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
```
## Adding New Domains
To add new domains to the allowlist:
1. Edit `firewall-allowlist.json`
2. Add the domain to the `allowlist.domains` array
3. Optionally add specific URLs to `allowlist.urls`
4. Categorize the domain in the `categories` section
5. Commit and push the changes
Example:
```json
{
"allowlist": {
"domains": [
"existing-domain.com",
"new-domain.com"
]
}
}
```
## Security Considerations
- Only add trusted domains to the allowlist
- Use specific URLs when possible instead of wildcard domains
- Review allowlist changes carefully in pull requests
- Keep the allowlist minimal - only include necessary domains
- Document the purpose of each domain/URL in the categories section
## Troubleshooting
If the Copilot agent cannot access a required site:
1. Check if the domain is in `firewall-allowlist.json`
2. Verify the setup script ran in the GitHub Actions workflow
3. Check workflow logs for firewall configuration messages
4. Ensure the domain format is correct (e.g., `www.example.com` not `http://www.example.com`)
5. For wildcard patterns, ensure they follow the correct format (e.g., `*.example.com`)
## Revision History
| Date | Version | Author | Notes |
| --- | --- | --- | --- |
| 2026-01-16 | 0.1.0 | Copilot | Initial firewall configuration setup |
-73
View File
@@ -1,73 +0,0 @@
{
"$schema": "https://docs.github.com/assets/schemas/copilot-firewall-allowlist.json",
"version": "1.0",
"description": "Firewall allowlist configuration for GitHub Copilot coding agent to access enterprise-ready sites and license sources",
"allowlist": {
"domains": [
"*.gnu.org",
"fsf.org",
"www.fsf.org",
"spdx.org",
"www.spdx.org",
"opensource.org",
"www.opensource.org",
"creativecommons.org",
"www.creativecommons.org",
"apache.org",
"www.apache.org",
"github.com",
"api.github.com",
"raw.githubusercontent.com"
],
"urls": [
"https://www.gnu.org/licenses/gpl-3.0.txt",
"https://www.gnu.org/licenses/gpl-3.0.html",
"https://www.gnu.org/licenses/agpl-3.0.txt",
"https://www.gnu.org/licenses/lgpl-3.0.txt",
"https://www.apache.org/licenses/LICENSE-2.0.txt",
"https://opensource.org/licenses/MIT",
"https://spdx.org/licenses/",
"https://creativecommons.org/licenses/"
]
},
"categories": [
{
"name": "license-sources",
"description": "Official license text sources",
"priority": "high",
"hosts": [
"www.gnu.org",
"opensource.org",
"spdx.org",
"apache.org",
"creativecommons.org"
]
},
{
"name": "code-repositories",
"description": "Source code and package repositories",
"priority": "high",
"hosts": [
"github.com",
"api.github.com",
"raw.githubusercontent.com"
]
},
{
"name": "standards-organizations",
"description": "Standards and specification sources",
"priority": "medium",
"hosts": [
"fsf.org",
"spdx.org"
]
}
],
"notes": [
"This configuration allows access to common license sources and enterprise-ready sites",
"Domains use wildcard patterns where appropriate (e.g., *.gnu.org)",
"Specific license file URLs are explicitly allowlisted",
"Categories help organize and prioritize different types of access",
"This file should be referenced in GitHub Actions setup steps before firewall initialization"
]
}
-57
View File
@@ -1,57 +0,0 @@
#!/bin/bash
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
#
# Setup script for configuring firewall allowlist in GitHub Actions
# This script should be run in GitHub Actions setup steps before the firewall is enabled
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ALLOWLIST_FILE="${SCRIPT_DIR}/firewall-allowlist.json"
echo "=== GitHub Copilot Firewall Setup ==="
echo "Configuring firewall allowlist for enterprise-ready sites..."
if [ ! -f "$ALLOWLIST_FILE" ]; then
echo "ERROR: Allowlist file not found: $ALLOWLIST_FILE"
exit 1
fi
# Read domains from the allowlist configuration
if ! DOMAINS=$(jq -r '.allowlist.domains[]' "$ALLOWLIST_FILE" 2>&1); then
echo "ERROR: Failed to parse allowlist configuration: $DOMAINS"
exit 1
fi
if [ -z "$DOMAINS" ]; then
echo "WARNING: No domains found in allowlist configuration"
exit 0
fi
echo "Domains to allowlist:"
echo "$DOMAINS" | while read -r domain; do
echo " - $domain"
done
# Export environment variable for GitHub Copilot
# This tells the Copilot agent which domains are allowed
export COPILOT_FIREWALL_ALLOWLIST=$(jq -c '.allowlist.domains' "$ALLOWLIST_FILE")
echo ""
echo "Firewall allowlist configured successfully"
echo "Environment variable set: COPILOT_FIREWALL_ALLOWLIST"
echo ""
echo "To use this in GitHub Actions, add to your workflow:"
echo ""
echo " - name: Configure Copilot Firewall"
echo " run: |"
echo " bash .github/copilot/setup-firewall.sh"
echo " echo \"COPILOT_FIREWALL_ALLOWLIST=\$COPILOT_FIREWALL_ALLOWLIST\" >> \$GITHUB_ENV"
echo ""
# Optionally output the configuration for GitHub Actions to use
if [ "$GITHUB_ACTIONS" = "true" ]; then
echo "COPILOT_FIREWALL_ALLOWLIST=${COPILOT_FIREWALL_ALLOWLIST}" >> "$GITHUB_ENV"
echo "✓ Firewall allowlist exported to GitHub Actions environment"
fi
+2
View File
@@ -200,3 +200,5 @@ venv/
*.coverage
hypothesis/
profile.ps1
.mcp.json
@@ -7,21 +7,6 @@ assignees: ''
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/adr.md
Description: Issue template for Architecture Decision Records
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
- 2024: Initial creation
-->
## ADR Number
ADR-XXXX
@@ -7,21 +7,6 @@ assignees: ''
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/bug_report.md
Description: Issue template for bug reports
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
- 2024: Initial creation
-->
## Bug Description
A clear and concise description of what the bug is.
@@ -8,10 +8,10 @@ contact_links:
url: https://mokoconsulting.tech/
about: Get help or ask questions through our website
- name: 📚 MokoStandards Documentation
url: https://github.com/mokoconsulting-tech/MokoStandards
url: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
about: View our coding standards and best practices
- name: 🔒 Report a Security Vulnerability
url: https://github.com/mokoconsulting-tech/.github-private/security/advisories/new
url: https://git.mokoconsulting.tech/mokoconsulting-tech/.github-private/security/advisories/new
about: Report security vulnerabilities privately (for critical issues)
- name: 💡 Community Discussions
url: https://github.com/orgs/mokoconsulting-tech/discussions
@@ -7,21 +7,6 @@ assignees: ''
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/documentation.md
Description: Issue template for documentation-related issues
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
- 2024: Initial creation
-->
## Documentation Issue
@@ -7,21 +7,6 @@ assignees: ''
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/enterprise_support.md
Description: Issue template for enterprise support requests
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
- 2024: Initial creation
-->
## Support Request Type
- [ ] Critical Production Issue
@@ -7,21 +7,6 @@ assignees: ''
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/feature_request.md
Description: Issue template for feature requests
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
- 2024: Initial creation
-->
## Feature Description
A clear and concise description of the feature you'd like to see.
@@ -52,7 +37,7 @@ If you have ideas about how this could be implemented, share them here:
Add any other context, mockups, or screenshots about the feature request here.
## Relevant Standards
Does this relate to any standards in [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards)?
Does this relate to any standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)?
- [ ] Accessibility (WCAG 2.1 AA)
- [ ] Localization (en_US/en_GB)
- [ ] Security best practices
@@ -3,22 +3,9 @@ name: Firewall Request
about: Request firewall rule changes or access to external resources
title: '[FIREWALL] [Resource Name] - [Brief Description]'
labels: ['firewall-request', 'infrastructure', 'security']
assignees: []
assignees: ['jmiller']
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/firewall-request.md
Description: Issue template for firewall rule change and access requests
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-03-11: Added SPDX header and version to match MokoStandards 03.02.00
-->
## Firewall Request
@@ -0,0 +1,48 @@
---
name: API Integration Request
about: Request integration with a new REST API or service
title: '[API] '
labels: 'enhancement, api-integration'
assignees: ''
---
## API Integration Request
### Target API
- **Service Name**: [e.g., Akeeba Backup, Joomla Web Services]
- **API Documentation**: [URL to API docs]
- **API Type**: [REST / GraphQL / SOAP]
- **Authentication**: [API Key / OAuth / Bearer Token / Basic Auth]
### Proposed Tools
List the MCP tools this integration would provide:
| Tool Name | HTTP Method | Endpoint | Description |
|---|---|---|---|
| `service_list` | GET | `/api/items` | List all items |
| `service_get` | GET | `/api/items/{id}` | Get single item |
| `service_create` | POST | `/api/items` | Create item |
### Multi-Connection
- [ ] Single instance only
- [ ] Multiple instances (production, staging, dev)
- [ ] Multi-tenant (one connection per client)
### Use Case
Describe the workflow this integration enables for AI assistants.
### Priority
- [ ] Critical — blocking current work
- [ ] High — needed soon
- [ ] Medium — would improve workflow
- [ ] Low — nice to have
### Existing Alternatives
Are there other ways to accomplish this today? If so, why is an MCP integration better?
### Checklist
- [ ] API documentation is available and accessible
- [ ] API supports the required authentication method
- [ ] I have tested the API endpoints manually
- [ ] The integration follows the Template-MCP architecture pattern
@@ -0,0 +1,67 @@
---
name: MCP Connection Issue
about: Report a connection, authentication, or API communication issue
title: '[CONNECTION] '
labels: 'bug, mcp-connection'
assignees: ''
---
## Connection Issue
### Issue Type
- [ ] Authentication failure (401/403)
- [ ] Connection refused / timeout
- [ ] TLS / SSL certificate error
- [ ] Wrong connection used (wrong environment)
- [ ] Config file not found / parse error
- [ ] API response error (4xx / 5xx)
### MCP Server
- **Server Name**: [e.g., mcp_mokowaas]
- **Server Version**: [e.g., 1.0.0]
- **Node.js Version**: [e.g., 20.x]
### Connection Details
- **Connection Name**: [e.g., production, staging, default]
- **API Base URL**: [e.g., https://api.example.com] *(do not include API keys)*
- **Insecure Mode**: [Yes / No]
### Error Message
```
Paste the exact error message here
```
### Steps to Reproduce
1. Configure connection with `npm run setup`
2. Call tool `...` with parameters `...`
3. See error
### Expected Behavior
What should have happened.
### Debugging Attempted
- [ ] Tested API directly with curl
- [ ] Verified API key is valid
- [ ] Checked config file exists and is valid JSON
- [ ] Tested with `list_connections` tool
- [ ] Ran server manually: `node dist/index.js 2> debug.log`
### Config File
```json
{
"defaultConnection": "...",
"connections": {
"connection_name": {
"baseUrl": "https://...",
"apiKey": "REDACTED"
}
}
}
```
*(Redact all API keys and tokens)*
### Environment
- **OS**: [e.g., macOS 14, Ubuntu 22.04, Windows 11]
- **Claude Code Version**: [e.g., latest]
- **Registration**: [.mcp.json / ~/.claude.json]
@@ -0,0 +1,49 @@
---
name: New MCP Tool Request
about: Request a new tool to be added to this MCP server
title: '[TOOL] '
labels: 'enhancement, mcp-tool'
assignees: ''
---
## Tool Request
### Tool Name
Proposed tool name (snake_case): `resource_action`
### Description
What should this tool do? What API endpoint(s) does it map to?
### API Endpoint(s)
- **Method**: [GET / POST / PUT / PATCH / DELETE]
- **Endpoint**: `/api/v1/...`
- **Auth**: [API Key / Token / None]
### Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| `id` | number | Yes | Resource ID |
| `search` | string | No | Search filter |
### Expected Response
```json
{
"id": 1,
"name": "Example"
}
```
### Use Case
Describe when and why someone would use this tool from Claude or another AI assistant.
### Connection Scope
- [ ] Works with all connections
- [ ] Specific to certain API versions
- [ ] Requires additional permissions
### Checklist
- [ ] I have checked this tool does not already exist
- [ ] I have verified the API endpoint exists and is documented
- [ ] The proposed name follows the `resource_action` convention
@@ -3,13 +3,9 @@ name: Question
about: Ask a question about usage, features, or best practices
title: '[QUESTION] '
labels: ['question']
assignees: []
assignees: ['jmiller']
---
<!--
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
SPDX-License-Identifier: GPL-3.0-or-later
-->
## Question
@@ -7,21 +7,6 @@ assignees: ''
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/rfc.md
Description: Issue template for Request for Comments proposals
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
- 2024: Initial creation
-->
## RFC Summary
One-paragraph summary of the proposal.
@@ -7,21 +7,6 @@ assignees: ''
---
<!--
SPDX-License-Identifier: GPL-3.0-or-later
Copyright (C) 2024-2026 Moko Consulting Tech
File: .github/ISSUE_TEMPLATE/security.md
Description: Issue template for security vulnerability reports
Project: .github-private
Author: Moko Consulting Tech
Version: 03.02.00
Revision History:
- 2026-01-04: Added MokoStandards compliant header with copyright, file info, and metadata
- 2026-03-11: Version bump to 03.02.00 to match MokoStandards
- 2024: Initial creation
-->
## ⚠️ IMPORTANT: Private Disclosure Required
@@ -50,7 +35,7 @@ Use this template only for:
<!-- Describe how this could be addressed -->
## Standards Reference
Does this relate to security standards in [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards)?
Does this relate to security standards in [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards)?
- [ ] SPDX license identifiers
- [ ] Secret management
- [ ] Dependency security
+24
View File
@@ -0,0 +1,24 @@
---
name: Version Bump
about: Request or track a version change
title: '[VERSION] '
labels: 'version, type: version'
assignees: 'jmiller'
---
## Version Change
**Current version**: <!-- e.g., 01.02.03 -->
**Requested version**: <!-- e.g., 01.03.00 -->
**Change type**: <!-- patch / minor / major -->
## Reason
<!-- Why is this version bump needed? -->
## Checklist
- [ ] README.md `VERSION:` field updated
- [ ] CHANGELOG.md entry added
- [ ] Module descriptor version updated (Dolibarr: `$this->version`, Joomla: `<version>`)
- [ ] All file headers will be auto-propagated by `sync-version-on-merge` workflow
@@ -7,7 +7,7 @@
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /.github/workflows/auto-assign.yml
# VERSION: 04.06.00
# BRIEF: Auto-assign jmiller-moko to unassigned issues and PRs every 15 minutes
# BRIEF: Auto-assign jmiller to unassigned issues and PRs every 15 minutes
name: Auto-Assign Issues & PRs
@@ -35,7 +35,7 @@ jobs:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
ASSIGNEE="jmiller-moko"
ASSIGNEE="jmiller"
echo "## 🏷️ Auto-Assign Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
@@ -135,7 +135,7 @@ jobs:
--title "$SUB_FULL_TITLE" \
--body "$SUB_BODY" \
--label "${SUB_LABELS}" \
--assignee "jmiller-moko" 2>&1)
--assignee "jmiller" 2>&1)
SUB_NUM=$(echo "$SUB_URL" | grep -oE '[0-9]+$')
if [ -n "$SUB_NUM" ]; then
@@ -154,7 +154,7 @@ jobs:
--title "$TITLE" \
--body "$PARENT_BODY" \
--label "${LABEL_TYPE},version" \
--assignee "jmiller-moko" 2>&1)
--assignee "jmiller" 2>&1)
PARENT_NUM=$(echo "$PARENT_URL" | grep -oE '[0-9]+$')
+251
View File
@@ -0,0 +1,251 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Automation
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.gitea/workflows/branch-protection.yml
# BRIEF: Apply standardised branch protection rules to all governed repositories
#
# +========================================================================+
# | BRANCH PROTECTION SETUP |
# +========================================================================+
# | |
# | Applies protection rules for: main, dev, rc, beta, alpha |
# | |
# | main — Require PR, block rejected reviews, no force push |
# | dev — Allow push, no force push, no delete |
# | rc — Allow push, no force push, no delete |
# | beta — Allow push, no force push, no delete |
# | alpha — Allow push, no force push, no delete |
# | |
# | jmiller has override authority on all branches. |
# | |
# +========================================================================+
name: Branch Protection Setup
on:
schedule:
- cron: '0 2 * * 1' # Weekly Monday 02:00 UTC
workflow_dispatch:
inputs:
dry_run:
description: 'Preview mode (no changes)'
required: false
type: boolean
default: false
repos:
description: 'Comma-separated repo names (empty = all governed repos)'
required: false
type: string
default: ''
env:
GITEA_URL: https://git.mokoconsulting.tech
GITEA_ORG: MokoConsulting
permissions:
contents: read
jobs:
protect:
name: Apply Branch Protection Rules
runs-on: ubuntu-latest
steps:
- name: Determine target repos
id: repos
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
API="${GITEA_URL}/api/v1"
# Platform/standards/infra repos to exclude
EXCLUDE="gitea-org-config org-profile gitea-private .mokogitea-private MokoStandards moko-platform MokoTesting"
EXCLUDE="$EXCLUDE MokoStandards-Template-Client MokoStandards-Template-Dolibarr MokoStandards-Template-Generic MokoStandards-Template-Joomla MokoDoliProjTemplate"
if [ -n "${{ inputs.repos }}" ]; then
# User-specified repos
REPOS=$(echo "${{ inputs.repos }}" | tr ',' ' ')
else
# Fetch all org repos
PAGE=1
REPOS=""
while true; do
BATCH=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/orgs/${GITEA_ORG}/repos?page=${PAGE}&limit=50" \
| jq -r '.[].name // empty')
[ -z "$BATCH" ] && break
REPOS="$REPOS $BATCH"
PAGE=$((PAGE + 1))
done
# Filter out excluded repos
FILTERED=""
for REPO in $REPOS; do
SKIP=false
for EX in $EXCLUDE; do
if [ "$REPO" = "$EX" ]; then
SKIP=true
break
fi
done
if [ "$SKIP" = "false" ]; then
FILTERED="$FILTERED $REPO"
fi
done
REPOS="$FILTERED"
fi
echo "repos=$REPOS" >> "$GITHUB_OUTPUT"
COUNT=$(echo "$REPOS" | wc -w)
echo "📋 Target repos (${COUNT}): $REPOS"
- name: Apply protection rules
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
DRY_RUN: ${{ inputs.dry_run || 'false' }}
run: |
API="${GITEA_URL}/api/v1"
REPOS="${{ steps.repos.outputs.repos }}"
SUCCESS=0
FAILED=0
SKIPPED=0
# ── Rule definitions ──────────────────────────────────────
# Only the CI bot (jmiller token) can push directly.
# All human contributors must use PRs.
# Force push disabled on all branches.
RULE_MAIN='{
"rule_name": "main",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"dismiss_stale_approvals": true,
"block_on_rejected_reviews": true,
"block_on_outdated_branch": false,
"priority": 1
}'
RULE_DEV='{
"rule_name": "dev",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 2
}'
RULE_RC='{
"rule_name": "rc",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 3
}'
RULE_BETA='{
"rule_name": "beta",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 4
}'
RULE_ALPHA='{
"rule_name": "alpha",
"enable_push": true,
"enable_push_whitelist": true,
"push_whitelist_usernames": ["jmiller"],
"enable_force_push": false,
"enable_force_push_allowlist": false,
"force_push_allowlist_usernames": [],
"enable_merge_whitelist": false,
"required_approvals": 0,
"block_on_rejected_reviews": false,
"priority": 5
}'
RULES=("$RULE_MAIN" "$RULE_DEV" "$RULE_RC" "$RULE_BETA" "$RULE_ALPHA")
RULE_NAMES=("main" "dev" "rc" "beta" "alpha")
# ── Apply rules to each repo ──────────────────────────────
for REPO in $REPOS; do
echo ""
echo "═══ ${REPO} ═══"
for i in "${!RULES[@]}"; do
RULE="${RULES[$i]}"
NAME="${RULE_NAMES[$i]}"
if [ "$DRY_RUN" = "true" ]; then
echo " [DRY RUN] Would apply rule: ${NAME}"
SKIPPED=$((SKIPPED + 1))
continue
fi
# Delete existing rule if present (idempotent recreate)
ENCODED_NAME=$(echo "$NAME" | sed 's|/|%2F|g')
curl -sS -o /dev/null -w "" \
-X DELETE \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections/${ENCODED_NAME}" 2>/dev/null || true
# Create rule
RESPONSE=$(curl -sS -w "\n%{http_code}" \
-X POST \
-H "Authorization: token ${GA_TOKEN}" \
-H "Content-Type: application/json" \
-d "$RULE" \
"${API}/repos/${GITEA_ORG}/${REPO}/branch_protections")
HTTP=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
if [ "$HTTP" = "201" ]; then
echo " ✅ ${NAME}"
SUCCESS=$((SUCCESS + 1))
else
echo " ❌ ${NAME} (HTTP ${HTTP}): $(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)"
FAILED=$((FAILED + 1))
fi
done
done
# ── Summary ───────────────────────────────────────────────
echo ""
echo "════════════════════════════════════════"
echo " ✅ Success: ${SUCCESS}"
echo " ❌ Failed: ${FAILED}"
echo " ⏭️ Skipped: ${SKIPPED}"
echo "════════════════════════════════════════"
if [ "$FAILED" -gt 0 ]; then
echo "::warning::${FAILED} rule(s) failed to apply"
fi
+213
View File
@@ -0,0 +1,213 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Maintenance
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
# PATH: /templates/workflows/cascade-dev.yml.template
# VERSION: 02.00.00
# BRIEF: Forward-merge main → all open branches after every push to main
#
# +========================================================================+
# | CASCADE MAIN → ALL BRANCHES |
# +========================================================================+
# | |
# | Triggers on every push to main (PR merges, bot commits, etc.) |
# | |
# | 1. List all branches matching: dev, rc/*, beta/*, alpha/* |
# | 2. For each: create PR (main → branch), auto-merge if clean |
# | 3. On conflict: leave PR open for manual resolution |
# | |
# +========================================================================+
name: Cascade Main → Dev
on:
push:
branches:
- main
workflow_dispatch:
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
permissions:
contents: write
pull-requests: write
jobs:
cascade:
name: Cascade main → branches
runs-on: ubuntu-latest
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip cascade]')
steps:
- name: Discover target branches
id: branches
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# Fetch all branches (paginated)
PAGE=1
ALL_BRANCHES=""
while true; do
BATCH=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/branches?page=${PAGE}&limit=50" \
| jq -r '.[].name // empty')
[ -z "$BATCH" ] && break
ALL_BRANCHES="$ALL_BRANCHES $BATCH"
PAGE=$((PAGE + 1))
done
# Filter to cascade targets: dev, dev/*, rc/*, beta/*, alpha/*
TARGETS=""
for BRANCH in $ALL_BRANCHES; do
case "$BRANCH" in
dev|dev/*|rc/*|beta/*|alpha/*)
TARGETS="$TARGETS $BRANCH"
;;
esac
done
TARGETS=$(echo "$TARGETS" | xargs) # trim whitespace
if [ -z "$TARGETS" ]; then
echo "targets=" >> "$GITHUB_OUTPUT"
echo "️ No cascade target branches found"
else
echo "targets=$TARGETS" >> "$GITHUB_OUTPUT"
COUNT=$(echo "$TARGETS" | wc -w)
echo "📋 Found ${COUNT} target branch(es): ${TARGETS}"
fi
- name: Cascade to all target branches
if: steps.branches.outputs.targets != ''
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
SHORT_SHA="${GITHUB_SHA:0:7}"
TARGETS="${{ steps.branches.outputs.targets }}"
SUCCESS=0
CONFLICTS=0
SKIPPED=0
FAILED=0
for BRANCH in $TARGETS; do
echo ""
echo "═══ main → ${BRANCH} ═══"
# Check if branch is already up to date
ENCODED_BRANCH=$(echo "$BRANCH" | sed 's|/|%2F|g')
RESPONSE=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/compare/${ENCODED_BRANCH}...main")
AHEAD=$(echo "$RESPONSE" | jq '.total_commits // 0')
if [ "$AHEAD" -eq 0 ]; then
echo " ✅ Already up to date"
SKIPPED=$((SKIPPED + 1))
continue
fi
echo " ️ main is ${AHEAD} commit(s) ahead"
# Check for existing cascade PR
EXISTING=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/pulls?state=open&head=${GITEA_ORG}:main&base=${ENCODED_BRANCH}&limit=1")
EXISTING_COUNT=$(echo "$EXISTING" | jq 'length')
PR_NUMBER=""
if [ "$EXISTING_COUNT" -gt 0 ]; then
PR_NUMBER=$(echo "$EXISTING" | jq -r '.[0].number')
echo " ️ Reusing existing PR #${PR_NUMBER}"
else
# Create cascade PR
PR_RESPONSE=$(curl -sS -w "\n%{http_code}" \
-X POST \
-H "Authorization: token ${GA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"title\": \"chore: cascade main → ${BRANCH} (${SHORT_SHA}) [skip ci]\",
\"body\": \"## Automatic cascade\\n\\nForward-merging \`main\` (${SHORT_SHA}) into \`${BRANCH}\`.\\n\\nIf conflicts exist, resolve manually and merge.\\n\\n> Auto-created by **Cascade Main → Dev**.\",
\"head\": \"main\",
\"base\": \"${BRANCH}\"
}" \
"${API}/pulls")
HTTP_CODE=$(echo "$PR_RESPONSE" | tail -1)
BODY=$(echo "$PR_RESPONSE" | sed '$d')
PR_NUMBER=$(echo "$BODY" | jq -r '.number // empty')
if [ "$HTTP_CODE" != "201" ] || [ -z "$PR_NUMBER" ]; then
MSG=$(echo "$BODY" | jq -r '.message // .' 2>/dev/null | head -1)
echo " ❌ Failed to create PR (HTTP ${HTTP_CODE}): ${MSG}"
FAILED=$((FAILED + 1))
continue
fi
echo " ✅ Created PR #${PR_NUMBER}"
fi
# Try auto-merge
PR_DATA=$(curl -sS \
-H "Authorization: token ${GA_TOKEN}" \
"${API}/pulls/${PR_NUMBER}")
MERGEABLE=$(echo "$PR_DATA" | jq -r '.mergeable // false')
if [ "$MERGEABLE" != "true" ]; then
echo " ⚠️ Conflicts — PR #${PR_NUMBER} left open"
CONFLICTS=$((CONFLICTS + 1))
continue
fi
MERGE_RESPONSE=$(curl -sS -w "\n%{http_code}" \
-X POST \
-H "Authorization: token ${GA_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"Do\": \"merge\",
\"merge_message_field\": \"chore: cascade main → ${BRANCH} [skip ci]\",
\"delete_branch_after_merge\": false
}" \
"${API}/pulls/${PR_NUMBER}/merge")
MERGE_HTTP=$(echo "$MERGE_RESPONSE" | tail -1)
if [ "$MERGE_HTTP" = "200" ] || [ "$MERGE_HTTP" = "204" ]; then
echo " ✅ Merged — ${BRANCH} is in sync"
SUCCESS=$((SUCCESS + 1))
else
MERGE_BODY=$(echo "$MERGE_RESPONSE" | sed '$d')
echo " ⚠️ Merge failed (HTTP ${MERGE_HTTP}) — PR #${PR_NUMBER} left open"
CONFLICTS=$((CONFLICTS + 1))
fi
done
# Summary
echo ""
echo "════════════════════════════════════════"
echo " ✅ Merged: ${SUCCESS}"
echo " ⚠️ Conflicts: ${CONFLICTS}"
echo " ⏭️ Up to date: ${SKIPPED}"
echo " ❌ Failed: ${FAILED}"
echo "════════════════════════════════════════"
if [ "$FAILED" -gt 0 ]; then
exit 1
fi
@@ -94,7 +94,7 @@ jobs:
AUTHORIZED="false"
# Hardcoded authorized users — always allowed to deploy
AUTHORIZED_USERS="jmiller-moko github-actions[bot]"
AUTHORIZED_USERS="jmiller github-actions[bot]"
for user in $AUTHORIZED_USERS; do
if [ "$ACTOR" = "$user" ]; then
AUTHORIZED="true"
@@ -704,7 +704,7 @@ jobs:
--title "$TITLE" \
--body "$BODY" \
--label "$LABEL" \
--assignee "jmiller-moko" \
--assignee "jmiller" \
| tee -a "$GITHUB_STEP_SUMMARY"
fi
@@ -99,7 +99,7 @@ jobs:
AUTHORIZED="false"
# Hardcoded authorized users — always allowed to deploy
AUTHORIZED_USERS="jmiller-moko github-actions[bot]"
AUTHORIZED_USERS="jmiller github-actions[bot]"
for user in $AUTHORIZED_USERS; do
if [ "$ACTOR" = "$user" ]; then
AUTHORIZED="true"
+96
View File
@@ -0,0 +1,96 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
# PATH: /templates/workflows/gitleaks.yml.template
# VERSION: 01.00.00
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
#
# +========================================================================+
# | SECRET SCANNING |
# +========================================================================+
# | |
# | Scans commits for leaked secrets using Gitleaks. |
# | |
# | - PR scan: only new commits in the PR |
# | - Scheduled: full repo scan weekly |
# | - Alerts via ntfy on findings |
# | |
# +========================================================================+
name: Secret Scanning
on:
pull_request:
branches:
- main
- 'dev/**'
schedule:
- cron: '0 5 * * 1' # Weekly Monday 05:00 UTC
workflow_dispatch:
permissions:
contents: read
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }}
jobs:
gitleaks:
name: Gitleaks Secret Scan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Gitleaks
run: |
GITLEAKS_VERSION="8.21.2"
curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz -C /usr/local/bin gitleaks
gitleaks version
- name: Scan for secrets
id: scan
run: |
echo "### Secret Scanning" >> $GITHUB_STEP_SUMMARY
ARGS="--source . --verbose --report-format json --report-path /tmp/gitleaks-report.json"
if [ "${{ github.event_name }}" = "pull_request" ]; then
# Scan only PR commits
ARGS="$ARGS --log-opts=${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}"
echo "Scanning PR commits only" >> $GITHUB_STEP_SUMMARY
else
echo "Full repository scan" >> $GITHUB_STEP_SUMMARY
fi
if gitleaks detect $ARGS 2>&1; then
echo "result=clean" >> "$GITHUB_OUTPUT"
echo "**No secrets detected.**" >> $GITHUB_STEP_SUMMARY
else
echo "result=found" >> "$GITHUB_OUTPUT"
FINDINGS=$(jq length /tmp/gitleaks-report.json 2>/dev/null || echo "unknown")
echo "**${FINDINGS} potential secret(s) detected.**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Review the findings and rotate any exposed credentials immediately." >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: Notify on findings
if: failure() && steps.scan.outputs.result == 'found'
run: |
REPO="${{ github.event.repository.name }}"
curl -sS \
-H "Title: ${REPO} — secrets detected in code" \
-H "Tags: rotating_light,key" \
-H "Priority: urgent" \
-d "Gitleaks found potential secrets. Review and rotate credentials immediately." \
"${NTFY_URL}/${NTFY_TOPIC}" || true
+25
View File
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
MokoStandards Repository Manifest
Auto-generated by cleanup script.
See: https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home
-->
<moko-platform xmlns="https://standards.mokoconsulting.tech/moko-platform/1.0" schema-version="1.0">
<identity>
<name>joomla-api-mcp</name>
<org>MokoConsulting</org>
<description>MCP server for Joomla Web Services API operations</description>
<license spdx="GPL-3.0-or-later">GNU General Public License v3</license>
</identity>
<governance>
<platform>nodejs</platform>
<standards-version>04.07.00</standards-version>
<standards-source>https://git.mokoconsulting.tech/MokoConsulting/moko-platform</standards-source>
<last-synced>2026-05-10T19:51:10+00:00</last-synced>
</governance>
<build>
<language>TypeScript</language>
<package-type>mcp-server</package-type>
<entry-point>src/</entry-point>
</build>
</moko-platform>
+278
View File
@@ -0,0 +1,278 @@
# MCP Server Auto-Release
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# MCP-specific release pipeline that builds TypeScript, runs validation,
# attaches the compiled dist/ as a release artifact, and creates a GitHub
# Release with tool inventory in the release notes.
#
# This replaces the generic auto-release.yml for MCP server repos.
name: MCP Release
on:
push:
branches:
- main
paths:
- 'src/**'
- 'package.json'
- 'tsconfig.json'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: write
issues: write
jobs:
build-and-release:
name: Build, Validate & Release
runs-on: ubuntu-latest
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
github.actor != 'github-actions[bot]'
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GH_TOKEN || github.token }}
fetch-depth: 0
# ── Build ────────────────────────────────────────────────────────
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: TypeScript compile check
run: npx tsc --noEmit
- name: Build
run: npm run build
- name: Verify dist output
run: |
for f in index.js client.js config.js types.js; do
test -f "dist/${f}" || (echo "ERROR: dist/${f} not found" && exit 1)
done
echo "✓ All dist files present"
# ── Tool Inventory ───────────────────────────────────────────────
- name: Generate tool inventory
id: tools
run: |
TOOL_COUNT=$(grep -c "server\.tool(" src/index.ts || echo "0")
echo "count=${TOOL_COUNT}" >> "$GITHUB_OUTPUT"
# Extract tool names
TOOL_LIST=$(grep -oE "'[a-z_]+'" src/index.ts | head -100 | tr -d "'" | sort -u)
echo "Tools registered: ${TOOL_COUNT}"
# Generate inventory for release notes
echo "## Tool Inventory (${TOOL_COUNT} tools)" > /tmp/tool-inventory.md
echo "" >> /tmp/tool-inventory.md
grep -B0 -A1 "server\.tool(" src/index.ts | grep -oE "'[^']+'" | while IFS= read -r name; do
read -r desc 2>/dev/null || true
CLEAN_NAME=$(echo "$name" | tr -d "'")
CLEAN_DESC=$(echo "$desc" | tr -d "'" | sed 's/,$//')
if [ -n "$CLEAN_NAME" ] && [ -n "$CLEAN_DESC" ]; then
echo "- \`${CLEAN_NAME}\` — ${CLEAN_DESC}" >> /tmp/tool-inventory.md
fi
done
# ── Version ──────────────────────────────────────────────────────
- name: Setup MokoStandards tools
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --branch version/04 --quiet \
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
/tmp/mokostandards
cd /tmp/mokostandards
composer install --no-dev --no-interaction --quiet
- name: Read version from README.md
id: version
run: |
VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null)
if [ -z "$VERSION" ]; then
echo "No VERSION in README.md — skipping release"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
MAJOR=$(echo "$VERSION" | awk -F. '{print $1}')
MINOR=$(echo "$VERSION" | awk -F. '{printf "%s.%s", $1, $2}')
PATCH=$(echo "$VERSION" | awk -F. '{print $3}')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT"
if [ "$PATCH" = "00" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
if [ "$PATCH" = "01" ]; then
echo "is_first=true" >> "$GITHUB_OUTPUT"
else
echo "is_first=false" >> "$GITHUB_OUTPUT"
fi
fi
- name: Check if already released
if: steps.version.outputs.skip != 'true'
id: check
run: |
TAG="${{ steps.version.outputs.release_tag }}"
TAG_EXISTS=false
git rev-parse "$TAG" >/dev/null 2>&1 && TAG_EXISTS=true
echo "tag_exists=$TAG_EXISTS" >> "$GITHUB_OUTPUT"
# ── Release Artifact ─────────────────────────────────────────────
- name: Package dist
if: steps.version.outputs.skip != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
REPO_NAME="${{ github.event.repository.name }}"
tar -czf "/tmp/${REPO_NAME}-${VERSION}.tar.gz" -C dist .
echo "artifact=/tmp/${REPO_NAME}-${VERSION}.tar.gz" >> "$GITHUB_OUTPUT"
# ── Version Updates ──────────────────────────────────────────────
- name: Set platform version
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
php /tmp/mokostandards/api/cli/version_set_platform.php \
--path . --version "$VERSION" --branch main
- name: Update version badges
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
find . -name "*.md" ! -path "./.git/*" ! -path "./vendor/*" | while read -r f; do
if grep -q '\[VERSION:' "$f" 2>/dev/null; then
sed -i "s/\[VERSION:[[:space:]]*[0-9]\{2\}\.[0-9]\{2\}\.[0-9]\{2\}\]/[VERSION: ${VERSION}]/" "$f"
fi
done
- name: Commit release changes
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true'
run: |
if git diff --quiet && git diff --cached --quiet; then
echo "No changes to commit"
exit 0
fi
VERSION="${{ steps.version.outputs.version }}"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add -A
git commit -m "chore(release): build ${VERSION} [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
# ── Version Branch ───────────────────────────────────────────────
- name: Archive version branch
if: steps.check.outputs.tag_exists != 'true'
run: |
BRANCH="${{ steps.version.outputs.branch }}"
git push origin HEAD:"$BRANCH" --force
echo "Updated archive branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
# ── Tag & Release ────────────────────────────────────────────────
- name: Create git tag
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true' &&
steps.version.outputs.is_first == 'true'
run: |
TAG="${{ steps.version.outputs.release_tag }}"
if ! git rev-parse "$TAG" >/dev/null 2>&1; then
git tag "$TAG"
git push origin "$TAG"
fi
- name: GitHub Release
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
VERSION="${{ steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
MAJOR="${{ steps.version.outputs.major }}"
BRANCH="${{ steps.version.outputs.branch }}"
TOOL_COUNT="${{ steps.tools.outputs.count }}"
REPO_NAME="${{ github.event.repository.name }}"
# Build release notes
NOTES=$(php /tmp/mokostandards/api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
{
echo "$NOTES"
echo ""
echo "---"
echo ""
echo "### MCP Server Info"
echo "- **Tools registered**: ${TOOL_COUNT}"
echo "- **Node.js**: 20+"
echo "- **MCP SDK**: $(node -p \"require('./package.json').dependencies['@modelcontextprotocol/sdk']\" 2>/dev/null || echo 'unknown')"
echo ""
cat /tmp/tool-inventory.md 2>/dev/null || true
} > /tmp/release_notes.md
EXISTING=$(gh release view "$RELEASE_TAG" --json tagName -q .tagName 2>/dev/null || true)
ARTIFACT="/tmp/${REPO_NAME}-${VERSION}.tar.gz"
if [ -z "$EXISTING" ]; then
gh release create "$RELEASE_TAG" \
--title "v${MAJOR} (latest: ${VERSION})" \
--notes-file /tmp/release_notes.md \
--target "$BRANCH" \
"$ARTIFACT"
echo "Release created: ${RELEASE_TAG} (${VERSION})" >> $GITHUB_STEP_SUMMARY
else
gh release edit "$RELEASE_TAG" \
--title "v${MAJOR} (latest: ${VERSION})" \
--notes-file /tmp/release_notes.md
gh release upload "$RELEASE_TAG" "$ARTIFACT" --clobber 2>/dev/null || true
echo "Release updated: ${RELEASE_TAG} -> ${VERSION}" >> $GITHUB_STEP_SUMMARY
fi
# ── Summary ──────────────────────────────────────────────────────
- name: Pipeline Summary
if: always()
run: |
VERSION="${{ steps.version.outputs.version }}"
TOOL_COUNT="${{ steps.tools.outputs.count }}"
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
else
echo "" >> $GITHUB_STEP_SUMMARY
echo "## MCP Release Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Detail | Value |" >> $GITHUB_STEP_SUMMARY
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tools | ${TOOL_COUNT} |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.release_tag }}\` |" >> $GITHUB_STEP_SUMMARY
fi
+65
View File
@@ -0,0 +1,65 @@
# MCP Server Build & Validation
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Builds the MCP server, validates TypeScript compilation, and checks
# that tools are properly registered with valid Zod schemas.
name: MCP Build & Validate
on:
push:
branches: [main, dev/**]
paths: ['src/**', 'package.json', 'tsconfig.json']
pull_request:
branches: [main]
paths: ['src/**', 'package.json', 'tsconfig.json']
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20, 22]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: TypeScript compile
run: npx tsc --noEmit
- name: Build
run: npm run build
- name: Verify dist output exists
run: |
test -f dist/index.js || (echo "ERROR: dist/index.js not found" && exit 1)
test -f dist/client.js || (echo "ERROR: dist/client.js not found" && exit 1)
test -f dist/config.js || (echo "ERROR: dist/config.js not found" && exit 1)
test -f dist/types.js || (echo "ERROR: dist/types.js not found" && exit 1)
echo "✓ All required dist files present"
- name: Verify shebang in index.js
run: |
head -1 dist/index.js | grep -q "#!/usr/bin/env node" || echo "WARNING: Missing shebang in dist/index.js"
- name: Count registered tools
run: |
TOOL_COUNT=$(grep -c "server\.tool(" src/index.ts || true)
echo "Registered tools: ${TOOL_COUNT}"
if [ "${TOOL_COUNT}" -eq 0 ]; then
echo "ERROR: No tools registered in src/index.ts"
exit 1
fi
+109
View File
@@ -0,0 +1,109 @@
# MCP SDK Version Check
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Weekly check for MCP SDK updates. Creates an issue when a new version
# of @modelcontextprotocol/sdk is available.
name: MCP SDK Version Check
on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 9am UTC
workflow_dispatch:
permissions:
contents: read
jobs:
check-sdk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Check for SDK updates
id: sdk-check
run: |
CURRENT=$(node -p "require('./package.json').dependencies['@modelcontextprotocol/sdk']" | sed 's/[\^~]//')
LATEST=$(npm view @modelcontextprotocol/sdk version 2>/dev/null || echo "unknown")
echo "current=${CURRENT}" >> $GITHUB_OUTPUT
echo "latest=${LATEST}" >> $GITHUB_OUTPUT
if [ "${CURRENT}" != "${LATEST}" ] && [ "${LATEST}" != "unknown" ]; then
echo "update_available=true" >> $GITHUB_OUTPUT
echo "MCP SDK update available: ${CURRENT} → ${LATEST}"
else
echo "update_available=false" >> $GITHUB_OUTPUT
echo "MCP SDK is up to date: ${CURRENT}"
fi
- name: Check for Zod updates
id: zod-check
run: |
CURRENT=$(node -p "require('./package.json').dependencies['zod']" | sed 's/[\^~]//')
LATEST=$(npm view zod version 2>/dev/null || echo "unknown")
echo "current=${CURRENT}" >> $GITHUB_OUTPUT
echo "latest=${LATEST}" >> $GITHUB_OUTPUT
if [ "${CURRENT}" != "${LATEST}" ] && [ "${LATEST}" != "unknown" ]; then
echo "update_available=true" >> $GITHUB_OUTPUT
else
echo "update_available=false" >> $GITHUB_OUTPUT
fi
- name: Create update issue
if: steps.sdk-check.outputs.update_available == 'true'
uses: actions/github-script@v7
with:
script: |
const title = `chore(deps): update @modelcontextprotocol/sdk ${process.env.CURRENT} → ${process.env.LATEST}`;
const body = [
'## MCP SDK Update Available',
'',
`| Package | Current | Latest |`,
`|---------|---------|--------|`,
`| @modelcontextprotocol/sdk | ${process.env.CURRENT} | ${process.env.LATEST} |`,
`| zod | ${process.env.ZOD_CURRENT} | ${process.env.ZOD_LATEST} |`,
'',
'### Steps',
'1. Update package.json',
'2. Run `npm install`',
'3. Run `npm run build` to verify compilation',
'4. Test all tools against target API',
'',
'### Changelog',
`https://github.com/modelcontextprotocol/typescript-sdk/releases`,
].join('\n');
// Check for existing open issue
const existing = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'api-change',
});
const alreadyExists = existing.data.some(i => i.title.includes('@modelcontextprotocol/sdk'));
if (!alreadyExists) {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title,
body,
labels: ['api-change', 'chore'],
});
}
env:
CURRENT: ${{ steps.sdk-check.outputs.current }}
LATEST: ${{ steps.sdk-check.outputs.latest }}
ZOD_CURRENT: ${{ steps.zod-check.outputs.current }}
ZOD_LATEST: ${{ steps.zod-check.outputs.latest }}
+61
View File
@@ -0,0 +1,61 @@
# MCP Tool Inventory
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Generates a tool inventory report on each push to main.
# Extracts tool names, descriptions, and parameter counts from src/index.ts.
name: MCP Tool Inventory
on:
push:
branches: [main]
paths: ['src/index.ts']
workflow_dispatch:
permissions:
contents: read
jobs:
inventory:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate tool inventory
run: |
echo "# MCP Tool Inventory" > TOOLS.md
echo "" >> TOOLS.md
echo "Auto-generated from \`src/index.ts\` on $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> TOOLS.md
echo "" >> TOOLS.md
# Count tools
TOOL_COUNT=$(grep -c "server\.tool(" src/index.ts || true)
echo "**Total tools: ${TOOL_COUNT}**" >> TOOLS.md
echo "" >> TOOLS.md
# Extract tool names and descriptions
echo "| Tool | Description |" >> TOOLS.md
echo "|------|-------------|" >> TOOLS.md
grep -A1 "server\.tool(" src/index.ts | grep -E "^\s*'" | while read -r line; do
TOOL_NAME=$(echo "$line" | sed "s/.*'\([^']*\)'.*/\1/")
# Get next line for description
DESC=$(grep -A2 "'${TOOL_NAME}'" src/index.ts | grep -E "^\s*'" | tail -1 | sed "s/.*'\([^']*\)'.*/\1/" || echo "")
echo "| \`${TOOL_NAME}\` | ${DESC} |" >> TOOLS.md
done
echo "" >> TOOLS.md
echo "---" >> TOOLS.md
echo "*Generated by MCP Tool Inventory workflow*" >> TOOLS.md
cat TOOLS.md
- name: Upload inventory artifact
uses: actions/upload-artifact@v4
with:
name: tool-inventory
path: TOOLS.md
retention-days: 90
+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
@@ -80,7 +80,7 @@ jobs:
echo "✅ Scheduled run — authorized"
exit 0
fi
AUTHORIZED_USERS="jmiller-moko github-actions[bot]"
AUTHORIZED_USERS="jmiller github-actions[bot]"
for user in $AUTHORIZED_USERS; do
if [ "$ACTOR" = "$user" ]; then
echo "✅ ${ACTOR} authorized"
@@ -2601,7 +2601,7 @@ jobs:
echo "Updated issue #${EXISTING}"
else
gh issue create --repo "$REPO" --title "$TITLE" --body "$BODY" \
--label "$LABEL" --assignee "jmiller-moko"
--label "$LABEL" --assignee "jmiller"
fi
# CUSTOMIZATION:
+76
View File
@@ -0,0 +1,76 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: GitHub.Workflow
# INGROUP: MokoStandards.Workflows.Shared
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /.mokogitea/workflows/auto-assign.yml
# VERSION: 04.06.00
# BRIEF: Auto-assign jmiller to unassigned issues and PRs every 15 minutes
name: "Universal: Auto-Assign"
on:
issues:
types: [opened]
pull_request_target:
types: [opened]
schedule:
- cron: '0 */12 * * *'
workflow_dispatch:
permissions:
issues: write
pull-requests: write
jobs:
auto-assign:
name: Assign unassigned issues and PRs
runs-on: ubuntu-latest
steps:
- name: Assign unassigned issues
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
ASSIGNEE="jmiller"
echo "## 🏷️ Auto-Assign Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
ASSIGNED_ISSUES=0
ASSIGNED_PRS=0
# Assign unassigned open issues
ISSUES=$(gh api "repos/$REPO/issues?state=open&per_page=100&assignee=none" --jq '.[].number' 2>/dev/null || true)
for NUM in $ISSUES; do
# Skip PRs (the issues endpoint returns PRs too)
IS_PR=$(gh api "repos/$REPO/issues/$NUM" --jq '.pull_request // empty' 2>/dev/null || true)
if [ -z "$IS_PR" ]; then
gh api "repos/$REPO/issues/$NUM/assignees" -X POST -f "assignees[]=$ASSIGNEE" --silent 2>/dev/null && {
ASSIGNED_ISSUES=$((ASSIGNED_ISSUES + 1))
echo " Assigned issue #$NUM"
} || true
fi
done
# Assign unassigned open PRs
PRS=$(gh api "repos/$REPO/pulls?state=open&per_page=100" --jq '.[] | select(.assignees | length == 0) | .number' 2>/dev/null || true)
for NUM in $PRS; do
gh api "repos/$REPO/issues/$NUM/assignees" -X POST -f "assignees[]=$ASSIGNEE" --silent 2>/dev/null && {
ASSIGNED_PRS=$((ASSIGNED_PRS + 1))
echo " Assigned PR #$NUM"
} || true
done
echo "| Type | Assigned |" >> $GITHUB_STEP_SUMMARY
echo "|------|----------|" >> $GITHUB_STEP_SUMMARY
echo "| Issues | $ASSIGNED_ISSUES |" >> $GITHUB_STEP_SUMMARY
echo "| Pull Requests | $ASSIGNED_PRS |" >> $GITHUB_STEP_SUMMARY
if [ "$ASSIGNED_ISSUES" -eq 0 ] && [ "$ASSIGNED_PRS" -eq 0 ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "✅ All issues and PRs already have assignees" >> $GITHUB_STEP_SUMMARY
fi
+66
View File
@@ -0,0 +1,66 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.mokogitea/workflows/auto-bump.yml
# VERSION: 09.02.00
# BRIEF: Auto patch-bump version on every push to dev (skips merge commits)
name: "Universal: Auto Version Bump"
on:
push:
branches:
- dev
- rc
- 'feature/**'
- 'patch/**'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
permissions:
contents: write
jobs:
bump:
name: Version Bump
runs-on: release
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
!contains(github.event.head_commit.message, '[skip bump]') &&
!startsWith(github.event.head_commit.message, 'Merge pull request')
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup moko-platform tools
run: |
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
if [ -d "/opt/moko-platform/cli" ]; then
echo "MOKO_CLI=/opt/moko-platform/cli" >> "$GITHUB_ENV"
else
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/MokoConsulting/moko-platform.git" \
/tmp/moko-platform-api
cd /tmp/moko-platform-api && composer install --no-dev --no-interaction --quiet
echo "MOKO_CLI=/tmp/moko-platform-api/cli" >> "$GITHUB_ENV"
fi
- name: Bump version
run: |
php ${MOKO_CLI}/version_auto_bump.php \
--path . --branch "${GITHUB_REF_NAME}" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--repo-url "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
+207
View File
@@ -0,0 +1,207 @@
# 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: GitHub.Workflow
# INGROUP: MokoStandards.Automation
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/auto-dev-issue.yml.template
# VERSION: 04.06.00
# BRIEF: Auto-create tracking issue with sub-issues for dev/rc branch workflow
# NOTE: Synced via bulk-repo-sync to .mokogitea/workflows/auto-dev-issue.yml in all governed repos.
name: "Universal: Dev/RC Branch Issue"
on:
# Auto-create on RC branch creation
create:
# Manual trigger for dev branches
workflow_dispatch:
inputs:
branch:
description: 'Branch name (e.g., dev/my-feature or dev/04.06)'
required: true
type: string
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
issues: write
jobs:
create-issue:
name: Create version tracking issue
runs-on: ubuntu-latest
if: >-
(github.event_name == 'workflow_dispatch') ||
(github.event.ref_type == 'branch' &&
(startsWith(github.event.ref, 'rc/') ||
startsWith(github.event.ref, 'alpha/') ||
startsWith(github.event.ref, 'beta/')))
steps:
- name: Create tracking issue and sub-issues
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
# For manual dispatch, use input; for auto, use event ref
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
BRANCH="${{ inputs.branch }}"
else
BRANCH="${{ github.event.ref }}"
fi
REPO="${{ github.repository }}"
ACTOR="${{ github.actor }}"
NOW=$(date -u '+%Y-%m-%d %H:%M UTC')
# Determine branch type and version
if [[ "$BRANCH" == rc/* ]]; then
VERSION="${BRANCH#rc/}"
BRANCH_TYPE="Release Candidate"
LABEL_TYPE="type: release"
TITLE_PREFIX="rc"
elif [[ "$BRANCH" == beta/* ]]; then
VERSION="${BRANCH#beta/}"
BRANCH_TYPE="Beta"
LABEL_TYPE="type: release"
TITLE_PREFIX="beta"
elif [[ "$BRANCH" == alpha/* ]]; then
VERSION="${BRANCH#alpha/}"
BRANCH_TYPE="Alpha"
LABEL_TYPE="type: release"
TITLE_PREFIX="alpha"
else
VERSION="${BRANCH#dev/}"
BRANCH_TYPE="Development"
LABEL_TYPE="type: feature"
TITLE_PREFIX="feat"
fi
TITLE="${TITLE_PREFIX}(${VERSION}): ${BRANCH_TYPE} tracking for ${BRANCH}"
# Check for existing issue with same title prefix
EXISTING=$(gh api "repos/${REPO}/issues?state=open&per_page=10" \
--jq ".[] | select(.title | startswith(\"${TITLE_PREFIX}(${VERSION})\")) | .number" 2>/dev/null | head -1)
if [ -n "$EXISTING" ]; then
echo "️ Issue #${EXISTING} already exists for ${VERSION}" >> $GITHUB_STEP_SUMMARY
exit 0
fi
# ── Define sub-issues for the workflow ─────────────────────────
if [[ "$BRANCH" == rc/* ]]; then
SUB_ISSUES=(
"RC Testing|Verify all features work on rc branch|type: test,release-candidate"
"Regression Testing|Run full regression suite before merge|type: test,release-candidate"
"Version Bump|Bump version in README.md and all headers|type: version,release-candidate"
"Changelog Update|Update CHANGELOG.md with release notes|documentation,release-candidate"
"Merge to Version Branch|Create PR to version/XX|type: release,needs-review"
)
elif [[ "$BRANCH" == alpha/* ]] || [[ "$BRANCH" == beta/* ]]; then
SUB_ISSUES=(
"Testing|Verify features on ${BRANCH_TYPE} branch|type: test,status: in-progress"
"Bug Fixes|Fix issues found during ${BRANCH_TYPE} testing|type: bug,status: pending"
"Promote to Next Stage|Create PR to promote to next release stage|type: release,needs-review"
)
else
SUB_ISSUES=(
"Development|Implement feature/fix on dev branch|type: feature,status: in-progress"
"Unit Testing|Write and pass unit tests|type: test,status: pending"
"Code Review|Request and complete code review|needs-review,status: pending"
"Version Bump|Bump version in README.md and all headers|type: version,status: pending"
"Changelog Update|Update CHANGELOG.md with release notes|documentation,status: pending"
"Create RC Branch|Promote dev to rc branch for final testing|type: release,status: pending"
"Merge to Main|Create PR from rc/dev to main|type: release,needs-review,status: pending"
)
fi
# ── Create sub-issues first ───────────────────────────────────────
SUB_LIST=""
SUB_NUMBERS=""
for SUB in "${SUB_ISSUES[@]}"; do
IFS='|' read -r SUB_TITLE SUB_DESC SUB_LABELS <<< "$SUB"
SUB_FULL_TITLE="${TITLE_PREFIX}(${VERSION}): ${SUB_TITLE}"
SUB_BODY=$(printf '### %s\n\n%s\n\n| Field | Value |\n|-------|-------|\n| **Parent Branch** | `%s` |\n| **Version** | `%s` |\n\n---\n*Sub-issue of the %s tracking issue for `%s`.*' \
"$SUB_TITLE" "$SUB_DESC" "$BRANCH" "$VERSION" "$BRANCH_TYPE" "$BRANCH")
SUB_URL=$(gh issue create \
--repo "$REPO" \
--title "$SUB_FULL_TITLE" \
--body "$SUB_BODY" \
--label "${SUB_LABELS}" \
--assignee "jmiller" 2>&1)
SUB_NUM=$(echo "$SUB_URL" | grep -oE '[0-9]+$')
if [ -n "$SUB_NUM" ]; then
SUB_LIST="${SUB_LIST}\n- [ ] ${SUB_TITLE} (#${SUB_NUM})"
SUB_NUMBERS="${SUB_NUMBERS} #${SUB_NUM}"
fi
sleep 0.3
done
# ── Create parent tracking issue ──────────────────────────────────
PARENT_BODY=$(printf '## %s Branch Created\n\n| Field | Value |\n|-------|-------|\n| **Branch** | `%s` |\n| **Version** | `%s` |\n| **Type** | %s |\n| **Created by** | @%s |\n| **Created at** | %s |\n| **Repository** | `%s` |\n\n## Workflow Sub-Issues\n\n%b\n\n---\n*Auto-created by [auto-dev-issue.yml](.github/workflows/auto-dev-issue.yml) on branch creation.*' \
"$BRANCH_TYPE" "$BRANCH" "$VERSION" "$BRANCH_TYPE" "$ACTOR" "$NOW" "$REPO" "$SUB_LIST")
PARENT_URL=$(gh issue create \
--repo "$REPO" \
--title "$TITLE" \
--body "$PARENT_BODY" \
--label "${LABEL_TYPE},version" \
--assignee "jmiller" 2>&1)
PARENT_NUM=$(echo "$PARENT_URL" | grep -oE '[0-9]+$')
# ── Link sub-issues back to parent ────────────────────────────────
if [ -n "$PARENT_NUM" ]; then
for SUB in "${SUB_ISSUES[@]}"; do
IFS='|' read -r SUB_TITLE _ _ <<< "$SUB"
SUB_FULL_TITLE="${TITLE_PREFIX}(${VERSION}): ${SUB_TITLE}"
SUB_NUM=$(gh api "repos/${REPO}/issues?state=open&per_page=20" \
--jq ".[] | select(.title == \"${SUB_FULL_TITLE}\") | .number" 2>/dev/null | head -1)
if [ -n "$SUB_NUM" ]; then
gh api "repos/${REPO}/issues/${SUB_NUM}" -X PATCH \
-f body="$(gh api "repos/${REPO}/issues/${SUB_NUM}" --jq '.body' 2>/dev/null)
> **Parent Issue:** #${PARENT_NUM}" --silent 2>/dev/null || true
fi
sleep 0.2
done
fi
# ── Create or update prerelease for alpha/beta/rc ────────────────
if [[ "$BRANCH" == rc/* ]] || [[ "$BRANCH" == alpha/* ]] || [[ "$BRANCH" == beta/* ]]; then
case "$BRANCH_TYPE" in
Alpha) RELEASE_TAG="alpha" ;;
Beta) RELEASE_TAG="beta" ;;
"Release Candidate") RELEASE_TAG="release-candidate" ;;
esac
EXISTING=$(gh release view "$RELEASE_TAG" --json tagName -q .tagName 2>/dev/null || true)
if [ -z "$EXISTING" ]; then
gh release create "$RELEASE_TAG" \
--title "${RELEASE_TAG} (${VERSION})" \
--notes "## ${BRANCH_TYPE} ${VERSION}\n\nBranch: \`${BRANCH}\`\nTracking issue: ${PARENT_URL}" \
--prerelease \
--target main 2>/dev/null || true
echo "${BRANCH_TYPE} release created: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
else
gh release edit "$RELEASE_TAG" \
--title "${RELEASE_TAG} (${VERSION})" --prerelease 2>/dev/null || true
echo "${BRANCH_TYPE} release updated: ${RELEASE_TAG}" >> $GITHUB_STEP_SUMMARY
fi
fi
# ── Summary ───────────────────────────────────────────────────────
echo "## Dev Workflow Issues Created" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Item | Issue |" >> $GITHUB_STEP_SUMMARY
echo "|------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| **Parent** | ${PARENT_URL} |" >> $GITHUB_STEP_SUMMARY
echo "| **Sub-issues** |${SUB_NUMBERS} |" >> $GITHUB_STEP_SUMMARY
+341
View File
@@ -0,0 +1,341 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/universal/auto-release.yml.template
# VERSION: 05.00.00
# BRIEF: Universal build & release detects platform from manifest.xml
#
# +========================================================================+
# | UNIVERSAL BUILD & RELEASE PIPELINE |
# +========================================================================+
# | |
# | Reads manifest.xml (joomla|dolibarr|generic) to branch logic. |
# | |
# | Platform-specific: |
# | joomla: XML manifest, type-prefixed packages |
# | dolibarr: mod*.class.php, update.txt, dev version reset |
# | generic: README-only, no update stream |
# | |
# +========================================================================+
name: "Universal: Build & Release"
on:
pull_request:
types: [opened, closed]
branches:
- main
workflow_dispatch:
inputs:
action:
description: 'Action to perform'
required: false
type: choice
default: release
options:
- release
- promote-rc
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
permissions:
contents: write
jobs:
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────
promote-rc:
name: Promote to RC
runs-on: release
if: >-
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
(github.event_name == 'workflow_dispatch' && inputs.action == 'promote-rc')
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 1
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
run: |
if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
echo Using pre-installed /opt/moko-platform
echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
else
echo Falling back to fresh clone
if ! command -v composer > /dev/null 2>&1; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/moko-platform-api
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
cd /tmp/moko-platform-api
composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
fi
- name: Rename branch to rc
run: |
php ${MOKO_CLI}/branch_rename.php \
--from "${{ github.event.pull_request.head.ref || 'dev' }}" --to rc \
--token "${{ secrets.MOKOGITEA_TOKEN }}" \
--api-base "${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" \
--pr "${{ github.event.pull_request.number }}"
- name: Checkout rc and configure git
run: |
git fetch origin rc
git checkout rc
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
- name: Publish RC release
run: |
php ${MOKO_CLI}/release_publish.php \
--path . --stability rc --bump minor --branch rc \
--token "${{ secrets.MOKOGITEA_TOKEN }}"
- name: Summary
if: always()
run: |
echo "## Promoted to Release Candidate" >> $GITHUB_STEP_SUMMARY
echo "Branch renamed to rc, minor bump, RC release built" >> $GITHUB_STEP_SUMMARY
# ── Merged PR → Build & Release (or promote RC to stable) ────────────────────
release:
name: Build & Release Pipeline
runs-on: release
if: >-
github.event.pull_request.merged == true ||
(github.event_name == 'workflow_dispatch' && inputs.action != 'promote-rc')
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 0
- name: Configure git for bot pushes
run: |
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
- name: Check for merge conflict markers
run: |
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
if [ -n "$CONFLICTS" ]; then
echo "::error::Merge conflict markers found — aborting release"
echo "## Release Blocked: Conflict Markers" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "No conflict markers found"
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
run: |
if [ -f /opt/moko-platform/cli/version_bump.php ] && [ -f /opt/moko-platform/vendor/autoload.php ]; then
echo Using pre-installed /opt/moko-platform
echo MOKO_CLI=/opt/moko-platform/cli >> $GITHUB_ENV
else
echo Falling back to fresh clone
if ! command -v composer > /dev/null 2>&1; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
fi
rm -rf /tmp/moko-platform-api
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/moko-platform-api
cd /tmp/moko-platform-api
composer install --no-dev --no-interaction --quiet
echo MOKO_CLI=/tmp/moko-platform-api/cli >> $GITHUB_ENV
fi
- name: "Determine version bump level"
id: bump
run: |
# Fix/patch branches: version was already bumped by pre-release, just strip suffix
# Feature/dev branches: bump minor for the new stable release
HEAD_REF="${{ github.event.pull_request.head.ref || 'dev' }}"
case "$HEAD_REF" in
fix/*|patch/*|hotfix/*|bugfix/*) BUMP="none" ;;
*) BUMP="minor" ;;
esac
echo "level=${BUMP}" >> "$GITHUB_OUTPUT"
echo "Bump level: ${BUMP} (from branch: ${HEAD_REF})"
- name: "Publish stable release"
run: |
BUMP_FLAG=""
if [ "${{ steps.bump.outputs.level }}" != "none" ]; then
BUMP_FLAG="--bump ${{ steps.bump.outputs.level }}"
fi
php ${MOKO_CLI}/release_publish.php \
--path . --stability stable ${BUMP_FLAG} --branch main \
--token "${{ secrets.MOKOGITEA_TOKEN }}"
- name: Update release notes from CHANGELOG.md
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# Extract [Unreleased] section from changelog
if [ -f "CHANGELOG.md" ]; then
NOTES=$(awk '/^## \[Unreleased\]/{found=1; next} /^## \[/{if(found) exit} found{print}' CHANGELOG.md)
[ -z "$NOTES" ] && NOTES="Stable release"
else
NOTES="Stable release"
fi
# Update release body via API
RELEASE_ID=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
"${API_BASE}/releases/tags/stable" | python3 -c "import json,sys; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true)
if [ -n "$RELEASE_ID" ]; then
python3 -c "
import json, urllib.request
body = open('/dev/stdin').read()
payload = json.dumps({'body': body}).encode()
req = urllib.request.Request(
'${API_BASE}/releases/${RELEASE_ID}',
data=payload, method='PATCH',
headers={
'Authorization': 'token ${{ secrets.MOKOGITEA_TOKEN }}',
'Content-Type': 'application/json'
})
urllib.request.urlopen(req)
" <<< "$NOTES"
echo "Release notes updated from CHANGELOG.md"
fi
# -- STEP 9: Mirror to GitHub (stable only) --------------------------------
- name: "Step 9: Mirror release to GitHub"
if: >-
steps.version.outputs.skip != 'true' &&
secrets.GH_MIRROR_TOKEN != ''
continue-on-error: true
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/release_mirror.php \
--version "$VERSION" --tag "$RELEASE_TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--gh-token "${{ secrets.GH_MIRROR_TOKEN }}" --gh-repo "$GH_REPO" \
--branch main 2>&1 || true
echo "GitHub mirror updated" >> $GITHUB_STEP_SUMMARY
# -- STEP 10: Sync main branch to GitHub mirror ----------------------------
- name: "Step 10: Push main to GitHub mirror"
if: >-
steps.version.outputs.skip != 'true' &&
secrets.GH_MIRROR_TOKEN != ''
continue-on-error: true
run: |
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
git remote add github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
git remote set-url github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
git fetch origin main --depth=1
git push github origin/main:refs/heads/main --force 2>/dev/null \
&& echo "main branch pushed to GitHub mirror" \
|| echo "WARNING: GitHub mirror push failed"
- name: "Step 11: Delete rc branch and recreate dev from main"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
# Delete rc branch (ephemeral — created by promote-rc)
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/rc" 2>/dev/null \
&& echo "Deleted rc branch" || echo "rc branch not found"
# Delete dev branch
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" \
"${API_BASE}/branches/dev" 2>/dev/null && echo "Deleted dev branch"
# Recreate dev from main (now includes version bump + changelog promotion)
curl -sf -X POST -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API_BASE}/branches" \
-d '{"new_branch_name":"dev","old_branch_name":"main"}' 2>/dev/null && echo "Recreated dev from main"
echo "Pre-release branches cleaned, dev reset from main" >> $GITHUB_STEP_SUMMARY
- name: "Step 12: Create version branch from main"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
BRANCH_NAME="version/${VERSION}"
MAIN_SHA=$(git rev-parse HEAD)
# Delete old version branch if it exists (same version re-release)
curl -sf -X DELETE -H "Authorization: token ${TOKEN}" "${API_BASE}/branches/${BRANCH_NAME}" 2>/dev/null && echo "Deleted old ${BRANCH_NAME}"
# Create version/XX.YY.ZZ from main
curl -sf -X POST -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API_BASE}/branches" -d "{\"new_branch_name\":\"${BRANCH_NAME}\",\"old_branch_name\":\"main\"}" 2>/dev/null && echo "Created ${BRANCH_NAME} from main (${MAIN_SHA})" || echo "WARNING: ${BRANCH_NAME} creation failed"
echo "Version branch created: ${BRANCH_NAME} (${MAIN_SHA})" >> $GITHUB_STEP_SUMMARY
# -- Dolibarr post-release: Reset dev version -----------------------------
- name: "Post-release: Reset dev version"
if: steps.version.outputs.skip != 'true'
continue-on-error: true
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
php ${MOKO_CLI}/version_reset_dev.php \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "${API_BASE}" \
--branch dev --path . 2>&1 || true
# -- Summary --------------------------------------------------------------
- name: Pipeline Summary
if: always()
run: |
VERSION="${{ steps.bump.outputs.version || steps.version.outputs.version }}"
PLATFORM="${{ steps.platform.outputs.platform }}"
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
echo "No VERSION in README.md" >> $GITHUB_STEP_SUMMARY
elif [ "${{ steps.check.outputs.already_released }}" = "true" ]; then
echo "## Already Released — ${VERSION}" >> $GITHUB_STEP_SUMMARY
else
echo "" >> $GITHUB_STEP_SUMMARY
echo "## Build & Release Complete (${PLATFORM})" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Step | Result |" >> $GITHUB_STEP_SUMMARY
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
echo "| Platform | \`${PLATFORM}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.tag }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Release | [View](${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/${{ steps.version.outputs.tag }}) |" >> $GITHUB_STEP_SUMMARY
fi
+48
View File
@@ -0,0 +1,48 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /.mokogitea/workflows/branch-cleanup.yml
# VERSION: 01.00.00
# BRIEF: Delete feature branches after PR merge
name: "Branch Cleanup"
on:
pull_request:
types: [closed]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
cleanup:
name: Delete merged branch
runs-on: ubuntu-latest
if: >-
github.event.pull_request.merged == true &&
github.event.pull_request.head.ref != 'dev' &&
github.event.pull_request.head.ref != 'main'
steps:
- name: Delete source branch
run: |
BRANCH="${{ github.event.pull_request.head.ref }}"
API="${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}/api/v1/repos/${{ github.repository }}/branches"
ENCODED=$(php -r "echo rawurlencode('${BRANCH}');")
STATUS=$(curl -sf -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
"${API}/${ENCODED}" 2>/dev/null || true)
if [ "$STATUS" = "204" ]; then
echo "Deleted branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
elif [ "$STATUS" = "404" ]; then
echo "Branch already deleted: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
else
echo "::warning::Failed to delete branch ${BRANCH} (HTTP ${STATUS})"
fi
+10
View File
@@ -0,0 +1,10 @@
# DISABLED — auto-release Step 11 recreates dev from main after every release.
# Cascade-dev is redundant and causes version conflicts when both main and dev
# have different version numbers in templateDetails.xml / manifest.xml.
name: "Cascade Main → Dev (DISABLED)"
on: workflow_dispatch
jobs:
noop:
runs-on: ubuntu-latest
steps:
- run: echo "Cascade disabled — auto-release handles dev recreation"
@@ -0,0 +1,101 @@
# 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: GitHub.Workflow.Template
# INGROUP: MokoStandards.CI
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/changelog-validation.yml.template
# VERSION: 04.06.00
# BRIEF: Validates CHANGELOG.md format and version consistency
# NOTE: Deployed to .mokogitea/workflows/changelog-validation.yml in governed repos.
name: "Universal: Changelog Validation"
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
permissions:
contents: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
validate-changelog:
name: Validate CHANGELOG.md
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Check CHANGELOG.md exists
run: |
echo "### Changelog Validation" >> $GITHUB_STEP_SUMMARY
if [ ! -f "CHANGELOG.md" ]; then
echo "CHANGELOG.md not found in repository root." >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "CHANGELOG.md exists." >> $GITHUB_STEP_SUMMARY
- name: Check VERSION header matches README.md
run: |
# Extract version from README.md FILE INFORMATION block
README_VERSION=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md | head -1)
if [ -z "$README_VERSION" ]; then
echo "No VERSION found in README.md FILE INFORMATION block." >> $GITHUB_STEP_SUMMARY
exit 1
fi
# Check that CHANGELOG.md has a matching version header
CHANGELOG_VERSION=$(grep -oP '^\#\#\s*\[\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' CHANGELOG.md | head -1)
if [ -z "$CHANGELOG_VERSION" ]; then
echo "No version header found in CHANGELOG.md (expected \`## [XX.YY.ZZ] - YYYY-MM-DD\`)." >> $GITHUB_STEP_SUMMARY
exit 1
fi
if [ "$CHANGELOG_VERSION" != "$README_VERSION" ]; then
echo "CHANGELOG latest version \`${CHANGELOG_VERSION}\` does not match README VERSION \`${README_VERSION}\`." >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "CHANGELOG version \`${CHANGELOG_VERSION}\` matches README VERSION." >> $GITHUB_STEP_SUMMARY
- name: Validate conventional changelog format
run: |
ERRORS=0
# Check that version entries follow ## [XX.YY.ZZ] - YYYY-MM-DD format
while IFS= read -r LINE; do
if ! echo "$LINE" | grep -qP '^\#\#\s*\[[0-9]{2}\.[0-9]{2}\.[0-9]{2}\]\s*-\s*[0-9]{4}-[0-9]{2}-[0-9]{2}'; then
echo "Malformed version header: \`${LINE}\`" >> $GITHUB_STEP_SUMMARY
echo " Expected format: \`## [XX.YY.ZZ] - YYYY-MM-DD\`" >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS + 1))
fi
done < <(grep -P '^\#\#\s*\[' CHANGELOG.md)
ENTRY_COUNT=$(grep -cP '^\#\#\s*\[' CHANGELOG.md || echo "0")
if [ "$ENTRY_COUNT" -eq 0 ]; then
echo "No version entries found in CHANGELOG.md." >> $GITHUB_STEP_SUMMARY
ERRORS=$((ERRORS + 1))
else
echo "Found ${ENTRY_COUNT} version entr(ies) in CHANGELOG.md." >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${ERRORS}" -gt 0 ]; then
echo "**${ERRORS} format issue(s) found.**" >> $GITHUB_STEP_SUMMARY
exit 1
else
echo "**Changelog format validation passed.**" >> $GITHUB_STEP_SUMMARY
fi
+204
View File
@@ -0,0 +1,204 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.CI
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
# PATH: /.gitea/workflows/ci-generic.yml
# VERSION: 01.00.00
# BRIEF: CI pipeline — lint, validate, and test for generic projects (PHP + Node.js)
name: "Generic: Project CI"
on:
push:
branches:
- main
- dev
- dev/**
- rc/**
- version/**
pull_request:
branches:
- main
- dev
- dev/**
- rc/**
workflow_dispatch:
permissions:
contents: read
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
# ── Lint & Validate ───────────────────────────────────────────────────
lint:
name: Lint & Validate
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Detect toolchain
id: detect
run: |
HAS_PHP=false
HAS_NODE=false
[ -f "composer.json" ] && HAS_PHP=true
[ -f "package.json" ] && HAS_NODE=true
echo "has_php=$HAS_PHP" >> "$GITHUB_OUTPUT"
echo "has_node=$HAS_NODE" >> "$GITHUB_OUTPUT"
echo "Toolchain: PHP=$HAS_PHP Node=$HAS_NODE"
- name: Setup PHP
if: steps.detect.outputs.has_php == 'true'
run: |
if ! command -v php &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1
fi
php -v
- name: Setup Node.js
if: steps.detect.outputs.has_node == 'true'
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install PHP dependencies
if: steps.detect.outputs.has_php == 'true'
run: |
if [ -f "composer.json" ]; then
composer install --no-interaction --prefer-dist --quiet 2>/dev/null || true
fi
- name: Install Node.js dependencies
if: steps.detect.outputs.has_node == 'true'
run: |
if [ -f "package.json" ]; then
npm ci --quiet 2>/dev/null || npm install --quiet 2>/dev/null || true
fi
- name: PHP syntax check
if: steps.detect.outputs.has_php == 'true'
run: |
ERRORS=0
while IFS= read -r -d '' file; do
if ! php -l "$file" 2>&1 | grep -q "No syntax errors"; then
echo "::error file=${file}::PHP syntax error"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -name "*.php" -not -path "./.git/*" -not -path "./vendor/*" -not -path "./node_modules/*" -print0)
echo "## PHP Lint" >> $GITHUB_STEP_SUMMARY
if [ "$ERRORS" -eq 0 ]; then
echo "All PHP files passed syntax check." >> $GITHUB_STEP_SUMMARY
else
echo "${ERRORS} file(s) with syntax errors." >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: TypeScript/JavaScript lint
if: steps.detect.outputs.has_node == 'true'
run: |
if [ -f "node_modules/.bin/eslint" ]; then
npx eslint src/ --quiet 2>&1 || { echo "::error::ESLint errors found"; exit 1; }
echo "## ESLint" >> $GITHUB_STEP_SUMMARY
echo "All files passed ESLint." >> $GITHUB_STEP_SUMMARY
elif [ -f ".eslintrc.json" ] || [ -f ".eslintrc.js" ] || [ -f "eslint.config.js" ]; then
echo "::warning::ESLint config found but eslint not installed"
else
echo "No ESLint configured — skipping"
fi
- name: TypeScript compile check
if: steps.detect.outputs.has_node == 'true'
run: |
if [ -f "tsconfig.json" ] && [ -f "node_modules/.bin/tsc" ]; then
npx tsc --noEmit 2>&1 || { echo "::error::TypeScript compilation errors"; exit 1; }
echo "## TypeScript" >> $GITHUB_STEP_SUMMARY
echo "TypeScript compilation passed." >> $GITHUB_STEP_SUMMARY
fi
- name: PHPStan static analysis
if: steps.detect.outputs.has_php == 'true'
run: |
if [ -f "phpstan.neon" ] && [ -f "vendor/bin/phpstan" ]; then
vendor/bin/phpstan analyse --no-progress 2>&1 || { echo "::warning::PHPStan found issues"; }
fi
# ── Tests ─────────────────────────────────────────────────────────────
test:
name: Tests
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Detect toolchain
id: detect
run: |
HAS_PHP=false
HAS_NODE=false
[ -f "composer.json" ] && HAS_PHP=true
[ -f "package.json" ] && HAS_NODE=true
echo "has_php=$HAS_PHP" >> "$GITHUB_OUTPUT"
echo "has_node=$HAS_NODE" >> "$GITHUB_OUTPUT"
- name: Setup PHP
if: steps.detect.outputs.has_php == 'true'
run: |
if ! command -v php &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1
fi
- name: Setup Node.js
if: steps.detect.outputs.has_node == 'true'
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install dependencies
run: |
[ -f "composer.json" ] && composer install --no-interaction --prefer-dist --quiet 2>/dev/null || true
[ -f "package.json" ] && { npm ci --quiet 2>/dev/null || npm install --quiet 2>/dev/null || true; }
- name: Run PHP tests
if: steps.detect.outputs.has_php == 'true'
run: |
if [ -f "vendor/bin/phpunit" ]; then
vendor/bin/phpunit --testdox 2>&1
echo "## PHPUnit" >> $GITHUB_STEP_SUMMARY
echo "Tests passed." >> $GITHUB_STEP_SUMMARY
elif [ -f "phpunit.xml" ] || [ -f "phpunit.xml.dist" ]; then
echo "::warning::PHPUnit config found but phpunit not installed"
else
echo "No PHPUnit configured — skipping"
fi
- name: Run Node.js tests
if: steps.detect.outputs.has_node == 'true'
run: |
if jq -e '.scripts.test' package.json > /dev/null 2>&1; then
npm test 2>&1
echo "## Node.js Tests" >> $GITHUB_STEP_SUMMARY
echo "Tests passed." >> $GITHUB_STEP_SUMMARY
else
echo "No test script in package.json — skipping"
fi
- name: Build check
run: |
if [ -f "Makefile" ]; then
make build 2>&1 || echo "::warning::Build failed or not configured"
elif [ -f "package.json" ] && jq -e '.scripts.build' package.json > /dev/null 2>&1; then
npm run build 2>&1 || echo "::warning::Build failed"
fi
+87
View File
@@ -0,0 +1,87 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Maintenance
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/cleanup.yml
# VERSION: 01.00.00
# BRIEF: Scheduled cleanup — delete merged branches and old workflow runs
name: "Universal: Repository Cleanup"
on:
schedule:
- cron: '0 3 * * 0' # Weekly on Sunday at 03:00 UTC
workflow_dispatch:
permissions:
contents: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
cleanup:
name: Clean Merged Branches
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GA_TOKEN }}
- name: Delete merged branches
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
echo "=== Merged Branch Cleanup ==="
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
# List branches via API
BRANCHES=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
"${API}/branches?limit=50" | jq -r '.[].name')
DELETED=0
for BRANCH in $BRANCHES; do
# Skip protected branches
case "$BRANCH" in
main|master|develop|release/*|hotfix/*) continue ;;
esac
# Check if branch is merged into main
if git merge-base --is-ancestor "origin/${BRANCH}" origin/main 2>/dev/null; then
echo " Deleting merged branch: ${BRANCH}"
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
"${API}/branches/${BRANCH}" 2>/dev/null || true
DELETED=$((DELETED + 1))
fi
done
echo "Deleted ${DELETED} merged branch(es)"
- name: Clean old workflow runs
env:
GA_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
echo "=== Workflow Run Cleanup ==="
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
CUTOFF=$(date -d "30 days ago" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -v-30d +%Y-%m-%dT%H:%M:%SZ)
# Get old completed runs
RUNS=$(curl -sS -H "Authorization: token ${GA_TOKEN}" \
"${API}/actions/runs?status=completed&limit=50" | \
jq -r ".workflow_runs[] | select(.created_at < \"${CUTOFF}\") | .id" 2>/dev/null)
DELETED=0
for RUN_ID in $RUNS; do
curl -sS -X DELETE -H "Authorization: token ${GA_TOKEN}" \
"${API}/actions/runs/${RUN_ID}" 2>/dev/null || true
DELETED=$((DELETED + 1))
done
echo "Deleted ${DELETED} old workflow run(s)"
+115
View File
@@ -0,0 +1,115 @@
# 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: GitHub.Workflow.Template
# INGROUP: MokoStandards.Security
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/generic/codeql-analysis.yml.template
# VERSION: 04.05.00
# BRIEF: CodeQL security scanning workflow (generic — all repo types)
# NOTE: Deployed to .mokogitea/workflows/codeql-analysis.yml in governed repos.
# CodeQL does not support PHP directly; JavaScript scans JSON/YAML/shell.
# For PHP-specific security scanning see standards-compliance.yml.
name: "Universal: CodeQL Analysis"
on:
push:
branches:
- main
- dev/**
- rc/**
- version/**
pull_request:
branches:
- main
- dev/**
- rc/**
schedule:
# Weekly on Monday at 06:00 UTC
- cron: '0 6 * * 1'
workflow_dispatch:
permissions:
actions: read
contents: read
security-events: write
pull-requests: read
jobs:
analyze:
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
timeout-minutes: 360
strategy:
fail-fast: false
matrix:
# CodeQL does not support PHP. Use 'javascript' to scan JSON, YAML,
# and shell scripts. Add 'actions' to scan GitHub Actions workflows.
language: ['javascript', 'actions']
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended,security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
upload: true
output: sarif-results
wait-for-processing: true
- name: Upload SARIF results
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.5.0
with:
name: codeql-results-${{ matrix.language }}
path: sarif-results
retention-days: 30
- name: Step summary
if: always()
run: |
echo "### 🔍 CodeQL — ${{ matrix.language }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
URL="https://github.com/${{ github.repository }}/security/code-scanning"
echo "See the [Security tab]($URL) for findings." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Severity | SLA |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-----|" >> $GITHUB_STEP_SUMMARY
echo "| Critical | 7 days |" >> $GITHUB_STEP_SUMMARY
echo "| High | 14 days |" >> $GITHUB_STEP_SUMMARY
echo "| Medium | 30 days |" >> $GITHUB_STEP_SUMMARY
echo "| Low | 60 days / next release |" >> $GITHUB_STEP_SUMMARY
summary:
name: Security Scan Summary
runs-on: ubuntu-latest
needs: analyze
if: always()
steps:
- name: Summary
run: |
echo "### 🛡️ CodeQL Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Trigger:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
SECURITY_URL="https://github.com/${{ github.repository }}/security"
echo "" >> $GITHUB_STEP_SUMMARY
echo "📊 [View all security alerts]($SECURITY_URL)" >> $GITHUB_STEP_SUMMARY
+44
View File
@@ -0,0 +1,44 @@
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
#
# GitHub Actions workflow for Copilot coding agent
# This workflow demonstrates how to use the firewall configuration
name: "MCP: Copilot Agent"
on:
pull_request:
types: [opened, synchronize, reopened]
issue_comment:
types: [created]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
copilot-agent:
name: Run Copilot Coding Agent
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Configure Copilot Firewall
run: |
echo "Configuring firewall allowlist for enterprise-ready sites..."
bash .github/copilot/setup-firewall.sh
echo "Firewall configuration completed"
- name: Run Copilot Agent
uses: github/copilot-swe-agent@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue_number: ${{ github.event.issue.number || github.event.pull_request.number }}
env:
# Environment variables are set by setup-firewall.sh
COPILOT_FIREWALL_ALLOWLIST: ${{ env.COPILOT_FIREWALL_ALLOWLIST }}
+126
View File
@@ -0,0 +1,126 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Deploy
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
# PATH: /templates/workflows/joomla/deploy-manual.yml.template
# VERSION: 04.07.00
# BRIEF: Manual SFTP deploy to dev server for Joomla repos
name: "Universal: Deploy to Dev (Manual)"
on:
workflow_dispatch:
inputs:
clear_remote:
description: 'Delete all remote files before uploading'
required: false
default: 'false'
type: boolean
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: read
jobs:
deploy:
name: SFTP Deploy to Dev
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup PHP
run: |
php -v && composer --version
- name: Setup MokoStandards tools
env:
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
/tmp/mokostandards-api 2>/dev/null || true
if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then
cd /tmp/mokostandards-api && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
fi
- name: Check FTP configuration
id: check
env:
HOST: ${{ vars.DEV_FTP_HOST }}
PATH_VAR: ${{ vars.DEV_FTP_PATH }}
PORT: ${{ vars.DEV_FTP_PORT }}
run: |
if [ -z "$HOST" ] || [ -z "$PATH_VAR" ]; then
echo "DEV_FTP_HOST or DEV_FTP_PATH not configured -- cannot deploy"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "host=$HOST" >> "$GITHUB_OUTPUT"
REMOTE="${PATH_VAR%/}"
echo "remote=$REMOTE" >> "$GITHUB_OUTPUT"
[ -z "$PORT" ] && PORT="22"
echo "port=$PORT" >> "$GITHUB_OUTPUT"
- name: Deploy via SFTP
if: steps.check.outputs.skip != 'true'
env:
SFTP_KEY: ${{ secrets.DEV_FTP_KEY }}
SFTP_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
SFTP_USER: ${{ vars.DEV_FTP_USERNAME }}
run: |
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
[ ! -d "$SOURCE_DIR" ] && { echo "No src/ or htdocs/ -- nothing to deploy"; exit 0; }
printf '{"host":"%s","port":%s,"username":"%s","remotePath":"%s"' \
"${{ steps.check.outputs.host }}" "${{ steps.check.outputs.port }}" "$SFTP_USER" "${{ steps.check.outputs.remote }}" \
> /tmp/sftp-config.json
if [ -n "$SFTP_KEY" ]; then
echo "$SFTP_KEY" > /tmp/deploy_key
chmod 600 /tmp/deploy_key
printf ',"privateKeyPath":"/tmp/deploy_key"}' >> /tmp/sftp-config.json
else
printf ',"password":"%s"}' "$SFTP_PASS" >> /tmp/sftp-config.json
fi
DEPLOY_ARGS=(--path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json)
[ "${{ inputs.clear_remote }}" = "true" ] && DEPLOY_ARGS+=(--clear-remote)
PLATFORM=$(php /tmp/mokostandards-api/cli/platform_detect.php --path . 2>/dev/null || true)
if [ "$PLATFORM" = "waas-component" ] && [ -f "/tmp/mokostandards-api/deploy/deploy-joomla.php" ]; then
php /tmp/mokostandards-api/deploy/deploy-joomla.php "${DEPLOY_ARGS[@]}"
else
php /tmp/mokostandards-api/deploy/deploy-sftp.php "${DEPLOY_ARGS[@]}"
fi
rm -f /tmp/deploy_key /tmp/sftp-config.json
- name: Summary
if: always()
run: |
if [ "${{ steps.check.outputs.skip }}" = "true" ]; then
echo "### Deploy Skipped -- FTP not configured" >> $GITHUB_STEP_SUMMARY
else
echo "### Manual Dev Deploy Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Host | \`${{ steps.check.outputs.host }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Remote | \`${{ steps.check.outputs.remote }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Clear | ${{ inputs.clear_remote }} |" >> $GITHUB_STEP_SUMMARY
fi
@@ -0,0 +1,758 @@
# 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
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# FILE INFORMATION
# DEFGROUP: GitHub.Workflow
# INGROUP: MokoStandards.Firewall
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/enterprise-firewall-setup.yml.template
# VERSION: 04.06.00
# BRIEF: Enterprise firewall configuration — generates outbound allow-rules including SFTP deployment server
# NOTE: Reads DEV_FTP_HOST / DEV_FTP_PORT variables to include SFTP egress rules alongside HTTPS rules.
name: "MCP: Enterprise Firewall"
# This workflow provides firewall configuration guidance for enterprise-ready sites
# It generates firewall rules for allowing outbound access to trusted domains
# including license providers, documentation sources, package registries,
# and the SFTP deployment server (DEV_FTP_HOST / DEV_FTP_PORT).
#
# Runs automatically when:
# - Coding agent workflows are triggered (pull requests with copilot/ prefix)
# - Manual workflow dispatch for custom configurations
on:
workflow_dispatch:
inputs:
firewall_type:
description: 'Target firewall type'
required: true
type: choice
options:
- 'iptables'
- 'ufw'
- 'firewalld'
- 'aws-security-group'
- 'azure-nsg'
- 'gcp-firewall'
- 'cloudflare'
- 'all'
default: 'all'
output_format:
description: 'Output format'
required: true
type: choice
options:
- 'shell-script'
- 'json'
- 'yaml'
- 'markdown'
- 'all'
default: 'markdown'
# Auto-run when coding agent creates or updates PRs
pull_request:
branches:
- 'copilot/**'
- 'agent/**'
types: [opened, synchronize, reopened]
# Auto-run on push to coding agent branches
push:
branches:
- 'copilot/**'
- 'agent/**'
permissions:
contents: read
actions: read
jobs:
generate-firewall-rules:
name: Generate Firewall Rules
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Apply Firewall Rules to Runner (Auto-run only)
if: github.event_name != 'workflow_dispatch'
env:
DEV_FTP_HOST: ${{ vars.DEV_FTP_HOST }}
DEV_FTP_PORT: ${{ vars.DEV_FTP_PORT }}
run: |
echo "🔥 Applying firewall rules for coding agent environment..."
echo ""
echo "This step ensures the GitHub Actions runner can access trusted domains"
echo "including license providers, package registries, and documentation sources."
echo ""
# Note: GitHub Actions runners are ephemeral and run in controlled environments
# This step documents what domains are being accessed during the workflow
# Actual firewall configuration is managed by GitHub
cat > /tmp/trusted-domains.txt << 'EOF'
# Trusted domains for coding agent environment
# License Providers
www.gnu.org
opensource.org
choosealicense.com
spdx.org
creativecommons.org
apache.org
fsf.org
# Documentation & Standards
semver.org
keepachangelog.com
conventionalcommits.org
# GitHub & Related
github.com
api.github.com
docs.github.com
raw.githubusercontent.com
ghcr.io
# Package Registries
npmjs.com
registry.npmjs.org
pypi.org
files.pythonhosted.org
packagist.org
repo.packagist.org
rubygems.org
# Platform-Specific
joomla.org
downloads.joomla.org
docs.joomla.org
php.net
getcomposer.org
dolibarr.org
wiki.dolibarr.org
docs.dolibarr.org
# Moko Consulting
mokoconsulting.tech
# SFTP Deployment Server (DEV_FTP_HOST)
${DEV_FTP_HOST:-<not configured>}
# Google Services
drive.google.com
docs.google.com
sheets.google.com
accounts.google.com
storage.googleapis.com
fonts.googleapis.com
fonts.gstatic.com
# GitHub Extended
upload.github.com
objects.githubusercontent.com
user-images.githubusercontent.com
codeload.github.com
pkg.github.com
# Developer Reference
developer.mozilla.org
stackoverflow.com
git-scm.com
# CDN & Infrastructure
cdn.jsdelivr.net
unpkg.com
cdnjs.cloudflare.com
img.shields.io
# Container Registries
hub.docker.com
registry-1.docker.io
# CI & Code Quality
codecov.io
sonarcloud.io
# Terraform & Infrastructure
registry.terraform.io
releases.hashicorp.com
checkpoint-api.hashicorp.com
EOF
echo "✓ Trusted domains documented for this runner"
echo "✓ GitHub Actions runners have network access to these domains"
echo ""
# Test connectivity to key domains
echo "Testing connectivity to key domains..."
for domain in "github.com" "www.gnu.org" "npmjs.com" "pypi.org"; do
if curl -s --max-time 3 -o /dev/null -w "%{http_code}" "https://$domain" | grep -q "200\|301\|302"; then
echo " ✓ $domain is accessible"
else
echo " ⚠️ $domain connectivity check failed (may be expected)"
fi
done
# Test SFTP server connectivity (TCP port check)
SFTP_HOST="${DEV_FTP_HOST:-}"
SFTP_PORT="${DEV_FTP_PORT:-22}"
if [ -n "$SFTP_HOST" ]; then
# Strip any embedded :port suffix
SFTP_HOST="${SFTP_HOST%%:*}"
echo ""
echo "Testing SFTP deployment server connectivity..."
if timeout 5 bash -c "echo >/dev/tcp/${SFTP_HOST}/${SFTP_PORT}" 2>/dev/null; then
echo " ✓ SFTP server ${SFTP_HOST}:${SFTP_PORT} is reachable"
else
echo " ⚠️ SFTP server ${SFTP_HOST}:${SFTP_PORT} is not reachable from runner (firewall rule needed)"
fi
else
echo ""
echo " ️ DEV_FTP_HOST not configured — skipping SFTP connectivity check"
fi
- name: Generate Firewall Configuration
id: generate
env:
DEV_FTP_HOST: ${{ vars.DEV_FTP_HOST }}
DEV_FTP_PORT: ${{ vars.DEV_FTP_PORT }}
run: |
cat > generate_firewall_config.py << 'PYTHON_EOF'
#!/usr/bin/env python3
"""
Enterprise Firewall Configuration Generator
Generates firewall rules for enterprise-ready deployments allowing
access to trusted domains including license providers, documentation
sources, package registries, and platform-specific sites.
"""
import json
import os
import yaml
import sys
from typing import List, Dict
# SFTP deployment server from org variables
_sftp_host_raw = os.environ.get("DEV_FTP_HOST", "").strip()
_sftp_port = os.environ.get("DEV_FTP_PORT", "").strip() or "22"
# Strip embedded :port suffix if present
_sftp_host = _sftp_host_raw.split(":")[0] if _sftp_host_raw else ""
if ":" in _sftp_host_raw and not _sftp_port:
_sftp_port = _sftp_host_raw.split(":")[1]
SFTP_HOST = _sftp_host
SFTP_PORT = int(_sftp_port) if _sftp_port.isdigit() else 22
# Trusted domains from .github/copilot.yml
TRUSTED_DOMAINS = {
"license_providers": [
"www.gnu.org",
"opensource.org",
"choosealicense.com",
"spdx.org",
"creativecommons.org",
"apache.org",
"fsf.org",
],
"documentation_standards": [
"semver.org",
"keepachangelog.com",
"conventionalcommits.org",
],
"github_related": [
"github.com",
"api.github.com",
"docs.github.com",
"raw.githubusercontent.com",
"ghcr.io",
],
"package_registries": [
"npmjs.com",
"registry.npmjs.org",
"pypi.org",
"files.pythonhosted.org",
"packagist.org",
"repo.packagist.org",
"rubygems.org",
],
"standards_organizations": [
"json-schema.org",
"w3.org",
"ietf.org",
],
"platform_specific": [
"joomla.org",
"downloads.joomla.org",
"docs.joomla.org",
"php.net",
"getcomposer.org",
"dolibarr.org",
"wiki.dolibarr.org",
"docs.dolibarr.org",
],
"moko_consulting": [
"mokoconsulting.tech",
],
"google_services": [
"drive.google.com",
"docs.google.com",
"sheets.google.com",
"accounts.google.com",
"storage.googleapis.com",
"fonts.googleapis.com",
"fonts.gstatic.com",
],
"github_extended": [
"upload.github.com",
"objects.githubusercontent.com",
"user-images.githubusercontent.com",
"codeload.github.com",
"pkg.github.com",
],
"developer_reference": [
"developer.mozilla.org",
"stackoverflow.com",
"git-scm.com",
],
"cdn_and_infrastructure": [
"cdn.jsdelivr.net",
"unpkg.com",
"cdnjs.cloudflare.com",
"img.shields.io",
],
"container_registries": [
"hub.docker.com",
"registry-1.docker.io",
],
"ci_code_quality": [
"codecov.io",
"sonarcloud.io",
],
"terraform_infrastructure": [
"registry.terraform.io",
"releases.hashicorp.com",
"checkpoint-api.hashicorp.com",
],
}
# Inject SFTP deployment server as a separate category (port 22, not 443)
if SFTP_HOST:
TRUSTED_DOMAINS["sftp_deployment_server"] = [SFTP_HOST]
print(f"️ SFTP deployment server: {SFTP_HOST}:{SFTP_PORT}")
def generate_sftp_iptables_rules(host: str, port: int) -> str:
"""Generate iptables rules specifically for SFTP egress"""
return (
f"# Allow SFTP to deployment server {host}:{port}\n"
f"iptables -A OUTPUT -p tcp -d $(dig +short {host} | head -1)"
f" --dport {port} -j ACCEPT # SFTP deploy\n"
)
def generate_sftp_ufw_rules(host: str, port: int) -> str:
"""Generate UFW rules for SFTP egress"""
return (
f"# Allow SFTP to deployment server\n"
f"ufw allow out to $(dig +short {host} | head -1)"
f" port {port} proto tcp comment 'SFTP deploy to {host}'\n"
)
def generate_sftp_firewalld_rules(host: str, port: int) -> str:
"""Generate firewalld rules for SFTP egress"""
return (
f"# Allow SFTP to deployment server\n"
f"firewall-cmd --permanent --add-rich-rule='"
f"rule family=ipv4 destination address=$(dig +short {host} | head -1)"
f" port port={port} protocol=tcp accept' # SFTP deploy\n"
)
def generate_iptables_rules(domains: List[str]) -> str:
"""Generate iptables firewall rules"""
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - iptables", ""]
rules.append("# Allow outbound HTTPS to trusted domains")
rules.append("")
for domain in domains:
rules.append(f"# Allow {domain}")
rules.append(f"iptables -A OUTPUT -p tcp -d $(dig +short {domain} | head -1) --dport 443 -j ACCEPT")
rules.append("")
rules.append("# Allow DNS lookups")
rules.append("iptables -A OUTPUT -p udp --dport 53 -j ACCEPT")
rules.append("iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT")
return "\n".join(rules)
def generate_ufw_rules(domains: List[str]) -> str:
"""Generate UFW firewall rules"""
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - UFW", ""]
rules.append("# Allow outbound HTTPS to trusted domains")
rules.append("")
for domain in domains:
rules.append(f"# Allow {domain}")
rules.append(f"ufw allow out to $(dig +short {domain} | head -1) port 443 proto tcp comment 'Allow {domain}'")
rules.append("")
rules.append("# Allow DNS")
rules.append("ufw allow out 53/udp comment 'Allow DNS UDP'")
rules.append("ufw allow out 53/tcp comment 'Allow DNS TCP'")
return "\n".join(rules)
def generate_firewalld_rules(domains: List[str]) -> str:
"""Generate firewalld rules"""
rules = ["#!/bin/bash", "", "# Enterprise Firewall Rules - firewalld", ""]
rules.append("# Add trusted domains to firewall")
rules.append("")
for domain in domains:
rules.append(f"# Allow {domain}")
rules.append(f"firewall-cmd --permanent --add-rich-rule='rule family=ipv4 destination address=$(dig +short {domain} | head -1) port port=443 protocol=tcp accept'")
rules.append("")
rules.append("# Reload firewall")
rules.append("firewall-cmd --reload")
return "\n".join(rules)
def generate_aws_security_group(domains: List[str]) -> Dict:
"""Generate AWS Security Group rules (JSON format)"""
rules = {
"SecurityGroupRules": {
"Egress": []
}
}
for domain in domains:
rules["SecurityGroupRules"]["Egress"].append({
"Description": f"Allow HTTPS to {domain}",
"IpProtocol": "tcp",
"FromPort": 443,
"ToPort": 443,
"CidrIp": "0.0.0.0/0", # In practice, resolve to specific IPs
"Tags": [{
"Key": "Domain",
"Value": domain
}]
})
# Add DNS
rules["SecurityGroupRules"]["Egress"].append({
"Description": "Allow DNS",
"IpProtocol": "udp",
"FromPort": 53,
"ToPort": 53,
"CidrIp": "0.0.0.0/0"
})
return rules
def generate_markdown_documentation(domains_by_category: Dict[str, List[str]]) -> str:
"""Generate markdown documentation"""
md = ["# Enterprise Firewall Configuration Guide", ""]
md.append("## Overview")
md.append("")
md.append("This document provides firewall configuration guidance for enterprise-ready deployments.")
md.append("It lists trusted domains that should be whitelisted for outbound access to ensure")
md.append("proper functionality of license validation, package management, and documentation access.")
md.append("")
md.append("## Trusted Domains by Category")
md.append("")
all_domains = []
for category, domains in domains_by_category.items():
category_name = category.replace("_", " ").title()
md.append(f"### {category_name}")
md.append("")
md.append("| Domain | Purpose |")
md.append("|--------|---------|")
for domain in domains:
all_domains.append(domain)
purpose = get_domain_purpose(domain)
md.append(f"| `{domain}` | {purpose} |")
md.append("")
md.append("## Implementation Examples")
md.append("")
md.append("### iptables Example")
md.append("")
md.append("```bash")
md.append("# Allow HTTPS to trusted domain")
md.append(f"iptables -A OUTPUT -p tcp -d $(dig +short {all_domains[0]}) --dport 443 -j ACCEPT")
md.append("```")
md.append("")
md.append("### UFW Example")
md.append("")
md.append("```bash")
md.append("# Allow HTTPS to trusted domain")
md.append(f"ufw allow out to {all_domains[0]} port 443 proto tcp")
md.append("```")
md.append("")
md.append("### AWS Security Group Example")
md.append("")
md.append("```json")
md.append("{")
md.append(' "IpPermissions": [{')
md.append(' "IpProtocol": "tcp",')
md.append(' "FromPort": 443,')
md.append(' "ToPort": 443,')
md.append(' "IpRanges": [{"CidrIp": "0.0.0.0/0", "Description": "HTTPS to trusted domains"}]')
md.append(" }]")
md.append("}")
md.append("```")
md.append("")
md.append("## Ports Required")
md.append("")
md.append("| Port | Protocol | Purpose |")
md.append("|------|----------|---------|")
md.append("| 443 | TCP | HTTPS (secure web access) |")
md.append("| 80 | TCP | HTTP (redirects to HTTPS) |")
md.append("| 53 | UDP/TCP | DNS resolution |")
md.append("")
md.append("## Security Considerations")
md.append("")
md.append("1. **DNS Resolution**: Ensure DNS queries are allowed (port 53 UDP/TCP)")
md.append("2. **Certificate Validation**: HTTPS requires ability to reach certificate authorities")
md.append("3. **Dynamic IPs**: Some domains use CDNs with dynamic IPs - consider using FQDNs in rules")
md.append("4. **Regular Updates**: Review and update whitelist as services change")
md.append("5. **Logging**: Enable logging for blocked connections to identify missing rules")
md.append("")
md.append("## Compliance Notes")
md.append("")
md.append("- All listed domains provide read-only access to public information")
md.append("- License providers enable GPL compliance verification")
md.append("- Package registries support dependency security scanning")
md.append("- No authentication credentials are transmitted to these domains")
md.append("")
return "\n".join(md)
def get_domain_purpose(domain: str) -> str:
"""Get human-readable purpose for a domain"""
purposes = {
"www.gnu.org": "GNU licenses and documentation",
"opensource.org": "Open Source Initiative resources",
"choosealicense.com": "GitHub license selection tool",
"spdx.org": "Software Package Data Exchange identifiers",
"creativecommons.org": "Creative Commons licenses",
"apache.org": "Apache Software Foundation licenses",
"fsf.org": "Free Software Foundation resources",
"semver.org": "Semantic versioning specification",
"keepachangelog.com": "Changelog format standards",
"conventionalcommits.org": "Commit message conventions",
"github.com": "GitHub platform access",
"api.github.com": "GitHub API access",
"docs.github.com": "GitHub documentation",
"raw.githubusercontent.com": "GitHub raw content access",
"npmjs.com": "npm package registry",
"pypi.org": "Python Package Index",
"packagist.org": "PHP Composer package registry",
"rubygems.org": "Ruby gems registry",
"joomla.org": "Joomla CMS platform",
"php.net": "PHP documentation and downloads",
"dolibarr.org": "Dolibarr ERP/CRM platform",
}
return purposes.get(domain, "Trusted resource")
def main():
# Use inputs if provided (manual dispatch), otherwise use defaults (auto-run)
firewall_type = "${{ github.event.inputs.firewall_type }}" or "all"
output_format = "${{ github.event.inputs.output_format }}" or "markdown"
print(f"Running in {'manual' if '${{ github.event.inputs.firewall_type }}' else 'automatic'} mode")
print(f"Firewall type: {firewall_type}")
print(f"Output format: {output_format}")
print("")
# Collect all domains
all_domains = []
for domains in TRUSTED_DOMAINS.values():
all_domains.extend(domains)
# Remove duplicates and sort
all_domains = sorted(set(all_domains))
print(f"Generating firewall rules for {len(all_domains)} trusted domains...")
print("")
# Exclude SFTP server from HTTPS rule generation (different port)
https_domains = [d for d in all_domains if d != SFTP_HOST]
# Generate based on firewall type
if firewall_type in ["iptables", "all"]:
rules = generate_iptables_rules(https_domains)
if SFTP_HOST:
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
rules += generate_sftp_iptables_rules(SFTP_HOST, SFTP_PORT)
with open("firewall-rules-iptables.sh", "w") as f:
f.write(rules)
print("✓ Generated iptables rules: firewall-rules-iptables.sh")
if firewall_type in ["ufw", "all"]:
rules = generate_ufw_rules(https_domains)
if SFTP_HOST:
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
rules += generate_sftp_ufw_rules(SFTP_HOST, SFTP_PORT)
with open("firewall-rules-ufw.sh", "w") as f:
f.write(rules)
print("✓ Generated UFW rules: firewall-rules-ufw.sh")
if firewall_type in ["firewalld", "all"]:
rules = generate_firewalld_rules(https_domains)
if SFTP_HOST:
rules += "\n# ── SFTP Deployment Server ──────────────────────────────\n"
rules += generate_sftp_firewalld_rules(SFTP_HOST, SFTP_PORT)
with open("firewall-rules-firewalld.sh", "w") as f:
f.write(rules)
print("✓ Generated firewalld rules: firewall-rules-firewalld.sh")
if firewall_type in ["aws-security-group", "all"]:
rules = generate_aws_security_group(all_domains)
with open("firewall-rules-aws-sg.json", "w") as f:
json.dump(rules, f, indent=2)
print("✓ Generated AWS Security Group rules: firewall-rules-aws-sg.json")
if output_format in ["yaml", "all"]:
with open("trusted-domains.yml", "w") as f:
yaml.dump(TRUSTED_DOMAINS, f, default_flow_style=False)
print("✓ Generated YAML domain list: trusted-domains.yml")
if output_format in ["json", "all"]:
with open("trusted-domains.json", "w") as f:
json.dump(TRUSTED_DOMAINS, f, indent=2)
print("✓ Generated JSON domain list: trusted-domains.json")
if output_format in ["markdown", "all"]:
md = generate_markdown_documentation(TRUSTED_DOMAINS)
with open("FIREWALL_CONFIGURATION.md", "w") as f:
f.write(md)
print("✓ Generated documentation: FIREWALL_CONFIGURATION.md")
print("")
print("Domain Categories:")
for category, domains in TRUSTED_DOMAINS.items():
print(f" - {category}: {len(domains)} domains")
print("")
print("Total unique domains: ", len(all_domains))
if __name__ == "__main__":
main()
PYTHON_EOF
chmod +x generate_firewall_config.py
pip install PyYAML
python3 generate_firewall_config.py
- name: Upload Firewall Configuration Artifacts
uses: actions/upload-artifact@v6
with:
name: firewall-configurations
path: |
firewall-rules-*.sh
firewall-rules-*.json
trusted-domains.*
FIREWALL_CONFIGURATION.md
retention-days: 90
- name: Display Summary
run: |
echo "## Firewall Configuration" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "**Mode**: Manual Execution" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Firewall rules have been generated for enterprise-ready deployments." >> $GITHUB_STEP_SUMMARY
else
echo "**Mode**: Automatic Execution (Coding Agent Active)" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "This workflow ran automatically because a coding agent (GitHub Copilot) is active." >> $GITHUB_STEP_SUMMARY
echo "Firewall configuration has been validated for the coding agent environment." >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Files Generated" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if ls firewall-rules-* trusted-domains.* FIREWALL_CONFIGURATION.md 2>/dev/null; then
ls -lh firewall-rules-* trusted-domains.* FIREWALL_CONFIGURATION.md 2>/dev/null | awk '{print "- " $9 " (" $5 ")"}' >> $GITHUB_STEP_SUMMARY
else
echo "- Documentation generated" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "### Download Artifacts" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Download the generated firewall configurations from the workflow artifacts." >> $GITHUB_STEP_SUMMARY
else
echo "### Trusted Domains Active" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "The coding agent has access to:" >> $GITHUB_STEP_SUMMARY
echo "- License providers (GPL, OSI, SPDX, Apache, etc.)" >> $GITHUB_STEP_SUMMARY
echo "- Package registries (npm, PyPI, Packagist, RubyGems)" >> $GITHUB_STEP_SUMMARY
echo "- Documentation sources (GitHub, Joomla, Dolibarr, PHP)" >> $GITHUB_STEP_SUMMARY
echo "- Standards organizations (W3C, IETF, JSON Schema)" >> $GITHUB_STEP_SUMMARY
fi
# Usage Instructions:
#
# This workflow runs in two modes:
#
# 1. AUTOMATIC MODE (Coding Agent):
# - Triggers when coding agent branches (copilot/**, agent/**) are pushed or PR'd
# - Validates firewall configuration for the coding agent environment
# - Documents accessible domains for compliance
# - Ensures license sources and package registries are available
#
# 2. MANUAL MODE (Enterprise Configuration):
# - Manually trigger from the Actions tab
# - Select desired firewall type and output format
# - Download generated artifacts
# - Apply firewall rules to your enterprise environment
#
# Configuration:
# - Trusted domains are sourced from .github/copilot.yml
# - Modify copilot.yml to add/remove trusted domains
# - Changes automatically propagate to firewall rules
#
# Important Notes:
# - Review generated rules before applying to production
# - Some domains may use CDNs with dynamic IPs
# - Consider using FQDN-based rules where supported
# - Test thoroughly in staging environment first
# - Monitor logs for blocked connections
# - Update rules as domains/services change
+96
View File
@@ -0,0 +1,96 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
# PATH: /templates/workflows/gitleaks.yml.template
# VERSION: 01.00.00
# BRIEF: Secret scanning — detect leaked credentials, API keys, and tokens
#
# +========================================================================+
# | SECRET SCANNING |
# +========================================================================+
# | |
# | Scans commits for leaked secrets using Gitleaks. |
# | |
# | - PR scan: only new commits in the PR |
# | - Scheduled: full repo scan weekly |
# | - Alerts via ntfy on findings |
# | |
# +========================================================================+
name: "Universal: Secret Scanning"
on:
pull_request:
branches:
- main
- 'dev/**'
schedule:
- cron: '0 5 * * 1' # Weekly Monday 05:00 UTC
workflow_dispatch:
permissions:
contents: read
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }}
jobs:
gitleaks:
name: Gitleaks Secret Scan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Gitleaks
run: |
GITLEAKS_VERSION="8.21.2"
curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz -C /usr/local/bin gitleaks
gitleaks version
- name: Scan for secrets
id: scan
run: |
echo "### Secret Scanning" >> $GITHUB_STEP_SUMMARY
ARGS="--source . --verbose --report-format json --report-path /tmp/gitleaks-report.json"
if [ "${{ github.event_name }}" = "pull_request" ]; then
# Scan only PR commits
ARGS="$ARGS --log-opts=${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}"
echo "Scanning PR commits only" >> $GITHUB_STEP_SUMMARY
else
echo "Full repository scan" >> $GITHUB_STEP_SUMMARY
fi
if gitleaks detect $ARGS 2>&1; then
echo "result=clean" >> "$GITHUB_OUTPUT"
echo "**No secrets detected.**" >> $GITHUB_STEP_SUMMARY
else
echo "result=found" >> "$GITHUB_OUTPUT"
FINDINGS=$(jq length /tmp/gitleaks-report.json 2>/dev/null || echo "unknown")
echo "**${FINDINGS} potential secret(s) detected.**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Review the findings and rotate any exposed credentials immediately." >> $GITHUB_STEP_SUMMARY
exit 1
fi
- name: Notify on findings
if: failure() && steps.scan.outputs.result == 'found'
run: |
REPO="${{ github.event.repository.name }}"
curl -sS \
-H "Title: ${REPO} — secrets detected in code" \
-H "Tags: rotating_light,key" \
-H "Priority: urgent" \
-d "Gitleaks found potential secrets. Review and rotate credentials immediately." \
"${NTFY_URL}/${NTFY_TOPIC}" || true
+73
View File
@@ -0,0 +1,73 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Automation
# VERSION: 01.00.00
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
on:
issues:
types: [opened]
permissions:
contents: write
issues: write
env:
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
jobs:
create-branch:
name: Create feature branch
runs-on: ubuntu-latest
steps:
- name: Create branch and comment
run: |
TOKEN="${{ secrets.GA_TOKEN }}"
API="${GITEA_URL}/api/v1/repos/${{ github.repository }}"
ISSUE_NUM="${{ github.event.issue.number }}"
ISSUE_TITLE="${{ github.event.issue.title }}"
# Build slug from title: lowercase, replace non-alnum with dash, trim
SLUG=$(echo "${ISSUE_TITLE}" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//' | cut -c1-40)
BRANCH="feature/${ISSUE_NUM}-${SLUG}"
# Check dev branch exists
DEV_EXISTS=$(curl -sf -o /dev/null -w '%{http_code}' \
-H "Authorization: token ${TOKEN}" \
"${API}/branches/dev" 2>/dev/null || echo "000")
if [ "${DEV_EXISTS}" != "200" ]; then
echo "No dev branch -- skipping"
exit 0
fi
# Create branch from dev
HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API}/branches" \
-d "{\"new_branch_name\":\"${BRANCH}\",\"old_branch_name\":\"dev\"}" 2>/dev/null || echo "000")
if [ "${HTTP}" = "201" ]; then
echo "Created branch: ${BRANCH}"
# Comment on issue with branch link
REPO_URL="${GITEA_URL}/${{ github.repository }}"
BODY="Branch created: [\`${BRANCH}\`](${REPO_URL}/src/branch/${BRANCH})\n\n\`\`\`bash\ngit fetch origin\ngit checkout ${BRANCH}\n\`\`\`"
curl -sf -X POST \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues/${ISSUE_NUM}/comments" \
-d "{\"body\":\"${BODY}\"}" > /dev/null 2>&1
echo "Commented on issue #${ISSUE_NUM}"
else
echo "Failed to create branch (HTTP ${HTTP}) -- may already exist"
fi
+278
View File
@@ -0,0 +1,278 @@
# MCP Server Auto-Release
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# MCP-specific release pipeline that builds TypeScript, runs validation,
# attaches the compiled dist/ as a release artifact, and creates a GitHub
# Release with tool inventory in the release notes.
#
# This replaces the generic auto-release.yml for MCP server repos.
name: "MCP: Build & Release"
on:
push:
branches:
- main
paths:
- 'src/**'
- 'package.json'
- 'tsconfig.json'
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: write
issues: write
jobs:
build-and-release:
name: Build, Validate & Release
runs-on: ubuntu-latest
if: >-
!contains(github.event.head_commit.message, '[skip ci]') &&
github.actor != 'github-actions[bot]'
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GH_TOKEN || github.token }}
fetch-depth: 0
# ── Build ────────────────────────────────────────────────────────
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: TypeScript compile check
run: npx tsc --noEmit
- name: Build
run: npm run build
- name: Verify dist output
run: |
for f in index.js client.js config.js types.js; do
test -f "dist/${f}" || (echo "ERROR: dist/${f} not found" && exit 1)
done
echo "✓ All dist files present"
# ── Tool Inventory ───────────────────────────────────────────────
- name: Generate tool inventory
id: tools
run: |
TOOL_COUNT=$(grep -c "server\.tool(" src/index.ts || echo "0")
echo "count=${TOOL_COUNT}" >> "$GITHUB_OUTPUT"
# Extract tool names
TOOL_LIST=$(grep -oE "'[a-z_]+'" src/index.ts | head -100 | tr -d "'" | sort -u)
echo "Tools registered: ${TOOL_COUNT}"
# Generate inventory for release notes
echo "## Tool Inventory (${TOOL_COUNT} tools)" > /tmp/tool-inventory.md
echo "" >> /tmp/tool-inventory.md
grep -B0 -A1 "server\.tool(" src/index.ts | grep -oE "'[^']+'" | while IFS= read -r name; do
read -r desc 2>/dev/null || true
CLEAN_NAME=$(echo "$name" | tr -d "'")
CLEAN_DESC=$(echo "$desc" | tr -d "'" | sed 's/,$//')
if [ -n "$CLEAN_NAME" ] && [ -n "$CLEAN_DESC" ]; then
echo "- \`${CLEAN_NAME}\` — ${CLEAN_DESC}" >> /tmp/tool-inventory.md
fi
done
# ── Version ──────────────────────────────────────────────────────
- name: Setup MokoStandards tools
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --branch version/04 --quiet \
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
/tmp/mokostandards
cd /tmp/mokostandards
composer install --no-dev --no-interaction --quiet
- name: Read version from README.md
id: version
run: |
VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null)
if [ -z "$VERSION" ]; then
echo "No VERSION in README.md — skipping release"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
MAJOR=$(echo "$VERSION" | awk -F. '{print $1}')
MINOR=$(echo "$VERSION" | awk -F. '{printf "%s.%s", $1, $2}')
PATCH=$(echo "$VERSION" | awk -F. '{print $3}')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT"
if [ "$PATCH" = "00" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
if [ "$PATCH" = "01" ]; then
echo "is_first=true" >> "$GITHUB_OUTPUT"
else
echo "is_first=false" >> "$GITHUB_OUTPUT"
fi
fi
- name: Check if already released
if: steps.version.outputs.skip != 'true'
id: check
run: |
TAG="${{ steps.version.outputs.release_tag }}"
TAG_EXISTS=false
git rev-parse "$TAG" >/dev/null 2>&1 && TAG_EXISTS=true
echo "tag_exists=$TAG_EXISTS" >> "$GITHUB_OUTPUT"
# ── Release Artifact ─────────────────────────────────────────────
- name: Package dist
if: steps.version.outputs.skip != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
REPO_NAME="${{ github.event.repository.name }}"
tar -czf "/tmp/${REPO_NAME}-${VERSION}.tar.gz" -C dist .
echo "artifact=/tmp/${REPO_NAME}-${VERSION}.tar.gz" >> "$GITHUB_OUTPUT"
# ── Version Updates ──────────────────────────────────────────────
- name: Set platform version
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
php /tmp/mokostandards/api/cli/version_set_platform.php \
--path . --version "$VERSION" --branch main
- name: Update version badges
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true'
run: |
VERSION="${{ steps.version.outputs.version }}"
find . -name "*.md" ! -path "./.git/*" ! -path "./vendor/*" | while read -r f; do
if grep -q '\[VERSION:' "$f" 2>/dev/null; then
sed -i "s/\[VERSION:[[:space:]]*[0-9]\{2\}\.[0-9]\{2\}\.[0-9]\{2\}\]/[VERSION: ${VERSION}]/" "$f"
fi
done
- name: Commit release changes
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true'
run: |
if git diff --quiet && git diff --cached --quiet; then
echo "No changes to commit"
exit 0
fi
VERSION="${{ steps.version.outputs.version }}"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add -A
git commit -m "chore(release): build ${VERSION} [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
# ── Version Branch ───────────────────────────────────────────────
- name: Archive version branch
if: steps.check.outputs.tag_exists != 'true'
run: |
BRANCH="${{ steps.version.outputs.branch }}"
git push origin HEAD:"$BRANCH" --force
echo "Updated archive branch: ${BRANCH}" >> $GITHUB_STEP_SUMMARY
# ── Tag & Release ────────────────────────────────────────────────
- name: Create git tag
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true' &&
steps.version.outputs.is_first == 'true'
run: |
TAG="${{ steps.version.outputs.release_tag }}"
if ! git rev-parse "$TAG" >/dev/null 2>&1; then
git tag "$TAG"
git push origin "$TAG"
fi
- name: GitHub Release
if: >-
steps.version.outputs.skip != 'true' &&
steps.check.outputs.tag_exists != 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
VERSION="${{ steps.version.outputs.version }}"
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
MAJOR="${{ steps.version.outputs.major }}"
BRANCH="${{ steps.version.outputs.branch }}"
TOOL_COUNT="${{ steps.tools.outputs.count }}"
REPO_NAME="${{ github.event.repository.name }}"
# Build release notes
NOTES=$(php /tmp/mokostandards/api/cli/release_notes.php --path . --version "$VERSION" 2>/dev/null)
[ -z "$NOTES" ] && NOTES="Release ${VERSION}"
{
echo "$NOTES"
echo ""
echo "---"
echo ""
echo "### MCP Server Info"
echo "- **Tools registered**: ${TOOL_COUNT}"
echo "- **Node.js**: 20+"
echo "- **MCP SDK**: $(node -p \"require('./package.json').dependencies['@modelcontextprotocol/sdk']\" 2>/dev/null || echo 'unknown')"
echo ""
cat /tmp/tool-inventory.md 2>/dev/null || true
} > /tmp/release_notes.md
EXISTING=$(gh release view "$RELEASE_TAG" --json tagName -q .tagName 2>/dev/null || true)
ARTIFACT="/tmp/${REPO_NAME}-${VERSION}.tar.gz"
if [ -z "$EXISTING" ]; then
gh release create "$RELEASE_TAG" \
--title "v${MAJOR} (latest: ${VERSION})" \
--notes-file /tmp/release_notes.md \
--target "$BRANCH" \
"$ARTIFACT"
echo "Release created: ${RELEASE_TAG} (${VERSION})" >> $GITHUB_STEP_SUMMARY
else
gh release edit "$RELEASE_TAG" \
--title "v${MAJOR} (latest: ${VERSION})" \
--notes-file /tmp/release_notes.md
gh release upload "$RELEASE_TAG" "$ARTIFACT" --clobber 2>/dev/null || true
echo "Release updated: ${RELEASE_TAG} -> ${VERSION}" >> $GITHUB_STEP_SUMMARY
fi
# ── Summary ──────────────────────────────────────────────────────
- name: Pipeline Summary
if: always()
run: |
VERSION="${{ steps.version.outputs.version }}"
TOOL_COUNT="${{ steps.tools.outputs.count }}"
if [ "${{ steps.version.outputs.skip }}" = "true" ]; then
echo "## Release Skipped" >> $GITHUB_STEP_SUMMARY
else
echo "" >> $GITHUB_STEP_SUMMARY
echo "## MCP Release Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Detail | Value |" >> $GITHUB_STEP_SUMMARY
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tools | ${TOOL_COUNT} |" >> $GITHUB_STEP_SUMMARY
echo "| Branch | \`${{ steps.version.outputs.branch }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Tag | \`${{ steps.version.outputs.release_tag }}\` |" >> $GITHUB_STEP_SUMMARY
fi
+65
View File
@@ -0,0 +1,65 @@
# MCP Server Build & Validation
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Builds the MCP server, validates TypeScript compilation, and checks
# that tools are properly registered with valid Zod schemas.
name: "MCP: Build & Validate"
on:
push:
branches: [main, dev/**]
paths: ['src/**', 'package.json', 'tsconfig.json']
pull_request:
branches: [main]
paths: ['src/**', 'package.json', 'tsconfig.json']
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20, 22]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: TypeScript compile
run: npx tsc --noEmit
- name: Build
run: npm run build
- name: Verify dist output exists
run: |
test -f dist/index.js || (echo "ERROR: dist/index.js not found" && exit 1)
test -f dist/client.js || (echo "ERROR: dist/client.js not found" && exit 1)
test -f dist/config.js || (echo "ERROR: dist/config.js not found" && exit 1)
test -f dist/types.js || (echo "ERROR: dist/types.js not found" && exit 1)
echo "✓ All required dist files present"
- name: Verify shebang in index.js
run: |
head -1 dist/index.js | grep -q "#!/usr/bin/env node" || echo "WARNING: Missing shebang in dist/index.js"
- name: Count registered tools
run: |
TOOL_COUNT=$(grep -c "server\.tool(" src/index.ts || true)
echo "Registered tools: ${TOOL_COUNT}"
if [ "${TOOL_COUNT}" -eq 0 ]; then
echo "ERROR: No tools registered in src/index.ts"
exit 1
fi
+109
View File
@@ -0,0 +1,109 @@
# MCP SDK Version Check
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Weekly check for MCP SDK updates. Creates an issue when a new version
# of @modelcontextprotocol/sdk is available.
name: "MCP: SDK Version Check"
on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 9am UTC
workflow_dispatch:
permissions:
contents: read
jobs:
check-sdk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Check for SDK updates
id: sdk-check
run: |
CURRENT=$(node -p "require('./package.json').dependencies['@modelcontextprotocol/sdk']" | sed 's/[\^~]//')
LATEST=$(npm view @modelcontextprotocol/sdk version 2>/dev/null || echo "unknown")
echo "current=${CURRENT}" >> $GITHUB_OUTPUT
echo "latest=${LATEST}" >> $GITHUB_OUTPUT
if [ "${CURRENT}" != "${LATEST}" ] && [ "${LATEST}" != "unknown" ]; then
echo "update_available=true" >> $GITHUB_OUTPUT
echo "MCP SDK update available: ${CURRENT} → ${LATEST}"
else
echo "update_available=false" >> $GITHUB_OUTPUT
echo "MCP SDK is up to date: ${CURRENT}"
fi
- name: Check for Zod updates
id: zod-check
run: |
CURRENT=$(node -p "require('./package.json').dependencies['zod']" | sed 's/[\^~]//')
LATEST=$(npm view zod version 2>/dev/null || echo "unknown")
echo "current=${CURRENT}" >> $GITHUB_OUTPUT
echo "latest=${LATEST}" >> $GITHUB_OUTPUT
if [ "${CURRENT}" != "${LATEST}" ] && [ "${LATEST}" != "unknown" ]; then
echo "update_available=true" >> $GITHUB_OUTPUT
else
echo "update_available=false" >> $GITHUB_OUTPUT
fi
- name: Create update issue
if: steps.sdk-check.outputs.update_available == 'true'
uses: actions/github-script@v7
with:
script: |
const title = `chore(deps): update @modelcontextprotocol/sdk ${process.env.CURRENT} → ${process.env.LATEST}`;
const body = [
'## MCP SDK Update Available',
'',
`| Package | Current | Latest |`,
`|---------|---------|--------|`,
`| @modelcontextprotocol/sdk | ${process.env.CURRENT} | ${process.env.LATEST} |`,
`| zod | ${process.env.ZOD_CURRENT} | ${process.env.ZOD_LATEST} |`,
'',
'### Steps',
'1. Update package.json',
'2. Run `npm install`',
'3. Run `npm run build` to verify compilation',
'4. Test all tools against target API',
'',
'### Changelog',
`https://github.com/modelcontextprotocol/typescript-sdk/releases`,
].join('\n');
// Check for existing open issue
const existing = await github.rest.issues.listForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
labels: 'api-change',
});
const alreadyExists = existing.data.some(i => i.title.includes('@modelcontextprotocol/sdk'));
if (!alreadyExists) {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title,
body,
labels: ['api-change', 'chore'],
});
}
env:
CURRENT: ${{ steps.sdk-check.outputs.current }}
LATEST: ${{ steps.sdk-check.outputs.latest }}
ZOD_CURRENT: ${{ steps.zod-check.outputs.current }}
ZOD_LATEST: ${{ steps.zod-check.outputs.latest }}
@@ -0,0 +1,61 @@
# MCP Tool Inventory
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Generates a tool inventory report on each push to main.
# Extracts tool names, descriptions, and parameter counts from src/index.ts.
name: "MCP: Tool Inventory"
on:
push:
branches: [main]
paths: ['src/index.ts']
workflow_dispatch:
permissions:
contents: read
jobs:
inventory:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate tool inventory
run: |
echo "# MCP Tool Inventory" > TOOLS.md
echo "" >> TOOLS.md
echo "Auto-generated from \`src/index.ts\` on $(date -u +%Y-%m-%dT%H:%M:%SZ)" >> TOOLS.md
echo "" >> TOOLS.md
# Count tools
TOOL_COUNT=$(grep -c "server\.tool(" src/index.ts || true)
echo "**Total tools: ${TOOL_COUNT}**" >> TOOLS.md
echo "" >> TOOLS.md
# Extract tool names and descriptions
echo "| Tool | Description |" >> TOOLS.md
echo "|------|-------------|" >> TOOLS.md
grep -A1 "server\.tool(" src/index.ts | grep -E "^\s*'" | while read -r line; do
TOOL_NAME=$(echo "$line" | sed "s/.*'\([^']*\)'.*/\1/")
# Get next line for description
DESC=$(grep -A2 "'${TOOL_NAME}'" src/index.ts | grep -E "^\s*'" | tail -1 | sed "s/.*'\([^']*\)'.*/\1/" || echo "")
echo "| \`${TOOL_NAME}\` | ${DESC} |" >> TOOLS.md
done
echo "" >> TOOLS.md
echo "---" >> TOOLS.md
echo "*Generated by MCP Tool Inventory workflow*" >> TOOLS.md
cat TOOLS.md
- name: Upload inventory artifact
uses: actions/upload-artifact@v4
with:
name: tool-inventory
path: TOOLS.md
retention-days: 90
+70
View File
@@ -0,0 +1,70 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Notifications
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/notify.yml
# VERSION: 01.00.00
# BRIEF: Push notifications via ntfy on release success or workflow failure
name: "Universal: Notifications"
on:
workflow_run:
workflows:
- "Joomla Build & Release"
- "Joomla Extension CI"
- "Deploy"
types:
- completed
permissions:
contents: read
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-releases' }}
jobs:
notify:
name: Send Notification
runs-on: ubuntu-latest
if: >-
github.event.workflow_run.conclusion == 'success' ||
github.event.workflow_run.conclusion == 'failure'
steps:
- name: Notify on success (releases only)
if: >-
github.event.workflow_run.conclusion == 'success' &&
contains(github.event.workflow_run.name, 'Release')
run: |
REPO="${{ github.event.repository.name }}"
WORKFLOW="${{ github.event.workflow_run.name }}"
URL="${{ github.event.workflow_run.html_url }}"
curl -sS \
-H "Title: ${REPO} released" \
-H "Tags: white_check_mark,package" \
-H "Priority: default" \
-H "Click: ${URL}" \
-d "${WORKFLOW} completed successfully." \
"${NTFY_URL}/${NTFY_TOPIC}"
- name: Notify on failure
if: github.event.workflow_run.conclusion == 'failure'
run: |
REPO="${{ github.event.repository.name }}"
WORKFLOW="${{ github.event.workflow_run.name }}"
URL="${{ github.event.workflow_run.html_url }}"
curl -sS \
-H "Title: ${REPO} workflow failed" \
-H "Tags: x,warning" \
-H "Priority: high" \
-H "Click: ${URL}" \
-d "${WORKFLOW} failed. Check the run for details." \
"${NTFY_URL}/${NTFY_TOPIC}"
+51
View File
@@ -0,0 +1,51 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
# SPDX-License-Identifier: GPL-3.0-or-later
name: "Publish to npm"
on:
push:
branches:
- main
workflow_dispatch:
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Check if version changed
id: version
run: |
PKG_NAME=$(node -p "require('./package.json').name")
PKG_VERSION=$(node -p "require('./package.json').version")
PUBLISHED=$(npm view "${PKG_NAME}@${PKG_VERSION}" version 2>/dev/null || echo "")
if [ "$PUBLISHED" = "$PKG_VERSION" ]; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "Version ${PKG_VERSION} already published, skipping."
else
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "Publishing ${PKG_NAME}@${PKG_VERSION}"
fi
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish
if: steps.version.outputs.skip != 'true'
run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+508
View File
@@ -0,0 +1,508 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.CI
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/universal/pr-check.yml.template
# VERSION: 09.23.00
# BRIEF: PR gate — branch policy + code validation before merge
name: "Universal: PR Check"
on:
pull_request:
types: [opened, synchronize, reopened, edited]
permissions:
contents: read
pull-requests: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
# ── Branch Policy ──────────────────────────────────────────────────────
branch-policy:
name: Branch Policy
runs-on: ubuntu-latest
steps:
- name: Check branch merge target
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
;;
patch/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "rc" ]; then
ALLOWED=false
REASON="Patch branches must target 'dev' or 'rc', not '${BASE}'"
fi
;;
hotfix/*)
if [ "$BASE" != "dev" ] && [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="Hotfix branches can only target 'dev' or 'main', not '${BASE}'"
fi
;;
rc)
if [ "$BASE" != "main" ]; then
ALLOWED=false
REASON="RC branch can only merge into '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 "## 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
# ── Code Validation ────────────────────────────────────────────────────
validate:
name: Validate PR
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check for merge conflict markers
run: |
CONFLICTS=$(grep -rn '<<<<<<< \|>>>>>>> \|^=======$' --include='*.php' --include='*.xml' --include='*.css' --include='*.js' --include='*.json' --include='*.md' --include='*.yml' --include='*.yaml' --include='*.ini' --include='*.txt' . 2>/dev/null | grep -v '.git/' || true)
if [ -n "$CONFLICTS" ]; then
echo "::error::Merge conflict markers found in source files"
echo "## Conflict Markers Found" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
echo "$CONFLICTS" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "No conflict markers found"
- name: Detect platform
id: platform
run: |
# Read platform from XML manifest (<platform> tag) or plain text fallback
PLATFORM=$(sed -n 's/.*<platform>\([^<]*\)<\/platform>.*/\1/p' .mokogitea/manifest.xml 2>/dev/null | head -1)
[ -z "$PLATFORM" ] && PLATFORM=$(cat .mokogitea/manifest.xml 2>/dev/null | tr -d '[:space:]')
[ -z "$PLATFORM" ] && PLATFORM="generic"
echo "platform=$PLATFORM" >> "$GITHUB_OUTPUT"
- name: Setup PHP
if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr'
run: |
if ! command -v php &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli php-mbstring php-xml >/dev/null 2>&1
fi
- name: PHP syntax check
if: steps.platform.outputs.platform == 'joomla' || steps.platform.outputs.platform == 'dolibarr'
run: |
ERRORS=0
while IFS= read -r -d '' file; do
if ! php -l "$file" 2>&1 | grep -q "No syntax errors"; then
ERRORS=$((ERRORS + 1))
fi
done < <(find . -name "*.php" -not -path "./.git/*" -not -path "./vendor/*" -print0)
echo "PHP lint: ${ERRORS} error(s)"
[ "$ERRORS" -eq 0 ] || { echo "::error::PHP syntax errors found"; exit 1; }
- name: Joomla JEXEC guard check
if: steps.platform.outputs.platform == 'joomla'
run: |
ERRORS=0
while IFS= read -r -d '' file; do
# Skip vendor, node_modules, and index.html stub files
case "$file" in ./vendor/*|./node_modules/*) continue ;; esac
# Check first 10 lines for JEXEC or JPATH guard
if ! head -20 "$file" | grep -qE "defined\s*\(\s*['\"](_JEXEC|JPATH_BASE|\\\\JPATH_PLATFORM)['\"]"; then
echo "::error file=${file}::Missing JEXEC guard: ${file}"
ERRORS=$((ERRORS + 1))
fi
done < <(find . -name "*.php" -path "*/src/*" -not -path "./.git/*" -not -path "./vendor/*" -print0)
if [ "$ERRORS" -gt 0 ]; then
echo "::error::${ERRORS} PHP file(s) missing defined('_JEXEC') or die guard"
echo "## JEXEC Guard Check: Failed" >> $GITHUB_STEP_SUMMARY
echo "${ERRORS} file(s) in src/ are missing the Joomla execution guard." >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "JEXEC guard: OK"
- name: Joomla directory listing protection
if: steps.platform.outputs.platform == 'joomla'
run: |
MISSING=0
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && exit 0
while IFS= read -r dir; do
if [ ! -f "${dir}/index.html" ]; then
echo "::warning::Missing index.html in ${dir} (directory listing protection)"
MISSING=$((MISSING + 1))
fi
done < <(find "$SOURCE_DIR" -type d -not -path "./.git/*" -not -path "*/vendor/*" -not -path "*/node_modules/*")
if [ "$MISSING" -gt 0 ]; then
echo "## Directory Protection" >> $GITHUB_STEP_SUMMARY
echo "${MISSING} director(ies) missing index.html" >> $GITHUB_STEP_SUMMARY
fi
echo "Directory protection: ${MISSING} missing (advisory)"
- name: Joomla script file and asset checks
if: steps.platform.outputs.platform == 'joomla'
run: |
ERRORS=0
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
[ -z "$MANIFEST" ] && exit 0
MANIFEST_DIR=$(dirname "$MANIFEST")
# Check scriptfile exists if declared
SCRIPTFILE=$(sed -n 's/.*<scriptfile>\([^<]*\)<\/scriptfile>.*/\1/p' "$MANIFEST" 2>/dev/null)
if [ -n "$SCRIPTFILE" ]; then
if [ ! -f "${MANIFEST_DIR}/${SCRIPTFILE}" ]; then
echo "::error::Manifest declares <scriptfile>${SCRIPTFILE}</scriptfile> but file not found at ${MANIFEST_DIR}/${SCRIPTFILE}"
ERRORS=$((ERRORS + 1))
else
echo "Script file: ${MANIFEST_DIR}/${SCRIPTFILE} (OK)"
fi
fi
# Require joomla.asset.json and validate it
ASSET_JSON=$(find "$MANIFEST_DIR" -name "joomla.asset.json" -not -path "./.git/*" 2>/dev/null | head -1)
if [ -z "$ASSET_JSON" ]; then
echo "::error::joomla.asset.json not found — Joomla asset system is required"
ERRORS=$((ERRORS + 1))
else
if command -v php &> /dev/null; then
php -r "json_decode(file_get_contents('$ASSET_JSON')); if(json_last_error()!==JSON_ERROR_NONE){echo json_last_error_msg();exit(1);}" 2>&1 || {
echo "::error::joomla.asset.json is not valid JSON"
ERRORS=$((ERRORS + 1))
}
fi
echo "joomla.asset.json: valid"
fi
# Validate all XML files in src/ are well-formed
XML_ERRORS=0
if command -v php &> /dev/null; then
while IFS= read -r -d '' xmlfile; do
if ! php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('$xmlfile'); if(!\$x){foreach(libxml_get_errors() as \$e) echo trim(\$e->message) . ' in $xmlfile'; exit(1);}" 2>&1; then
XML_ERRORS=$((XML_ERRORS + 1))
fi
done < <(find "$MANIFEST_DIR" -name "*.xml" -not -path "./.git/*" -print0)
fi
if [ "$XML_ERRORS" -gt 0 ]; then
echo "::error::${XML_ERRORS} XML file(s) are malformed"
ERRORS=$((ERRORS + 1))
else
echo "XML well-formedness: OK"
fi
[ "$ERRORS" -gt 0 ] && exit 1
echo "Joomla asset checks: OK"
- name: Validate platform manifest
run: |
PLATFORM="${{ steps.platform.outputs.platform }}"
case "$PLATFORM" in
joomla)
MANIFEST=$(find . -maxdepth 3 -name "*.xml" ! -path "./.git/*" -exec grep -l '<extension' {} \; 2>/dev/null | head -1)
if [ -z "$MANIFEST" ]; then
echo "::warning::No Joomla manifest found (WaaS site)"
exit 0
fi
echo "Manifest: ${MANIFEST}"
if command -v php &> /dev/null; then
php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('$MANIFEST'); if(!\$x){foreach(libxml_get_errors() as \$e) echo \$e->message; exit(1);}" || { echo "::error::Manifest XML is malformed"; exit 1; }
fi
for ELEMENT in name version description; do
grep -q "<${ELEMENT}>" "$MANIFEST" || { echo "::error::Missing <${ELEMENT}> in manifest"; exit 1; }
done
# Block legacy raw/branch update server URLs on MokoGitea
RAW_URLS=$(grep -n 'raw/branch' "$MANIFEST" | grep -i 'mokoconsulting\|mokogitea\|git\.mokoconsulting\.tech' || true)
if [ -n "$RAW_URLS" ]; then
echo "::error::Manifest contains legacy raw/branch update server URL on MokoGitea. Use the Gitea Pages URL instead (e.g. /{REPO}/updates.xml not /{REPO}/raw/branch/main/updates.xml)"
echo "$RAW_URLS"
exit 1
fi
echo "Joomla manifest valid"
;;
dolibarr)
MOD_FILE=$(find . -maxdepth 4 -name "mod*.class.php" ! -path "./.git/*" -exec grep -l 'extends DolibarrModules' {} \; 2>/dev/null | head -1)
if [ -z "$MOD_FILE" ]; then
echo "::error::No mod*.class.php found"
exit 1
fi
echo "Dolibarr module: ${MOD_FILE}"
;;
*)
echo "Generic platform — no manifest validation"
;;
esac
- name: Check update stream format
run: |
PLATFORM="${{ steps.platform.outputs.platform }}"
case "$PLATFORM" in
joomla)
if [ -f "updates.xml" ]; then
if command -v php &> /dev/null; then
php -r "libxml_use_internal_errors(true); \$x = simplexml_load_file('updates.xml'); if(!\$x){foreach(libxml_get_errors() as \$e) echo \$e->message; exit(1);}" || { echo "::error::updates.xml is malformed"; exit 1; }
fi
echo "updates.xml valid"
fi
;;
dolibarr)
[ -f "update.txt" ] && echo "update.txt present" || echo "::warning::No update.txt"
;;
esac
- name: Validate Joomla language files
if: steps.platform.outputs.platform == 'joomla'
run: |
ERRORS=0
WARNINGS=0
# Require both en-GB and en-US language directories
LANG_ROOT=$(find . -path "*/language" -type d -not -path "./.git/*" 2>/dev/null | head -1)
if [ -z "$LANG_ROOT" ]; then
echo "No language/ directory found — skipping"
exit 0
fi
if [ ! -d "$LANG_ROOT/en-GB" ]; then
echo "::error::Missing en-GB language directory (${LANG_ROOT}/en-GB)"
ERRORS=$((ERRORS + 1))
fi
if [ ! -d "$LANG_ROOT/en-US" ]; then
echo "::error::Missing en-US language directory (${LANG_ROOT}/en-US)"
ERRORS=$((ERRORS + 1))
fi
# Check that en-GB and en-US have matching .ini files
if [ -d "$LANG_ROOT/en-GB" ] && [ -d "$LANG_ROOT/en-US" ]; then
for GB_INI in "$LANG_ROOT/en-GB"/*.ini; do
[ ! -f "$GB_INI" ] && continue
US_INI="$LANG_ROOT/en-US/$(basename "$GB_INI")"
if [ ! -f "$US_INI" ]; then
echo "::error::$(basename "$GB_INI") exists in en-GB but missing from en-US"
ERRORS=$((ERRORS + 1))
fi
done
for US_INI in "$LANG_ROOT/en-US"/*.ini; do
[ ! -f "$US_INI" ] && continue
GB_INI="$LANG_ROOT/en-GB/$(basename "$US_INI")"
if [ ! -f "$GB_INI" ]; then
echo "::error::$(basename "$US_INI") exists in en-US but missing from en-GB"
ERRORS=$((ERRORS + 1))
fi
done
fi
# Find all .ini language files
INI_FILES=$(find . -path "*/language/*/*.ini" -not -path "./.git/*" 2>/dev/null)
if [ -z "$INI_FILES" ]; then
echo "No .ini language files found"
[ "$ERRORS" -gt 0 ] && exit 1
exit 0
fi
echo "Found $(echo "$INI_FILES" | wc -l) language file(s)"
for FILE in $INI_FILES; do
FNAME=$(basename "$FILE")
LINENUM=0
SEEN_KEYS=""
while IFS= read -r line || [ -n "$line" ]; do
LINENUM=$((LINENUM + 1))
# Skip empty lines and comments
[ -z "$line" ] && continue
echo "$line" | grep -qE '^\s*;' && continue
echo "$line" | grep -qE '^\s*$' && continue
# Must match KEY="VALUE" format
if ! echo "$line" | grep -qE '^[A-Z_][A-Z0-9_]*=".*"$'; then
echo "::error file=${FILE},line=${LINENUM}::Malformed line: ${line}"
ERRORS=$((ERRORS + 1))
continue
fi
# Extract key and check for duplicates
KEY=$(echo "$line" | sed 's/=.*//')
if echo "$SEEN_KEYS" | grep -qx "$KEY"; then
echo "::error file=${FILE},line=${LINENUM}::Duplicate key: ${KEY}"
ERRORS=$((ERRORS + 1))
fi
SEEN_KEYS="${SEEN_KEYS}
${KEY}"
done < "$FILE"
echo " ${FILE}: checked ${LINENUM} lines"
done
# Cross-check en-GB vs en-US key consistency
GB_DIR=$(find . -path "*/language/en-GB" -type d -not -path "./.git/*" 2>/dev/null | head -1)
US_DIR=$(find . -path "*/language/en-US" -type d -not -path "./.git/*" 2>/dev/null | head -1)
if [ -n "$GB_DIR" ] && [ -n "$US_DIR" ]; then
for GB_FILE in "$GB_DIR"/*.ini; do
[ ! -f "$GB_FILE" ] && continue
FNAME=$(basename "$GB_FILE")
US_FILE="$US_DIR/$FNAME"
[ ! -f "$US_FILE" ] && continue
GB_KEYS=$(grep -oP '^[A-Z_][A-Z0-9_]*(?==)' "$GB_FILE" 2>/dev/null | sort)
US_KEYS=$(grep -oP '^[A-Z_][A-Z0-9_]*(?==)' "$US_FILE" 2>/dev/null | sort)
# Keys in en-GB but not en-US
MISSING_US=$(comm -23 <(echo "$GB_KEYS") <(echo "$US_KEYS"))
if [ -n "$MISSING_US" ]; then
echo "::warning::Keys in en-GB/$FNAME but missing from en-US/$FNAME:"
echo "$MISSING_US" | while read -r k; do echo " - $k"; done
WARNINGS=$((WARNINGS + 1))
fi
# Keys in en-US but not en-GB
MISSING_GB=$(comm -13 <(echo "$GB_KEYS") <(echo "$US_KEYS"))
if [ -n "$MISSING_GB" ]; then
echo "::warning::Keys in en-US/$FNAME but missing from en-GB/$FNAME:"
echo "$MISSING_GB" | while read -r k; do echo " - $k"; done
WARNINGS=$((WARNINGS + 1))
fi
done
fi
{
echo "### Language File Validation"
echo "| Metric | Count |"
echo "|---|---|"
echo "| Files checked | $(echo "$INI_FILES" | wc -l) |"
echo "| Errors | ${ERRORS} |"
echo "| Warnings | ${WARNINGS} |"
} >> $GITHUB_STEP_SUMMARY
if [ "$ERRORS" -gt 0 ]; then
echo "::error::Language validation failed with ${ERRORS} error(s)"
exit 1
fi
echo "Language files: OK (${WARNINGS} warning(s))"
- name: Check changelog has unreleased entry
run: |
if [ ! -f "CHANGELOG.md" ]; then
echo "::warning::No CHANGELOG.md found"
exit 0
fi
# Check for content under [Unreleased] section
if ! grep -q "## \[Unreleased\]" CHANGELOG.md; then
echo "::error::CHANGELOG.md missing [Unreleased] section"
exit 1
fi
# Check there's at least one entry (Added/Changed/Fixed/Removed) under Unreleased
UNRELEASED_CONTENT=$(sed -n '/## \[Unreleased\]/,/## \[/p' CHANGELOG.md | grep -cE '^\s*-\s' || true)
if [ "$UNRELEASED_CONTENT" -eq 0 ]; then
echo "::error::CHANGELOG.md [Unreleased] section has no entries. Add a changelog entry describing your changes."
echo "## Changelog Check: Failed" >> $GITHUB_STEP_SUMMARY
echo "The \`[Unreleased]\` section in CHANGELOG.md has no entries." >> $GITHUB_STEP_SUMMARY
echo "Add a line like \`- Description of your change\` under a heading (\`### Added\`, \`### Changed\`, \`### Fixed\`, etc.)" >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "Changelog: ${UNRELEASED_CONTENT} entry/entries in [Unreleased]"
- name: Verify package source
run: |
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
if [ ! -d "$SOURCE_DIR" ]; then
echo "::warning::No src/ or htdocs/ directory"
exit 0
fi
FILE_COUNT=$(find "$SOURCE_DIR" -type f | wc -l)
echo "Source: ${FILE_COUNT} files"
[ "$FILE_COUNT" -gt 0 ] || { echo "::error::Source directory is empty"; exit 1; }
# ── Pre-Release RC Build ─────────────────────────────────────────────────
pre-release:
name: Build RC Package
runs-on: ubuntu-latest
needs: [branch-policy, validate]
steps:
- name: Trigger RC pre-release
env:
GA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: ${{ github.head_ref }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
curl -s -X POST "${GITEA_URL}/api/v1/repos/${REPO}/actions/workflows/pre-release.yml/dispatches" -H "Authorization: token ${GITEA_TOKEN}" -H "Content-Type: application/json" -d "{\"ref\":\"${BRANCH}\",\"inputs\":{\"stability\":\"release-candidate\"}}"
echo "### Pre-Release" >> $GITHUB_STEP_SUMMARY
echo "Triggered RC build on branch \`${BRANCH}\`" >> $GITHUB_STEP_SUMMARY
# ── Issue Reporter ──────────────────────────────────────────────────────
report-issues:
name: Report Issues
runs-on: ubuntu-latest
needs: [branch-policy, validate]
if: >-
always() &&
needs.validate.result == 'failure'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: automation/ci-issue-reporter.sh
sparse-checkout-cone-mode: false
- name: "File issue for PR validation failure"
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x automation/ci-issue-reporter.sh
./automation/ci-issue-reporter.sh \
--gate "PR Validation" \
--workflow "PR Check" \
--severity error \
--details "PR validation failed (syntax, manifest, changelog, or source checks). See the CI run for the specific check that failed."
+11
View File
@@ -0,0 +1,11 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Release
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /templates/workflows/universal/pre-release.yml.template
# VERSION: 05.01.00
# BRIEF: Auto pre-release on push to dev/alpha/beta/rc branches
+711
View File
@@ -0,0 +1,711 @@
# ============================================================================
# Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
#
# This file is part of a Moko Consulting project.
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Validation
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/moko-platform
# PATH: /templates/workflows/joomla/repo_health.yml.template
# VERSION: 09.23.00
# BRIEF: Enforces repository guardrails by validating scripts governance, tooling availability, and core repository health artifacts.
# ============================================================================
name: "Generic: Repo Health"
defaults:
run:
shell: bash
on:
workflow_dispatch:
inputs:
profile:
description: 'Validation profile: all, scripts, or repo'
required: true
default: all
type: choice
options:
- all
- scripts
- repo
pull_request:
push:
permissions:
contents: read
env:
# Scripts governance policy
SCRIPTS_REQUIRED_DIRS:
SCRIPTS_ALLOWED_DIRS: scripts,scripts/fix,scripts/lib,scripts/release,scripts/run,scripts/validate
# Repo health policy
REPO_REQUIRED_ARTIFACTS: README.md,LICENSE,CHANGELOG.md,CONTRIBUTING.md,CODE_OF_CONDUCT.md,.mokogitea/workflows/
REPO_OPTIONAL_FILES: SECURITY.md,GOVERNANCE.md,.editorconfig,.gitattributes,.gitignore,README.md,docs/
REPO_DISALLOWED_DIRS:
REPO_DISALLOWED_FILES: TODO.md,todo.md
# Extended checks toggles
EXTENDED_CHECKS: "true"
# File / directory variables
DOCS_INDEX: docs/docs-index.md
SCRIPT_DIR: scripts
WORKFLOWS_DIR: .mokogitea/workflows
SHELLCHECK_PATTERN: '*.sh'
SPDX_FILE_GLOBS: '*.sh,*.php,*.js,*.ts,*.css,*.xml,*.yml,*.yaml'
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
access_check:
name: Access control
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
outputs:
allowed: ${{ steps.perm.outputs.allowed }}
permission: ${{ steps.perm.outputs.permission }}
steps:
- name: Check actor permission (admin only)
id: perm
env:
TOKEN: ${{ secrets.MOKOGITEA_TOKEN || secrets.MOKOGITEA_TOKEN || github.token }}
REPO: ${{ github.repository }}
ACTOR: ${{ github.actor }}
run: |
set -euo pipefail
ALLOWED=false
PERMISSION=unknown
METHOD=""
# Hardcoded authorized users — always allowed
case "$ACTOR" in
jmiller|gitea-actions[bot])
ALLOWED=true
PERMISSION=admin
METHOD="hardcoded allowlist"
;;
*)
# Detect platform and check permissions via API
API_BASE="${GITHUB_API_URL:-${GITEA_API_URL:-https://api.github.com}}"
RESP=$(curl -sf -H "Authorization: token ${TOKEN}" \
"${API_BASE}/repos/${REPO}/collaborators/${ACTOR}/permission" 2>/dev/null || echo '{}')
PERMISSION=$(echo "$RESP" | grep -oP '"permission"\s*:\s*"\K[^"]+' || echo "unknown")
if [ "$PERMISSION" = "admin" ] || [ "$PERMISSION" = "maintain" ] || [ "$PERMISSION" = "owner" ]; then
ALLOWED=true
fi
METHOD="collaborator API"
;;
esac
echo "permission=${PERMISSION}" >> "$GITHUB_OUTPUT"
echo "allowed=${ALLOWED}" >> "$GITHUB_OUTPUT"
{
echo "## Access Authorization"
echo ""
echo "| Field | Value |"
echo "|-------|-------|"
echo "| **Actor** | \`${ACTOR}\` |"
echo "| **Repository** | \`${REPO}\` |"
echo "| **Permission** | \`${PERMISSION}\` |"
echo "| **Method** | ${METHOD} |"
echo "| **Authorized** | ${ALLOWED} |"
echo ""
if [ "$ALLOWED" = "true" ]; then
echo "${ACTOR} authorized (${METHOD})"
else
echo "${ACTOR} is NOT authorized. Requires admin or maintain role."
fi
} >> "${GITHUB_STEP_SUMMARY}"
- name: Deny execution when not permitted
if: ${{ steps.perm.outputs.allowed != 'true' }}
run: |
set -euo pipefail
printf '%s\n' 'ERROR: Access denied. Admin permission required.' >> "${GITHUB_STEP_SUMMARY}"
exit 1
scripts_governance:
name: Scripts governance
needs: access_check
if: ${{ needs.access_check.outputs.allowed == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Scripts folder checks
env:
PROFILE_RAW: ${{ github.event.inputs.profile }}
run: |
set -euo pipefail
profile="${PROFILE_RAW:-all}"
case "${profile}" in
all|scripts|repo) ;;
*)
printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
exit 1
;;
esac
if [ "${profile}" = 'repo' ]; then
{
printf '%s\n' '### Scripts governance'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' 'Status: SKIPPED'
printf '%s\n' 'Reason: profile excludes scripts governance'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
if [ ! -d "${SCRIPT_DIR}" ]; then
{
printf '%s\n' '### Scripts governance'
printf '%s\n' 'Status: OK (advisory)'
printf '%s\n' 'scripts/ directory not present. No scripts governance enforced.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
if [ -n "${SCRIPTS_REQUIRED_DIRS:-}" ]; then IFS=',' read -r -a required_dirs <<< "${SCRIPTS_REQUIRED_DIRS}"; else required_dirs=(); fi
IFS=',' read -r -a allowed_dirs <<< "${SCRIPTS_ALLOWED_DIRS}"
missing_dirs=()
unapproved_dirs=()
for d in "${required_dirs[@]}"; do
req="${d%/}"
[ ! -d "${req}" ] && missing_dirs+=("${req}/")
done
while IFS= read -r d; do
allowed=false
for a in "${allowed_dirs[@]}"; do
a_norm="${a%/}"
[ "${d%/}" = "${a_norm}" ] && allowed=true
done
[ "${allowed}" = false ] && unapproved_dirs+=("${d%/}/")
done < <(find "${SCRIPT_DIR}" -maxdepth 1 -mindepth 1 -type d 2>/dev/null | sed 's#^\./##')
{
printf '%s\n' '### Scripts governance'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' '| Area | Status | Notes |'
printf '%s\n' '|---|---|---|'
if [ "${#missing_dirs[@]}" -gt 0 ]; then
printf '%s\n' '| Required directories | Warning | Missing required subfolders |'
else
printf '%s\n' '| Required directories | OK | All required subfolders present |'
fi
if [ "${#unapproved_dirs[@]}" -gt 0 ]; then
printf '%s\n' '| Directory policy | Warning | Unapproved directories detected |'
else
printf '%s\n' '| Directory policy | OK | No unapproved directories |'
fi
printf '%s\n' '| Enforcement mode | Advisory | scripts folder is optional |'
printf '\n'
if [ "${#missing_dirs[@]}" -gt 0 ]; then
printf '%s\n' 'Missing required script directories:'
for m in "${missing_dirs[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
else
printf '%s\n' 'Missing required script directories: none.'
printf '\n'
fi
if [ "${#unapproved_dirs[@]}" -gt 0 ]; then
printf '%s\n' 'Unapproved script directories detected:'
for m in "${unapproved_dirs[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
else
printf '%s\n' 'Unapproved script directories detected: none.'
printf '\n'
fi
printf '%s\n' 'Scripts governance completed in advisory mode.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
repo_health:
name: Repository health
needs: access_check
if: ${{ needs.access_check.outputs.allowed == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Repository health checks
env:
PROFILE_RAW: ${{ github.event.inputs.profile }}
run: |
set -euo pipefail
profile="${PROFILE_RAW:-all}"
case "${profile}" in
all|scripts|repo) ;;
*)
printf '%s\n' "ERROR: Unknown profile: ${profile}" >> "${GITHUB_STEP_SUMMARY}"
exit 1
;;
esac
if [ "${profile}" = 'scripts' ]; then
{
printf '%s\n' '### Repository health'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' 'Status: SKIPPED'
printf '%s\n' 'Reason: profile excludes repository health'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 0
fi
IFS=',' read -r -a required_artifacts <<< "${REPO_REQUIRED_ARTIFACTS}"
IFS=',' read -r -a optional_files <<< "${REPO_OPTIONAL_FILES}"
if [ -n "${REPO_DISALLOWED_DIRS:-}" ]; then IFS=',' read -r -a disallowed_dirs <<< "${REPO_DISALLOWED_DIRS}"; else disallowed_dirs=(); fi
IFS=',' read -r -a disallowed_files <<< "${REPO_DISALLOWED_FILES:-}"
missing_required=()
missing_optional=()
# Source directory: src/ or htdocs/ (either is valid for extension repos)
SOURCE_DIR=""
if [ -d "src" ]; then
SOURCE_DIR="src"
elif [ -d "htdocs" ]; then
SOURCE_DIR="htdocs"
elif [ -d "deploy" ] || [ -d "cli" ] || [ -d "monitoring" ]; then
# Platform/tooling repos don't need src/
SOURCE_DIR=""
else
missing_required+=("src/ or htdocs/ (source directory required)")
fi
for item in "${required_artifacts[@]}"; do
if printf '%s' "${item}" | grep -q '/$'; then
d="${item%/}"
[ ! -d "${d}" ] && missing_required+=("${item}")
else
[ ! -f "${item}" ] && missing_required+=("${item}")
fi
done
for f in "${optional_files[@]}"; do
if printf '%s' "${f}" | grep -q '/$'; then
d="${f%/}"
[ ! -d "${d}" ] && missing_optional+=("${f}")
else
[ ! -f "${f}" ] && missing_optional+=("${f}")
fi
done
for d in "${disallowed_dirs[@]}"; do
d_norm="${d%/}"
[ -d "${d_norm}" ] && missing_required+=("${d_norm}/ (disallowed)")
done
for f in "${disallowed_files[@]}"; do
[ -f "${f}" ] && missing_required+=("${f} (disallowed)")
done
git fetch origin --prune
dev_paths=()
dev_branches=()
while IFS= read -r b; do
name="${b#origin/}"
if [ "${name}" = 'dev' ]; then
dev_branches+=("${name}")
else
dev_paths+=("${name}")
fi
done < <(git branch -r --list 'origin/dev*' | sed 's/^ *//')
if [ "${#dev_paths[@]}" -eq 0 ] && [ "${#dev_branches[@]}" -eq 0 ]; then
missing_required+=("dev or dev/* branch")
fi
content_warnings=()
if [ -f 'CHANGELOG.md' ] && ! grep -Eq '^# Changelog' CHANGELOG.md; then
content_warnings+=("CHANGELOG.md missing '# Changelog' header")
fi
if [ -f 'CHANGELOG.md' ] && grep -Eq '^[# ]*Unreleased' CHANGELOG.md; then
content_warnings+=("CHANGELOG.md contains Unreleased section (review release readiness)")
fi
if [ -f 'LICENSE' ] && ! grep -qiE 'GNU GENERAL PUBLIC LICENSE|GPL' LICENSE; then
content_warnings+=("LICENSE does not look like a GPL text")
fi
if [ -f 'README.md' ] && ! grep -qiE 'moko|Moko' README.md; then
content_warnings+=("README.md missing expected brand keyword")
fi
export PROFILE_RAW="${profile}"
export MISSING_REQUIRED="$(printf '%s\n' "${missing_required[@]:-}")"
export MISSING_OPTIONAL="$(printf '%s\n' "${missing_optional[@]:-}")"
export CONTENT_WARNINGS="$(printf '%s\n' "${content_warnings[@]:-}")"
report_json=$(printf '{"profile":"%s","missing_required":%d,"missing_optional":%d,"content_warnings":%d}' "$profile" "${#missing_required[@]}" "${#missing_optional[@]}" "${#content_warnings[@]}")
{
printf '%s\n' '### Repository health'
printf '%s\n' "Profile: ${profile}"
printf '%s\n' '| Metric | Value |'
printf '%s\n' '|---|---|'
printf '%s\n' "| Missing required | ${#missing_required[@]} |"
printf '%s\n' "| Missing optional | ${#missing_optional[@]} |"
printf '%s\n' "| Content warnings | ${#content_warnings[@]} |"
printf '\n'
printf '%s\n' '### Guardrails report (JSON)'
printf '%s\n' '```json'
printf '%s\n' "${report_json}"
printf '%s\n' '```'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
if [ "${#missing_required[@]}" -gt 0 ]; then
{
printf '%s\n' '### Missing required repo artifacts'
for m in "${missing_required[@]}"; do printf '%s\n' "- ${m}"; done
printf '%s\n' 'ERROR: Guardrails failed. Missing required repository artifacts.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
if [ "${#missing_optional[@]}" -gt 0 ]; then
{
printf '%s\n' '### Missing optional repo artifacts'
for m in "${missing_optional[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
if [ "${#content_warnings[@]}" -gt 0 ]; then
{
printf '%s\n' '### Repo content warnings'
for m in "${content_warnings[@]}"; do printf '%s\n' "- ${m}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
# -- Joomla-specific checks --
joomla_findings=()
MANIFEST="$(find . -maxdepth 2 -name '*.xml' -exec grep -l '<extension' {} \; 2>/dev/null | head -1 || true)"
if [ -z "${MANIFEST}" ]; then
joomla_findings+=("Joomla XML manifest not found (no *.xml with <extension> tag)")
else
if ! grep -qP '<version>' "${MANIFEST}"; then
joomla_findings+=("XML manifest: <version> tag missing")
fi
if ! grep -qP 'type="(component|module|plugin|library|package|template|language)"' "${MANIFEST}"; then
joomla_findings+=("XML manifest: type attribute missing or invalid")
fi
if ! grep -qP '<name>' "${MANIFEST}"; then
joomla_findings+=("XML manifest: <name> tag missing")
fi
if ! grep -qP '<author>' "${MANIFEST}"; then
joomla_findings+=("XML manifest: <author> tag missing")
fi
if ! grep -qP '<namespace' "${MANIFEST}"; then
joomla_findings+=("XML manifest: <namespace> missing (required for Joomla 5+)")
fi
fi
INI_COUNT="$(find . -name '*.ini' -type f 2>/dev/null | wc -l)"
if [ "${INI_COUNT}" -eq 0 ]; then
joomla_findings+=("No .ini language files found")
fi
if [ ! -f 'updates.xml' ]; then
joomla_findings+=("updates.xml missing in root (required for Joomla update server)")
fi
if [ -n "${SOURCE_DIR}" ]; then
INDEX_DIRS=("${SOURCE_DIR}" "${SOURCE_DIR}/admin" "${SOURCE_DIR}/site")
for dir in "${INDEX_DIRS[@]}"; do
if [ -d "${dir}" ] && [ ! -f "${dir}/index.html" ]; then
joomla_findings+=("${dir}/index.html missing (directory listing protection)")
fi
done
fi
if [ "${#joomla_findings[@]}" -gt 0 ]; then
{
printf '%s\n' '### Joomla extension checks'
printf '%s\n' '| Check | Status |'
printf '%s\n' '|---|---|'
for f in "${joomla_findings[@]}"; do
printf '%s\n' "| ${f} | Warning |"
done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
else
{
printf '%s\n' '### Joomla extension checks'
printf '%s\n' 'All Joomla-specific checks passed.'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
extended_enabled="${EXTENDED_CHECKS:-true}"
extended_findings=()
if [ "${extended_enabled}" = 'true' ]; then
if [ -f '.github/CODEOWNERS' ] || [ -f 'CODEOWNERS' ] || [ -f 'docs/CODEOWNERS' ]; then
:
else
extended_findings+=("CODEOWNERS not found (.github/CODEOWNERS preferred)")
fi
if ls "${WORKFLOWS_DIR}"/*.yml >/dev/null 2>&1 || ls "${WORKFLOWS_DIR}"/*.yaml >/dev/null 2>&1; then
bad_refs="$(grep -RIn --include='*.yml' --include='*.yaml' -E '^[[:space:]]*uses:[[:space:]]*[^#]+@(main|master)\b' "${WORKFLOWS_DIR}" 2>/dev/null || true)"
if [ -n "${bad_refs}" ]; then
extended_findings+=("Workflows reference actions @main/@master (pin versions): see log excerpt")
{
printf '%s\n' '### Workflow pinning advisory'
printf '%s\n' 'Found uses: entries pinned to main/master:'
printf '%s\n' '```'
printf '%s\n' "${bad_refs}"
printf '%s\n' '```'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
fi
if [ -f "${DOCS_INDEX}" ]; then
missing_links=""
while IFS= read -r docline; do
for link in $(echo "$docline" | grep -oE '\]\([^)]+\)' | sed 's/\](//' | sed 's/)$//' || true); do
case "$link" in http://*|https://*|"#"*|mailto:*) continue ;; esac
linkpath="${link%%#*}"
linkpath="${linkpath%%\?*}"
[ -z "$linkpath" ] && continue
if [ "${linkpath:0:1}" = "/" ]; then
testpath="${linkpath#/}"
else
testpath="$(dirname "${DOCS_INDEX}")/${linkpath}"
fi
[ ! -e "$testpath" ] && missing_links="${missing_links}${testpath} "
done
done < "${DOCS_INDEX}"
if [ -n "${missing_links}" ]; then
extended_findings+=("docs/docs-index.md contains broken relative links")
{
printf '%s\n' '### Docs index link integrity'
printf '%s\n' 'Broken relative links:'
for bl in ${missing_links}; do
printf '%s\n' "- ${bl}"
done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
fi
if [ -d "${SCRIPT_DIR}" ]; then
if ! command -v shellcheck >/dev/null 2>&1; then
sudo apt-get update -qq
sudo apt-get install -y shellcheck >/dev/null
fi
sc_out=''
while IFS= read -r shf; do
[ -z "${shf}" ] && continue
out_one="$(shellcheck -S warning -x "${shf}" 2>/dev/null || true)"
if [ -n "${out_one}" ]; then
sc_out="${sc_out}${out_one}\n"
fi
done < <(find "${SCRIPT_DIR}" -type f -name "${SHELLCHECK_PATTERN}" 2>/dev/null | sort)
if [ -n "${sc_out}" ]; then
extended_findings+=("ShellCheck warnings detected (advisory)")
sc_head="$(printf '%s' "${sc_out}" | head -n 200)"
{
printf '%s\n' '### ShellCheck (advisory)'
printf '%s\n' '```'
printf '%s\n' "${sc_head}"
printf '%s\n' '```'
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
fi
spdx_missing=()
IFS=',' read -r -a spdx_globs <<< "${SPDX_FILE_GLOBS}"
spdx_args=()
for g in "${spdx_globs[@]}"; do spdx_args+=("${g}"); done
while IFS= read -r f; do
[ -z "${f}" ] && continue
if ! head -n 40 "${f}" | grep -q 'SPDX-License-Identifier:'; then
spdx_missing+=("${f}")
fi
done < <(git ls-files "${spdx_args[@]}" 2>/dev/null || true)
if [ "${#spdx_missing[@]}" -gt 0 ]; then
extended_findings+=("SPDX header missing in some tracked files (advisory)")
{
printf '%s\n' '### SPDX header advisory'
printf '%s\n' 'Files missing SPDX-License-Identifier (first 40 lines scan):'
for f in "${spdx_missing[@]}"; do printf '%s\n' "- ${f}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
stale_cutoff_days=180
stale_branches="$(git for-each-ref --format='%(refname:short) %(committerdate:unix)' refs/remotes/origin 2>/dev/null | awk -v now="$(date +%s)" -v days="${stale_cutoff_days}" '{if (now-$2 > days*86400) print $1}' | head -50)"
if [ -n "${stale_branches}" ]; then
extended_findings+=("Stale remote branches detected (advisory)")
{
printf '%s\n' '### Git hygiene advisory'
printf '%s\n' "Branches with last commit older than ${stale_cutoff_days} days (sample up to 50):"
while IFS= read -r b; do [ -n "${b}" ] && printf '%s\n' "- ${b}"; done <<< "${stale_branches}"
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
fi
{
printf '%s\n' '### Guardrails coverage matrix'
printf '%s\n' '| Domain | Status | Notes |'
printf '%s\n' '|---|---|---|'
printf '%s\n' '| Access control | OK | Admin-only execution gate |'
printf '%s\n' '| Release policy | N/A | Releases handled by MokoGitea |'
printf '%s\n' '| Scripts governance | OK | Directory policy and advisory reporting |'
printf '%s\n' '| Repo required artifacts | OK | Required, optional, disallowed enforcement |'
printf '%s\n' '| Repo content heuristics | OK | Brand, license, changelog structure |'
if [ "${extended_enabled}" = 'true' ]; then
if [ "${#extended_findings[@]}" -gt 0 ]; then
printf '%s\n' '| Extended checks | Warning | See extended findings below |'
else
printf '%s\n' '| Extended checks | OK | No findings |'
fi
else
printf '%s\n' '| Extended checks | SKIPPED | EXTENDED_CHECKS disabled |'
fi
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
if [ "${extended_enabled}" = 'true' ] && [ "${#extended_findings[@]}" -gt 0 ]; then
{
printf '%s\n' '### Extended findings (advisory)'
for f in "${extended_findings[@]}"; do printf '%s\n' "- ${f}"; done
printf '\n'
} >> "${GITHUB_STEP_SUMMARY}"
fi
printf '%s\n' 'Repository health guardrails passed.' >> "${GITHUB_STEP_SUMMARY}"
site-health:
name: Site Health
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
- name: Uptime check
if: env.URLS != ''
run: |
echo "$URLS" > /tmp/urls.txt
php monitoring/uptime-probe.php --urls /tmp/urls.txt --timeout 15 || echo "::warning::Some sites are down"
rm -f /tmp/urls.txt
env:
URLS: ${{ vars.MONITORED_URLS }}
- name: SSL certificate check
if: env.DOMAINS != ''
run: |
echo "$DOMAINS" > /tmp/domains.txt
php monitoring/ssl-check.php --domains /tmp/domains.txt --warn-days 30 || echo "::warning::SSL certificates expiring soon"
rm -f /tmp/domains.txt
env:
DOMAINS: ${{ vars.MONITORED_DOMAINS }}
- name: Summary
if: always()
run: |
echo "### Site Health" >> $GITHUB_STEP_SUMMARY
echo "Uptime and SSL checks completed." >> $GITHUB_STEP_SUMMARY
# ═══════════════════════════════════════════════════════════════════════
# Issue Reporter — file issues for failed gates
# ═══════════════════════════════════════════════════════════════════════
report-issues:
name: "Report Issues"
runs-on: ubuntu-latest
needs: [access_check, scripts_governance, repo_health]
if: >-
always() &&
(needs.scripts_governance.result == 'failure' ||
needs.repo_health.result == 'failure')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
sparse-checkout: automation/ci-issue-reporter.sh
sparse-checkout-cone-mode: false
- name: "File issues for failed gates"
env:
GITEA_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
run: |
chmod +x automation/ci-issue-reporter.sh
REPORTER="./automation/ci-issue-reporter.sh"
WF="Repo Health"
report_gate() {
local gate="$1" result="$2" details="$3"
if [ "$result" = "failure" ]; then
"$REPORTER" --gate "$gate" --details "$details" --workflow "$WF" --severity error
fi
}
report_gate "Scripts Governance" \
"${{ needs.scripts_governance.result }}" \
"Scripts directory policy violations detected. Review required and allowed directories."
report_gate "Repository Health" \
"${{ needs.repo_health.result }}" \
"Repository health checks failed — missing required artifacts, disallowed files, or content warnings. Check the CI run summary."
+525
View File
@@ -0,0 +1,525 @@
# 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: GitHub.Workflow
# INGROUP: MokoStandards.Maintenance
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/repository-cleanup.yml.template
# VERSION: 04.06.00
# BRIEF: Recurring repository maintenance — labels, branches, workflows, logs, doc indexes
# NOTE: Synced via bulk-repo-sync to .mokogitea/workflows/repository-cleanup.yml in all governed repos.
# Runs on the 1st and 15th of each month at 6:00 AM UTC, and on manual dispatch.
name: "Universal: Repository Cleanup"
on:
schedule:
- cron: '0 6 1,15 * *'
workflow_dispatch:
inputs:
reset_labels:
description: 'Delete ALL existing labels and recreate the standard set'
type: boolean
default: false
clean_branches:
description: 'Delete old chore/sync-mokostandards-* branches'
type: boolean
default: true
clean_workflows:
description: 'Delete orphaned workflow runs (cancelled, stale)'
type: boolean
default: true
clean_logs:
description: 'Delete workflow run logs older than 30 days'
type: boolean
default: true
fix_templates:
description: 'Strip copyright comment blocks from issue templates'
type: boolean
default: true
rebuild_indexes:
description: 'Rebuild docs/ index files'
type: boolean
default: true
delete_closed_issues:
description: 'Delete issues that have been closed for more than 30 days'
type: boolean
default: false
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
permissions:
contents: write
issues: write
actions: write
jobs:
cleanup:
name: Repository Maintenance
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.GH_TOKEN || github.token }}
fetch-depth: 0
- name: Check actor permission
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
ACTOR="${{ github.actor }}"
# Schedule triggers use github-actions[bot]
if [ "${{ github.event_name }}" = "schedule" ]; then
echo "✅ Scheduled run — authorized"
exit 0
fi
AUTHORIZED_USERS="jmiller github-actions[bot]"
for user in $AUTHORIZED_USERS; do
if [ "$ACTOR" = "$user" ]; then
echo "✅ ${ACTOR} authorized"
exit 0
fi
done
PERMISSION=$(gh api "repos/${{ github.repository }}/collaborators/${ACTOR}/permission" \
--jq '.permission' 2>/dev/null)
case "$PERMISSION" in
admin|maintain) echo "✅ ${ACTOR} has ${PERMISSION}" ;;
*) echo "❌ Admin or maintain required"; exit 1 ;;
esac
# ── Determine which tasks to run ─────────────────────────────────────
# On schedule: run all tasks with safe defaults (labels NOT reset)
# On dispatch: use input toggles
- name: Set task flags
id: tasks
run: |
if [ "${{ github.event_name }}" = "schedule" ]; then
echo "reset_labels=false" >> $GITHUB_OUTPUT
echo "clean_branches=true" >> $GITHUB_OUTPUT
echo "clean_workflows=true" >> $GITHUB_OUTPUT
echo "clean_logs=true" >> $GITHUB_OUTPUT
echo "fix_templates=true" >> $GITHUB_OUTPUT
echo "rebuild_indexes=true" >> $GITHUB_OUTPUT
echo "delete_closed_issues=false" >> $GITHUB_OUTPUT
else
echo "reset_labels=${{ inputs.reset_labels }}" >> $GITHUB_OUTPUT
echo "clean_branches=${{ inputs.clean_branches }}" >> $GITHUB_OUTPUT
echo "clean_workflows=${{ inputs.clean_workflows }}" >> $GITHUB_OUTPUT
echo "clean_logs=${{ inputs.clean_logs }}" >> $GITHUB_OUTPUT
echo "fix_templates=${{ inputs.fix_templates }}" >> $GITHUB_OUTPUT
echo "rebuild_indexes=${{ inputs.rebuild_indexes }}" >> $GITHUB_OUTPUT
echo "delete_closed_issues=${{ inputs.delete_closed_issues }}" >> $GITHUB_OUTPUT
fi
# ── DELETE RETIRED WORKFLOWS (always runs) ────────────────────────────
- name: Delete retired workflow files
run: |
echo "## 🗑️ Retired Workflow Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
RETIRED=(
".github/workflows/build.yml"
".github/workflows/code-quality.yml"
".github/workflows/release-cycle.yml"
".github/workflows/release-pipeline.yml"
".github/workflows/branch-cleanup.yml"
".github/workflows/auto-update-changelog.yml"
".github/workflows/enterprise-issue-manager.yml"
".github/workflows/flush-actions-cache.yml"
".github/workflows/mokostandards-script-runner.yml"
".github/workflows/unified-ci.yml"
".github/workflows/unified-platform-testing.yml"
".github/workflows/reusable-build.yml"
".github/workflows/reusable-ci-validation.yml"
".github/workflows/reusable-deploy.yml"
".github/workflows/reusable-php-quality.yml"
".github/workflows/reusable-platform-testing.yml"
".github/workflows/reusable-project-detector.yml"
".github/workflows/reusable-release.yml"
".github/workflows/reusable-script-executor.yml"
".github/workflows/rebuild-docs-indexes.yml"
".github/workflows/setup-project-v2.yml"
".github/workflows/sync-docs-to-project.yml"
".github/workflows/release.yml"
".github/workflows/sync-changelogs.yml"
".github/workflows/version_branch.yml"
"update.json"
".github/workflows/auto-version-branch.yml"
".github/workflows/publish-to-mokodolibarr.yml"
".github/workflows/ci.yml"
".github/workflows/deploy-rs.yml"
"sftp-config.json"
"sftp-config.json.template"
"scripts/sftp-config"
)
DELETED=0
for wf in "${RETIRED[@]}"; do
if [ -f "$wf" ]; then
git rm "$wf" 2>/dev/null || rm -f "$wf"
echo " Deleted: \`$(basename $wf)\`" >> $GITHUB_STEP_SUMMARY
DELETED=$((DELETED+1))
fi
done
if [ "$DELETED" -gt 0 ]; then
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add -A
git commit -m "chore: delete ${DELETED} retired workflow file(s) [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
echo "✅ ${DELETED} retired workflow(s) deleted" >> $GITHUB_STEP_SUMMARY
else
echo "✅ No retired workflows found" >> $GITHUB_STEP_SUMMARY
fi
# ── LABEL RESET ──────────────────────────────────────────────────────
- name: Reset labels to standard set
if: steps.tasks.outputs.reset_labels == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
echo "## 🏷️ Label Reset" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
gh api "repos/${REPO}/labels?per_page=100" --paginate --jq '.[].name' | while read -r label; do
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$label', safe=''))")
gh api -X DELETE "repos/${REPO}/labels/${ENCODED}" --silent 2>/dev/null || true
done
while IFS='|' read -r name color description; do
[ -z "$name" ] && continue
gh api "repos/${REPO}/labels" \
-f name="$name" -f color="$color" -f description="$description" \
--silent 2>/dev/null || true
done << 'LABELS'
joomla|7F52FF|Joomla extension or component
dolibarr|FF6B6B|Dolibarr module or extension
generic|808080|Generic project or library
php|4F5D95|PHP code changes
javascript|F7DF1E|JavaScript code changes
typescript|3178C6|TypeScript code changes
python|3776AB|Python code changes
css|1572B6|CSS/styling changes
html|E34F26|HTML template changes
documentation|0075CA|Documentation changes
ci-cd|000000|CI/CD pipeline changes
docker|2496ED|Docker configuration changes
tests|00FF00|Test suite changes
security|FF0000|Security-related changes
dependencies|0366D6|Dependency updates
config|F9D0C4|Configuration file changes
build|FFA500|Build system changes
automation|8B4513|Automated processes or scripts
mokostandards|B60205|MokoStandards compliance
needs-review|FBCA04|Awaiting code review
work-in-progress|D93F0B|Work in progress, not ready for merge
breaking-change|D73A4A|Breaking API or functionality change
priority: critical|B60205|Critical priority, must be addressed immediately
priority: high|D93F0B|High priority
priority: medium|FBCA04|Medium priority
priority: low|0E8A16|Low priority
type: bug|D73A4A|Something isn't working
type: feature|A2EEEF|New feature or request
type: enhancement|84B6EB|Enhancement to existing feature
type: refactor|F9D0C4|Code refactoring
type: chore|FEF2C0|Maintenance tasks
type: version|0E8A16|Version-related change
status: pending|FBCA04|Pending action or decision
status: in-progress|0E8A16|Currently being worked on
status: blocked|B60205|Blocked by another issue or dependency
status: on-hold|D4C5F9|Temporarily on hold
status: wontfix|FFFFFF|This will not be worked on
size/xs|C5DEF5|Extra small change (1-10 lines)
size/s|6FD1E2|Small change (11-30 lines)
size/m|F9DD72|Medium change (31-100 lines)
size/l|FFA07A|Large change (101-300 lines)
size/xl|FF6B6B|Extra large change (301-1000 lines)
size/xxl|B60205|Extremely large change (1000+ lines)
health: excellent|0E8A16|Health score 90-100
health: good|FBCA04|Health score 70-89
health: fair|FFA500|Health score 50-69
health: poor|FF6B6B|Health score below 50
standards-update|B60205|MokoStandards sync update
standards-drift|FBCA04|Repository drifted from MokoStandards
sync-report|0075CA|Bulk sync run report
sync-failure|D73A4A|Bulk sync failure requiring attention
push-failure|D73A4A|File push failure requiring attention
health-check|0E8A16|Repository health check results
version-drift|FFA500|Version mismatch detected
deploy-failure|CC0000|Automated deploy failure tracking
template-validation-failure|D73A4A|Template workflow validation failure
version|0E8A16|Version bump or release
LABELS
echo "✅ Standard labels created" >> $GITHUB_STEP_SUMMARY
# ── BRANCH CLEANUP ───────────────────────────────────────────────────
- name: Delete old sync branches
if: steps.tasks.outputs.clean_branches == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
CURRENT="chore/sync-mokostandards-v04.05"
echo "## 🌿 Branch Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
FOUND=false
gh api "repos/${REPO}/branches?per_page=100" --jq '.[].name' | \
grep "^chore/sync-mokostandards" | \
grep -v "^${CURRENT}$" | while read -r branch; do
gh pr list --repo "$REPO" --head "$branch" --state open --json number --jq '.[].number' 2>/dev/null | while read -r pr; do
gh pr close "$pr" --repo "$REPO" --comment "Superseded by \`${CURRENT}\`" 2>/dev/null || true
echo " Closed PR #${pr}" >> $GITHUB_STEP_SUMMARY
done
gh api -X DELETE "repos/${REPO}/git/refs/heads/${branch}" --silent 2>/dev/null || true
echo " Deleted: \`${branch}\`" >> $GITHUB_STEP_SUMMARY
FOUND=true
done
if [ "$FOUND" != "true" ]; then
echo "✅ No old sync branches found" >> $GITHUB_STEP_SUMMARY
fi
# ── WORKFLOW RUN CLEANUP ─────────────────────────────────────────────
- name: Clean up workflow runs
if: steps.tasks.outputs.clean_workflows == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
echo "## 🔄 Workflow Run Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
DELETED=0
# Delete cancelled and stale workflow runs
for status in cancelled stale; do
gh api "repos/${REPO}/actions/runs?status=${status}&per_page=100" \
--jq '.workflow_runs[].id' 2>/dev/null | while read -r run_id; do
gh api -X DELETE "repos/${REPO}/actions/runs/${run_id}" --silent 2>/dev/null || true
DELETED=$((DELETED+1))
done
done
echo "✅ Cleaned cancelled/stale workflow runs" >> $GITHUB_STEP_SUMMARY
# ── LOG CLEANUP ──────────────────────────────────────────────────────
- name: Delete old workflow run logs
if: steps.tasks.outputs.clean_logs == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
CUTOFF=$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)
echo "## 📋 Log Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Deleting logs older than: ${CUTOFF}" >> $GITHUB_STEP_SUMMARY
DELETED=0
gh api "repos/${REPO}/actions/runs?created=<${CUTOFF}&per_page=100" \
--jq '.workflow_runs[].id' 2>/dev/null | while read -r run_id; do
gh api -X DELETE "repos/${REPO}/actions/runs/${run_id}/logs" --silent 2>/dev/null || true
DELETED=$((DELETED+1))
done
echo "✅ Cleaned old workflow run logs" >> $GITHUB_STEP_SUMMARY
# ── ISSUE TEMPLATE FIX ──────────────────────────────────────────────
- name: Strip copyright headers from issue templates
if: steps.tasks.outputs.fix_templates == 'true'
run: |
echo "## 📋 Issue Template Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
FIXED=0
for f in .github/ISSUE_TEMPLATE/*.md; do
[ -f "$f" ] || continue
if grep -q '^<!--$' "$f"; then
sed -i '/^<!--$/,/^-->$/d' "$f"
echo " Cleaned: \`$(basename $f)\`" >> $GITHUB_STEP_SUMMARY
FIXED=$((FIXED+1))
fi
done
if [ "$FIXED" -gt 0 ]; then
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add .github/ISSUE_TEMPLATE/
git commit -m "fix: strip copyright comment blocks from issue templates [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
echo "✅ ${FIXED} template(s) cleaned and committed" >> $GITHUB_STEP_SUMMARY
else
echo "✅ No templates need cleaning" >> $GITHUB_STEP_SUMMARY
fi
# ── REBUILD DOC INDEXES ─────────────────────────────────────────────
- name: Rebuild docs/ index files
if: steps.tasks.outputs.rebuild_indexes == 'true'
run: |
echo "## 📚 Documentation Index Rebuild" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ ! -d "docs" ]; then
echo "⏭️ No docs/ directory — skipping" >> $GITHUB_STEP_SUMMARY
exit 0
fi
UPDATED=0
# Generate index.md for each docs/ subdirectory
find docs -type d | while read -r dir; do
INDEX="${dir}/index.md"
FILES=$(find "$dir" -maxdepth 1 -name "*.md" ! -name "index.md" -printf "- [%f](./%f)\n" 2>/dev/null | sort)
if [ -z "$FILES" ]; then
continue
fi
cat > "$INDEX" << INDEXEOF
# $(basename "$dir")
## Documents
${FILES}
---
*Auto-generated by repository-cleanup workflow*
INDEXEOF
# Dedent
sed -i 's/^ //' "$INDEX"
UPDATED=$((UPDATED+1))
done
if [ "$UPDATED" -gt 0 ]; then
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add docs/
if ! git diff --cached --quiet; then
git commit -m "docs: rebuild documentation indexes [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
echo "✅ ${UPDATED} index file(s) rebuilt and committed" >> $GITHUB_STEP_SUMMARY
else
echo "✅ All indexes already up to date" >> $GITHUB_STEP_SUMMARY
fi
else
echo "✅ No indexes to rebuild" >> $GITHUB_STEP_SUMMARY
fi
# ── VERSION DRIFT DETECTION ──────────────────────────────────────────
- name: Check for version drift
run: |
echo "## 📦 Version Drift Check" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ ! -f "README.md" ]; then
echo "⏭️ No README.md — skipping" >> $GITHUB_STEP_SUMMARY
exit 0
fi
README_VERSION=$(grep -oP '^\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' README.md 2>/dev/null | head -1)
if [ -z "$README_VERSION" ]; then
echo "⚠️ No VERSION found in README.md FILE INFORMATION block" >> $GITHUB_STEP_SUMMARY
exit 0
fi
echo "**README version:** \`${README_VERSION}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
DRIFT=0
CHECKED=0
# Check all files with FILE INFORMATION blocks
while IFS= read -r -d '' file; do
FILE_VERSION=$(grep -oP '^\s*\*?\s*VERSION:\s*\K[0-9]{2}\.[0-9]{2}\.[0-9]{2}' "$file" 2>/dev/null | head -1)
[ -z "$FILE_VERSION" ] && continue
CHECKED=$((CHECKED+1))
if [ "$FILE_VERSION" != "$README_VERSION" ]; then
echo " ⚠️ \`${file}\`: \`${FILE_VERSION}\` (expected \`${README_VERSION}\`)" >> $GITHUB_STEP_SUMMARY
DRIFT=$((DRIFT+1))
fi
done < <(find . -maxdepth 4 -type f \( -name "*.php" -o -name "*.md" -o -name "*.yml" \) ! -path "./.git/*" ! -path "./vendor/*" ! -path "./node_modules/*" -print0 2>/dev/null)
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$DRIFT" -gt 0 ]; then
echo "⚠️ **${DRIFT}** file(s) out of ${CHECKED} have version drift" >> $GITHUB_STEP_SUMMARY
echo "Run \`sync-version-on-merge\` workflow or update manually" >> $GITHUB_STEP_SUMMARY
else
echo "✅ All ${CHECKED} file(s) match README version \`${README_VERSION}\`" >> $GITHUB_STEP_SUMMARY
fi
# ── PROTECT CUSTOM WORKFLOWS ────────────────────────────────────────
- name: Ensure custom workflow directory exists
run: |
echo "## 🔧 Custom Workflows" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ ! -d ".github/workflows/custom" ]; then
mkdir -p .github/workflows/custom
cat > .github/workflows/custom/README.md << 'CWEOF'
# Custom Workflows
Place repo-specific workflows here. Files in this directory are:
- **Never overwritten** by MokoStandards bulk sync
- **Never deleted** by the repository-cleanup workflow
- Safe for custom CI, notifications, or repo-specific automation
Synced workflows live in `.github/workflows/` (parent directory).
CWEOF
sed -i 's/^ //' .github/workflows/custom/README.md
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add .github/workflows/custom/
if ! git diff --cached --quiet; then
git commit -m "chore: create .github/workflows/custom/ for repo-specific workflows [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
echo "✅ Created \`.github/workflows/custom/\` directory" >> $GITHUB_STEP_SUMMARY
fi
else
CUSTOM_COUNT=$(find .github/workflows/custom -name "*.yml" -o -name "*.yaml" 2>/dev/null | wc -l)
echo "✅ Custom workflow directory exists (${CUSTOM_COUNT} workflow(s))" >> $GITHUB_STEP_SUMMARY
fi
# ── DELETE CLOSED ISSUES ──────────────────────────────────────────────
- name: Delete old closed issues
if: steps.tasks.outputs.delete_closed_issues == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
run: |
REPO="${{ github.repository }}"
CUTOFF=$(date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-30d +%Y-%m-%dT%H:%M:%SZ)
echo "## 🗑️ Closed Issue Cleanup" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Deleting issues closed before: ${CUTOFF}" >> $GITHUB_STEP_SUMMARY
DELETED=0
gh api "repos/${REPO}/issues?state=closed&since=1970-01-01T00:00:00Z&per_page=100&sort=updated&direction=asc" \
--jq ".[] | select(.closed_at < \"${CUTOFF}\") | .number" 2>/dev/null | while read -r num; do
# Lock and close with "not_planned" to mark as cleaned up
gh api "repos/${REPO}/issues/${num}/lock" -X PUT -f lock_reason="resolved" --silent 2>/dev/null || true
echo " Locked issue #${num}" >> $GITHUB_STEP_SUMMARY
DELETED=$((DELETED+1))
done
if [ "$DELETED" -eq 0 ] 2>/dev/null; then
echo "✅ No old closed issues found" >> $GITHUB_STEP_SUMMARY
else
echo "✅ Locked ${DELETED} old closed issue(s)" >> $GITHUB_STEP_SUMMARY
fi
- name: Summary
if: always()
run: |
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "*Run by @${{ github.actor }} — trigger: ${{ github.event_name }}*" >> $GITHUB_STEP_SUMMARY
+82
View File
@@ -0,0 +1,82 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: MokoStandards.Security
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards
# PATH: /.gitea/workflows/security-audit.yml
# VERSION: 01.00.00
# BRIEF: Dependency vulnerability scanning for composer and npm packages
name: "Universal: Security Audit"
on:
schedule:
- cron: '0 6 * * 1' # Weekly on Monday at 06:00 UTC
pull_request:
branches:
- main
paths:
- 'composer.json'
- 'composer.lock'
- 'package.json'
- 'package-lock.json'
workflow_dispatch:
permissions:
contents: read
env:
NTFY_URL: ${{ vars.NTFY_URL || 'https://ntfy.mokoconsulting.tech' }}
NTFY_TOPIC: ${{ vars.NTFY_TOPIC || 'gitea-security' }}
jobs:
audit:
name: Dependency Audit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Composer audit
if: hashFiles('composer.lock') != ''
run: |
echo "=== Composer Security Audit ==="
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq
sudo apt-get install -y -qq php-cli composer >/dev/null 2>&1
fi
composer audit --format=plain 2>&1 | tee /tmp/composer-audit.txt
RESULT=$?
if [ $RESULT -ne 0 ]; then
echo "::warning::Composer vulnerabilities found"
echo "composer_vulnerable=true" >> "$GITHUB_ENV"
else
echo "No known vulnerabilities in composer dependencies"
fi
- name: NPM audit
if: hashFiles('package-lock.json') != ''
run: |
echo "=== NPM Security Audit ==="
npm audit --production 2>&1 | tee /tmp/npm-audit.txt || true
if npm audit --production 2>&1 | grep -q "found 0 vulnerabilities"; then
echo "No known vulnerabilities in npm dependencies"
else
echo "::warning::NPM vulnerabilities found"
echo "npm_vulnerable=true" >> "$GITHUB_ENV"
fi
- name: Notify on vulnerabilities
if: env.composer_vulnerable == 'true' || env.npm_vulnerable == 'true'
run: |
REPO="${{ github.event.repository.name }}"
curl -sS \
-H "Title: ${REPO} has vulnerable dependencies" \
-H "Tags: lock,warning" \
-H "Priority: high" \
-d "Security audit found vulnerabilities. Review dependency updates." \
"${NTFY_URL}/${NTFY_TOPIC}" || true
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,133 @@
# 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: GitHub.Workflow
# INGROUP: MokoStandards.Automation
# REPO: https://github.com/mokoconsulting-tech/MokoStandards
# PATH: /templates/workflows/shared/sync-version-on-merge.yml.template
# VERSION: 04.06.00
# BRIEF: Auto-bump patch version on every push to main and propagate to all file headers
# NOTE: Synced via bulk-repo-sync to .mokogitea/workflows/sync-version-on-merge.yml in all governed repos.
# README.md is the single source of truth for the repository version.
name: "Universal: Sync Version on Merge"
on:
push:
branches:
- main
- master
workflow_dispatch:
inputs:
dry_run:
description: 'Dry run (preview only, no commit)'
type: boolean
default: false
permissions:
contents: write
issues: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
sync-version:
name: Propagate README version
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
token: ${{ secrets.GH_TOKEN || github.token }}
fetch-depth: 0
- name: Set up PHP
uses: shivammathur/setup-php@fcafdd6392932010c2bd5094439b8e33be2a8a09 # v2.37.0
with:
php-version: '8.1'
tools: composer
- name: Setup MokoStandards tools
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN || github.token }}"}}'
run: |
git clone --depth 1 --branch version/04 --quiet \
"https://x-access-token:${GH_TOKEN}@github.com/mokoconsulting-tech/MokoStandards.git" \
/tmp/mokostandards
cd /tmp/mokostandards
composer install --no-dev --no-interaction --quiet
- name: Auto-bump patch version
if: ${{ github.event_name == 'push' && github.actor != 'github-actions[bot]' }}
run: |
if git diff --name-only HEAD~1 HEAD 2>/dev/null | grep -q '^README\.md$'; then
echo "README.md changed in this push — skipping auto-bump"
exit 0
fi
RESULT=$(php /tmp/mokostandards/api/cli/version_bump.php --path .) || {
echo "⚠️ Could not bump version — skipping"
exit 0
}
echo "Auto-bumping patch: $RESULT"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add README.md
git commit -m "chore(version): auto-bump patch ${RESULT} [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
- name: Extract version from README.md
id: readme_version
run: |
git pull --ff-only 2>/dev/null || true
VERSION=$(php /tmp/mokostandards/api/cli/version_read.php --path . 2>/dev/null)
if [ -z "$VERSION" ]; then
echo "⚠️ No VERSION in README.md — skipping propagation"
echo "skip=true" >> $GITHUB_OUTPUT
exit 0
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "skip=false" >> $GITHUB_OUTPUT
echo "✅ README.md version: $VERSION"
- name: Run version sync
if: ${{ steps.readme_version.outputs.skip != 'true' && inputs.dry_run != true }}
run: |
php /tmp/mokostandards/api/maintenance/update_version_from_readme.php \
--path . \
--create-issue \
--repo "${{ github.repository }}"
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
- name: Commit updated files
if: ${{ steps.readme_version.outputs.skip != 'true' && inputs.dry_run != true }}
run: |
git pull --ff-only 2>/dev/null || true
if git diff --quiet; then
echo "️ No version changes needed — already up to date"
exit 0
fi
VERSION="${{ steps.readme_version.outputs.version }}"
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add -A
git commit -m "chore(version): sync badges and headers to ${VERSION} [skip ci]" \
--author="github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
git push
- name: Summary
run: |
VERSION="${{ steps.readme_version.outputs.version }}"
echo "## 📦 Version Sync — ${VERSION}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Source:** \`README.md\` FILE INFORMATION block" >> $GITHUB_STEP_SUMMARY
echo "**Version:** \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
+312
View File
@@ -0,0 +1,312 @@
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: moko-platform.Universal
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /templates/workflows/update-server.yml
# VERSION: 05.00.00
# BRIEF: Pre-release build + update server XML for dev/alpha/beta/rc branches
#
# Thin wrapper around moko-platform CLI tools.
# Builds packages, updates updates.xml, and optionally deploys via SFTP.
#
# Joomla filters update entries by the user's "Minimum Stability" setting.
name: "Update Server"
on:
push:
branches:
- 'dev'
- 'dev/**'
- 'alpha/**'
- 'beta/**'
- 'rc/**'
paths:
- 'src/**'
- 'htdocs/**'
pull_request:
types: [closed]
branches:
- 'dev'
- 'dev/**'
- 'alpha/**'
- 'beta/**'
- 'rc/**'
paths:
- 'src/**'
- 'htdocs/**'
workflow_dispatch:
inputs:
stability:
description: 'Stability tag'
required: true
default: 'development'
type: choice
options:
- development
- alpha
- beta
- rc
- stable
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
GITEA_URL: ${{ vars.GITEA_URL || 'https://git.mokoconsulting.tech' }}
GITEA_ORG: ${{ vars.GITEA_ORG || github.repository_owner }}
GITEA_REPO: ${{ vars.GITEA_REPO || github.event.repository.name }}
permissions:
contents: write
jobs:
update-xml:
name: Update Server
runs-on: release
if: >-
github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' || github.event_name == 'push'
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.MOKOGITEA_TOKEN }}
fetch-depth: 0
- name: Setup moko-platform tools
env:
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGITEA_TOKEN }}
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
COMPOSER_AUTH: '{"http-basic":{"git.mokoconsulting.tech":{"username":"token","password":"${{ secrets.MOKOGITEA_TOKEN }}"}}}'
run: |
if ! command -v composer &> /dev/null; then
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
fi
# Always fetch latest CLI tools — never use stale cache from previous runs
rm -rf /tmp/moko-platform
git clone --depth 1 --branch main --quiet \
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/moko-platform.git" \
/tmp/moko-platform 2>/dev/null || true
if [ -d "/tmp/moko-platform" ] && [ -f "/tmp/moko-platform/composer.json" ]; then
cd /tmp/moko-platform && composer install --no-dev --no-interaction --quiet 2>/dev/null || true
fi
echo "MOKO_CLI=/tmp/moko-platform/cli" >> "$GITHUB_ENV"
- name: Detect platform
id: platform
run: php ${MOKO_CLI}/manifest_read.php --path . --github-output
- name: Resolve stability and bump version
id: meta
run: |
BRANCH="${{ github.ref_name }}"
# Configure git for bot pushes
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
git config --local user.name "gitea-actions[bot]"
git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
# Auto-bump patch version
php ${MOKO_CLI}/version_bump.php --path . 2>/dev/null || true
VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null || echo "0.0.0")
# Strip any existing suffix before applying stability
VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//')
# Determine stability from branch or manual input
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
STABILITY="${{ inputs.stability }}"
elif [[ "$BRANCH" == rc/* ]]; then
STABILITY="rc"
elif [[ "$BRANCH" == beta/* ]]; then
STABILITY="beta"
elif [[ "$BRANCH" == alpha/* ]]; then
STABILITY="alpha"
else
STABILITY="development"
fi
# Version suffix per stability stream
case "$STABILITY" in
development) SUFFIX="-dev"; TAG="development" ;;
alpha) SUFFIX="-alpha"; TAG="alpha" ;;
beta) SUFFIX="-beta"; TAG="beta" ;;
rc) SUFFIX="-rc"; TAG="release-candidate" ;;
*) SUFFIX=""; TAG="stable" ;;
esac
# Propagate version with stability suffix to all manifest files
php ${MOKO_CLI}/version_set_platform.php \
--path . --version "$VERSION" --branch "$BRANCH" --stability "$STABILITY" 2>/dev/null || true
php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true
# Re-read version (now includes suffix from version_set_platform)
if [ -n "$SUFFIX" ]; then
VERSION="${VERSION}${SUFFIX}"
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "stability=${STABILITY}" >> "$GITHUB_OUTPUT"
echo "suffix=${SUFFIX}" >> "$GITHUB_OUTPUT"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "display_version=${VERSION}" >> "$GITHUB_OUTPUT"
# Commit version bump if changed
git add -A
git diff --cached --quiet || {
git commit -m "chore(version): auto-bump ${VERSION} [skip ci]" \
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
git push
}
- name: Create release and upload package
id: package
run: |
VERSION="${{ steps.meta.outputs.version }}"
TAG="${{ steps.meta.outputs.tag }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
# Create or update Gitea release
php ${MOKO_CLI}/release_create.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --branch "${{ github.ref_name }}" --prerelease
# Build package and upload
php ${MOKO_CLI}/release_package.php \
--path . --version "$VERSION" --tag "$TAG" \
--token "${{ secrets.MOKOGITEA_TOKEN }}" --api-base "$API_BASE" \
--repo "${GITEA_REPO}" --output /tmp || true
- name: Update updates.xml
if: steps.platform.outputs.platform == 'joomla'
run: |
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
SHA256="${{ steps.package.outputs.sha256_zip }}"
if [ ! -f "updates.xml" ]; then
echo "No updates.xml — skipping"
exit 0
fi
SHA_FLAG=""
[ -n "$SHA256" ] && SHA_FLAG="--sha ${SHA256}"
php ${MOKO_CLI}/updates_xml_build.php \
--path . --version "${VERSION}" --stability "${STABILITY}" \
--gitea-url "${GITEA_URL}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" \
${SHA_FLAG}
# Commit and push updates.xml
git add updates.xml
git diff --cached --quiet || {
git commit -m "chore: update ${STABILITY} channel ${VERSION} [skip ci]"
git push
}
- name: Sync updates.xml to main
if: github.ref_name != 'main' && steps.platform.outputs.platform == 'joomla'
run: |
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
GITEA_TOKEN="${{ secrets.MOKOGITEA_TOKEN }}"
FILE_SHA=$(curl -sf -H "Authorization: token ${GITEA_TOKEN}" \
"${API_BASE}/contents/updates.xml?ref=main" | python3 -c "import sys,json; print(json.load(sys.stdin).get('sha',''))" 2>/dev/null || true)
if [ -n "$FILE_SHA" ] && [ -f "updates.xml" ]; then
python3 -c "
import base64, json, urllib.request, sys
with open('updates.xml', 'rb') as f:
content = base64.b64encode(f.read()).decode()
payload = json.dumps({
'content': content,
'sha': '${FILE_SHA}',
'message': 'chore: sync updates.xml from ${{ steps.meta.outputs.stability }} [skip ci]',
'branch': 'main'
}).encode()
req = urllib.request.Request(
'${API_BASE}/contents/updates.xml',
data=payload, method='PUT',
headers={
'Authorization': 'token ${GITEA_TOKEN}',
'Content-Type': 'application/json'
})
try:
urllib.request.urlopen(req)
print('updates.xml synced to main')
except Exception as e:
print(f'WARNING: sync to main failed: {e}', file=sys.stderr)
"
fi
- name: SFTP deploy to dev server
if: contains(github.ref, 'dev/') || github.ref == 'refs/heads/dev'
env:
DEV_HOST: ${{ vars.DEV_FTP_HOST }}
DEV_PATH: ${{ vars.DEV_FTP_PATH }}
DEV_SUFFIX: ${{ vars.DEV_FTP_SUFFIX }}
DEV_USER: ${{ vars.DEV_FTP_USERNAME }}
DEV_PORT: ${{ vars.DEV_FTP_PORT }}
DEV_KEY: ${{ secrets.DEV_FTP_KEY }}
DEV_PASS: ${{ secrets.DEV_FTP_PASSWORD }}
run: |
# Permission check: admin or maintain role required
ACTOR="${{ github.actor }}"
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \
"${API_BASE}/collaborators/${ACTOR}/permission" 2>/dev/null | \
python3 -c "import sys,json; print(json.load(sys.stdin).get('permission','read'))" 2>/dev/null || echo "read")
case "$PERMISSION" in
admin|maintain|write) ;;
*)
echo "Deploy denied: ${ACTOR} has '${PERMISSION}' — requires admin, maintain, or write"
exit 0
;;
esac
[ -z "$DEV_HOST" ] || [ -z "$DEV_PATH" ] && { echo "DEV FTP not configured — skipping SFTP"; exit 0; }
SOURCE_DIR="src"
[ ! -d "$SOURCE_DIR" ] && SOURCE_DIR="htdocs"
[ ! -d "$SOURCE_DIR" ] && exit 0
PORT="${DEV_PORT:-22}"
REMOTE="${DEV_PATH%/}"
[ -n "$DEV_SUFFIX" ] && REMOTE="${REMOTE}/${DEV_SUFFIX#/}"
printf '{"host":"%s","port":%s,"username":"%s","remotePath":"%s"' \
"$DEV_HOST" "$PORT" "$DEV_USER" "$REMOTE" > /tmp/sftp-config.json
if [ -n "$DEV_KEY" ]; then
echo "$DEV_KEY" > /tmp/deploy_key && chmod 600 /tmp/deploy_key
printf ',"privateKeyPath":"/tmp/deploy_key"}' >> /tmp/sftp-config.json
else
printf ',"password":"%s"}' "$DEV_PASS" >> /tmp/sftp-config.json
fi
PLATFORM=$(php ${MOKO_CLI}/platform_detect.php --path . 2>/dev/null || true)
if [ "$PLATFORM" = "waas-component" ] && [ -f "${MOKO_CLI}/../deploy/deploy-joomla.php" ]; then
php ${MOKO_CLI}/../deploy/deploy-joomla.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
elif [ -f "${MOKO_CLI}/../deploy/deploy-sftp.php" ]; then
php ${MOKO_CLI}/../deploy/deploy-sftp.php --path . --src-dir "$SOURCE_DIR" --config /tmp/sftp-config.json
fi
rm -f /tmp/deploy_key /tmp/sftp-config.json
echo "SFTP deploy to dev complete" >> $GITHUB_STEP_SUMMARY
- name: Summary
if: always()
run: |
VERSION="${{ steps.meta.outputs.version }}"
STABILITY="${{ steps.meta.outputs.stability }}"
DISPLAY="${{ steps.meta.outputs.display_version }}"
echo "## Update Server" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Field | Value |" >> $GITHUB_STEP_SUMMARY
echo "|-------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| Stability | \`${STABILITY}\` |" >> $GITHUB_STEP_SUMMARY
echo "| Version | \`${DISPLAY}\` |" >> $GITHUB_STEP_SUMMARY
+9 -1
View File
@@ -1,4 +1,4 @@
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
@@ -28,6 +28,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Changed
- Migrated all workflow and template paths from `.github/` to `.mokogitea/`
- Template source paths updated: `templates/gitea/` to `templates/mokogitea/`
- HCL definition files removed -- Template repos are now the canonical source
### Added
- `branch-cleanup.yml`: auto-delete merged feature branches after PR merge
### Added
- GitHub Actions firewall configuration for Copilot agent
- `.github/copilot/firewall-allowlist.json`: Allowlist for enterprise-ready sites and license sources
+43
View File
@@ -0,0 +1,43 @@
# CLAUDE.md
This file provides guidance to Claude Code when working with this repository.
## Project Overview
**joomla-api-mcp** -- MCP server for Joomla Web Services API operations
| Field | Value |
|---|---|
| **Platform** | mcp-server |
| **Language** | TypeScript |
| **Default branch** | main |
| **License** | GPL-3.0-or-later |
| **Wiki** | [joomla-api-mcp Wiki](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki) |
| **Standards** | [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home) |
## Common Commands
```bash
npm install # Install dependencies
npm run build # Compile TypeScript
npm run dev # Development mode
```
## Architecture
This is an MCP (Model Context Protocol) server. Key files:
- `src/index.ts` -- server entry point and tool registration
- `src/config.ts` -- configuration loading
- `src/tools/` -- individual tool implementations
- `dist/` -- compiled output (gitignored)
## Rules
- **Workflow directory**: `.mokogitea/` (not `.gitea/` or `.github/`)
- **Never commit** `.claude/`, `.mcp.json`, `TODO.md`, or `*.min.css`/`*.min.js`
- **Attribution**: use `Authored-by: Moko Consulting` in commits
- **Branch strategy**: develop on `dev`, merge to `main` for release
- **Minification**: handled at build time (CI) and runtime (MokoMinifyHelper for Joomla templates)
- **Wiki**: documentation lives in the Gitea wiki, not in `docs/` files
- **Standards**: this repo follows [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)
+1 -1
View File
@@ -1,4 +1,4 @@
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
+161 -127
View File
@@ -1,127 +1,161 @@
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License (./LICENSE).
# FILE INFORMATION
DEFGROUP:
INGROUP: Project.Documentation
REPO: mokoconsulting-tech/MokoStandards-Template-Generic
VERSION: 00.00.01
PATH: ./CONTRIBUTING.md
BRIEF: Contribution guidelines for the project
-->
# Contributing to MokoStandards-Template-Generic
We appreciate your interest in contributing to this project! This document provides guidelines for contributing.
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [How to Contribute](#how-to-contribute)
- [Development Workflow](#development-workflow)
- [Commit Messages](#commit-messages)
- [Pull Request Process](#pull-request-process)
## Code of Conduct
This project adheres to the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to hello@mokoconsulting.tech.
## Getting Started
1. Fork the repository
2. Clone your fork locally
3. Set up the development environment
4. Create a new branch for your work
## How to Contribute
### Reporting Bugs
- Use the GitHub issue tracker
- Describe the bug clearly with steps to reproduce
- Include relevant logs, screenshots, or error messages
- Specify your environment (OS, version, etc.)
### Suggesting Enhancements
- Use the GitHub issue tracker
- Clearly describe the enhancement and its benefits
- Provide examples of how it would work
### Contributing Code
- Pick an issue or create one
- Fork the repository and create a branch
- Make your changes following the project conventions
- Write or update tests as needed
- Submit a pull request
## Development Workflow
1. Ensure your fork is up to date with the main repository
2. Create a feature branch from `main`
3. Make your changes
4. Test your changes thoroughly
5. Commit your changes with clear messages
6. Push to your fork
7. Create a pull request
## Commit Messages
Follow the conventional commit format:
```
<type>(<scope>): <subject>
<body>
<footer>
```
Types: `feat`, `fix`, `docs`, `style`, `refactor`, `test`, `chore`, `ci`, `build`, `perf`, `revert`
Example:
```
feat(docs): add contributing guidelines
Add comprehensive contributing guidelines to help new contributors
understand the development workflow and coding standards.
```
## Pull Request Process
1. Update documentation for any new features
2. Follow the project's coding style and conventions
3. Ensure all tests pass
4. Update the CHANGELOG.md with your changes
5. Request review from maintainers
6. Address any feedback promptly
7. Once approved, your PR will be merged
## Style Guidelines
- Follow the `.editorconfig` settings
- Use tabs for indentation (width: 2 spaces)
- Ensure files end with a newline
- Use LF line endings (except for Windows-specific files)
- Trim trailing whitespace (except in Markdown)
## Questions?
If you have questions about contributing, feel free to open an issue or contact the maintainers.
## Revision History
| Date | Version | Author | Notes |
| --- | --- | --- | --- |
| 2026-01-16 | 0.1.0 | Copilot | Initial contributing guidelines |
# Contributing to Moko Consulting Projects
Thank you for your interest in contributing. All Moko Consulting repositories follow this universal workflow and version policy.
## Branching Workflow
```
feature/* ──PR──> dev ──draft PR──> (renamed to rc) ──merge──> main
```
### Step by step
1. **Create a feature branch** from `dev`:
```bash
git checkout dev && git pull
git checkout -b feature/my-change
```
2. **Work and commit** on your feature branch. Push to origin.
3. **Open a PR**: `feature/my-change` → `dev`. After review and checks, merge it.
4. **When ready for release**, open a **draft PR**: `dev` → `main`.
- This automatically renames the source branch to `rc` (release candidate)
- An RC pre-release is built and uploaded
5. **Alpha and beta branches** are created by manually renaming the branch before the RC stage:
- Rename `dev` to `alpha` for early testing → alpha pre-release is built
- Rename `alpha` to `beta` for feature-complete testing → beta pre-release is built
- When the draft PR is created, the branch is renamed to `rc`
6. **Once PR checks pass** on the `rc` branch, mark the PR as ready and merge to `main`.
7. **Merging to main** triggers the stable release pipeline:
- Minor version bump (e.g., `02.09.xx` → `02.10.00`)
- Stability suffix stripped (clean version)
- Gitea release created with ZIP/tar.gz packages
- `updates.xml` updated (Joomla extensions)
- `dev` branch recreated from `main`
### Branch summary
| Branch | Purpose | Created by |
|--------|---------|-----------|
| `feature/*` | New features and fixes | Developer |
| `dev` | Integration branch | Auto-recreated after release |
| `alpha` | Alpha pre-release testing | Manual rename from `dev` |
| `beta` | Beta pre-release testing | Manual rename from `alpha` |
| `rc` | Release candidate | Auto-renamed on draft PR to main |
| `main` | Stable releases | Protected, merge only |
| `version/XX.YY.ZZ` | Archived release snapshots | Auto-created by CI |
### Protected branches
| Branch | Direct push | Merge via |
|--------|------------|-----------|
| `main` | Blocked (CI bot whitelisted) | PR merge only |
| `dev` | Blocked (CI bot whitelisted) | PR merge from feature/* |
| `rc` | Blocked (CI bot whitelisted) | Auto-created on draft PR |
| `alpha` | Blocked (CI bot whitelisted) | Manual rename |
| `beta` | Blocked (CI bot whitelisted) | Manual rename |
| `feature/*` | Open | N/A (source branch) |
## Version Policy
### Format
All versions use `XX.YY.ZZ` — three two-digit segments, zero-padded:
- **XX** — Major version (breaking changes)
- **YY** — Minor version (new features, bumped on release to main)
- **ZZ** — Patch version (auto-incremented on every push to dev/feature branches)
Rollover: patch `99` → `00` increments minor; minor `99` → `00` increments major.
### Stability suffixes
Each branch appends a suffix to indicate stability:
| Branch | Suffix | Example |
|--------|--------|---------|
| `main` | (none) | `02.09.00` |
| `dev` | `-dev` | `02.09.01-dev` |
| `feature/*` | `-dev` | `02.09.01-dev` |
| `alpha` | `-alpha` | `02.09.01-alpha` |
| `beta` | `-beta` | `02.09.01-beta` |
| `rc` | `-rc` | `02.09.01-rc` |
### Auto version bump
On every push to `dev`, `feature/*`, or `patch/*`:
1. Patch version incremented
2. Stability suffix `-dev` applied
3. All version-bearing files updated (manifests, CHANGELOG, PHP headers, etc.)
4. Commit created with `[skip ci]` to avoid loops
### Release version flow
Version bumps happen at specific release events:
| Event | Bump | Example |
|-------|------|---------|
| Feature merged to dev | Patch bump after dev release | `02.09.01-dev` → release → `02.09.02-dev` |
| Dev promoted to RC | Minor bump | `02.09.02-dev` → `02.10.00-rc` |
| RC merged to main | Minor bump | `02.10.00-rc` → `02.11.00` (stable) |
| Dev recreated from main | Patch bump | `02.11.00` → `02.11.01-dev` |
### Release stream copies
When a higher-stability release is published, copies are created for all lesser streams with the same base version:
- **RC `02.10.00-rc`** also creates: `02.10.00-dev`, `02.10.00-alpha`, `02.10.00-beta`
- **Stable `02.11.00`** also creates: `02.11.00-dev`, `02.11.00-alpha`, `02.11.00-beta`, `02.11.00-rc`
This ensures Joomla sites on ANY stability channel see the update (Joomla only shows versions higher than what's installed).
### Version files
The version tools update all files containing version stamps:
- `.mokogitea/manifest.xml` (canonical source)
- Joomla XML manifests (`<version>` tag)
- `README.md`, `CHANGELOG.md` (`VERSION:` pattern)
- `package.json`, `pyproject.toml`
- Any text file with a `VERSION: XX.YY.ZZ` label
Files synced from other repos (with a `# REPO:` header) are not touched.
## Code Standards
- **PHP**: PSR-12, tabs for indentation
- **Copyright**: all files must include the Moko Consulting copyright header
- **License**: SPDX identifier `GPL-3.0-or-later` (or as specified per repo)
- **Attribution**: use `Authored-by: Moko Consulting` in commits, not individual names
## Commit Messages
Use conventional commit format:
```
type(scope): short description
Optional body with context.
Authored-by: Moko Consulting
```
Types: `feat`, `fix`, `chore`, `docs`, `style`, `refactor`, `test`, `ci`
Special flags in commit messages:
- `[skip ci]` — skip all CI workflows
- `[skip bump]` — skip auto version bump only
## Reporting Issues
Use the repository's issue tracker with the appropriate template.
---
*Moko Consulting <hello@mokoconsulting.tech>*
+68 -97
View File
@@ -1,133 +1,104 @@
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
# joomla-api-mcp
This file is part of a Moko Consulting project.
MCP server for Joomla Web Services API operations
SPDX-LICENSE-IDENTIFIER: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License (./LICENSE).
# FILE INFORMATION
DEFGROUP:
INGROUP: Project.Documentation
REPO: mokoconsulting-tech/MokoStandards-Template-Generic
VERSION: 00.00.01
PATH: ./README.md
BRIEF: Generic coding project template according to MokoStandards
-->
![Language](https://img.shields.io/badge/Markdown-000000?style=flat-square&logo=markdown&logoColor=white) ![License](https://img.shields.io/badge/license-GPL--3.0--or--later-green?style=flat-square) ![Wiki](https://img.shields.io/badge/wiki-joomla-api-mcp-blue?style=flat-square)
[![Version](https://img.shields.io/badge/version-00.00.01-blue.svg?logo=v&logoColor=white)](https://github.com/mokoconsulting-tech/MokoStandards-Template-Generic/releases/tag/v00)
[![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)
Model Context Protocol server for the Joomla Web Services API -- full CRUD for articles, categories, users, menus, contacts, tags, media, plugins, and more.
# MokoStandards-Template-Generic
---
[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
| | |
|---|---|
| **Type** | MCP Server |
| **Language** | Node.js |
| **Tools** | 67 tools across 15 resource groups |
| **License** | GPL-3.0-or-later |
| **Platform** | [Gitea](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp) (primary) |
A template repository for generic coding projects that follows MokoStandards conventions.
---
This template provides a standardized structure for any coding project, including proper documentation, licensing, contribution guidelines, and project organization. It is designed to help you quickly bootstrap new projects with best practices and consistent conventions.
## Overview
## Table of Contents
joomla-api-mcp wraps the entire Joomla Web Services REST API into MCP tools that Claude Code can call directly. It supports multi-site connections via named connection configs.
- [Background](#background)
- [Install](#install)
- [Usage](#usage)
- [Structure](#structure)
- [Contributing](#contributing)
- [License](#license)
- [Maintainers](#maintainers)
### Resource Coverage
## Background
| Group | Operations |
|-------|------------|
| Articles | list, get, create, update, delete |
| Categories | list, create, update, delete |
| Users | list, get, create, update, delete, groups |
| Contacts | list, get, create, update, delete |
| Menus | list types, list/get/create/update/delete items |
| Tags | list, get, create, update, delete |
| Custom Fields | list, get, create, delete |
| Plugins | list, update (enable/disable) |
| Modules | list |
| Templates | list |
| Media | list, get file, delete file, create folder |
| Banners | list, get, create, delete, list clients |
| Newsfeeds | list, get, create, delete |
| Messages | list, get, send, delete |
| Redirects | list, create, delete |
| Config | get, update |
| Content History | list versions |
| Checkin | unlock checked-out items |
| Associations | list multilingual associations |
| Generic | raw API request, list connections |
MokoStandards-Template-Generic is a repository template designed to provide a consistent foundation for generic coding projects. It includes:
---
- Standard documentation structure (README, LICENSE, CONTRIBUTING, CODE_OF_CONDUCT, CHANGELOG)
- MokoStandards-compliant file headers and metadata
- EditorConfig for consistent coding styles across editors
- Git configuration templates
- Documentation index system for easy navigation
## Wiki Pages
This template follows the [standard-readme](https://github.com/RichardLitt/standard-readme) specification and incorporates MokoStandards conventions for enterprise-grade project organization.
### Guides
## Install
- [Installation](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki/INSTALLATION) -- setup, .env configuration, Claude Code registration, multi-site connections
To use this template:
### Reference
1. Click the "Use this template" button on GitHub
2. Create a new repository from this template
3. Clone your new repository locally:
- [API](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki/API) -- all 67 tools with parameters, grouped by resource type
- [Architecture](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki/ARCHITECTURE) -- source file map, component design, connection handling
```sh
git clone https://github.com/your-username/your-new-repo.git
cd your-new-repo
```
### Templates
4. Update the project-specific details:
- Update README.md with your project name and description
- Update LICENSE if using a different license
- Update file headers with appropriate REPO, DEFGROUP, and BRIEF values
- Update CHANGELOG.md with your version history
- [Templates Index](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki/templates-index) -- workflow and config templates
- [README Template](templates-README-template) -- README template for MCP repos
## Usage
---
This template is designed to be customized for your specific project needs.
## Related Wikis
### Getting Started
| Repo | Purpose |
|------|---------|
| [backup-mcp](https://git.mokoconsulting.tech/MokoConsulting/backup-mcp/wiki) | Backup MCP (uses Joomla API for Akeeba) |
| [MokoWaaS](https://git.mokoconsulting.tech/MokoConsulting/MokoWaaS/wiki) | Joomla WaaS system plugin |
| [Template-Client-WaaS](https://git.mokoconsulting.tech/MokoConsulting/Template-Client-WaaS/wiki) | Client site template |
| [MokoOnyx](https://git.mokoconsulting.tech/MokoConsulting/MokoOnyx/wiki) | Joomla admin template |
1. Replace placeholder text with your project details
2. Add your source code to the `src/` directory
3. Add scripts to the `scripts/` directory
4. Add documentation to the `docs/` directory
5. Update the CHANGELOG.md as you make changes
---
### Project Structure
> **[MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki)** -- central standards hub for all Moko Consulting projects.
```
.
├── docs/ # Documentation files
├── scripts/ # Build and utility scripts
├── src/ # Source code
├── README.md # This file
├── LICENSE # License information
├── CONTRIBUTING.md # Contribution guidelines
├── CODE_OF_CONDUCT.md # Code of conduct
└── CHANGELOG.md # Version history
```
---
## Structure
The repository follows MokoStandards conventions:
- **Documentation**: All `.md` files include copyright headers and file metadata
- **Index Files**: Each directory contains an `index.md` for navigation
- **EditorConfig**: Maintains consistent coding styles (tabs, width 2)
- **Git Configuration**: Includes `.gitattributes`, `.gitignore`, and `.gitmessage` templates
---
## Documentation
Full documentation is available on the [Wiki](https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp/wiki).
## Contributing
Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests.
This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md) Code of Conduct.
See the wiki for development guidelines and contribution instructions.
## License
This project is licensed under the GNU General Public License v3.0 or later - see the [LICENSE](LICENSE) file for details.
This project is licensed under the GNU General Public License v3.0 or later -- see the [LICENSE](LICENSE) file.
Copyright © 2025 Moko Consulting <hello@mokoconsulting.tech>
---
## Maintainers
[@mokoconsulting-tech](https://github.com/mokoconsulting-tech)
For questions or support, please contact: hello@mokoconsulting.tech
## Revision History
| Date | Version | Author | Notes |
| --- | --- | --- | --- |
| 2026-01-16 | 0.1.0 | Copilot | Initial MokoStandards-compliant README |
*[Moko Consulting](https://mokoconsulting.tech) -- [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/moko-platform/wiki/Home)*
-142
View File
@@ -1,142 +0,0 @@
<!--
Copyright (C) 2026 [Organization Name] <contact@example.com>
This file is part of [Project Name].
SPDX-License-Identifier: GPL-3.0-or-later
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
-->
# [Project Name] Roadmap
## Scope and Intent
This document defines the roadmap for [Project Name] starting with version **[X.Y.Z]**. It establishes the sequencing, intent, and maturity expectations for deliverables governed by this project.
This roadmap is forward-looking by design. Completed work prior to the current baseline version is considered foundational and is intentionally excluded. This file tracks **current and future-state development only**.
## Version [X.Y.Z] — [Phase Name] ✅ COMPLETED / 🔄 IN PROGRESS / 📋 PLANNED
Focus: [Brief description of this version's primary focus]
### Completed Deliverables
***[Category Name]**
* ✅ [Specific deliverable or feature]
* ✅ [Specific deliverable or feature]
***[Category Name]**
* ✅ [Specific deliverable or feature]
### In Progress
* 🔄 [Item currently being worked on]
* 🔄 [Item currently being worked on]
### Planned Deliverables
* [Future planned item]
* [Future planned item]
### Achieved Outcomes
* ✅ [Measurable outcome or benefit]
* ✅ [Measurable outcome or benefit]
* 🔄 [Partially achieved outcome]
## Version [X.Y+1.Z] — [Next Phase Name]
Focus: [Brief description of next version's primary focus]
### In-Scope Deliverables
* [Deliverable for next version]
* [Deliverable for next version]
### Outcomes
* [Expected outcome or benefit]
* [Expected outcome or benefit]
## Version [X.Y+2.Z] — [Future Phase Name]
Focus: [Brief description of future version's primary focus]
### Planned Deliverables
* [Future deliverable]
* [Future deliverable]
### Outcomes
* [Expected outcome]
* [Expected outcome]
## Version [X.Y+3.Z] and Beyond — [Long-term Vision]
Focus: [Long-term strategic direction]
### Forward-Looking Initiatives
* [Strategic initiative]
* [Strategic initiative]
### Outcomes
* [Long-term goal]
* [Long-term goal]
---
This roadmap is intentionally conservative and additive. New versions extend prior guarantees without breaking existing contracts.
## Guidelines for Version Planning
### Version Numbering
Use semantic versioning for clarity:
- **Major versions** (X.0.0): Breaking changes, major architectural shifts
- **Minor versions** (X.Y.0): New features, significant enhancements
- **Patch versions** (X.Y.Z): Bug fixes, minor improvements
### Planning Horizon
- **Current Version**: Actively being delivered
- **Next 2-3 Versions**: Clearly defined with specific deliverables
- **Future Versions**: High-level themes and strategic direction
### Status Indicators
-**COMPLETED**: Delivered and validated
- 🔄 **IN PROGRESS**: Active development underway
- 📋 **PLANNED**: Scheduled but not yet started
- ⏸️ **PAUSED**: Temporarily on hold
-**CANCELLED**: No longer pursuing
## Metadata
```
Owner: [Owner Name/Role]
Reviewers: [Reviewer Names/Roles]
Status: Active
Last Updated: [YYYY-MM-DD]
Next Review: [YYYY-MM-DD]
```
## Revision History
| Date | Version | Author | Notes |
| ---------- | -------- | -------------- | ------------------------------- |
| YYYY-MM-DD | X.Y.Z | [Author Name] | [Description of changes] |
| YYYY-MM-DD | X.Y.Z | [Author Name] | [Description of changes] |
+5
View File
@@ -45,6 +45,11 @@ Security updates are provided for the following versions:
Only the current major version receives security updates. Users should upgrade to the latest supported version to receive security patches.
## Reporting a Vulnerability
Report security vulnerabilities via Gitea issue (preferred):
https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-Template-Generic/issues/new?template=security.yaml
Or email: hello@mokoconsulting.tech
### Where to Report
+12
View File
@@ -0,0 +1,12 @@
# TODO
> **Note:** This file is not tracked in version control (.gitignore). It is for local task tracking only.
## Critical
-
## Normal
-
## Low
-
+237
View File
@@ -0,0 +1,237 @@
#!/usr/bin/env bash
# ============================================================================
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
# FILE INFORMATION
# DEFGROUP: Automation.CI
# INGROUP: moko-platform.Automation
# REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
# PATH: /automation/ci-issue-reporter.sh
# VERSION: 09.23.00
# BRIEF: Creates or updates a Gitea issue when a CI gate fails.
# Deduplicates by searching open issues with the "ci-auto" label
# whose title matches the gate. If a matching issue exists, a comment
# is appended instead of opening a duplicate.
# ============================================================================
set -euo pipefail
# ── Defaults ────────────────────────────────────────────────────────────────
GITEA_URL="${GITEA_URL:-https://git.mokoconsulting.tech}"
GITEA_TOKEN="${GITEA_TOKEN:-}"
REPO="${GITHUB_REPOSITORY:-}"
RUN_URL="${GITHUB_SERVER_URL:-${GITEA_URL}}/${REPO}/actions/runs/${GITHUB_RUN_ID:-0}"
LABEL_NAME="ci-auto"
LABEL_COLOR="#e11d48"
GATE=""
DETAILS=""
SEVERITY="error"
WORKFLOW=""
# ── Parse arguments ─────────────────────────────────────────────────────────
usage() {
cat <<EOF
Usage: ci-issue-reporter.sh --gate NAME --details TEXT [OPTIONS]
Required:
--gate CI gate name (e.g. "Code Quality", "Self-Health")
--details Human-readable failure description
Optional:
--severity "error" (default) or "warning"
--workflow Workflow name for the issue title
--repo owner/repo (default: \$GITHUB_REPOSITORY)
--run-url URL to the CI run (auto-detected from env)
--token Gitea API token (default: \$GITEA_TOKEN)
--url Gitea base URL (default: \$GITEA_URL)
EOF
exit 1
}
while [[ $# -gt 0 ]]; do
case "$1" in
--gate) GATE="$2"; shift 2 ;;
--details) DETAILS="$2"; shift 2 ;;
--severity) SEVERITY="$2"; shift 2 ;;
--workflow) WORKFLOW="$2"; shift 2 ;;
--repo) REPO="$2"; shift 2 ;;
--run-url) RUN_URL="$2"; shift 2 ;;
--token) GITEA_TOKEN="$2"; shift 2 ;;
--url) GITEA_URL="$2"; shift 2 ;;
-h|--help) usage ;;
*) echo "Unknown option: $1"; usage ;;
esac
done
[[ -z "$GATE" ]] && { echo "ERROR: --gate is required"; usage; }
[[ -z "$DETAILS" ]] && { echo "ERROR: --details is required"; usage; }
[[ -z "$GITEA_TOKEN" ]] && { echo "ERROR: GITEA_TOKEN not set"; exit 1; }
[[ -z "$REPO" ]] && { echo "ERROR: GITHUB_REPOSITORY not set"; exit 1; }
API="${GITEA_URL}/api/v1/repos/${REPO}"
# ── Build title ─────────────────────────────────────────────────────────────
if [[ -n "$WORKFLOW" ]]; then
TITLE="[CI] ${WORKFLOW}: ${GATE} failed"
else
TITLE="[CI] ${GATE} failed"
fi
# ── Ensure label exists ─────────────────────────────────────────────────────
ensure_label() {
local exists
exists=$(curl -sf -o /dev/null -w '%{http_code}' \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/labels" 2>/dev/null || echo "000")
if [[ "$exists" == "200" ]]; then
# Check if label already exists
local found
found=$(curl -sf \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/labels" 2>/dev/null \
| grep -o "\"name\":\"${LABEL_NAME}\"" || true)
if [[ -z "$found" ]]; then
curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/labels" \
-d "{\"name\":\"${LABEL_NAME}\",\"color\":\"${LABEL_COLOR}\",\"description\":\"Auto-created by CI issue reporter\"}" \
> /dev/null 2>&1 || true
fi
fi
}
# ── Search for existing open issue ──────────────────────────────────────────
find_existing_issue() {
# URL-encode the gate name for the query
local query
query=$(printf '%s' "[CI] ${GATE}" | sed 's/ /%20/g; s/\[/%5B/g; s/\]/%5D/g')
local response
response=$(curl -sf \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/issues?type=issues&state=open&labels=${LABEL_NAME}&q=${query}&limit=5" \
2>/dev/null || echo "[]")
# Extract the first matching issue number
echo "$response" \
| grep -oP '"number":\s*\K[0-9]+' \
| head -1
}
# ── Build issue body ────────────────────────────────────────────────────────
build_body() {
local severity_badge
if [[ "$SEVERITY" == "error" ]]; then
severity_badge="**Severity:** Error"
else
severity_badge="**Severity:** Warning"
fi
cat <<BODY
## CI Gate Failure: ${GATE}
${severity_badge}
**Workflow:** ${WORKFLOW:-unknown}
**Branch:** ${GITHUB_REF_NAME:-unknown}
**Commit:** \`${GITHUB_SHA:0:8}\`
**Run:** [View CI run](${RUN_URL})
### Details
${DETAILS}
### Resolution
Fix the issue described above and push a new commit. This issue will be closed automatically when the gate passes, or can be closed manually.
---
*Auto-created by [ci-issue-reporter](${GITEA_URL}/${REPO}/src/branch/main/automation/ci-issue-reporter.sh)*
BODY
}
# ── Build comment body (for existing issues) ────────────────────────────────
build_comment() {
cat <<COMMENT
### CI failure recurrence
**Branch:** ${GITHUB_REF_NAME:-unknown}
**Commit:** \`${GITHUB_SHA:0:8}\`
**Run:** [View CI run](${RUN_URL})
${DETAILS}
COMMENT
}
# ── Main ────────────────────────────────────────────────────────────────────
ensure_label
EXISTING=$(find_existing_issue)
if [[ -n "$EXISTING" ]]; then
# Append comment to existing issue
COMMENT_BODY=$(build_comment)
COMMENT_JSON=$(printf '%s' "$COMMENT_BODY" | python3 -c "
import sys, json
print(json.dumps({'body': sys.stdin.read()}))" 2>/dev/null)
HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues/${EXISTING}/comments" \
-d "${COMMENT_JSON}" 2>/dev/null || echo "000")
if [[ "$HTTP" == "201" ]]; then
echo "Commented on existing issue #${EXISTING}"
else
echo "WARNING: Failed to comment on issue #${EXISTING} (HTTP ${HTTP})"
fi
else
# Create new issue
ISSUE_BODY=$(build_body)
ISSUE_JSON=$(python3 -c "
import sys, json
body = sys.stdin.read()
print(json.dumps({
'title': sys.argv[1],
'body': body,
'labels': []
}))" "$TITLE" <<< "$ISSUE_BODY" 2>/dev/null)
# Create the issue
RESPONSE=$(curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues" \
-d "${ISSUE_JSON}" 2>/dev/null || echo "{}")
ISSUE_NUM=$(echo "$RESPONSE" | grep -oP '"number":\s*\K[0-9]+' | head -1)
if [[ -n "$ISSUE_NUM" ]]; then
# Apply label (separate call — more reliable across Gitea versions)
LABEL_ID=$(curl -sf \
-H "Authorization: token ${GITEA_TOKEN}" \
"${API}/labels" 2>/dev/null \
| grep -oP "\"id\":\s*\K[0-9]+(?=[^}]*\"name\":\s*\"${LABEL_NAME}\")" \
| head -1 || true)
if [[ -n "$LABEL_ID" ]]; then
curl -sf -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
"${API}/issues/${ISSUE_NUM}/labels" \
-d "{\"labels\":[${LABEL_ID}]}" \
> /dev/null 2>&1 || true
fi
echo "Created issue #${ISSUE_NUM}: ${TITLE}"
else
echo "WARNING: Failed to create issue"
echo "Response: ${RESPONSE}"
fi
fi
+18
View File
@@ -0,0 +1,18 @@
{
"defaultConnection": "production",
"connections": {
"local-dev": {
"baseUrl": "https://localhost:8080",
"apiToken": "your-joomla-api-token-here",
"insecure": true
},
"production": {
"baseUrl": "https://www.example.com",
"apiToken": "your-production-api-token"
},
"staging": {
"baseUrl": "https://staging.example.com",
"apiToken": "your-staging-api-token"
}
}
}
View File
-441
View File
@@ -1,441 +0,0 @@
<!--
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
PATH: /docs/INSTALLATION.md
VERSION: 04.00.15
BRIEF: Installation and setup instructions for [PROJECT_NAME]
-->
# Installation
## Overview
This document provides comprehensive installation and setup instructions for **[PROJECT_NAME]**.
## Table of Contents
- [Prerequisites](#prerequisites)
- [Installation Methods](#installation-methods)
- [Quick Start](#quick-start)
- [Detailed Installation](#detailed-installation)
- [Configuration](#configuration)
- [Verification](#verification)
- [Troubleshooting](#troubleshooting)
- [Next Steps](#next-steps)
## Prerequisites
### System Requirements
- **Operating System**: [Specify supported OS versions]
- **Runtime**: [e.g., PHP 8.1+, Node.js 20+, Python 3.9+]
- **Memory**: [Minimum RAM required]
- **Disk Space**: [Minimum disk space required]
### Software Dependencies
**Required:**
- [List required dependencies with versions]
- Example: Git 2.30+
- Example: Composer 2.0+
**Optional:**
- [List optional dependencies]
### Access Requirements
- [Any required access permissions, credentials, or accounts]
- Example: GitHub account for cloning private repositories
- Example: Database access credentials
## Installation Methods
### Method 1: Using Package Manager (Recommended)
**For [Platform/Package Manager]:**
```bash
# Installation command
[package-manager] install [package-name]
# Verify installation
[package-name] --version
```
### Method 2: From Source
**Clone the repository:**
```bash
# Clone from GitHub
git clone https://github.com/[organization]/[repository].git
cd [repository]
# Checkout stable version (recommended)
git checkout tags/v[VERSION]
```
### Method 3: Using Pre-built Binary/Package
**Download and install:**
```bash
# Download release
wget https://github.com/[organization]/[repository]/releases/download/v[VERSION]/[package-name]
# Make executable (if applicable)
chmod +x [package-name]
# Move to system path (optional)
sudo mv [package-name] /usr/local/bin/
```
## Quick Start
For users who want to get started quickly:
```bash
# 1. Install
[installation-command]
# 2. Configure
[configuration-command]
# 3. Run
[run-command]
# 4. Verify
[verification-command]
```
## Detailed Installation
### Step 1: Prepare Environment
**1.1 Install System Dependencies**
For Ubuntu/Debian:
```bash
sudo apt update
sudo apt install [dependencies]
```
For macOS:
```bash
brew install [dependencies]
```
For Windows:
```powershell
# PowerShell commands or link to Windows-specific guide
```
**1.2 Set Up Environment Variables**
```bash
# Add to ~/.bashrc or ~/.zshrc
export [VAR_NAME]=[value]
# Reload shell configuration
source ~/.bashrc
```
### Step 2: Install Application
**2.1 Install via [Method]**
```bash
[Detailed installation commands with explanations]
```
**2.2 Install Dependencies**
```bash
# For PHP projects
composer install --no-dev
# For Node.js projects
npm install --production
# For Python projects
pip install -r requirements.txt
```
### Step 3: Initial Configuration
**3.1 Create Configuration File**
```bash
# Copy example configuration
cp config/config.example.php config/config.php
# Or use configuration wizard
php bin/configure.php
```
**3.2 Configure Database (if applicable)**
```bash
# Create database
mysql -u root -p -e "CREATE DATABASE [db_name];"
# Import schema
mysql -u root -p [db_name] < database/schema.sql
# Update configuration
nano config/database.php
```
**3.3 Set Permissions**
```bash
# Set appropriate ownership
sudo chown -R www-data:www-data /var/www/[project]
# Set directory permissions (755)
find /var/www/[project] -type d -exec chmod 755 {} \;
# Set file permissions (644 for most files)
find /var/www/[project] -type f -exec chmod 644 {} \;
# Make executable files executable (if needed)
chmod +x /var/www/[project]/bin/*
# Restrict sensitive directories (storage, cache, logs)
chmod 750 /var/www/[project]/storage
chmod 750 /var/www/[project]/cache
```
### Step 4: Initialize Application
**4.1 Run Setup Script**
```bash
# Run initialization
php bin/setup.php
# Or for other platforms
./scripts/setup.sh
```
**4.2 Create Admin User (if applicable)**
```bash
# Create first admin user
php bin/create-admin.php --email=admin@example.com --name="Admin User"
```
## Configuration
### Configuration Files
| File | Purpose | Required |
|------|---------|----------|
| `config/config.php` | Main configuration | Yes |
| `config/database.php` | Database settings | Yes |
| `config/cache.php` | Cache configuration | No |
| `.env` | Environment variables | Yes |
### Essential Configuration Options
**config/config.php:**
```php
return [
'app_name' => '[APPLICATION_NAME]',
'app_url' => 'https://example.com',
'debug' => false, // Set to true for development
'timezone' => 'UTC',
];
```
**Database Configuration:**
```php
return [
'host' => 'localhost',
'port' => 3306,
'database' => '[db_name]',
'username' => '[db_user]',
'password' => '[db_password]',
];
```
### Environment Variables
Create `.env` file:
```bash
APP_ENV=production
APP_DEBUG=false
APP_URL=https://example.com
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=[db_name]
DB_USERNAME=[db_user]
DB_PASSWORD=[db_password]
```
## Verification
### Verify Installation
**Check version:**
```bash
[command] --version
# Expected output: v[VERSION]
```
**Run health check:**
```bash
[command] health-check
# or
php bin/health-check.php
```
**Test basic functionality:**
```bash
# Run test command
[command] test
# Access web interface
curl http://localhost:[port]/health
```
### Expected Output
```
✓ Application installed successfully
✓ Database connection established
✓ All dependencies available
✓ Configuration valid
✓ System ready for use
```
## Troubleshooting
### Common Issues
#### Issue: Installation fails with dependency error
**Symptom:**
```
Error: Package [package-name] not found
```
**Solution:**
```bash
# Update package manager
[package-manager] update
# Retry installation
[package-manager] install [package-name]
```
#### Issue: Database connection fails
**Symptom:**
```
Error: SQLSTATE[HY000] [2002] Connection refused
```
**Solution:**
1. Verify database service is running:
```bash
sudo systemctl status mysql
```
2. Check database credentials in configuration
3. Verify database host and port are correct
#### Issue: Permission denied errors
**Symptom:**
```
Error: Permission denied: /var/www/[project]/storage
```
**Solution:**
```bash
# Fix ownership
sudo chown -R www-data:www-data /var/www/[project]
# Fix permissions
sudo chmod -R 755 /var/www/[project]/storage
```
### Getting Help
If you encounter issues not covered here:
1. **Check Logs:**
```bash
tail -f logs/application.log
tail -f /var/log/apache2/error.log
```
2. **Enable Debug Mode:**
```bash
# In config/config.php
'debug' => true
```
3. **Consult Documentation:**
- [Troubleshooting Guide](guide/troubleshooting.md)
- [FAQ](guide/faq.md)
4. **Community Support:**
- GitHub Issues: [link]
- Discussion Forum: [link]
- Email: support@example.com
## Next Steps
After successful installation:
1. **Review Configuration:**
- [Configuration Guide](guide/configuration.md)
- [Security Hardening](guide/security.md)
2. **Read Getting Started:**
- [Quick Start Guide](guide/quickstart.md)
- [User Guide](guide/user-guide.md)
3. **For Developers:**
- [Development Setup](development/setup.md)
- [Contributing Guidelines](../CONTRIBUTING.md)
4. **For Operators:**
- [Deployment Guide](deployment/procedures.md)
- [Monitoring Setup](operations/monitoring.md)
## Additional Resources
- [Project Documentation](README.md)
- [API Reference](reference/api/)
- [Change Log](../CHANGELOG.md)
- [Security Policy](../SECURITY.md)
---
## Support
For installation support:
- **Documentation**: Review all guides in [docs/guide/](guide/)
- **Issues**: Report problems at [GitHub Issues](https://github.com/[organization]/[repository]/issues)
- **Email**: support@mokoconsulting.tech
---
*Last Updated: [DATE]*
*Version: [VERSION]*
-25
View File
@@ -1,25 +0,0 @@
# Docs Index: /templates/docs
## Purpose
This index provides navigation to documentation within this folder.
## Subfolders
- [extra/](./extra/index.md)
- [required/](./required/index.md)
## Documents
- [README](./README.md)
## Metadata
- **Document Type:** index
- **Auto-generated:** This file is automatically generated by rebuild_indexes.py
## Revision History
| Change | Notes | Author |
| --- | --- | --- |
| Automated update | Generated by documentation index automation | rebuild_indexes.py |
+1 -1
View File
@@ -1,4 +1,4 @@
<!-- Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
This file is part of a Moko Consulting project.
+10 -33
View File
@@ -1,8 +1,7 @@
{
// The tab key will cycle through the settings when first created
// Sublime Text SFTP Plugin
// Visit https://codexns.io/products/sftp_for_subime/settings for help
// sftp, ftp or ftps
"type": "sftp",
"save_before_upload": true,
@@ -14,43 +13,21 @@
"confirm_sync": true,
"confirm_overwrite_newer": false,
"host": "example.com",
"user": "username",
"host": "dev.mokoconsulting.tech",
"user": "mokoconsulting_dev",
"port": "22",
//Default
//"port": "22",
"ssh_key_file": "C:/Users/jmill/OneDrive/Documents/Keys/repos/joomla-api-mcp",
//"password": "",
//Uncomment One:
//"ssh_key_file": "absolute/path/to/key/file",
//"password": "password",
"remote_path": "/example/path/",
"remote_path": "/home/mokoconsulting_dev/",
"ignore_regexes": [
"\\.sublime-(project|workspace|settings)", "\\.libsass.json/",
"sftp-config(-alt\\d?)?\\.json",
"sftp-config(-alt\\d?)?\\.json", "sftp-config.json.template",
"sftp-settings\\.json", "/venv/", "\\.svn/", "\\.hg/", "\\.git*",
"\\.bzr", "_darcs", "CVS", "\\.DS_Store", "Thumbs\\.db", "robots\\.txt",
"desktop\\.ini", "configuration\\.php",
"administrator/components/com_akeebabackup/backup", "\\.ffs*", "\\.md",
"\\.zip", "\\.editorconfig"
"desktop\\.ini", "\\.ffs*", "\\.editorconfig", "\\.md", "\\.zip", "docs/"
],
//"file_permissions": "664",
//"dir_permissions": "775",
//"extra_list_connections": 0,
"connect_timeout": 30,
//"keepalive": 120,
//"ftp_passive_mode": true,
//"ftp_obey_passive_host": false,
//"ssh_key_file": "~/.ssh/id_rsa",
//"sftp_sudo": false,
//"sftp_debug": false,
//"sftp_flags": ["-F", "/path/to/ssh_config"],
//"preserve_modification_times": false,
//"remote_time_offset_in_hours": 0,
//"remote_encoding": "utf-8",
//"remote_locale": "C",
//"allow_config_upload": false,
"connect_timeout": 30
}
+35
View File
@@ -0,0 +1,35 @@
{
"name": "@mokoconsulting/mcp-mokowaas-api",
"version": "1.0.0",
"description": "MCP server for Joomla Web Services API operations",
"type": "module",
"main": "dist/index.js",
"bin": {
"joomla-api-mcp": "dist/index.js"
},
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"start": "node dist/index.js",
"lint": "eslint src/",
"setup": "node scripts/setup.mjs",
"clean": "rm -rf dist/"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.12.1",
"zod": "^3.24.4"
},
"devDependencies": {
"@types/node": "^22.15.3",
"typescript": "^5.8.3"
},
"engines": {
"node": ">=20.0.0"
},
"license": "GPL-3.0-or-later",
"author": "Moko Consulting <hello@mokoconsulting.tech>",
"repository": {
"type": "git",
"url": "https://git.mokoconsulting.tech/MokoConsulting/mcp-mokowaas-api.git"
}
}
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env node
/* 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: joomla-api-mcp.Scripts
* INGROUP: joomla-api-mcp
* REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
* PATH: /scripts/setup.mjs
* VERSION: 00.00.01
* BRIEF: Interactive setup — prompts for Joomla API connection details and writes config
*/
import { createInterface } from 'node:readline/promises';
import { readFile, writeFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { homedir } from 'node:os';
const CONFIG_PATH = resolve(homedir(), '.joomla-api-mcp.json');
const rl = createInterface({ input: process.stdin, output: process.stdout });
async function prompt(question, defaultValue) {
const suffix = defaultValue ? ` [${defaultValue}]` : '';
const answer = await rl.question(`${question}${suffix}: `);
return answer.trim() || defaultValue || '';
}
async function promptRequired(question) {
let answer = '';
while (!answer) {
answer = (await rl.question(`${question}: `)).trim();
if (!answer) {
console.log(' This field is required.');
}
}
return answer;
}
async function main() {
console.log('');
console.log('=== joomla-api-mcp Setup ===');
console.log('');
console.log('This will create your configuration file at:');
console.log(` ${CONFIG_PATH}`);
console.log('');
// Check for existing config
let existing = null;
try {
const raw = await readFile(CONFIG_PATH, 'utf-8');
existing = JSON.parse(raw);
console.log('Existing config found. You can add a new connection or overwrite.');
console.log(` Current connections: ${Object.keys(existing.connections).join(', ')}`);
console.log('');
} catch {
// No existing config
}
const connectionName = await prompt('Connection name', 'production');
const baseUrl = await promptRequired('Joomla site URL (e.g. https://www.example.com)');
const apiToken = await promptRequired('Joomla API token');
const cleanUrl = baseUrl.replace(/\/+$/, '');
const insecureAnswer = await prompt('Skip TLS verification for self-signed certs? (y/N)', 'N');
const insecure = insecureAnswer.toLowerCase() === 'y';
const connection = { baseUrl: cleanUrl, apiToken };
if (insecure) {
connection.insecure = true;
}
let config;
if (existing) {
config = existing;
config.connections[connectionName] = connection;
const setDefault = await prompt(`Set "${connectionName}" as default connection? (y/N)`, 'N');
if (setDefault.toLowerCase() === 'y') {
config.defaultConnection = connectionName;
}
} else {
config = {
defaultConnection: connectionName,
connections: {
[connectionName]: connection,
},
};
}
await writeFile(CONFIG_PATH, JSON.stringify(config, null, '\t') + '\n', 'utf-8');
console.log('');
console.log(`Config written to ${CONFIG_PATH}`);
console.log(` Connection "${connectionName}" configured for ${cleanUrl}`);
console.log('');
const addAnother = await prompt('Add another connection? (y/N)', 'N');
if (addAnother.toLowerCase() === 'y') {
rl.close();
// Re-run to add another
const { execFileSync } = await import('node:child_process');
execFileSync('node', [new URL(import.meta.url).pathname], { stdio: 'inherit' });
return;
}
console.log('Setup complete. You can now use the MCP server.');
console.log('');
rl.close();
}
main().catch((err) => {
console.error(`Setup failed: ${err.message}`);
rl.close();
process.exit(1);
});
View File
+141
View File
@@ -0,0 +1,141 @@
/* 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: joomla-api-mcp.Client
* INGROUP: joomla-api-mcp
* REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
* PATH: /src/client.ts
* VERSION: 01.00.00
* BRIEF: HTTP client for Joomla Web Services API (v1)
*/
import * as https from 'node:https';
import * as http from 'node:http';
import type { JoomlaConnection, ApiResponse } from './types.js';
const API_PREFIX = '/api/index.php/v1';
const TIMEOUT_MS = 30_000;
export class JoomlaClient {
private readonly base_url: string;
private readonly headers: Record<string, string>;
private readonly insecure: boolean;
constructor(conn: JoomlaConnection) {
this.base_url = conn.baseUrl.replace(/\/+$/, '') + API_PREFIX;
this.headers = {
'Authorization': `Bearer ${conn.apiToken}`,
'Content-Type': 'application/json',
'Accept': 'application/vnd.api+json',
};
this.insecure = conn.insecure ?? false;
}
async get(endpoint: string, params?: Record<string, string>): Promise<ApiResponse> {
const url = this.buildUrl(endpoint, params);
return this.request(url, 'GET');
}
async post(endpoint: string, body?: unknown): Promise<ApiResponse> {
const url = this.buildUrl(endpoint);
return this.request(url, 'POST', body);
}
async patch(endpoint: string, body: unknown): Promise<ApiResponse> {
const url = this.buildUrl(endpoint);
return this.request(url, 'PATCH', body);
}
async delete(endpoint: string): Promise<ApiResponse> {
const url = this.buildUrl(endpoint);
return this.request(url, 'DELETE');
}
private buildUrl(endpoint: string, params?: Record<string, string>): string {
const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
const url = new URL(`${this.base_url}${path}`);
if (params) {
for (const [key, value] of Object.entries(params)) {
url.searchParams.set(key, value);
}
}
return url.toString();
}
private tryParseJson(raw: string): unknown | null {
// Try full string first
try { return JSON.parse(raw); } catch { /* fall through */ }
// Joomla may append HTML after JSON — find the last } or ] and try parsing up to that point
const trimmed = raw.trimStart();
if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) return null;
const closer = trimmed.startsWith('{') ? '}' : ']';
let idx = raw.lastIndexOf(closer);
while (idx > 0) {
try {
return JSON.parse(raw.substring(0, idx + 1));
} catch {
idx = raw.lastIndexOf(closer, idx - 1);
}
}
return null;
}
private request(url: string, method: string, body?: unknown): Promise<ApiResponse> {
return new Promise((resolve, reject) => {
const parsed = new URL(url);
const is_https = parsed.protocol === 'https:';
const transport = is_https ? https : http;
const options: https.RequestOptions = {
hostname: parsed.hostname,
port: parsed.port || (is_https ? 443 : 80),
path: parsed.pathname + parsed.search,
method,
headers: { ...this.headers },
timeout: TIMEOUT_MS,
};
if (this.insecure && is_https) {
options.rejectUnauthorized = false;
}
const payload = body !== undefined ? JSON.stringify(body) : undefined;
if (payload) {
(options.headers as Record<string, string>)['Content-Length'] = Buffer.byteLength(payload).toString();
}
const req = transport.request(options, (res) => {
const chunks: Buffer[] = [];
res.on('data', (chunk: Buffer) => chunks.push(chunk));
res.on('end', () => {
const raw = Buffer.concat(chunks).toString('utf-8');
let data: unknown;
// Joomla API may return JSON with text/html content-type,
// and may append HTML error fragments after valid JSON.
// Try to parse as JSON, trimming trailing non-JSON content.
data = this.tryParseJson(raw) ?? raw;
resolve({ status: res.statusCode ?? 0, data });
});
});
req.on('error', (err) => reject(err));
req.on('timeout', () => {
req.destroy();
reject(new Error('Request timed out'));
});
if (payload) {
req.write(payload);
}
req.end();
});
}
}
+58
View File
@@ -0,0 +1,58 @@
/* 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: joomla-api-mcp.Config
* INGROUP: joomla-api-mcp
* REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
* PATH: /src/config.ts
* VERSION: 01.00.00
* BRIEF: Configuration loader for Joomla API MCP connections
*/
import { readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { homedir } from 'node:os';
import type { JoomlaConfig, JoomlaConnection } from './types.js';
const CONFIG_FILENAME = '.mcp_mokowaas.json';
export async function loadConfig(): Promise<JoomlaConfig> {
const config_path = process.env.JOOMLA_API_MCP_CONFIG
? resolve(process.env.JOOMLA_API_MCP_CONFIG)
: resolve(homedir(), CONFIG_FILENAME);
try {
const raw = await readFile(config_path, 'utf-8');
const parsed = JSON.parse(raw) as Partial<JoomlaConfig>;
if (!parsed.connections || Object.keys(parsed.connections).length === 0) {
throw new Error('No connections defined in config');
}
return {
connections: parsed.connections,
defaultConnection: parsed.defaultConnection ?? Object.keys(parsed.connections)[0],
};
} catch (err) {
const message = err instanceof Error ? err.message : String(err);
throw new Error(
`Failed to load config from ${config_path}: ${message}\n` +
`Create ${config_path} — see config.example.json for format.`,
);
}
}
export function getConnection(config: JoomlaConfig, name?: string): JoomlaConnection {
const key = name ?? config.defaultConnection;
const conn = config.connections[key];
if (!conn) {
throw new Error(
`Connection "${key}" not found. Available: ${Object.keys(config.connections).join(', ')}`,
);
}
return conn;
}
-16
View File
@@ -1,16 +0,0 @@
# Docs Index: /templates/repos/generic/src
## Purpose
This index provides navigation to documentation within this folder.
## Metadata
- **Document Type:** index
- **Auto-generated:** This file is automatically generated by rebuild_indexes.py
## Revision History
| Change | Notes | Author |
| --- | --- | --- |
| Automated update | Generated by documentation index automation | rebuild_indexes.py |
+1314
View File
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
/* 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: joomla-api-mcp.Types
* INGROUP: joomla-api-mcp
* REPO: https://git.mokoconsulting.tech/MokoConsulting/joomla-api-mcp
* PATH: /src/types.ts
* VERSION: 01.00.00
* BRIEF: TypeScript type definitions for Joomla API MCP server
*/
export interface JoomlaConnection {
baseUrl: string;
apiToken: string;
/** Skip TLS certificate verification (self-signed certs) */
insecure?: boolean;
}
export interface JoomlaConfig {
connections: Record<string, JoomlaConnection>;
defaultConnection: string;
}
export interface ApiResponse {
status: number;
data: unknown;
errors?: Array<{ title: string; detail?: string }>;
}
+19
View File
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}