Compare commits
31 Commits
| 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
|
* BRIEF: Bulk scaffold and sync Joomla template repositories
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/automation/bulk_joomla_template.php --scaffold --name=MokoTheme
|
* php automation/bulk_joomla_template.php --scaffold --name=MokoTheme
|
||||||
* php api/automation/bulk_joomla_template.php --scaffold --name=MokoTheme --client=administrator
|
* php automation/bulk_joomla_template.php --scaffold --name=MokoTheme --client=administrator
|
||||||
* php api/automation/bulk_joomla_template.php --sync --repos=MokoTheme,MokoDarkTheme
|
* php automation/bulk_joomla_template.php --sync --repos=MokoTheme,MokoDarkTheme
|
||||||
* php api/automation/bulk_joomla_template.php --sync --all
|
* php automation/bulk_joomla_template.php --sync --all
|
||||||
* php api/automation/bulk_joomla_template.php --list
|
* php automation/bulk_joomla_template.php --list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@@ -717,13 +717,13 @@ class BulkJoomlaTemplate extends CLIApp
|
|||||||
// ── Sync updates.xml between platforms ───────────────────────────────
|
// ── 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,
|
* Reads the file from both platforms, compares by latest <version> tag,
|
||||||
* and pushes the newer one to the stale platform.
|
* and pushes the newer one to the stale platform.
|
||||||
*
|
*
|
||||||
* Designed to be called from a CI workflow via:
|
* 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
|
private function syncUpdatesBetweenPlatforms(string $org): int
|
||||||
{
|
{
|
||||||
@@ -788,7 +788,7 @@ class BulkJoomlaTemplate extends CLIApp
|
|||||||
$name = $repo['name'];
|
$name = $repo['name'];
|
||||||
$this->log("\n[{$name}]", 'INFO');
|
$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);
|
$updateFile = $this->resolveUpdateFile($gitea, $github, $org, $name);
|
||||||
if ($updateFile === null) {
|
if ($updateFile === null) {
|
||||||
$this->log(" ⊘ No update(s).xml found on either platform", 'INFO');
|
$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.
|
* 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>.
|
* Returns the content from the platform with the newer <version>.
|
||||||
* Gitea wins ties (primary platform).
|
* Gitea wins ties (primary platform).
|
||||||
*
|
*
|
||||||
@@ -861,7 +861,7 @@ class BulkJoomlaTemplate extends CLIApp
|
|||||||
string $org,
|
string $org,
|
||||||
string $name
|
string $name
|
||||||
): ?array {
|
): ?array {
|
||||||
$candidates = ['updates.xml', 'update.xml'];
|
$candidates = ['updates.xml', 'updates.xml'];
|
||||||
$found = []; // platform => [name, content, version]
|
$found = []; // platform => [name, content, version]
|
||||||
|
|
||||||
foreach (['gitea' => $gitea, 'github' => $github] as $platform => $adapter) {
|
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("The bulk repository sync is failing silently because the core", 'ERROR');
|
||||||
$this->log("synchronization logic has not been implemented yet.", 'ERROR');
|
$this->log("synchronization logic has not been implemented yet.", 'ERROR');
|
||||||
$this->log("", '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("Method: processRepository()", 'ERROR');
|
||||||
$this->log("", 'ERROR');
|
$this->log("", 'ERROR');
|
||||||
$this->log("Required Implementation:", 'ERROR');
|
$this->log("Required Implementation:", 'ERROR');
|
||||||
@@ -509,7 +509,7 @@ class BulkSync extends CLIApp
|
|||||||
]);
|
]);
|
||||||
$script = basename(__FILE__);
|
$script = basename(__FILE__);
|
||||||
$this->log("💾 Checkpoint saved. To resume once the issue is resolved, run:", 'INFO');
|
$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) {
|
} catch (\Exception $e) {
|
||||||
$this->log("⚠️ Failed to save interrupt checkpoint: " . $e->getMessage(), 'WARN');
|
$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.
|
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.).
|
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.
|
4. Close this issue once all repos are synced successfully.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
* BRIEF: Migrate repositories from GitHub to self-hosted Gitea instance
|
* BRIEF: Migrate repositories from GitHub to self-hosted Gitea instance
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/automation/migrate_to_gitea.php --dry-run
|
* php automation/migrate_to_gitea.php --dry-run
|
||||||
* php api/automation/migrate_to_gitea.php --repos MokoCRM MokoDoliMods
|
* php automation/migrate_to_gitea.php --repos MokoCRM MokoDoliMods
|
||||||
* php api/automation/migrate_to_gitea.php --exclude MokoStandards --skip-archived
|
* php automation/migrate_to_gitea.php --exclude MokoStandards --skip-archived
|
||||||
* php api/automation/migrate_to_gitea.php --resume
|
* php automation/migrate_to_gitea.php --resume
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|||||||
@@ -590,7 +590,7 @@ class PushFiles extends CLIApp
|
|||||||
|
|
||||||
1. Check the output above for the specific error per repo.
|
1. Check the output above for the specific error per repo.
|
||||||
2. Fix the underlying issue (API token, branch permissions, file path, etc.).
|
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.
|
4. Close this issue once resolved.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
* BRIEF: Gracefully retire a governed repository — archive, close issues/PRs, remove sync def
|
* BRIEF: Gracefully retire a governed repository — archive, close issues/PRs, remove sync def
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/cli/archive_repo.php --repo MokoOldModule
|
* php cli/archive_repo.php --repo MokoOldModule
|
||||||
* php api/cli/archive_repo.php --repo MokoOldModule --dry-run
|
* php 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 --skip-close # Archive only, keep issues open
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
* BRIEF: Create baseline GitHub Projects for repositories with standard fields and views
|
* BRIEF: Create baseline GitHub Projects for repositories with standard fields and views
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/cli/create_project.php --repo MokoCRM # Auto-detect type, create project
|
* php cli/create_project.php --repo MokoCRM # Auto-detect type, create project
|
||||||
* php api/cli/create_project.php --repo MokoCRM --type dolibarr # Force type
|
* php 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 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 --dry-run # Preview without changes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@@ -385,7 +385,7 @@ function createProject(
|
|||||||
updateProjectV2(input: {
|
updateProjectV2(input: {
|
||||||
projectId: $projectId,
|
projectId: $projectId,
|
||||||
shortDescription: $shortDescription,
|
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 }
|
projectV2 { id }
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -15,9 +15,9 @@
|
|||||||
* BRIEF: Scaffold a new governed repository with full MokoStandards baseline
|
* BRIEF: Scaffold a new governed repository with full MokoStandards baseline
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/cli/create_repo.php --name MokoNewModule --type dolibarr --description "My new module"
|
* php cli/create_repo.php --name MokoNewModule --type dolibarr --description "My new module"
|
||||||
* php api/cli/create_repo.php --name MokoNewModule --type joomla --private
|
* php 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 generic --dry-run
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@@ -229,7 +229,7 @@ if (!$dryRun) {
|
|||||||
if (file_exists($syncScript)) {
|
if (file_exists($syncScript)) {
|
||||||
passthru("php " . escapeshellarg($syncScript) . " --repos " . escapeshellarg($name) . " --force --yes");
|
passthru("php " . escapeshellarg($syncScript) . " --repos " . escapeshellarg($name) . " --force --yes");
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
echo " (dry-run) would run initial sync\n";
|
echo " (dry-run) would run initial sync\n";
|
||||||
@@ -242,7 +242,7 @@ if (!$dryRun) {
|
|||||||
if (file_exists($projectScript)) {
|
if (file_exists($projectScript)) {
|
||||||
passthru("php " . escapeshellarg($projectScript) . " --repo " . escapeshellarg($name) . " --type " . escapeshellarg($type));
|
passthru("php " . escapeshellarg($projectScript) . " --repo " . escapeshellarg($name) . " --type " . escapeshellarg($type));
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
echo " (dry-run) would create Project\n";
|
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
|
* BRIEF: Joomla release pipeline — build ZIP+tar.gz, upload to GitHub Release, update updates.xml
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/cli/joomla_release.php --repo MokoCassiopeia --stability stable
|
* php cli/joomla_release.php --repo MokoCassiopeia --stability stable
|
||||||
* php api/cli/joomla_release.php --repo MokoCassiopeia --stability development
|
* php cli/joomla_release.php --repo MokoCassiopeia --stability development
|
||||||
* php api/cli/joomla_release.php --repo MokoCassiopeia --stability rc --dry-run
|
* php 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 --path /local/repo --stability stable
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|||||||
+5
-5
@@ -13,10 +13,10 @@
|
|||||||
* BRIEF: Automate the MokoStandards version branch release flow
|
* BRIEF: Automate the MokoStandards version branch release flow
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/cli/release.php # Release current version
|
* php cli/release.php # Release current version
|
||||||
* php api/cli/release.php --bump minor # Bump minor, then release
|
* php cli/release.php --bump minor # Bump minor, then release
|
||||||
* php api/cli/release.php --bump major # Bump major, then release
|
* php cli/release.php --bump major # Bump major, then release
|
||||||
* php api/cli/release.php --dry-run # Preview without changes
|
* php cli/release.php --dry-run # Preview without changes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
@@ -30,7 +30,7 @@ foreach ($argv as $i => $arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$repoRoot = dirname(__DIR__, 2);
|
$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
|
// Check both workflow directories for the bulk-repo-sync workflow
|
||||||
$bulkSyncFile = file_exists("{$repoRoot}/.gitea/workflows/bulk-repo-sync.yml")
|
$bulkSyncFile = file_exists("{$repoRoot}/.gitea/workflows/bulk-repo-sync.yml")
|
||||||
? "{$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
|
* BRIEF: Apply branch protection rules to all repos via platform adapter
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/cli/sync_rulesets.php # Apply to all repos
|
* php cli/sync_rulesets.php # Apply to all repos
|
||||||
* php api/cli/sync_rulesets.php --repo MokoCRM # Single repo
|
* php cli/sync_rulesets.php --repo MokoCRM # Single repo
|
||||||
* php api/cli/sync_rulesets.php --dry-run # Preview only
|
* php cli/sync_rulesets.php --dry-run # Preview only
|
||||||
* php api/cli/sync_rulesets.php --delete # Remove then re-apply
|
* php cli/sync_rulesets.php --delete # Remove then re-apply
|
||||||
*
|
*
|
||||||
* NOTE: On GitHub, this creates rulesets via the rulesets API.
|
* NOTE: On GitHub, this creates rulesets via the rulesets API.
|
||||||
* On Gitea, this creates branch_protections via the branch protection API.
|
* On Gitea, this creates branch_protections via the branch protection API.
|
||||||
|
|||||||
+2
-3
@@ -17,7 +17,6 @@
|
|||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-zip": "*",
|
"ext-zip": "*",
|
||||||
"guzzlehttp/guzzle": "^7.8",
|
"guzzlehttp/guzzle": "^7.8",
|
||||||
"mokoconsulting-tech/enterprise": "dev-version/04",
|
|
||||||
"monolog/monolog": "^3.5",
|
"monolog/monolog": "^3.5",
|
||||||
"php": ">=8.1",
|
"php": ">=8.1",
|
||||||
"phpseclib/phpseclib": "^3.0",
|
"phpseclib/phpseclib": "^3.0",
|
||||||
@@ -74,8 +73,8 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "phpunit",
|
"test": "phpunit",
|
||||||
"phpcs": "phpcs --standard=phpcs.xml api/",
|
"phpcs": "phpcs --standard=phpcs.xml lib/ validate/ automation/",
|
||||||
"phpstan": "phpstan analyse -c phpstan.neon api/",
|
"phpstan": "phpstan analyse -c phpstan.neon lib/ validate/ automation/",
|
||||||
"psalm": "psalm --config=psalm.xml",
|
"psalm": "psalm --config=psalm.xml",
|
||||||
"check": [
|
"check": [
|
||||||
"@phpcs",
|
"@phpcs",
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ locals {
|
|||||||
https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/raw/branch/main/updates.xml
|
https://git.mokoconsulting.tech/MokoConsulting/{{REPO_NAME}}/raw/branch/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
<server type="extension" priority="2" name="{{TEMPLATE_NAME}} Update 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>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ locals {
|
|||||||
https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{TEMPLATE_SHORT_NAME}}.zip
|
https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{TEMPLATE_SHORT_NAME}}.zip
|
||||||
</downloadurl>
|
</downloadurl>
|
||||||
<downloadurl type="full" format="zip">
|
<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>
|
</downloadurl>
|
||||||
</downloads>
|
</downloads>
|
||||||
<targetplatform name="joomla" version="[56].*"/>
|
<targetplatform name="joomla" version="[56].*"/>
|
||||||
|
|||||||
@@ -83,13 +83,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
|
protected = true
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -101,10 +101,10 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<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>
|
||||||
<server type="extension" priority="2" name="{{EXTENSION_NAME}}">
|
<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>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ locals {
|
|||||||
https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
https://git.mokoconsulting.tech/mokoconsulting-tech/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip
|
||||||
</downloadurl>
|
</downloadurl>
|
||||||
<downloadurl type="full" format="zip">
|
<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>
|
</downloadurl>
|
||||||
</downloads>
|
</downloads>
|
||||||
<targetplatform name="joomla" version="[56].*"/>
|
<targetplatform name="joomla" version="[56].*"/>
|
||||||
@@ -377,7 +377,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -425,7 +425,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = ".github"
|
name = ".github"
|
||||||
path = ".github"
|
path = ".github"
|
||||||
description = "GitHub-specific configuration"
|
description = "Gitea/GitHub Actions configuration (Gitea reads .github/workflows natively)"
|
||||||
requirement_status = "suggested"
|
requirement_status = "suggested"
|
||||||
purpose = "Contains GitHub Actions workflows and configuration"
|
purpose = "Contains GitHub Actions workflows and configuration"
|
||||||
files = [
|
files = [
|
||||||
@@ -467,7 +467,7 @@ locals {
|
|||||||
> | Placeholder | Where to find the value |
|
> | Placeholder | Where to find the value |
|
||||||
> |---|---|
|
> |---|---|
|
||||||
> | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) |
|
> | `{{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_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_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`) |
|
> | `{{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
|
## 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}}
|
Repository URL: {{REPO_URL}}
|
||||||
Extension name: **{{EXTENSION_NAME}}**
|
Extension name: **{{EXTENSION_NAME}}**
|
||||||
@@ -552,13 +552,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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. -->
|
The version="[56].*" regex matches Joomla 5.x and 6.x. -->
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -582,7 +582,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -644,16 +644,16 @@ locals {
|
|||||||
|
|
||||||
## GitHub Actions — Token Usage
|
## 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
|
```yaml
|
||||||
# ✅ Correct
|
# ✅ Correct
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GA_TOKEN }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -666,16 +666,16 @@ locals {
|
|||||||
|
|
||||||
## MokoStandards Reference
|
## 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 |
|
| 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 |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR title/body conventions |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide |
|
| [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 |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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`
|
- 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, `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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -762,7 +762,7 @@ locals {
|
|||||||
> | Placeholder | Where to find the value |
|
> | Placeholder | Where to find the value |
|
||||||
> |---|---|
|
> |---|---|
|
||||||
> | `{{REPO_NAME}}` | The GitHub repository name (visible in the URL, `README.md` heading, or `git remote -v`) |
|
> | `{{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 |
|
> | `{{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_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_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}}`)
|
Extension type: **{{EXTENSION_TYPE}}** (`{{EXTENSION_ELEMENT}}`)
|
||||||
Repository URL: {{REPO_URL}}
|
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}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -839,32 +839,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<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.
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -948,16 +948,16 @@ locals {
|
|||||||
|
|
||||||
# GitHub Actions — Token Usage
|
# 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
|
```yaml
|
||||||
# ✅ Correct
|
# ✅ Correct
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GH_TOKEN }}
|
token: ${{ secrets.GA_TOKEN }}
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
GA_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -973,8 +973,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -999,7 +999,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
@@ -1010,12 +1010,12 @@ locals {
|
|||||||
|
|
||||||
| Document | Purpose |
|
| 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 |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/coding-style-guide.md) | Naming and formatting conventions |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/branching-strategy.md) | Branch naming, hierarchy, and release workflow |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/merge-strategy.md) | Squash-merge policy and PR conventions |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/policy/changelog-standards.md) | How and when to update CHANGELOG.md |
|
| [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://github.com/mokoconsulting-tech/MokoStandards/blob/main/docs/guide/waas/joomla-development-guide.md) | MokoWaaS Joomla extension development guide |
|
| [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
|
MOKO_END
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "updated" },
|
{ path = "SECURITY.md" action = "updated" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "created" },
|
{ path = "SECURITY.md" action = "created" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -164,13 +164,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -182,7 +182,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -453,7 +453,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -628,13 +628,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -660,7 +660,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -792,8 +792,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -867,7 +867,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -917,32 +917,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1051,8 +1051,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1077,7 +1077,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "updated" },
|
{ path = "SECURITY.md" action = "updated" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -164,13 +164,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -182,7 +182,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -453,7 +453,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -628,13 +628,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -660,7 +660,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -792,8 +792,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -867,7 +867,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -917,32 +917,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1051,8 +1051,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1077,7 +1077,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "updated" },
|
{ path = "SECURITY.md" action = "updated" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "updated" },
|
{ path = "SECURITY.md" action = "updated" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "created" },
|
{ path = "SECURITY.md" action = "created" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "updated" },
|
{ path = "SECURITY.md" action = "updated" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "updated" },
|
{ path = "SECURITY.md" action = "updated" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "created" },
|
{ path = "SECURITY.md" action = "created" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "created" },
|
{ path = "CODE_OF_CONDUCT.md" action = "created" },
|
||||||
{ path = "CONTRIBUTING.md" action = "created" },
|
{ path = "CONTRIBUTING.md" action = "created" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "created" },
|
{ path = "SECURITY.md" action = "created" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "created" },
|
{ path = "SECURITY.md" action = "created" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ locals {
|
|||||||
|
|
||||||
synced_files = [
|
synced_files = [
|
||||||
{ path = "LICENSE" action = "updated" },
|
{ path = "LICENSE" action = "updated" },
|
||||||
{ path = "update.xml" action = "updated" },
|
{ path = "updates.xml" action = "updated" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "updated" },
|
{ path = "Makefile" action = "updated" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -149,13 +149,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -167,7 +167,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -605,13 +605,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -637,7 +637,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -769,8 +769,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -844,7 +844,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -894,32 +894,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1028,8 +1028,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1054,7 +1054,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ locals {
|
|||||||
{ path = "SECURITY.md" action = "updated" },
|
{ path = "SECURITY.md" action = "updated" },
|
||||||
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
{ path = "CODE_OF_CONDUCT.md" action = "updated" },
|
||||||
{ path = "CONTRIBUTING.md" action = "updated" },
|
{ path = "CONTRIBUTING.md" action = "updated" },
|
||||||
{ path = "update.xml" action = "created" },
|
{ path = "updates.xml" action = "created" },
|
||||||
{ path = "phpstan.neon" action = "updated" },
|
{ path = "phpstan.neon" action = "updated" },
|
||||||
{ path = "Makefile" action = "created" },
|
{ path = "Makefile" action = "created" },
|
||||||
{ path = ".gitignore" action = "updated" },
|
{ path = ".gitignore" action = "updated" },
|
||||||
@@ -165,13 +165,13 @@ locals {
|
|||||||
audience = "contributor"
|
audience = "contributor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name = "update.xml"
|
name = "updates.xml"
|
||||||
extension = "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; must be kept in sync with manifest.xml version"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = false
|
always_overwrite = false
|
||||||
audience = "developer"
|
audience = "developer"
|
||||||
template = "templates/joomla/update.xml.template"
|
template = "templates/joomla/updates.xml.template"
|
||||||
stub_content = <<-MOKO_END
|
stub_content = <<-MOKO_END
|
||||||
<!--
|
<!--
|
||||||
Joomla Extension Update Server XML
|
Joomla Extension Update Server XML
|
||||||
@@ -183,7 +183,7 @@ locals {
|
|||||||
The manifest.xml in this repository must reference this file:
|
The manifest.xml in this repository must reference this file:
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
|
|
||||||
@@ -454,7 +454,7 @@ locals {
|
|||||||
{
|
{
|
||||||
name = "update-server.md"
|
name = "update-server.md"
|
||||||
extension = "md"
|
extension = "md"
|
||||||
description = "Joomla update server (update.xml) documentation"
|
description = "Joomla update server (updates.xml) documentation"
|
||||||
required = true
|
required = true
|
||||||
always_overwrite = true
|
always_overwrite = true
|
||||||
template = "templates/docs/required/template-update-server-joomla.md"
|
template = "templates/docs/required/template-update-server-joomla.md"
|
||||||
@@ -629,13 +629,13 @@ locals {
|
|||||||
|
|
||||||
### Joomla Version Alignment
|
### 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
|
```xml
|
||||||
<!-- In manifest.xml — must match README.md version -->
|
<!-- In manifest.xml — must match README.md version -->
|
||||||
<version>01.02.04</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
|
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
|
in the XML attribute value. Joomla's update server treats the value as a
|
||||||
regular expression, so \. matches a literal dot. -->
|
regular expression, so \. matches a literal dot. -->
|
||||||
@@ -661,7 +661,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── 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:
|
The `manifest.xml` must reference it via:
|
||||||
```xml
|
```xml
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release must prepend a new `<update>` block at the top of `update.xml` — old entries must be preserved below.
|
- Every release must prepend a new `<update>` block at the top of `updates.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`.
|
- 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).
|
- 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.
|
- `<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
|
## manifest.xml Rules
|
||||||
|
|
||||||
- Lives at the repo root as `manifest.xml` (not inside `site/` or `admin/`).
|
- 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`.
|
- `<version>` tag must be kept in sync with `README.md` version and `updates.xml`.
|
||||||
- Must include `<updateservers>` block pointing to this repo's `update.xml`.
|
- Must include `<updateservers>` block pointing to this repo's `updates.xml`.
|
||||||
- Must include `<files folder="site">` and `<administration>` sections.
|
- Must include `<files folder="site">` and `<administration>` sections.
|
||||||
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
- Joomla 4.x requires `<namespace path="src">Moko\{{EXTENSION_NAME}}</namespace>` for namespaced extensions.
|
||||||
|
|
||||||
@@ -793,8 +793,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed manifest.xml | Update `updates.xml` version; bump README.md version |
|
||||||
| New release | Prepend `<update>` block to `update.xml`; update CHANGELOG.md; 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` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 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
|
MOKO_END
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -868,7 +868,7 @@ locals {
|
|||||||
```
|
```
|
||||||
{{REPO_NAME}}/
|
{{REPO_NAME}}/
|
||||||
├── manifest.xml # Joomla installer manifest (root — required)
|
├── 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
|
├── site/ # Frontend (site) code
|
||||||
│ ├── controller.php
|
│ ├── controller.php
|
||||||
│ ├── controllers/
|
│ ├── controllers/
|
||||||
@@ -918,32 +918,32 @@ locals {
|
|||||||
|------|------------------------|
|
|------|------------------------|
|
||||||
| `README.md` | `FILE INFORMATION` block + badge |
|
| `README.md` | `FILE INFORMATION` block + badge |
|
||||||
| `manifest.xml` | `<version>` tag |
|
| `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.
|
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
|
```xml
|
||||||
<!-- In manifest.xml -->
|
<!-- In manifest.xml -->
|
||||||
<updateservers>
|
<updateservers>
|
||||||
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
<server type="extension" priority="1" name="{{EXTENSION_NAME}}">
|
||||||
{{REPO_URL}}/raw/main/update.xml
|
{{REPO_URL}}/raw/main/updates.xml
|
||||||
</server>
|
</server>
|
||||||
</updateservers>
|
</updateservers>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Rules:**
|
**Rules:**
|
||||||
- Every release prepends a new `<update>` block at the top — older entries are preserved.
|
- 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.
|
- `<downloadurl>` must be a publicly accessible GitHub Releases asset URL.
|
||||||
- `<targetplatform version="4\.[0-9]+">` — backslash is literal (Joomla regex syntax).
|
- `<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
|
```xml
|
||||||
<updates>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
@@ -1052,8 +1052,8 @@ locals {
|
|||||||
| Change type | Documentation to update |
|
| Change type | Documentation to update |
|
||||||
|-------------|------------------------|
|
|-------------|------------------------|
|
||||||
| New or renamed PHP class/method | PHPDoc block; `docs/api/` entry |
|
| 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 or changed `manifest.xml` | Sync version to `updates.xml` and `README.md` |
|
||||||
| New release | Prepend `<update>` to `update.xml`; update `CHANGELOG.md`; bump `README.md` |
|
| New release | Prepend `<update>` to `updates.xml`; update `CHANGELOG.md`; bump `README.md` |
|
||||||
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
| New or changed workflow | `docs/workflows/<workflow-name>.md` |
|
||||||
| Any modified file | Update the `VERSION` field in that file's `FILE INFORMATION` block |
|
| 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 |
|
| **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 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 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 skip the FILE INFORMATION block** on a new source file.
|
||||||
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
- **Never use bare `catch (\Throwable $e) {}`** — always log or re-throw.
|
||||||
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
- **Never mix tabs and spaces** within a file — follow `.editorconfig`.
|
||||||
@@ -1078,7 +1078,7 @@ locals {
|
|||||||
Before opening a PR, verify:
|
Before opening a PR, verify:
|
||||||
|
|
||||||
- [ ] Patch version bumped in `README.md` (e.g. `01.02.03` → `01.02.04`)
|
- [ ] 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
|
- [ ] FILE INFORMATION headers updated in modified files
|
||||||
- [ ] CHANGELOG.md updated
|
- [ ] CHANGELOG.md updated
|
||||||
- [ ] Tests pass
|
- [ ] Tests pass
|
||||||
|
|||||||
@@ -20,9 +20,9 @@
|
|||||||
* changes — only XML manifest changes require a Joomla reinstall.
|
* changes — only XML manifest changes require a Joomla reinstall.
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/deploy/deploy-joomla.php --path . --config /tmp/sftp-config.json
|
* php 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 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 . --env dev
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|||||||
@@ -96,25 +96,25 @@ CONFIG FORMAT
|
|||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
# Dry-run preview of dev deployment
|
# 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
|
# 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
|
# 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
|
# 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
|
# Explicit config with encrypted key
|
||||||
php api/deploy/deploy-sftp.php \
|
php deploy/deploy-sftp.php \
|
||||||
--path /repos/mymodule \
|
--path /repos/mymodule \
|
||||||
--env rs \
|
--env rs \
|
||||||
--key-passphrase "my passphrase"
|
--key-passphrase "my passphrase"
|
||||||
|
|
||||||
# Quiet mode (errors only)
|
# Quiet mode (errors only)
|
||||||
php api/deploy/deploy-sftp.php --env dev --quiet
|
php deploy/deploy-sftp.php --env dev --quiet
|
||||||
|
|
||||||
EXIT CODES
|
EXIT CODES
|
||||||
0 All files uploaded successfully
|
0 All files uploaded successfully
|
||||||
|
|||||||
@@ -95,93 +95,101 @@ development
|
|||||||
|
|
||||||
The module descriptor's `url_last_version` should point to:
|
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)
|
## 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.
|
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
|
### Complete Multi-Entry Example
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<updates>
|
<updates>
|
||||||
<!-- Stable entry: visible to all sites (default minimum stability) -->
|
<!-- Stable: dual download (Gitea + GitHub), visible to all sites -->
|
||||||
<update>
|
<update>
|
||||||
<name>My Extension</name>
|
<name>My Extension</name>
|
||||||
<description>My Extension stable release</description>
|
<description>My Extension stable release</description>
|
||||||
<element>com_myextension</element>
|
<element>com_myextension</element>
|
||||||
<type>component</type>
|
<type>component</type>
|
||||||
<version>01.02.03</version>
|
<version>01.02.03</version>
|
||||||
<client>site</client>
|
|
||||||
<tags>
|
<tags>
|
||||||
<tag>stable</tag>
|
<tag>stable</tag>
|
||||||
</tags>
|
</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>
|
<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>
|
</downloads>
|
||||||
<sha256>abc123...full-hash-here</sha256>
|
|
||||||
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
||||||
<maintainer>Moko Consulting</maintainer>
|
<maintainer>Moko Consulting</maintainer>
|
||||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
</update>
|
</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>
|
<update>
|
||||||
<name>My Extension</name>
|
<name>My Extension</name>
|
||||||
<description>My Extension release candidate</description>
|
<description>My Extension release candidate</description>
|
||||||
<element>com_myextension</element>
|
<element>com_myextension</element>
|
||||||
<type>component</type>
|
<type>component</type>
|
||||||
<version>01.03.01-rc</version>
|
<version>01.03.01-rc</version>
|
||||||
<client>site</client>
|
|
||||||
<tags>
|
<tags>
|
||||||
<tag>rc</tag>
|
<tag>rc</tag>
|
||||||
</tags>
|
</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>
|
<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>
|
</downloads>
|
||||||
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
||||||
<maintainer>Moko Consulting</maintainer>
|
<maintainer>Moko Consulting</maintainer>
|
||||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
</update>
|
</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>
|
<update>
|
||||||
<name>My Extension</name>
|
<name>My Extension</name>
|
||||||
<description>My Extension beta build</description>
|
<description>My Extension beta build</description>
|
||||||
<element>com_myextension</element>
|
<element>com_myextension</element>
|
||||||
<type>component</type>
|
<type>component</type>
|
||||||
<version>01.03.01-beta</version>
|
<version>01.03.01-beta</version>
|
||||||
<client>site</client>
|
|
||||||
<tags>
|
<tags>
|
||||||
<tag>beta</tag>
|
<tag>beta</tag>
|
||||||
</tags>
|
</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>
|
<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>
|
</downloads>
|
||||||
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
||||||
<maintainer>Moko Consulting</maintainer>
|
<maintainer>Moko Consulting</maintainer>
|
||||||
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
<maintainerurl>https://mokoconsulting.tech</maintainerurl>
|
||||||
</update>
|
</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>
|
<update>
|
||||||
<name>My Extension</name>
|
<name>My Extension</name>
|
||||||
<description>My Extension alpha build</description>
|
<description>My Extension alpha build</description>
|
||||||
<element>com_myextension</element>
|
<element>com_myextension</element>
|
||||||
<type>component</type>
|
<type>component</type>
|
||||||
<version>01.03.01-alpha</version>
|
<version>01.03.01-alpha</version>
|
||||||
<client>site</client>
|
|
||||||
<tags>
|
<tags>
|
||||||
<tag>alpha</tag>
|
<tag>alpha</tag>
|
||||||
</tags>
|
</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>
|
<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>
|
</downloads>
|
||||||
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
<targetplatform name="joomla" version="((4\.[3-9])|(5\.[0-9]))" />
|
||||||
<maintainer>Moko Consulting</maintainer>
|
<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>
|
<element>com_myextension</element>
|
||||||
<type>component</type>
|
<type>component</type>
|
||||||
<version>01.04.00-dev</version>
|
<version>01.04.00-dev</version>
|
||||||
<client>site</client>
|
|
||||||
<tags>
|
<tags>
|
||||||
<tag>development</tag>
|
<tag>development</tag>
|
||||||
</tags>
|
</tags>
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /lib/CliBase.php
|
* PATH: /lib/CliBase.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /lib/Common.php
|
* PATH: /lib/Common.php
|
||||||
* VERSION: 04.06.00
|
* 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).
|
* 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.
|
* All version regex patterns enforce exactly two digits per component by design.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ class EnterpriseReadinessValidator
|
|||||||
];
|
];
|
||||||
|
|
||||||
foreach ($required as $library) {
|
foreach ($required as $library) {
|
||||||
$phpFile = "{$path}/api/lib/Enterprise/{$library}.php";
|
$phpFile = "{$path}/lib/Enterprise/{$library}.php";
|
||||||
$this->addResult(
|
$this->addResult(
|
||||||
"Enterprise library: {$library}",
|
"Enterprise library: {$library}",
|
||||||
file_exists($phpFile),
|
file_exists($phpFile),
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class RepositorySynchronizer
|
|||||||
{
|
{
|
||||||
$this->logger->logInfo("Starting synchronization for {$org}/{$repo}");
|
$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)
|
// API repo root (definitions, sync code)
|
||||||
$repoRoot = dirname(dirname(__DIR__));
|
$repoRoot = dirname(dirname(__DIR__));
|
||||||
// MokoStandards repo root (templates, configs)
|
// MokoStandards repo root (templates, configs)
|
||||||
@@ -509,7 +509,7 @@ HCL;
|
|||||||
try {
|
try {
|
||||||
$issueData = $this->adapter->createIssue($org, $repo, $issueTitle, $issueBody, [
|
$issueData = $this->adapter->createIssue($org, $repo, $issueTitle, $issueBody, [
|
||||||
'labels' => ['mokostandards', 'type: chore', 'automation'],
|
'labels' => ['mokostandards', 'type: chore', 'automation'],
|
||||||
'assignees' => ['jmiller-moko'],
|
'assignees' => ['jmiller'],
|
||||||
]);
|
]);
|
||||||
$issueNumber = $issueData['number'] ?? null;
|
$issueNumber = $issueData['number'] ?? null;
|
||||||
$this->logger->logInfo("Created tracking issue #{$issueNumber} — " . count($summary['copied']) . " files synced directly to {$defaultBranch}");
|
$this->logger->logInfo("Created tracking issue #{$issueNumber} — " . count($summary['copied']) . " files synced directly to {$defaultBranch}");
|
||||||
@@ -598,7 +598,12 @@ HCL;
|
|||||||
$isReadme = $basename === 'readme.md';
|
$isReadme = $basename === 'readme.md';
|
||||||
$isChangelog = in_array($basename, ['changelog.md', 'changelog'], true);
|
$isChangelog = in_array($basename, ['changelog.md', 'changelog'], true);
|
||||||
$isProtected = $isReadme || $isChangelog;
|
$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) {
|
if ($isReadme) {
|
||||||
$summary['skipped'][] = ['file' => $targetPath, 'reason' => 'README — never overwritten'];
|
$summary['skipped'][] = ['file' => $targetPath, 'reason' => 'README — never overwritten'];
|
||||||
@@ -903,6 +908,77 @@ HCL;
|
|||||||
return $entries;
|
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
|
private function mergeGitConfigFile(string $existing, string $template): string
|
||||||
{
|
{
|
||||||
$existingLines = array_map('rtrim', explode("\n", $existing));
|
$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.
|
* pinned commit SHA. Already-pinned references (40-char hex SHA) are left untouched.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* php api/maintenance/pin_action_shas.php [--dry-run] [--verbose] [--help]
|
* php maintenance/pin_action_shas.php [--dry-run] [--verbose] [--help]
|
||||||
*
|
*
|
||||||
* Environment:
|
* Environment:
|
||||||
* GH_TOKEN Personal access token for GitHub API calls.
|
* GH_TOKEN Personal access token for GitHub API calls.
|
||||||
@@ -90,7 +90,7 @@ class ActionShaPinner
|
|||||||
private function showHelp(): void
|
private function showHelp(): void
|
||||||
{
|
{
|
||||||
echo <<<'HELP'
|
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
|
Pins GitHub Actions to immutable commit SHAs in all .github/workflows/*.yml
|
||||||
files. Already-pinned references (40-character commit SHA) are skipped.
|
files. Already-pinned references (40-character commit SHA) are skipped.
|
||||||
@@ -106,10 +106,10 @@ Environment:
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
# Preview all changes
|
# 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
|
# Apply changes
|
||||||
GH_TOKEN=ghp_xxx php api/maintenance/pin_action_shas.php
|
GH_TOKEN=ghp_xxx php maintenance/pin_action_shas.php
|
||||||
|
|
||||||
HELP;
|
HELP;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
* BRIEF: Generate a live inventory dashboard of all governed repos as a GitHub issue
|
* BRIEF: Generate a live inventory dashboard of all governed repos as a GitHub issue
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/maintenance/repo_inventory.php # Generate and post dashboard
|
* php maintenance/repo_inventory.php # Generate and post dashboard
|
||||||
* php api/maintenance/repo_inventory.php --dry-run # Preview only
|
* php maintenance/repo_inventory.php --dry-run # Preview only
|
||||||
* php api/maintenance/repo_inventory.php --json # JSON output to stdout
|
* php maintenance/repo_inventory.php --json # JSON output to stdout
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
* BRIEF: Audit FTP secrets and variables across all governed repos — report missing or stale
|
* BRIEF: Audit FTP secrets and variables across all governed repos — report missing or stale
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/maintenance/rotate_secrets.php --all # Audit all repos
|
* php maintenance/rotate_secrets.php --all # Audit all repos
|
||||||
* php api/maintenance/rotate_secrets.php --repo MokoCRM # Single repo
|
* php maintenance/rotate_secrets.php --repo MokoCRM # Single repo
|
||||||
* php api/maintenance/rotate_secrets.php --all --json # JSON output
|
* php 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 --create-issue # Post results as issue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ declare(strict_types=1);
|
|||||||
*/
|
*/
|
||||||
class ScriptRegistryUpdater
|
class ScriptRegistryUpdater
|
||||||
{
|
{
|
||||||
private const REGISTRY_PATH = 'api/.script-registry.json';
|
private const REGISTRY_PATH = '.script-registry.json';
|
||||||
|
|
||||||
private bool $dryRun = false;
|
private bool $dryRun = false;
|
||||||
private bool $verbose = false;
|
private bool $verbose = false;
|
||||||
|
|||||||
@@ -435,15 +435,15 @@ class UpdateVersionFromReadme extends CliFramework
|
|||||||
"",
|
"",
|
||||||
"1. Run the sync script locally:",
|
"1. Run the sync script locally:",
|
||||||
" ```bash",
|
" ```bash",
|
||||||
" php api/maintenance/update_version_from_readme.php --path . --dry-run",
|
" php 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 .",
|
||||||
" ```",
|
" ```",
|
||||||
"2. Inspect any files still flagged — they may use a non-standard VERSION format.",
|
"2. Inspect any files still flagged — they may use a non-standard VERSION format.",
|
||||||
"3. Update them manually to match `VERSION: {$version}`.",
|
"3. Update them manually to match `VERSION: {$version}`.",
|
||||||
"4. Commit and push — this issue will be closed automatically on the next successful sync.",
|
"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 {
|
try {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ Icon?
|
|||||||
.idea/
|
.idea/
|
||||||
.settings/
|
.settings/
|
||||||
.claude/
|
.claude/
|
||||||
|
.claude-worktree*/
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/settings.json.example
|
!.vscode/settings.json.example
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ Icon?
|
|||||||
.idea/
|
.idea/
|
||||||
.settings/
|
.settings/
|
||||||
.claude/
|
.claude/
|
||||||
|
.claude-worktree*/
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/settings.json.example
|
!.vscode/settings.json.example
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ Icon?
|
|||||||
.idea/
|
.idea/
|
||||||
.settings/
|
.settings/
|
||||||
.claude/
|
.claude/
|
||||||
|
.claude-worktree*/
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/settings.json.example
|
!.vscode/settings.json.example
|
||||||
|
|||||||
@@ -1,45 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
<!--
|
<!-- Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
||||||
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>
|
<updates>
|
||||||
<update>
|
<update>
|
||||||
<name>{{EXTENSION_NAME}}</name>
|
<name>{{EXTENSION_NAME}}</name>
|
||||||
@@ -48,12 +12,14 @@ NOTE: Dual-platform: Gitea (primary) and GitHub (backup mirror).
|
|||||||
<type>{{EXTENSION_TYPE}}</type>
|
<type>{{EXTENSION_TYPE}}</type>
|
||||||
<version>{{VERSION}}</version>
|
<version>{{VERSION}}</version>
|
||||||
<downloads>
|
<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">
|
||||||
<downloadurl type="full" format="zip">https://github.com/{{GITHUB_ORG}}/{{REPO_NAME}}/releases/download/v{{VERSION}}/{{EXTENSION_ELEMENT}}.zip</downloadurl>
|
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>
|
</downloads>
|
||||||
<targetplatform name="joomla" version="((5\.[0-9])|(6\.[0-9]))" />
|
<targetplatform name="joomla" version="[56].*"/>
|
||||||
<php_minimum>8.2</php_minimum>
|
<php_minimum>8.1</php_minimum>
|
||||||
<maintainer>Moko Consulting</maintainer>
|
|
||||||
<maintainerurl>{{MAINTAINER_URL}}</maintainerurl>
|
|
||||||
</update>
|
</update>
|
||||||
</updates>
|
</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):
|
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
|
- **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
|
- **deploy-manual.yml.template** - Manual deployment workflow for Joomla extensions with release triggering
|
||||||
- **release.yml.template** - Automated release workflow for creating and publishing Joomla extension packages
|
|
||||||
- **repo_health.yml.template** - Repository health monitoring including documentation checks and standards validation
|
- **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/`)
|
### Dolibarr Templates (`dolibarr/`)
|
||||||
|
|
||||||
@@ -474,6 +474,44 @@ Project-specific validation workflows using the MokoStandards plugin system. Eac
|
|||||||
- Artifact upload for validation results
|
- Artifact upload for validation results
|
||||||
- Proper exit codes (0=success, 1=failure, 2=error)
|
- 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
|
## Usage
|
||||||
|
|
||||||
### For New Projects
|
### For New Projects
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ jobs:
|
|||||||
|
|
||||||
# Hardcoded authorized users — always allowed
|
# Hardcoded authorized users — always allowed
|
||||||
case "$ACTOR" in
|
case "$ACTOR" in
|
||||||
jmiller-moko|github-actions\[bot\])
|
jmiller|gitea-actions[bot])
|
||||||
ALLOWED=true
|
ALLOWED=true
|
||||||
PERMISSION=admin
|
PERMISSION=admin
|
||||||
METHOD="hardcoded allowlist"
|
METHOD="hardcoded allowlist"
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ jobs:
|
|||||||
|
|
||||||
# Search for an existing health-check issue (any state)
|
# 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 \
|
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
|
if [ -n "$EXISTING" ] && [ "$EXISTING" != "null" ]; then
|
||||||
# Check if it's closed — reopen if so
|
# Check if it's closed — reopen if so
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
# | 8. Build ZIP, upload asset, write SHA-256 to updates.xml |
|
# | 8. Build ZIP, upload asset, write SHA-256 to updates.xml |
|
||||||
# | |
|
# | |
|
||||||
# | Every version change: archives main -> version/XX.YY branch |
|
# | 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): |
|
# | First release only (patch == 01): |
|
||||||
# | 7b. Create new Gitea Release |
|
# | 7b. Create new Gitea Release |
|
||||||
# | |
|
# | |
|
||||||
@@ -73,9 +73,9 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
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: |
|
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" \
|
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||||
/tmp/mokostandards-api
|
/tmp/mokostandards-api
|
||||||
cd /tmp/mokostandards-api
|
cd /tmp/mokostandards-api
|
||||||
@@ -102,22 +102,15 @@ jobs:
|
|||||||
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
|
echo "branch=version/${MAJOR}" >> "$GITHUB_OUTPUT"
|
||||||
echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
|
echo "minor=$MINOR" >> "$GITHUB_OUTPUT"
|
||||||
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
|
echo "major=$MAJOR" >> "$GITHUB_OUTPUT"
|
||||||
echo "release_tag=v${MAJOR}" >> "$GITHUB_OUTPUT"
|
echo "release_tag=stable" >> "$GITHUB_OUTPUT"
|
||||||
# Determine stability for mirror gating
|
|
||||||
echo "stability=stable" >> "$GITHUB_OUTPUT"
|
echo "stability=stable" >> "$GITHUB_OUTPUT"
|
||||||
if [ "$PATCH" = "00" ]; then
|
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
if [ "$PATCH" = "00" ] || [ "$PATCH" = "01" ]; then
|
||||||
echo "is_minor=false" >> "$GITHUB_OUTPUT"
|
echo "is_minor=true" >> "$GITHUB_OUTPUT"
|
||||||
echo "Version: $VERSION (patch 00 = development — skipping release)"
|
echo "Version: $VERSION (first release for this minor — full pipeline)"
|
||||||
else
|
else
|
||||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
echo "is_minor=false" >> "$GITHUB_OUTPUT"
|
||||||
if [ "$PATCH" = "01" ]; then
|
echo "Version: $VERSION (patch — platform version + badges only)"
|
||||||
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
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Check if already released
|
- name: Check if already released
|
||||||
@@ -296,9 +289,15 @@ jobs:
|
|||||||
[ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
|
[ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
|
||||||
[ -z "$EXT_TYPE" ] && EXT_TYPE="component"
|
[ -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
|
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
|
fi
|
||||||
|
|
||||||
# Build client tag: plugins and frontend modules need <client>site</client>
|
# Build client tag: plugins and frontend modules need <client>site</client>
|
||||||
@@ -326,11 +325,12 @@ jobs:
|
|||||||
PHP_TAG="<php_minimum>${PHP_MINIMUM}</php_minimum>"
|
PHP_TAG="<php_minimum>${PHP_MINIMUM}</php_minimum>"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/v${VERSION}/${EXT_ELEMENT}-${VERSION}.zip"
|
DOWNLOAD_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/download/stable/${EXT_ELEMENT}-${VERSION}.zip"
|
||||||
INFO_URL="${GITEA_URL}/${GITEA_ORG}/${GITEA_REPO}/releases/tag/v${VERSION}"
|
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' ' <update>'
|
||||||
printf '%s\n' " <name>${EXT_NAME}</name>"
|
printf '%s\n' " <name>${EXT_NAME}</name>"
|
||||||
printf '%s\n' " <description>${EXT_NAME} update</description>"
|
printf '%s\n' " <description>${EXT_NAME} update</description>"
|
||||||
@@ -339,9 +339,7 @@ jobs:
|
|||||||
printf '%s\n' " <version>${VERSION}</version>"
|
printf '%s\n' " <version>${VERSION}</version>"
|
||||||
[ -n "$CLIENT_TAG" ] && printf '%s\n' " ${CLIENT_TAG}"
|
[ -n "$CLIENT_TAG" ] && printf '%s\n' " ${CLIENT_TAG}"
|
||||||
[ -n "$FOLDER_TAG" ] && printf '%s\n' " ${FOLDER_TAG}"
|
[ -n "$FOLDER_TAG" ] && printf '%s\n' " ${FOLDER_TAG}"
|
||||||
printf '%s\n' ' <tags>'
|
printf '%s\n' " <tags><tag>${TAG_NAME}</tag></tags>"
|
||||||
printf '%s\n' ' <tag>stable</tag>'
|
|
||||||
printf '%s\n' ' </tags>'
|
|
||||||
printf '%s\n' " <infourl title=\"${EXT_NAME}\">${INFO_URL}</infourl>"
|
printf '%s\n' " <infourl title=\"${EXT_NAME}\">${INFO_URL}</infourl>"
|
||||||
printf '%s\n' ' <downloads>'
|
printf '%s\n' ' <downloads>'
|
||||||
printf '%s\n' " <downloadurl type=\"full\" format=\"zip\">${DOWNLOAD_URL}</downloadurl>"
|
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' ' <maintainer>Moko Consulting</maintainer>'
|
||||||
printf '%s\n' ' <maintainerurl>https://mokoconsulting.tech</maintainerurl>'
|
printf '%s\n' ' <maintainerurl>https://mokoconsulting.tech</maintainerurl>'
|
||||||
printf '%s\n' ' </update>'
|
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>'
|
printf '%s\n' '<updates>'
|
||||||
[ -n "$DEV_ENTRY" ] && echo "$DEV_ENTRY"
|
build_entry "development"
|
||||||
[ -n "$ALPHA_ENTRY" ] && echo "$ALPHA_ENTRY"
|
build_entry "alpha"
|
||||||
[ -n "$BETA_ENTRY" ] && echo "$BETA_ENTRY"
|
build_entry "beta"
|
||||||
[ -n "$RC_ENTRY" ] && echo "$RC_ENTRY"
|
build_entry "rc"
|
||||||
cat /tmp/stable_entry.xml
|
build_entry "stable"
|
||||||
printf '%s\n' '</updates>'
|
printf '%s\n' '</updates>'
|
||||||
} > updates.xml
|
} > 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 ---------------------------------------------------
|
# -- Commit all changes ---------------------------------------------------
|
||||||
- name: Commit release changes
|
- name: Commit release changes
|
||||||
@@ -393,10 +384,12 @@ jobs:
|
|||||||
VERSION="${{ steps.version.outputs.version }}"
|
VERSION="${{ steps.version.outputs.version }}"
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||||
git config --local user.name "gitea-actions[bot]"
|
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 add -A
|
||||||
git commit -m "chore(release): build ${VERSION} [skip ci]" \
|
git commit -m "chore(release): build ${VERSION} [skip ci]" \
|
||||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>"
|
||||||
git push
|
git push -u origin HEAD
|
||||||
|
|
||||||
# -- STEP 6: Create tag ---------------------------------------------------
|
# -- STEP 6: Create tag ---------------------------------------------------
|
||||||
- name: "Step 6: Create git tag"
|
- name: "Step 6: Create git tag"
|
||||||
@@ -577,9 +570,9 @@ jobs:
|
|||||||
block = re.sub(r' <downloads>.*?</downloads>', new_downloads, block, flags=re.DOTALL)
|
block = re.sub(r' <downloads>.*?</downloads>', new_downloads, block, flags=re.DOTALL)
|
||||||
# Add or replace sha256
|
# Add or replace sha256
|
||||||
if '<sha256>' in block:
|
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:
|
else:
|
||||||
block = block.replace('</downloads>', f'</downloads>\n <sha256>sha256:{sha}</sha256>')
|
block = block.replace('</downloads>', f'</downloads>\n <sha256>{sha}</sha256>')
|
||||||
return block
|
return block
|
||||||
|
|
||||||
content = re.sub(
|
content = re.sub(
|
||||||
@@ -593,10 +586,76 @@ jobs:
|
|||||||
f.write(content)
|
f.write(content)
|
||||||
PYEOF
|
PYEOF
|
||||||
|
|
||||||
|
CURRENT_BRANCH="${{ github.ref_name }}"
|
||||||
git add updates.xml
|
git add updates.xml
|
||||||
git commit -m "chore(release): ZIP + tar.gz for ${VERSION} [skip ci]" \
|
git commit -m "chore(release): ZIP + tar.gz for ${VERSION} [skip ci]" \
|
||||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" || true
|
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" || true
|
||||||
git push || 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
|
fi
|
||||||
|
|
||||||
echo "### Joomla Packages" >> $GITHUB_STEP_SUMMARY
|
echo "### Joomla Packages" >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -613,10 +672,10 @@ jobs:
|
|||||||
if: >-
|
if: >-
|
||||||
steps.version.outputs.skip != 'true' &&
|
steps.version.outputs.skip != 'true' &&
|
||||||
steps.version.outputs.stability == 'stable' &&
|
steps.version.outputs.stability == 'stable' &&
|
||||||
secrets.GH_MIRROR_TOKEN != ''
|
secrets.GH_TOKEN != ''
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_MIRROR_TOKEN }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
VERSION="${{ steps.version.outputs.version }}"
|
VERSION="${{ steps.version.outputs.version }}"
|
||||||
RELEASE_TAG="${{ steps.version.outputs.release_tag }}"
|
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_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||||
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
|
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
|
||||||
run: |
|
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" \
|
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||||
/tmp/mokostandards-api
|
/tmp/mokostandards-api
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# PATH: /templates/workflows/joomla/deploy-manual.yml.template
|
# PATH: /templates/workflows/joomla/deploy-manual.yml.template
|
||||||
# VERSION: 04.06.00
|
# VERSION: 04.06.00
|
||||||
# BRIEF: Manual SFTP deploy to dev server for Joomla repos
|
# 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.
|
# dev server testing only — triggered via workflow_dispatch.
|
||||||
|
|
||||||
name: Deploy to Dev (Manual)
|
name: Deploy to Dev (Manual)
|
||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
MOKO_CLONE_HOST: ${{ secrets.GA_TOKEN && 'git.mokoconsulting.tech/MokoConsulting' || 'github.com/mokoconsulting-tech' }}
|
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 }}"}}'
|
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GA_TOKEN || github.token }}"}}'
|
||||||
run: |
|
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" \
|
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||||
/tmp/mokostandards-api 2>/dev/null || true
|
/tmp/mokostandards-api 2>/dev/null || true
|
||||||
if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then
|
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
|
## Available Templates
|
||||||
|
|
||||||
- **ci.yml** - Continuous integration workflow with PHP validation, XML checking, and manifest verification
|
- **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.
|
||||||
- **test.yml** - Comprehensive testing workflow with PHPUnit, code quality checks, and integration tests
|
- **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).
|
||||||
- **release.yml** - Automated release workflow for creating and publishing Joomla extension packages
|
- **ci-joomla.yml.template** - Continuous integration workflow with PHP validation, XML checking, and manifest verification
|
||||||
- **repo_health.yml** - Repository health monitoring including documentation checks and standards validation
|
- **deploy-manual.yml.template** - Manual deployment workflow for Joomla extensions
|
||||||
- **version_branch.yml** - Automated version branch management and release preparation
|
- **repo_health.yml.template** - Repository health monitoring including documentation checks and standards validation
|
||||||
|
|
||||||
## Metadata
|
## Metadata
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ jobs:
|
|||||||
|
|
||||||
# Hardcoded authorized users — always allowed
|
# Hardcoded authorized users — always allowed
|
||||||
case "$ACTOR" in
|
case "$ACTOR" in
|
||||||
jmiller-moko|github-actions\[bot\])
|
jmiller|gitea-actions[bot])
|
||||||
ALLOWED=true
|
ALLOWED=true
|
||||||
PERMISSION=admin
|
PERMISSION=admin
|
||||||
METHOD="hardcoded allowlist"
|
METHOD="hardcoded allowlist"
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
MOKO_CLONE_TOKEN: ${{ secrets.GA_TOKEN }}
|
||||||
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
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: |
|
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" \
|
"https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/MokoStandards-API.git" \
|
||||||
/tmp/mokostandards-api 2>/dev/null || true
|
/tmp/mokostandards-api 2>/dev/null || true
|
||||||
if [ -d "/tmp/mokostandards-api" ] && [ -f "/tmp/mokostandards-api/composer.json" ]; then
|
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}"
|
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")
|
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)
|
# Auto-bump patch on all branches (dev, alpha, beta, rc)
|
||||||
if [[ "$BRANCH" != dev/* ]]; then
|
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
||||||
git config --local user.email "gitea-actions[bot]@mokoconsulting.tech"
|
git config --local user.name "gitea-actions[bot]"
|
||||||
git config --local user.name "gitea-actions[bot]"
|
BUMPED=$(php /tmp/mokostandards-api/cli/version_bump.php --path . 2>/dev/null || true)
|
||||||
BUMPED=$(php /tmp/mokostandards-api/cli/version_bump.php --path . 2>/dev/null || true)
|
if [ -n "$BUMPED" ]; then
|
||||||
if [ -n "$BUMPED" ]; then
|
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null || echo "$VERSION")
|
||||||
VERSION=$(php /tmp/mokostandards-api/cli/version_read.php --path . 2>/dev/null || echo "$VERSION")
|
git add -A
|
||||||
git add -A
|
git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
|
||||||
git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \
|
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" 2>/dev/null || true
|
||||||
--author="gitea-actions[bot] <gitea-actions[bot]@mokoconsulting.tech>" 2>/dev/null || true
|
git push 2>/dev/null || true
|
||||||
git push 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Determine stability from branch or input
|
# Determine stability from branch or input
|
||||||
@@ -140,9 +138,12 @@ jobs:
|
|||||||
[ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
|
[ -z "$EXT_NAME" ] && EXT_NAME="${{ github.event.repository.name }}"
|
||||||
[ -z "$EXT_TYPE" ] && EXT_TYPE="component"
|
[ -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
|
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
|
fi
|
||||||
|
|
||||||
# Use manifest version if README version is empty
|
# 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=\"zip\">${DOWNLOAD_URL}</downloadurl>\n"
|
||||||
NEW_ENTRY="${NEW_ENTRY} <downloadurl type=\"full\" format=\"tar.gz\">${TAR_URL}</downloadurl>\n"
|
NEW_ENTRY="${NEW_ENTRY} <downloadurl type=\"full\" format=\"tar.gz\">${TAR_URL}</downloadurl>\n"
|
||||||
NEW_ENTRY="${NEW_ENTRY} </downloads>\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"
|
NEW_ENTRY="${NEW_ENTRY} ${TARGET_PLATFORM}\n"
|
||||||
[ -n "$PHP_TAG" ] && NEW_ENTRY="${NEW_ENTRY} ${PHP_TAG}\n"
|
[ -n "$PHP_TAG" ] && NEW_ENTRY="${NEW_ENTRY} ${PHP_TAG}\n"
|
||||||
NEW_ENTRY="${NEW_ENTRY} <maintainer>Moko Consulting</maintainer>\n"
|
NEW_ENTRY="${NEW_ENTRY} <maintainer>Moko Consulting</maintainer>\n"
|
||||||
@@ -285,23 +286,50 @@ jobs:
|
|||||||
printf '%b' "$NEW_ENTRY" > /tmp/new_entry.xml
|
printf '%b' "$NEW_ENTRY" > /tmp/new_entry.xml
|
||||||
|
|
||||||
# -- Merge into updates.xml (only update this stability channel) -
|
# -- 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
|
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
|
printf '%s\n' '<updates>' >> updates.xml
|
||||||
cat /tmp/new_entry.xml >> updates.xml
|
cat /tmp/new_entry.xml >> updates.xml
|
||||||
printf '\n%s\n' '</updates>' >> updates.xml
|
printf '\n%s\n' '</updates>' >> updates.xml
|
||||||
else
|
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
|
python3 << PYEOF
|
||||||
import re
|
import re, os
|
||||||
|
targets = os.environ["PY_TARGETS"].split(",")
|
||||||
stability = "${STABILITY}"
|
stability = "${STABILITY}"
|
||||||
with open("updates.xml") as f:
|
with open("updates.xml") as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
with open("/tmp/new_entry.xml") as f:
|
with open("/tmp/new_entry.xml") as f:
|
||||||
new_entry = f.read()
|
new_entry_template = f.read()
|
||||||
pattern = r" <update>.*?<tag>" + re.escape(stability) + r"</tag>.*?</update>\n?"
|
for tag in targets:
|
||||||
content = re.sub(pattern, "", content, flags=re.DOTALL)
|
tag = tag.strip()
|
||||||
content = content.replace("</updates>", new_entry + "\n</updates>")
|
# 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)
|
content = re.sub(r"\n{3,}", "\n\n", content)
|
||||||
with open("updates.xml", "w") as f:
|
with open("updates.xml", "w") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
@@ -309,7 +337,12 @@ jobs:
|
|||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
# Fallback: rebuild keeping other stability entries
|
# 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>'
|
printf '%s\n' '<updates>'
|
||||||
for TAG in stable rc development; do
|
for TAG in stable rc development; do
|
||||||
[ "$TAG" = "${STABILITY}" ] && continue
|
[ "$TAG" = "${STABILITY}" ] && continue
|
||||||
@@ -338,10 +371,10 @@ jobs:
|
|||||||
- name: Mirror release to GitHub
|
- name: Mirror release to GitHub
|
||||||
if: >-
|
if: >-
|
||||||
(steps.update.outputs.stability == 'stable' || steps.update.outputs.stability == 'rc') &&
|
(steps.update.outputs.stability == 'stable' || steps.update.outputs.stability == 'rc') &&
|
||||||
secrets.GH_MIRROR_TOKEN != ''
|
secrets.GH_TOKEN != ''
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GH_MIRROR_TOKEN }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
||||||
STABILITY="${{ steps.update.outputs.stability }}"
|
STABILITY="${{ steps.update.outputs.stability }}"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
|
# REPO: https://git.mokoconsulting.tech/mokoconsulting-tech/MokoStandards-API
|
||||||
# PATH: /.github/workflows/auto-assign.yml
|
# PATH: /.github/workflows/auto-assign.yml
|
||||||
# VERSION: 04.06.00
|
# 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
|
name: Auto-Assign Issues & PRs
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ jobs:
|
|||||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||||
run: |
|
run: |
|
||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
ASSIGNEE="jmiller-moko"
|
ASSIGNEE="jmiller"
|
||||||
|
|
||||||
echo "## 🏷️ Auto-Assign Report" >> $GITHUB_STEP_SUMMARY
|
echo "## 🏷️ Auto-Assign Report" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -44,10 +44,10 @@ jobs:
|
|||||||
ASSIGNED_PRS=0
|
ASSIGNED_PRS=0
|
||||||
|
|
||||||
# Assign unassigned open issues
|
# 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
|
for NUM in $ISSUES; do
|
||||||
# Skip PRs (the issues endpoint returns PRs too)
|
# 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
|
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 && {
|
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))
|
ASSIGNED_ISSUES=$((ASSIGNED_ISSUES + 1))
|
||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Assign unassigned open PRs
|
# 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
|
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 && {
|
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))
|
ASSIGNED_PRS=$((ASSIGNED_PRS + 1))
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ jobs:
|
|||||||
--title "$SUB_FULL_TITLE" \
|
--title "$SUB_FULL_TITLE" \
|
||||||
--body "$SUB_BODY" \
|
--body "$SUB_BODY" \
|
||||||
--label "${SUB_LABELS}" \
|
--label "${SUB_LABELS}" \
|
||||||
--assignee "jmiller-moko" 2>&1)
|
--assignee "jmiller" 2>&1)
|
||||||
|
|
||||||
SUB_NUM=$(echo "$SUB_URL" | grep -oE '[0-9]+$')
|
SUB_NUM=$(echo "$SUB_URL" | grep -oE '[0-9]+$')
|
||||||
if [ -n "$SUB_NUM" ]; then
|
if [ -n "$SUB_NUM" ]; then
|
||||||
@@ -154,7 +154,7 @@ jobs:
|
|||||||
--title "$TITLE" \
|
--title "$TITLE" \
|
||||||
--body "$PARENT_BODY" \
|
--body "$PARENT_BODY" \
|
||||||
--label "${LABEL_TYPE},version" \
|
--label "${LABEL_TYPE},version" \
|
||||||
--assignee "jmiller-moko" 2>&1)
|
--assignee "jmiller" 2>&1)
|
||||||
|
|
||||||
PARENT_NUM=$(echo "$PARENT_URL" | grep -oE '[0-9]+$')
|
PARENT_NUM=$(echo "$PARENT_URL" | grep -oE '[0-9]+$')
|
||||||
|
|
||||||
|
|||||||
@@ -44,9 +44,10 @@ jobs:
|
|||||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||||
run: |
|
run: |
|
||||||
ACTOR="${{ github.actor }}"
|
ACTOR="${{ github.actor }}"
|
||||||
|
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||||
REPO="${{ github.repository }}"
|
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 \
|
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
|
if [ "$PERMISSION" != "admin" ]; then
|
||||||
echo "Denied: only admins can freeze/unfreeze branches (${ACTOR} has ${PERMISSION})"
|
echo "Denied: only admins can freeze/unfreeze branches (${ACTOR} has ${PERMISSION})"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -80,7 +81,7 @@ jobs:
|
|||||||
printf '"conditions":{"ref_name":{"include":["refs/heads/%s"],"exclude":[]}},' "${BRANCH}" >> /tmp/ruleset.json
|
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
|
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
|
if echo "$RESULT" | grep -qE '^[0-9]+$'; then
|
||||||
echo "Frozen \`${BRANCH}\` — ruleset #${RESULT}" >> $GITHUB_STEP_SUMMARY
|
echo "Frozen \`${BRANCH}\` — ruleset #${RESULT}" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ jobs:
|
|||||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||||
run: |
|
run: |
|
||||||
ACTOR="${{ github.actor }}"
|
ACTOR="${{ github.actor }}"
|
||||||
|
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
ORG="${{ github.repository_owner }}"
|
ORG="${{ github.repository_owner }}"
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ jobs:
|
|||||||
AUTHORIZED="false"
|
AUTHORIZED="false"
|
||||||
|
|
||||||
# Hardcoded authorized users — always allowed to deploy
|
# 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
|
for user in $AUTHORIZED_USERS; do
|
||||||
if [ "$ACTOR" = "$user" ]; then
|
if [ "$ACTOR" = "$user" ]; then
|
||||||
AUTHORIZED="true"
|
AUTHORIZED="true"
|
||||||
@@ -99,12 +100,12 @@ jobs:
|
|||||||
# For other actors, check repo/org permissions via API
|
# For other actors, check repo/org permissions via API
|
||||||
if [ "$AUTHORIZED" != "true" ]; then
|
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 \
|
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"
|
METHOD="repo collaborator API"
|
||||||
|
|
||||||
if [ -z "$PERMISSION" ]; then
|
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}" \
|
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"
|
METHOD="org membership API"
|
||||||
if [ "$ORG_ROLE" = "owner" ]; then
|
if [ "$ORG_ROLE" = "owner" ]; then
|
||||||
PERMISSION="admin"
|
PERMISSION="admin"
|
||||||
@@ -637,6 +638,7 @@ jobs:
|
|||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
RUN_URL="${{ github.server_url }}/${REPO}/actions/runs/${{ github.run_id }}"
|
RUN_URL="${{ github.server_url }}/${REPO}/actions/runs/${{ github.run_id }}"
|
||||||
ACTOR="${{ github.actor }}"
|
ACTOR="${{ github.actor }}"
|
||||||
|
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||||
BRANCH="${{ github.ref_name }}"
|
BRANCH="${{ github.ref_name }}"
|
||||||
EVENT="${{ github.event_name }}"
|
EVENT="${{ github.event_name }}"
|
||||||
NOW=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
NOW=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
||||||
@@ -673,7 +675,7 @@ jobs:
|
|||||||
|
|
||||||
# Look for an existing open deploy-failure issue
|
# 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 \
|
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
|
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 \
|
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" \
|
--title "$TITLE" \
|
||||||
--body "$BODY" \
|
--body "$BODY" \
|
||||||
--label "$LABEL" \
|
--label "$LABEL" \
|
||||||
--assignee "jmiller-moko" \
|
--assignee "jmiller" \
|
||||||
| tee -a "$GITHUB_STEP_SUMMARY"
|
| tee -a "$GITHUB_STEP_SUMMARY"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ jobs:
|
|||||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||||
run: |
|
run: |
|
||||||
ACTOR="${{ github.actor }}"
|
ACTOR="${{ github.actor }}"
|
||||||
|
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
ORG="${{ github.repository_owner }}"
|
ORG="${{ github.repository_owner }}"
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ jobs:
|
|||||||
AUTHORIZED="false"
|
AUTHORIZED="false"
|
||||||
|
|
||||||
# Hardcoded authorized users — always allowed to deploy
|
# 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
|
for user in $AUTHORIZED_USERS; do
|
||||||
if [ "$ACTOR" = "$user" ]; then
|
if [ "$ACTOR" = "$user" ]; then
|
||||||
AUTHORIZED="true"
|
AUTHORIZED="true"
|
||||||
@@ -103,12 +104,12 @@ jobs:
|
|||||||
# For other actors, check repo/org permissions via API
|
# For other actors, check repo/org permissions via API
|
||||||
if [ "$AUTHORIZED" != "true" ]; then
|
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 \
|
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"
|
METHOD="repo collaborator API"
|
||||||
|
|
||||||
if [ -z "$PERMISSION" ]; then
|
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}" \
|
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"
|
METHOD="org membership API"
|
||||||
if [ "$ORG_ROLE" = "owner" ]; then
|
if [ "$ORG_ROLE" = "owner" ]; then
|
||||||
PERMISSION="admin"
|
PERMISSION="admin"
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ jobs:
|
|||||||
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
GA_TOKEN: ${{ secrets.GA_TOKEN || secrets.GA_TOKEN || github.token }}
|
||||||
run: |
|
run: |
|
||||||
ACTOR="${{ github.actor }}"
|
ACTOR="${{ github.actor }}"
|
||||||
|
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
ORG="${{ github.repository_owner }}"
|
ORG="${{ github.repository_owner }}"
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ jobs:
|
|||||||
AUTHORIZED="false"
|
AUTHORIZED="false"
|
||||||
|
|
||||||
# Hardcoded authorized users — always allowed to deploy
|
# 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
|
for user in $AUTHORIZED_USERS; do
|
||||||
if [ "$ACTOR" = "$user" ]; then
|
if [ "$ACTOR" = "$user" ]; then
|
||||||
AUTHORIZED="true"
|
AUTHORIZED="true"
|
||||||
@@ -107,12 +108,12 @@ jobs:
|
|||||||
# For other actors, check repo/org permissions via API
|
# For other actors, check repo/org permissions via API
|
||||||
if [ "$AUTHORIZED" != "true" ]; then
|
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 \
|
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"
|
METHOD="repo collaborator API"
|
||||||
|
|
||||||
if [ -z "$PERMISSION" ]; then
|
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}" \
|
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"
|
METHOD="org membership API"
|
||||||
if [ "$ORG_ROLE" = "owner" ]; then
|
if [ "$ORG_ROLE" = "owner" ]; then
|
||||||
PERMISSION="admin"
|
PERMISSION="admin"
|
||||||
@@ -579,6 +580,7 @@ jobs:
|
|||||||
REPO="${{ github.repository }}"
|
REPO="${{ github.repository }}"
|
||||||
RUN_URL="${{ github.server_url }}/${REPO}/actions/runs/${{ github.run_id }}"
|
RUN_URL="${{ github.server_url }}/${REPO}/actions/runs/${{ github.run_id }}"
|
||||||
ACTOR="${{ github.actor }}"
|
ACTOR="${{ github.actor }}"
|
||||||
|
ALLOWED_USERS="jmiller gitea-actions[bot]"
|
||||||
BRANCH="${{ github.ref_name }}"
|
BRANCH="${{ github.ref_name }}"
|
||||||
EVENT="${{ github.event_name }}"
|
EVENT="${{ github.event_name }}"
|
||||||
NOW=$(date -u '+%Y-%m-%d %H:%M:%S UTC')
|
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)
|
# 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 \
|
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
|
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 \
|
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" \
|
--title "$TITLE" \
|
||||||
--body "$BODY" \
|
--body "$BODY" \
|
||||||
--label "$LABEL" \
|
--label "$LABEL" \
|
||||||
--assignee "jmiller-moko" \
|
--assignee "jmiller" \
|
||||||
| tee -a "$GITHUB_STEP_SUMMARY"
|
| tee -a "$GITHUB_STEP_SUMMARY"
|
||||||
fi
|
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"
|
echo "✅ Scheduled run — authorized"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
AUTHORIZED_USERS="jmiller-moko gitea-actions[bot]"
|
AUTHORIZED_USERS="jmiller gitea-actions[bot]"
|
||||||
for user in $AUTHORIZED_USERS; do
|
for user in $AUTHORIZED_USERS; do
|
||||||
if [ "$ACTOR" = "$user" ]; then
|
if [ "$ACTOR" = "$user" ]; then
|
||||||
echo "✅ ${ACTOR} authorized"
|
echo "✅ ${ACTOR} authorized"
|
||||||
@@ -88,7 +88,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
done
|
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 \
|
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
|
case "$PERMISSION" in
|
||||||
admin|maintain) echo "✅ ${ACTOR} has ${PERMISSION}" ;;
|
admin|maintain) echo "✅ ${ACTOR} has ${PERMISSION}" ;;
|
||||||
*) echo "❌ Admin or maintain required"; exit 1 ;;
|
*) echo "❌ Admin or maintain required"; exit 1 ;;
|
||||||
@@ -191,7 +191,7 @@ jobs:
|
|||||||
echo "## 🏷️ Label Reset" >> $GITHUB_STEP_SUMMARY
|
echo "## 🏷️ Label Reset" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $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=''))")
|
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
|
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
|
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 | \
|
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 "^chore/sync-mokostandards" | \
|
||||||
grep -v "^${CURRENT}$" | while read -r branch; do
|
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
|
gh pr close "$pr" --repo "$REPO" --comment "Superseded by \`${CURRENT}\`" 2>/dev/null || true
|
||||||
echo " Closed PR #${pr}" >> $GITHUB_STEP_SUMMARY
|
echo " Closed PR #${pr}" >> $GITHUB_STEP_SUMMARY
|
||||||
done
|
done
|
||||||
@@ -305,7 +305,7 @@ jobs:
|
|||||||
# Delete cancelled and stale workflow runs
|
# Delete cancelled and stale workflow runs
|
||||||
for status in cancelled stale; do
|
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 \
|
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
|
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))
|
DELETED=$((DELETED+1))
|
||||||
done
|
done
|
||||||
@@ -327,7 +327,7 @@ jobs:
|
|||||||
|
|
||||||
DELETED=0
|
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 \
|
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
|
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))
|
DELETED=$((DELETED+1))
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ jobs:
|
|||||||
title: `[Terraform Drift] ${env} environment has drifted`,
|
title: `[Terraform Drift] ${env} environment has drifted`,
|
||||||
body: body,
|
body: body,
|
||||||
labels: ['terraform-drift', `environment:${env}`, 'infrastructure'],
|
labels: ['terraform-drift', `environment:${env}`, 'infrastructure'],
|
||||||
assignees: ['copilot', 'jmiller-moko']
|
assignees: ['copilot', 'jmiller']
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Update existing issue
|
// Update existing issue
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ jobs:
|
|||||||
if [ "${{ inputs.target_repos }}" = "all" ]; then
|
if [ "${{ inputs.target_repos }}" = "all" ]; then
|
||||||
# Get all org repositories
|
# 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" \
|
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
|
else
|
||||||
# Use specified repositories
|
# Use specified repositories
|
||||||
echo "${{ inputs.target_repos }}" | tr ',' '\n' > repos.txt
|
echo "${{ inputs.target_repos }}" | tr ',' '\n' > repos.txt
|
||||||
@@ -288,7 +288,7 @@ jobs:
|
|||||||
title: 'Terraform Repository Template Update Plan',
|
title: 'Terraform Repository Template Update Plan',
|
||||||
body: output,
|
body: output,
|
||||||
labels: ['terraform', 'repository-management', 'automation'],
|
labels: ['terraform', 'repository-management', 'automation'],
|
||||||
assignees: ['copilot', 'jmiller-moko']
|
assignees: ['copilot', 'jmiller']
|
||||||
});
|
});
|
||||||
|
|
||||||
- name: Terraform Apply
|
- name: Terraform Apply
|
||||||
@@ -342,7 +342,7 @@ jobs:
|
|||||||
title: `Repository Templates Updated - ${new Date().toISOString().split('T')[0]}`,
|
title: `Repository Templates Updated - ${new Date().toISOString().split('T')[0]}`,
|
||||||
body: body,
|
body: body,
|
||||||
labels: ['terraform', 'repository-management', 'completed'],
|
labels: ['terraform', 'repository-management', 'completed'],
|
||||||
assignees: ['copilot', 'jmiller-moko']
|
assignees: ['copilot', 'jmiller']
|
||||||
});
|
});
|
||||||
|
|
||||||
- name: Summary
|
- name: Summary
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class AutoDetectPlatform extends CLIApp
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'repo-path:' => 'Path to repository to analyze (default: current directory)',
|
'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)',
|
'output-dir:' => 'Directory for output reports (default: var/logs/validation)',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
* BRIEF: Validate composer.json enterprise dependency across all governed repos
|
* BRIEF: Validate composer.json enterprise dependency across all governed repos
|
||||||
*
|
*
|
||||||
* USAGE
|
* USAGE
|
||||||
* php api/validate/check_composer_deps.php --repo MokoCRM # Single repo
|
* php validate/check_composer_deps.php --repo MokoCRM # Single repo
|
||||||
* php api/validate/check_composer_deps.php --all # All repos
|
* php 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 --all --json # JSON output
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|||||||
@@ -139,18 +139,18 @@ class EnterpriseReadinessChecker extends CliFramework
|
|||||||
{
|
{
|
||||||
$required = ['ApiClient', 'AuditLogger', 'Config', 'ErrorRecovery', 'MetricsCollector'];
|
$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.
|
// A single vendor/ directory confirms the whole package is present — no need to check per-file.
|
||||||
$vendorPkg = "{$path}/vendor/mokoconsulting-tech/enterprise";
|
$vendorPkg = "{$path}/vendor/mokoconsulting-tech/enterprise";
|
||||||
$inVendor = is_dir($vendorPkg);
|
$inVendor = is_dir($vendorPkg);
|
||||||
|
|
||||||
foreach ($required as $library) {
|
foreach ($required as $library) {
|
||||||
$localFile = "{$path}/api/lib/Enterprise/{$library}.php";
|
$localFile = "{$path}/lib/Enterprise/{$library}.php";
|
||||||
$found = $inVendor || file_exists($localFile);
|
$found = $inVendor || file_exists($localFile);
|
||||||
$this->addResult(
|
$this->addResult(
|
||||||
"Enterprise library: {$library}",
|
"Enterprise library: {$library}",
|
||||||
$found,
|
$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 ────────────────────────────────
|
// ── Check PHP Enterprise library files ────────────────────────────────
|
||||||
$this->section('Checking PHP source files');
|
$this->section('Checking PHP source files');
|
||||||
|
|
||||||
$phpFiles = $this->findPhpFiles($path . '/api/lib/Enterprise');
|
$phpFiles = $this->findPhpFiles($path . '/lib/Enterprise');
|
||||||
$phpTotal = count($phpFiles);
|
$phpTotal = count($phpFiles);
|
||||||
|
|
||||||
foreach ($phpFiles as $i => $file) {
|
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 .= "1. **Option 1:** Run bulk sync to update all files automatically\n";
|
||||||
$body .= " ```bash\n";
|
$body .= " ```bash\n";
|
||||||
$body .= " # From MokoStandards repository\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 .= " ```\n\n";
|
||||||
$body .= "2. **Option 2:** If changes are intentional, update `.github/override.tf` to exclude files\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";
|
$body .= "3. **Option 3:** Manually update files to match templates\n\n";
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/auto_detect_platform.php
|
* PATH: /wrappers/auto_detect_platform.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'auto_detect_platform';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/bulk_sync.php
|
* PATH: /wrappers/bulk_sync.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'bulk_sync';
|
const SCRIPT_NAME = 'bulk_sync';
|
||||||
const SCRIPT_PATH = 'api/automation/bulk_sync.php';
|
const SCRIPT_PATH = 'automation/bulk_sync.php';
|
||||||
const SCRIPT_CATEGORY = 'automation';
|
const SCRIPT_CATEGORY = 'automation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_changelog.php
|
* PATH: /wrappers/check_changelog.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_changelog';
|
const SCRIPT_NAME = 'check_changelog';
|
||||||
const SCRIPT_PATH = 'api/validate/check_changelog.php';
|
const SCRIPT_PATH = 'validate/check_changelog.php';
|
||||||
const SCRIPT_CATEGORY = 'validate';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_dolibarr_module.php
|
* PATH: /wrappers/check_dolibarr_module.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_dolibarr_module';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_enterprise_readiness.php
|
* PATH: /wrappers/check_enterprise_readiness.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_enterprise_readiness';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_joomla_manifest.php
|
* PATH: /wrappers/check_joomla_manifest.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_joomla_manifest';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_language_structure.php
|
* PATH: /wrappers/check_language_structure.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_language_structure';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_license_headers.php
|
* PATH: /wrappers/check_license_headers.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_license_headers';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_no_secrets.php
|
* PATH: /wrappers/check_no_secrets.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_no_secrets';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_paths.php
|
* PATH: /wrappers/check_paths.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_paths';
|
const SCRIPT_NAME = 'check_paths';
|
||||||
const SCRIPT_PATH = 'api/validate/check_paths.php';
|
const SCRIPT_PATH = 'validate/check_paths.php';
|
||||||
const SCRIPT_CATEGORY = 'validate';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_php_syntax.php
|
* PATH: /wrappers/check_php_syntax.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_php_syntax';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_repo_health.php
|
* PATH: /wrappers/check_repo_health.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_repo_health';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_structure.php
|
* PATH: /wrappers/check_structure.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_structure';
|
const SCRIPT_NAME = 'check_structure';
|
||||||
const SCRIPT_PATH = 'api/validate/check_structure.php';
|
const SCRIPT_PATH = 'validate/check_structure.php';
|
||||||
const SCRIPT_CATEGORY = 'validate';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_tabs.php
|
* PATH: /wrappers/check_tabs.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_tabs';
|
const SCRIPT_NAME = 'check_tabs';
|
||||||
const SCRIPT_PATH = 'api/validate/check_tabs.php';
|
const SCRIPT_PATH = 'validate/check_tabs.php';
|
||||||
const SCRIPT_CATEGORY = 'validate';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_version_consistency.php
|
* PATH: /wrappers/check_version_consistency.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_version_consistency';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/check_xml_wellformed.php
|
* PATH: /wrappers/check_xml_wellformed.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'check_xml_wellformed';
|
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';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/deploy_sftp.php
|
* PATH: /wrappers/deploy_sftp.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'deploy_sftp';
|
const SCRIPT_NAME = 'deploy_sftp';
|
||||||
const SCRIPT_PATH = 'api/deploy/deploy-sftp.php';
|
const SCRIPT_PATH = 'deploy/deploy-sftp.php';
|
||||||
const SCRIPT_CATEGORY = 'deploy';
|
const SCRIPT_CATEGORY = 'deploy';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/fix_line_endings.php
|
* PATH: /wrappers/fix_line_endings.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'fix_line_endings';
|
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';
|
const SCRIPT_CATEGORY = 'fix';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/fix_permissions.php
|
* PATH: /wrappers/fix_permissions.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'fix_permissions';
|
const SCRIPT_NAME = 'fix_permissions';
|
||||||
const SCRIPT_PATH = 'api/fix/fix_permissions.php';
|
const SCRIPT_PATH = 'fix/fix_permissions.php';
|
||||||
const SCRIPT_CATEGORY = 'fix';
|
const SCRIPT_CATEGORY = 'fix';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/fix_tabs.php
|
* PATH: /wrappers/fix_tabs.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'fix_tabs';
|
const SCRIPT_NAME = 'fix_tabs';
|
||||||
const SCRIPT_PATH = 'api/fix/fix_tabs.php';
|
const SCRIPT_PATH = 'fix/fix_tabs.php';
|
||||||
const SCRIPT_CATEGORY = 'fix';
|
const SCRIPT_CATEGORY = 'fix';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/fix_trailing_spaces.php
|
* PATH: /wrappers/fix_trailing_spaces.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'fix_trailing_spaces';
|
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';
|
const SCRIPT_CATEGORY = 'fix';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+33
-33
@@ -12,7 +12,7 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/gen_wrappers.php
|
* PATH: /wrappers/gen_wrappers.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
@@ -24,43 +24,43 @@ declare(strict_types=1);
|
|||||||
*/
|
*/
|
||||||
const SCRIPTS = [
|
const SCRIPTS = [
|
||||||
// validate
|
// validate
|
||||||
'auto_detect_platform' => ['api/validate/auto_detect_platform.php', 'validate'],
|
'auto_detect_platform' => ['validate/auto_detect_platform.php', 'validate'],
|
||||||
'check_changelog' => ['api/validate/check_changelog.php', 'validate'],
|
'check_changelog' => ['validate/check_changelog.php', 'validate'],
|
||||||
'check_dolibarr_module' => ['api/validate/check_dolibarr_module.php', 'validate'],
|
'check_dolibarr_module' => ['validate/check_dolibarr_module.php', 'validate'],
|
||||||
'check_enterprise_readiness' => ['api/validate/check_enterprise_readiness.php', 'validate'],
|
'check_enterprise_readiness' => ['validate/check_enterprise_readiness.php', 'validate'],
|
||||||
'check_joomla_manifest' => ['api/validate/check_joomla_manifest.php', 'validate'],
|
'check_joomla_manifest' => ['validate/check_joomla_manifest.php', 'validate'],
|
||||||
'check_language_structure' => ['api/validate/check_language_structure.php', 'validate'],
|
'check_language_structure' => ['validate/check_language_structure.php', 'validate'],
|
||||||
'check_license_headers' => ['api/validate/check_license_headers.php', 'validate'],
|
'check_license_headers' => ['validate/check_license_headers.php', 'validate'],
|
||||||
'check_no_secrets' => ['api/validate/check_no_secrets.php', 'validate'],
|
'check_no_secrets' => ['validate/check_no_secrets.php', 'validate'],
|
||||||
'check_paths' => ['api/validate/check_paths.php', 'validate'],
|
'check_paths' => ['validate/check_paths.php', 'validate'],
|
||||||
'check_php_syntax' => ['api/validate/check_php_syntax.php', 'validate'],
|
'check_php_syntax' => ['validate/check_php_syntax.php', 'validate'],
|
||||||
'check_repo_health' => ['api/validate/check_repo_health.php', 'validate'],
|
'check_repo_health' => ['validate/check_repo_health.php', 'validate'],
|
||||||
'check_structure' => ['api/validate/check_structure.php', 'validate'],
|
'check_structure' => ['validate/check_structure.php', 'validate'],
|
||||||
'check_tabs' => ['api/validate/check_tabs.php', 'validate'],
|
'check_tabs' => ['validate/check_tabs.php', 'validate'],
|
||||||
'check_version_consistency' => ['api/validate/check_version_consistency.php', 'validate'],
|
'check_version_consistency' => ['validate/check_version_consistency.php', 'validate'],
|
||||||
'check_xml_wellformed' => ['api/validate/check_xml_wellformed.php', 'validate'],
|
'check_xml_wellformed' => ['validate/check_xml_wellformed.php', 'validate'],
|
||||||
'scan_drift' => ['api/validate/scan_drift.php', 'validate'],
|
'scan_drift' => ['validate/scan_drift.php', 'validate'],
|
||||||
// automation
|
// automation
|
||||||
'bulk_sync' => ['api/automation/bulk_sync.php', 'automation'],
|
'bulk_sync' => ['automation/bulk_sync.php', 'automation'],
|
||||||
// deploy
|
// deploy
|
||||||
'deploy_sftp' => ['api/deploy/deploy-sftp.php', 'deploy'],
|
'deploy_sftp' => ['deploy/deploy-sftp.php', 'deploy'],
|
||||||
// fix
|
// fix
|
||||||
'fix_line_endings' => ['api/fix/fix_line_endings.php', 'fix'],
|
'fix_line_endings' => ['fix/fix_line_endings.php', 'fix'],
|
||||||
'fix_permissions' => ['api/fix/fix_permissions.php', 'fix'],
|
'fix_permissions' => ['fix/fix_permissions.php', 'fix'],
|
||||||
'fix_tabs' => ['api/fix/fix_tabs.php', 'fix'],
|
'fix_tabs' => ['fix/fix_tabs.php', 'fix'],
|
||||||
'fix_trailing_spaces' => ['api/fix/fix_trailing_spaces.php', 'fix'],
|
'fix_trailing_spaces' => ['fix/fix_trailing_spaces.php', 'fix'],
|
||||||
// maintenance
|
// maintenance
|
||||||
'pin_action_shas' => ['api/maintenance/pin_action_shas.php', 'maintenance'],
|
'pin_action_shas' => ['maintenance/pin_action_shas.php', 'maintenance'],
|
||||||
'setup_labels' => ['api/maintenance/setup_labels.php', 'maintenance'],
|
'setup_labels' => ['maintenance/setup_labels.php', 'maintenance'],
|
||||||
'sync_dolibarr_readmes' => ['api/maintenance/sync_dolibarr_readmes.php', 'maintenance'],
|
'sync_dolibarr_readmes' => ['maintenance/sync_dolibarr_readmes.php', 'maintenance'],
|
||||||
'update_sha_hashes' => ['api/maintenance/update_sha_hashes.php', 'maintenance'],
|
'update_sha_hashes' => ['maintenance/update_sha_hashes.php', 'maintenance'],
|
||||||
'update_version_from_readme' => ['api/maintenance/update_version_from_readme.php', 'maintenance'],
|
'update_version_from_readme' => ['maintenance/update_version_from_readme.php', 'maintenance'],
|
||||||
// plugin
|
// plugin
|
||||||
'plugin_health_check' => ['api/plugin_health_check.php', 'plugin'],
|
'plugin_health_check' => ['plugin_health_check.php', 'plugin'],
|
||||||
'plugin_list' => ['api/plugin_list.php', 'plugin'],
|
'plugin_list' => ['plugin_list.php', 'plugin'],
|
||||||
'plugin_metrics' => ['api/plugin_metrics.php', 'plugin'],
|
'plugin_metrics' => ['plugin_metrics.php', 'plugin'],
|
||||||
'plugin_readiness' => ['api/plugin_readiness.php', 'plugin'],
|
'plugin_readiness' => ['plugin_readiness.php', 'plugin'],
|
||||||
'plugin_validate' => ['api/plugin_validate.php', 'plugin'],
|
'plugin_validate' => ['plugin_validate.php', 'plugin'],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/pin_action_shas.php
|
* PATH: /wrappers/pin_action_shas.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'pin_action_shas';
|
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';
|
const SCRIPT_CATEGORY = 'maintenance';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/plugin_health_check.php
|
* PATH: /wrappers/plugin_health_check.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'plugin_health_check';
|
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';
|
const SCRIPT_CATEGORY = 'plugin';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/plugin_list.php
|
* PATH: /wrappers/plugin_list.php
|
||||||
* VERSION: 04.06.00
|
* VERSION: 04.06.00
|
||||||
* BRIEF: PHP wrapper for api/plugin_list.php
|
* BRIEF: PHP wrapper for plugin_list.php
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'plugin_list';
|
const SCRIPT_NAME = 'plugin_list';
|
||||||
const SCRIPT_PATH = 'api/plugin_list.php';
|
const SCRIPT_PATH = 'plugin_list.php';
|
||||||
const SCRIPT_CATEGORY = 'plugin';
|
const SCRIPT_CATEGORY = 'plugin';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/plugin_metrics.php
|
* PATH: /wrappers/plugin_metrics.php
|
||||||
* VERSION: 04.06.00
|
* VERSION: 04.06.00
|
||||||
* BRIEF: PHP wrapper for api/plugin_metrics.php
|
* BRIEF: PHP wrapper for plugin_metrics.php
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'plugin_metrics';
|
const SCRIPT_NAME = 'plugin_metrics';
|
||||||
const SCRIPT_PATH = 'api/plugin_metrics.php';
|
const SCRIPT_PATH = 'plugin_metrics.php';
|
||||||
const SCRIPT_CATEGORY = 'plugin';
|
const SCRIPT_CATEGORY = 'plugin';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/plugin_readiness.php
|
* PATH: /wrappers/plugin_readiness.php
|
||||||
* VERSION: 04.06.00
|
* VERSION: 04.06.00
|
||||||
* BRIEF: PHP wrapper for api/plugin_readiness.php
|
* BRIEF: PHP wrapper for plugin_readiness.php
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'plugin_readiness';
|
const SCRIPT_NAME = 'plugin_readiness';
|
||||||
const SCRIPT_PATH = 'api/plugin_readiness.php';
|
const SCRIPT_PATH = 'plugin_readiness.php';
|
||||||
const SCRIPT_CATEGORY = 'plugin';
|
const SCRIPT_CATEGORY = 'plugin';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/plugin_validate.php
|
* PATH: /wrappers/plugin_validate.php
|
||||||
* VERSION: 04.06.00
|
* VERSION: 04.06.00
|
||||||
* BRIEF: PHP wrapper for api/plugin_validate.php
|
* BRIEF: PHP wrapper for plugin_validate.php
|
||||||
*/
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'plugin_validate';
|
const SCRIPT_NAME = 'plugin_validate';
|
||||||
const SCRIPT_PATH = 'api/plugin_validate.php';
|
const SCRIPT_PATH = 'plugin_validate.php';
|
||||||
const SCRIPT_CATEGORY = 'plugin';
|
const SCRIPT_CATEGORY = 'plugin';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/scan_drift.php
|
* PATH: /wrappers/scan_drift.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'scan_drift';
|
const SCRIPT_NAME = 'scan_drift';
|
||||||
const SCRIPT_PATH = 'api/validate/scan_drift.php';
|
const SCRIPT_PATH = 'validate/scan_drift.php';
|
||||||
const SCRIPT_CATEGORY = 'validate';
|
const SCRIPT_CATEGORY = 'validate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/setup_labels.php
|
* PATH: /wrappers/setup_labels.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'setup_labels';
|
const SCRIPT_NAME = 'setup_labels';
|
||||||
const SCRIPT_PATH = 'api/maintenance/setup_labels.php';
|
const SCRIPT_PATH = 'maintenance/setup_labels.php';
|
||||||
const SCRIPT_CATEGORY = 'maintenance';
|
const SCRIPT_CATEGORY = 'maintenance';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/sync_dolibarr_readmes.php
|
* PATH: /wrappers/sync_dolibarr_readmes.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'sync_dolibarr_readmes';
|
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';
|
const SCRIPT_CATEGORY = 'maintenance';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
||||||
* PATH: /wrappers/update_sha_hashes.php
|
* PATH: /wrappers/update_sha_hashes.php
|
||||||
* VERSION: 04.06.00
|
* 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);
|
declare(strict_types=1);
|
||||||
|
|
||||||
const SCRIPT_NAME = 'update_sha_hashes';
|
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';
|
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