7b863f690d
Updated ~60 files: comments, usage docs, SCRIPT_PATH constants, wrapper paths, require paths, error messages, and help text. All api/validate/ → validate/, api/automation/ → automation/, etc. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
187 lines
5.8 KiB
PHP
187 lines
5.8 KiB
PHP
#!/usr/bin/env php
|
|
<?php
|
|
/* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
|
|
*
|
|
* This file is part of a Moko Consulting project.
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*
|
|
* FILE INFORMATION
|
|
* DEFGROUP: MokoStandards.Scripts.Validate
|
|
* INGROUP: MokoStandards
|
|
* REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoStandards-API
|
|
* PATH: /validate/check_composer_deps.php
|
|
* VERSION: 04.06.00
|
|
* BRIEF: Validate composer.json enterprise dependency across all governed repos
|
|
*
|
|
* USAGE
|
|
* php validate/check_composer_deps.php --repo MokoCRM # Single repo
|
|
* php validate/check_composer_deps.php --all # All repos
|
|
* php validate/check_composer_deps.php --all --json # JSON output
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
$allMode = in_array('--all', $argv);
|
|
$jsonOut = in_array('--json', $argv);
|
|
|
|
$org = 'mokoconsulting-tech';
|
|
$repoName = null;
|
|
|
|
foreach ($argv as $i => $arg) {
|
|
if ($arg === '--repo' && isset($argv[$i + 1])) { $repoName = $argv[$i + 1]; }
|
|
if ($arg === '--org' && isset($argv[$i + 1])) { $org = $argv[$i + 1]; }
|
|
}
|
|
|
|
if (!$repoName && !$allMode) {
|
|
fwrite(STDERR, "Usage: php check_composer_deps.php --repo <name> | --all [--json]\n");
|
|
exit(2);
|
|
}
|
|
|
|
$config = \MokoEnterprise\Config::load();
|
|
try {
|
|
$_adapter = \MokoEnterprise\PlatformAdapterFactory::create($config);
|
|
$_api = $_adapter->getApiClient();
|
|
} catch (\Exception $e) {
|
|
fwrite(STDERR, "Platform init failed: " . $e->getMessage() . "\n");
|
|
exit(1);
|
|
}
|
|
$token = $config->getString('platform', 'gitea') === 'gitea'
|
|
? $config->getString('gitea.token', '')
|
|
: $config->getString('github.token', '');
|
|
|
|
$EXPECTED_VERSION = '04.02.30';
|
|
$EXPECTED_DEP = "dev-version/{$EXPECTED_VERSION}";
|
|
$ENTERPRISE_PKG = 'mokoconsulting-tech/enterprise';
|
|
$ALWAYS_EXCLUDE = ['MokoStandards', '.github-private'];
|
|
|
|
/**
|
|
* GitHub REST API GET helper.
|
|
*
|
|
* @return array{int, array<string, mixed>}
|
|
*/
|
|
function apiGet(string $path, string $token): array
|
|
{
|
|
global $_api;
|
|
try {
|
|
$result = $_api->get("/{$path}");
|
|
return [200, $result];
|
|
} catch (\Exception $e) {
|
|
return [500, ['message' => $e->getMessage()]];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch and parse composer.json from a repo.
|
|
*
|
|
* @return array<string, mixed>|null
|
|
*/
|
|
function fetchComposer(string $org, string $repo, string $token): ?array
|
|
{
|
|
[$status, $data] = apiGet("repos/{$org}/{$repo}/contents/composer.json", $token);
|
|
if ($status !== 200 || empty($data['content'])) { return null; }
|
|
return json_decode(base64_decode($data['content']), true);
|
|
}
|
|
|
|
// ── Build repo list ─────────────────────────────────────────────────────
|
|
$repos = [];
|
|
if ($allMode) {
|
|
echo "Fetching repositories from {$org}...\n";
|
|
$page = 1;
|
|
do {
|
|
[$_, $batch] = apiGet("orgs/{$org}/repos?per_page=100&page={$page}&type=all", $token);
|
|
foreach ($batch as $r) {
|
|
if (!($r['archived'] ?? false) && !in_array($r['name'], $ALWAYS_EXCLUDE, true)) {
|
|
$repos[] = $r['name'];
|
|
}
|
|
}
|
|
$page++;
|
|
} while (count($batch) === 100);
|
|
sort($repos);
|
|
echo "Found " . count($repos) . " repositories\n\n";
|
|
} else {
|
|
$repos = [$repoName];
|
|
}
|
|
|
|
// ── Check each repo ─────────────────────────────────────────────────────
|
|
$results = [];
|
|
$issueCount = 0;
|
|
|
|
foreach ($repos as $repo) {
|
|
$result = [
|
|
'repo' => $repo,
|
|
'has_composer' => false,
|
|
'has_enterprise' => false,
|
|
'version' => null,
|
|
'version_ok' => false,
|
|
'has_lock' => false,
|
|
'issues' => [],
|
|
];
|
|
|
|
$composer = fetchComposer($org, $repo, $token);
|
|
if ($composer === null) {
|
|
$result['issues'][] = 'No composer.json found';
|
|
if (!$jsonOut) { echo "{$repo}: no composer.json\n"; }
|
|
$results[] = $result;
|
|
continue;
|
|
}
|
|
|
|
$result['has_composer'] = true;
|
|
|
|
// Check for enterprise dependency
|
|
$allDeps = array_merge($composer['require'] ?? [], $composer['require-dev'] ?? []);
|
|
|
|
if (isset($allDeps[$ENTERPRISE_PKG])) {
|
|
$result['has_enterprise'] = true;
|
|
$result['version'] = $allDeps[$ENTERPRISE_PKG];
|
|
|
|
if ($allDeps[$ENTERPRISE_PKG] === $EXPECTED_DEP) {
|
|
$result['version_ok'] = true;
|
|
} else {
|
|
$result['issues'][] = "Version mismatch: {$allDeps[$ENTERPRISE_PKG]} (expected {$EXPECTED_DEP})";
|
|
if ($allDeps[$ENTERPRISE_PKG] === 'dev-main') {
|
|
$result['issues'][] = 'STALE: pointing to dev-main instead of version branch';
|
|
}
|
|
}
|
|
} else {
|
|
$result['issues'][] = 'Enterprise dependency not in require/require-dev';
|
|
}
|
|
|
|
// Check for composer.lock
|
|
[$lockStatus] = apiGet("repos/{$org}/{$repo}/contents/composer.lock", $token);
|
|
$result['has_lock'] = ($lockStatus === 200);
|
|
if (!$result['has_lock']) {
|
|
$result['issues'][] = 'No composer.lock committed';
|
|
}
|
|
|
|
if (!$jsonOut) {
|
|
if (empty($result['issues'])) {
|
|
echo "{$repo}: OK ({$result['version']})\n";
|
|
} else {
|
|
foreach ($result['issues'] as $issue) {
|
|
echo "{$repo}: {$issue}\n";
|
|
$issueCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
$results[] = $result;
|
|
}
|
|
|
|
// ── Output ──────────────────────────────────────────────────────────────
|
|
if ($jsonOut) {
|
|
echo json_encode($results, JSON_PRETTY_PRINT) . "\n";
|
|
} else {
|
|
echo "\n" . str_repeat('-', 50) . "\n";
|
|
$total = count($results);
|
|
$withDep = count(array_filter($results, fn($r) => $r['has_enterprise']));
|
|
$ok = count(array_filter($results, fn($r) => $r['version_ok']));
|
|
$stale = count(array_filter($results, fn($r) => $r['version'] === 'dev-main'));
|
|
|
|
echo "Total: {$total} | With enterprise dep: {$withDep} | Correct version: {$ok}";
|
|
if ($stale > 0) { echo " | Stale dev-main: {$stale}"; }
|
|
echo " | Issues: {$issueCount}\n";
|
|
}
|
|
|
|
exit($issueCount > 0 ? 1 : 0);
|