Compare commits
31 Commits
development
..
alpha
| Author | SHA1 | Date | |
|---|---|---|---|
| c3e989d150 | |||
| d146b5d51e | |||
| 4cf967f92b | |||
| 4d99ab9a4e | |||
| 617344c4d7 | |||
| b57de90cef | |||
| dbd7ec8ae6 | |||
| f30c0dc9f9 | |||
| dcd22dcfdc | |||
| adcbd2d2f4 | |||
| 14b4477ff2 | |||
| 032c32637f | |||
| 16a86a94b7 | |||
| b68a23622a | |||
| 005ae12598 | |||
| 3834781899 | |||
| c00a04087f | |||
| 2b9bfb032e | |||
| b9109c51bc | |||
| 0f9f110c2d | |||
| 4cf931e7a3 | |||
| a7f758f888 | |||
| 7b863f690d | |||
| bd53fe834f | |||
| 784f423973 | |||
| 4742dfcbec | |||
| 5dff3346f0 | |||
| 029033c2f6 | |||
| 700e0abaac | |||
| bbadbfd2ad | |||
| c3fe454eb6 |
@@ -0,0 +1,112 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoStandards-API.Automation
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
# PATH: /.gitea/workflows/bulk-repo-sync.yml
|
||||
# VERSION: 04.06.12
|
||||
# BRIEF: Bulk repo sync — runs from API repo, syncs standards to all governed repos
|
||||
|
||||
name: Bulk Repository Sync
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 1 * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Preview mode (no changes)'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
repos:
|
||||
description: 'Comma-separated repo names (empty = all)'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
exclude:
|
||||
description: 'Comma-separated repos to skip'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
force:
|
||||
description: 'Force overwrite protected files'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
bulk-sync:
|
||||
name: Sync Standards to Repositories
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.1'
|
||||
extensions: json, mbstring, curl
|
||||
tools: composer
|
||||
coverage: none
|
||||
|
||||
- name: Install Dependencies
|
||||
run: composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
|
||||
|
||||
- name: Build CLI Arguments
|
||||
id: args
|
||||
run: |
|
||||
ARGS="--org MokoConsulting"
|
||||
if [ "${{ inputs.dry_run }}" = "true" ] || [ "${{ gitea.event_name }}" = "schedule" ]; then
|
||||
ARGS="$ARGS --dry-run"
|
||||
fi
|
||||
if [ -n "${{ inputs.repos }}" ]; then
|
||||
ARGS="$ARGS --repos ${{ inputs.repos }}"
|
||||
fi
|
||||
if [ -n "${{ inputs.exclude }}" ]; then
|
||||
ARGS="$ARGS --exclude ${{ inputs.exclude }}"
|
||||
fi
|
||||
if [ "${{ inputs.force }}" = "true" ]; then
|
||||
ARGS="$ARGS --force"
|
||||
fi
|
||||
ARGS="$ARGS --yes"
|
||||
echo "args=$ARGS" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Run Bulk Sync
|
||||
run: |
|
||||
echo "Running: php automation/bulk_sync.php ${{ steps.args.outputs.args }}"
|
||||
php automation/bulk_sync.php ${{ steps.args.outputs.args }} 2>&1 | tee /tmp/bulk_sync.log
|
||||
env:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
GIT_PLATFORM: gitea
|
||||
GITEA_URL: https://git.mokoconsulting.tech
|
||||
GITEA_ORG: MokoConsulting
|
||||
|
||||
- name: Commit Updated Definitions
|
||||
if: success() && inputs.dry_run != 'true'
|
||||
run: |
|
||||
if [ -n "$(git status --porcelain definitions/sync/)" ]; then
|
||||
git config user.name "gitea-actions[bot]"
|
||||
git config user.email "gitea-actions[bot]@git.mokoconsulting.tech"
|
||||
git add definitions/sync/*.def.tf
|
||||
git commit -m "chore: update synced repository definitions" || true
|
||||
git push || true
|
||||
fi
|
||||
|
||||
- name: Upload Sync Log
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: bulk-sync-log-${{ gitea.run_number }}
|
||||
path: /tmp/bulk_sync.log
|
||||
retention-days: 30
|
||||
@@ -15,11 +15,11 @@
|
||||
* BRIEF: Bulk scaffold and sync Joomla template repositories
|
||||
*
|
||||
* USAGE
|
||||
* php api/automation/bulk_joomla_template.php --scaffold --name=MokoTheme
|
||||
* php api/automation/bulk_joomla_template.php --scaffold --name=MokoTheme --client=administrator
|
||||
* php api/automation/bulk_joomla_template.php --sync --repos=MokoTheme,MokoDarkTheme
|
||||
* php api/automation/bulk_joomla_template.php --sync --all
|
||||
* php api/automation/bulk_joomla_template.php --list
|
||||
* php automation/bulk_joomla_template.php --scaffold --name=MokoTheme
|
||||
* php automation/bulk_joomla_template.php --scaffold --name=MokoTheme --client=administrator
|
||||
* php automation/bulk_joomla_template.php --sync --repos=MokoTheme,MokoDarkTheme
|
||||
* php automation/bulk_joomla_template.php --sync --all
|
||||
* php automation/bulk_joomla_template.php --list
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -717,13 +717,13 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
// ── Sync updates.xml between platforms ───────────────────────────────
|
||||
|
||||
/**
|
||||
* Sync updates.xml (or update.xml) between Gitea and GitHub for Joomla repos.
|
||||
* Sync updates.xml (or updates.xml) between Gitea and GitHub for Joomla repos.
|
||||
*
|
||||
* Reads the file from both platforms, compares by latest <version> tag,
|
||||
* and pushes the newer one to the stale platform.
|
||||
*
|
||||
* Designed to be called from a CI workflow via:
|
||||
* php api/automation/bulk_joomla_template.php --sync-updates --repos=MokoCassiopeia
|
||||
* php automation/bulk_joomla_template.php --sync-updates --repos=MokoCassiopeia
|
||||
*/
|
||||
private function syncUpdatesBetweenPlatforms(string $org): int
|
||||
{
|
||||
@@ -788,7 +788,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
$name = $repo['name'];
|
||||
$this->log("\n[{$name}]", 'INFO');
|
||||
|
||||
// Try both update.xml and updates.xml filenames
|
||||
// Try both updates.xml and updates.xml filenames
|
||||
$updateFile = $this->resolveUpdateFile($gitea, $github, $org, $name);
|
||||
if ($updateFile === null) {
|
||||
$this->log(" ⊘ No update(s).xml found on either platform", 'INFO');
|
||||
@@ -849,7 +849,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
/**
|
||||
* Find the updates file on both platforms, return the one with the higher version.
|
||||
*
|
||||
* Checks both `updates.xml` and `update.xml` filenames.
|
||||
* Checks both `updates.xml` and `updates.xml` filenames.
|
||||
* Returns the content from the platform with the newer <version>.
|
||||
* Gitea wins ties (primary platform).
|
||||
*
|
||||
@@ -861,7 +861,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
string $org,
|
||||
string $name
|
||||
): ?array {
|
||||
$candidates = ['updates.xml', 'update.xml'];
|
||||
$candidates = ['updates.xml', 'updates.xml'];
|
||||
$found = []; // platform => [name, content, version]
|
||||
|
||||
foreach (['gitea' => $gitea, 'github' => $github] as $platform => $adapter) {
|
||||
|
||||
@@ -420,7 +420,7 @@ class BulkSync extends CLIApp
|
||||
$this->log("The bulk repository sync is failing silently because the core", 'ERROR');
|
||||
$this->log("synchronization logic has not been implemented yet.", 'ERROR');
|
||||
$this->log("", 'ERROR');
|
||||
$this->log("Location: api/lib/Enterprise/RepositorySynchronizer.php", 'ERROR');
|
||||
$this->log("Location: lib/Enterprise/RepositorySynchronizer.php", 'ERROR');
|
||||
$this->log("Method: processRepository()", 'ERROR');
|
||||
$this->log("", 'ERROR');
|
||||
$this->log("Required Implementation:", 'ERROR');
|
||||
@@ -509,7 +509,7 @@ class BulkSync extends CLIApp
|
||||
]);
|
||||
$script = basename(__FILE__);
|
||||
$this->log("💾 Checkpoint saved. To resume once the issue is resolved, run:", 'INFO');
|
||||
$this->log(" php api/automation/{$script} --resume [same flags as before]", 'INFO');
|
||||
$this->log(" php automation/{$script} --resume [same flags as before]", 'INFO');
|
||||
} catch (\Exception $e) {
|
||||
$this->log("⚠️ Failed to save interrupt checkpoint: " . $e->getMessage(), 'WARN');
|
||||
}
|
||||
@@ -1355,7 +1355,7 @@ class BulkSync extends CLIApp
|
||||
|
||||
1. Check the local audit log or re-run with `--repos=<repo>` to see the specific error.
|
||||
2. Fix the underlying issue (API token, rate limit, branch protection, etc.).
|
||||
3. Re-run: `php api/automation/bulk_sync.php --org={$org} --repos=<repo> --force --yes`
|
||||
3. Re-run: `php automation/bulk_sync.php --org={$org} --repos=<repo> --force --yes`
|
||||
4. Close this issue once all repos are synced successfully.
|
||||
|
||||
---
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
* BRIEF: Migrate repositories from GitHub to self-hosted Gitea instance
|
||||
*
|
||||
* USAGE
|
||||
* php api/automation/migrate_to_gitea.php --dry-run
|
||||
* php api/automation/migrate_to_gitea.php --repos MokoCRM MokoDoliMods
|
||||
* php api/automation/migrate_to_gitea.php --exclude MokoStandards --skip-archived
|
||||
* php api/automation/migrate_to_gitea.php --resume
|
||||
* php automation/migrate_to_gitea.php --dry-run
|
||||
* php automation/migrate_to_gitea.php --repos MokoCRM MokoDoliMods
|
||||
* php automation/migrate_to_gitea.php --exclude MokoStandards --skip-archived
|
||||
* php automation/migrate_to_gitea.php --resume
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
@@ -590,7 +590,7 @@ class PushFiles extends CLIApp
|
||||
|
||||
1. Check the output above for the specific error per repo.
|
||||
2. Fix the underlying issue (API token, branch permissions, file path, etc.).
|
||||
3. Re-run: `php api/automation/push_files.php --org={$org} --repos=<repo> --files=<files> --yes`
|
||||
3. Re-run: `php automation/push_files.php --org={$org} --repos=<repo> --files=<files> --yes`
|
||||
4. Close this issue once resolved.
|
||||
|
||||
---
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
* BRIEF: Gracefully retire a governed repository — archive, close issues/PRs, remove sync def
|
||||
*
|
||||
* USAGE
|
||||
* php api/cli/archive_repo.php --repo MokoOldModule
|
||||
* php api/cli/archive_repo.php --repo MokoOldModule --dry-run
|
||||
* php api/cli/archive_repo.php --repo MokoOldModule --skip-close # Archive only, keep issues open
|
||||
* php cli/archive_repo.php --repo MokoOldModule
|
||||
* php cli/archive_repo.php --repo MokoOldModule --dry-run
|
||||
* php cli/archive_repo.php --repo MokoOldModule --skip-close # Archive only, keep issues open
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
* BRIEF: Create baseline GitHub Projects for repositories with standard fields and views
|
||||
*
|
||||
* USAGE
|
||||
* php api/cli/create_project.php --repo MokoCRM # Auto-detect type, create project
|
||||
* php api/cli/create_project.php --repo MokoCRM --type dolibarr # Force type
|
||||
* php api/cli/create_project.php --org mokoconsulting-tech --all # All repos without projects
|
||||
* php api/cli/create_project.php --repo MokoCRM --dry-run # Preview without changes
|
||||
* php cli/create_project.php --repo MokoCRM # Auto-detect type, create project
|
||||
* php cli/create_project.php --repo MokoCRM --type dolibarr # Force type
|
||||
* php cli/create_project.php --org mokoconsulting-tech --all # All repos without projects
|
||||
* php cli/create_project.php --repo MokoCRM --dry-run # Preview without changes
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -385,7 +385,7 @@ function createProject(
|
||||
updateProjectV2(input: {
|
||||
projectId: $projectId,
|
||||
shortDescription: $shortDescription,
|
||||
readme: "Managed by MokoStandards. Run `php api/cli/create_project.php` to regenerate."
|
||||
readme: "Managed by MokoStandards. Run `php cli/create_project.php` to regenerate."
|
||||
}) {
|
||||
projectV2 { id }
|
||||
}
|
||||
|
||||
+5
-5
@@ -15,9 +15,9 @@
|
||||
* BRIEF: Scaffold a new governed repository with full MokoStandards baseline
|
||||
*
|
||||
* USAGE
|
||||
* php api/cli/create_repo.php --name MokoNewModule --type dolibarr --description "My new module"
|
||||
* php api/cli/create_repo.php --name MokoNewModule --type joomla --private
|
||||
* php api/cli/create_repo.php --name MokoNewModule --type generic --dry-run
|
||||
* php cli/create_repo.php --name MokoNewModule --type dolibarr --description "My new module"
|
||||
* php cli/create_repo.php --name MokoNewModule --type joomla --private
|
||||
* php cli/create_repo.php --name MokoNewModule --type generic --dry-run
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -229,7 +229,7 @@ if (!$dryRun) {
|
||||
if (file_exists($syncScript)) {
|
||||
passthru("php " . escapeshellarg($syncScript) . " --repos " . escapeshellarg($name) . " --force --yes");
|
||||
} else {
|
||||
echo " Run manually: php api/automation/bulk_sync.php --repos {$name} --force --yes\n";
|
||||
echo " Run manually: php automation/bulk_sync.php --repos {$name} --force --yes\n";
|
||||
}
|
||||
} else {
|
||||
echo " (dry-run) would run initial sync\n";
|
||||
@@ -242,7 +242,7 @@ if (!$dryRun) {
|
||||
if (file_exists($projectScript)) {
|
||||
passthru("php " . escapeshellarg($projectScript) . " --repo " . escapeshellarg($name) . " --type " . escapeshellarg($type));
|
||||
} else {
|
||||
echo " Run manually: php api/cli/create_project.php --repo {$name} --type {$type}\n";
|
||||
echo " Run manually: php cli/create_project.php --repo {$name} --type {$type}\n";
|
||||
}
|
||||
} else {
|
||||
echo " (dry-run) would create Project\n";
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
* BRIEF: Joomla release pipeline — build ZIP+tar.gz, upload to GitHub Release, update updates.xml
|
||||
*
|
||||
* USAGE
|
||||
* php api/cli/joomla_release.php --repo MokoCassiopeia --stability stable
|
||||
* php api/cli/joomla_release.php --repo MokoCassiopeia --stability development
|
||||
* php api/cli/joomla_release.php --repo MokoCassiopeia --stability rc --dry-run
|
||||
* php api/cli/joomla_release.php --path /local/repo --stability stable
|
||||
* php cli/joomla_release.php --repo MokoCassiopeia --stability stable
|
||||
* php cli/joomla_release.php --repo MokoCassiopeia --stability development
|
||||
* php cli/joomla_release.php --repo MokoCassiopeia --stability rc --dry-run
|
||||
* php cli/joomla_release.php --path /local/repo --stability stable
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
+5
-5
@@ -13,10 +13,10 @@
|
||||
* BRIEF: Automate the MokoStandards version branch release flow
|
||||
*
|
||||
* USAGE
|
||||
* php api/cli/release.php # Release current version
|
||||
* php api/cli/release.php --bump minor # Bump minor, then release
|
||||
* php api/cli/release.php --bump major # Bump major, then release
|
||||
* php api/cli/release.php --dry-run # Preview without changes
|
||||
* php cli/release.php # Release current version
|
||||
* php cli/release.php --bump minor # Bump minor, then release
|
||||
* php cli/release.php --bump major # Bump major, then release
|
||||
* php cli/release.php --dry-run # Preview without changes
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -30,7 +30,7 @@ foreach ($argv as $i => $arg) {
|
||||
}
|
||||
|
||||
$repoRoot = dirname(__DIR__, 2);
|
||||
$syncFile = "{$repoRoot}/api/lib/Enterprise/RepositorySynchronizer.php";
|
||||
$syncFile = "{$repoRoot}/lib/Enterprise/RepositorySynchronizer.php";
|
||||
// Check both workflow directories for the bulk-repo-sync workflow
|
||||
$bulkSyncFile = file_exists("{$repoRoot}/.gitea/workflows/bulk-repo-sync.yml")
|
||||
? "{$repoRoot}/.gitea/workflows/bulk-repo-sync.yml"
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
* BRIEF: Apply branch protection rules to all repos via platform adapter
|
||||
*
|
||||
* USAGE
|
||||
* php api/cli/sync_rulesets.php # Apply to all repos
|
||||
* php api/cli/sync_rulesets.php --repo MokoCRM # Single repo
|
||||
* php api/cli/sync_rulesets.php --dry-run # Preview only
|
||||
* php api/cli/sync_rulesets.php --delete # Remove then re-apply
|
||||
* php cli/sync_rulesets.php # Apply to all repos
|
||||
* php cli/sync_rulesets.php --repo MokoCRM # Single repo
|
||||
* php cli/sync_rulesets.php --dry-run # Preview only
|
||||
* php cli/sync_rulesets.php --delete # Remove then re-apply
|
||||
*
|
||||
* NOTE: On GitHub, this creates rulesets via the rulesets API.
|
||||
* On Gitea, this creates branch_protections via the branch protection API.
|
||||
|
||||
+2
-3
@@ -17,7 +17,6 @@
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"guzzlehttp/guzzle": "^7.8",
|
||||
"mokoconsulting-tech/enterprise": "dev-version/04",
|
||||
"monolog/monolog": "^3.5",
|
||||
"php": ">=8.1",
|
||||
"phpseclib/phpseclib": "^3.0",
|
||||
@@ -74,8 +73,8 @@
|
||||
],
|
||||
"scripts": {
|
||||
"test": "phpunit",
|
||||
"phpcs": "phpcs --standard=phpcs.xml api/",
|
||||
"phpstan": "phpstan analyse -c phpstan.neon api/",
|
||||
"phpcs": "phpcs --standard=phpcs.xml lib/ validate/ automation/",
|
||||
"phpstan": "phpstan analyse -c phpstan.neon lib/ validate/ automation/",
|
||||
"psalm": "psalm --config=psalm.xml",
|
||||
"check": [
|
||||
"@phpcs",
|
||||
|
||||
@@ -132,7 +132,7 @@ locals {
|
||||
https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/raw/branch/main/updates.xml
|
||||
</server>
|
||||
<server type="extension" priority="2" name="{{TEMPLATE_NAME}} Update Server">
|
||||
https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/updates.xml
|
||||
https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -179,7 +179,7 @@ locals {
|
||||
https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{TEMPLATE_SHORT_NAME}}.zip
|
||||
</downloadurl>
|
||||
<downloadurl type="full" format="zip">
|
||||
https://github.com/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
|
||||
</downloadurl>
|
||||
</downloads>
|
||||
<targetplatform name="joomla" version="[56].*"/>
|
||||
|
||||
@@ -83,13 +83,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; managed by release workflow, never overwritten by sync"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
protected = true
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -101,10 +101,10 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/raw/branch/main/update.xml
|
||||
https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/raw/branch/main/updates.xml
|
||||
</server>
|
||||
<server type="extension" priority="2" name="{{EXTENSION_NAME}}">
|
||||
https://raw.githubusercontent.com/mokoconsulting-tech/{{REPO_NAME}}/main/update.xml
|
||||
https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/raw/branch/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -123,7 +123,7 @@ locals {
|
||||
https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
||||
</downloadurl>
|
||||
<downloadurl type="full" format="zip">
|
||||
https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
||||
https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
||||
</downloadurl>
|
||||
</downloads>
|
||||
<targetplatform name="joomla" version="[56].*"/>
|
||||
@@ -377,7 +377,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -425,7 +425,7 @@ locals {
|
||||
{
|
||||
name = ".github"
|
||||
path = ".github"
|
||||
description = "GitHub-specific configuration"
|
||||
description = "Gitea/GitHub Actions configuration (Gitea reads .github/workflows natively)"
|
||||
requirement_status = "suggested"
|
||||
purpose = "Contains GitHub Actions workflows and configuration"
|
||||
files = [
|
||||
@@ -467,7 +467,7 @@ locals {
|
||||
> | 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-name>` |
|
||||
> | `{{REPO_URL}}` | Full Gitea URL, e.g. `https://git.mokoconsulting.tech/MokoConsulting/<repo-name>` |
|
||||
> | `{{EXTENSION_NAME}}` | The `<name>` element in `manifest.xml` at the repository root |
|
||||
> | `{{EXTENSION_TYPE}}` | The `type` attribute of the `<extension>` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) |
|
||||
> | `{{EXTENSION_ELEMENT}}` | The `<element>` tag in `manifest.xml`, or the filename prefix (e.g. `com_myextension`, `mod_mymodule`) |
|
||||
@@ -478,7 +478,7 @@ locals {
|
||||
|
||||
## What This Repo Is
|
||||
|
||||
This is a **Moko Consulting MokoWaaS** (Joomla) 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.
|
||||
This is a **Moko Consulting MokoWaaS** (Joomla) repository governed by [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards). All coding standards, workflows, and policies are defined there and enforced here via bulk sync.
|
||||
|
||||
Repository URL: {{REPO_URL}}
|
||||
Extension name: **{{EXTENSION_NAME}}**
|
||||
@@ -552,13 +552,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
The version="[56].*" regex matches Joomla 5.x and 6.x. -->
|
||||
<updates>
|
||||
<update>
|
||||
@@ -582,7 +582,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -611,22 +611,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="[56].*">` — Joomla treats the version value as a regex; `[56].*` matches Joomla 5.x and 6.x.
|
||||
|
||||
@@ -635,8 +635,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -644,16 +644,16 @@ locals {
|
||||
|
||||
## GitHub Actions — Token Usage
|
||||
|
||||
Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token).
|
||||
Every workflow must use **`secrets.GA_TOKEN`** (the Gitea API token). Use `secrets.GH_TOKEN` only for GitHub mirror operations (stable/RC releases).
|
||||
|
||||
```yaml
|
||||
# ✅ Correct
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
token: ${{ secrets.GA_TOKEN }}
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
```
|
||||
|
||||
```yaml
|
||||
@@ -666,16 +666,16 @@ locals {
|
||||
|
||||
## MokoStandards Reference
|
||||
|
||||
This repository is governed by [MokoStandards](https://github.com/mokoconsulting-tech/MokoStandards). Authoritative policies:
|
||||
This repository is governed by [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/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 |
|
||||
| [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide |
|
||||
| [file-header-standards.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type |
|
||||
| [coding-style-guide.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions |
|
||||
| [branching-strategy.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow |
|
||||
| [merge-strategy.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR title/body conventions |
|
||||
| [changelog-standards.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md |
|
||||
| [joomla-development-guide.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide |
|
||||
|
||||
---
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -728,8 +728,8 @@ locals {
|
||||
- Never skip the FILE INFORMATION block on a new file
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Use `secrets.GA_TOKEN` for Gitea operations. Use `secrets.GH_TOKEN` only for GitHub mirror (stable/RC). Never use `secrets.GITHUB_TOKEN` directly
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -762,7 +762,7 @@ locals {
|
||||
> | 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-name>` |
|
||||
> | `{{REPO_URL}}` | Full Gitea URL, e.g. `https://git.mokoconsulting.tech/MokoConsulting/<repo-name>` |
|
||||
> | `{{REPO_DESCRIPTION}}` | First paragraph of `README.md` body, or the GitHub repo description |
|
||||
> | `{{EXTENSION_NAME}}` | The `<name>` element in `manifest.xml` at the repository root |
|
||||
> | `{{EXTENSION_TYPE}}` | The `type` attribute of the `<extension>` tag in `manifest.xml` (`component`, `module`, `plugin`, or `template`) |
|
||||
@@ -780,7 +780,7 @@ locals {
|
||||
Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`)
|
||||
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.
|
||||
This repository is governed by [MokoStandards](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards) — the single source of truth for coding standards, file-header policies, GitHub Actions workflows, and Terraform configuration templates across all Moko Consulting repositories.
|
||||
|
||||
---
|
||||
|
||||
@@ -789,7 +789,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -839,32 +839,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="[56].*">` — Joomla treats the version value as a regex; `[56].*` matches Joomla 5.x and 6.x.
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -948,16 +948,16 @@ locals {
|
||||
|
||||
# GitHub Actions — Token Usage
|
||||
|
||||
Every workflow must use **`secrets.GH_TOKEN`** (the org-level Personal Access Token).
|
||||
Every workflow must use **`secrets.GA_TOKEN`** (the Gitea API token). Use `secrets.GH_TOKEN` only for GitHub mirror operations (stable/RC releases).
|
||||
|
||||
```yaml
|
||||
# ✅ Correct
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GH_TOKEN }}
|
||||
token: ${{ secrets.GA_TOKEN }}
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
```
|
||||
|
||||
```yaml
|
||||
@@ -973,8 +973,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -985,7 +985,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -999,7 +999,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
@@ -1010,12 +1010,12 @@ locals {
|
||||
|
||||
| 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 |
|
||||
| [joomla-development-guide.md](https://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide |
|
||||
| [file-header-standards.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/file-header-standards.md) | Copyright-header rules for every file type |
|
||||
| [coding-style-guide.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions |
|
||||
| [branching-strategy.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow |
|
||||
| [merge-strategy.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR conventions |
|
||||
| [changelog-standards.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md |
|
||||
| [joomla-development-guide.md](https://git.mokoconsulting.tech/MokoConsulting/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide |
|
||||
MOKO_END
|
||||
}
|
||||
]
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "updated" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "created" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -164,13 +164,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -182,7 +182,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -453,7 +453,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -628,13 +628,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -660,7 +660,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -689,22 +689,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -713,8 +713,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -792,8 +792,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -807,7 +807,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -867,7 +867,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -917,32 +917,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1051,8 +1051,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1063,7 +1063,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1077,7 +1077,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "updated" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -164,13 +164,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -182,7 +182,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -453,7 +453,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -628,13 +628,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -660,7 +660,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -689,22 +689,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -713,8 +713,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -792,8 +792,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -807,7 +807,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -867,7 +867,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -917,32 +917,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1051,8 +1051,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1063,7 +1063,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1077,7 +1077,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "updated" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "updated" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "created" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "updated" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "updated" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "created" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "created" },
|
||||
{ path = "CONTRIBUTING.md" action = "created" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "created" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "created" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -31,7 +31,7 @@ locals {
|
||||
|
||||
synced_files = [
|
||||
{ path = "LICENSE" action = "updated" },
|
||||
{ path = "update.xml" action = "updated" },
|
||||
{ path = "updates.xml" action = "updated" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "updated" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -149,13 +149,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -167,7 +167,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -605,13 +605,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -637,7 +637,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -666,22 +666,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -690,8 +690,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -769,8 +769,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -784,7 +784,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -844,7 +844,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -894,32 +894,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1028,8 +1028,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1040,7 +1040,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1054,7 +1054,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -34,7 +34,7 @@ locals {
|
||||
{ path = "SECURITY.md" action = "updated" },
|
||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||
{ path = "update.xml" action = "created" },
|
||||
{ path = "updates.xml" action = "created" },
|
||||
{ path = "phpstan.neon" action = "updated" },
|
||||
{ path = "Makefile" action = "created" },
|
||||
{ path = ".gitignore" action = "updated" },
|
||||
@@ -165,13 +165,13 @@ locals {
|
||||
audience = "contributor"
|
||||
},
|
||||
{
|
||||
name = "update.xml"
|
||||
name = "updates.xml"
|
||||
extension = "xml"
|
||||
description = "Joomla extension update server manifest — lists releases for Joomla auto-update; must be kept in sync with manifest.xml version"
|
||||
required = true
|
||||
always_overwrite = false
|
||||
audience = "developer"
|
||||
template = "templates/joomla/update.xml.template"
|
||||
template = "templates/joomla/updates.xml.template"
|
||||
stub_content = <<-MOKO_END
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
@@ -183,7 +183,7 @@ locals {
|
||||
The manifest.xml in this repository must reference this file:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
@@ -454,7 +454,7 @@ locals {
|
||||
{
|
||||
name = "update-server.md"
|
||||
extension = "md"
|
||||
description = "Joomla update server (update.xml) documentation"
|
||||
description = "Joomla update server (updates.xml) documentation"
|
||||
required = true
|
||||
always_overwrite = true
|
||||
template = "templates/docs/required/template-update-server-joomla.md"
|
||||
@@ -629,13 +629,13 @@ locals {
|
||||
|
||||
### Joomla Version Alignment
|
||||
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `update.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
The version in `README.md` **must always match** the `<version>` tag in `manifest.xml` and the latest entry in `updates.xml`. The `make release` command / release workflow updates all three automatically.
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml — must match README.md version -->
|
||||
<version>01.02.04</version>
|
||||
|
||||
<!-- In update.xml — prepend a new <update> block for every release.
|
||||
<!-- In updates.xml — prepend a new <update> block for every release.
|
||||
Note: the backslash in version="4\.[0-9]+" is a literal backslash character
|
||||
in the XML attribute value. Joomla's update server treats the value as a
|
||||
regular expression, so \. matches a literal dot. -->
|
||||
@@ -661,7 +661,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required, see below)
|
||||
├── updates.xml # Update server manifest (root — required, see below)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -690,22 +690,22 @@ locals {
|
||||
|
||||
---
|
||||
|
||||
## update.xml — Required in Repo Root
|
||||
## updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
`updates.xml` **must exist at the repository root**. It is the Joomla update server manifest that allows Joomla installations to check for new versions of this extension.
|
||||
|
||||
The `manifest.xml` must reference it via:
|
||||
```xml
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- Every release must prepend a new `<update>` block at the top of `updates.xml` — old entries must be preserved below.
|
||||
- The `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and the version in `README.md`.
|
||||
- The `<downloadurl>` must be a publicly accessible direct download link (GitHub Releases asset URL).
|
||||
- `<targetplatform name="joomla" version="4\.[0-9]+">` — the backslash is a **literal backslash character** in the XML attribute value; Joomla's update-server parser treats the value as a regular expression, so `\.` matches a literal dot and `[0-9]+` matches one or more digits. Do not double-escape it.
|
||||
|
||||
@@ -714,8 +714,8 @@ locals {
|
||||
## manifest.xml Rules
|
||||
|
||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `update.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
||||
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||
- Must include `<files folder="site">` and `<administration>` sections.
|
||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||
|
||||
@@ -793,8 +793,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed manifest.xml | Update `update.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||
| New release | Prepend `<update>` block to `updates.xml`; update CHANGELOG.md; bump README.md version |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -808,7 +808,7 @@ locals {
|
||||
- Never add `defined('_JEXEC') or die;` to CLI scripts or model tests — only to web-accessible PHP files
|
||||
- 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 let `manifest.xml` version, `update.xml` version, and `README.md` version go out of sync
|
||||
- Never let `manifest.xml` version, `updates.xml` version, and `README.md` version go out of sync
|
||||
MOKO_END
|
||||
},
|
||||
{
|
||||
@@ -868,7 +868,7 @@ locals {
|
||||
```
|
||||
{{REPO_NAME}}/
|
||||
├── manifest.xml # Joomla installer manifest (root — required)
|
||||
├── update.xml # Update server manifest (root — required)
|
||||
├── updates.xml # Update server manifest (root — required)
|
||||
├── site/ # Frontend (site) code
|
||||
│ ├── controller.php
|
||||
│ ├── controllers/
|
||||
@@ -918,32 +918,32 @@ locals {
|
||||
|------|------------------------|
|
||||
| `README.md` | `FILE INFORMATION` block + badge |
|
||||
| `manifest.xml` | `<version>` tag |
|
||||
| `update.xml` | `<version>` in the most recent `<update>` block |
|
||||
| `updates.xml` | `<version>` in the most recent `<update>` block |
|
||||
|
||||
The `make release` command / release workflow syncs all three automatically.
|
||||
|
||||
---
|
||||
|
||||
# update.xml — Required in Repo Root
|
||||
# updates.xml — Required in Repo Root
|
||||
|
||||
`update.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
`updates.xml` is the Joomla update server manifest. It allows Joomla installations to check for new versions of this extension via:
|
||||
|
||||
```xml
|
||||
<!-- In manifest.xml -->
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||
{{REPO_URL}}/raw/main/update.xml
|
||||
{{REPO_URL}}/raw/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
||||
- `<version>` in `update.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<version>` in `updates.xml` must exactly match `<version>` in `manifest.xml` and `README.md`.
|
||||
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
||||
|
||||
Example `update.xml` entry for a new release:
|
||||
Example `updates.xml` entry for a new release:
|
||||
```xml
|
||||
<updates>
|
||||
<update>
|
||||
@@ -1052,8 +1052,8 @@ locals {
|
||||
| Change type | Documentation to update |
|
||||
|-------------|------------------------|
|
||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
||||
| New or changed `manifest.xml` | Sync version to `update.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||
| 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 |
|
||||
@@ -1064,7 +1064,7 @@ locals {
|
||||
|
||||
- **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 let `manifest.xml`, `update.xml`, and `README.md` versions diverge.**
|
||||
- **Never let `manifest.xml`, `updates.xml`, and `README.md` versions diverge.**
|
||||
- **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`.
|
||||
@@ -1078,7 +1078,7 @@ locals {
|
||||
Before opening a PR, verify:
|
||||
|
||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `update.xml` updated with new entry
|
||||
- [ ] If this is a release: `manifest.xml` version updated; `updates.xml` updated with new entry
|
||||
- [ ] FILE INFORMATION headers updated in modified files
|
||||
- [ ] CHANGELOG.md updated
|
||||
- [ ] Tests pass
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
* changes — only XML manifest changes require a Joomla reinstall.
|
||||
*
|
||||
* USAGE
|
||||
* php api/deploy/deploy-joomla.php --path . --config /tmp/sftp-config.json
|
||||
* php api/deploy/deploy-joomla.php --path . --config /tmp/sftp-config.json --dry-run
|
||||
* php api/deploy/deploy-joomla.php --path . --env dev
|
||||
* php deploy/deploy-joomla.php --path . --config /tmp/sftp-config.json
|
||||
* php deploy/deploy-joomla.php --path . --config /tmp/sftp-config.json --dry-run
|
||||
* php deploy/deploy-joomla.php --path . --env dev
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
@@ -96,25 +96,25 @@ CONFIG FORMAT
|
||||
|
||||
EXAMPLES
|
||||
# Dry-run preview of dev deployment
|
||||
php api/deploy/deploy-sftp.php --env dev --dry-run --verbose
|
||||
php deploy/deploy-sftp.php --env dev --dry-run --verbose
|
||||
|
||||
# Deploy to dev server
|
||||
php api/deploy/deploy-sftp.php --path /repos/mymodule --env dev
|
||||
php deploy/deploy-sftp.php --path /repos/mymodule --env dev
|
||||
|
||||
# Deploy to release/production server
|
||||
php api/deploy/deploy-sftp.php --path /repos/mymodule --env rs
|
||||
php deploy/deploy-sftp.php --path /repos/mymodule --env rs
|
||||
|
||||
# Use a different source directory
|
||||
php api/deploy/deploy-sftp.php --env dev --src-dir htdocs
|
||||
php deploy/deploy-sftp.php --env dev --src-dir htdocs
|
||||
|
||||
# Explicit config with encrypted key
|
||||
php api/deploy/deploy-sftp.php \
|
||||
php deploy/deploy-sftp.php \
|
||||
--path /repos/mymodule \
|
||||
--env rs \
|
||||
--key-passphrase "my passphrase"
|
||||
|
||||
# Quiet mode (errors only)
|
||||
php api/deploy/deploy-sftp.php --env dev --quiet
|
||||
php deploy/deploy-sftp.php --env dev --quiet
|
||||
|
||||
EXIT CODES
|
||||
0 All files uploaded successfully
|
||||
|
||||
@@ -95,93 +95,101 @@ development
|
||||
|
||||
The module descriptor's `url_last_version` should point to:
|
||||
```
|
||||
https://raw.githubusercontent.com/{org}/{repo}/main/update.txt
|
||||
https://git.mokoconsulting.tech/MokoConsulting/{repo}/raw/branch/main/update.txt
|
||||
```
|
||||
|
||||
## Joomla: `updates.xml` (Multi-Entry)
|
||||
|
||||
The `updates.xml` file contains **up to five stability entries at once** (one per stability level). Joomla reads the entire file and filters by the site's minimum stability setting.
|
||||
|
||||
### Platform Distribution
|
||||
|
||||
| Release Type | Gitea Release | GitHub Release | Download URLs |
|
||||
|-------------|--------------|----------------|---------------|
|
||||
| **Stable** | Yes | Yes (via mirror) | Dual (Gitea + GitHub) |
|
||||
| **RC** | Yes | No | Single (Gitea only) |
|
||||
| **Beta** | Yes | No | Single (Gitea only) |
|
||||
| **Alpha** | Yes | No | Single (Gitea only) |
|
||||
| **Development** | Yes | No | Single (Gitea only) |
|
||||
|
||||
Pre-release builds stay on Gitea for internal testing. Only stable releases are mirrored to GitHub.
|
||||
|
||||
### Complete Multi-Entry Example
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<updates>
|
||||
<!-- Stable entry: visible to all sites (default minimum stability) -->
|
||||
<!-- Stable: dual download (Gitea + GitHub), visible to all sites -->
|
||||
<update>
|
||||
<name>My Extension</name>
|
||||
<description>My Extension stable release</description>
|
||||
<element>com_myextension</element>
|
||||
<type>component</type>
|
||||
<version>01.02.03</version>
|
||||
<client>site</client>
|
||||
<tags>
|
||||
<tag>stable</tag>
|
||||
</tags>
|
||||
<infourl title="My Extension">https://github.com/org/repo/releases/tag/v01</infourl>
|
||||
<infourl title="My Extension">https://git.mokoconsulting.tech/MokoConsulting/MyExtension/releases</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/org/repo/releases/download/v01/com_myextension-01.02.03.zip</downloadurl>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MyExtension/releases/download/v01/com_myextension-01.02.03.zip</downloadurl>
|
||||
<downloadurl type="full" format="zip">https://github.com/mokoconsulting-tech/MyExtension/releases/download/v01/com_myextension-01.02.03.zip</downloadurl>
|
||||
</downloads>
|
||||
<sha256>abc123...full-hash-here</sha256>
|
||||
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
|
||||
<!-- RC entry: visible to sites with minimum stability = RC or lower -->
|
||||
<!-- RC: Gitea only, visible to sites with minimum stability = RC or lower -->
|
||||
<update>
|
||||
<name>My Extension</name>
|
||||
<description>My Extension release candidate</description>
|
||||
<element>com_myextension</element>
|
||||
<type>component</type>
|
||||
<version>01.03.01-rc</version>
|
||||
<client>site</client>
|
||||
<tags>
|
||||
<tag>rc</tag>
|
||||
</tags>
|
||||
<infourl title="My Extension">https://github.com/org/repo/tree/rc/01.03.01</infourl>
|
||||
<infourl title="My Extension">https://git.mokoconsulting.tech/MokoConsulting/MyExtension/src/branch/rc</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/org/repo/archive/refs/heads/rc/01.03.01.zip</downloadurl>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MyExtension/releases/download/rc/com_myextension-01.03.01-rc.zip</downloadurl>
|
||||
</downloads>
|
||||
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
|
||||
<!-- Beta entry: visible to sites with minimum stability = Beta or lower -->
|
||||
<!-- Beta: Gitea only, visible to sites with minimum stability = Beta or lower -->
|
||||
<update>
|
||||
<name>My Extension</name>
|
||||
<description>My Extension beta build</description>
|
||||
<element>com_myextension</element>
|
||||
<type>component</type>
|
||||
<version>01.03.01-beta</version>
|
||||
<client>site</client>
|
||||
<tags>
|
||||
<tag>beta</tag>
|
||||
</tags>
|
||||
<infourl title="My Extension">https://github.com/org/repo/tree/beta/01.03.01</infourl>
|
||||
<infourl title="My Extension">https://git.mokoconsulting.tech/MokoConsulting/MyExtension/src/branch/beta</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/org/repo/archive/refs/heads/beta/01.03.01.zip</downloadurl>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MyExtension/releases/download/beta/com_myextension-01.03.01-beta.zip</downloadurl>
|
||||
</downloads>
|
||||
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||
</update>
|
||||
|
||||
<!-- Alpha entry: visible to sites with minimum stability = Alpha or lower -->
|
||||
<!-- Alpha: Gitea only, visible to sites with minimum stability = Alpha or lower -->
|
||||
<update>
|
||||
<name>My Extension</name>
|
||||
<description>My Extension alpha build</description>
|
||||
<element>com_myextension</element>
|
||||
<type>component</type>
|
||||
<version>01.03.01-alpha</version>
|
||||
<client>site</client>
|
||||
<tags>
|
||||
<tag>alpha</tag>
|
||||
</tags>
|
||||
<infourl title="My Extension">https://github.com/org/repo/tree/alpha/01.03.01</infourl>
|
||||
<infourl title="My Extension">https://git.mokoconsulting.tech/MokoConsulting/MyExtension/src/branch/alpha</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/org/repo/archive/refs/heads/alpha/01.03.01.zip</downloadurl>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/MokoConsulting/MyExtension/releases/download/alpha/com_myextension-01.03.01-alpha.zip</downloadurl>
|
||||
</downloads>
|
||||
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
@@ -195,7 +203,6 @@ The `updates.xml` file contains **up to five stability entries at once** (one pe
|
||||
<element>com_myextension</element>
|
||||
<type>component</type>
|
||||
<version>01.04.00-dev</version>
|
||||
<client>site</client>
|
||||
<tags>
|
||||
<tag>development</tag>
|
||||
</tags>
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /lib/CliBase.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: Standalone base CLI class for api/ scripts that do not use CliFramework
|
||||
* BRIEF: Standalone base CLI class for scripts that do not use CliFramework
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /lib/Common.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: Common utility functions for api/ scripts
|
||||
* BRIEF: Common utility functions for scripts
|
||||
* NOTE: Version format used throughout is zero-padded semver: XX.YY.ZZ (e.g. 04.00.04).
|
||||
* All version regex patterns enforce exactly two digits per component by design.
|
||||
*/
|
||||
|
||||
@@ -92,7 +92,7 @@ class EnterpriseReadinessValidator
|
||||
];
|
||||
|
||||
foreach ($required as $library) {
|
||||
$phpFile = "{$path}/api/lib/Enterprise/{$library}.php";
|
||||
$phpFile = "{$path}/lib/Enterprise/{$library}.php";
|
||||
$this->addResult(
|
||||
"Enterprise library: {$library}",
|
||||
file_exists($phpFile),
|
||||
|
||||
@@ -166,7 +166,7 @@ class RepositorySynchronizer
|
||||
{
|
||||
$this->logger->logInfo("Starting synchronization for {$org}/{$repo}");
|
||||
|
||||
// Resolve repo root (two levels up from this file: Enterprise/ → lib/ → api/ → root)
|
||||
// Resolve repo root (three levels up from this file: Enterprise/ → lib/ → root)
|
||||
// API repo root (definitions, sync code)
|
||||
$repoRoot = dirname(dirname(__DIR__));
|
||||
// MokoStandards repo root (templates, configs)
|
||||
@@ -509,7 +509,7 @@ HCL;
|
||||
try {
|
||||
$issueData = $this->adapter->createIssue($org, $repo, $issueTitle, $issueBody, [
|
||||
'labels' => ['mokostandards', 'type: chore', 'automation'],
|
||||
'assignees' => ['jmiller-moko'],
|
||||
'assignees' => ['jmiller'],
|
||||
]);
|
||||
$issueNumber = $issueData['number'] ?? null;
|
||||
$this->logger->logInfo("Created tracking issue #{$issueNumber} — " . count($summary['copied']) . " files synced directly to {$defaultBranch}");
|
||||
@@ -598,7 +598,12 @@ HCL;
|
||||
$isReadme = $basename === 'readme.md';
|
||||
$isChangelog = in_array($basename, ['changelog.md', 'changelog'], true);
|
||||
$isProtected = $isReadme || $isChangelog;
|
||||
$canOverwrite = !$isProtected && ($force || $entry['always_overwrite']) && !($entry['protected'] ?? false);
|
||||
// Protected files are NEVER overwritten, even with --force
|
||||
if ($entry['protected'] ?? false) {
|
||||
$summary['skipped'][] = ['file' => $targetPath, 'reason' => 'Protected — never overwritten'];
|
||||
continue;
|
||||
}
|
||||
$canOverwrite = !$isProtected && ($force || $entry['always_overwrite']);
|
||||
|
||||
if ($isReadme) {
|
||||
$summary['skipped'][] = ['file' => $targetPath, 'reason' => 'README — never overwritten'];
|
||||
@@ -903,6 +908,77 @@ HCL;
|
||||
return $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Required .gitignore entries that MUST exist in every governed repo.
|
||||
* The sync validates these exist (appending if missing) without
|
||||
* overwriting custom entries. Repos can add their own patterns freely.
|
||||
*/
|
||||
private const REQUIRED_GITIGNORE_ENTRIES = [
|
||||
// Secrets & environment
|
||||
'.env',
|
||||
'.env.local',
|
||||
'.env.*.local',
|
||||
'secrets/',
|
||||
'*.secrets.*',
|
||||
|
||||
// Sublime Text project files
|
||||
'*.sublime-project',
|
||||
'*.sublime-workspace',
|
||||
'*.sublime-settings',
|
||||
|
||||
// SFTP config (Sublime SFTP, VS Code SFTP, etc.)
|
||||
'sftp-config*.json',
|
||||
'sftp-config.json.template',
|
||||
'sftp-settings.json',
|
||||
|
||||
// IDE / editor
|
||||
'.idea/',
|
||||
'.vscode/*',
|
||||
'.claude/',
|
||||
'*.code-workspace',
|
||||
|
||||
// OS cruft
|
||||
'.DS_Store',
|
||||
'Thumbs.db',
|
||||
|
||||
// Task tracking
|
||||
'TODO.md',
|
||||
|
||||
// Vendor / dependencies
|
||||
'/vendor/',
|
||||
'node_modules/',
|
||||
|
||||
// Logs
|
||||
'*.log',
|
||||
];
|
||||
|
||||
/**
|
||||
* Validate that required .gitignore entries exist in a repo.
|
||||
* Returns array of missing entries, empty if all present.
|
||||
*
|
||||
* @param string $existingContent Current .gitignore content from repo
|
||||
* @return array<string> Missing required entries
|
||||
*/
|
||||
public function validateGitignoreEntries(string $existingContent): array
|
||||
{
|
||||
$existingLines = array_map('trim', explode("\n", $existingContent));
|
||||
$existingSet = [];
|
||||
foreach ($existingLines as $line) {
|
||||
if ($line !== '' && !str_starts_with($line, '#')) {
|
||||
$existingSet[$line] = true;
|
||||
}
|
||||
}
|
||||
|
||||
$missing = [];
|
||||
foreach (self::REQUIRED_GITIGNORE_ENTRIES as $entry) {
|
||||
if (!isset($existingSet[$entry])) {
|
||||
$missing[] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
return $missing;
|
||||
}
|
||||
|
||||
private function mergeGitConfigFile(string $existing, string $template): string
|
||||
{
|
||||
$existingLines = array_map('rtrim', explode("\n", $existing));
|
||||
|
||||
@@ -34,7 +34,7 @@ use MokoEnterprise\PlatformAdapterFactory;
|
||||
* pinned commit SHA. Already-pinned references (40-char hex SHA) are left untouched.
|
||||
*
|
||||
* Usage:
|
||||
* php api/maintenance/pin_action_shas.php [--dry-run] [--verbose] [--help]
|
||||
* php maintenance/pin_action_shas.php [--dry-run] [--verbose] [--help]
|
||||
*
|
||||
* Environment:
|
||||
* GH_TOKEN Personal access token for GitHub API calls.
|
||||
@@ -90,7 +90,7 @@ class ActionShaPinner
|
||||
private function showHelp(): void
|
||||
{
|
||||
echo <<<'HELP'
|
||||
Usage: php api/maintenance/pin_action_shas.php [OPTIONS]
|
||||
Usage: php maintenance/pin_action_shas.php [OPTIONS]
|
||||
|
||||
Pins GitHub Actions to immutable commit SHAs in all .github/workflows/*.yml
|
||||
files. Already-pinned references (40-character commit SHA) are skipped.
|
||||
@@ -106,10 +106,10 @@ Environment:
|
||||
|
||||
Examples:
|
||||
# Preview all changes
|
||||
GH_TOKEN=ghp_xxx php api/maintenance/pin_action_shas.php --dry-run --verbose
|
||||
GH_TOKEN=ghp_xxx php maintenance/pin_action_shas.php --dry-run --verbose
|
||||
|
||||
# Apply changes
|
||||
GH_TOKEN=ghp_xxx php api/maintenance/pin_action_shas.php
|
||||
GH_TOKEN=ghp_xxx php maintenance/pin_action_shas.php
|
||||
|
||||
HELP;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
* BRIEF: Generate a live inventory dashboard of all governed repos as a GitHub issue
|
||||
*
|
||||
* USAGE
|
||||
* php api/maintenance/repo_inventory.php # Generate and post dashboard
|
||||
* php api/maintenance/repo_inventory.php --dry-run # Preview only
|
||||
* php api/maintenance/repo_inventory.php --json # JSON output to stdout
|
||||
* php maintenance/repo_inventory.php # Generate and post dashboard
|
||||
* php maintenance/repo_inventory.php --dry-run # Preview only
|
||||
* php maintenance/repo_inventory.php --json # JSON output to stdout
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
* BRIEF: Audit FTP secrets and variables across all governed repos — report missing or stale
|
||||
*
|
||||
* USAGE
|
||||
* php api/maintenance/rotate_secrets.php --all # Audit all repos
|
||||
* php api/maintenance/rotate_secrets.php --repo MokoCRM # Single repo
|
||||
* php api/maintenance/rotate_secrets.php --all --json # JSON output
|
||||
* php api/maintenance/rotate_secrets.php --all --create-issue # Post results as issue
|
||||
* php maintenance/rotate_secrets.php --all # Audit all repos
|
||||
* php maintenance/rotate_secrets.php --repo MokoCRM # Single repo
|
||||
* php maintenance/rotate_secrets.php --all --json # JSON output
|
||||
* php maintenance/rotate_secrets.php --all --create-issue # Post results as issue
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
@@ -25,7 +25,7 @@ declare(strict_types=1);
|
||||
*/
|
||||
class ScriptRegistryUpdater
|
||||
{
|
||||
private const REGISTRY_PATH = 'api/.script-registry.json';
|
||||
private const REGISTRY_PATH = '.script-registry.json';
|
||||
|
||||
private bool $dryRun = false;
|
||||
private bool $verbose = false;
|
||||
|
||||
@@ -435,15 +435,15 @@ class UpdateVersionFromReadme extends CliFramework
|
||||
"",
|
||||
"1. Run the sync script locally:",
|
||||
" ```bash",
|
||||
" php api/maintenance/update_version_from_readme.php --path . --dry-run",
|
||||
" php api/maintenance/update_version_from_readme.php --path .",
|
||||
" php maintenance/update_version_from_readme.php --path . --dry-run",
|
||||
" php maintenance/update_version_from_readme.php --path .",
|
||||
" ```",
|
||||
"2. Inspect any files still flagged — they may use a non-standard VERSION format.",
|
||||
"3. Update them manually to match `VERSION: {$version}`.",
|
||||
"4. Commit and push — this issue will be closed automatically on the next successful sync.",
|
||||
"",
|
||||
"---",
|
||||
"*Automatically created by [update_version_from_readme.php](api/maintenance/update_version_from_readme.php)*",
|
||||
"*Automatically created by [update_version_from_readme.php](maintenance/update_version_from_readme.php)*",
|
||||
]);
|
||||
|
||||
try {
|
||||
|
||||
@@ -46,6 +46,7 @@ Icon?
|
||||
.idea/
|
||||
.settings/
|
||||
.claude/
|
||||
.claude-worktree*/
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/settings.json.example
|
||||
|
||||
@@ -46,6 +46,7 @@ Icon?
|
||||
.idea/
|
||||
.settings/
|
||||
.claude/
|
||||
.claude-worktree*/
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/settings.json.example
|
||||
|
||||
@@ -46,6 +46,7 @@ Icon?
|
||||
.idea/
|
||||
.settings/
|
||||
.claude/
|
||||
.claude-worktree*/
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/settings.json.example
|
||||
|
||||
@@ -1,45 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
VERSION: {{VERSION}}
|
||||
-->
|
||||
|
||||
This file is part of a Moko Consulting project.
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
FILE INFORMATION
|
||||
DEFGROUP: MokoStandards.Templates.Joomla
|
||||
INGROUP: MokoStandards.Templates
|
||||
REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards
|
||||
PATH: /templates/joomla/updates.xml.template
|
||||
VERSION: XX.YY.ZZ
|
||||
BRIEF: Joomla update server XML template — lists available extension releases for Joomla auto-updates
|
||||
|
||||
NOTE: Dual-platform: Gitea (primary) and GitHub (backup mirror).
|
||||
The manifest.xml <updateservers> must declare both servers.
|
||||
Tokens replaced at sync time: {{REPO_NAME}}, {{GITEA_ORG}}, {{GITHUB_ORG}},
|
||||
{{EXTENSION_NAME}}, {{EXTENSION_TYPE}}, {{EXTENSION_ELEMENT}}, {{VERSION}},
|
||||
{{MAINTAINER_URL}}
|
||||
-->
|
||||
<!--
|
||||
Joomla Extension Update Server XML
|
||||
See: https://docs.joomla.org/Deploying_an_Update_Server
|
||||
|
||||
This file is the update server manifest for {{EXTENSION_NAME}}.
|
||||
The Joomla installer polls this URL to check for new versions.
|
||||
|
||||
The manifest.xml in this repository must reference BOTH update servers:
|
||||
<updateservers>
|
||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}} Update Server (Gitea)">
|
||||
https://git.mokoconsulting.tech/{{GITEA_ORG}}/{{REPO_NAME}}/raw/branch/main/updates.xml
|
||||
</server>
|
||||
<server type="extension" priority="2" name="{{EXTENSION_NAME}} Update Server (GitHub)">
|
||||
https://raw.githubusercontent.com/{{GITHUB_ORG}}/{{REPO_NAME}}/main/updates.xml
|
||||
</server>
|
||||
</updateservers>
|
||||
|
||||
When a new release is made, run `make release` or the release workflow to
|
||||
prepend a new <update> entry to this file automatically.
|
||||
-->
|
||||
<updates>
|
||||
<update>
|
||||
<name>{{EXTENSION_NAME}}</name>
|
||||
@@ -48,12 +12,14 @@ NOTE: Dual-platform: Gitea (primary) and GitHub (backup mirror).
|
||||
<type>{{EXTENSION_TYPE}}</type>
|
||||
<version>{{VERSION}}</version>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://git.mokoconsulting.tech/{{GITEA_ORG}}/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip</downloadurl>
|
||||
<downloadurl type="full" format="zip">https://github.com/{{GITHUB_ORG}}/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip</downloadurl>
|
||||
<downloadurl type="full" format="zip">
|
||||
https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
||||
</downloadurl>
|
||||
<downloadurl type="full" format="zip">
|
||||
https://github.com/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
||||
</downloadurl>
|
||||
</downloads>
|
||||
<targetplatform name="joomla" version="((5\.[0-9])|(6\.[0-9]))" />
|
||||
<php_minimum>8.2</php_minimum>
|
||||
<maintainer>Moko Consulting</maintainer>
|
||||
<maintainerurl>{{MAINTAINER_URL}}</maintainerurl>
|
||||
<targetplatform name="joomla" version="[56].*"/>
|
||||
<php_minimum>8.1</php_minimum>
|
||||
</update>
|
||||
</updates>
|
||||
|
||||
@@ -139,11 +139,11 @@ The workflows are organized by platform and purpose:
|
||||
|
||||
Workflow templates specifically designed for Joomla extensions (components, modules, plugins, libraries, packages, templates):
|
||||
|
||||
- **auto-release.yml.template** - Build & release pipeline for stable releases (triggers on merge to main). Reads version from README.md, sets platform version, builds ZIP+tar.gz packages, creates/updates Gitea releases, updates only the **stable** channel in updates.xml, and mirrors to GitHub. All patches release (including patch 00).
|
||||
- **update-server.yml.template** - Multi-channel Joomla update server (triggers on dev/alpha/beta/rc branch merges). Builds packages, uploads to per-channel Gitea releases, updates only the **matching stability channel** in updates.xml via targeted Python regex replacement. Supports SFTP deploy to dev server.
|
||||
- **ci-joomla.yml.template** - Continuous integration workflow with PHP validation, XML checking, and manifest verification
|
||||
- **test.yml.template** - Comprehensive testing with PHPUnit, code quality checks, and integration tests
|
||||
- **release.yml.template** - Automated release workflow for creating and publishing Joomla extension packages
|
||||
- **deploy-manual.yml.template** - Manual deployment workflow for Joomla extensions with release triggering
|
||||
- **repo_health.yml.template** - Repository health monitoring including documentation checks and standards validation
|
||||
- **version_branch.yml.template** - Automated version branch management and release preparation
|
||||
|
||||
### Dolibarr Templates (`dolibarr/`)
|
||||
|
||||
@@ -474,6 +474,44 @@ Project-specific validation workflows using the MokoStandards plugin system. Eac
|
||||
- Artifact upload for validation results
|
||||
- Proper exit codes (0=success, 1=failure, 2=error)
|
||||
|
||||
## Multi-Channel updates.xml Architecture (Joomla)
|
||||
|
||||
Joomla extensions use `updates.xml` as their update server manifest. MokoStandards implements a **multi-channel** architecture where each stability level has its own `<update>` block:
|
||||
|
||||
```xml
|
||||
<updates>
|
||||
<!-- 1. DEVELOPMENT --> <update>...<tag>development</tag>...</update>
|
||||
<!-- 2. ALPHA --> <update>...<tag>alpha</tag>...</update>
|
||||
<!-- 3. BETA --> <update>...<tag>beta</tag>...</update>
|
||||
<!-- 4. RC --> <update>...<tag>rc</tag>...</update>
|
||||
<!-- 5. STABLE --> <update>...<tag>stable</tag>...</update>
|
||||
</updates>
|
||||
```
|
||||
|
||||
### Key Principles
|
||||
|
||||
- **Cascading channel updates** — Each release updates its own channel and all lower stability channels. This ensures every site sees the update regardless of their minimum stability setting:
|
||||
- `stable` → updates development, alpha, beta, rc, stable
|
||||
- `rc` → updates development, alpha, beta, rc
|
||||
- `beta` → updates development, alpha, beta
|
||||
- `alpha` → updates development, alpha
|
||||
- `development` → updates development only
|
||||
- **Joomla filters by user setting** — Site administrators choose "Minimum Stability" in Joomla's update settings; Joomla shows updates matching that level or higher
|
||||
- **SHA-256 must be raw hex** — No `sha256:` prefix. Joomla expects the raw hash value
|
||||
- **Version format is zero-padded semver** — `XX.YY.ZZ` (e.g., `01.00.00`), not tag names like `v01`
|
||||
- **All patches release** — Including patch `00`. Release workflows auto-bump the patch version before building (increments `XX.YY.ZZ` → `XX.YY.(ZZ+1)` in README.md, manifest, and the matching updates.xml channel)
|
||||
- **Auto-bump on all branches** — `release.yml` (manual dispatch) and `update-server.yml` (branch merges) both auto-bump patch before building. No manual version bump required
|
||||
|
||||
### Channel-to-Workflow Mapping
|
||||
|
||||
| Channel | Workflow | Trigger | Release Tag |
|
||||
|---------|----------|---------|-------------|
|
||||
| `stable` | `auto-release.yml` | Merge PR to `main` | `stable` |
|
||||
| `development` | `update-server.yml` | Merge PR to `dev/**` | `development` |
|
||||
| `alpha` | `update-server.yml` | Merge PR to `alpha/**` | `alpha` |
|
||||
| `beta` | `update-server.yml` | Merge PR to `beta/**` | `beta` |
|
||||
| `rc` | `update-server.yml` | Merge PR to `rc/**` | `release-candidate` |
|
||||
|
||||
## Usage
|
||||
|
||||
### For New Projects
|
||||
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
|
||||
# Hardcoded authorized users — always allowed
|
||||
case "$ACTOR" in
|
||||
jmiller-moko|github-actions\[bot\])
|
||||
jmiller|gitea-actions[bot])
|
||||
ALLOWED=true
|
||||
PERMISSION=admin
|
||||
METHOD="hardcoded allowlist"
|
||||
|
||||
@@ -293,7 +293,7 @@ jobs:
|
||||
|
||||
# Search for an existing health-check issue (any state)
|
||||
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/issues?labels=${LABEL}&state=all&per_page=1&sort=updated&direction=desc" 2>/dev/null \
|
||||
--jq '.[0].number' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.[0].number')
|
||||
|
||||
if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ]; then
|
||||
# Check if it's closed — reopen if so
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# | 8. Build ZIP, upload asset, write SHA-256 to updates.xml |
|
||||
# | |
|
||||
# | Every version change: archives main -> version/XX.YY branch |
|
||||
# | Patch 00 = development (no release). First release = patch 01. |
|
||||
# | All patches release (including 00). Patch 00/01 = full pipeline. |
|
||||
# | First release only (patch == 01): |
|
||||
# | 7b. Create new Gitea Release |
|
||||
# | |
|
||||
@@ -73,9 +73,9 @@ jobs:
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
|
||||
run: |
|
||||
git clone --depth 1 --branch {{standards_branch}} --quiet \
|
||||
git clone --depth 1 --branch main --quiet \
|
||||
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||
/tmp/mokostandards-api
|
||||
cd /tmp/mokostandards-api
|
||||
@@ -102,22 +102,15 @@ jobs:
|
||||
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
|
||||
echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
|
||||
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
|
||||
echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT"
|
||||
# Determine stability for mirror gating
|
||||
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
|
||||
echo "stability=stable" >> "$GITHUB_OUTPUT"
|
||||
if [ "$PATCH" = "00" ]; then
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
echo "is_minor=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (patch 00 = development — skipping release)"
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
if [ "$PATCH" = "00" ] || [ "$PATCH" = "01" ]; then
|
||||
echo "is_minor=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (first release for this minor — full pipeline)"
|
||||
else
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
if [ "$PATCH" = "01" ]; then
|
||||
echo "is_minor=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (first release — full pipeline)"
|
||||
else
|
||||
echo "is_minor=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (patch — platform version + badges only)"
|
||||
fi
|
||||
echo "is_minor=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Version: $VERSION (patch — platform version + badges only)"
|
||||
fi
|
||||
|
||||
- name: Check if already released
|
||||
@@ -296,9 +289,15 @@ jobs:
|
||||
[ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
|
||||
[ -z "$EXT_TYPE" ] && EXT_TYPE="component"
|
||||
|
||||
# Templates/modules don't have <element> — derive from <name> (lowercased)
|
||||
# Derive element if not in manifest:
|
||||
# 1. Try XML filename (e.g. mokowaas.xml → mokowaas)
|
||||
# 2. Fall back to repo name (lowercased)
|
||||
if [ -z "$EXT_ELEMENT" ]; then
|
||||
EXT_ELEMENT=$(echo "$EXT_NAME" | tr '[:upper:]' '[:lower:]' | tr -d ' ')
|
||||
EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
|
||||
# If filename is generic (templateDetails, manifest), use repo name
|
||||
case "$EXT_ELEMENT" in
|
||||
templatedetails|manifest|*.xml) EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Build client tag: plugins and frontend modules need <client>site</client>
|
||||
@@ -326,11 +325,12 @@ jobs:
|
||||
PHP_TAG="<php_minimum>${PHP_MINIMUM}</php_minimum>"
|
||||
fi
|
||||
|
||||
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/v${VERSION}/${EXT_ELEMENT}-${VERSION}.zip"
|
||||
INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/v${VERSION}"
|
||||
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/stable/${EXT_ELEMENT}-${VERSION}.zip"
|
||||
INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/stable"
|
||||
|
||||
# -- Build stable entry to temp file
|
||||
{
|
||||
# -- Build update entry for a given stability tag
|
||||
build_entry() {
|
||||
local TAG_NAME="$1"
|
||||
printf '%s\n' ' <update>'
|
||||
printf '%s\n' " <name>${EXT_NAME}</name>"
|
||||
printf '%s\n' " <description>${EXT_NAME} update</description>"
|
||||
@@ -339,9 +339,7 @@ jobs:
|
||||
printf '%s\n' " <version>${VERSION}</version>"
|
||||
[ -n "$CLIENT_TAG" ] && printf '%s\n' " ${CLIENT_TAG}"
|
||||
[ -n "$FOLDER_TAG" ] && printf '%s\n' " ${FOLDER_TAG}"
|
||||
printf '%s\n' ' <tags>'
|
||||
printf '%s\n' ' <tag>stable</tag>'
|
||||
printf '%s\n' ' </tags>'
|
||||
printf '%s\n' " <tags><tag>${TAG_NAME}</tag></tags>"
|
||||
printf '%s\n' " <infourl title=\"${EXT_NAME}\">${INFO_URL}</infourl>"
|
||||
printf '%s\n' ' <downloads>'
|
||||
printf '%s\n' " <downloadurl type=\"full\" format=\"zip\">${DOWNLOAD_URL}</downloadurl>"
|
||||
@@ -351,34 +349,27 @@ jobs:
|
||||
printf '%s\n' ' <maintainer>Moko Consulting</maintainer>'
|
||||
printf '%s\n' ' <maintainerurl>https://mokoconsulting.tech</maintainerurl>'
|
||||
printf '%s\n' ' </update>'
|
||||
} > /tmp/stable_entry.xml
|
||||
|
||||
# -- Write updates.xml preserving dev/rc entries
|
||||
# Extract existing entries for other stability levels
|
||||
if [ -f "updates.xml" ]; then
|
||||
printf 'import re, sys\n' > /tmp/extract.py
|
||||
printf 'with open("updates.xml") as f: c = f.read()\n' >> /tmp/extract.py
|
||||
printf 'tag = sys.argv[1]\n' >> /tmp/extract.py
|
||||
printf 'm = re.search(r"( <update>.*?<tag>" + re.escape(tag) + r"</tag>.*?</update>)", c, re.DOTALL)\n' >> /tmp/extract.py
|
||||
printf 'if m: print(m.group(1))\n' >> /tmp/extract.py
|
||||
fi
|
||||
DEV_ENTRY=$(python3 /tmp/extract.py development 2>/dev/null || true)
|
||||
ALPHA_ENTRY=$(python3 /tmp/extract.py alpha 2>/dev/null || true)
|
||||
BETA_ENTRY=$(python3 /tmp/extract.py beta 2>/dev/null || true)
|
||||
RC_ENTRY=$(python3 /tmp/extract.py rc 2>/dev/null || true)
|
||||
}
|
||||
|
||||
# -- Write updates.xml with cascading channels
|
||||
# Stable release updates ALL channels (development, alpha, beta, rc, stable)
|
||||
{
|
||||
printf '%s\n' '<?xml version="1.0" encoding="utf-8"?>'
|
||||
printf '%s\n' "<?xml version='1.0' encoding='UTF-8'?>"
|
||||
printf '%s\n' "<!-- Copyright (C) $(date +%Y) Moko Consulting <hello@mokoconsulting.tech>"
|
||||
printf '%s\n' " SPDX-License-Identifier: GPL-3.0-or-later"
|
||||
printf '%s\n' " VERSION: ${VERSION}"
|
||||
printf '%s\n' " -->"
|
||||
printf '%s\n' ""
|
||||
printf '%s\n' '<updates>'
|
||||
[ -n "$DEV_ENTRY" ] && echo "$DEV_ENTRY"
|
||||
[ -n "$ALPHA_ENTRY" ] && echo "$ALPHA_ENTRY"
|
||||
[ -n "$BETA_ENTRY" ] && echo "$BETA_ENTRY"
|
||||
[ -n "$RC_ENTRY" ] && echo "$RC_ENTRY"
|
||||
cat /tmp/stable_entry.xml
|
||||
build_entry "development"
|
||||
build_entry "alpha"
|
||||
build_entry "beta"
|
||||
build_entry "rc"
|
||||
build_entry "stable"
|
||||
printf '%s\n' '</updates>'
|
||||
} > updates.xml
|
||||
|
||||
echo "updates.xml: ${VERSION} (stable + rc/dev preserved)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "updates.xml: ${VERSION} (all channels updated to stable)" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# -- Commit all changes ---------------------------------------------------
|
||||
- name: Commit release changes
|
||||
@@ -393,10 +384,12 @@ jobs:
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
# Set push URL with token for branch-protected repos
|
||||
git remote set-url origin "https://jmiller:${{ secrets.GA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
||||
git add -A
|
||||
git commit -m "chore(release): build ${VERSION} [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||
git push
|
||||
git push -u origin HEAD
|
||||
|
||||
# -- STEP 6: Create tag ---------------------------------------------------
|
||||
- name: "Step 6: Create git tag"
|
||||
@@ -577,9 +570,9 @@ jobs:
|
||||
block = re.sub(r' <downloads>.*?</downloads>', new_downloads, block, flags=re.DOTALL)
|
||||
# Add or replace sha256
|
||||
if '<sha256>' in block:
|
||||
block = re.sub(r' <sha256>.*?</sha256>', f' <sha256>sha256:{sha}</sha256>', block)
|
||||
block = re.sub(r' <sha256>.*?</sha256>', f' <sha256>{sha}</sha256>', block)
|
||||
else:
|
||||
block = block.replace('</downloads>', f'</downloads>\n <sha256>sha256:{sha}</sha256>')
|
||||
block = block.replace('</downloads>', f'</downloads>\n <sha256>{sha}</sha256>')
|
||||
return block
|
||||
|
||||
content = re.sub(
|
||||
@@ -593,10 +586,76 @@ jobs:
|
||||
f.write(content)
|
||||
PYEOF
|
||||
|
||||
CURRENT_BRANCH="${{ github.ref_name }}"
|
||||
git add updates.xml
|
||||
git commit -m "chore(release): ZIP + tar.gz for ${VERSION} [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" || true
|
||||
git push || true
|
||||
|
||||
# Sync updates.xml to main via PR (respects branch protection)
|
||||
if [ "$CURRENT_BRANCH" != "main" ]; then
|
||||
GA_TOKEN="${{ secrets.GA_TOKEN }}"
|
||||
API="${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}"
|
||||
PR_BRANCH="chore/update-xml-${VERSION}"
|
||||
|
||||
# Create branch from main
|
||||
MAIN_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/branches/main" | jq -r '.commit.sha // empty')
|
||||
|
||||
if [ -n "$MAIN_SHA" ]; then
|
||||
curl -sf -X POST -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/branches" \
|
||||
-d "$(jq -n --arg name "$PR_BRANCH" --arg sha "$MAIN_SHA" \
|
||||
'{new_branch_name: $name, old_branch_name: "main"}')" > /dev/null 2>&1 || true
|
||||
|
||||
# Update updates.xml on the PR branch
|
||||
FILE_SHA=$(curl -sf -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/contents/updates.xml?ref=${PR_BRANCH}" | jq -r '.sha // empty')
|
||||
|
||||
if [ -n "$FILE_SHA" ]; then
|
||||
CONTENT=$(base64 -w0 updates.xml)
|
||||
curl -sf -X PUT -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/contents/updates.xml" \
|
||||
-d "$(jq -n \
|
||||
--arg content "$CONTENT" \
|
||||
--arg sha "$FILE_SHA" \
|
||||
--arg msg "chore: update stable channel to ${VERSION} [skip ci]" \
|
||||
--arg branch "$PR_BRANCH" \
|
||||
'{content: $content, sha: $sha, message: $msg, branch: $branch}'
|
||||
)" > /dev/null 2>&1
|
||||
|
||||
# Create PR
|
||||
PR_URL=$(curl -sf -X POST -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/pulls" \
|
||||
-d "$(jq -n \
|
||||
--arg title "chore: update updates.xml for ${VERSION} [skip ci]" \
|
||||
--arg head "$PR_BRANCH" \
|
||||
--arg base "main" \
|
||||
--arg body "Auto-generated by release workflow. Updates updates.xml with SHA-256 and download URLs for ${VERSION}." \
|
||||
'{title: $title, head: $head, base: $base, body: $body}'
|
||||
)" | jq -r '.number // empty')
|
||||
|
||||
# Auto-merge the PR
|
||||
if [ -n "$PR_URL" ]; then
|
||||
curl -sf -X POST -H "Authorization: token ${GA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"${API}/pulls/${PR_URL}/merge" \
|
||||
-d '{"Do":"merge","merge_message_field":"chore: update updates.xml for '"${VERSION}"' [skip ci]"}' > /dev/null 2>&1 \
|
||||
&& echo "updates.xml synced to main via PR #${PR_URL}" \
|
||||
|| echo "PR #${PR_URL} created but auto-merge failed — merge manually"
|
||||
|
||||
# Cleanup: delete PR branch
|
||||
curl -sf -X DELETE -H "Authorization: token ${GA_TOKEN}" \
|
||||
"${API}/branches/${PR_BRANCH}" > /dev/null 2>&1 || true
|
||||
else
|
||||
echo "WARNING: failed to create PR for updates.xml sync"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "### Joomla Packages" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -613,10 +672,10 @@ jobs:
|
||||
if: >-
|
||||
steps.version.outputs.skip != 'true' &&
|
||||
steps.version.outputs.stability == 'stable' &&
|
||||
secrets.GH_MIRROR_TOKEN != ''
|
||||
secrets.GH_TOKEN != ''
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_MIRROR_TOKEN }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
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' }}
|
||||
run: |
|
||||
git clone --depth 1 --branch {{standards_branch}} --quiet \
|
||||
git clone --depth 1 --branch main --quiet \
|
||||
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||
/tmp/mokostandards-api
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# PATH: /templates/workflows/joomla/deploy-manual.yml.template
|
||||
# VERSION: 04.06.00
|
||||
# BRIEF: Manual SFTP deploy to dev server for Joomla repos
|
||||
# NOTE: Joomla repos use update.xml for distribution. This is for manual
|
||||
# NOTE: Joomla repos use updates.xml for distribution. This is for manual
|
||||
# dev server testing only — triggered via workflow_dispatch.
|
||||
|
||||
name: Deploy to Dev (Manual)
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
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 {{standards_branch}} --quiet \
|
||||
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
|
||||
|
||||
@@ -6,11 +6,11 @@ This directory contains GitHub Actions workflow templates specifically designed
|
||||
|
||||
## Available Templates
|
||||
|
||||
- **ci.yml** - Continuous integration workflow with PHP validation, XML checking, and manifest verification
|
||||
- **test.yml** - Comprehensive testing workflow with PHPUnit, code quality checks, and integration tests
|
||||
- **release.yml** - Automated release workflow for creating and publishing Joomla extension packages
|
||||
- **repo_health.yml** - Repository health monitoring including documentation checks and standards validation
|
||||
- **version_branch.yml** - Automated version branch management and release preparation
|
||||
- **auto-release.yml.template** - Build & release pipeline for stable releases on merge to main. Reads version from README.md, builds ZIP+tar.gz, creates/updates Gitea release, updates only the stable channel in updates.xml. Mirrors to GitHub for stable releases.
|
||||
- **update-server.yml.template** - Multi-channel Joomla update server. Triggers on dev/alpha/beta/rc branch merges, builds packages, uploads to per-channel Gitea releases, updates only the matching stability channel in updates.xml. All patches release (including patch 00).
|
||||
- **ci-joomla.yml.template** - Continuous integration workflow with PHP validation, XML checking, and manifest verification
|
||||
- **deploy-manual.yml.template** - Manual deployment workflow for Joomla extensions
|
||||
- **repo_health.yml.template** - Repository health monitoring including documentation checks and standards validation
|
||||
|
||||
## Metadata
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
|
||||
# Hardcoded authorized users — always allowed
|
||||
case "$ACTOR" in
|
||||
jmiller-moko|github-actions\[bot\])
|
||||
jmiller|gitea-actions[bot])
|
||||
ALLOWED=true
|
||||
PERMISSION=admin
|
||||
METHOD="hardcoded allowlist"
|
||||
|
||||
@@ -71,9 +71,9 @@ jobs:
|
||||
env:
|
||||
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
|
||||
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_TOKEN }}"}}'
|
||||
run: |
|
||||
git clone --depth 1 --branch {{standards_branch}} --quiet \
|
||||
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
|
||||
@@ -88,18 +88,16 @@ jobs:
|
||||
API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}"
|
||||
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null || echo "0.0.0")
|
||||
|
||||
# Auto-bump patch on alpha/beta/rc branches (not dev — dev bumps manually)
|
||||
if [[ "$BRANCH" != dev/* ]]; then
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
BUMPED=$(php /tmp/mokostandards-api/cli/version_bump.php --path . 2>/dev/null || true)
|
||||
if [ -n "$BUMPED" ]; then
|
||||
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null || echo "$VERSION")
|
||||
git add -A
|
||||
git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" 2>/dev/null || true
|
||||
git push 2>/dev/null || true
|
||||
fi
|
||||
# Auto-bump patch on all branches (dev, alpha, beta, rc)
|
||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||
git config --local user.name "gitea-actions[bot]"
|
||||
BUMPED=$(php /tmp/mokostandards-api/cli/version_bump.php --path . 2>/dev/null || true)
|
||||
if [ -n "$BUMPED" ]; then
|
||||
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null || echo "$VERSION")
|
||||
git add -A
|
||||
git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
|
||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" 2>/dev/null || true
|
||||
git push 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Determine stability from branch or input
|
||||
@@ -140,9 +138,12 @@ jobs:
|
||||
[ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
|
||||
[ -z "$EXT_TYPE" ] && EXT_TYPE="component"
|
||||
|
||||
# Templates and modules don't have <element> — derive from <name>
|
||||
# Derive element if not in manifest: try XML filename, then repo name
|
||||
if [ -z "$EXT_ELEMENT" ]; then
|
||||
EXT_ELEMENT=$(echo "$EXT_NAME" | tr '[:upper:]' '[:lower:]' | tr -d ' ')
|
||||
EXT_ELEMENT=$(basename "$MANIFEST" .xml | tr '[:upper:]' '[:lower:]')
|
||||
case "$EXT_ELEMENT" in
|
||||
templatedetails|manifest|*.xml) EXT_ELEMENT=$(echo "${{ github.event.repository.name }}" | tr '[:upper:]' '[:lower:]' | tr -d ' -') ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Use manifest version if README version is empty
|
||||
@@ -274,7 +275,7 @@ jobs:
|
||||
NEW_ENTRY="${NEW_ENTRY} <downloadurl type=\"full\" format=\"zip\">${DOWNLOAD_URL}</downloadurl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <downloadurl type=\"full\" format=\"tar.gz\">${TAR_URL}</downloadurl>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} </downloads>\n"
|
||||
[ -n "$SHA256" ] && NEW_ENTRY="${NEW_ENTRY} <sha256>sha256:${SHA256}</sha256>\n"
|
||||
[ -n "$SHA256" ] && NEW_ENTRY="${NEW_ENTRY} <sha256>${SHA256}</sha256>\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} ${TARGET_PLATFORM}\n"
|
||||
[ -n "$PHP_TAG" ] && NEW_ENTRY="${NEW_ENTRY} ${PHP_TAG}\n"
|
||||
NEW_ENTRY="${NEW_ENTRY} <maintainer>Moko Consulting</maintainer>\n"
|
||||
@@ -285,23 +286,50 @@ jobs:
|
||||
printf '%b' "$NEW_ENTRY" > /tmp/new_entry.xml
|
||||
|
||||
# -- Merge into updates.xml (only update this stability channel) -
|
||||
# Cascading update: each stability level updates itself and all lower levels
|
||||
# stable → all | rc → rc,beta,alpha,dev | beta → beta,alpha,dev | alpha → alpha,dev | dev → dev
|
||||
CASCADE_MAP="stable:development,alpha,beta,rc,stable rc:development,alpha,beta,rc beta:development,alpha,beta alpha:development,alpha development:development"
|
||||
TARGETS=""
|
||||
for entry in $CASCADE_MAP; do
|
||||
key="${entry%%:*}"
|
||||
vals="${entry#*:}"
|
||||
if [ "$key" = "${STABILITY}" ]; then
|
||||
TARGETS="$vals"
|
||||
break
|
||||
fi
|
||||
done
|
||||
[ -z "$TARGETS" ] && TARGETS="${STABILITY}"
|
||||
|
||||
if [ ! -f "updates.xml" ]; then
|
||||
printf '%s\n' '<?xml version="1.0" encoding="utf-8"?>' > updates.xml
|
||||
printf '%s\n' "<?xml version='1.0' encoding='UTF-8'?>" > updates.xml
|
||||
printf '%s\n' "<!-- Copyright (C) $(date +%Y) Moko Consulting <hello@mokoconsulting.tech>" >> updates.xml
|
||||
printf '%s\n' " SPDX-License-Identifier: GPL-3.0-or-later" >> updates.xml
|
||||
printf '%s\n' " VERSION: ${VERSION}" >> updates.xml
|
||||
printf '%s\n' " -->" >> updates.xml
|
||||
printf '%s\n' "" >> updates.xml
|
||||
printf '%s\n' '<updates>' >> updates.xml
|
||||
cat /tmp/new_entry.xml >> updates.xml
|
||||
printf '\n%s\n' '</updates>' >> updates.xml
|
||||
else
|
||||
# Remove existing entry for this stability, insert new one
|
||||
# Replace each cascading channel with the new entry (different tag)
|
||||
export PY_TARGETS="$TARGETS"
|
||||
python3 << PYEOF
|
||||
import re
|
||||
import re, os
|
||||
targets = os.environ["PY_TARGETS"].split(",")
|
||||
stability = "${STABILITY}"
|
||||
with open("updates.xml") as f:
|
||||
content = f.read()
|
||||
with open("/tmp/new_entry.xml") as f:
|
||||
new_entry = f.read()
|
||||
pattern = r" <update>.*?<tag>" + re.escape(stability) + r"</tag>.*?</update>\n?"
|
||||
content = re.sub(pattern, "", content, flags=re.DOTALL)
|
||||
content = content.replace("</updates>", new_entry + "\n</updates>")
|
||||
new_entry_template = f.read()
|
||||
for tag in targets:
|
||||
tag = tag.strip()
|
||||
# Build entry with this tag
|
||||
new_entry = re.sub(r"<tag>[^<]*</tag>", f"<tag>{tag}</tag>", new_entry_template)
|
||||
# Remove existing entry for this tag
|
||||
pattern = r" <update>.*?<tag>" + re.escape(tag) + r"</tag>.*?</update>\n?"
|
||||
content = re.sub(pattern, "", content, flags=re.DOTALL)
|
||||
# Insert before </updates>
|
||||
content = content.replace("</updates>", new_entry + "\n</updates>")
|
||||
content = re.sub(r"\n{3,}", "\n\n", content)
|
||||
with open("updates.xml", "w") as f:
|
||||
f.write(content)
|
||||
@@ -309,7 +337,12 @@ jobs:
|
||||
if [ $? -ne 0 ]; then
|
||||
# Fallback: rebuild keeping other stability entries
|
||||
{
|
||||
printf '%s\n' '<?xml version="1.0" encoding="utf-8"?>'
|
||||
printf '%s\n' "<?xml version='1.0' encoding='UTF-8'?>"
|
||||
printf '%s\n' "<!-- Copyright (C) $(date +%Y) Moko Consulting <hello@mokoconsulting.tech>"
|
||||
printf '%s\n' " SPDX-License-Identifier: GPL-3.0-or-later"
|
||||
printf '%s\n' " VERSION: ${VERSION}"
|
||||
printf '%s\n' " -->"
|
||||
printf '%s\n' ""
|
||||
printf '%s\n' '<updates>'
|
||||
for TAG in stable rc development; do
|
||||
[ "$TAG" = "${STABILITY}" ] && continue
|
||||
@@ -338,10 +371,10 @@ jobs:
|
||||
- name: Mirror release to GitHub
|
||||
if: >-
|
||||
(steps.update.outputs.stability == 'stable' || steps.update.outputs.stability == 'rc') &&
|
||||
secrets.GH_MIRROR_TOKEN != ''
|
||||
secrets.GH_TOKEN != ''
|
||||
continue-on-error: true
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_MIRROR_TOKEN }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: |
|
||||
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
||||
STABILITY="${{ steps.update.outputs.stability }}"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
|
||||
# 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:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||
run: |
|
||||
REPO="${{ github.repository }}"
|
||||
ASSIGNEE="jmiller-moko"
|
||||
ASSIGNEE="jmiller"
|
||||
|
||||
echo "## 🏷️ Auto-Assign Report" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -44,10 +44,10 @@ jobs:
|
||||
ASSIGNED_PRS=0
|
||||
|
||||
# Assign unassigned open issues
|
||||
ISSUES=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/issues?state=open&per_page=100&assignee=none" --jq '.[].number' 2>/dev/null || true)
|
||||
ISSUES=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/issues?state=open&per_page=100&assignee=none" 2>/dev/null | jq -r '.[].number' || true)
|
||||
for NUM in $ISSUES; do
|
||||
# Skip PRs (the issues endpoint returns PRs too)
|
||||
IS_PR=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/issues/$NUM" --jq '.pull_request // empty' 2>/dev/null || true)
|
||||
IS_PR=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/issues/$NUM" 2>/dev/null | jq -r '.pull_request // empty' || true)
|
||||
if [ -z "$IS_PR" ]; then
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/issues/$NUM/assignees" -X POST -f "assignees[]=$ASSIGNEE" --silent 2>/dev/null && {
|
||||
ASSIGNED_ISSUES=$((ASSIGNED_ISSUES + 1))
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
done
|
||||
|
||||
# Assign unassigned open PRs
|
||||
PRS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/pulls?state=open&per_page=100" --jq '.[] | select(.assignees | length == 0) | .number' 2>/dev/null || true)
|
||||
PRS=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/pulls?state=open&per_page=100" 2>/dev/null | jq -r '.[] | select(.assignees | length == 0) | .number' || true)
|
||||
for NUM in $PRS; do
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/repos/${{ github.repository }}/issues/$NUM/assignees" -X POST -f "assignees[]=$ASSIGNEE" --silent 2>/dev/null && {
|
||||
ASSIGNED_PRS=$((ASSIGNED_PRS + 1))
|
||||
|
||||
@@ -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]+$')
|
||||
|
||||
|
||||
@@ -44,9 +44,10 @@ jobs:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||
run: |
|
||||
ACTOR="${{ github.actor }}"
|
||||
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||
REPO="${{ github.repository }}"
|
||||
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/collaborators/${ACTOR}/permission" 2>/dev/null \
|
||||
--jq '.permission' 2>/dev/null || echo "read")
|
||||
2>/dev/null | jq -r '.permission' || echo "read")
|
||||
if [ "$PERMISSION" != "admin" ]; then
|
||||
echo "Denied: only admins can freeze/unfreeze branches (${ACTOR} has ${PERMISSION})"
|
||||
exit 1
|
||||
@@ -80,7 +81,7 @@ jobs:
|
||||
printf '"conditions":{"ref_name":{"include":["refs/heads/%s"],"exclude":[]}},' "${BRANCH}" >> /tmp/ruleset.json
|
||||
printf '"rules":[{"type":"update"},{"type":"deletion"},{"type":"non_fast_forward"}]}' >> /tmp/ruleset.json
|
||||
|
||||
RESULT=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/rulesets" 2>/dev/null -X POST --input /tmp/ruleset.json --jq '.id' 2>&1) || true
|
||||
RESULT=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/rulesets" 2>/dev/null -X POST -d @/tmp/ruleset.json 2>&1 | jq -r '.id') || true
|
||||
|
||||
if echo "$RESULT" | grep -qE '^[0-9]+$'; then
|
||||
echo "Frozen \`${BRANCH}\` — ruleset #${RESULT}" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
@@ -79,6 +79,7 @@ jobs:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||
run: |
|
||||
ACTOR="${{ github.actor }}"
|
||||
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||
REPO="${{ github.repository }}"
|
||||
ORG="${{ github.repository_owner }}"
|
||||
|
||||
@@ -86,7 +87,7 @@ jobs:
|
||||
AUTHORIZED="false"
|
||||
|
||||
# Hardcoded authorized users — always allowed to deploy
|
||||
AUTHORIZED_USERS="jmiller-moko gitea-actions[bot]"
|
||||
AUTHORIZED_USERS="jmiller gitea-actions[bot]"
|
||||
for user in $AUTHORIZED_USERS; do
|
||||
if [ "$ACTOR" = "$user" ]; then
|
||||
AUTHORIZED="true"
|
||||
@@ -99,12 +100,12 @@ jobs:
|
||||
# For other actors, check repo/org permissions via API
|
||||
if [ "$AUTHORIZED" != "true" ]; then
|
||||
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/collaborators/${ACTOR}/permission" 2>/dev/null \
|
||||
--jq '.permission' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.permission')
|
||||
METHOD="repo collaborator API"
|
||||
|
||||
if [ -z "$PERMISSION" ]; then
|
||||
ORG_ROLE=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/orgs/${ORG}/memberships/${ACTOR}" \
|
||||
--jq '.role' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.role')
|
||||
METHOD="org membership API"
|
||||
if [ "$ORG_ROLE" = "owner" ]; then
|
||||
PERMISSION="admin"
|
||||
@@ -637,6 +638,7 @@ jobs:
|
||||
REPO="${{ github.repository }}"
|
||||
RUN_URL="${{ github.server_url }}/${REPO}/actions/runs/${{ github.run_id }}"
|
||||
ACTOR="${{ github.actor }}"
|
||||
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||
BRANCH="${{ github.ref_name }}"
|
||||
EVENT="${{ github.event_name }}"
|
||||
NOW=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||
@@ -673,7 +675,7 @@ jobs:
|
||||
|
||||
# Look for an existing open deploy-failure issue
|
||||
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/issues?labels=${LABEL}&state=all&per_page=1&sort=created&direction=desc" 2>/dev/null \
|
||||
--jq '.[0].number' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.[0].number')
|
||||
|
||||
if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ]; then
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/issues/${EXISTING}" 2>/dev/null \
|
||||
@@ -689,7 +691,7 @@ jobs:
|
||||
--title "$TITLE" \
|
||||
--body "$BODY" \
|
||||
--label "$LABEL" \
|
||||
--assignee "jmiller-moko" \
|
||||
--assignee "jmiller" \
|
||||
| tee -a "$GITHUB_STEP_SUMMARY"
|
||||
fi
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ jobs:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||
run: |
|
||||
ACTOR="${{ github.actor }}"
|
||||
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||
REPO="${{ github.repository }}"
|
||||
ORG="${{ github.repository_owner }}"
|
||||
|
||||
@@ -90,7 +91,7 @@ jobs:
|
||||
AUTHORIZED="false"
|
||||
|
||||
# Hardcoded authorized users — always allowed to deploy
|
||||
AUTHORIZED_USERS="jmiller-moko gitea-actions[bot]"
|
||||
AUTHORIZED_USERS="jmiller gitea-actions[bot]"
|
||||
for user in $AUTHORIZED_USERS; do
|
||||
if [ "$ACTOR" = "$user" ]; then
|
||||
AUTHORIZED="true"
|
||||
@@ -103,12 +104,12 @@ jobs:
|
||||
# For other actors, check repo/org permissions via API
|
||||
if [ "$AUTHORIZED" != "true" ]; then
|
||||
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/collaborators/${ACTOR}/permission" 2>/dev/null \
|
||||
--jq '.permission' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.permission')
|
||||
METHOD="repo collaborator API"
|
||||
|
||||
if [ -z "$PERMISSION" ]; then
|
||||
ORG_ROLE=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/orgs/${ORG}/memberships/${ACTOR}" \
|
||||
--jq '.role' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.role')
|
||||
METHOD="org membership API"
|
||||
if [ "$ORG_ROLE" = "owner" ]; then
|
||||
PERMISSION="admin"
|
||||
|
||||
@@ -87,6 +87,7 @@ jobs:
|
||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||
run: |
|
||||
ACTOR="${{ github.actor }}"
|
||||
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||
REPO="${{ github.repository }}"
|
||||
ORG="${{ github.repository_owner }}"
|
||||
|
||||
@@ -94,7 +95,7 @@ jobs:
|
||||
AUTHORIZED="false"
|
||||
|
||||
# Hardcoded authorized users — always allowed to deploy
|
||||
AUTHORIZED_USERS="jmiller-moko gitea-actions[bot]"
|
||||
AUTHORIZED_USERS="jmiller gitea-actions[bot]"
|
||||
for user in $AUTHORIZED_USERS; do
|
||||
if [ "$ACTOR" = "$user" ]; then
|
||||
AUTHORIZED="true"
|
||||
@@ -107,12 +108,12 @@ jobs:
|
||||
# For other actors, check repo/org permissions via API
|
||||
if [ "$AUTHORIZED" != "true" ]; then
|
||||
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/collaborators/${ACTOR}/permission" 2>/dev/null \
|
||||
--jq '.permission' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.permission')
|
||||
METHOD="repo collaborator API"
|
||||
|
||||
if [ -z "$PERMISSION" ]; then
|
||||
ORG_ROLE=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/orgs/${ORG}/memberships/${ACTOR}" \
|
||||
--jq '.role' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.role')
|
||||
METHOD="org membership API"
|
||||
if [ "$ORG_ROLE" = "owner" ]; then
|
||||
PERMISSION="admin"
|
||||
@@ -579,6 +580,7 @@ jobs:
|
||||
REPO="${{ github.repository }}"
|
||||
RUN_URL="${{ github.server_url }}/${REPO}/actions/runs/${{ github.run_id }}"
|
||||
ACTOR="${{ github.actor }}"
|
||||
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||
BRANCH="${{ github.ref_name }}"
|
||||
EVENT="${{ github.event_name }}"
|
||||
NOW=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||
@@ -615,7 +617,7 @@ jobs:
|
||||
|
||||
# Look for an existing deploy-failure issue (any state — reopen if closed)
|
||||
EXISTING=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/issues?labels=${LABEL}&state=all&per_page=1&sort=created&direction=desc" 2>/dev/null \
|
||||
--jq '.[0].number' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.[0].number')
|
||||
|
||||
if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ]; then
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/issues/${EXISTING}" 2>/dev/null \
|
||||
@@ -631,7 +633,7 @@ jobs:
|
||||
--title "$TITLE" \
|
||||
--body "$BODY" \
|
||||
--label "$LABEL" \
|
||||
--assignee "jmiller-moko" \
|
||||
--assignee "jmiller" \
|
||||
| tee -a "$GITHUB_STEP_SUMMARY"
|
||||
fi
|
||||
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoStandards-API.Deployment
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
# PATH: /templates/workflows/shared/export-mysql.yml.template
|
||||
# VERSION: 04.06.12
|
||||
# BRIEF: Export MySQL database from dev/demo server and save as artifact or commit
|
||||
|
||||
name: Export MySQL Database
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
environment:
|
||||
description: 'Which server to export from'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- dev
|
||||
- demo
|
||||
default: 'dev'
|
||||
database:
|
||||
description: 'Database name (overrides variable)'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
save_to_repo:
|
||||
description: 'Commit SQL dump to repo (otherwise artifact only)'
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
branch:
|
||||
description: 'Branch to commit to (if save_to_repo)'
|
||||
required: false
|
||||
type: string
|
||||
default: 'dev'
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Required secrets and variables (per environment):
|
||||
#
|
||||
# DEV ENVIRONMENT — secrets/variables:
|
||||
# DEV_SSH_HOST — Dev server hostname
|
||||
# DEV_SSH_PORT — SSH port (default: 22)
|
||||
# DEV_SSH_USERNAME — SSH user
|
||||
# DEV_SSH_KEY — SSH private key
|
||||
# DEV_PULL_PATH — Remote install path (repo variable)
|
||||
#
|
||||
# DEMO ENVIRONMENT — secrets/variables:
|
||||
# DEMO_FTP_HOST — Demo server hostname (reused from deploy)
|
||||
# DEMO_FTP_PORT — SSH port (reused, default: 22)
|
||||
# DEMO_FTP_USERNAME — SSH user (reused from deploy)
|
||||
# DEMO_FTP_KEY — SSH key (reused from deploy)
|
||||
# DEMO_FTP_PATH — Remote install path (repo variable)
|
||||
#
|
||||
# MySQL credentials are read automatically from:
|
||||
# Joomla: configuration.php ($user, $password, $db)
|
||||
# Dolibarr: conf/conf.php ($dolibarr_main_db_user, etc.)
|
||||
# No MySQL secrets needed — credentials come from the remote config file.
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
export-mysql:
|
||||
name: Export MySQL — ${{ inputs.environment }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
if: inputs.save_to_repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
|
||||
- name: Resolve environment config
|
||||
id: env
|
||||
run: |
|
||||
ENV="${{ inputs.environment }}"
|
||||
|
||||
if [ "$ENV" = "dev" ]; then
|
||||
HOST="${{ vars.DEV_SSH_HOST }}"
|
||||
PORT="${{ vars.DEV_SSH_PORT || '22' }}"
|
||||
USER="${{ vars.DEV_SSH_USERNAME }}"
|
||||
DB="${{ inputs.database || vars.DEV_MYSQL_DATABASE }}"
|
||||
MYSQL_USER="${{ vars.DEV_MYSQL_USER || 'root' }}"
|
||||
elif [ "$ENV" = "demo" ]; then
|
||||
HOST="${{ vars.DEMO_FTP_HOST }}"
|
||||
PORT="${{ vars.DEMO_FTP_PORT || '22' }}"
|
||||
USER="${{ vars.DEMO_FTP_USERNAME }}"
|
||||
DB="${{ inputs.database || vars.DEMO_MYSQL_DATABASE }}"
|
||||
MYSQL_USER="${{ vars.DEMO_MYSQL_USER || 'root' }}"
|
||||
fi
|
||||
|
||||
MISSING=""
|
||||
[ -z "$HOST" ] && MISSING="${MISSING} ${ENV^^}_SSH_HOST"
|
||||
[ -z "$USER" ] && MISSING="${MISSING} ${ENV^^}_SSH_USERNAME"
|
||||
[ -z "$DB" ] && MISSING="${MISSING} ${ENV^^}_MYSQL_DATABASE"
|
||||
if [ -n "$MISSING" ]; then
|
||||
echo "ERROR: Missing variables:${MISSING}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "host=${HOST}" >> $GITHUB_OUTPUT
|
||||
echo "port=${PORT}" >> $GITHUB_OUTPUT
|
||||
echo "user=${USER}" >> $GITHUB_OUTPUT
|
||||
echo "database=${DB}" >> $GITHUB_OUTPUT
|
||||
echo "mysql_user=${MYSQL_USER}" >> $GITHUB_OUTPUT
|
||||
echo "Config OK — exporting ${DB} from ${USER}@${HOST}"
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
|
||||
ENV="${{ inputs.environment }}"
|
||||
if [ "$ENV" = "dev" ]; then
|
||||
KEY="${{ secrets.DEV_SSH_KEY }}"
|
||||
else
|
||||
KEY="${{ secrets.DEMO_FTP_KEY }}"
|
||||
fi
|
||||
|
||||
if [ -n "$KEY" ]; then
|
||||
echo "$KEY" > ~/.ssh/export_key
|
||||
chmod 600 ~/.ssh/export_key
|
||||
else
|
||||
echo "ERROR: No SSH key found for ${ENV} environment"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Host *" > ~/.ssh/config
|
||||
echo " StrictHostKeyChecking no" >> ~/.ssh/config
|
||||
echo " UserKnownHostsFile /dev/null" >> ~/.ssh/config
|
||||
chmod 600 ~/.ssh/config
|
||||
|
||||
- name: Export MySQL database
|
||||
id: export
|
||||
run: |
|
||||
HOST="${{ steps.env.outputs.host }}"
|
||||
PORT="${{ steps.env.outputs.port }}"
|
||||
USER="${{ steps.env.outputs.user }}"
|
||||
DB="${{ steps.env.outputs.database }}"
|
||||
ENV="${{ inputs.environment }}"
|
||||
CONFIG_PATH="${{ vars.DEV_PULL_PATH || vars.DEMO_FTP_PATH }}"
|
||||
|
||||
# Read MySQL credentials from the remote config file
|
||||
# Joomla: configuration.php → $user, $password, $db
|
||||
# Dolibarr: conf/conf.php → $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name
|
||||
echo "Reading MySQL credentials from remote config file..."
|
||||
|
||||
CREDS=$(ssh -p "${PORT}" -i ~/.ssh/export_key "${USER}@${HOST}" bash << 'SSHEOF'
|
||||
# Try Joomla configuration.php first
|
||||
for cfg in "{{CONFIG_PATH}}/configuration.php" "/var/www/html/configuration.php" "$(find /var/www -name 'configuration.php' -maxdepth 3 2>/dev/null | head -1)"; do
|
||||
if [ -f "$cfg" ]; then
|
||||
DB_USER=$(php -r "include '$cfg'; echo \$user ?? '';")
|
||||
DB_PASS=$(php -r "include '$cfg'; echo \$password ?? '';")
|
||||
DB_NAME=$(php -r "include '$cfg'; echo \$db ?? '';")
|
||||
DB_HOST=$(php -r "include '$cfg'; echo \$host ?? 'localhost';")
|
||||
if [ -n "$DB_USER" ] && [ -n "$DB_NAME" ]; then
|
||||
echo "TYPE=joomla"
|
||||
echo "DB_USER=$DB_USER"
|
||||
echo "DB_PASS=$DB_PASS"
|
||||
echo "DB_NAME=$DB_NAME"
|
||||
echo "DB_HOST=$DB_HOST"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Try Dolibarr conf/conf.php
|
||||
for cfg in "{{CONFIG_PATH}}/conf/conf.php" "/var/www/html/conf/conf.php" "$(find /var/www -name 'conf.php' -path '*/conf/*' -maxdepth 4 2>/dev/null | head -1)"; do
|
||||
if [ -f "$cfg" ]; then
|
||||
DB_USER=$(php -r "include '$cfg'; echo \$dolibarr_main_db_user ?? '';")
|
||||
DB_PASS=$(php -r "include '$cfg'; echo \$dolibarr_main_db_pass ?? '';")
|
||||
DB_NAME=$(php -r "include '$cfg'; echo \$dolibarr_main_db_name ?? '';")
|
||||
DB_HOST=$(php -r "include '$cfg'; echo \$dolibarr_main_db_host ?? 'localhost';")
|
||||
if [ -n "$DB_USER" ] && [ -n "$DB_NAME" ]; then
|
||||
echo "TYPE=dolibarr"
|
||||
echo "DB_USER=$DB_USER"
|
||||
echo "DB_PASS=$DB_PASS"
|
||||
echo "DB_NAME=$DB_NAME"
|
||||
echo "DB_HOST=$DB_HOST"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo "TYPE=not_found"
|
||||
SSHEOF
|
||||
)
|
||||
|
||||
PLATFORM=$(echo "$CREDS" | grep "^TYPE=" | cut -d= -f2)
|
||||
MYSQL_USER=$(echo "$CREDS" | grep "^DB_USER=" | cut -d= -f2-)
|
||||
MYSQL_PASS=$(echo "$CREDS" | grep "^DB_PASS=" | cut -d= -f2-)
|
||||
DB_NAME=$(echo "$CREDS" | grep "^DB_NAME=" | cut -d= -f2-)
|
||||
DB_HOST_REMOTE=$(echo "$CREDS" | grep "^DB_HOST=" | cut -d= -f2-)
|
||||
|
||||
if [ "$PLATFORM" = "not_found" ]; then
|
||||
echo "ERROR: Could not find Joomla configuration.php or Dolibarr conf/conf.php on remote server"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Override DB name if explicitly provided
|
||||
[ -n "$DB" ] && DB_NAME="$DB"
|
||||
|
||||
echo "Platform: ${PLATFORM}"
|
||||
echo "Database: ${DB_NAME} (user: ${MYSQL_USER}, host: ${DB_HOST_REMOTE})"
|
||||
|
||||
TIMESTAMP=$(date -u +%Y%m%d_%H%M%S)
|
||||
FILENAME="${DB_NAME}_${ENV}_${TIMESTAMP}.sql"
|
||||
|
||||
echo "Exporting ${DB_NAME} from ${HOST}..."
|
||||
|
||||
# Run mysqldump over SSH using credentials from config file
|
||||
ssh -p "${PORT}" -i ~/.ssh/export_key "${USER}@${HOST}" \
|
||||
"mysqldump --single-transaction --no-tablespaces --routines --triggers \
|
||||
-h ${DB_HOST_REMOTE} -u ${MYSQL_USER} -p'${MYSQL_PASS}' ${DB_NAME}" \
|
||||
> "/tmp/${FILENAME}" 2>/tmp/mysqldump.err
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: mysqldump failed"
|
||||
cat /tmp/mysqldump.err
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SIZE=$(du -h "/tmp/${FILENAME}" | cut -f1)
|
||||
LINES=$(wc -l < "/tmp/${FILENAME}")
|
||||
echo "Export complete: ${FILENAME} (${SIZE}, ${LINES} lines)"
|
||||
|
||||
# ── Sanitize PII / credentials ──────────────────────────
|
||||
echo "Sanitizing sensitive data..."
|
||||
SANITIZED="/tmp/${FILENAME%.sql}_sanitized.sql"
|
||||
cp "/tmp/${FILENAME}" "$SANITIZED"
|
||||
|
||||
# Joomla sanitization
|
||||
# - Clear user passwords (set to bcrypt hash of 'sanitized')
|
||||
# - Clear session data
|
||||
# - Clear user email addresses (keep admin)
|
||||
# - Clear reset tokens
|
||||
BCRYPT_SANITIZED='$2y$10$sanitized.sanitized.sanitized.sanitized.sanitized.sa'
|
||||
sed -i \
|
||||
-e "s/\(VALUES([^)]*,'[^']*','\)\$2[ayb]\$[^']*\('/\1${BCRYPT_SANITIZED}'/g" \
|
||||
"$SANITIZED"
|
||||
|
||||
# Joomla: clear sessions table content
|
||||
sed -i '/INSERT INTO.*_session/d' "$SANITIZED"
|
||||
|
||||
# Joomla: sanitize user emails (replace with user{id}@sanitized.local)
|
||||
python3 -c "
|
||||
import re, sys
|
||||
|
||||
with open('$SANITIZED', encoding='utf-8', errors='replace') as f:
|
||||
content = f.read()
|
||||
|
||||
# Joomla users table: sanitize emails but keep structure
|
||||
# Pattern: email addresses in INSERT statements for user tables
|
||||
content = re.sub(
|
||||
r\"(['\\\"])([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})(['\\\"])\",
|
||||
lambda m: m.group(1) + 'user@sanitized.local' + m.group(3)
|
||||
if 'admin' not in m.group(2).lower() and 'moko' not in m.group(2).lower()
|
||||
else m.group(0),
|
||||
content
|
||||
)
|
||||
|
||||
# Dolibarr: clear API keys, passwords, session tokens
|
||||
content = re.sub(r\"'(api_key|pass_crypted|pass_temp|session_id|token)','[^']*'\", r\"'\1',''\", content)
|
||||
|
||||
# Dolibarr: clear LDAP passwords
|
||||
content = re.sub(r\"'ldap_pass','[^']*'\", \"'ldap_pass',''\", content)
|
||||
|
||||
# Clear any raw passwords or tokens in conf values
|
||||
content = re.sub(r\"'(smtp_pass|ftp_password|oauth_.*secret)','[^']*'\", r\"'\1','[SANITIZED]'\", content)
|
||||
|
||||
with open('$SANITIZED', 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
|
||||
print('Sanitization complete')
|
||||
" 2>/dev/null || echo "Python sanitization skipped (no python3)"
|
||||
|
||||
mv "$SANITIZED" "/tmp/${FILENAME}"
|
||||
echo "Sanitized: passwords, sessions, emails (admin/moko preserved)"
|
||||
|
||||
# Compress
|
||||
gzip "/tmp/${FILENAME}"
|
||||
GZ_SIZE=$(du -h "/tmp/${FILENAME}.gz" | cut -f1)
|
||||
echo "Compressed: ${FILENAME}.gz (${GZ_SIZE})"
|
||||
|
||||
echo "filename=${FILENAME}" >> $GITHUB_OUTPUT
|
||||
echo "gz_filename=${FILENAME}.gz" >> $GITHUB_OUTPUT
|
||||
echo "size=${GZ_SIZE}" >> $GITHUB_OUTPUT
|
||||
echo "lines=${LINES}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit to repo
|
||||
if: inputs.save_to_repo && steps.export.outputs.filename != ''
|
||||
run: |
|
||||
mkdir -p sql/exports
|
||||
cp "/tmp/${{ steps.export.outputs.gz_filename }}" "sql/exports/"
|
||||
|
||||
git config user.name "gitea-actions[bot]"
|
||||
git config user.email "gitea-actions[bot]@noreply.git.mokoconsulting.tech"
|
||||
git add sql/exports/
|
||||
git commit -m "chore(db): export ${{ steps.env.outputs.database }} from ${{ inputs.environment }}
|
||||
|
||||
File: ${{ steps.export.outputs.gz_filename }}
|
||||
Size: ${{ steps.export.outputs.size }}
|
||||
Lines: ${{ steps.export.outputs.lines }}
|
||||
Source: ${{ steps.env.outputs.user }}@${{ steps.env.outputs.host }}"
|
||||
git push origin ${{ inputs.branch }}
|
||||
echo "Committed to ${{ inputs.branch }}"
|
||||
|
||||
- name: Upload artifact
|
||||
if: steps.export.outputs.filename != ''
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mysql-export-${{ inputs.environment }}-${{ steps.env.outputs.database }}
|
||||
path: /tmp/${{ steps.export.outputs.gz_filename }}
|
||||
retention-days: 30
|
||||
|
||||
- name: Summary
|
||||
run: |
|
||||
echo "## MySQL Export — ${{ inputs.environment }}"
|
||||
echo ""
|
||||
echo "- Database: \`${{ steps.env.outputs.database }}\`"
|
||||
echo "- Server: \`${{ steps.env.outputs.host }}\`"
|
||||
echo "- File: \`${{ steps.export.outputs.gz_filename }}\`"
|
||||
echo "- Size: ${{ steps.export.outputs.size }}"
|
||||
echo "- Lines: ${{ steps.export.outputs.lines }}"
|
||||
if [ "${{ inputs.save_to_repo }}" = "true" ]; then
|
||||
echo "- Saved to: \`sql/exports/\` on branch \`${{ inputs.branch }}\`"
|
||||
else
|
||||
echo "- Available as workflow artifact (30 day retention)"
|
||||
fi
|
||||
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: rm -f ~/.ssh/export_key /tmp/*.sql /tmp/*.sql.gz
|
||||
@@ -0,0 +1,173 @@
|
||||
# Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
# FILE INFORMATION
|
||||
# DEFGROUP: Gitea.Workflow
|
||||
# INGROUP: MokoStandards-API.Deployment
|
||||
# REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
# PATH: /templates/workflows/shared/pull-from-dev.yml.template
|
||||
# VERSION: 04.06.12
|
||||
# BRIEF: Download files from dev server into repo src/ directory
|
||||
|
||||
name: Pull from Dev Server
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
remote_path:
|
||||
description: 'Remote path to download (overrides DEV_PULL_PATH variable)'
|
||||
required: false
|
||||
type: string
|
||||
default: ''
|
||||
target_dir:
|
||||
description: 'Local directory to save to'
|
||||
required: false
|
||||
type: string
|
||||
default: 'src'
|
||||
branch:
|
||||
description: 'Branch to commit to'
|
||||
required: false
|
||||
type: string
|
||||
default: 'dev'
|
||||
dry_run:
|
||||
description: 'Preview only (no commit)'
|
||||
required: false
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
# Required secrets and variables:
|
||||
#
|
||||
# SECRETS (org or repo level):
|
||||
# DEV_SSH_KEY — SSH private key for dev server access
|
||||
# DEV_SSH_PASSWORD — OR password auth (if not using key)
|
||||
#
|
||||
# VARIABLES (org or repo level):
|
||||
# DEV_SSH_HOST — Dev server hostname (e.g., dev.mokoconsulting.tech)
|
||||
# DEV_SSH_PORT — SSH port (default: 22)
|
||||
# DEV_SSH_USERNAME — SSH user
|
||||
# DEV_PULL_PATH — Remote path to download (e.g., /var/www/html/plugins/system/mokojoomtos)
|
||||
# ──────────────────────────────────────────────────────────────
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
pull-from-dev:
|
||||
name: Pull from Dev Server
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.branch }}
|
||||
|
||||
- name: Validate configuration
|
||||
run: |
|
||||
MISSING=""
|
||||
[ -z "${{ vars.DEV_SSH_HOST }}" ] && MISSING="${MISSING} DEV_SSH_HOST"
|
||||
[ -z "${{ vars.DEV_SSH_USERNAME }}" ] && MISSING="${MISSING} DEV_SSH_USERNAME"
|
||||
REMOTE="${{ inputs.remote_path || vars.DEV_PULL_PATH }}"
|
||||
[ -z "$REMOTE" ] && MISSING="${MISSING} DEV_PULL_PATH"
|
||||
if [ -n "$MISSING" ]; then
|
||||
echo "ERROR: Missing required variables:${MISSING}"
|
||||
echo "Set these as org or repo variables in Gitea Actions settings."
|
||||
exit 1
|
||||
fi
|
||||
echo "remote_path=${REMOTE}" >> $GITHUB_OUTPUT
|
||||
echo "Config OK — pulling from ${{ vars.DEV_SSH_USERNAME }}@${{ vars.DEV_SSH_HOST }}:${REMOTE}"
|
||||
id: config
|
||||
|
||||
- name: Setup SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
chmod 700 ~/.ssh
|
||||
|
||||
if [ -n "${{ secrets.DEV_SSH_KEY }}" ]; then
|
||||
echo "${{ secrets.DEV_SSH_KEY }}" > ~/.ssh/dev_key
|
||||
chmod 600 ~/.ssh/dev_key
|
||||
echo "Auth: SSH key"
|
||||
else
|
||||
echo "Auth: password (sshpass)"
|
||||
sudo apt-get install -y sshpass -qq
|
||||
fi
|
||||
|
||||
# Disable host key checking for automation
|
||||
echo "Host *" > ~/.ssh/config
|
||||
echo " StrictHostKeyChecking no" >> ~/.ssh/config
|
||||
echo " UserKnownHostsFile /dev/null" >> ~/.ssh/config
|
||||
chmod 600 ~/.ssh/config
|
||||
|
||||
- name: Download from dev server
|
||||
id: download
|
||||
run: |
|
||||
HOST="${{ vars.DEV_SSH_HOST }}"
|
||||
PORT="${{ vars.DEV_SSH_PORT || '22' }}"
|
||||
USER="${{ vars.DEV_SSH_USERNAME }}"
|
||||
REMOTE="${{ steps.config.outputs.remote_path }}"
|
||||
LOCAL="${{ inputs.target_dir }}"
|
||||
|
||||
echo "Downloading: ${USER}@${HOST}:${REMOTE} → ${LOCAL}/"
|
||||
|
||||
# Build rsync command
|
||||
SSH_CMD="ssh -p ${PORT}"
|
||||
if [ -f ~/.ssh/dev_key ]; then
|
||||
SSH_CMD="${SSH_CMD} -i ~/.ssh/dev_key"
|
||||
fi
|
||||
|
||||
# Rsync from remote to local (mirror mode, delete extra local files)
|
||||
rsync -avz --delete \
|
||||
-e "${SSH_CMD}" \
|
||||
"${USER}@${HOST}:${REMOTE}/" \
|
||||
"${LOCAL}/" \
|
||||
--exclude='.git' \
|
||||
--exclude='.gitignore' \
|
||||
--exclude='node_modules' \
|
||||
--exclude='vendor' \
|
||||
--exclude='cache' \
|
||||
--exclude='tmp' \
|
||||
--exclude='log' \
|
||||
2>&1 | tee /tmp/rsync.log
|
||||
|
||||
CHANGED=$(git status --porcelain "${LOCAL}/" | wc -l)
|
||||
echo "changed=${CHANGED}" >> $GITHUB_OUTPUT
|
||||
echo "Files changed: ${CHANGED}"
|
||||
|
||||
- name: Show diff
|
||||
if: steps.download.outputs.changed != '0'
|
||||
run: |
|
||||
echo "=== Changed files ==="
|
||||
git status --short "${{ inputs.target_dir }}/"
|
||||
echo ""
|
||||
echo "=== Diff summary ==="
|
||||
git diff --stat "${{ inputs.target_dir }}/"
|
||||
|
||||
- name: Commit and push
|
||||
if: steps.download.outputs.changed != '0' && inputs.dry_run != true
|
||||
run: |
|
||||
git config user.name "gitea-actions[bot]"
|
||||
git config user.email "gitea-actions[bot]@noreply.git.mokoconsulting.tech"
|
||||
git add "${{ inputs.target_dir }}/"
|
||||
git commit -m "chore(sync): pull latest from dev server
|
||||
|
||||
Source: ${{ vars.DEV_SSH_USERNAME }}@${{ vars.DEV_SSH_HOST }}:${{ steps.config.outputs.remote_path }}
|
||||
Files changed: ${{ steps.download.outputs.changed }}
|
||||
Triggered by: ${{ gitea.actor }}"
|
||||
git push origin ${{ inputs.branch }}
|
||||
echo "Pushed to ${{ inputs.branch }}"
|
||||
|
||||
- name: Summary
|
||||
run: |
|
||||
echo "## Pull from Dev Server"
|
||||
echo ""
|
||||
if [ "${{ inputs.dry_run }}" = "true" ]; then
|
||||
echo "**DRY RUN** — no changes committed"
|
||||
fi
|
||||
echo "- Source: \`${{ vars.DEV_SSH_USERNAME }}@${{ vars.DEV_SSH_HOST }}:${{ steps.config.outputs.remote_path }}\`"
|
||||
echo "- Target: \`${{ inputs.target_dir }}/\`"
|
||||
echo "- Changed files: ${{ steps.download.outputs.changed }}"
|
||||
|
||||
- name: Cleanup
|
||||
if: always()
|
||||
run: rm -f ~/.ssh/dev_key
|
||||
@@ -80,7 +80,7 @@ jobs:
|
||||
echo "✅ Scheduled run — authorized"
|
||||
exit 0
|
||||
fi
|
||||
AUTHORIZED_USERS="jmiller-moko gitea-actions[bot]"
|
||||
AUTHORIZED_USERS="jmiller gitea-actions[bot]"
|
||||
for user in $AUTHORIZED_USERS; do
|
||||
if [ "$ACTOR" = "$user" ]; then
|
||||
echo "✅ ${ACTOR} authorized"
|
||||
@@ -88,7 +88,7 @@ jobs:
|
||||
fi
|
||||
done
|
||||
PERMISSION=$(curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/collaborators/${ACTOR}/permission" 2>/dev/null \
|
||||
--jq '.permission' 2>/dev/null)
|
||||
2>/dev/null | jq -r '.permission')
|
||||
case "$PERMISSION" in
|
||||
admin|maintain) echo "✅ ${ACTOR} has ${PERMISSION}" ;;
|
||||
*) echo "❌ Admin or maintain required"; exit 1 ;;
|
||||
@@ -191,7 +191,7 @@ jobs:
|
||||
echo "## 🏷️ Label Reset" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/labels?per_page=100" 2>/dev/null --paginate --jq '.[].name' | while read -r label; do
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/labels?per_page=100" 2>/dev/null --jq '.[].name' | while read -r label; do
|
||||
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$label', safe=''))")
|
||||
curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/labels/${ENCODED}" 2>/dev/null || true
|
||||
done
|
||||
@@ -278,7 +278,7 @@ jobs:
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/branches?per_page=100" | jq -r '.[].name' 2>/dev/null | \
|
||||
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 list --repo "$REPO" --head "$branch" --state open --json number 2>/dev/null | jq -r '.[].number' | 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
|
||||
@@ -305,7 +305,7 @@ jobs:
|
||||
# Delete cancelled and stale workflow runs
|
||||
for status in cancelled stale; do
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/actions/runs?status=${status}&per_page=100" 2>/dev/null \
|
||||
--jq '.workflow_runs[].id' 2>/dev/null | while read -r run_id; do
|
||||
2>/dev/null | jq -r '.workflow_runs[].id' | while read -r run_id; do
|
||||
curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/actions/runs/${run_id}" 2>/dev/null || true
|
||||
DELETED=$((DELETED+1))
|
||||
done
|
||||
@@ -327,7 +327,7 @@ jobs:
|
||||
|
||||
DELETED=0
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/actions/runs?created=<${CUTOFF}&per_page=100" 2>/dev/null \
|
||||
--jq '.workflow_runs[].id' 2>/dev/null | while read -r run_id; do
|
||||
2>/dev/null | jq -r '.workflow_runs[].id' | while read -r run_id; do
|
||||
curl -sf -X DELETE -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${{GITEA_URL:-https://git.mokoconsulting.tech}}/api/v1/repos/${{ github.repository }}/actions/runs/${run_id}/logs" 2>/dev/null || true
|
||||
DELETED=$((DELETED+1))
|
||||
done
|
||||
|
||||
@@ -171,7 +171,7 @@ jobs:
|
||||
title: `[Terraform Drift] ${env} environment has drifted`,
|
||||
body: body,
|
||||
labels: ['terraform-drift', `environment:${env}`, 'infrastructure'],
|
||||
assignees: ['copilot', 'jmiller-moko']
|
||||
assignees: ['copilot', 'jmiller']
|
||||
});
|
||||
} else {
|
||||
// Update existing issue
|
||||
|
||||
@@ -209,7 +209,7 @@ jobs:
|
||||
if [ "${{ inputs.target_repos }}" = "all" ]; then
|
||||
# Get all org repositories
|
||||
curl -sf -H "Authorization: token ${{ secrets.GA_TOKEN }}" "${GITEA_URL:-https://git.mokoconsulting.tech}/api/v1/orgs/${{ github.repository_owner }}/repos?limit=50" \
|
||||
--jq '.[].name' > repos.txt
|
||||
| jq -r '.[].name' > repos.txt
|
||||
else
|
||||
# Use specified repositories
|
||||
echo "${{ inputs.target_repos }}" | tr ',' '\n' > repos.txt
|
||||
@@ -288,7 +288,7 @@ jobs:
|
||||
title: 'Terraform Repository Template Update Plan',
|
||||
body: output,
|
||||
labels: ['terraform', 'repository-management', 'automation'],
|
||||
assignees: ['copilot', 'jmiller-moko']
|
||||
assignees: ['copilot', 'jmiller']
|
||||
});
|
||||
|
||||
- name: Terraform Apply
|
||||
@@ -342,7 +342,7 @@ jobs:
|
||||
title: `Repository Templates Updated - ${new Date().toISOString().split('T')[0]}`,
|
||||
body: body,
|
||||
labels: ['terraform', 'repository-management', 'completed'],
|
||||
assignees: ['copilot', 'jmiller-moko']
|
||||
assignees: ['copilot', 'jmiller']
|
||||
});
|
||||
|
||||
- name: Summary
|
||||
|
||||
@@ -64,7 +64,7 @@ class AutoDetectPlatform extends CLIApp
|
||||
{
|
||||
return [
|
||||
'repo-path:' => 'Path to repository to analyze (default: current directory)',
|
||||
'schema-dir:' => 'Path to schema definitions directory (default: api/definitions/default)',
|
||||
'schema-dir:' => 'Path to schema definitions directory (default: definitions/default)',
|
||||
'output-dir:' => 'Directory for output reports (default: var/logs/validation)',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
* BRIEF: Validate composer.json enterprise dependency across all governed repos
|
||||
*
|
||||
* USAGE
|
||||
* php api/validate/check_composer_deps.php --repo MokoCRM # Single repo
|
||||
* php api/validate/check_composer_deps.php --all # All repos
|
||||
* php api/validate/check_composer_deps.php --all --json # JSON output
|
||||
* php validate/check_composer_deps.php --repo MokoCRM # Single repo
|
||||
* php validate/check_composer_deps.php --all # All repos
|
||||
* php validate/check_composer_deps.php --all --json # JSON output
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
@@ -139,18 +139,18 @@ class EnterpriseReadinessChecker extends CliFramework
|
||||
{
|
||||
$required = ['ApiClient', 'AuditLogger', 'Config', 'ErrorRecovery', 'MetricsCollector'];
|
||||
|
||||
// Enterprise libs may live in vendor/ (Composer install) or api/lib/Enterprise/ (MokoStandards itself).
|
||||
// Enterprise libs may live in vendor/ (Composer install) or lib/Enterprise/ (MokoStandards itself).
|
||||
// A single vendor/ directory confirms the whole package is present — no need to check per-file.
|
||||
$vendorPkg = "{$path}/vendor/mokoconsulting-tech/enterprise";
|
||||
$inVendor = is_dir($vendorPkg);
|
||||
|
||||
foreach ($required as $library) {
|
||||
$localFile = "{$path}/api/lib/Enterprise/{$library}.php";
|
||||
$localFile = "{$path}/lib/Enterprise/{$library}.php";
|
||||
$found = $inVendor || file_exists($localFile);
|
||||
$this->addResult(
|
||||
"Enterprise library: {$library}",
|
||||
$found,
|
||||
"Missing enterprise library (not in vendor/mokoconsulting-tech/enterprise or api/lib/Enterprise/)"
|
||||
"Missing enterprise library (not in vendor/mokoconsulting-tech/enterprise or lib/Enterprise/)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ class CheckVersionConsistency extends CliFramework
|
||||
// ── Check PHP Enterprise library files ────────────────────────────────
|
||||
$this->section('Checking PHP source files');
|
||||
|
||||
$phpFiles = $this->findPhpFiles($path . '/api/lib/Enterprise');
|
||||
$phpFiles = $this->findPhpFiles($path . '/lib/Enterprise');
|
||||
$phpTotal = count($phpFiles);
|
||||
|
||||
foreach ($phpFiles as $i => $file) {
|
||||
|
||||
@@ -529,7 +529,7 @@ class DriftScanner extends CliFramework
|
||||
$body .= "1. **Option 1:** Run bulk sync to update all files automatically\n";
|
||||
$body .= " ```bash\n";
|
||||
$body .= " # From MokoStandards repository\n";
|
||||
$body .= " php api/automation/bulk_sync.php --repos=\"{$repo}\"\n";
|
||||
$body .= " php automation/bulk_sync.php --repos=\"{$repo}\"\n";
|
||||
$body .= " ```\n\n";
|
||||
$body .= "2. **Option 2:** If changes are intentional, update `.github/override.tf` to exclude files\n\n";
|
||||
$body .= "3. **Option 3:** Manually update files to match templates\n\n";
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/auto_detect_platform.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/auto_detect_platform.php
|
||||
* BRIEF: PHP wrapper for validate/auto_detect_platform.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'auto_detect_platform';
|
||||
const SCRIPT_PATH = 'api/validate/auto_detect_platform.php';
|
||||
const SCRIPT_PATH = 'validate/auto_detect_platform.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/bulk_sync.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/automation/bulk_sync.php
|
||||
* BRIEF: PHP wrapper for automation/bulk_sync.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'bulk_sync';
|
||||
const SCRIPT_PATH = 'api/automation/bulk_sync.php';
|
||||
const SCRIPT_PATH = 'automation/bulk_sync.php';
|
||||
const SCRIPT_CATEGORY = 'automation';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_changelog.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_changelog.php
|
||||
* BRIEF: PHP wrapper for validate/check_changelog.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_changelog';
|
||||
const SCRIPT_PATH = 'api/validate/check_changelog.php';
|
||||
const SCRIPT_PATH = 'validate/check_changelog.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_dolibarr_module.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_dolibarr_module.php
|
||||
* BRIEF: PHP wrapper for validate/check_dolibarr_module.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_dolibarr_module';
|
||||
const SCRIPT_PATH = 'api/validate/check_dolibarr_module.php';
|
||||
const SCRIPT_PATH = 'validate/check_dolibarr_module.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_enterprise_readiness.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_enterprise_readiness.php
|
||||
* BRIEF: PHP wrapper for validate/check_enterprise_readiness.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_enterprise_readiness';
|
||||
const SCRIPT_PATH = 'api/validate/check_enterprise_readiness.php';
|
||||
const SCRIPT_PATH = 'validate/check_enterprise_readiness.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_joomla_manifest.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_joomla_manifest.php
|
||||
* BRIEF: PHP wrapper for validate/check_joomla_manifest.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_joomla_manifest';
|
||||
const SCRIPT_PATH = 'api/validate/check_joomla_manifest.php';
|
||||
const SCRIPT_PATH = 'validate/check_joomla_manifest.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_language_structure.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_language_structure.php
|
||||
* BRIEF: PHP wrapper for validate/check_language_structure.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_language_structure';
|
||||
const SCRIPT_PATH = 'api/validate/check_language_structure.php';
|
||||
const SCRIPT_PATH = 'validate/check_language_structure.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_license_headers.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_license_headers.php
|
||||
* BRIEF: PHP wrapper for validate/check_license_headers.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_license_headers';
|
||||
const SCRIPT_PATH = 'api/validate/check_license_headers.php';
|
||||
const SCRIPT_PATH = 'validate/check_license_headers.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_no_secrets.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_no_secrets.php
|
||||
* BRIEF: PHP wrapper for validate/check_no_secrets.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_no_secrets';
|
||||
const SCRIPT_PATH = 'api/validate/check_no_secrets.php';
|
||||
const SCRIPT_PATH = 'validate/check_no_secrets.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_paths.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_paths.php
|
||||
* BRIEF: PHP wrapper for validate/check_paths.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_paths';
|
||||
const SCRIPT_PATH = 'api/validate/check_paths.php';
|
||||
const SCRIPT_PATH = 'validate/check_paths.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_php_syntax.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_php_syntax.php
|
||||
* BRIEF: PHP wrapper for validate/check_php_syntax.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_php_syntax';
|
||||
const SCRIPT_PATH = 'api/validate/check_php_syntax.php';
|
||||
const SCRIPT_PATH = 'validate/check_php_syntax.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_repo_health.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_repo_health.php
|
||||
* BRIEF: PHP wrapper for validate/check_repo_health.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_repo_health';
|
||||
const SCRIPT_PATH = 'api/validate/check_repo_health.php';
|
||||
const SCRIPT_PATH = 'validate/check_repo_health.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_structure.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_structure.php
|
||||
* BRIEF: PHP wrapper for validate/check_structure.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_structure';
|
||||
const SCRIPT_PATH = 'api/validate/check_structure.php';
|
||||
const SCRIPT_PATH = 'validate/check_structure.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_tabs.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_tabs.php
|
||||
* BRIEF: PHP wrapper for validate/check_tabs.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_tabs';
|
||||
const SCRIPT_PATH = 'api/validate/check_tabs.php';
|
||||
const SCRIPT_PATH = 'validate/check_tabs.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_version_consistency.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_version_consistency.php
|
||||
* BRIEF: PHP wrapper for validate/check_version_consistency.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_version_consistency';
|
||||
const SCRIPT_PATH = 'api/validate/check_version_consistency.php';
|
||||
const SCRIPT_PATH = 'validate/check_version_consistency.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/check_xml_wellformed.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/check_xml_wellformed.php
|
||||
* BRIEF: PHP wrapper for validate/check_xml_wellformed.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'check_xml_wellformed';
|
||||
const SCRIPT_PATH = 'api/validate/check_xml_wellformed.php';
|
||||
const SCRIPT_PATH = 'validate/check_xml_wellformed.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/deploy_sftp.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/deploy/deploy-sftp.php
|
||||
* BRIEF: PHP wrapper for deploy/deploy-sftp.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'deploy_sftp';
|
||||
const SCRIPT_PATH = 'api/deploy/deploy-sftp.php';
|
||||
const SCRIPT_PATH = 'deploy/deploy-sftp.php';
|
||||
const SCRIPT_CATEGORY = 'deploy';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/fix_line_endings.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/fix/fix_line_endings.php
|
||||
* BRIEF: PHP wrapper for fix/fix_line_endings.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'fix_line_endings';
|
||||
const SCRIPT_PATH = 'api/fix/fix_line_endings.php';
|
||||
const SCRIPT_PATH = 'fix/fix_line_endings.php';
|
||||
const SCRIPT_CATEGORY = 'fix';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/fix_permissions.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/fix/fix_permissions.php
|
||||
* BRIEF: PHP wrapper for fix/fix_permissions.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'fix_permissions';
|
||||
const SCRIPT_PATH = 'api/fix/fix_permissions.php';
|
||||
const SCRIPT_PATH = 'fix/fix_permissions.php';
|
||||
const SCRIPT_CATEGORY = 'fix';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/fix_tabs.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/fix/fix_tabs.php
|
||||
* BRIEF: PHP wrapper for fix/fix_tabs.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'fix_tabs';
|
||||
const SCRIPT_PATH = 'api/fix/fix_tabs.php';
|
||||
const SCRIPT_PATH = 'fix/fix_tabs.php';
|
||||
const SCRIPT_CATEGORY = 'fix';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/fix_trailing_spaces.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/fix/fix_trailing_spaces.php
|
||||
* BRIEF: PHP wrapper for fix/fix_trailing_spaces.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'fix_trailing_spaces';
|
||||
const SCRIPT_PATH = 'api/fix/fix_trailing_spaces.php';
|
||||
const SCRIPT_PATH = 'fix/fix_trailing_spaces.php';
|
||||
const SCRIPT_CATEGORY = 'fix';
|
||||
|
||||
/**
|
||||
|
||||
+33
-33
@@ -12,7 +12,7 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/gen_wrappers.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: Generate PHP CLI wrapper scripts for every PHP script in api/
|
||||
* BRIEF: Generate PHP CLI wrapper scripts for every PHP script in the repo
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
@@ -24,43 +24,43 @@ declare(strict_types=1);
|
||||
*/
|
||||
const SCRIPTS = [
|
||||
// validate
|
||||
'auto_detect_platform' => ['api/validate/auto_detect_platform.php', 'validate'],
|
||||
'check_changelog' => ['api/validate/check_changelog.php', 'validate'],
|
||||
'check_dolibarr_module' => ['api/validate/check_dolibarr_module.php', 'validate'],
|
||||
'check_enterprise_readiness' => ['api/validate/check_enterprise_readiness.php', 'validate'],
|
||||
'check_joomla_manifest' => ['api/validate/check_joomla_manifest.php', 'validate'],
|
||||
'check_language_structure' => ['api/validate/check_language_structure.php', 'validate'],
|
||||
'check_license_headers' => ['api/validate/check_license_headers.php', 'validate'],
|
||||
'check_no_secrets' => ['api/validate/check_no_secrets.php', 'validate'],
|
||||
'check_paths' => ['api/validate/check_paths.php', 'validate'],
|
||||
'check_php_syntax' => ['api/validate/check_php_syntax.php', 'validate'],
|
||||
'check_repo_health' => ['api/validate/check_repo_health.php', 'validate'],
|
||||
'check_structure' => ['api/validate/check_structure.php', 'validate'],
|
||||
'check_tabs' => ['api/validate/check_tabs.php', 'validate'],
|
||||
'check_version_consistency' => ['api/validate/check_version_consistency.php', 'validate'],
|
||||
'check_xml_wellformed' => ['api/validate/check_xml_wellformed.php', 'validate'],
|
||||
'scan_drift' => ['api/validate/scan_drift.php', 'validate'],
|
||||
'auto_detect_platform' => ['validate/auto_detect_platform.php', 'validate'],
|
||||
'check_changelog' => ['validate/check_changelog.php', 'validate'],
|
||||
'check_dolibarr_module' => ['validate/check_dolibarr_module.php', 'validate'],
|
||||
'check_enterprise_readiness' => ['validate/check_enterprise_readiness.php', 'validate'],
|
||||
'check_joomla_manifest' => ['validate/check_joomla_manifest.php', 'validate'],
|
||||
'check_language_structure' => ['validate/check_language_structure.php', 'validate'],
|
||||
'check_license_headers' => ['validate/check_license_headers.php', 'validate'],
|
||||
'check_no_secrets' => ['validate/check_no_secrets.php', 'validate'],
|
||||
'check_paths' => ['validate/check_paths.php', 'validate'],
|
||||
'check_php_syntax' => ['validate/check_php_syntax.php', 'validate'],
|
||||
'check_repo_health' => ['validate/check_repo_health.php', 'validate'],
|
||||
'check_structure' => ['validate/check_structure.php', 'validate'],
|
||||
'check_tabs' => ['validate/check_tabs.php', 'validate'],
|
||||
'check_version_consistency' => ['validate/check_version_consistency.php', 'validate'],
|
||||
'check_xml_wellformed' => ['validate/check_xml_wellformed.php', 'validate'],
|
||||
'scan_drift' => ['validate/scan_drift.php', 'validate'],
|
||||
// automation
|
||||
'bulk_sync' => ['api/automation/bulk_sync.php', 'automation'],
|
||||
'bulk_sync' => ['automation/bulk_sync.php', 'automation'],
|
||||
// deploy
|
||||
'deploy_sftp' => ['api/deploy/deploy-sftp.php', 'deploy'],
|
||||
'deploy_sftp' => ['deploy/deploy-sftp.php', 'deploy'],
|
||||
// fix
|
||||
'fix_line_endings' => ['api/fix/fix_line_endings.php', 'fix'],
|
||||
'fix_permissions' => ['api/fix/fix_permissions.php', 'fix'],
|
||||
'fix_tabs' => ['api/fix/fix_tabs.php', 'fix'],
|
||||
'fix_trailing_spaces' => ['api/fix/fix_trailing_spaces.php', 'fix'],
|
||||
'fix_line_endings' => ['fix/fix_line_endings.php', 'fix'],
|
||||
'fix_permissions' => ['fix/fix_permissions.php', 'fix'],
|
||||
'fix_tabs' => ['fix/fix_tabs.php', 'fix'],
|
||||
'fix_trailing_spaces' => ['fix/fix_trailing_spaces.php', 'fix'],
|
||||
// maintenance
|
||||
'pin_action_shas' => ['api/maintenance/pin_action_shas.php', 'maintenance'],
|
||||
'setup_labels' => ['api/maintenance/setup_labels.php', 'maintenance'],
|
||||
'sync_dolibarr_readmes' => ['api/maintenance/sync_dolibarr_readmes.php', 'maintenance'],
|
||||
'update_sha_hashes' => ['api/maintenance/update_sha_hashes.php', 'maintenance'],
|
||||
'update_version_from_readme' => ['api/maintenance/update_version_from_readme.php', 'maintenance'],
|
||||
'pin_action_shas' => ['maintenance/pin_action_shas.php', 'maintenance'],
|
||||
'setup_labels' => ['maintenance/setup_labels.php', 'maintenance'],
|
||||
'sync_dolibarr_readmes' => ['maintenance/sync_dolibarr_readmes.php', 'maintenance'],
|
||||
'update_sha_hashes' => ['maintenance/update_sha_hashes.php', 'maintenance'],
|
||||
'update_version_from_readme' => ['maintenance/update_version_from_readme.php', 'maintenance'],
|
||||
// plugin
|
||||
'plugin_health_check' => ['api/plugin_health_check.php', 'plugin'],
|
||||
'plugin_list' => ['api/plugin_list.php', 'plugin'],
|
||||
'plugin_metrics' => ['api/plugin_metrics.php', 'plugin'],
|
||||
'plugin_readiness' => ['api/plugin_readiness.php', 'plugin'],
|
||||
'plugin_validate' => ['api/plugin_validate.php', 'plugin'],
|
||||
'plugin_health_check' => ['plugin_health_check.php', 'plugin'],
|
||||
'plugin_list' => ['plugin_list.php', 'plugin'],
|
||||
'plugin_metrics' => ['plugin_metrics.php', 'plugin'],
|
||||
'plugin_readiness' => ['plugin_readiness.php', 'plugin'],
|
||||
'plugin_validate' => ['plugin_validate.php', 'plugin'],
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/pin_action_shas.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/maintenance/pin_action_shas.php
|
||||
* BRIEF: PHP wrapper for maintenance/pin_action_shas.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'pin_action_shas';
|
||||
const SCRIPT_PATH = 'api/maintenance/pin_action_shas.php';
|
||||
const SCRIPT_PATH = 'maintenance/pin_action_shas.php';
|
||||
const SCRIPT_CATEGORY = 'maintenance';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/plugin_health_check.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/plugin_health_check.php
|
||||
* BRIEF: PHP wrapper for plugin_health_check.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'plugin_health_check';
|
||||
const SCRIPT_PATH = 'api/plugin_health_check.php';
|
||||
const SCRIPT_PATH = 'plugin_health_check.php';
|
||||
const SCRIPT_CATEGORY = 'plugin';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/plugin_list.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/plugin_list.php
|
||||
* BRIEF: PHP wrapper for plugin_list.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'plugin_list';
|
||||
const SCRIPT_PATH = 'api/plugin_list.php';
|
||||
const SCRIPT_PATH = 'plugin_list.php';
|
||||
const SCRIPT_CATEGORY = 'plugin';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/plugin_metrics.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/plugin_metrics.php
|
||||
* BRIEF: PHP wrapper for plugin_metrics.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'plugin_metrics';
|
||||
const SCRIPT_PATH = 'api/plugin_metrics.php';
|
||||
const SCRIPT_PATH = 'plugin_metrics.php';
|
||||
const SCRIPT_CATEGORY = 'plugin';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/plugin_readiness.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/plugin_readiness.php
|
||||
* BRIEF: PHP wrapper for plugin_readiness.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'plugin_readiness';
|
||||
const SCRIPT_PATH = 'api/plugin_readiness.php';
|
||||
const SCRIPT_PATH = 'plugin_readiness.php';
|
||||
const SCRIPT_CATEGORY = 'plugin';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/plugin_validate.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/plugin_validate.php
|
||||
* BRIEF: PHP wrapper for plugin_validate.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'plugin_validate';
|
||||
const SCRIPT_PATH = 'api/plugin_validate.php';
|
||||
const SCRIPT_PATH = 'plugin_validate.php';
|
||||
const SCRIPT_CATEGORY = 'plugin';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/scan_drift.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/validate/scan_drift.php
|
||||
* BRIEF: PHP wrapper for validate/scan_drift.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'scan_drift';
|
||||
const SCRIPT_PATH = 'api/validate/scan_drift.php';
|
||||
const SCRIPT_PATH = 'validate/scan_drift.php';
|
||||
const SCRIPT_CATEGORY = 'validate';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/setup_labels.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/maintenance/setup_labels.php
|
||||
* BRIEF: PHP wrapper for maintenance/setup_labels.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'setup_labels';
|
||||
const SCRIPT_PATH = 'api/maintenance/setup_labels.php';
|
||||
const SCRIPT_PATH = 'maintenance/setup_labels.php';
|
||||
const SCRIPT_CATEGORY = 'maintenance';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/sync_dolibarr_readmes.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/maintenance/sync_dolibarr_readmes.php
|
||||
* BRIEF: PHP wrapper for maintenance/sync_dolibarr_readmes.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'sync_dolibarr_readmes';
|
||||
const SCRIPT_PATH = 'api/maintenance/sync_dolibarr_readmes.php';
|
||||
const SCRIPT_PATH = 'maintenance/sync_dolibarr_readmes.php';
|
||||
const SCRIPT_CATEGORY = 'maintenance';
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||
* PATH: /wrappers/update_sha_hashes.php
|
||||
* VERSION: 04.06.00
|
||||
* BRIEF: PHP wrapper for api/maintenance/update_sha_hashes.php
|
||||
* BRIEF: PHP wrapper for maintenance/update_sha_hashes.php
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
const SCRIPT_NAME = 'update_sha_hashes';
|
||||
const SCRIPT_PATH = 'api/maintenance/update_sha_hashes.php';
|
||||
const SCRIPT_PATH = 'maintenance/update_sha_hashes.php';
|
||||
const SCRIPT_CATEGORY = 'maintenance';
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user