diff --git a/definitions/default/client-site.tf b/definitions/default/client.tf similarity index 99% rename from definitions/default/client-site.tf rename to definitions/default/client.tf index 5f29420..13435ba 100644 --- a/definitions/default/client-site.tf +++ b/definitions/default/client.tf @@ -13,7 +13,7 @@ locals { metadata = { name = "Client Joomla Site" description = "Standard repository structure for client Joomla site projects (overrides, media, configuration)" - repository_type = "client-site" + repository_type = "client" platform = "mokowaas" last_updated = "2026-05-04T00:00:00Z" maintainer = "Moko Consulting" diff --git a/definitions/default/crm-module.tf b/definitions/default/dolibarr.tf similarity index 99% rename from definitions/default/crm-module.tf rename to definitions/default/dolibarr.tf index e34ddd9..c560824 100644 --- a/definitions/default/crm-module.tf +++ b/definitions/default/dolibarr.tf @@ -13,7 +13,7 @@ locals { metadata = { name = "MokoCRM Module" description = "Standard repository structure for MokoCRM (Dolibarr) modules" - repository_type = "crm-module" + repository_type = "dolibarr" platform = "dolibarr" last_updated = "2026-01-07T00:00:00Z" maintainer = "Moko Consulting" diff --git a/definitions/default/generic-repository.tf b/definitions/default/generic-repository.tf deleted file mode 100644 index 0d36b5f..0000000 --- a/definitions/default/generic-repository.tf +++ /dev/null @@ -1,1166 +0,0 @@ -/** - * Generic Repository Structure Definition - * Standard repository structure for generic projects and libraries - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Version: 04.05.00 - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Generic Repository" - description = "Standard repository structure for generic projects and libraries" - repository_type = "library" - platform = "multi-platform" - last_updated = "2026-01-15T00:00:00Z" - maintainer = "Moko Consulting" - version = "04.05.00" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Project overview and documentation" - required = true - always_overwrite = false - protected = true - audience = "general" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later)" - required = true - audience = "general" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - audience = "contributor" - }, - { - name = "ROADMAP.md" - extension = "md" - description = "Project roadmap with version goals and milestones" - required = false - audience = "general" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns - preserved during sync operations" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.generic" - }, - { - name = ".gitattributes" - extension = "gitattributes" - description = "Git attributes configuration" - required = true - audience = "developer" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style - preserved during sync" - required = true - always_overwrite = false - audience = "developer" - }, - { - name = "Makefile" - description = "Build automation" - requirement_status = "suggested" - audience = "developer" - }, - { - name = "composer.json" - extension = "json" - description = "Composer manifest โ€” requires mokoconsulting-tech/enterprise for CLI scripts and tooling" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/composer.generic.json" - }, - { - name = ".gitea/.mokostandards" - extension = "xml" - description = "MokoStandards XML manifest โ€” generated programmatically by RepositorySynchronizer::migrateMokoStandards()" - required = true - always_overwrite = false - audience = "developer" - template = "managed-by-sync" - source_type = "programmatic" - }, - { - name = "GOVERNANCE.md" - extension = "md" - description = "Project governance rules, roles, and decision process โ€” auto-maintained by MokoStandards" - required = true - always_overwrite = false - protected = true - audience = "all" - template = "templates/docs/required/GOVERNANCE.md" - } - ] - - directories = [ - { - name = "src" - path = "src" - description = "Source code" - requirement_status = "suggested" - purpose = "Contains application/library source code" - }, - { - name = "docs" - path = "docs" - description = "Documentation" - required = true - purpose = "Contains comprehensive documentation" - files = [ - { - name = "index.md" - extension = "md" - description = "Documentation index" - requirement_status = "suggested" - } - ] - }, - { - name = "scripts" - path = "scripts" - description = "Repo-specific scripts โ€” not managed by MokoStandards sync" - required = false - purpose = "Optional directory for repo-specific build helpers and one-off scripts. MokoStandards tools are installed via Composer (mokoconsulting-tech/enterprise) and called through vendor/bin/." - files = [ - { - name = "MokoStandards.override.xml" - extension = "xml" - description = "MokoStandards sync override configuration - preserved during sync" - requirement_status = "optional" - always_overwrite = false - audience = "developer" - } - ] - }, - { - name = "tests" - path = "tests" - description = "Test files" - requirement_status = "suggested" - purpose = "Contains unit tests, integration tests, and test fixtures" - }, - { - name = ".github" - path = ".github" - description = "GitHub-specific configuration" - requirement_status = "suggested" - purpose = "Contains GitHub Actions workflows and configuration" - files = [ - { - name = "copilot.yml" - extension = "yml" - description = "GitHub Copilot allowed domains configuration" - requirement_status = "required" - always_overwrite = true - template = ".github/copilot.yml" - }, - { - name = "copilot-instructions.md" - extension = "md" - description = "GitHub Copilot custom instructions enforcing MokoStandards" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "copilot-instructions.md" - template = "templates/github/copilot-instructions.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{PRIMARY_LANGUAGE}}` | The dominant programming language (check file extensions in the repository) | - > | `{{PLATFORM_TYPE}}` | The project type: `PHP library`, `Joomla extension`, `Dolibarr module`, `WaaS site`, etc. โ€” infer from repo structure | - > - > --- - - # {{REPO_NAME}} โ€” 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: {{REPO_URL}} - Primary language: **{{PRIMARY_LANGUAGE}}** - Platform type: **{{PLATFORM_TYPE}}** - - --- - - ## Primary Language - - **{{PRIMARY_LANGUAGE}} 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 - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /path/to/file.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of purpose - */ - - declare(strict_types=1); - ``` - - **Markdown:** - ```markdown - - ``` - - **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@v4 - 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 - 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: `(): ` โ€” 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 - - Format: `/[/description]` - - Approved prefixes: `dev/` ยท `rc/` ยท `version/` ยท `patch/` ยท `copilot/` ยท `dependabot/` - - - โœ… `dev/1.2.0/add-feature` - - โœ… `patch/1.2.1/fix-bug` - - โŒ `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/.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 | - MOKO_END - }, - { - name = "CLAUDE.md" - extension = "md" - description = "Claude AI assistant context enforcing MokoStandards" - requirement_status = "required" - always_overwrite = false - destination_path = ".github" - destination_filename = "CLAUDE.md" - template = "templates/github/CLAUDE.md.template" - stub_content = <<-MOKO_END - > [!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 | - > |---|---| - > | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) | - > | `{{REPO_URL}}` | Full GitHub URL, e.g. `https://github.com/mokoconsulting-tech/` | - > | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description | - > | `{{PRIMARY_LANGUAGE}}` | The dominant programming language (check file extensions in the repository) | - > | `{{PLATFORM_TYPE}}` | The project type: `PHP library`, `Joomla extension`, `Dolibarr module`, `WaaS site`, etc. โ€” infer from repo structure | - > - > --- - - # What This Repo Is - - **{{REPO_NAME}}** is a Moko Consulting **{{PLATFORM_TYPE}}** repository. - - {{REPO_DESCRIPTION}} - - Repository URL: {{REPO_URL}} - - This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards) โ€” the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories. - - --- - - # Repo Structure - - ``` - {{REPO_NAME}}/ - โ”œโ”€โ”€ src/ # Primary source code - โ”œโ”€โ”€ docs/ # Documentation - โ”œโ”€โ”€ tests/ # Test suite - โ”œโ”€โ”€ .github/ - โ”‚ โ”œโ”€โ”€ workflows/ # CI/CD workflows (synced from MokoStandards) - โ”‚ โ”œโ”€โ”€ ISSUE_TEMPLATE/ # Issue templates (inherited from mokoconsulting-tech/.github-private) - โ”‚ โ”œโ”€โ”€ copilot-instructions.md # GitHub Copilot custom instructions - โ”‚ โ”œโ”€โ”€ CLAUDE.md # This file โ€” Claude AI assistant context - โ”‚ โ””โ”€โ”€ override.tf # Repository-specific health-check overrides - โ”œโ”€โ”€ README.md # Project overview โ€” version source of truth - โ”œโ”€โ”€ CHANGELOG.md # Version history - โ”œโ”€โ”€ CONTRIBUTING.md # Contribution guidelines - โ””โ”€โ”€ LICENSE # GPL-3.0-or-later - ``` - - --- - - # Primary Language - - **{{PRIMARY_LANGUAGE}}** is the primary language for this repository. - - YAML uses 2-space indentation (spaces, not tabs). All other text files use tabs per `.editorconfig`. - - --- - - # Composer Package (PHP repositories) - - This repository requires the MokoStandards enterprise library. The package is installed from the private GitHub VCS source. - - `composer.json` must contain: - - ```json - { - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/mokoconsulting-tech/MokoStandards" - } - ], - "require": { - "mokoconsulting/mokostandards": "^4.0" - } - } - ``` - - Install or update with: - - ```bash - composer install # first time - composer update mokoconsulting/mokostandards # upgrade - ``` - - --- - - # PHP Script Pattern - - All PHP scripts must extend `MokoStandards\Enterprise\CliFramework` โ€” **never** use a standalone class or the legacy `CliBase`. - - ```php - #!/usr/bin/env php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Scripts - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /api/my_script.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of what this script does - */ - - 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 of what this script does'); - $this->addArgument('--path', 'Repository root path', '.'); - $this->addArgument('--dry-run', 'Preview changes without writing', false); - } - - protected function run(): int - { - $path = $this->getArgument('--path'); - $dryRun = (bool) $this->getArgument('--dry-run'); - - // implementation โ€ฆ - $this->log('INFO', "Processing: {$path}"); - - return 0; - } - } - - $script = new MyScript('my_script', 'One-line description of what this script does'); - exit($script->execute()); - ``` - - **CliFramework interface summary:** - - | Member | Purpose | - |--------|---------| - | `configure(): void` | Abstract โ€” register arguments with `addArgument()` | - | `run(): int` | Abstract โ€” main script logic; return the exit code | - | `initialize(): void` | Optional hook โ€” runs after arg-parse, before `run()` | - | `execute(array $argv = []): int` | **Public entry point** โ€” call this at the bottom; it calls `configure()`, parses argv, then calls `run()` | - | `addArgument(string $name, string $desc, mixed $default)` | Register a CLI argument | - | `getArgument(string $name): mixed` | Read a parsed or default argument value | - | `log(string $level, string $message)` | Structured log โ€” levels: INFO SUCCESS WARNING ERROR DEBUG | - | `error(string $message, int $code = 1): never` | Log error and exit | - | `$this->dryRun` | `true` when `--dry-run` is passed | - | `$this->verbose` | `true` when `--verbose` / `-v` is passed | - - **Forbidden patterns in PHP:** - - ```php - // โŒ Wrong โ€” legacy base class, not namespaced - class MyScript extends CliBase { โ€ฆ } - - // โŒ Wrong โ€” standalone class with no framework - class MyScript { public function run() { โ€ฆ } } - - // โŒ Wrong โ€” method names and entry-point transposed - protected function execute(): int { โ€ฆ } // should be run() - exit($script->run()); // should be execute() - - // โœ… Correct - class MyScript extends CliFramework { - protected function configure(): void { โ€ฆ } - protected function run(): int { โ€ฆ } - } - $script = new MyScript('name', 'description'); - exit($script->execute()); - ``` - - --- - - # 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 to all badges and `FILE INFORMATION` headers automatically on merge to `main`. - - The `VERSION: XX.YY.ZZ` field in the `README.md` `FILE INFORMATION` block governs all other version references. - - Update `README.md` only โ€” the `sync-version-on-merge` workflow propagates it to all badges and `FILE INFORMATION` headers automatically on merge to `main`. - - Version format is zero-padded semver: `XX.YY.ZZ` (e.g. `01.02.03`). - - Never hardcode a version number in body text โ€” use the badge or FILE INFORMATION header only. - - --- - - # File Header Requirements - - Every new file **must** have a copyright header as its first content. JSON files, binary files, generated files, and third-party files are exempt. - - ## Minimal header - - **PHP:** - ```php - - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * FILE INFORMATION - * DEFGROUP: {{REPO_NAME}}.Module - * INGROUP: {{REPO_NAME}} - * REPO: {{REPO_URL}} - * PATH: /src/MyClass.php - * VERSION: XX.YY.ZZ - * BRIEF: One-line description of file purpose - */ - - declare(strict_types=1); - ``` - - **Markdown:** - ```markdown - - ``` - - **YAML / Shell:** Use `#` comments with the same fields. JSON files are exempt. - - --- - - # Coding Standards - - ## Naming Conventions - - | Context | Convention | Example | - |---------|-----------|---------| - | PHP class | `PascalCase` | `MyService` | - | PHP method / function | `camelCase` | `getUserData()` | - | PHP variable | `$snake_case` | `$user_id` | - | PHP constant | `UPPER_SNAKE_CASE` | `MAX_RETRIES` | - | PHP class file | `PascalCase.php` | `UserService.php` | - | PHP script file | `snake_case.php` | `check_health.php` | - | YAML workflow | `kebab-case.yml` | `code-quality.yml` | - | Markdown doc | `kebab-case.md` | `coding-style-guide.md` | - - ## Commit Messages - - Format: `(): ` โ€” imperative, lower-case subject, no trailing period. - - Valid types: `feat` ยท `fix` ยท `docs` ยท `chore` ยท `ci` ยท `refactor` ยท `style` ยท `test` ยท `perf` ยท `revert` ยท `build` - - ## Branch Naming - - Format: `/[/description]` - - Approved prefixes: `dev/` ยท `rc/` ยท `version/` ยท `patch/` ยท `copilot/` ยท `dependabot/` - - --- - - # GitHub Actions โ€” Token Usage - - Every workflow in this repository must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token). - - ```yaml - # โœ… Correct โ€” always use GH_TOKEN - - uses: actions/checkout@v4 - with: - token: ${{ secrets.GH_TOKEN }} - - env: - GH_TOKEN: ${{ secrets.GH_TOKEN }} - ``` - - ```yaml - # โŒ Wrong โ€” never use these - 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 a local-dev fallback only. - - --- - - # 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/.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. - - --- - - # What NOT to Do - - - **Never commit directly to `main`** โ€” all changes go through a PR. - - **Never hardcode version numbers** in body text โ€” update `README.md` and let automation propagate. - - **Never skip the FILE INFORMATION block** on a new source file. - - **Never use bare `catch (\Throwable $e) {}`** โ€” always log or re-throw. - - **Never mix tabs and spaces** within a file โ€” follow `.editorconfig`. - - **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` instead. - - **Never use `exit($script->run())`** โ€” the correct entry point is `exit($script->execute())`. - - --- - - # Key Policy Documents (MokoStandards) - - | 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 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 | - MOKO_END - } - ] - subdirectories = [ - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows" - requirement_status = "suggested" - files = [ - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/generic/codeql-analysis.yml.template" - } - ] - }, - { - name = "ISSUE_TEMPLATE" - path = ".github/ISSUE_TEMPLATE" - description = "GitHub issue templates synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "config.yml" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/config.yml" - }, - { - name = "adr.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/adr.md" - }, - { - name = "bug_report.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/bug_report.md" - }, - { - name = "documentation.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/documentation.md" - }, - { - name = "enterprise_support.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/enterprise_support.md" - }, - { - name = "feature_request.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/feature_request.md" - }, - { - name = "firewall-request.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/firewall-request.md" - }, - { - name = "question.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/question.md" - }, - { - name = "request-license.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/request-license.md" - }, - { - name = "rfc.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/rfc.md" - }, - { - name = "security.md" - always_overwrite = true - template = "templates/github/ISSUE_TEMPLATE/security.md" - } - ] - } - ] - }, - { - name = "workflows" - path = ".github/workflows" - description = "GitHub Actions workflows synced from MokoStandards" - requirement_status = "required" - files = [ - { - name = "standards-compliance.yml" - extension = "yml" - description = "MokoStandards compliance validation" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/standards-compliance.yml" - }, - { - name = "codeql-analysis.yml" - extension = "yml" - description = "CodeQL security analysis workflow" - requirement_status = "required" - always_overwrite = true - template = ".github/workflows/codeql-analysis.yml" - }, - { - name = "enterprise-firewall-setup.yml" - extension = "yml" - description = "Enterprise firewall configuration for trusted domain access" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/enterprise-firewall-setup.yml.template" - }, - { - name = "deploy-dev.yml" - extension = "yml" - description = "SFTP deployment of src/ to the development server" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-dev.yml.template" - }, - { - name = "deploy-demo.yml" - extension = "yml" - description = "SFTP deployment of src/ to the demo server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-demo.yml.template" - }, - { - name = "deploy-rs.yml" - extension = "yml" - description = "SFTP deployment of src/ to the release staging server on merge to main" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/deploy-rs.yml.template" - }, - { - name = "sync-version-on-merge.yml" - extension = "yml" - description = "Auto-bump patch version on merge and propagate to all file headers" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/sync-version-on-merge.yml.template" - }, - { - name = "auto-release.yml" - extension = "yml" - description = "Auto-create GitHub Release on push to main with version from README.md" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-release.yml.template" - }, - { - name = "repository-cleanup.yml" - extension = "yml" - description = "Scheduled cleanup: delete retired workflows, stale branches, old workflow runs" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/repository-cleanup.yml.template" - }, - { - name = "auto-dev-issue.yml" - extension = "yml" - description = "Auto-create tracking issue when a dev/** branch is pushed" - requirement_status = "required" - always_overwrite = true - template = "templates/workflows/shared/auto-dev-issue.yml.template" - } - ] - } - ] - - repository_requirements = { - secrets = [ - { - name = "GH_TOKEN" - description = "Org-level GitHub PAT for automation" - required = true - scope = "org" - }, - { - name = "DEV_FTP_KEY" - description = "SSH private key for SFTP dev deployment (preferred); if DEV_FTP_PASSWORD is also set it is used as the key passphrase, with password-only as fallback" - required = false - scope = "org" - }, - { - name = "DEV_FTP_PASSWORD" - description = "SFTP password for dev deployment; used as SSH key passphrase when DEV_FTP_KEY is also set, and as standalone fallback if key auth fails" - required = false - scope = "org" - note = "At least one of DEV_FTP_KEY or DEV_FTP_PASSWORD must be configured" - } - ] - - variables = [ - { - name = "DEV_FTP_HOST" - description = "Dev server hostname; may include port suffix (e.g. dev.example.com or dev.example.com:2222)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PATH" - description = "Base remote path for SFTP deployment (e.g. /var/www/html)" - required = true - scope = "org" - }, - { - name = "DEV_FTP_USERNAME" - description = "SFTP username for dev server authentication" - required = true - scope = "org" - }, - { - name = "DEV_FTP_PORT" - description = "Explicit SFTP port override; if omitted the port is parsed from DEV_FTP_HOST or defaults to 22" - required = false - scope = "org" - }, - { - name = "DEV_FTP_SUFFIX" - description = "Per-repo path suffix appended to DEV_FTP_PATH (e.g. /my-project)" - required = false - scope = "repo" - } - ] - } - } -} diff --git a/definitions/default/default-repository.tf b/definitions/default/generic.tf similarity index 100% rename from definitions/default/default-repository.tf rename to definitions/default/generic.tf diff --git a/definitions/default/joomla-template.tf b/definitions/default/joomla-template.tf deleted file mode 100644 index ca08e68..0000000 --- a/definitions/default/joomla-template.tf +++ /dev/null @@ -1,499 +0,0 @@ -/** - * MokoWaaS Joomla Template Structure Definition - * Standard repository structure for Joomla template projects - * - * Copyright (C) 2026 Moko Consulting - * SPDX-License-Identifier: GPL-3.0-or-later - * Version: 04.06.10 - * Schema Version: 1.0 - */ - -locals { - repository_structure = { - metadata = { - name = "Joomla Template" - description = "Standard repository structure for Joomla templates (site or administrator)" - repository_type = "joomla-template" - platform = "mokowaas" - last_updated = "2026-04-14T00:00:00Z" - maintainer = "Moko Consulting" - version = "04.06.10" - schema_version = "1.0" - } - - root_files = [ - { - name = "README.md" - extension = "md" - description = "Developer-focused documentation for contributors and maintainers" - required = true - always_overwrite = false - protected = true - audience = "developer" - }, - { - name = "LICENSE" - extension = "" - description = "License file (GPL-3.0-or-later) - Default for Joomla templates" - required = true - audience = "general" - template = "templates/licenses/GPL-3.0" - license_type = "GPL-3.0-or-later" - }, - { - name = "CHANGELOG.md" - extension = "md" - description = "Version history and changes" - required = true - audience = "general" - }, - { - name = "SECURITY.md" - extension = "md" - description = "Security policy and vulnerability reporting" - required = true - always_overwrite = true - template = "templates/docs/required/template-SECURITY.md" - audience = "general" - }, - { - name = "CODE_OF_CONDUCT.md" - extension = "md" - description = "Community code of conduct" - required = true - always_overwrite = true - template = "templates/docs/extra/template-CODE_OF_CONDUCT.md" - audience = "contributor" - }, - { - name = "CONTRIBUTING.md" - extension = "md" - description = "Contribution guidelines" - required = true - always_overwrite = true - template = "templates/docs/required/template-CONTRIBUTING.md" - audience = "contributor" - }, - { - name = "templateDetails.xml" - extension = "xml" - description = "Joomla template manifest โ€” declares template metadata, positions, styles, and dependencies" - required = true - always_overwrite = false - audience = "developer" - stub_content = <<-MOKO_END - - - {{TEMPLATE_NAME}} - {{CREATION_DATE}} - Moko Consulting - hello@mokoconsulting.tech - https://mokoconsulting.tech - Copyright (C) 2026 Moko Consulting. All rights reserved. - GPL-3.0-or-later - {{VERSION}} - {{REPO_DESCRIPTION}} - - - index.php - component.php - error.php - offline.php - templateDetails.xml - html - css - js - images - language - - - - css - js - images - scss - - - - topbar - navbar - hero - breadcrumbs - sidebar-left - sidebar-right - main-top - main-bottom - footer - debug - - - - - https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/raw/branch/main/updates.xml - - - https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/main/updates.xml - - - - - -
- - - - - - - - -
-
- - - - -
-
-
-
- MOKO_END - }, - { - name = "updates.xml" - extension = "xml" - description = "Joomla template update server manifest โ€” polled by Joomla for new versions (dual-platform: Gitea priority 1, GitHub priority 2)" - required = true - always_overwrite = false - audience = "developer" - stub_content = <<-MOKO_END - - - {{TEMPLATE_NAME}} - {{REPO_DESCRIPTION}} - tpl_{{TEMPLATE_SHORT_NAME}} - template - {{VERSION}} - - - https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{TEMPLATE_SHORT_NAME}}.zip - - - https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{TEMPLATE_SHORT_NAME}}.zip - - - - 8.1 - - - MOKO_END - }, - { - name = "phpstan.neon" - extension = "neon" - description = "PHPStan static analysis config with Joomla framework class stubs" - required = true - always_overwrite = true - audience = "developer" - template = "templates/configs/phpstan.joomla.neon" - }, - { - name = "Makefile" - description = "Build automation for Joomla template packaging" - required = true - always_overwrite = true - audience = "developer" - template = "templates/makefiles/Makefile.joomla.template" - }, - { - name = ".gitignore" - extension = "gitignore" - description = "Git ignore patterns for Joomla template development" - required = true - always_overwrite = false - audience = "developer" - template = "templates/configs/.gitignore.joomla" - }, - { - name = ".editorconfig" - extension = "editorconfig" - description = "Editor configuration for consistent coding style" - required = true - always_overwrite = true - template = "templates/configs/.editorconfig" - audience = "developer" - }, - { - name = ".ftpignore" - extension = "ftpignore" - description = "FTP/SFTP ignore patterns for deploy-joomla.php" - required = false - always_overwrite = false - audience = "developer" - }, - ] - - subdirectories = [ - { - name = "src" - description = "Template source files โ€” maps to templates/{name}/ on the Joomla server" - required = true - files = [ - { - name = "index.php" - description = "Main template entry point" - required = true - always_overwrite = false - stub_content = <<-MOKO_END - getWebAssetManager(); - $doc = $app->getDocument(); - $lang = $app->getLanguage(); - - // Load template CSS/JS via Web Asset Manager - $wa->useStyle('template.{{TEMPLATE_SHORT_NAME}}.css'); - $wa->useScript('template.{{TEMPLATE_SHORT_NAME}}.js'); - - ?> - - - - - - - - -
- - -
- - - - -
- - - - -
- -
- -
- - - - - MOKO_END - }, - { - name = "error.php" - description = "Error page template (404, 500, etc.)" - required = true - always_overwrite = false - }, - { - name = "offline.php" - description = "Offline page template shown when site is in maintenance mode" - required = true - always_overwrite = false - }, - { - name = "component.php" - description = "Component-only template (print view / raw output)" - required = false - always_overwrite = false - }, - ] - }, - { - name = "src/html" - description = "Template overrides for Joomla component/module views" - required = true - files = [ - { - name = "index.html" - description = "Prevents directory listing" - required = true - always_overwrite = true - stub_content = "" - }, - ] - }, - { - name = "src/css" - description = "Compiled CSS files" - required = true - files = [] - }, - { - name = "src/js" - description = "JavaScript files" - required = true - files = [] - }, - { - name = "src/images" - description = "Template images and icons" - required = true - files = [ - { - name = "template_preview.png" - description = "Template preview screenshot shown in Joomla admin" - required = false - always_overwrite = false - }, - { - name = "template_thumbnail.png" - description = "Template thumbnail shown in template list" - required = false - always_overwrite = false - }, - ] - }, - { - name = "src/language/en-GB" - description = "English language files for the template" - required = true - files = [ - { - name = "tpl_{{TEMPLATE_SHORT_NAME}}.ini" - description = "Main language strings" - required = true - always_overwrite = false - }, - { - name = "tpl_{{TEMPLATE_SHORT_NAME}}.sys.ini" - description = "System language strings (used in admin template manager)" - required = true - always_overwrite = false - }, - ] - }, - { - name = "media" - description = "Template media files โ€” maps to media/templates/site/{name}/ on the Joomla server" - required = true - files = [] - }, - { - name = "media/css" - description = "Compiled CSS assets served from /media/" - required = true - files = [] - }, - { - name = "media/js" - description = "JavaScript assets served from /media/" - required = true - files = [] - }, - { - name = "media/images" - description = "Image assets served from /media/" - required = true - files = [] - }, - { - name = "media/scss" - description = "SCSS source files (compiled to media/css/)" - required = false - files = [] - }, - { - name = ".gitea/workflows" - description = "Gitea Actions CI/CD workflows" - required = true - files = [ - { - name = "auto-release.yml" - description = "Automated release โ€” builds zip, creates Gitea release, updates SHA in updates.xml. Triggered by push to main (stable) or pre-release tags (development, alpha, beta, rc)" - required = true - always_overwrite = true - template = "workflows/auto-release.yml" - }, - { - name = "ci-joomla.yml" - description = "Continuous integration โ€” PHP linting, PHPStan static analysis, coding standards checks" - required = true - always_overwrite = true - template = "workflows/ci-joomla.yml" - }, - { - name = "pre-release.yml" - description = "Manual pre-release โ€” builds dev/alpha/beta/rc packages with patch version bump" - required = true - always_overwrite = true - template = "workflows/pre-release.yml" - }, - { - name = "deploy-manual.yml" - description = "Manual deployment โ€” allows selecting target environment and branch for on-demand deploys" - required = true - always_overwrite = true - template = "workflows/deploy-manual.yml" - }, - { - name = "repo-health.yml" - description = "Repository health checks โ€” validates required files, structure compliance, and standards alignment" - required = true - always_overwrite = true - template = "workflows/repo-health.yml" - }, - { - name = "update-server.yml" - description = "Update server maintenance โ€” validates updates.xml format and ensures download URLs are reachable" - required = true - always_overwrite = true - template = "workflows/update-server.yml" - }, - { - name = "pr-check.yml" - description = "PR gate โ€” validates PHP syntax, manifest XML, and package build before merge to main" - required = true - always_overwrite = true - template = "workflows/pr-check.yml" - }, - { - name = "security-audit.yml" - description = "Dependency vulnerability scanning โ€” weekly schedule and on PR when lock files change" - required = true - always_overwrite = true - template = "workflows/security-audit.yml" - }, - { - name = "notify.yml" - description = "Push notifications via ntfy on release success or workflow failure" - required = true - always_overwrite = true - template = "workflows/notify.yml" - }, - { - name = "cleanup.yml" - description = "Scheduled cleanup โ€” delete merged branches and old workflow runs weekly" - required = true - always_overwrite = true - template = "workflows/cleanup.yml" - }, - ] - }, - ] - } -} diff --git a/definitions/default/waas-component.tf b/definitions/default/joomla.tf similarity index 99% rename from definitions/default/waas-component.tf rename to definitions/default/joomla.tf index 7756ec2..0a22e9b 100644 --- a/definitions/default/waas-component.tf +++ b/definitions/default/joomla.tf @@ -13,7 +13,7 @@ locals { metadata = { name = "MokoWaaS Component" description = "Standard repository structure for MokoWaaS (Joomla) components" - repository_type = "waas-component" + repository_type = "joomla" platform = "mokowaas" last_updated = "2026-01-15T00:00:00Z" maintainer = "Moko Consulting" diff --git a/definitions/default/crm-platform.tf b/definitions/default/platform.tf similarity index 99% rename from definitions/default/crm-platform.tf rename to definitions/default/platform.tf index 3e8a962..8212f00 100644 --- a/definitions/default/crm-platform.tf +++ b/definitions/default/platform.tf @@ -2,7 +2,7 @@ * Dolibarr Platform Structure Definition * Standard repository structure for the full Dolibarr ERP/CRM installation * - * This is distinct from crm-module โ€” it defines the ENTIRE Dolibarr platform + * This is distinct from dolibarr โ€” it defines the ENTIRE Dolibarr platform * (htdocs/, not src/). It does NOT have a module descriptor, numero, or * publish-to-mokodolimods workflow. * @@ -17,7 +17,7 @@ locals { metadata = { name = "Dolibarr Platform" description = "Full Dolibarr ERP/CRM installation โ€” htdocs/ root, not a module" - repository_type = "crm-platform" + repository_type = "platform" platform = "dolibarr" last_updated = "2026-03-31T00:00:00Z" maintainer = "Moko Consulting" diff --git a/definitions/default/standards-repository.tf b/definitions/default/standards.tf similarity index 100% rename from definitions/default/standards-repository.tf rename to definitions/default/standards.tf diff --git a/docs/WORKFLOW_STANDARDS.md b/docs/WORKFLOW_STANDARDS.md index 3f4fec1..0c8532b 100644 --- a/docs/WORKFLOW_STANDARDS.md +++ b/docs/WORKFLOW_STANDARDS.md @@ -176,5 +176,5 @@ done | 2026-05-02 | Release naming: includes extension element name (e.g. "mokodpcalendarapi 03.00.00 (stable)") | | 2026-05-02 | Stable releases overwrite (not append) | | 2026-05-04 | Removed updates.xml + update-server.yml from client repos (sites, not extensions) | -| 2026-05-04 | Added client-site.tf definition in MokoStandards-API | +| 2026-05-04 | Added client.tf definition in MokoStandards-API | | 2026-05-05 | Version policy: stable=minor bump, pre-release=patch bump (was major/patch) | diff --git a/lib/Enterprise/RepositorySynchronizer.php b/lib/Enterprise/RepositorySynchronizer.php index 38f7721..fff5d22 100644 --- a/lib/Enterprise/RepositorySynchronizer.php +++ b/lib/Enterprise/RepositorySynchronizer.php @@ -275,7 +275,7 @@ class RepositorySynchronizer * * @param string $org * @param string $repo - * @param string $platform Detected platform slug (e.g. 'crm-module') + * @param string $platform Detected platform slug (e.g. 'dolibarr') * @param array $repoInfo Raw GitHub API repository object * @param array $summary Sync result from createSyncPR: {copied[], skipped[], total} * @return bool @@ -298,7 +298,7 @@ class RepositorySynchronizer $repoRoot = dirname(dirname(__DIR__)); $baseDefPath = "{$repoRoot}/definitions/default/{$platform}.tf"; if (!file_exists($baseDefPath)) { - $baseDefPath = "{$repoRoot}/definitions/default/default-repository.tf"; + $baseDefPath = "{$repoRoot}/definitions/default/generic.tf"; } $baseDefinition = file_get_contents($baseDefPath) ?: ''; @@ -469,48 +469,48 @@ HCL; // Explicit platform repos โ€” full Dolibarr installation, not a module if (in_array($name, self::CRM_PLATFORM_REPOS, true)) { - return 'crm-platform'; + return 'platform'; } if (in_array('dolibarr-platform', $topics)) { - return 'crm-platform'; + return 'platform'; } // Check topics first โ€” templates before generic joomla - if (in_array('joomla-template', $topics)) { - return 'joomla-template'; + if (in_array('joomla', $topics)) { + return 'joomla'; } if (in_array('joomla', $topics) || in_array('joomla-extension', $topics)) { - return 'waas-component'; + return 'joomla'; } if (in_array('dolibarr', $topics) || in_array('dolibarr-module', $topics)) { - return 'crm-module'; + return 'dolibarr'; } // Check name patterns โ€” templates before generic joomla if (str_contains($nameLower, 'template') && (str_contains($nameLower, 'joomla') || str_contains($nameLower, 'tpl'))) { - return 'joomla-template'; + return 'joomla'; } if (str_contains($nameLower, 'joomla') || str_contains($nameLower, 'waas')) { - return 'waas-component'; + return 'joomla'; } if (str_contains($nameLower, 'doli') || str_contains($nameLower, 'crm')) { - return 'crm-module'; + return 'dolibarr'; } // Check description patterns if (str_contains($description, 'joomla template') || str_contains($description, 'joomla 5 template') || str_contains($description, 'joomla 4 template')) { - return 'joomla-template'; + return 'joomla'; } if (str_contains($description, 'joomla') || str_contains($description, 'component')) { - return 'waas-component'; + return 'joomla'; } if (str_contains($description, 'dolibarr') || str_contains($description, 'module')) { - return 'crm-module'; + return 'dolibarr'; } // Default - return 'default-repository'; + return 'generic'; } /** @@ -518,7 +518,7 @@ HCL; * * @param string $org * @param string $repo - * @param string $platform Detected platform slug (e.g. 'crm-module') + * @param string $platform Detected platform slug (e.g. 'dolibarr') * @param array $filesToSync * @param string $repoRoot Absolute path to the MokoStandards repository root * @param bool $force When true, overwrite files even when always_overwrite = false @@ -608,7 +608,7 @@ HCL; * {{PRIMARY_LANGUAGE}} โ€” dominant language from GitHub * {{PLATFORM_TYPE}} โ€” human-readable platform label * - * Dolibarr-specific tokens (crm-module platform only): + * Dolibarr-specific tokens (dolibarr platform only): * {{MODULE_NAME}} โ€” lowercase module name (e.g. mokocrm) * {{MODULE_CLASS}} โ€” PascalCase class name (e.g. MokoCRM) * {{MODULE_ID}} โ€” $this->numero from descriptor (null โ†’ left unreplaced) @@ -1059,8 +1059,8 @@ HCL; // Determine which template repo to source from $templateType = match (true) { - in_array($platform, ['crm-module', 'crm-platform']) => 'dolibarr', - in_array($platform, ['waas-component', 'joomla-template']) => 'joomla', + in_array($platform, ['dolibarr', 'platform']) => 'dolibarr', + in_array($platform, ['joomla', 'joomla']) => 'joomla', str_starts_with($platform, 'client') => 'client', default => 'generic', }; @@ -1096,10 +1096,10 @@ HCL; // Platform-specific gitignore (merged, not replaced) $gitignoreMap = [ - 'crm-module' => 'templates/configs/gitignore.dolibarr', - 'crm-platform' => 'templates/configs/gitignore.dolibarr', - 'waas-component' => 'templates/configs/.gitignore.joomla', - 'joomla-template' => 'templates/configs/.gitignore.joomla', + 'dolibarr' => 'templates/configs/gitignore.dolibarr', + 'platform' => 'templates/configs/gitignore.dolibarr', + 'joomla' => 'templates/configs/.gitignore.joomla', + 'joomla' => 'templates/configs/.gitignore.joomla', ]; $gitignoreTemplate = $gitignoreMap[$platform] ?? 'templates/configs/gitignore'; $shared[] = [$gitignoreTemplate, '.gitignore']; @@ -1135,7 +1135,7 @@ HCL; } // Create update.txt stub for Dolibarr repos (plain text version file) - if ($platform === 'crm-module') { + if ($platform === 'dolibarr') { $entries[] = [ 'inline_content' => '0.0.0', 'destination' => 'update.txt', @@ -1289,9 +1289,9 @@ HCL; // Map platform slug to human-readable label $platformType = match ($platform) { - 'crm-module' => 'Dolibarr module', - 'waas-component' => 'Joomla extension', - 'default-repository' => 'PHP library', + 'dolibarr' => 'Dolibarr module', + 'joomla' => 'Joomla extension', + 'generic' => 'PHP library', default => ucfirst(str_replace('-', ' ', $platform)), };