b3d9ee8255
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Blocked by required conditions
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Blocked by required conditions
Platform: moko-platform CI / Gate 4: Governance (push) 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
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Platform: moko-platform CI / Gate 1: Code Quality (push) Failing after 36s
Wrap all CLI tools in cli/, automation/, maintenance/, deploy/, and release/ in classes extending CliFramework. Replaces manual $argv parsing with configure()/addArgument(), moves logic into run(): int, and converts fwrite(STDERR,...) to $this->log(). Two CLIApp subclasses (generate_dolibarr_version_txt, generate_joomla_update_xml) converted to extend CliFramework directly. Every script now gets free --help, --verbose, --quiet, --dry-run, --json, --no-color, banners, coloured logging, and progress bars. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
192 lines
7.2 KiB
PHP
192 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());
|