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
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>
136 lines
4.0 KiB
PHP
136 lines
4.0 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/changelog_prune.php
|
|
* BRIEF: Prune old CHANGELOG.md entries — keeps [Unreleased] + last N releases
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
|
|
|
|
use MokoEnterprise\CliFramework;
|
|
|
|
class ChangelogPruneCli extends CliFramework
|
|
{
|
|
protected function configure(): void
|
|
{
|
|
$this->setDescription('Prune old CHANGELOG.md entries — keeps [Unreleased] + last N releases');
|
|
$this->addArgument('--path', 'Repository path', '.');
|
|
$this->addArgument('--keep', 'Number of versioned releases to keep', '5');
|
|
}
|
|
|
|
protected function run(): int
|
|
{
|
|
$path = $this->getArgument('--path');
|
|
$keep = (int) $this->getArgument('--keep');
|
|
|
|
$changelog = realpath($path) . '/CHANGELOG.md';
|
|
if (!file_exists($changelog)) {
|
|
$this->log('ERROR', "No CHANGELOG.md found at {$path}");
|
|
return 1;
|
|
}
|
|
|
|
$content = file_get_contents($changelog);
|
|
$lines = explode("\n", $content);
|
|
|
|
// Split into sections by ## headings
|
|
$sections = [];
|
|
$current = [];
|
|
$currentHeading = null;
|
|
|
|
foreach ($lines as $line) {
|
|
if (preg_match('/^## /', $line)) {
|
|
if ($currentHeading !== null) {
|
|
$sections[] = ['heading' => $currentHeading, 'lines' => $current];
|
|
}
|
|
$currentHeading = $line;
|
|
$current = [$line];
|
|
} else {
|
|
$current[] = $line;
|
|
}
|
|
}
|
|
if ($currentHeading !== null) {
|
|
$sections[] = ['heading' => $currentHeading, 'lines' => $current];
|
|
}
|
|
|
|
// Find the header (everything before the first ## section)
|
|
$header = [];
|
|
$contentLines = explode("\n", $content);
|
|
foreach ($contentLines as $line) {
|
|
if (preg_match('/^## /', $line)) {
|
|
break;
|
|
}
|
|
$header[] = $line;
|
|
}
|
|
|
|
// Separate [Unreleased] from versioned sections
|
|
$unreleased = null;
|
|
$versioned = [];
|
|
|
|
foreach ($sections as $section) {
|
|
if (preg_match('/\[Unreleased\]/i', $section['heading'])) {
|
|
$unreleased = $section;
|
|
} else {
|
|
$versioned[] = $section;
|
|
}
|
|
}
|
|
|
|
$totalVersioned = count($versioned);
|
|
$pruned = $totalVersioned - $keep;
|
|
|
|
if ($pruned <= 0) {
|
|
echo "CHANGELOG has {$totalVersioned} versioned entries — nothing to prune (keeping {$keep})\n";
|
|
return 0;
|
|
}
|
|
|
|
// Keep only the first N versioned sections
|
|
$keptVersioned = array_slice($versioned, 0, $keep);
|
|
$droppedVersioned = array_slice($versioned, $keep);
|
|
|
|
// Report
|
|
echo "CHANGELOG: {$totalVersioned} versioned entries found\n";
|
|
echo " Keeping: {$keep} most recent\n";
|
|
echo " Pruning: {$pruned} old entries\n";
|
|
|
|
foreach ($droppedVersioned as $section) {
|
|
$heading = trim($section['heading']);
|
|
echo " - {$heading}\n";
|
|
}
|
|
|
|
if ($this->dryRun) {
|
|
echo "\n(dry-run) No changes written\n";
|
|
return 0;
|
|
}
|
|
|
|
// Rebuild the file
|
|
$output = implode("\n", $header);
|
|
|
|
if ($unreleased !== null) {
|
|
$output .= implode("\n", $unreleased['lines']) . "\n";
|
|
}
|
|
|
|
foreach ($keptVersioned as $section) {
|
|
$output .= implode("\n", $section['lines']) . "\n";
|
|
}
|
|
|
|
// Clean up excessive blank lines at end
|
|
$output = rtrim($output) . "\n";
|
|
|
|
file_put_contents($changelog, $output);
|
|
echo "\nCHANGELOG pruned: removed {$pruned} old entries\n";
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
$app = new ChangelogPruneCli();
|
|
exit($app->execute());
|