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>
252 lines
8.5 KiB
PHP
252 lines
8.5 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/version_reset_dev.php
|
|
* BRIEF: Reset platform version to 'development' on a branch via Gitea API
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../lib/Enterprise/CliFramework.php';
|
|
|
|
use MokoEnterprise\CliFramework;
|
|
|
|
class VersionResetDevCli extends CliFramework
|
|
{
|
|
protected function configure(): void
|
|
{
|
|
$this->setDescription('Reset platform version to development on a branch via Gitea API');
|
|
$this->addArgument('--token', 'Gitea API token (also reads MOKOGITEA_TOKEN / GITEA_TOKEN env)', '');
|
|
$this->addArgument('--api-base', 'Gitea API base URL for the repo', '');
|
|
$this->addArgument('--branch', 'Target branch (default: dev)', 'dev');
|
|
$this->addArgument('--platform', 'Platform type: dolibarr, crm-module, joomla, waas-component', '');
|
|
$this->addArgument('--path', 'Repo root for auto-detecting platform from manifest.xml', '');
|
|
}
|
|
|
|
protected function run(): int
|
|
{
|
|
$token = $this->getArgument('--token');
|
|
$apiBase = $this->getArgument('--api-base');
|
|
$branch = $this->getArgument('--branch');
|
|
$platform = $this->getArgument('--platform');
|
|
$path = $this->getArgument('--path');
|
|
|
|
// Allow token from environment
|
|
if ($token === '') {
|
|
$envToken = getenv('MOKOGITEA_TOKEN');
|
|
if ($envToken !== false && $envToken !== '') {
|
|
$token = $envToken;
|
|
}
|
|
}
|
|
if ($token === '') {
|
|
$envToken = getenv('GITEA_TOKEN');
|
|
if ($envToken !== false && $envToken !== '') {
|
|
$token = $envToken;
|
|
}
|
|
}
|
|
|
|
if ($token === '' || $apiBase === '') {
|
|
$this->log('ERROR', '--token and --api-base are required.');
|
|
return 1;
|
|
}
|
|
|
|
$apiBase = rtrim($apiBase, '/');
|
|
|
|
// ── Platform detection ───────────────────────────────────────────────────────
|
|
|
|
if ($platform === '' && $path !== '') {
|
|
$platform = $this->detectPlatform($path) ?? '';
|
|
if ($platform !== '') {
|
|
echo "Detected platform: {$platform}\n";
|
|
}
|
|
}
|
|
|
|
if ($platform === '') {
|
|
$this->log('ERROR', 'Could not determine platform. Use --platform or --path.');
|
|
return 1;
|
|
}
|
|
|
|
// ── Dispatch by platform ─────────────────────────────────────────────────────
|
|
|
|
$changed = 0;
|
|
|
|
if (in_array($platform, ['dolibarr', 'crm-module'], true)) {
|
|
$changed = $this->resetDolibarrVersion($apiBase, $token, $branch);
|
|
} elseif (in_array($platform, ['joomla', 'waas-component'], true)) {
|
|
echo "Joomla version reset is not yet implemented — skipping.\n";
|
|
} else {
|
|
echo "Platform '{$platform}' has no version-reset logic — skipping.\n";
|
|
}
|
|
|
|
echo "Reset {$changed} file(s) to 'development' on branch '{$branch}'.\n";
|
|
return 0;
|
|
}
|
|
|
|
private function detectPlatform(string $repoPath): ?string
|
|
{
|
|
$root = realpath($repoPath) ?: $repoPath;
|
|
$manifestXml = "{$root}/.mokogitea/manifest.xml";
|
|
|
|
if (!file_exists($manifestXml)) {
|
|
return null;
|
|
}
|
|
|
|
$xml = @simplexml_load_file($manifestXml);
|
|
if ($xml === false) {
|
|
return null;
|
|
}
|
|
|
|
if (isset($xml->governance->platform)) {
|
|
$platform = (string) $xml->governance->platform;
|
|
if ($platform !== '') {
|
|
return $platform;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function giteaApiCall(string $url, string $token, string $method = 'GET', ?string $body = null): ?array
|
|
{
|
|
$ch = curl_init($url);
|
|
if ($ch === false) {
|
|
$this->log('ERROR', "curl_init() failed for {$url}");
|
|
return null;
|
|
}
|
|
|
|
$headers = [
|
|
"Authorization: token {$token}",
|
|
'Accept: application/json',
|
|
];
|
|
if ($body !== null) {
|
|
$headers[] = 'Content-Type: application/json';
|
|
}
|
|
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_HTTPHEADER => $headers,
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_CUSTOMREQUEST => $method,
|
|
]);
|
|
|
|
if ($body !== null) {
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
|
|
}
|
|
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($httpCode < 200 || $httpCode >= 300 || !is_string($response) || $response === '') {
|
|
return null;
|
|
}
|
|
|
|
$data = json_decode($response, true);
|
|
if (!is_array($data)) {
|
|
return null;
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function resetDolibarrVersion(string $apiBase, string $token, string $branch): int
|
|
{
|
|
// Search the repo tree for mod*.class.php files
|
|
$treeUrl = "{$apiBase}/git/trees/{$branch}?recursive=true";
|
|
$tree = $this->giteaApiCall($treeUrl, $token);
|
|
|
|
if ($tree === null || !isset($tree['tree']) || !is_array($tree['tree'])) {
|
|
$this->log('ERROR', "Could not read repository tree for branch '{$branch}'.");
|
|
return 0;
|
|
}
|
|
|
|
// Find candidate files: mod*.class.php anywhere in the tree
|
|
$candidates = [];
|
|
foreach ($tree['tree'] as $entry) {
|
|
if (!isset($entry['path']) || !is_string($entry['path'])) {
|
|
continue;
|
|
}
|
|
$basename = basename($entry['path']);
|
|
if (preg_match('/^mod[A-Za-z0-9_]+\.class\.php$/', $basename)) {
|
|
$candidates[] = $entry['path'];
|
|
}
|
|
}
|
|
|
|
if (empty($candidates)) {
|
|
echo "No mod*.class.php files found on branch '{$branch}'.\n";
|
|
return 0;
|
|
}
|
|
|
|
$changed = 0;
|
|
|
|
foreach ($candidates as $filePath) {
|
|
// GET file contents via API
|
|
$encodedPath = implode('/', array_map('rawurlencode', explode('/', $filePath)));
|
|
$fileUrl = "{$apiBase}/contents/{$encodedPath}?ref={$branch}";
|
|
$fileData = $this->giteaApiCall($fileUrl, $token);
|
|
|
|
if ($fileData === null || !isset($fileData['content'])) {
|
|
echo "Skipping {$filePath}: could not fetch contents.\n";
|
|
continue;
|
|
}
|
|
|
|
// Decode base64 content
|
|
$rawContent = is_string($fileData['content']) ? $fileData['content'] : '';
|
|
$content = base64_decode($rawContent, true);
|
|
if ($content === false) {
|
|
echo "Skipping {$filePath}: could not decode content.\n";
|
|
continue;
|
|
}
|
|
|
|
// Verify this file extends DolibarrModules
|
|
if (!str_contains($content, 'extends DolibarrModules')) {
|
|
continue;
|
|
}
|
|
|
|
// Replace $this->version = '...' with $this->version = 'development'
|
|
$updated = preg_replace(
|
|
'/(\$this->version\s*=\s*)[\'"][^\'"]*[\'"]/',
|
|
"\${1}'development'",
|
|
$content
|
|
);
|
|
|
|
if ($updated === null || $updated === $content) {
|
|
echo "Skipping {$filePath}: no version change needed.\n";
|
|
continue;
|
|
}
|
|
|
|
// PUT updated content back via API
|
|
$sha = $fileData['sha'] ?? '';
|
|
$putBody = json_encode([
|
|
'content' => base64_encode($updated),
|
|
'message' => 'chore(version): reset dev version [skip ci]',
|
|
'branch' => $branch,
|
|
'sha' => $sha,
|
|
]);
|
|
|
|
$putUrl = "{$apiBase}/contents/{$encodedPath}";
|
|
$result = $this->giteaApiCall($putUrl, $token, 'PUT', $putBody);
|
|
|
|
if ($result !== null) {
|
|
echo "Reset: {$filePath} -> \$this->version = 'development'\n";
|
|
$changed++;
|
|
} else {
|
|
$this->log('ERROR', "Failed to update {$filePath} on branch '{$branch}'.");
|
|
}
|
|
}
|
|
|
|
return $changed;
|
|
}
|
|
}
|
|
|
|
$app = new VersionResetDevCli();
|
|
exit($app->execute());
|