From 89007ab9ba02971e5e216be935f00dfb4d295f04 Mon Sep 17 00:00:00 2001 From: Jonathan Miller <1+jmiller@noreply.git.mokoconsulting.tech> Date: Fri, 22 May 2026 02:39:17 +0000 Subject: [PATCH] feat(cli): updates_xml_sync.php replaces inline workflow sync (#39) --- .mokogitea/workflows/pre-release.yml | 23 +--- cli/archive_repo.php | 4 +- cli/badge_update.php | 4 +- cli/bulk_workflow_trigger.php | 4 +- cli/changelog_promote.php | 4 +- cli/client_inventory.php | 4 +- cli/create_project.php | 4 +- cli/create_repo.php | 6 +- cli/joomla_release.php | 4 +- cli/manifest_read.php | 4 +- cli/package_build.php | 4 +- cli/platform_detect.php | 4 +- cli/release.php | 4 +- cli/release_cascade.php | 4 +- cli/release_manage.php | 4 +- cli/release_notes.php | 4 +- cli/scaffold_client.php | 4 +- cli/sync_rulesets.php | 4 +- cli/updates_xml_build.php | 4 +- cli/updates_xml_sync.php | 169 +++++++++++++++++++++++++++ cli/version_bump.php | 4 +- cli/version_read.php | 4 +- cli/version_set_platform.php | 4 +- 23 files changed, 213 insertions(+), 65 deletions(-) create mode 100644 cli/updates_xml_sync.php diff --git a/.mokogitea/workflows/pre-release.yml b/.mokogitea/workflows/pre-release.yml index 623bb57..c872554 100644 --- a/.mokogitea/workflows/pre-release.yml +++ b/.mokogitea/workflows/pre-release.yml @@ -335,28 +335,7 @@ jobs: - name: "Sync updates.xml to all branches" if: steps.platform.outputs.platform == 'joomla' run: | - CURRENT_BRANCH="${{ github.ref_name }}" - TOKEN="${{ secrets.GA_TOKEN }}" - API="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" - VERSION="${{ steps.meta.outputs.version }}" - - # Sync updates.xml to main and dev via API (avoids git checkout conflicts) - for BRANCH in main dev; do - [ "$BRANCH" = "$CURRENT_BRANCH" ] && continue - - echo "Syncing updates.xml -> ${BRANCH}" - - FILE_SHA=$(curl -sf -H "Authorization: token ${TOKEN}" "${API}/contents/updates.xml?ref=${BRANCH}" | jq -r '.sha // empty' 2>/dev/null || true) - - if [ -z "$FILE_SHA" ]; then - echo " WARNING: could not get updates.xml SHA from ${BRANCH}" - continue - fi - - CONTENT=$(base64 -w0 updates.xml) - curl -sf -X PUT -H "Authorization: token ${TOKEN}" -H "Content-Type: application/json" "${API}/contents/updates.xml" -d "$(jq -n --arg content \"$CONTENT\" --arg sha \"$FILE_SHA\" --arg msg \"chore: sync updates.xml ${VERSION} from ${CURRENT_BRANCH} [skip ci]\" --arg branch \"$BRANCH\" '{content: $content, sha: $sha, message: $msg, branch: $branch}' - )" > /dev/null 2>&1 && echo " Synced to ${BRANCH}" || echo " WARNING: push to ${BRANCH} failed" - done + php /tmp/moko-platform-api/cli/updates_xml_sync.php --path . --current "${{ github.ref_name }}" --branches main,dev --version "${{ steps.meta.outputs.version }}" --token "${{ secrets.GA_TOKEN }}" --org "${GITEA_ORG}" --repo "${GITEA_REPO}" --gitea-url "${GITEA_URL}" - name: "Delete lesser pre-release channels (cascade)" continue-on-error: true diff --git a/cli/archive_repo.php b/cli/archive_repo.php index 376f6e9..d71fe33 100644 --- a/cli/archive_repo.php +++ b/cli/archive_repo.php @@ -7,8 +7,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/archive_repo.php * BRIEF: Gracefully retire a governed repository — archive, close issues/PRs, remove sync def diff --git a/cli/badge_update.php b/cli/badge_update.php index 87a1e8b..7470de5 100644 --- a/cli/badge_update.php +++ b/cli/badge_update.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/badge_update.php * BRIEF: Update [VERSION: XX.XX.XX] badges in all markdown files diff --git a/cli/bulk_workflow_trigger.php b/cli/bulk_workflow_trigger.php index 25b66be..2c2fa48 100644 --- a/cli/bulk_workflow_trigger.php +++ b/cli/bulk_workflow_trigger.php @@ -7,8 +7,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.Scripts.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/bulk_workflow_trigger.php * VERSION: 01.00.00 diff --git a/cli/changelog_promote.php b/cli/changelog_promote.php index 1419a15..c1c7fa2 100644 --- a/cli/changelog_promote.php +++ b/cli/changelog_promote.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/changelog_promote.php * BRIEF: Promote [Unreleased] section in CHANGELOG.md to a versioned entry diff --git a/cli/client_inventory.php b/cli/client_inventory.php index 0654464..0151aa7 100644 --- a/cli/client_inventory.php +++ b/cli/client_inventory.php @@ -7,8 +7,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.Scripts.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/client_inventory.php * VERSION: 01.00.00 diff --git a/cli/create_project.php b/cli/create_project.php index 75a5a69..15e4c19 100644 --- a/cli/create_project.php +++ b/cli/create_project.php @@ -7,8 +7,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/create_project.php * BRIEF: Create baseline GitHub Projects for repositories with standard fields and views diff --git a/cli/create_repo.php b/cli/create_repo.php index 1e3314f..16003b0 100644 --- a/cli/create_repo.php +++ b/cli/create_repo.php @@ -7,8 +7,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/create_repo.php * BRIEF: Scaffold a new governed repository with full MokoStandards baseline @@ -158,7 +158,7 @@ SPDX-License-Identifier: GPL-3.0-or-later # FILE INFORMATION DEFGROUP: {$name} -INGROUP: MokoStandards +INGROUP: moko-platform REPO: {$repoUrl} PATH: /README.md BRIEF: {$description} diff --git a/cli/joomla_release.php b/cli/joomla_release.php index d27f917..7429bf8 100644 --- a/cli/joomla_release.php +++ b/cli/joomla_release.php @@ -7,8 +7,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/joomla_release.php * BRIEF: Joomla release pipeline — build ZIP+tar.gz, upload to GitHub Release, update updates.xml diff --git a/cli/manifest_read.php b/cli/manifest_read.php index d5837f9..5f8196e 100644 --- a/cli/manifest_read.php +++ b/cli/manifest_read.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/manifest_read.php * VERSION: 04.09.00 diff --git a/cli/package_build.php b/cli/package_build.php index 5b3f519..1d18182 100644 --- a/cli/package_build.php +++ b/cli/package_build.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/package_build.php * BRIEF: Build ZIP and tar.gz install packages for Joomla/Dolibarr/generic projects diff --git a/cli/platform_detect.php b/cli/platform_detect.php index c295acc..50a08f7 100644 --- a/cli/platform_detect.php +++ b/cli/platform_detect.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/platform_detect.php * BRIEF: Detect platform from .mokostandards file — outputs platform string diff --git a/cli/release.php b/cli/release.php index 63bc23d..c725032 100644 --- a/cli/release.php +++ b/cli/release.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/release.php * BRIEF: Automate the MokoStandards version branch release flow diff --git a/cli/release_cascade.php b/cli/release_cascade.php index 5f7670a..ad71d26 100644 --- a/cli/release_cascade.php +++ b/cli/release_cascade.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/release_cascade.php * BRIEF: Delete lesser pre-release channels from Gitea when promoting stability diff --git a/cli/release_manage.php b/cli/release_manage.php index 1d9eb00..32789e0 100644 --- a/cli/release_manage.php +++ b/cli/release_manage.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/release_manage.php * BRIEF: Create/update Gitea releases, upload assets, update release body diff --git a/cli/release_notes.php b/cli/release_notes.php index be91fe2..643000d 100644 --- a/cli/release_notes.php +++ b/cli/release_notes.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/release_notes.php * BRIEF: Extract release notes from CHANGELOG.md for a given version diff --git a/cli/scaffold_client.php b/cli/scaffold_client.php index 56c4081..d5a60e3 100644 --- a/cli/scaffold_client.php +++ b/cli/scaffold_client.php @@ -7,8 +7,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.Scripts.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/scaffold_client.php * VERSION: 01.00.00 diff --git a/cli/sync_rulesets.php b/cli/sync_rulesets.php index 807be66..8b2361e 100644 --- a/cli/sync_rulesets.php +++ b/cli/sync_rulesets.php @@ -7,8 +7,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/sync_rulesets.php * BRIEF: Apply branch protection rules to all repos via platform adapter diff --git a/cli/updates_xml_build.php b/cli/updates_xml_build.php index 8217a6e..6122167 100644 --- a/cli/updates_xml_build.php +++ b/cli/updates_xml_build.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/updates_xml_build.php * BRIEF: Generate Joomla updates.xml from extension manifest metadata diff --git a/cli/updates_xml_sync.php b/cli/updates_xml_sync.php new file mode 100644 index 0000000..46efbc1 --- /dev/null +++ b/cli/updates_xml_sync.php @@ -0,0 +1,169 @@ +#!/usr/bin/env php + + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * FILE INFORMATION + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform + * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform + * PATH: /cli/updates_xml_sync.php + * VERSION: 05.00.01 + * BRIEF: Sync updates.xml to target branches via Gitea API + * NOTE: Called by pre-release and auto-release workflows after updates.xml + * is modified on the current branch. Pushes the file to other branches + * without requiring a git checkout (avoids merge conflicts). + * + * Usage: + * php updates_xml_sync.php --path /repo --branches main,dev --current dev + * php updates_xml_sync.php --path /repo --branches main --current dev --version 02.01.27 + * + * Options: + * --path Repository root containing updates.xml (default: .) + * --branches Comma-separated target branches to sync to (default: main,dev) + * --current Current branch to skip (required) + * --version Version string for commit message (optional) + * --token Gitea API token (default: env GA_TOKEN) + * --gitea-url Gitea instance URL (default: env GITEA_URL or https://git.mokoconsulting.tech) + * --org Organization (default: env GITEA_ORG) + * --repo Repository name (default: env GITEA_REPO) + */ + +declare(strict_types=1); + +// ── Argument parsing ──────────────────────────────────────────────────── +$path = '.'; +$branches = 'main,dev'; +$current = ''; +$version = ''; +$token = getenv('GA_TOKEN') ?: ''; +$giteaUrl = getenv('GITEA_URL') ?: 'https://git.mokoconsulting.tech'; +$org = getenv('GITEA_ORG') ?: ''; +$repo = getenv('GITEA_REPO') ?: ''; + +foreach ($argv as $i => $arg) { + if ($arg === '--path' && isset($argv[$i + 1])) $path = $argv[$i + 1]; + if ($arg === '--branches' && isset($argv[$i + 1])) $branches = $argv[$i + 1]; + if ($arg === '--current' && isset($argv[$i + 1])) $current = $argv[$i + 1]; + if ($arg === '--version' && isset($argv[$i + 1])) $version = $argv[$i + 1]; + if ($arg === '--token' && isset($argv[$i + 1])) $token = $argv[$i + 1]; + if ($arg === '--gitea-url' && isset($argv[$i + 1])) $giteaUrl = $argv[$i + 1]; + if ($arg === '--org' && isset($argv[$i + 1])) $org = $argv[$i + 1]; + if ($arg === '--repo' && isset($argv[$i + 1])) $repo = $argv[$i + 1]; +} + +if ($current === '') { + fwrite(STDERR, "Error: --current is required\n"); + exit(1); +} + +if ($token === '') { + fwrite(STDERR, "Error: --token or GA_TOKEN env is required\n"); + exit(1); +} + +if ($org === '' || $repo === '') { + fwrite(STDERR, "Error: --org and --repo (or GITEA_ORG/GITEA_REPO env) are required\n"); + exit(1); +} + +$updatesFile = rtrim($path, '/') . '/updates.xml'; +if (!file_exists($updatesFile)) { + fwrite(STDERR, "No updates.xml found at {$updatesFile}\n"); + exit(0); +} + +$content = file_get_contents($updatesFile); +$encoded = base64_encode($content); +$giteaUrl = rtrim($giteaUrl, '/'); +$apiBase = "{$giteaUrl}/api/v1/repos/{$org}/{$repo}"; +$vLabel = $version !== '' ? " {$version}" : ''; + +$targets = array_filter( + array_map('trim', explode(',', $branches)), + fn($b) => $b !== '' && $b !== $current +); + +if (empty($targets)) { + fwrite(STDERR, "No target branches to sync to (current: {$current})\n"); + exit(0); +} + +$synced = 0; +$failed = 0; + +foreach ($targets as $branch) { + fwrite(STDERR, "Syncing updates.xml -> {$branch}...\n"); + + $sha = getFileSha($apiBase, $token, $branch); + + if ($sha === null) { + fwrite(STDERR, " WARNING: could not get SHA from {$branch}\n"); + $failed++; + continue; + } + + $ok = putFile($apiBase, $token, $branch, $encoded, $sha, + "chore: sync updates.xml{$vLabel} from {$current} [skip ci]"); + + if ($ok) { + fwrite(STDERR, " Synced to {$branch}\n"); + $synced++; + } else { + fwrite(STDERR, " WARNING: push to {$branch} failed\n"); + $failed++; + } +} + +fwrite(STDERR, "Done: {$synced} synced, {$failed} failed\n"); +exit($failed > 0 ? 1 : 0); + +// ═══════════════════════════════════════════════════════════════════════ + +function getFileSha(string $apiBase, string $token, string $branch): ?string +{ + $resp = apiCall('GET', "{$apiBase}/contents/updates.xml?ref={$branch}", $token); + return $resp['sha'] ?? null; +} + +function putFile(string $apiBase, string $token, string $branch, + string $encoded, string $sha, string $msg): bool +{ + $resp = apiCall('PUT', "{$apiBase}/contents/updates.xml", $token, [ + 'content' => $encoded, + 'sha' => $sha, + 'message' => $msg, + 'branch' => $branch, + ]); + return $resp !== null; +} + +function apiCall(string $method, string $url, string $token, ?array $data = null): ?array +{ + $headers = [ + "Authorization: token {$token}", + 'Content-Type: application/json', + 'Accept: application/json', + ]; + + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_TIMEOUT, 30); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + + if ($data !== null) { + curl_setopt($ch, CURLOPT_POSTFIELDS, + json_encode($data, JSON_UNESCAPED_SLASHES)); + } + + $body = curl_exec($ch); + $code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + return ($code >= 200 && $code < 300) + ? (json_decode($body, true) ?: []) + : null; +} diff --git a/cli/version_bump.php b/cli/version_bump.php index d330ff7..a7d155f 100644 --- a/cli/version_bump.php +++ b/cli/version_bump.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/version_bump.php * BRIEF: Auto-increment patch version in README.md — outputs old → new diff --git a/cli/version_read.php b/cli/version_read.php index 13aa29f..0c0063b 100644 --- a/cli/version_read.php +++ b/cli/version_read.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/version_read.php * BRIEF: Read VERSION from README.md — outputs just the version string diff --git a/cli/version_set_platform.php b/cli/version_set_platform.php index 852a669..8e9a4c7 100644 --- a/cli/version_set_platform.php +++ b/cli/version_set_platform.php @@ -5,8 +5,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION - * DEFGROUP: MokoStandards.CLI - * INGROUP: MokoStandards + * DEFGROUP: moko-platform.CLI + * INGROUP: moko-platform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /cli/version_set_platform.php * BRIEF: Set version in platform-specific files (Dolibarr $this->version, Joomla ) -- 2.52.0