diff --git a/.mokogitea/manifest.xml b/.mokogitea/manifest.xml index cbab803..a420f95 100644 --- a/.mokogitea/manifest.xml +++ b/.mokogitea/manifest.xml @@ -13,7 +13,7 @@ generic - 04.07.00 + 04.09.00 https://git.mokoconsulting.tech/MokoConsulting/moko-platform 2026-05-10T19:51:08+00:00 diff --git a/CHANGELOG.md b/CHANGELOG.md index cd4ce7b..7b9d626 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,30 @@ Version format: `XX.YY.ZZ` (zero-padded semver). ## [Unreleased] +## [04.09.00] - 2026-05-12 + +### Added +- `` section support in `.manifest.xml` schema: `source-dir`, `remote-subdir`, `excludes`, `dev-host`, `demo-host` +- `manifest_read.php` now parses all deploy fields for CI consumption + +### Changed +- Deploy workflows can now read deploy paths from manifest instead of guessing from directory structure + +## [04.08.00] - 2026-05-12 + +### Added +- `cli/manifest_read.php` -- full `.manifest.xml` parser for CI consumption + - Supports `--field`, `--all`, `--json`, and `--github-output` modes + - Backward-compatible with `.moko-platform` (XML) and `.mokostandards` (YAML) formats + - Replaces inline `sed` detection blocks in workflows + +### Changed +- Workflows (`auto-release`, `pre-release`, `pr-check`) now use `manifest_read.php` for platform detection +- `entry-point` field from manifest replaces `find` tree scan for mod file discovery +- Platform detection outputs all manifest fields to `GITHUB_OUTPUT` (name, org, language, package-type, etc.) + + + ## [05.00.00] - 2026-05-11 ### Added diff --git a/cli/manifest_read.php b/cli/manifest_read.php new file mode 100644 index 0000000..4e8a8ca --- /dev/null +++ b/cli/manifest_read.php @@ -0,0 +1,170 @@ +#!/usr/bin/env php + + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + * FILE INFORMATION + * DEFGROUP: MokoStandards.CLI + * INGROUP: MokoStandards + * REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform + * PATH: /cli/manifest_read.php + * VERSION: 04.09.00 + * BRIEF: Parse .manifest.xml and output requested field(s) for CI consumption + * + * Usage: + * php manifest_read.php --path /repo --field platform + * php manifest_read.php --path /repo --field entry-point + * php manifest_read.php --path /repo --all + * php manifest_read.php --path /repo --github-output + * + * Fields: name, org, description, license, license-spdx, platform, + * standards-version, standards-source, language, package-type, entry-point, + * source-dir, remote-subdir, excludes, dev-host, demo-host + * + * --all Print all fields as KEY=VALUE lines + * --github-output Append all fields to $GITHUB_OUTPUT (for Gitea/GitHub Actions) + * --json Output all fields as JSON + * --field Print a single field value (no key, just value) + */ + +declare(strict_types=1); + +// -- Argument parsing --------------------------------------------------------- +$path = '.'; +$field = null; +$mode = 'field'; // field | all | github-output | json + +foreach ($argv as $i => $arg) { + if ($arg === '--path' && isset($argv[$i + 1])) $path = $argv[$i + 1]; + if ($arg === '--field' && isset($argv[$i + 1])) $field = $argv[$i + 1]; + if ($arg === '--all') $mode = 'all'; + if ($arg === '--github-output') $mode = 'github-output'; + if ($arg === '--json') $mode = 'json'; +} + +// -- Locate manifest ---------------------------------------------------------- +$root = realpath($path) ?: $path; +$manifestFile = null; + +// Priority: .manifest.xml > .moko-platform (backward compat) +$candidates = [ + "{$root}/.mokogitea/.manifest.xml", + "{$root}/.mokogitea/.moko-platform", + "{$root}/.gitea/.mokostandards", // legacy v4 +]; + +foreach ($candidates as $candidate) { + if (file_exists($candidate)) { + $manifestFile = $candidate; + break; + } +} + +if ($manifestFile === null) { + fwrite(STDERR, "No manifest found in {$root} +"); + exit(1); +} + +// -- Parse XML ---------------------------------------------------------------- +$xml = @simplexml_load_file($manifestFile); + +if ($xml === false) { + // Fallback: try YAML format (.mokostandards legacy) + $content = file_get_contents($manifestFile); + $fields = []; + if (preg_match('/^platform:\s*(.+)/m', $content, $m)) { + $fields['platform'] = trim($m[1], " + \"'"); + } + if (preg_match('/^standards_version:\s*(.+)/m', $content, $m)) { + $fields['standards-version'] = trim($m[1], " + \"'"); + } + if (preg_match('/^governed_repo:\s*(.+)/m', $content, $m)) { + $fields['name'] = trim($m[1], " + \"'"); + } +} else { + // Register namespace for XPath (optional, simple path works without) + $fields = [ + 'name' => (string)($xml->identity->name ?? ''), + 'org' => (string)($xml->identity->org ?? ''), + 'description' => (string)($xml->identity->description ?? ''), + 'license' => (string)($xml->identity->license ?? ''), + 'license-spdx' => (string)($xml->identity->license['spdx'] ?? ''), + 'platform' => (string)($xml->governance->platform ?? ''), + 'standards-version' => (string)($xml->governance->{"standards-version"} ?? ''), + 'standards-source' => (string)($xml->governance->{"standards-source"} ?? ''), + 'language' => (string)($xml->build->language ?? ''), + 'package-type' => (string)($xml->build->{"package-type"} ?? ''), + 'entry-point' => (string)($xml->build->{"entry-point"} ?? ''), + 'source-dir' => (string)($xml->deploy->{"source-dir"} ?? ''), + 'remote-subdir' => (string)($xml->deploy->{"remote-subdir"} ?? ''), + 'excludes' => (string)($xml->deploy->excludes ?? ''), + 'dev-host' => (string)($xml->deploy->{"dev-host"} ?? ''), + 'demo-host' => (string)($xml->deploy->{"demo-host"} ?? ''), + 'manifest-file' => $manifestFile, + ]; +} + +// Strip empty values for cleaner output +$fields = array_filter($fields, fn($v) => $v !== ''); + +// -- Output ------------------------------------------------------------------- +switch ($mode) { + case 'field': + if ($field === null) { + fwrite(STDERR, "Usage: manifest_read.php --path --field +"); + fwrite(STDERR, " manifest_read.php --path --all +"); + fwrite(STDERR, " manifest_read.php --path --json +"); + fwrite(STDERR, " manifest_read.php --path --github-output +"); + exit(2); + } + echo ($fields[$field] ?? '') . " +"; + break; + + case 'all': + foreach ($fields as $k => $v) { + echo "{$k}={$v} +"; + } + break; + + case 'json': + echo json_encode($fields, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . " +"; + break; + + case 'github-output': + $outputFile = getenv('GITHUB_OUTPUT'); + if ($outputFile === false || $outputFile === '') { + fwrite(STDERR, "GITHUB_OUTPUT not set — printing to stdout instead +"); + foreach ($fields as $k => $v) { + // Convert field-name to FIELD_NAME for env var style + $envKey = str_replace('-', '_', $k); + echo "{$envKey}={$v} +"; + } + } else { + $fh = fopen($outputFile, 'a'); + foreach ($fields as $k => $v) { + $envKey = str_replace('-', '_', $k); + fwrite($fh, "{$envKey}={$v} +"); + } + fclose($fh); + fwrite(STDERR, "Wrote " . count($fields) . " fields to GITHUB_OUTPUT +"); + } + break; +} + +exit(0);