Files
moko-platform/cli/release.php
T
Jonathan Miller 66e728b078
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Blocked by required conditions
Platform: moko-platform CI / Gate 5: Template Integrity (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (push) Blocked by required conditions
Platform: moko-platform CI / CI Summary (pull_request) Blocked by required conditions
Platform: moko-platform CI / Gate 5: Template Integrity (push) Blocked by required conditions
Platform: moko-platform CI / CI Summary (push) Blocked by required conditions
Generic: Repo Health / Release configuration (push) Blocked by required conditions
Generic: Repo Health / Scripts governance (push) Blocked by required conditions
Generic: Repo Health / Repository health (push) Blocked by required conditions
Universal: PR Check / Build RC Package (pull_request) Blocked by required conditions
Generic: Repo Health / Release configuration (pull_request) Blocked by required conditions
Generic: Repo Health / Scripts governance (pull_request) Blocked by required conditions
Generic: Repo Health / Repository health (pull_request) Blocked by required conditions
Generic: Repo Health / Access control (push) Successful in 18s
Generic: Repo Health / Site Health (push) Has been skipped
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: Auto Version Bump / Version Bump (push) Failing after 27s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 28s
Universal: PR Check / Validate PR (pull_request) Failing after 6s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Generic: Repo Health / Access control (pull_request) Successful in 3s
Platform: moko-platform CI / Gate 1: Code Quality (pull_request) Failing after 1m7s
Platform: moko-platform CI / Gate 1: Code Quality (push) Failing after 1m7s
style: fix PHPCS violations across migrated CLI scripts
Auto-fixed 5006 tab-indent and line-ending errors via phpcbf, then
manually broke 100 lines exceeding 150-char limit. All 74 files in
cli/, automation/, maintenance/, deploy/ now pass PHPCS PSR-12 clean.

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-31 13:36:05 -05:00

193 lines
7.2 KiB
PHP

#!/usr/bin/env php
<?php
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
*
* 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/release.php
* BRIEF: Automate the moko-platform version branch release flow
*/
declare(strict_types=1);
require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
use MokoEnterprise\CliFramework;
class ReleaseCli extends CliFramework
{
protected function configure(): void
{
$this->setDescription('Automate the moko-platform version branch release flow');
$this->addArgument('--bump', 'Bump type: patch, minor, or major', '');
}
protected function run(): int
{
$bumpType = $this->getArgument('--bump');
if (empty($bumpType)) {
$bumpType = null;
}
$repoRoot = dirname(__DIR__, 2);
$syncFile = "{$repoRoot}/lib/Enterprise/RepositorySynchronizer.php";
// Check both workflow directories for the bulk-repo-sync workflow
$bulkSyncFile = file_exists("{$repoRoot}/.mokogitea/workflows/bulk-repo-sync.yml")
? "{$repoRoot}/.mokogitea/workflows/bulk-repo-sync.yml"
: "{$repoRoot}/.github/workflows/bulk-repo-sync.yml";
$cleanupFile = "{$repoRoot}/templates/workflows/shared/repository-cleanup.yml.template";
// -- Step 1: Read current version --
$readme = "{$repoRoot}/README.md";
$content = file_get_contents($readme);
if (!preg_match('/^\s*VERSION:\s*(\d{2})\.(\d{2})\.(\d{2})/m', $content, $m)) {
$this->log('ERROR', 'No VERSION found in README.md');
return 1;
}
$major = (int)$m[1];
$minor = (int)$m[2];
$patch = (int)$m[3];
$currentVersion = sprintf('%02d.%02d.%02d', $major, $minor, $patch);
// -- Step 2: Bump version if requested --
if ($bumpType) {
switch ($bumpType) {
case 'major':
$major++;
$minor = 0;
$patch = 0;
break;
case 'minor':
$minor++;
$patch = 0;
break;
case 'patch':
$patch++;
break;
default:
$this->log('ERROR', "Invalid bump type: {$bumpType} (use patch/minor/major)");
return 1;
}
$newVersion = sprintf('%02d.%02d.%02d', $major, $minor, $patch);
echo "Bumping: {$currentVersion} -> {$newVersion}\n";
if (!$this->dryRun) {
// Update README.md
$content = preg_replace(
'/^(\s*VERSION:\s*)\d{2}\.\d{2}\.\d{2}/m',
'${1}' . $newVersion,
$content,
1
);
file_put_contents($readme, $content);
// Propagate to all files
echo "Propagating version to all files...\n";
passthru("php {$repoRoot}/api/maintenance/update_version_from_readme.php --path {$repoRoot}");
}
$currentVersion = $newVersion;
} else {
echo "Version: {$currentVersion}\n";
}
// Derive major.minor for branch naming (patches update existing branch)
$versionParts = explode('.', $currentVersion);
$minorVersion = $versionParts[0] . '.' . $versionParts[1];
$branch = "version/{$minorVersion}";
// -- Step 3: Update STANDARDS_VERSION + STANDARDS_MINOR constants --
echo "Updating STANDARDS_VERSION -> {$currentVersion}\n";
echo "Updating STANDARDS_MINOR -> {$minorVersion}\n";
if (!$this->dryRun) {
$syncContent = file_get_contents($syncFile);
$syncContent = preg_replace(
"/STANDARDS_VERSION\s*=\s*'[^']+'/",
"STANDARDS_VERSION = '{$currentVersion}'",
$syncContent
);
$syncContent = preg_replace(
"/STANDARDS_MINOR\s*=\s*'[^']+'/",
"STANDARDS_MINOR = '{$minorVersion}'",
$syncContent
);
file_put_contents($syncFile, $syncContent);
}
// -- Step 4: Update bulk-repo-sync.yml checkout ref --
echo "Updating bulk-repo-sync.yml -> {$branch}\n";
if (!$this->dryRun) {
$bulkContent = file_get_contents($bulkSyncFile);
$bulkContent = preg_replace(
'/ref:\s*version\/[\d.]+/',
"ref: {$branch}",
$bulkContent
);
file_put_contents($bulkSyncFile, $bulkContent);
}
// -- Step 5: Update repository-cleanup.yml current branch --
echo "Updating repository-cleanup.yml -> chore/sync-mokostandards-v{$minorVersion}\n";
if (!$this->dryRun) {
$cleanupContent = file_get_contents($cleanupFile);
$cleanupContent = preg_replace(
'/CURRENT="chore\/sync-mokostandards-v[^"]*"/',
"CURRENT=\"chore/sync-mokostandards-v{$minorVersion}\"",
$cleanupContent
);
file_put_contents($cleanupFile, $cleanupContent);
}
// -- Step 6: Commit changes --
if (!$this->dryRun) {
echo "Committing...\n";
passthru("cd {$repoRoot} && git add -A && git commit -m \"chore(release): prepare {$currentVersion} release [skip ci]\"");
passthru("cd {$repoRoot} && git pull --rebase 2>/dev/null; git push");
}
// -- Step 7: Create or update version branch --
$isPatch = ($versionParts[2] ?? '00') !== '00';
if ($isPatch) {
echo "Updating version branch: {$branch} (patch update)\n";
if (!$this->dryRun) {
passthru("cd " . escapeshellarg($repoRoot) . " && git push origin main:{$branch} --force 2>&1");
}
} else {
echo "Creating version branch: {$branch} (minor release)\n";
if (!$this->dryRun) {
$exitCode = 0;
passthru("cd " . escapeshellarg($repoRoot) . " && git push origin main:{$branch} 2>&1", $exitCode);
if ($exitCode !== 0) {
echo "Branch {$branch} already exists — force updating\n";
passthru("cd " . escapeshellarg($repoRoot) . " && git push origin main:{$branch} --force 2>&1");
}
}
}
// -- Step 8: Create git tag (never overwrite existing) --
$tag = "v{$currentVersion}";
echo "Creating tag {$tag}\n";
if (!$this->dryRun) {
$exitCode = 0;
passthru("cd {$repoRoot} && git tag {$tag} 2>/dev/null && git push origin {$tag} 2>/dev/null", $exitCode);
if ($exitCode !== 0) {
echo "Tag {$tag} already exists — skipping\n";
}
}
echo "\nRelease {$currentVersion} complete\n";
echo " Branch: {$branch}\n";
echo " Tag: {$tag}\n";
echo " Next: run bulk sync to push to all repos\n";
return 0;
}
}
$app = new ReleaseCli();
exit($app->execute());