feat: delete orphan workflows during sync — preserve custom-* prefix #315

Merged
jmiller merged 4 commits from feature/delete-orphan-workflows into main 2026-06-23 21:49:40 +00:00
37 changed files with 165 additions and 41 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Automation
# VERSION: 01.00.00
# VERSION: 09.38.02
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
+1 -1
View File
@@ -6,7 +6,7 @@ DEFGROUP: MokoPlatform.Root
INGROUP: MokoPlatform
REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
PATH: /README.md
VERSION: 09.38.00
VERSION: 09.38.02
BRIEF: Project overview and documentation
-->
+1 -1
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/branch_rename.php
* VERSION: 09.38.00
* VERSION: 09.38.02
* BRIEF: Rename a git branch via Gitea 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.38.00
* VERSION: 09.38.02
* BRIEF: Push a workflow file to all governed repos via the Gitea 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* BRIEF: Validate MokoGitea 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* BRIEF: Read repo metadata from Gitea 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* BRIEF: Scaffold a new client-waas repo from Template-Client-WaaS 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.38.00
* VERSION: 09.38.02
* BRIEF: Sync updates.xml to target branches via Gitea 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.38.00
* VERSION: 09.38.02
* BRIEF: Auto patch-bump, set stability suffix, and commit — single CLI replacing inline workflow bash
*/
+1 -1
View File
@@ -370,7 +370,7 @@ class VersionBumpCli extends CliFramework
/**
* Scan git release tags for the highest version across all channels.
*
* Checks release names like "MokoSuiteClient (VERSION: 09.38.00)" in
* Checks release names like "MokoSuiteClient (VERSION: 09.38.02)" 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.38.00
* VERSION: 09.38.02
* 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.38.00
* VERSION: 09.38.02
* BRIEF: Sync select wiki pages from mokocli to all template repos
*/
+128 -4
View File
@@ -10,7 +10,7 @@
* INGROUP: mokocli
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /cli/workflow_sync.php
* VERSION: 09.38.00
* VERSION: 09.38.02
* BRIEF: Sync workflows from Generic → platform templates → live repos based on manifest.platform
*/
@@ -42,9 +42,13 @@ class WorkflowSyncCli extends CliFramework
'joomla' => ['deploy-manual.yml'],
];
/** Prefix for custom workflows preserved during orphan cleanup. */
private const CUSTOM_PREFIX = 'custom-';
private int $updated = 0;
private int $created = 0;
private int $skipped = 0;
private int $deleted = 0;
private int $errors = 0;
protected function configure(): void
@@ -56,6 +60,7 @@ class WorkflowSyncCli extends CliFramework
$this->addArgument('--branch', 'Target branch (default: main)', 'main');
$this->addArgument('--phase', 'Phase to run: all, templates, repos (default: all)', 'all');
$this->addArgument('--platform-filter', 'Only sync repos matching this platform', '');
$this->addArgument('--delete-orphans', 'Delete workflows not in template (preserves custom-* and custom/)', false);
}
protected function run(): int
@@ -114,7 +119,7 @@ class WorkflowSyncCli extends CliFramework
echo "\n";
$this->log('INFO', "Done: {$this->created} created, {$this->updated} updated, "
. "{$this->skipped} skipped, {$this->errors} error(s).");
. "{$this->deleted} deleted, {$this->skipped} skipped, {$this->errors} error(s).");
return $this->errors > 0 ? 1 : 0;
}
@@ -275,14 +280,15 @@ class WorkflowSyncCli extends CliFramework
foreach ($workflows as $workflow) {
$filename = $workflow['name'];
$destPath = '.mokogitea/workflows/' . $filename;
$label = "{$repoFullName}/{$filename}";
// Skip platform-excluded workflows
if (in_array($filename, self::PLATFORM_EXCLUDES[$platform] ?? [], true)) {
fprintf(STDERR, "%-45s | %s\n", $label, 'EXCLUDED (platform)');
$this->skipped++;
continue;
}
$destPath = '.mokogitea/workflows/' . $filename;
$label = "{$repoFullName}/{$filename}";
// Get source content from template
$sourceContent = $this->getFileContent(
@@ -303,6 +309,14 @@ class WorkflowSyncCli extends CliFramework
$destPath, $sourceContent, $branch, $commitMsg, $label
);
}
// Delete orphan workflows if enabled
if ($this->getArgument('--delete-orphans', false)) {
$templateNames = array_map(fn($w) => $w['name'], $workflows);
$this->deleteOrphanWorkflows(
$giteaUrl, $token, $org, $repoName, $branch, $templateNames, $platform
);
}
}
echo "\n";
@@ -406,6 +420,116 @@ class WorkflowSyncCli extends CliFramework
}
}
/**
* Delete workflows in a repo that are NOT in the template and NOT custom.
*
* Protected from deletion:
* - Files matching template workflow names
* - Files with `custom-` prefix (convention for repo-specific workflows)
* - Directories named `custom` (future: subfolder discovery)
* - Platform-excluded workflows
*/
private function deleteOrphanWorkflows(
string $giteaUrl,
string $token,
string $org,
string $repoName,
string $branch,
array $templateNames,
string $platform
): void {
$repoWorkflows = $this->listWorkflows($giteaUrl, $token, $org, $repoName, $branch);
if ($repoWorkflows === null) {
return;
}
$platformExcludes = self::PLATFORM_EXCLUDES[$platform] ?? [];
foreach ($repoWorkflows as $workflow) {
$name = $workflow['name'];
// Keep if it's in the template
if (in_array($name, $templateNames, true)) {
continue;
}
// Keep if it has the custom- prefix
if (str_starts_with($name, self::CUSTOM_PREFIX)) {
$label = "{$org}/{$repoName}/{$name}";
fprintf(STDERR, "%-45s | %s\n", $label, 'KEPT (custom)');
continue;
}
// Keep if it's platform-excluded (legitimately skipped during sync)
if (in_array($name, $platformExcludes, true)) {
$label = "{$org}/{$repoName}/{$name}";
fprintf(STDERR, "%-45s | %s\n", $label, 'KEPT (platform-excluded)');
continue;
}
// Delete orphan
$filePath = '.mokogitea/workflows/' . $name;
$label = "{$org}/{$repoName}/{$name}";
if ($this->dryRun) {
fprintf(STDERR, "%-45s | %s\n", $label, 'WOULD DELETE');
$this->deleted++;
continue;
}
$deleted = $this->deleteFile($giteaUrl, $token, $org, $repoName, $filePath, $branch);
if ($deleted) {
fprintf(STDERR, "%-45s | %s\n", $label, 'DELETED');
$this->deleted++;
} else {
fprintf(STDERR, "%-45s | %s\n", $label, 'ERROR (delete)');
$this->errors++;
}
}
}
/**
* Delete a file from a repo via the Gitea Contents API.
*/
private function deleteFile(
string $giteaUrl,
string $token,
string $org,
string $repoName,
string $filePath,
string $branch
): bool {
// Get SHA first
$existing = $this->apiRequest(
$giteaUrl, $token, 'GET',
"/api/v1/repos/{$org}/{$repoName}/contents/{$filePath}?ref={$branch}"
);
if ($existing['code'] !== 200) {
return false;
}
$data = json_decode($existing['body'], true);
$sha = $data['sha'] ?? '';
if ($sha === '') {
return false;
}
$payload = json_encode([
'sha' => $sha,
'message' => "chore: delete orphan workflow {$filePath} [skip ci]",
'branch' => $branch,
]);
$response = $this->apiRequest(
$giteaUrl, $token, 'DELETE',
"/api/v1/repos/{$org}/{$repoName}/contents/{$filePath}",
$payload
);
return $response['code'] === 200;
}
/**
* List workflow files in a repo's .mokogitea/workflows/ directory.
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoPlatform
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/backup-before-deploy.php
* VERSION: 09.38.00
* VERSION: 09.38.02
* BRIEF: Snapshot Joomla directories before deployment for rollback capability
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoPlatform
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/deploy-dolibarr.php
* VERSION: 09.38.00
* VERSION: 09.38.02
* BRIEF: Deploy Dolibarr module files to a remote server via SFTP/rsync
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoPlatform
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/health-check.php
* VERSION: 09.38.00
* VERSION: 09.38.02
* BRIEF: Post-deploy health check — verify a Joomla site is responding correctly
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoPlatform
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/rollback-joomla.php
* VERSION: 09.38.00
* VERSION: 09.38.02
* BRIEF: Rollback a Joomla deployment by restoring from a pre-deploy snapshot
*/
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoPlatform
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /deploy/sync-joomla.php
* VERSION: 09.38.00
* VERSION: 09.38.02
* 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.38.00
VERSION: 09.38.02
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.38.00
VERSION: 09.38.02
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.38.00
VERSION: 09.38.02
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.38.00
VERSION: 09.38.02
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.38.00 -->\nSome content\n"
"<!-- VERSION: 09.38.02 -->\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.38.00 -->\n"
"# Test\n<!-- VERSION: 09.38.02 -->\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.38.00 -->\n"
"<!-- VERSION: 09.38.02 -->\n"
);
mkdir("{$this->tmpDir}/src", 0755, true);
file_put_contents(
+1 -1
View File
@@ -12,7 +12,7 @@
* INGROUP: MokoPlatform
* REPO: https://git.mokoconsulting.tech/MokoConsulting/mokocli
* PATH: /validate/check_file_integrity.php
* VERSION: 09.38.00
* VERSION: 09.38.02
* BRIEF: Compare deployed files on a remote server against the local repository to detect drift
*/