Merge pull request 'chore: migrate 7 CLIApp scripts to CliFramework' (#108) from dev into main
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 / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 4s
Generic: Repo Health / Release configuration (push) Successful in 5s
Generic: Repo Health / Scripts governance (push) Successful in 5s
Generic: Repo Health / Repository health (push) Successful in 13s
Platform: moko-platform CI / Gate 1: Code Quality (push) Successful in 56s
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 / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: Cascade Main → Dev / Cascade main → branches (push) Successful in 4s
Generic: Repo Health / Release configuration (push) Successful in 5s
Generic: Repo Health / Scripts governance (push) Successful in 5s
Generic: Repo Health / Repository health (push) Successful in 13s
Platform: moko-platform CI / Gate 1: Code Quality (push) Successful in 56s
This commit was merged in pull request #108.
This commit is contained in:
@@ -30,7 +30,7 @@ require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
|
||||
|
||||
use MokoEnterprise\{
|
||||
AuditLogger,
|
||||
CLIApp,
|
||||
CliFramework,
|
||||
Config,
|
||||
GitPlatformAdapter,
|
||||
MetricsCollector,
|
||||
@@ -47,7 +47,7 @@ use MokoEnterprise\{
|
||||
*
|
||||
* Works with both GitHub and Gitea via the PlatformAdapterFactory.
|
||||
*/
|
||||
class BulkJoomlaTemplate extends CLIApp
|
||||
class BulkJoomlaTemplate extends CliFramework
|
||||
{
|
||||
public const DEFAULT_ORG = 'MokoConsulting';
|
||||
public const VERSION = '04.06.10';
|
||||
@@ -56,22 +56,20 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
private AuditLogger $logger;
|
||||
private Config $config;
|
||||
|
||||
protected function setupArguments(): array
|
||||
protected function configure(): void
|
||||
{
|
||||
return [
|
||||
'org:' => 'Organization (default: ' . self::DEFAULT_ORG . ')',
|
||||
'scaffold' => 'Create a new Joomla template repository',
|
||||
'sync' => 'Sync MokoStandards files to existing template repos',
|
||||
'list' => 'List all joomla-template repositories',
|
||||
'name:' => 'Template name for --scaffold (e.g. MokoTheme)',
|
||||
'client:' => 'Joomla client: site (default) or administrator',
|
||||
'repos:' => 'Target repositories for --sync (comma-separated, or use --all)',
|
||||
'all' => 'Sync all repos tagged joomla-template',
|
||||
'sync-updates' => 'Sync updates.xml between Gitea and GitHub for Joomla repos',
|
||||
'private' => 'Create as private repository (--scaffold)',
|
||||
'dry-run' => 'Preview changes without making them',
|
||||
'yes' => 'Auto-confirm prompts',
|
||||
];
|
||||
$this->setDescription('Bulk Joomla template management');
|
||||
$this->addArgument('--org', 'Organization', self::DEFAULT_ORG);
|
||||
$this->addArgument('--scaffold', 'Create new template repo', false);
|
||||
$this->addArgument('--sync', 'Sync files to template repos', false);
|
||||
$this->addArgument('--list', 'List template repos', false);
|
||||
$this->addArgument('--name', 'Template name for scaffold', '');
|
||||
$this->addArgument('--client', 'Joomla client: site or admin', 'site');
|
||||
$this->addArgument('--repos', 'Target repos (comma-separated)', '');
|
||||
$this->addArgument('--all', 'Sync all tagged repos', false);
|
||||
$this->addArgument('--sync-updates', 'Sync updates.xml', false);
|
||||
$this->addArgument('--private', 'Create as private repo', false);
|
||||
$this->addArgument('--yes', 'Auto-confirm', false);
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
@@ -88,23 +86,23 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
}
|
||||
|
||||
$this->logger = new AuditLogger('joomla_template');
|
||||
$org = $this->getOption('org', self::DEFAULT_ORG);
|
||||
$org = $this->getArgument('--org', self::DEFAULT_ORG);
|
||||
$platform = $this->adapter->getPlatformName();
|
||||
$this->log("Platform: {$platform} | Organization: {$org}", 'INFO');
|
||||
|
||||
if ($this->hasOption('list')) {
|
||||
if ($this->getArgument('--list', false)) {
|
||||
return $this->listTemplateRepos($org);
|
||||
}
|
||||
|
||||
if ($this->hasOption('scaffold')) {
|
||||
if ($this->getArgument('--scaffold', false)) {
|
||||
return $this->scaffoldTemplate($org);
|
||||
}
|
||||
|
||||
if ($this->hasOption('sync')) {
|
||||
if ($this->getArgument('--sync', false)) {
|
||||
return $this->syncTemplates($org);
|
||||
}
|
||||
|
||||
if ($this->hasOption('sync-updates')) {
|
||||
if ($this->getArgument('--sync-updates', false)) {
|
||||
return $this->syncUpdatesBetweenPlatforms($org);
|
||||
}
|
||||
|
||||
@@ -138,9 +136,9 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
|
||||
private function scaffoldTemplate(string $org): int
|
||||
{
|
||||
$name = $this->getOption('name', '');
|
||||
$client = $this->getOption('client', 'site');
|
||||
$dryRun = $this->hasOption('dry-run');
|
||||
$name = $this->getArgument('--name', '');
|
||||
$client = $this->getArgument('--client', 'site');
|
||||
$dryRun = $this->dryRun;
|
||||
|
||||
if (empty($name)) {
|
||||
$this->log("❌ --name is required for --scaffold", 'ERROR');
|
||||
@@ -176,7 +174,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
}
|
||||
|
||||
// Confirm
|
||||
if (!$this->hasOption('yes')) {
|
||||
if (!$this->getArgument('--yes', false)) {
|
||||
echo "\nCreate repository {$org}/{$name}? [y/N]: ";
|
||||
$handle = fopen('php://stdin', 'r');
|
||||
$line = fgets($handle);
|
||||
@@ -192,7 +190,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
// Create repository
|
||||
$this->log("\nCreating repository...", 'INFO');
|
||||
try {
|
||||
$isPrivate = $this->hasOption('private');
|
||||
$isPrivate = $this->getArgument('--private', false);
|
||||
$this->adapter->createOrgRepo($org, $name, [
|
||||
'description' => "Joomla {$client} template — {$name}",
|
||||
'private' => $isPrivate,
|
||||
@@ -263,10 +261,10 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
{
|
||||
$repos = [];
|
||||
|
||||
if ($this->hasOption('all')) {
|
||||
if ($this->getArgument('--all', false)) {
|
||||
$repos = $this->findTemplateRepos($org);
|
||||
} else {
|
||||
$reposArg = $this->getOption('repos', '');
|
||||
$reposArg = $this->getArgument('--repos', '');
|
||||
if (empty($reposArg)) {
|
||||
$this->log("❌ --repos or --all required for --sync", 'ERROR');
|
||||
return 1;
|
||||
@@ -284,7 +282,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
|
||||
$this->log("\nSyncing " . count($repos) . " template repo(s)...", 'INFO');
|
||||
|
||||
$dryRun = $this->hasOption('dry-run');
|
||||
$dryRun = $this->dryRun;
|
||||
$success = 0;
|
||||
$failed = 0;
|
||||
|
||||
@@ -741,7 +739,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
{
|
||||
$repos = [];
|
||||
|
||||
if ($this->hasOption('all')) {
|
||||
if ($this->getArgument('--all', false)) {
|
||||
$repos = $this->findTemplateRepos($org);
|
||||
// Also include waas-component repos
|
||||
$allRepos = $this->adapter->listOrgRepos($org, true);
|
||||
@@ -765,7 +763,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
return true;
|
||||
});
|
||||
} else {
|
||||
$reposArg = $this->getOption('repos', '');
|
||||
$reposArg = $this->getArgument('--repos', '');
|
||||
if (empty($reposArg)) {
|
||||
$this->log("❌ --repos or --all required for --sync-updates", 'ERROR');
|
||||
return 1;
|
||||
@@ -791,7 +789,7 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
|
||||
$gitea = $adapters['gitea'];
|
||||
$github = $adapters['github'];
|
||||
$dryRun = $this->hasOption('dry-run');
|
||||
$dryRun = $this->dryRun;
|
||||
|
||||
$this->log("\nSyncing updates.xml across Gitea <-> GitHub for " . count($repos) . " repo(s)...", 'INFO');
|
||||
|
||||
@@ -936,10 +934,6 @@ class BulkJoomlaTemplate extends CLIApp
|
||||
|
||||
// Execute if run directly
|
||||
if (php_sapi_name() === 'cli' && isset($argv[0]) && realpath($argv[0]) === __FILE__) {
|
||||
$app = new BulkJoomlaTemplate(
|
||||
'joomla-template',
|
||||
'Bulk scaffold and sync Joomla template repositories',
|
||||
BulkJoomlaTemplate::VERSION
|
||||
);
|
||||
$app = new BulkJoomlaTemplate();
|
||||
exit($app->execute());
|
||||
}
|
||||
|
||||
+23
-27
@@ -26,7 +26,7 @@ use MokoEnterprise\{
|
||||
AuditLogger,
|
||||
CheckpointManager,
|
||||
CircuitBreakerOpen,
|
||||
CLIApp,
|
||||
CliFramework,
|
||||
Config,
|
||||
GitPlatformAdapter,
|
||||
MetricsCollector,
|
||||
@@ -45,7 +45,7 @@ use MokoEnterprise\{
|
||||
* Synchronizes MokoStandards files across multiple repositories using
|
||||
* the Enterprise library for robust, audited operations.
|
||||
*/
|
||||
class BulkSync extends CLIApp
|
||||
class BulkSync extends CliFramework
|
||||
{
|
||||
/**
|
||||
* Default organization for bulk sync operations
|
||||
@@ -65,6 +65,7 @@ class BulkSync extends CLIApp
|
||||
private RepositorySynchronizer $synchronizer;
|
||||
private AuditLogger $logger;
|
||||
private CheckpointManager $checkpoints;
|
||||
private MetricsCollector $metrics;
|
||||
private SecurityValidator $security;
|
||||
private PluginFactory $pluginFactory;
|
||||
private ProjectTypeDetector $typeDetector;
|
||||
@@ -76,21 +77,20 @@ class BulkSync extends CLIApp
|
||||
/**
|
||||
* Setup command-line arguments
|
||||
*/
|
||||
protected function setupArguments(): array
|
||||
protected function configure(): void
|
||||
{
|
||||
return [
|
||||
'org:' => 'GitHub organization (default: MokoConsulting)',
|
||||
'repos:' => 'Specific repositories to sync (space-separated)',
|
||||
'exclude:' => 'Repositories to exclude (space-separated)',
|
||||
'skip-archived' => 'Skip archived repositories',
|
||||
'yes' => 'Auto-confirm prompts',
|
||||
'resume' => 'Resume from last checkpoint, skipping already-processed repositories',
|
||||
'force' => 'Force overwrite of protected files (always_overwrite=false), except truly protected files',
|
||||
'protect' => 'Apply/enforce main branch protection rules on all synced repositories',
|
||||
'no-issue' => 'Skip creating a tracking issue in each target repository',
|
||||
'update-branches' => 'After sync, merge main into all other open PR branches in each repo',
|
||||
'health' => 'Run repo health checks after sync and include results in the report',
|
||||
];
|
||||
$this->setDescription('Bulk repository synchronization');
|
||||
$this->addArgument('--org', 'Organization', self::DEFAULT_ORG);
|
||||
$this->addArgument('--repos', 'Specific repos', '');
|
||||
$this->addArgument('--exclude', 'Repos to exclude', '');
|
||||
$this->addArgument('--skip-archived', 'Skip archived repos', false);
|
||||
$this->addArgument('--yes', 'Auto-confirm', false);
|
||||
$this->addArgument('--resume', 'Resume from checkpoint', false);
|
||||
$this->addArgument('--force', 'Force overwrite', false);
|
||||
$this->addArgument('--protect', 'Apply branch protection', false);
|
||||
$this->addArgument('--no-issue', 'Skip tracking issue', false);
|
||||
$this->addArgument('--update-branches', 'Merge main into branches', false);
|
||||
$this->addArgument('--health', 'Run health checks', false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,13 +106,13 @@ class BulkSync extends CLIApp
|
||||
}
|
||||
|
||||
// Get configuration
|
||||
$org = $this->getOption('org', self::DEFAULT_ORG);
|
||||
$skipArchived = $this->hasOption('skip-archived');
|
||||
$autoConfirm = $this->hasOption('yes');
|
||||
$org = $this->getArgument('--org', self::DEFAULT_ORG);
|
||||
$skipArchived = $this->getArgument('--skip-archived', false);
|
||||
$autoConfirm = $this->getArgument('--yes', false);
|
||||
|
||||
// Get repository filters
|
||||
$specificRepos = $this->parseRepositoryList($this->getOption('repos', ''));
|
||||
$excludeRepos = $this->parseRepositoryList($this->getOption('exclude', ''));
|
||||
$specificRepos = $this->parseRepositoryList($this->getArgument('--repos', ''));
|
||||
$excludeRepos = $this->parseRepositoryList($this->getArgument('--exclude', ''));
|
||||
|
||||
$this->log("Organization: {$org}", 'INFO');
|
||||
if (!empty($specificRepos)) {
|
||||
@@ -139,7 +139,7 @@ class BulkSync extends CLIApp
|
||||
|
||||
// Load resume checkpoint if --resume is set
|
||||
$alreadyProcessed = [];
|
||||
if ($this->hasOption('resume')) {
|
||||
if ($this->getArgument('--resume', false)) {
|
||||
$checkpoint = $this->checkpoints->loadCheckpoint('bulk_sync');
|
||||
if ($checkpoint !== null) {
|
||||
$alreadyProcessed = array_keys($checkpoint['results']['repositories'] ?? []);
|
||||
@@ -1424,10 +1424,6 @@ class BulkSync extends CLIApp
|
||||
|
||||
// Execute if run directly
|
||||
if (php_sapi_name() === 'cli' && isset($argv[0]) && realpath($argv[0]) === __FILE__) {
|
||||
$app = new BulkSync(
|
||||
'bulk-sync',
|
||||
'Enterprise-grade bulk repository synchronization',
|
||||
BulkSync::VERSION
|
||||
);
|
||||
$app = new BulkSync();
|
||||
exit($app->execute());
|
||||
}
|
||||
|
||||
+27
-29
@@ -24,7 +24,7 @@ require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
|
||||
use MokoEnterprise\{
|
||||
ApiClient,
|
||||
AuditLogger,
|
||||
CLIApp,
|
||||
CliFramework,
|
||||
Config,
|
||||
DefinitionParser,
|
||||
GitPlatformAdapter,
|
||||
@@ -51,7 +51,7 @@ use MokoEnterprise\{
|
||||
* php push_files.php --files=".github/workflows/ci.yml,.github/workflows/codeql-analysis.yml" --repos=MokoCRM,WaasComponent
|
||||
* php push_files.php --files=templates/foo.txt:docs/foo.txt --repos=MyRepo --direct
|
||||
*/
|
||||
class PushFiles extends CLIApp
|
||||
class PushFiles extends CliFramework
|
||||
{
|
||||
public const DEFAULT_ORG = 'MokoConsulting';
|
||||
public const VERSION = '04.06.00';
|
||||
@@ -65,18 +65,17 @@ class PushFiles extends CLIApp
|
||||
/**
|
||||
* Setup command-line arguments
|
||||
*/
|
||||
protected function setupArguments(): array
|
||||
protected function configure(): void
|
||||
{
|
||||
return [
|
||||
'org:' => 'GitHub organization (default: ' . self::DEFAULT_ORG . ')',
|
||||
'repos:' => 'Target repositories — comma or space-separated (required)',
|
||||
'files:' => 'Files to push — destination paths or source:destination pairs, comma/space-separated (required)',
|
||||
'message:' => 'Custom commit message (optional)',
|
||||
'branch:' => 'Target branch for direct pushes (default: repo default branch). Ignored unless --direct is set',
|
||||
'direct' => 'Push directly to target branch instead of creating a PR',
|
||||
'yes' => 'Auto-confirm without prompting',
|
||||
'no-issue' => 'Skip creating a tracking issue in each target repository',
|
||||
];
|
||||
$this->setDescription('Push files to remote repositories');
|
||||
$this->addArgument('--org', 'GitHub organization', self::DEFAULT_ORG);
|
||||
$this->addArgument('--repos', 'Target repos (comma-separated)', '');
|
||||
$this->addArgument('--files', 'Files to push (comma-separated)', '');
|
||||
$this->addArgument('--message', 'Custom commit message', '');
|
||||
$this->addArgument('--branch', 'Target branch for direct pushes', '');
|
||||
$this->addArgument('--direct', 'Push directly instead of PR', false);
|
||||
$this->addArgument('--yes', 'Auto-confirm without prompting', false);
|
||||
$this->addArgument('--no-issue', 'Skip creating tracking issue', false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,11 +89,11 @@ class PushFiles extends CLIApp
|
||||
return 1;
|
||||
}
|
||||
|
||||
$org = $this->getOption('org', self::DEFAULT_ORG);
|
||||
$reposArg = $this->getOption('repos', '');
|
||||
$filesArg = $this->getOption('files', '');
|
||||
$direct = $this->hasOption('direct');
|
||||
$autoYes = $this->hasOption('yes');
|
||||
$org = $this->getArgument('--org', self::DEFAULT_ORG);
|
||||
$reposArg = $this->getArgument('--repos', '');
|
||||
$filesArg = $this->getArgument('--files', '');
|
||||
$direct = $this->getArgument('--direct', false);
|
||||
$autoYes = $this->getArgument('--yes', false);
|
||||
|
||||
// Validate required arguments
|
||||
if (empty($reposArg)) {
|
||||
@@ -127,7 +126,7 @@ class PushFiles extends CLIApp
|
||||
}
|
||||
|
||||
// Confirm before proceeding
|
||||
if (!$autoYes && !$this->confirm($repoFileMaps, $direct)) {
|
||||
if (!$autoYes && !$this->confirmPush($repoFileMaps, $direct)) {
|
||||
$this->log('❌ Cancelled.', 'INFO');
|
||||
return 0;
|
||||
}
|
||||
@@ -265,7 +264,8 @@ class PushFiles extends CLIApp
|
||||
// Fall back to live detection
|
||||
try {
|
||||
$repoData = $this->api->get("/repos/{$org}/{$repo}");
|
||||
return $this->typeDetector->detect($repoData, $org, $repo);
|
||||
$result = $this->typeDetector->detect('.');
|
||||
return $result['type'] ?? 'default';
|
||||
} catch (\Exception $e) {
|
||||
$this->log(" ⚠️ Could not detect platform for {$repo}, using 'default'", 'WARN');
|
||||
return 'default';
|
||||
@@ -277,7 +277,7 @@ class PushFiles extends CLIApp
|
||||
*
|
||||
* @param array<string, list<array{source: string, destination: string}>> $repoFileMaps
|
||||
*/
|
||||
private function confirm(array $repoFileMaps, bool $direct): bool
|
||||
private function confirmPush(array $repoFileMaps, bool $direct): bool
|
||||
{
|
||||
if ($this->quiet) {
|
||||
return true;
|
||||
@@ -322,8 +322,8 @@ class PushFiles extends CLIApp
|
||||
'repos' => [],
|
||||
];
|
||||
|
||||
$customMessage = $this->getOption('message', '');
|
||||
$targetBranch = $this->getOption('branch', '');
|
||||
$customMessage = $this->getArgument('--message', '');
|
||||
$targetBranch = $this->getArgument('--branch', '');
|
||||
|
||||
foreach ($repoFileMaps as $repo => $entries) {
|
||||
$this->log("\n[{$repo}] Pushing " . count($entries) . ' file(s)...', 'INFO');
|
||||
@@ -520,6 +520,7 @@ class PushFiles extends CLIApp
|
||||
'direction' => 'desc',
|
||||
]);
|
||||
|
||||
$existing = array_values($existing);
|
||||
if (!empty($existing) && isset($existing[0]['number'])) {
|
||||
$num = $existing[0]['number'];
|
||||
$patch = ['title' => $title, 'body' => $body, 'assignees' => ['jmiller']];
|
||||
@@ -581,7 +582,7 @@ class PushFiles extends CLIApp
|
||||
));
|
||||
|
||||
$repoList = implode("\n", array_map(fn($r) => "- `{$r}`", $failedRepos));
|
||||
$fileArgs = $this->getOption('files', '');
|
||||
$fileArgs = $this->getArgument('--files', '');
|
||||
|
||||
$title = "fix: push_files failed for {$failed} repo(s) — action required";
|
||||
|
||||
@@ -622,6 +623,7 @@ class PushFiles extends CLIApp
|
||||
'direction' => 'desc',
|
||||
]);
|
||||
|
||||
$existing = array_values($existing);
|
||||
if (!empty($existing) && isset($existing[0]['number'])) {
|
||||
$num = $existing[0]['number'];
|
||||
$patch = ['title' => $title, 'body' => $body, 'assignees' => ['jmiller']];
|
||||
@@ -693,10 +695,6 @@ class PushFiles extends CLIApp
|
||||
|
||||
// Execute if run directly
|
||||
if (php_sapi_name() === 'cli' && isset($argv[0]) && realpath($argv[0]) === __FILE__) {
|
||||
$app = new PushFiles(
|
||||
'push-files',
|
||||
'Push one or more specific files to one or more remote repositories',
|
||||
PushFiles::VERSION
|
||||
);
|
||||
$app = new PushFiles();
|
||||
exit($app->execute());
|
||||
}
|
||||
|
||||
+72
-78
@@ -21,7 +21,7 @@ declare(strict_types=1);
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
|
||||
|
||||
use MokoEnterprise\{ApiClient, AuditLogger, CLIApp, Config, GitPlatformAdapter, MetricsCollector, PlatformAdapterFactory};
|
||||
use MokoEnterprise\{ApiClient, AuditLogger, CliFramework, Config, GitPlatformAdapter, MetricsCollector, PlatformAdapterFactory};
|
||||
|
||||
/**
|
||||
* Enterprise Repository Cleanup
|
||||
@@ -36,7 +36,7 @@ use MokoEnterprise\{ApiClient, AuditLogger, CLIApp, Config, GitPlatformAdapter,
|
||||
* 7. Verify and provision standard labels
|
||||
* 8. Version drift detection
|
||||
*/
|
||||
class RepoCleanup extends CLIApp
|
||||
class RepoCleanup extends CliFramework
|
||||
{
|
||||
private const VERSION = '04.06.00';
|
||||
private const SYNC_PREFIX = 'chore/sync-mokostandards-';
|
||||
@@ -60,40 +60,34 @@ class RepoCleanup extends CLIApp
|
||||
private GitPlatformAdapter $adapter;
|
||||
private AuditLogger $logger;
|
||||
private MetricsCollector $metrics;
|
||||
private bool $dryRun = false;
|
||||
protected bool $dryRun = false;
|
||||
private float $startTime;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this->setName('repo-cleanup');
|
||||
$this->setDescription('Enterprise repository cleanup — branches, PRs, issues, workflows, labels, logs');
|
||||
$this->setVersion(self::VERSION);
|
||||
|
||||
$this->addOption('org', 'GitHub organization', 'MokoConsulting');
|
||||
$this->addOption('repos', 'Specific repositories (space-separated)', '');
|
||||
$this->addOption('skip-archived', 'Skip archived repositories', false);
|
||||
$this->addOption('close-issues', 'Close resolved tracking issues (merged PR = done)', false);
|
||||
$this->addOption('lock-old-issues', 'Lock issues closed >30 days', false);
|
||||
$this->addOption('clean-workflows', 'Delete cancelled/stale workflow runs', false);
|
||||
$this->addOption('clean-logs', 'Delete workflow run logs older than --log-days', false);
|
||||
$this->addOption('log-days', 'Days to keep logs (default: 30)', '30');
|
||||
$this->addOption('delete-retired', 'Delete retired workflow files from repos', false);
|
||||
$this->addOption('check-labels', 'Verify mokostandards label exists', false);
|
||||
$this->addOption('check-drift', 'Check for version drift against README.md', false);
|
||||
$this->addOption('all', 'Run all cleanup operations', false);
|
||||
$this->addOption('yes', 'Auto-confirm prompts', false);
|
||||
$this->addOption('dry-run', 'Preview changes without making them', false);
|
||||
$this->addOption('verbose', 'Show detailed output', false);
|
||||
$this->addOption('quiet', 'Suppress non-error output', false);
|
||||
$this->addOption('json', 'Output results as JSON', false);
|
||||
$this->setDescription('Enterprise repository cleanup');
|
||||
$this->addArgument('--org', 'GitHub organization', 'MokoConsulting');
|
||||
$this->addArgument('--repos', 'Specific repos (space-separated)', '');
|
||||
$this->addArgument('--skip-archived', 'Skip archived repos', false);
|
||||
$this->addArgument('--close-issues', 'Close resolved tracking issues', false);
|
||||
$this->addArgument('--lock-old-issues', 'Lock issues closed >30 days', false);
|
||||
$this->addArgument('--clean-workflows', 'Delete stale workflow runs', false);
|
||||
$this->addArgument('--clean-logs', 'Delete old workflow logs', false);
|
||||
$this->addArgument('--log-days', 'Days to keep logs', '30');
|
||||
$this->addArgument('--delete-retired', 'Delete retired workflows', false);
|
||||
$this->addArgument('--check-labels', 'Verify labels exist', false);
|
||||
$this->addArgument('--check-drift', 'Check version drift', false);
|
||||
$this->addArgument('--all', 'Run all operations', false);
|
||||
$this->addArgument('--yes', 'Auto-confirm', false);
|
||||
$this->addArgument('--json', 'Output as JSON', false);
|
||||
}
|
||||
|
||||
protected function execute(): int
|
||||
protected function run(): int
|
||||
{
|
||||
$this->startTime = microtime(true);
|
||||
$org = $this->getOption('org', 'MokoConsulting');
|
||||
$this->dryRun = (bool) $this->getOption('dry-run', false);
|
||||
$runAll = (bool) $this->getOption('all', false);
|
||||
$org = $this->getArgument('--org', 'MokoConsulting');
|
||||
$this->dryRun = (bool) $this->getArgument('--dry-run', false);
|
||||
$runAll = (bool) $this->getArgument('--all', false);
|
||||
|
||||
$config = Config::load();
|
||||
|
||||
@@ -101,24 +95,24 @@ class RepoCleanup extends CLIApp
|
||||
$this->adapter = PlatformAdapterFactory::create($config);
|
||||
$this->api = $this->adapter->getApiClient();
|
||||
} catch (\Exception $e) {
|
||||
$this->error('Failed to initialize platform adapter: ' . $e->getMessage());
|
||||
$this->errorMsg('Failed to initialize platform adapter: ' . $e->getMessage());
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->logger = new AuditLogger('repo_cleanup');
|
||||
$this->metrics = new MetricsCollector('repo_cleanup');
|
||||
|
||||
$this->log("🧹 MokoStandards Repository Cleanup v" . self::VERSION);
|
||||
$this->log("Organization: {$org}");
|
||||
$this->log("Current sync branch: " . self::CURRENT_BRANCH);
|
||||
$this->logMsg("🧹 MokoStandards Repository Cleanup v" . self::VERSION);
|
||||
$this->logMsg("Organization: {$org}");
|
||||
$this->logMsg("Current sync branch: " . self::CURRENT_BRANCH);
|
||||
if ($this->dryRun) {
|
||||
$this->log("⚠️ DRY RUN — no changes will be made");
|
||||
$this->logMsg("⚠️ DRY RUN — no changes will be made");
|
||||
}
|
||||
$this->log('');
|
||||
$this->logMsg('');
|
||||
|
||||
$repos = $this->fetchRepositories($org);
|
||||
$this->log("Found " . count($repos) . " repositories");
|
||||
$this->log('');
|
||||
$this->logMsg("Found " . count($repos) . " repositories");
|
||||
$this->logMsg('');
|
||||
|
||||
$results = [
|
||||
'repos_processed' => 0,
|
||||
@@ -140,7 +134,7 @@ class RepoCleanup extends CLIApp
|
||||
$name = $repo['name'];
|
||||
$num = $i + 1;
|
||||
$total = count($repos);
|
||||
$this->log("[{$num}/{$total}] {$name}");
|
||||
$this->logMsg("[{$num}/{$total}] {$name}");
|
||||
$results['repos_processed']++;
|
||||
|
||||
try {
|
||||
@@ -151,37 +145,37 @@ class RepoCleanup extends CLIApp
|
||||
$cleaned = $this->cleanBranches($org, $name, $results) || $cleaned;
|
||||
|
||||
// Optional: close resolved issues
|
||||
if ($runAll || $this->getOption('close-issues', false)) {
|
||||
if ($runAll || $this->getArgument('--close-issues', false)) {
|
||||
$cleaned = $this->closeResolvedIssues($org, $name, $results) || $cleaned;
|
||||
}
|
||||
|
||||
// Optional: lock old closed issues
|
||||
if ($runAll || $this->getOption('lock-old-issues', false)) {
|
||||
if ($runAll || $this->getArgument('--lock-old-issues', false)) {
|
||||
$cleaned = $this->lockOldIssues($org, $name, $results) || $cleaned;
|
||||
}
|
||||
|
||||
// Optional: delete retired workflow files
|
||||
if ($runAll || $this->getOption('delete-retired', false)) {
|
||||
if ($runAll || $this->getArgument('--delete-retired', false)) {
|
||||
$cleaned = $this->deleteRetiredWorkflows($org, $name, $results) || $cleaned;
|
||||
}
|
||||
|
||||
// Optional: clean workflow runs
|
||||
if ($runAll || $this->getOption('clean-workflows', false)) {
|
||||
if ($runAll || $this->getArgument('--clean-workflows', false)) {
|
||||
$cleaned = $this->cleanWorkflowRuns($org, $name, $results) || $cleaned;
|
||||
}
|
||||
|
||||
// Optional: clean old logs
|
||||
if ($runAll || $this->getOption('clean-logs', false)) {
|
||||
if ($runAll || $this->getArgument('--clean-logs', false)) {
|
||||
$cleaned = $this->cleanOldLogs($org, $name, $results) || $cleaned;
|
||||
}
|
||||
|
||||
// Optional: check labels
|
||||
if ($runAll || $this->getOption('check-labels', false)) {
|
||||
if ($runAll || $this->getArgument('--check-labels', false)) {
|
||||
$this->checkLabels($org, $name, $results);
|
||||
}
|
||||
|
||||
// Optional: check version drift
|
||||
if ($runAll || $this->getOption('check-drift', false)) {
|
||||
if ($runAll || $this->getArgument('--check-drift', false)) {
|
||||
$this->checkVersionDrift($org, $name, $results);
|
||||
}
|
||||
|
||||
@@ -189,32 +183,32 @@ class RepoCleanup extends CLIApp
|
||||
$results['repos_cleaned']++;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$this->error(" ✗ {$name}: " . $e->getMessage());
|
||||
$this->errorMsg(" ✗ {$name}: " . $e->getMessage());
|
||||
$results['errors']++;
|
||||
}
|
||||
}
|
||||
|
||||
$duration = round(microtime(true) - $this->startTime, 1);
|
||||
|
||||
$this->log('');
|
||||
$this->log('============================================================');
|
||||
$this->log("🧹 Cleanup Complete ({$duration}s)");
|
||||
$this->log('============================================================');
|
||||
$this->log("Repos processed: {$results['repos_processed']}");
|
||||
$this->log("Repos with changes: {$results['repos_cleaned']}");
|
||||
$this->log("Branches deleted: {$results['branches_deleted']}");
|
||||
$this->log("PRs closed: {$results['prs_closed']}");
|
||||
$this->log("Issues closed: {$results['issues_closed']}");
|
||||
$this->log("Issues locked: {$results['issues_locked']}");
|
||||
$this->log("Retired files: {$results['retired_files']}");
|
||||
$this->log("Workflow runs: {$results['runs_deleted']}");
|
||||
$this->log("Logs cleaned: {$results['logs_deleted']}");
|
||||
$this->log("Labels missing: {$results['labels_missing']}");
|
||||
$this->log("Version drift: {$results['version_drift']}");
|
||||
$this->log("Errors: {$results['errors']}");
|
||||
$this->log('============================================================');
|
||||
$this->logMsg('');
|
||||
$this->logMsg('============================================================');
|
||||
$this->logMsg("🧹 Cleanup Complete ({$duration}s)");
|
||||
$this->logMsg('============================================================');
|
||||
$this->logMsg("Repos processed: {$results['repos_processed']}");
|
||||
$this->logMsg("Repos with changes: {$results['repos_cleaned']}");
|
||||
$this->logMsg("Branches deleted: {$results['branches_deleted']}");
|
||||
$this->logMsg("PRs closed: {$results['prs_closed']}");
|
||||
$this->logMsg("Issues closed: {$results['issues_closed']}");
|
||||
$this->logMsg("Issues locked: {$results['issues_locked']}");
|
||||
$this->logMsg("Retired files: {$results['retired_files']}");
|
||||
$this->logMsg("Workflow runs: {$results['runs_deleted']}");
|
||||
$this->logMsg("Logs cleaned: {$results['logs_deleted']}");
|
||||
$this->logMsg("Labels missing: {$results['labels_missing']}");
|
||||
$this->logMsg("Version drift: {$results['version_drift']}");
|
||||
$this->logMsg("Errors: {$results['errors']}");
|
||||
$this->logMsg('============================================================');
|
||||
|
||||
if ($this->getOption('json', false)) {
|
||||
if ($this->getArgument('--json', false)) {
|
||||
$results['duration_seconds'] = $duration;
|
||||
echo json_encode($results, JSON_PRETTY_PRINT) . "\n";
|
||||
}
|
||||
@@ -226,8 +220,8 @@ class RepoCleanup extends CLIApp
|
||||
|
||||
private function fetchRepositories(string $org): array
|
||||
{
|
||||
$specificRepos = trim((string) $this->getOption('repos', ''));
|
||||
$skipArchived = (bool) $this->getOption('skip-archived', false);
|
||||
$specificRepos = trim((string) $this->getArgument('--repos', ''));
|
||||
$skipArchived = (bool) $this->getArgument('--skip-archived', false);
|
||||
|
||||
if (!empty($specificRepos)) {
|
||||
$names = preg_split('/[\s,]+/', $specificRepos);
|
||||
@@ -264,7 +258,7 @@ class RepoCleanup extends CLIApp
|
||||
if (($pr['number'] ?? 0) > 0 && !$this->dryRun) {
|
||||
$this->api->patch("/repos/{$org}/{$repo}/pulls/{$pr['number']}", ['state' => 'closed']);
|
||||
}
|
||||
$this->log(" 🔒 Closed PR #{$pr['number']} ({$name})");
|
||||
$this->logMsg(" 🔒 Closed PR #{$pr['number']} ({$name})");
|
||||
$results['prs_closed']++;
|
||||
$changed = true;
|
||||
}
|
||||
@@ -279,7 +273,7 @@ class RepoCleanup extends CLIApp
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$this->log(" 🗑️ Deleted branch: {$name}");
|
||||
$this->logMsg(" 🗑️ Deleted branch: {$name}");
|
||||
$results['branches_deleted']++;
|
||||
$changed = true;
|
||||
}
|
||||
@@ -312,7 +306,7 @@ class RepoCleanup extends CLIApp
|
||||
'state' => 'closed', 'state_reason' => 'completed',
|
||||
]);
|
||||
}
|
||||
$this->log(" ✅ Closed issue #{$num} (PR #{$prNum} merged)");
|
||||
$this->logMsg(" ✅ Closed issue #{$num} (PR #{$prNum} merged)");
|
||||
$results['issues_closed']++;
|
||||
$changed = true;
|
||||
}
|
||||
@@ -361,7 +355,7 @@ class RepoCleanup extends CLIApp
|
||||
}
|
||||
|
||||
if ($results['issues_locked'] > 0) {
|
||||
$this->log(" 🔒 Locked {$results['issues_locked']} old closed issue(s)");
|
||||
$this->logMsg(" 🔒 Locked {$results['issues_locked']} old closed issue(s)");
|
||||
}
|
||||
return $changed;
|
||||
}
|
||||
@@ -396,7 +390,7 @@ class RepoCleanup extends CLIApp
|
||||
'branch' => $defaultBranch,
|
||||
]);
|
||||
}
|
||||
$this->log(" Deleted retired: {$wf} (from {$wfDir})");
|
||||
$this->logMsg(" Deleted retired: {$wf} (from {$wfDir})");
|
||||
$results['retired_files']++;
|
||||
$changed = true;
|
||||
} catch (\Exception $e) {
|
||||
@@ -433,7 +427,7 @@ class RepoCleanup extends CLIApp
|
||||
}
|
||||
}
|
||||
if ($results['runs_deleted'] > 0) {
|
||||
$this->log(" 🔄 Cleaned {$results['runs_deleted']} workflow run(s)");
|
||||
$this->logMsg(" 🔄 Cleaned {$results['runs_deleted']} workflow run(s)");
|
||||
}
|
||||
return $changed;
|
||||
}
|
||||
@@ -441,7 +435,7 @@ class RepoCleanup extends CLIApp
|
||||
private function cleanOldLogs(string $org, string $repo, array &$results): bool
|
||||
{
|
||||
$changed = false;
|
||||
$days = (int) $this->getOption('log-days', '30');
|
||||
$days = (int) $this->getArgument('--log-days', '30');
|
||||
$cutoff = date('Y-m-d\TH:i:s\Z', strtotime("-{$days} days"));
|
||||
|
||||
try {
|
||||
@@ -465,7 +459,7 @@ class RepoCleanup extends CLIApp
|
||||
}
|
||||
|
||||
if ($results['logs_deleted'] > 0) {
|
||||
$this->log(" 📋 Cleaned {$results['logs_deleted']} old log(s)");
|
||||
$this->logMsg(" 📋 Cleaned {$results['logs_deleted']} old log(s)");
|
||||
}
|
||||
return $changed;
|
||||
}
|
||||
@@ -475,7 +469,7 @@ class RepoCleanup extends CLIApp
|
||||
try {
|
||||
$this->api->get("/repos/{$org}/{$repo}/labels/mokostandards");
|
||||
} catch (\Exception $e) {
|
||||
$this->log(" ⚠️ Missing 'mokostandards' label");
|
||||
$this->logMsg(" ⚠️ Missing 'mokostandards' label");
|
||||
$results['labels_missing']++;
|
||||
$this->api->resetCircuitBreaker();
|
||||
}
|
||||
@@ -495,7 +489,7 @@ class RepoCleanup extends CLIApp
|
||||
$mokoContent = base64_decode($mokoFile['content'] ?? '');
|
||||
if (preg_match('/standards_version:\s*(\d{2}\.\d{2}\.\d{2})/m', $mokoContent, $vm)) {
|
||||
if ($vm[1] !== self::VERSION) {
|
||||
$this->log(" ⚠️ Standards drift: {$vm[1]} (expected " . self::VERSION . ")");
|
||||
$this->logMsg(" ⚠️ Standards drift: {$vm[1]} (expected " . self::VERSION . ")");
|
||||
$results['version_drift']++;
|
||||
}
|
||||
}
|
||||
@@ -510,14 +504,14 @@ class RepoCleanup extends CLIApp
|
||||
|
||||
// ─── Helpers ─────────────────────────────────────────────────────────
|
||||
|
||||
private function log(string $message): void
|
||||
private function logMsg(string $message): void
|
||||
{
|
||||
if (!$this->getOption('quiet', false)) {
|
||||
if (!$this->quiet) {
|
||||
echo $message . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
private function error(string $message): void
|
||||
private function errorMsg(string $message): void
|
||||
{
|
||||
fwrite(STDERR, $message . "\n");
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use MokoEnterprise\{ApiClient, AuditLogger, CLIApp, Config, PlatformAdapterFactory};
|
||||
use MokoEnterprise\{ApiClient, AuditLogger, CliFramework, Config, PlatformAdapterFactory};
|
||||
|
||||
class JoomlaRelease extends CLIApp
|
||||
class JoomlaRelease extends CliFramework
|
||||
{
|
||||
private const VERSION = '04.06.00';
|
||||
private const ORG = 'mokoconsulting-tech';
|
||||
@@ -49,6 +49,7 @@ class JoomlaRelease extends CLIApp
|
||||
|
||||
private ApiClient $api;
|
||||
private AuditLogger $logger;
|
||||
private \MokoEnterprise\GitPlatformAdapter $adapter;
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
@@ -498,5 +499,5 @@ class JoomlaRelease extends CLIApp
|
||||
}
|
||||
}
|
||||
|
||||
$script = new JoomlaRelease('joomla_release', 'Joomla release pipeline');
|
||||
exit($script->execute());
|
||||
$app = new JoomlaRelease();
|
||||
exit($app->execute());
|
||||
|
||||
@@ -261,9 +261,9 @@ class ApiClient
|
||||
* @throws RateLimitExceeded
|
||||
* @throws CircuitBreakerOpen
|
||||
*/
|
||||
public function delete(string $endpoint): array
|
||||
public function delete(string $endpoint, ?array $body = null): array
|
||||
{
|
||||
return $this->request('DELETE', $endpoint);
|
||||
return $this->request('DELETE', $endpoint, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,10 +16,6 @@ parameters:
|
||||
analyseAndScan:
|
||||
- vendor
|
||||
- node_modules (?)
|
||||
# Legacy CLIApp scripts — need migration to CliFramework
|
||||
- automation/repo_cleanup.php
|
||||
- automation/push_files.php
|
||||
- cli/joomla_release.php
|
||||
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
|
||||
|
||||
use MokoEnterprise\{
|
||||
CLIApp,
|
||||
CliFramework,
|
||||
ProjectTypeDetector,
|
||||
PluginFactory,
|
||||
PluginRegistry,
|
||||
@@ -36,7 +36,7 @@ use MokoEnterprise\{
|
||||
* Detects whether a repository is a Joomla/WaaS component, Dolibarr/CRM module,
|
||||
* or generic repository, then validates against appropriate schema
|
||||
*/
|
||||
class AutoDetectPlatform extends CLIApp
|
||||
class AutoDetectPlatform extends CliFramework
|
||||
{
|
||||
private const DETECTION_THRESHOLD = 0.5; // 50% confidence required
|
||||
|
||||
@@ -62,20 +62,19 @@ class AutoDetectPlatform extends CLIApp
|
||||
private string $schemaFile = '';
|
||||
private ?object $detectedPlugin = null;
|
||||
|
||||
protected function setupArguments(): array
|
||||
protected function configure(): void
|
||||
{
|
||||
return [
|
||||
'repo-path:' => 'Path to repository to analyze (default: current directory)',
|
||||
'schema-dir:' => 'Path to schema definitions directory (default: definitions/default)',
|
||||
'output-dir:' => 'Directory for output reports (default: var/logs/validation)',
|
||||
];
|
||||
$this->setDescription('Automatically detect platform type and validate repository');
|
||||
$this->addArgument('--repo-path', 'Path to repository to analyze', '.');
|
||||
$this->addArgument('--schema-dir', 'Path to schema definitions directory', 'definitions/default');
|
||||
$this->addArgument('--output-dir', 'Directory for output reports', 'var/logs/validation');
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$repoPath = $this->getOption('repo-path', '.');
|
||||
$schemaDir = $this->getOption('schema-dir', 'definitions/default');
|
||||
$outputDir = $this->getOption('output-dir', 'var/logs/validation');
|
||||
$repoPath = $this->getArgument('--repo-path', '.');
|
||||
$schemaDir = $this->getArgument('--schema-dir', 'definitions/default');
|
||||
$outputDir = $this->getArgument('--output-dir', 'var/logs/validation');
|
||||
|
||||
// Make paths absolute
|
||||
$repoPath = $this->getAbsolutePath($repoPath);
|
||||
@@ -151,7 +150,7 @@ class AutoDetectPlatform extends CLIApp
|
||||
}
|
||||
|
||||
// Output results
|
||||
if ($this->jsonOutput) {
|
||||
if ($this->getArgument("--json", false)) {
|
||||
$this->outputJson();
|
||||
} else {
|
||||
$this->displayResults();
|
||||
@@ -953,5 +952,5 @@ class AutoDetectPlatform extends CLIApp
|
||||
}
|
||||
|
||||
// Run the application
|
||||
$app = new AutoDetectPlatform('auto_detect_platform', 'Automatically detect platform type and validate repository');
|
||||
$app = new AutoDetectPlatform();
|
||||
exit($app->execute());
|
||||
|
||||
@@ -17,29 +17,24 @@ declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use MokoEnterprise\CLIApp;
|
||||
use MokoEnterprise\CliFramework;
|
||||
|
||||
class CheckWikiHealth extends CLIApp
|
||||
class CheckWikiHealth extends CliFramework
|
||||
{
|
||||
public function __construct()
|
||||
protected function configure(): void
|
||||
{
|
||||
parent::__construct('check-wiki-health', 'Validate wiki health for a repository', '01.00.00');
|
||||
}
|
||||
|
||||
protected function setupArguments(): array
|
||||
{
|
||||
return [
|
||||
'path:' => 'Repository path (default: current directory)',
|
||||
'gitea-url:' => 'Gitea base URL (default: https://git.mokoconsulting.tech)',
|
||||
'token:' => 'Gitea API token (or set GITEA_TOKEN env var)',
|
||||
];
|
||||
$this->setDescription('Validate wiki health for a repository');
|
||||
$this->addArgument('--path', 'Repository path (default: current directory)', '.');
|
||||
$this->addArgument('--gitea-url', 'Gitea base URL', 'https://git.mokoconsulting.tech');
|
||||
$this->addArgument('--token', 'Gitea API token (or set GITEA_TOKEN env var)', '');
|
||||
$this->addArgument('--json', 'Output as JSON', false);
|
||||
}
|
||||
|
||||
protected function run(): int
|
||||
{
|
||||
$repoPath = realpath($this->getOption('path', '.')) ?: '.';
|
||||
$giteaUrl = $this->getOption('gitea-url', 'https://git.mokoconsulting.tech');
|
||||
$token = $this->getOption('token', getenv('GITEA_TOKEN') ?: '');
|
||||
$repoPath = realpath($this->getArgument('--path', '.')) ?: '.';
|
||||
$giteaUrl = $this->getArgument('--gitea-url', 'https://git.mokoconsulting.tech');
|
||||
$token = $this->getArgument('--token', getenv('GITEA_TOKEN') ?: '');
|
||||
|
||||
// Detect repo owner/name from git config
|
||||
$configFile = $repoPath . '/.git/config';
|
||||
@@ -76,7 +71,7 @@ class CheckWikiHealth extends CLIApp
|
||||
if ($pages === null) {
|
||||
$this->log(' No wiki found or API error', 'WARNING');
|
||||
$issues++;
|
||||
if ($this->jsonOutput) {
|
||||
if ($this->getArgument("--json", false)) {
|
||||
echo json_encode(['status' => 'no_wiki', 'issues' => $issues]);
|
||||
}
|
||||
return 0;
|
||||
@@ -118,7 +113,7 @@ class CheckWikiHealth extends CLIApp
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->jsonOutput) {
|
||||
if ($this->getArgument("--json", false)) {
|
||||
echo json_encode([
|
||||
'repo' => "{$owner}/{$repo}",
|
||||
'pages' => $pageCount,
|
||||
@@ -153,4 +148,5 @@ class CheckWikiHealth extends CLIApp
|
||||
}
|
||||
}
|
||||
|
||||
(new CheckWikiHealth())->execute();
|
||||
$app = new CheckWikiHealth();
|
||||
exit($app->execute());
|
||||
|
||||
Reference in New Issue
Block a user