#!/usr/bin/env php * * SPDX-License-Identifier: GPL-3.0-or-later * * FILE INFORMATION * DEFGROUP: MokoPlatform.Validate * INGROUP: MokoPlatform * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform * PATH: /validate/check_wiki_health.php * BRIEF: Validate wiki health — checks Home page exists, has moko-platform link, pages are indexed */ declare(strict_types=1); require_once __DIR__ . '/../vendor/autoload.php'; use MokoEnterprise\CliFramework; /** * Wiki Health Checker * * Validates Gitea wiki structure and content for a repository, * checking for required pages, broken links, and formatting issues. * * @since 04.00.00 */ class CheckWikiHealth extends CliFramework { protected function configure(): void { $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->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'; $remote = ''; if (is_file($configFile)) { $config = file_get_contents($configFile); if (preg_match('/url\s*=\s*(.+)/', $config, $m)) { $remote = trim($m[1]); } } if (empty($remote)) { $this->log('Cannot determine git remote — skipping wiki check', 'WARNING'); return 0; } // Parse owner/repo from remote URL if (preg_match('#[:/]([^/]+)/([^/.]+?)(?:\.git)?$#', $remote, $m)) { $owner = $m[1]; $repo = $m[2]; } else { $this->log("Cannot parse owner/repo from remote: {$remote}", 'WARNING'); return 0; } $this->log("Checking wiki: {$owner}/{$repo}"); $issues = 0; // Check wiki pages via API $apiUrl = "{$giteaUrl}/api/v1/repos/{$owner}/{$repo}/wiki/pages"; $headers = $token ? ["Authorization: token {$token}"] : []; $pages = $this->apiGet($apiUrl, $headers); if ($pages === null) { $this->log(' No wiki found or API error', 'WARNING'); $issues++; if ($this->getArgument("--json", false)) { echo json_encode(['status' => 'no_wiki', 'issues' => $issues]); } return 0; } $pageCount = count($pages); $this->log(" Found {$pageCount} wiki page(s)"); // Check Home exists $hasHome = false; $pageTitles = []; foreach ($pages as $page) { $title = $page['title'] ?? ''; $pageTitles[] = $title; if (strtolower($title) === 'home') { $hasHome = true; } } if (!$hasHome) { $this->log(' FAIL: No Home page', 'ERROR'); $issues++; } else { $this->log(' OK: Home page exists'); } // Check Home has moko-platform link if ($hasHome) { $homeUrl = "{$giteaUrl}/api/v1/repos/{$owner}/{$repo}/wiki/page/Home"; $home = $this->apiGet($homeUrl, $headers); if ($home) { $content = base64_decode($home['content_base64'] ?? ''); if (stripos($content, 'moko-platform/wiki') !== false || stripos($content, 'moko-platform') !== false) { $this->log(' OK: Has moko-platform reference'); } else { $this->log(' WARN: Home page missing moko-platform reference', 'WARNING'); $issues++; } } } if ($this->getArgument("--json", false)) { echo json_encode([ 'repo' => "{$owner}/{$repo}", 'pages' => $pageCount, 'has_home' => $hasHome, 'issues' => $issues, 'page_titles' => $pageTitles, ], JSON_PRETTY_PRINT); } return $issues > 0 ? 1 : 0; } private function apiGet(string $url, array $headers = []): ?array { $ctx = stream_context_create([ 'http' => [ 'method' => 'GET', 'header' => array_merge(['Accept: application/json'], $headers), 'timeout' => 10, 'ignore_errors' => true, ], 'ssl' => ['verify_peer' => false], ]); $response = @file_get_contents($url, false, $ctx); if ($response === false) { return null; } $data = json_decode($response, true); return is_array($data) ? $data : null; } } $app = new CheckWikiHealth(); exit($app->execute());