From 789155fdd84190bcba75d1411e9c1e3c717d8933 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Thu, 28 May 2026 23:02:11 -0500 Subject: [PATCH 1/9] fix(lib): pass empty array to request() when delete body is null Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/Enterprise/ApiClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Enterprise/ApiClient.php b/lib/Enterprise/ApiClient.php index eb6a369..af55001 100644 --- a/lib/Enterprise/ApiClient.php +++ b/lib/Enterprise/ApiClient.php @@ -263,7 +263,7 @@ class ApiClient */ public function delete(string $endpoint, ?array $body = null): array { - return $this->request('DELETE', $endpoint, $body); + return $this->request('DELETE', $endpoint, $body ?? []); } /** -- 2.52.0 From 169473e9d8174aa049b064add68201790868d565 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Fri, 29 May 2026 04:02:23 +0000 Subject: [PATCH 2/9] chore(version): auto-bump patch 09.05.01-dev [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 30f610e..5b9264d 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ DEFGROUP: MokoStandards.Root INGROUP: MokoStandards REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform PATH: /README.md -VERSION: 09.05.00 +VERSION: 09.05.01 BRIEF: Project overview and documentation --> -- 2.52.0 From 09d4e531ee503bc301d82fb67cf224318256b4b7 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Thu, 28 May 2026 23:07:18 -0500 Subject: [PATCH 3/9] fix(cli): use correct Gitea API path for deleting release assets Gitea requires /releases/{id}/assets/{id}, not /releases/assets/{id}. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- cli/joomla_release.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/joomla_release.php b/cli/joomla_release.php index d57905e..4845f0a 100644 --- a/cli/joomla_release.php +++ b/cli/joomla_release.php @@ -392,7 +392,7 @@ class JoomlaRelease extends CliFramework foreach ($release['assets'] ?? [] as $asset) { if ($asset['name'] === $fileName) { - $this->api->delete("/repos/{$repo}/releases/assets/{$asset['id']}"); + $this->api->delete("/repos/{$repo}/releases/{$release['id']}/assets/{$asset['id']}"); } } -- 2.52.0 From c5cb67f54251351cc59fe23c0de8d2ffc830ecae Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Fri, 29 May 2026 04:07:42 +0000 Subject: [PATCH 4/9] chore(version): auto-bump patch 09.05.02-dev [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5b9264d..2f8aa56 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ DEFGROUP: MokoStandards.Root INGROUP: MokoStandards REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform PATH: /README.md -VERSION: 09.05.01 +VERSION: 09.05.02 BRIEF: Project overview and documentation --> -- 2.52.0 From c76b9fd07bca8d591ee9c882dbc37596e8372b3b Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Fri, 29 May 2026 04:10:58 -0500 Subject: [PATCH 5/9] fix(cli): change pipe delimiters to hash in version regexes Pipe | as regex delimiter conflicts with alternation inside (?:dev|alpha|beta|rc). Caused preg_match warnings and failed version reads. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- cli/version_bump.php | 8 ++++---- cli/version_check.php | 2 +- cli/version_read.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cli/version_bump.php b/cli/version_bump.php index ece23de..33f5775 100644 --- a/cli/version_bump.php +++ b/cli/version_bump.php @@ -31,7 +31,7 @@ $mokoManifest = "{$root}/.mokogitea/manifest.xml"; $mokoContent = ''; if (file_exists($mokoManifest)) { $mokoContent = file_get_contents($mokoManifest); - if (preg_match('|(\d{2}\.\d{2}\.\d{2})(?:-((?:(?:dev|alpha|beta|rc)-?)+))?|', $mokoContent, $m)) { + if (preg_match('#(\d{2}\.\d{2}\.\d{2})(?:-((?:(?:dev|alpha|beta|rc)-?)+))?#', $mokoContent, $m)) { $mokoVersion = $m[1]; $mokoSuffix = isset($m[2]) ? $m[2] : ''; } @@ -64,7 +64,7 @@ foreach ($manifestFiles as $xmlFile) { if (strpos($xmlContent, '') === false) { continue; } - if (preg_match('|(\d{2}\.\d{2}\.\d{2})((?:-(?:dev|alpha|beta|rc))+)?|', $xmlContent, $xm)) { + if (preg_match('#(\d{2}\.\d{2}\.\d{2})((?:-(?:dev|alpha|beta|rc))+)?#', $xmlContent, $xm)) { $candidate = $xm[1]; if ($manifestVersion === null || version_compare($candidate, $manifestVersion, '>')) { $manifestVersion = $candidate; @@ -120,7 +120,7 @@ $newFull = $new; // -- Update .mokogitea/manifest.xml (canonical — preserves suffix) -- if (file_exists($mokoManifest) && !empty($mokoContent)) { $updated = preg_replace( - '|\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?|', + '#\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?#', "{$newFull}", $mokoContent, 1 @@ -160,7 +160,7 @@ foreach ($xmlPatterns as $pattern) { continue; } $newContent = preg_replace( - '|\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?|', + '#\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?#', "{$newFull}", $content ); diff --git a/cli/version_check.php b/cli/version_check.php index ff4d538..0c49c64 100644 --- a/cli/version_check.php +++ b/cli/version_check.php @@ -59,7 +59,7 @@ foreach ($xmlGlobs as $glob) { $xmlContent = file_get_contents($file); if (strpos($xmlContent, '(\d{2}\.\d{2}\.\d{2})(?:(?:-(?:dev|alpha|beta|rc))+)?|', $xmlContent, $xm)) { + if (preg_match('#(\d{2}\.\d{2}\.\d{2})(?:(?:-(?:dev|alpha|beta|rc))+)?#', $xmlContent, $xm)) { $relPath = str_replace($root . '/', '', $file); $relPath = str_replace($root . '\\', '', $relPath); $versions[$relPath] = $xm[1]; diff --git a/cli/version_read.php b/cli/version_read.php index 5c76856..3324b36 100644 --- a/cli/version_read.php +++ b/cli/version_read.php @@ -66,7 +66,7 @@ foreach ($manifestFiles as $xmlFile) { if (strpos($xmlContent, '') === false) { continue; } - if (preg_match('|(\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?)|', $xmlContent, $xm)) { + if (preg_match('#(\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?)#', $xmlContent, $xm)) { $candidate = $xm[1]; $candidateBase = preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $candidate); $currentBase = $manifestVersion ? preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $manifestVersion) : null; @@ -119,7 +119,7 @@ if ($version === null) { // -- Backfill: if manifest.xml exists but lacks , insert it -- if (file_exists($mokoManifest)) { $content = file_get_contents($mokoManifest); - if (!preg_match('|\d{2}\.\d{2}\.\d{2}((?:-(?:dev|alpha|beta|rc))+)?|', $content)) { + if (!preg_match('#\d{2}\.\d{2}\.\d{2}((?:-(?:dev|alpha|beta|rc))+)?#', $content)) { if (strpos($content, ' Date: Fri, 29 May 2026 09:11:28 +0000 Subject: [PATCH 6/9] chore(version): auto-bump patch 09.05.03-dev [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2f8aa56..726803c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ DEFGROUP: MokoStandards.Root INGROUP: MokoStandards REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform PATH: /README.md -VERSION: 09.05.02 +VERSION: 09.05.03 BRIEF: Project overview and documentation --> -- 2.52.0 From dea9bb3577c8721fad21702295846e41411184cd Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Fri, 29 May 2026 04:26:36 -0500 Subject: [PATCH 7/9] feat(workflows): multi-branch stability suffixes and remove redundant sed - auto-bump: support dev, alpha, beta, rc, feature/* branches - auto-bump: map branch to stability suffix via CLI tools - auto-release: remove redundant sed strips (CLI handles internally) - Feature branches inherit -dev stability Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- .mokogitea/workflows/auto-bump.yml | 26 ++++++++++++++++++++++---- .mokogitea/workflows/auto-release.yml | 8 +++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/.mokogitea/workflows/auto-bump.yml b/.mokogitea/workflows/auto-bump.yml index dc76039..fb99033 100644 --- a/.mokogitea/workflows/auto-bump.yml +++ b/.mokogitea/workflows/auto-bump.yml @@ -16,6 +16,10 @@ on: push: branches: - dev + - alpha + - beta + - rc + - 'feature/**' env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true @@ -57,17 +61,31 @@ jobs: - name: Bump version run: | + BRANCH="${GITHUB_REF_NAME}" + + # Map branch name to stability suffix + # Feature branches (feature/*) use dev stability + case "$BRANCH" in + dev) STABILITY="dev" ;; + alpha) STABILITY="alpha" ;; + beta) STABILITY="beta" ;; + rc) STABILITY="rc" ;; + feature/*) STABILITY="dev" ;; + *) STABILITY="dev" ;; + esac + BUMP=$(php ${MOKO_CLI}/version_bump.php --path . 2>&1) || true echo "$BUMP" VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null) || true [ -z "$VERSION" ] && { echo "No version found — skipping"; exit 0; } - # Propagate to platform manifests with -dev suffix + # version_set_platform strips existing suffixes internally + # Propagate to platform manifests with stability suffix php ${MOKO_CLI}/version_set_platform.php \ - --path . --version "$VERSION" --branch dev --stability dev 2>/dev/null || true + --path . --version "$VERSION" --branch "$BRANCH" --stability "$STABILITY" 2>/dev/null || true php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true - VERSION="${VERSION}-dev" + VERSION="${VERSION}-${STABILITY}" # Commit if anything changed if git diff --quiet && git diff --cached --quiet; then @@ -81,5 +99,5 @@ jobs: git add -A git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \ --author="gitea-actions[bot] " - git push origin dev + git push origin "$BRANCH" echo "Bumped to ${VERSION}" >> $GITHUB_STEP_SUMMARY diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml index 72ce95a..871ecde 100644 --- a/.mokogitea/workflows/auto-release.yml +++ b/.mokogitea/workflows/auto-release.yml @@ -165,9 +165,8 @@ jobs: echo "skip=true" >> "$GITHUB_OUTPUT" exit 0 fi - # Strip any pre-release suffix merged from dev (e.g. 01.02.20-dev → 01.02.20) - VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//') - MAJOR=$(echo "$VERSION" | cut -d. -f1) + # version_set_platform strips suffixes internally when --stability stable + MAJOR=$(echo "$VERSION" | cut -d. -f1 | sed 's/-.*//') echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "release_tag=stable" >> "$GITHUB_OUTPUT" echo "skip=false" >> "$GITHUB_OUTPUT" @@ -201,8 +200,7 @@ jobs: MOKO_API="/tmp/moko-platform-api/cli" php ${MOKO_API}/version_bump.php --path . --minor 2>&1 || true VERSION=$(php ${MOKO_API}/version_read.php --path .) - # Strip any pre-release suffix — stable releases have no suffix - VERSION=$(echo "$VERSION" | sed 's/-\(dev\|alpha\|beta\|rc\)$//') + # version_set_platform handles suffix stripping — just pass clean base version echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Bumped to: ${VERSION}" -- 2.52.0 From b76b3d53370a4f02b887aadd63e34e266f25ae76 Mon Sep 17 00:00:00 2001 From: "gitea-actions[bot]" Date: Fri, 29 May 2026 09:27:10 +0000 Subject: [PATCH 8/9] chore(version): auto-bump patch 09.05.04-dev [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 726803c..c559669 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ DEFGROUP: MokoStandards.Root INGROUP: MokoStandards REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform PATH: /README.md -VERSION: 09.05.03 +VERSION: 09.05.04 BRIEF: Project overview and documentation --> -- 2.52.0 From db06dc31cc5cb12ae9ca8d0987d16bb30f23a1b8 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Fri, 29 May 2026 04:50:22 -0500 Subject: [PATCH 9/9] =?UTF-8?q?feat(cli):=20version=20pipeline=20overhaul?= =?UTF-8?q?=20=E2=80=94=20multi-branch=20stability,=20generic=20file=20sca?= =?UTF-8?q?nning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Phase 1: version_bump.php — scan CHANGELOG.md and all text files for VERSION: patterns Phase 2: version_check.php — check manifest.xml, package.json, pyproject.toml, CHANGELOG Phase 3: version_auto_bump.php — new CLI tool replacing inline workflow bash Phase 4: auto-release.yml — replace python3 calls with PHP Phase 5: auto-bump.yml — slim to single CLI call, support all branch types Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- .mokogitea/workflows/auto-bump.yml | 44 +-------- .mokogitea/workflows/auto-release.yml | 4 +- cli/version_auto_bump.php | 137 ++++++++++++++++++++++++++ cli/version_bump.php | 75 ++++++++++++++ cli/version_check.php | 100 ++++++++++++++++++- 5 files changed, 316 insertions(+), 44 deletions(-) create mode 100644 cli/version_auto_bump.php diff --git a/.mokogitea/workflows/auto-bump.yml b/.mokogitea/workflows/auto-bump.yml index fb99033..8673649 100644 --- a/.mokogitea/workflows/auto-bump.yml +++ b/.mokogitea/workflows/auto-bump.yml @@ -61,43 +61,7 @@ jobs: - name: Bump version run: | - BRANCH="${GITHUB_REF_NAME}" - - # Map branch name to stability suffix - # Feature branches (feature/*) use dev stability - case "$BRANCH" in - dev) STABILITY="dev" ;; - alpha) STABILITY="alpha" ;; - beta) STABILITY="beta" ;; - rc) STABILITY="rc" ;; - feature/*) STABILITY="dev" ;; - *) STABILITY="dev" ;; - esac - - BUMP=$(php ${MOKO_CLI}/version_bump.php --path . 2>&1) || true - echo "$BUMP" - - VERSION=$(php ${MOKO_CLI}/version_read.php --path . 2>/dev/null) || true - [ -z "$VERSION" ] && { echo "No version found — skipping"; exit 0; } - - # version_set_platform strips existing suffixes internally - # Propagate to platform manifests with stability suffix - php ${MOKO_CLI}/version_set_platform.php \ - --path . --version "$VERSION" --branch "$BRANCH" --stability "$STABILITY" 2>/dev/null || true - php ${MOKO_CLI}/version_check.php --path . --fix 2>/dev/null || true - VERSION="${VERSION}-${STABILITY}" - - # Commit if anything changed - if git diff --quiet && git diff --cached --quiet; then - echo "No version changes to commit" - exit 0 - fi - - git config --local user.email "gitea-actions[bot]@mokoconsulting.tech" - git config --local user.name "gitea-actions[bot]" - git remote set-url origin "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git" - git add -A - git commit -m "chore(version): auto-bump patch ${VERSION} [skip ci]" \ - --author="gitea-actions[bot] " - git push origin "$BRANCH" - echo "Bumped to ${VERSION}" >> $GITHUB_STEP_SUMMARY + php ${MOKO_CLI}/version_auto_bump.php \ + --path . --branch "${GITHUB_REF_NAME}" \ + --token "${{ secrets.MOKOGITEA_TOKEN }}" \ + --repo-url "https://x-access-token:${{ secrets.MOKOGITEA_TOKEN }}@git.mokoconsulting.tech/${{ github.repository }}.git" diff --git a/.mokogitea/workflows/auto-release.yml b/.mokogitea/workflows/auto-release.yml index 871ecde..618cb76 100644 --- a/.mokogitea/workflows/auto-release.yml +++ b/.mokogitea/workflows/auto-release.yml @@ -180,7 +180,7 @@ jobs: API_BASE="${GITEA_URL}/api/v1/repos/${GITEA_ORG}/${GITEA_REPO}" RC_JSON=$(curl -sf -H "Authorization: token ${{ secrets.MOKOGITEA_TOKEN }}" \ "${API_BASE}/releases/tags/release-candidate" 2>/dev/null || echo "{}") - RC_ID=$(echo "$RC_JSON" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null || true) + RC_ID=$(echo "$RC_JSON" | php -r "\$d=json_decode(file_get_contents('php://stdin'),true); echo \$d['id'] ?? '';" 2>/dev/null || true) if [ -n "$RC_ID" ] && [ "$RC_ID" != "None" ] && [ "$RC_ID" != "" ]; then echo "promote=true" >> "$GITHUB_OUTPUT" @@ -374,7 +374,7 @@ jobs: API="${GITEA_URL}/api/v1/repos/${{ github.repository }}" curl -sf -H "Authorization: token ${GITEA_TOKEN}" \ "${API}/contents/updates.xml?ref=main" 2>/dev/null | \ - python3 -c "import sys,json,base64; print(base64.b64decode(json.load(sys.stdin)['content']).decode())" \ + php -r "\$d=json_decode(file_get_contents('php://stdin'),true); echo base64_decode(\$d['content'] ?? '');" \ > updates.xml 2>/dev/null || true SHA_FLAG="" diff --git a/cli/version_auto_bump.php b/cli/version_auto_bump.php new file mode 100644 index 0000000..ecb4450 --- /dev/null +++ b/cli/version_auto_bump.php @@ -0,0 +1,137 @@ +#!/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/version_auto_bump.php + * VERSION: 01.00.00 + * BRIEF: Auto patch-bump, set stability suffix, and commit — single CLI replacing inline workflow bash + * + * Usage: + * php version_auto_bump.php --path . --branch dev + * php version_auto_bump.php --path . --branch feature/my-feature --token TOKEN --repo-url URL + * php version_auto_bump.php --path . --branch alpha --dry-run + */ + +declare(strict_types=1); + +$path = '.'; +$branch = null; +$token = ''; +$repoUrl = ''; +$dryRun = false; + +foreach ($argv as $i => $arg) { + if ($arg === '--path' && isset($argv[$i + 1])) $path = $argv[$i + 1]; + if ($arg === '--branch' && isset($argv[$i + 1])) $branch = $argv[$i + 1]; + if ($arg === '--token' && isset($argv[$i + 1])) $token = $argv[$i + 1]; + if ($arg === '--repo-url' && isset($argv[$i + 1])) $repoUrl = $argv[$i + 1]; + if ($arg === '--dry-run') $dryRun = true; +} + +// Auto-detect branch from git or CI env +if ($branch === null) { + $branch = getenv('GITHUB_REF_NAME') ?: trim((string) @shell_exec('git rev-parse --abbrev-ref HEAD 2>/dev/null')); + if (empty($branch) || $branch === 'HEAD') { + fwrite(STDERR, "Cannot detect branch — pass --branch\n"); + exit(1); + } +} + +// Map branch to stability suffix +$stabilityMap = [ + 'dev' => 'dev', + 'alpha' => 'alpha', + 'beta' => 'beta', + 'rc' => 'rc', +]; + +if (array_key_exists($branch, $stabilityMap)) { + $stability = $stabilityMap[$branch]; +} elseif (str_starts_with($branch, 'feature/')) { + $stability = 'dev'; +} else { + $stability = 'dev'; +} + +$cli = __DIR__; +$php = PHP_BINARY; + +// Step 1: Patch bump +$bumpOutput = []; +exec("{$php} {$cli}/version_bump.php --path " . escapeshellarg($path) . " 2>&1", $bumpOutput, $bumpRc); +foreach ($bumpOutput as $line) { + echo "{$line}\n"; +} + +// Step 2: Read version +$versionOutput = []; +exec("{$php} {$cli}/version_read.php --path " . escapeshellarg($path) . " 2>&1", $versionOutput, $versionRc); +$version = trim($versionOutput[0] ?? ''); + +if (empty($version)) { + echo "No version found — skipping\n"; + exit(0); +} + +echo "Version: {$version} | Branch: {$branch} | Stability: {$stability}\n"; + +// Step 3: Set platform version with stability suffix +exec("{$php} {$cli}/version_set_platform.php --path " . escapeshellarg($path) + . " --version " . escapeshellarg($version) + . " --branch " . escapeshellarg($branch) + . " --stability " . escapeshellarg($stability) . " 2>&1", $setPlatOutput); +foreach ($setPlatOutput as $line) { + echo "{$line}\n"; +} + +// Step 4: Version consistency check and fix +exec("{$php} {$cli}/version_check.php --path " . escapeshellarg($path) . " --fix 2>&1", $checkOutput); + +// Re-read version (now includes suffix from version_set_platform) +$suffixMap = [ + 'dev' => '-dev', + 'alpha' => '-alpha', + 'beta' => '-beta', + 'rc' => '-rc', +]; +$displayVersion = preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $version) . ($suffixMap[$stability] ?? ''); + +if ($dryRun) { + echo "[DRY-RUN] Would commit and push {$displayVersion} to {$branch}\n"; + exit(0); +} + +// Step 5: Git commit and push +$root = realpath($path) ?: $path; + +// Check if anything changed +$diffStatus = trim((string) @shell_exec("cd " . escapeshellarg($root) . " && git diff --quiet && git diff --cached --quiet 2>&1 && echo clean || echo dirty")); +if ($diffStatus === 'clean') { + echo "No version changes to commit\n"; + exit(0); +} + +// Configure git +@shell_exec("cd " . escapeshellarg($root) . " && git config --local user.email \"gitea-actions[bot]@mokoconsulting.tech\""); +@shell_exec("cd " . escapeshellarg($root) . " && git config --local user.name \"gitea-actions[bot]\""); + +if (!empty($repoUrl)) { + @shell_exec("cd " . escapeshellarg($root) . " && git remote set-url origin " . escapeshellarg($repoUrl)); +} + +@shell_exec("cd " . escapeshellarg($root) . " && git add -A"); +$commitMsg = "chore(version): auto-bump patch {$displayVersion} [skip ci]"; +@shell_exec("cd " . escapeshellarg($root) . " && git commit -m " . escapeshellarg($commitMsg) + . " --author=\"gitea-actions[bot] \""); + +$pushResult = @shell_exec("cd " . escapeshellarg($root) . " && git push origin " . escapeshellarg($branch) . " 2>&1"); +echo $pushResult ?? ''; + +echo "Bumped to {$displayVersion}\n"; +exit(0); diff --git a/cli/version_bump.php b/cli/version_bump.php index 33f5775..afe3713 100644 --- a/cli/version_bump.php +++ b/cli/version_bump.php @@ -205,5 +205,80 @@ if (file_exists($pyprojectFile)) { } } +// -- Update CHANGELOG.md -- +$changelogFile = "{$root}/CHANGELOG.md"; +if (file_exists($changelogFile)) { + $clContent = file_get_contents($changelogFile); + $updatedCl = preg_replace( + '/(VERSION:\s*)\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?/m', + '${1}' . $newFull, + $clContent + ); + if ($updatedCl !== null && $updatedCl !== $clContent) { + file_put_contents($changelogFile, $updatedCl); + fwrite(STDERR, "Updated CHANGELOG.md\n"); + } +} + +// -- Generic VERSION: pattern scan across all text files -- +$scanExtensions = ['php', 'yml', 'yaml', 'md', 'txt', 'xml', 'sh', 'toml', 'ini', 'css', 'js']; +$excludeDirs = ['.git', 'vendor', 'node_modules', 'build', 'dist', '.claude']; +$versionPattern = '/(VERSION:\s*)\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?/m'; + +$directory = new RecursiveDirectoryIterator($root, RecursiveDirectoryIterator::SKIP_DOTS); +$filter = new RecursiveCallbackFilterIterator($directory, function ($current, $key, $iterator) use ($excludeDirs) { + if ($current->isDir() && in_array($current->getFilename(), $excludeDirs, true)) { + return false; + } + return true; +}); +$iterator = new RecursiveIteratorIterator($filter); + +$genericUpdated = []; +foreach ($iterator as $fileInfo) { + if ($fileInfo->isDir()) { + continue; + } + + $ext = strtolower($fileInfo->getExtension()); + if (!in_array($ext, $scanExtensions, true)) { + continue; + } + + $filePath = $fileInfo->getPathname(); + + // Skip files already handled above + $relPath = str_replace([$root . '/', $root . '\\'], '', $filePath); + if (in_array($relPath, ['README.md', 'CHANGELOG.md', 'package.json', 'pyproject.toml'], true)) { + continue; + } + if (in_array($relPath, $updatedFiles ?? [], true)) { + continue; + } + if (strpos($relPath, '.mokogitea/manifest.xml') !== false) { + continue; + } + + $content = @file_get_contents($filePath); + if ($content === false) { + continue; + } + + // Skip synced files — they have their own version managed by their source repo + if (preg_match('/^#\s*REPO:\s*https?:\/\//m', $content)) { + continue; + } + + $updated = preg_replace($versionPattern, '${1}' . $newFull, $content); + if ($updated !== null && $updated !== $content) { + file_put_contents($filePath, $updated); + $genericUpdated[] = $relPath; + } +} + +if (!empty($genericUpdated)) { + fwrite(STDERR, "Updated VERSION: in " . count($genericUpdated) . " file(s): " . implode(', ', $genericUpdated) . "\n"); +} + echo "{$old} -> {$newFull}\n"; exit(0); diff --git a/cli/version_check.php b/cli/version_check.php index 0c49c64..1cc3e01 100644 --- a/cli/version_check.php +++ b/cli/version_check.php @@ -34,6 +34,19 @@ $root = realpath($path) ?: $path; $errors = 0; $versions = []; +// ── Read .mokogitea/manifest.xml (canonical) ──────────────────────────────── +$mokoManifest = "{$root}/.mokogitea/manifest.xml"; +if (file_exists($mokoManifest)) { + $xml = @simplexml_load_file($mokoManifest); + if ($xml !== false) { + $v = (string)($xml->identity->version ?? ''); + $base = preg_replace('/(-(dev|alpha|beta|rc))+$/', '', $v); + if (preg_match('/^\d{2}\.\d{2}\.\d{2}$/', $base)) { + $versions['.mokogitea/manifest.xml'] = $base; + } + } +} + // ── Read README.md version ─────────────────────────────────────────────────── $readme = "{$root}/README.md"; if (file_exists($readme)) { @@ -43,6 +56,33 @@ if (file_exists($readme)) { } } +// ── Read CHANGELOG.md version ─────────────────────────────────────────────── +$changelog = "{$root}/CHANGELOG.md"; +if (file_exists($changelog)) { + $content = file_get_contents($changelog); + if (preg_match('/VERSION:\s*(\d{2}\.\d{2}\.\d{2})/m', $content, $m)) { + $versions['CHANGELOG.md'] = $m[1]; + } +} + +// ── Read package.json version ─────────────────────────────────────────────── +$packageJson = "{$root}/package.json"; +if (file_exists($packageJson)) { + $pkg = json_decode(file_get_contents($packageJson), true); + if (isset($pkg['version']) && preg_match('/^\d{2}\.\d{2}\.\d{2}$/', $pkg['version'])) { + $versions['package.json'] = $pkg['version']; + } +} + +// ── Read pyproject.toml version ───────────────────────────────────────────── +$pyproject = "{$root}/pyproject.toml"; +if (file_exists($pyproject)) { + $content = file_get_contents($pyproject); + if (preg_match('/^version\s*=\s*"(\d{2}\.\d{2}\.\d{2})"/m', $content, $m)) { + $versions['pyproject.toml'] = $m[1]; + } +} + // ── Read manifest XML versions ─────────────────────────────────────────────── $xmlGlobs = [ "{$root}/src/pkg_*.xml", @@ -111,9 +151,65 @@ if (count($uniqueVersions) === 1) { echo " Fixed: README.md -> {$highestVersion}\n"; } + // Fix .mokogitea/manifest.xml + if (isset($versions['.mokogitea/manifest.xml']) && $versions['.mokogitea/manifest.xml'] !== $highestVersion) { + $content = file_get_contents($mokoManifest); + $updated = preg_replace( + '#\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?#', + "{$highestVersion}", + $content + ); + if ($updated !== null) { + file_put_contents($mokoManifest, $updated); + } + echo " Fixed: .mokogitea/manifest.xml -> {$highestVersion}\n"; + } + + // Fix CHANGELOG.md + if (isset($versions['CHANGELOG.md']) && $versions['CHANGELOG.md'] !== $highestVersion) { + $content = file_get_contents($changelog); + $updated = preg_replace( + '/(VERSION:\s*)\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?/m', + '${1}' . $highestVersion, + $content + ); + if ($updated !== null) { + file_put_contents($changelog, $updated); + } + echo " Fixed: CHANGELOG.md -> {$highestVersion}\n"; + } + + // Fix package.json + if (isset($versions['package.json']) && $versions['package.json'] !== $highestVersion) { + $content = file_get_contents($packageJson); + $updated = preg_replace( + '/("version"\s*:\s*")\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?(")/m', + '${1}' . $highestVersion . '${2}', + $content + ); + if ($updated !== null) { + file_put_contents($packageJson, $updated); + } + echo " Fixed: package.json -> {$highestVersion}\n"; + } + + // Fix pyproject.toml + if (isset($versions['pyproject.toml']) && $versions['pyproject.toml'] !== $highestVersion) { + $content = file_get_contents($pyproject); + $updated = preg_replace( + '/^(version\s*=\s*")\d{2}\.\d{2}\.\d{2}(?:(?:-(?:dev|alpha|beta|rc))+)?(")/m', + '${1}' . $highestVersion . '${2}', + $content + ); + if ($updated !== null) { + file_put_contents($pyproject, $updated); + } + echo " Fixed: pyproject.toml -> {$highestVersion}\n"; + } + // Fix XML manifests foreach ($versions as $source => $ver) { - if ($source === 'README.md') continue; + if (in_array($source, ['README.md', 'CHANGELOG.md', '.mokogitea/manifest.xml', 'package.json', 'pyproject.toml'], true)) continue; if ($ver === $highestVersion) continue; $file = "{$root}/{$source}"; @@ -121,7 +217,7 @@ if (count($uniqueVersions) === 1) { $content = file_get_contents($file); $updated = preg_replace( - '|[^<]*|', + '#[^<]*#', "{$highestVersion}", $content ); -- 2.52.0