feat(workflow-sync): add --phase health drift detection + --repo-filter [#350] #358

Merged
jmiller merged 2 commits from feature/workflow-health-check into main 2026-07-17 00:09:37 +00:00
39 changed files with 356 additions and 41 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
# FILE INFORMATION
# DEFGROUP: MokoGIT.Workflow
# INGROUP: MokoCLI.Automation
# VERSION: 01.00.00
# VERSION: 09.45.01
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
+4
View File
@@ -13,6 +13,10 @@ BRIEF: Release changelog
## [Unreleased]
### Added
- `workflow_sync.php`: `--phase health` — read-only drift detection that flags repos missing their synced `.mokogit/workflows/`, with a non-zero exit plus optional critical ntfy push (`--alert-ntfy`) and auto-filed Git issue (`--alert-issue`).
- `workflow_sync.php`: `--repo-filter` to scope sync/health to specific repos.
## [09.42.00] --- 2026-07-04
### Fixed
+1 -1
View File
@@ -6,7 +6,7 @@ DEFGROUP: MokoCLI.Root
INGROUP: MokoCLI
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
PATH: /README.md
VERSION: 09.45.00
VERSION: 09.45.01
BRIEF: Project overview and documentation
-->
+1
View File
@@ -185,6 +185,7 @@ const COMMAND_MAP = [
// Bulk operations
'bulk:push-workflow' => 'cli/bulk_workflow_push.php',
'bulk:trigger' => 'cli/bulk_workflow_trigger.php',
'workflow:sync' => 'cli/workflow_sync.php',
'bulk:sync-rulesets' => 'cli/sync_rulesets.php',
'bulk:push-files' => 'automation/push_files.php',
'bulk:push-manifest' => 'automation/push_manifest_xml.php',
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/branch_rename.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Rename a git branch via Git API (create new, update PR, delete old)
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/bulk_workflow_push.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Push a workflow file to all governed repos via the Git Contents API
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/bulk_workflow_trigger.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Trigger a workflow across multiple repos at once
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/client_dashboard.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Generate unified client dashboard HTML
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/client_inventory.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Discover and list all client-waas repos with their server configuration status
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/client_provision.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Provision a new client environment end-to-end
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/grafana_dashboard.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Manage Grafana dashboards via API
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/joomla_build.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Build a Joomla extension ZIP from manifest — all types supported
* NOTE: Called by pre-release and auto-release workflows.
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/joomla_metadata_validate.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Validate MokoGIT repo metadata against Joomla extension manifest XML
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/manifest_detect.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Auto-detect manifest fields from source files and optionally push to API
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/manifest_integrity.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Cross-check manifest API fields against repo contents across the org
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/manifest_licensing.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Ensure licensing tags (updateservers, dlid) in Joomla extension manifests
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/manifest_read.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Read repo metadata from Git manifest API, auto-detect the rest
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/platform_detect.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Auto-detect repository platform type and optionally update manifest
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/release_cascade.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Cascade release zip to all lower stability channels
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/release_publish.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Publish a release and create copies for all lesser stability streams.
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/scaffold_client.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Scaffold a new client-waas repo from Template-Client with pre-configured settings
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/updates_xml_sync.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Sync updates.xml to target branches via Git API
* NOTE: Called by pre-release and auto-release workflows after updates.xml
* is modified on the current branch. Pushes the file to other branches
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/version_auto_bump.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Auto patch-bump, set stability suffix, and commit — single CLI replacing inline workflow bash
*/
+1 -1
View File
@@ -389,7 +389,7 @@ class VersionBumpCli extends CliFramework
/**
* Scan git release tags for the highest version across all channels.
*
* Checks release names like "MokoSuiteClient (VERSION: 09.45.00)" in
* Checks release names like "MokoSuiteClient (VERSION: 09.45.01)" in
* git tags (stable, release-candidate, development, etc.) to find the
* highest version that has been released on any channel.
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/version_check.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Validate version consistency across README, manifests, and sub-packages
*/
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/wiki_sync.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Sync select wiki pages from mokocli to all template repos
*/
+314 -4
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/workflow_sync.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Sync workflows from Generic → platform templates → live repos based on manifest.platform
*/
@@ -59,6 +59,13 @@ class WorkflowSyncCli extends CliFramework
/** Prefix for custom workflows preserved during orphan cleanup. */
private const CUSTOM_PREFIX = 'custom-';
/** Default ntfy endpoint for critical drift alerts (matches notify.yml / gitleaks.yml). */
private const DEFAULT_NTFY_URL = 'https://ntfy.mokoconsulting.tech';
private const DEFAULT_NTFY_TOPIC = 'mokogit-ops';
/** Marker in auto-filed health issues, used for idempotency. */
private const HEALTH_ISSUE_MARKER = '[workflow-health]';
private int $updated = 0;
private int $created = 0;
private int $skipped = 0;
@@ -72,9 +79,16 @@ class WorkflowSyncCli extends CliFramework
$this->addArgument('--token', 'Git API token', '');
$this->addArgument('--org', 'Target organization', '');
$this->addArgument('--branch', 'Target branch (default: main)', 'main');
$this->addArgument('--phase', 'Phase to run: all, templates, repos (default: all)', 'all');
$this->addArgument('--phase', 'Phase to run: all, templates, repos, health (default: all)', 'all');
$this->addArgument('--platform-filter', 'Only sync repos matching this platform', '');
$this->addArgument('--repo-filter', 'Only sync/check these repos (comma-separated names)', '');
$this->addArgument('--delete-orphans', 'Delete workflows not in template (preserves custom-* and custom/)', false);
// Health-check (--phase health) options — read-only unless an alert flag is set.
$this->addArgument('--alert-ntfy', 'On drift, send a critical ntfy push notification', false);
$this->addArgument('--ntfy-url', 'ntfy server URL', self::DEFAULT_NTFY_URL);
$this->addArgument('--ntfy-topic', 'ntfy topic', self::DEFAULT_NTFY_TOPIC);
$this->addArgument('--alert-issue', 'On drift, open/update a Git issue on each affected repo', false);
}
protected function run(): int
@@ -96,11 +110,16 @@ class WorkflowSyncCli extends CliFramework
return 1;
}
if (!in_array($phase, ['all', 'templates', 'repos'], true)) {
$this->log('ERROR', "--phase must be one of: all, templates, repos (got: {$phase})");
if (!in_array($phase, ['all', 'templates', 'repos', 'health'], true)) {
$this->log('ERROR', "--phase must be one of: all, templates, repos, health (got: {$phase})");
return 1;
}
// Health-check is a standalone, read-only phase — it never syncs.
if ($phase === 'health') {
return $this->runHealthCheck($gitUrl, $token, $org, $branch, $platformFilter);
}
$this->log('INFO', "Workflow Sync — org: {$org}, branch: {$branch}, phase: {$phase}");
if ($platformFilter !== '') {
@@ -240,6 +259,12 @@ class WorkflowSyncCli extends CliFramework
$this->log('INFO', '=== Phase 2: Sync Platform Templates → Live Repos ===');
echo "\n";
$repoFilter = $this->parseRepoFilter();
if ($repoFilter !== []) {
$this->log('INFO', 'Repo filter: ' . implode(', ', $repoFilter));
}
$repos = $this->fetchOrgRepos($gitUrl, $token, $org);
if ($repos === null) {
@@ -263,6 +288,11 @@ class WorkflowSyncCli extends CliFramework
continue;
}
// Apply repo filter
if ($repoFilter !== [] && !in_array($repoName, $repoFilter, true)) {
continue;
}
// Read manifest.platform
$platform = $this->getRepoPlatform($gitUrl, $token, $org, $repoName, $branch);
@@ -692,6 +722,286 @@ class WorkflowSyncCli extends CliFramework
return $repos;
}
// =========================================================================
// Phase: health — read-only drift detection + alerting
// =========================================================================
/**
* Parse --repo-filter into a list of repo names (empty ⇒ no filter).
*
* @return string[]
*/
private function parseRepoFilter(): array
{
$raw = (string) $this->getArgument('--repo-filter');
return array_values(array_filter(array_map('trim', explode(',', $raw)), fn($n) => $n !== ''));
}
/**
* Health-check phase: verify every live repo still has the synced workflows its
* platform template provides, and (optionally) alert on drift. Fails loudly
* (non-zero exit) when a repo is missing its canonical set, so a scheduled job,
* an ntfy push, and/or a Git issue surface silent loss instead of it rotting.
*/
private function runHealthCheck(
string $gitUrl,
string $token,
string $org,
string $branch,
string $platformFilter
): int {
$alertNtfy = (bool) $this->getArgument('--alert-ntfy');
$alertIssue = (bool) $this->getArgument('--alert-issue');
$ntfyUrl = rtrim((string) $this->getArgument('--ntfy-url'), '/');
$ntfyTopic = (string) $this->getArgument('--ntfy-topic');
$repoFilter = $this->parseRepoFilter();
$this->log('INFO', "Workflow Health-Check — org: {$org}, branch: {$branch}");
if ($platformFilter !== '') {
$this->log('INFO', "Platform filter: {$platformFilter}");
}
if ($repoFilter !== []) {
$this->log('INFO', 'Repo filter: ' . implode(', ', $repoFilter));
}
echo "\n";
$repos = $this->fetchOrgRepos($gitUrl, $token, $org);
if ($repos === null) {
return self::EXIT_FAILURE;
}
$this->log('INFO', 'Scanning ' . count($repos) . " repo(s) in \"{$org}\".");
echo "\n";
$templateCache = [];
$unhealthy = [];
$checked = 0;
foreach ($repos as $repoFullName) {
[, $repoName] = explode('/', $repoFullName, 2);
if (str_starts_with($repoName, 'Template-')) {
continue;
}
$platform = $this->getRepoPlatform($gitUrl, $token, $org, $repoName, $branch);
if ($platformFilter !== '' && $platform !== $platformFilter) {
continue;
}
if ($repoFilter !== [] && !in_array($repoName, $repoFilter, true)) {
continue;
}
// A repo that has no such branch is out of scope for this run, not unhealthy.
if (!$this->branchExists($gitUrl, $token, $org, $repoName, $branch)) {
continue;
}
$templateRepo = self::PLATFORM_TEMPLATES[$platform] ?? self::DEFAULT_TEMPLATE;
// Expected set = the template's workflows (cached), minus platform excludes.
// Do NOT fall back to Generic on an unreachable template — that assesses against
// the wrong baseline. Record null (missing) distinctly.
if (!array_key_exists($templateRepo, $templateCache)) {
$tpl = $this->listWorkflows($gitUrl, $token, $org, $templateRepo, $branch);
$templateCache[$templateRepo] = $tpl === null
? null
: array_map(fn($w) => $w['name'], $tpl);
}
if ($templateCache[$templateRepo] === null) {
$this->log('WARN', "Template '{$templateRepo}' for platform '{$platform}' is unreachable"
. " — cannot assess {$repoName}.");
continue;
}
$expected = array_values(array_diff(
$templateCache[$templateRepo],
self::PLATFORM_EXCLUDES[$platform] ?? []
));
if (count($expected) === 0) {
continue;
}
$repoList = $this->listWorkflows($gitUrl, $token, $org, $repoName, $branch);
$actual = array_map(fn($w) => $w['name'], $repoList ?? []);
$missing = $this->evaluateRepoHealth($expected, $actual);
$checked++;
if (count($missing) > 0) {
$unhealthy[$repoName] = [
'full' => $repoFullName,
'platform' => $platform,
'expected' => count($expected),
'present' => count(array_intersect($expected, $actual)),
'missing' => $missing,
];
}
}
echo "\n";
if (count($unhealthy) === 0) {
$this->success("All {$checked} in-scope repo(s) have their synced workflows on '{$branch}'.");
return self::EXIT_SUCCESS;
}
$rows = [];
foreach ($unhealthy as $repo => $info) {
$rows[] = [$repo, $info['platform'], "{$info['present']}/{$info['expected']}", (string) count($info['missing'])];
}
$this->log('ERROR', count($unhealthy) . " of {$checked} repo(s) are MISSING synced workflows on '{$branch}':");
$this->table(['Repo', 'Platform', 'Present', 'Missing'], $rows);
if ($alertNtfy) {
$this->sendNtfyAlert($ntfyUrl, $ntfyTopic, $org, $branch, $unhealthy);
}
if ($alertIssue) {
foreach ($unhealthy as $repo => $info) {
$this->openHealthIssue($gitUrl, $token, $org, $repo, $branch, $info);
}
}
return self::EXIT_FAILURE;
}
/**
* Health verdict policy — given the workflows a repo SHOULD have (its platform
* template's set, minus excludes) and what it ACTUALLY has, return the missing
* filenames. Non-empty ⇒ unhealthy. Extra/custom files are ignored.
*
* @param string[] $expected
* @param string[] $actual
* @return string[]
*/
private function evaluateRepoHealth(array $expected, array $actual): array
{
return array_values(array_diff($expected, $actual));
}
/**
* Return true when the given branch exists in the repo.
*/
private function branchExists(
string $gitUrl,
string $token,
string $org,
string $repoName,
string $branch
): bool {
$response = $this->apiRequest($gitUrl, $token, 'GET', "/api/v1/repos/{$org}/{$repoName}/branches/{$branch}");
return $response['code'] === 200;
}
/**
* Send a critical ntfy push notification about drift (matches notify.yml headers).
*/
private function sendNtfyAlert(
string $ntfyUrl,
string $topic,
string $org,
string $branch,
array $unhealthy
): void {
if ($ntfyUrl === '' || $topic === '') {
$this->warn('ntfy alert requested but --ntfy-url/--ntfy-topic is empty; skipping.');
return;
}
$count = count($unhealthy);
$names = implode(', ', array_keys($unhealthy));
$title = "Workflow drift: {$count} repo(s) missing workflows";
$body = "Org {$org} ({$branch}): {$count} repo(s) missing synced .mokogit/workflows/.\n{$names}";
if ($this->dryRun) {
$this->log('INFO', "[DRY RUN] Would send critical ntfy to {$ntfyUrl}/{$topic}: {$title}");
return;
}
$ch = curl_init("{$ntfyUrl}/{$topic}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Title: {$title}",
'Priority: urgent',
'Tags: rotating_light,warning',
]);
curl_exec($ch);
$code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code >= 200 && $code < 300) {
$this->success("Sent critical ntfy alert to {$ntfyUrl}/{$topic}.");
} else {
$this->warn("ntfy alert failed (HTTP {$code}).");
}
}
/**
* Open a Git issue on an affected repo describing the missing workflows.
* Idempotent: skips if an open issue carrying the marker already exists.
*/
private function openHealthIssue(
string $gitUrl,
string $token,
string $org,
string $repoName,
string $branch,
array $info
): void {
$existing = $this->apiRequest(
$gitUrl, $token, 'GET',
"/api/v1/repos/{$org}/{$repoName}/issues?state=open&type=issues&limit=50"
);
if ($existing['code'] === 200) {
$issues = json_decode($existing['body'], true) ?: [];
foreach ($issues as $iss) {
if (str_contains((string) ($iss['title'] ?? ''), self::HEALTH_ISSUE_MARKER)) {
$this->log('INFO', "{$repoName}: health issue already open (#{$iss['number']}), skipping.");
return;
}
}
}
$missingList = implode("\n", array_map(fn($f) => "- `{$f}`", $info['missing']));
$title = self::HEALTH_ISSUE_MARKER . " Missing synced workflows on {$branch}";
$body = 'Automated health-check found this repository is missing '
. count($info['missing']) . " workflow(s) that its platform template "
. "(`{$info['platform']}`) provides in `.mokogit/workflows/` on `{$branch}`:\n\n"
. $missingList
. "\n\nRestore with:\n\n```\nphp bin/moko workflow:sync --org {$org} --branch {$branch} --token \$TOKEN\n```"
. "\n\n<sub>Filed by workflow_sync.php --phase health.</sub>";
if ($this->dryRun) {
$this->log('INFO', "[DRY RUN] Would open health issue on {$org}/{$repoName}.");
return;
}
$payload = json_encode(['title' => $title, 'body' => $body]);
$resp = $this->apiRequest($gitUrl, $token, 'POST', "/api/v1/repos/{$org}/{$repoName}/issues", $payload);
if ($resp['code'] === 201) {
$data = json_decode($resp['body'], true);
$this->success("Opened health issue {$org}/{$repoName}#" . ($data['number'] ?? '?') . '.');
} else {
$this->warn("Failed to open issue on {$org}/{$repoName} (HTTP {$resp['code']}).");
}
}
/**
* Make an HTTP request to the Git API.
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoCLI
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/backup-before-deploy.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Snapshot Joomla directories before deployment for rollback capability
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoCLI
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/deploy-dolibarr.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Deploy Dolibarr module files to a remote server via SFTP/rsync
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoCLI
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/health-check.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Post-deploy health check — verify a Joomla site is responding correctly
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoCLI
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/rollback-joomla.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Rollback a Joomla deployment by restoring from a pre-deploy snapshot
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoCLI
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/sync-joomla.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Sync Joomla site directories between two servers via rsync over SSH
*/
+1 -1
View File
@@ -14,7 +14,7 @@
DEFGROUP: dolibarr-api-mcp.Documentation
INGROUP: dolibarr-api-mcp
REPO: https://git.mokoconsulting.tech/MokoConsulting/dolibarr-api-mcp
VERSION: 09.45.00
VERSION: 09.45.01
PATH: ./CONTRIBUTING.md
BRIEF: Contribution guidelines for the project
-->
+1 -1
View File
@@ -10,7 +10,7 @@ DEFGROUP: dolibarr-api-mcp.Documentation
INGROUP: dolibarr-api-mcp
REPO: https://git.mokoconsulting.tech/MokoConsulting/dolibarr-api-mcp
PATH: /SECURITY.md
VERSION: 09.45.00
VERSION: 09.45.01
BRIEF: Security vulnerability reporting and handling policy
-->
+1 -1
View File
@@ -14,7 +14,7 @@
DEFGROUP:
INGROUP: Project.Documentation
REPO: https://git.mokoconsulting.tech/MokoConsulting/MokoCli-Template-Generic
VERSION: 09.45.00
VERSION: 09.45.01
PATH: ./CONTRIBUTING.md
BRIEF: Contribution guidelines for the project
-->
+1 -1
View File
@@ -23,7 +23,7 @@ DEFGROUP: [PROJECT_NAME]
INGROUP: [PROJECT_NAME].Documentation
REPO: [REPOSITORY_URL]
PATH: /SECURITY.md
VERSION: 09.45.00
VERSION: 09.45.01
BRIEF: Security vulnerability reporting and handling policy
-->
+1 -1
View File
@@ -63,7 +63,7 @@ class VersionBumpTest extends TestCase
{
file_put_contents(
"{$this->tmpDir}/README.md",
"<!-- VERSION: 09.45.00 -->\nSome content\n"
"<!-- VERSION: 09.45.01 -->\nSome content\n"
);
$this->execute();
+2 -2
View File
@@ -34,7 +34,7 @@ class VersionReadTest extends TestCase
{
file_put_contents(
"{$this->tmpDir}/README.md",
"# Test\n<!-- VERSION: 09.45.00 -->\n"
"# Test\n<!-- VERSION: 09.45.01 -->\n"
);
$this->assertSame('02.03.04', trim($this->runScript()));
@@ -68,7 +68,7 @@ class VersionReadTest extends TestCase
{
file_put_contents(
"{$this->tmpDir}/README.md",
"<!-- VERSION: 09.45.00 -->\n"
"<!-- VERSION: 09.45.01 -->\n"
);
mkdir("{$this->tmpDir}/src", 0755, true);
file_put_contents(
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoCLI
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /validate/check_file_integrity.php
* VERSION: 09.45.00
* VERSION: 09.45.01
* BRIEF: Compare deployed files on a remote server against the local repository to detect drift
*/