Skip to content

Commit 9d4f2a1

Browse files
agent: deploy workflow-sync
1 parent b4338ff commit 9d4f2a1

1 file changed

Lines changed: 184 additions & 0 deletions

File tree

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# .github/workflows/agent-workflow-sync.yml
2+
# Self-improving agent that keeps all org RoadCode repos in sync
3+
# When workflows change in operator, automatically propagates to all 16 orgs
4+
# Also detects and disables broken workflows across all orgs
5+
6+
name: "Agent: Workflow Sync"
7+
8+
on:
9+
push:
10+
branches: [main]
11+
paths:
12+
- '.github/workflows/autonomous-*.yml'
13+
- '.github/workflows/agent-*.yml'
14+
schedule:
15+
- cron: '0 12 * * 1' # Weekly Monday noon UTC
16+
workflow_dispatch:
17+
inputs:
18+
action:
19+
description: 'Action'
20+
required: false
21+
default: 'sync'
22+
type: choice
23+
options:
24+
- sync
25+
- disable_broken
26+
- full
27+
28+
permissions:
29+
contents: write
30+
31+
jobs:
32+
sync-workflows:
33+
name: "Sync Workflows to All Orgs"
34+
runs-on: ubuntu-latest
35+
if: github.event_name == 'push' || inputs.action == 'sync' || inputs.action == 'full'
36+
37+
steps:
38+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
39+
40+
- name: Sync autonomous workflows to all RoadCode repos
41+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
42+
with:
43+
script: |
44+
const ORGS = [
45+
'BlackRoad-OS-Inc', 'BlackRoad-OS', 'BlackRoad-Studio', 'BlackRoad-Archive',
46+
'BlackRoad-Interactive', 'BlackRoad-Security', 'BlackRoad-Gov', 'BlackRoad-Education',
47+
'BlackRoad-Hardware', 'BlackRoad-Media', 'BlackRoad-Foundation', 'BlackRoad-Ventures',
48+
'BlackRoad-Cloud', 'BlackRoad-Labs', 'BlackRoad-AI', 'Blackbox-Enterprises'
49+
];
50+
51+
const WORKFLOWS = [
52+
'autonomous-orchestrator.yml',
53+
'autonomous-self-healer.yml',
54+
'autonomous-issue-manager.yml',
55+
'autonomous-cross-repo.yml',
56+
'autonomous-dependency-manager.yml'
57+
];
58+
59+
let synced = 0, errors = 0;
60+
61+
for (const wf of WORKFLOWS) {
62+
// Read source workflow from this repo
63+
let sourceContent;
64+
try {
65+
const { data } = await github.rest.repos.getContent({
66+
owner: 'BlackRoad-OS-Inc', repo: 'blackroad-operator',
67+
path: `.github/workflows/${wf}`
68+
});
69+
sourceContent = data.content;
70+
} catch (e) {
71+
console.log(`Source not found: ${wf}`);
72+
continue;
73+
}
74+
75+
for (const org of ORGS) {
76+
try {
77+
// Check if target exists
78+
let sha;
79+
try {
80+
const { data } = await github.rest.repos.getContent({
81+
owner: org, repo: 'RoadCode',
82+
path: `.github/workflows/${wf}`
83+
});
84+
sha = data.sha;
85+
86+
// Skip if content is identical
87+
if (data.content.replace(/\s/g, '') === sourceContent.replace(/\s/g, '')) {
88+
continue;
89+
}
90+
} catch {}
91+
92+
const params = {
93+
owner: org, repo: 'RoadCode',
94+
path: `.github/workflows/${wf}`,
95+
message: `agent: sync ${wf} from operator`,
96+
content: sourceContent,
97+
committer: { name: 'BlackRoad Agent', email: 'agent@blackroad.io' }
98+
};
99+
if (sha) params.sha = sha;
100+
101+
await github.rest.repos.createOrUpdateFileContents(params);
102+
synced++;
103+
console.log(`Synced: ${org}/RoadCode/${wf}`);
104+
} catch (e) {
105+
errors++;
106+
console.log(`Error: ${org}/RoadCode/${wf} — ${e.message}`);
107+
}
108+
}
109+
}
110+
111+
console.log(`\nSynced: ${synced} | Errors: ${errors}`);
112+
await core.summary.addRaw(`## Workflow Sync\n\nSynced: ${synced} workflows\nErrors: ${errors}`).write();
113+
114+
disable-broken:
115+
name: "Disable Broken Workflows"
116+
runs-on: ubuntu-latest
117+
if: github.event_name == 'schedule' || inputs.action == 'disable_broken' || inputs.action == 'full'
118+
119+
steps:
120+
- name: Find and disable failing scheduled workflows
121+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
122+
with:
123+
script: |
124+
const ORGS = [
125+
'BlackRoad-OS-Inc', 'BlackRoad-OS', 'BlackRoad-AI', 'BlackRoad-Studio',
126+
'BlackRoad-Education', 'BlackRoad-Security', 'BlackRoad-Labs', 'BlackRoad-Hardware',
127+
'BlackRoad-Media', 'BlackRoad-Foundation', 'BlackRoad-Ventures', 'BlackRoad-Cloud',
128+
'BlackRoad-Gov', 'BlackRoad-Archive', 'BlackRoad-Interactive', 'Blackbox-Enterprises'
129+
];
130+
131+
// Patterns that indicate broken looping workflows
132+
const DISABLE_PATTERNS = [
133+
'Self-Healing', 'self-heal', 'Auto-Heal', 'auto-heal',
134+
'HuggingFace', 'Autonomy System', 'BlackRoad AI Agents',
135+
'Production Health Check', 'Uptime'
136+
];
137+
138+
let disabled = 0, checked = 0;
139+
140+
for (const org of ORGS) {
141+
const { data: repos } = await github.rest.repos.listForOrg({ org, per_page: 100 });
142+
143+
for (const repo of repos.filter(r => !r.archived)) {
144+
try {
145+
const { data: workflows } = await github.rest.actions.listRepoWorkflows({
146+
owner: org, repo: repo.name
147+
});
148+
149+
for (const wf of workflows.workflows) {
150+
if (wf.state !== 'active') continue;
151+
checked++;
152+
153+
// Check if it matches a broken pattern
154+
const shouldDisable = DISABLE_PATTERNS.some(p =>
155+
wf.name.includes(p) || wf.path.includes(p.toLowerCase().replace(/ /g, '-'))
156+
);
157+
158+
if (!shouldDisable) continue;
159+
160+
// Verify it's actually failing (last 3 runs all failed)
161+
try {
162+
const { data: runs } = await github.rest.actions.listWorkflowRuns({
163+
owner: org, repo: repo.name, workflow_id: wf.id,
164+
per_page: 3, status: 'completed'
165+
});
166+
167+
const allFailed = runs.workflow_runs.length >= 3 &&
168+
runs.workflow_runs.every(r => r.conclusion === 'failure');
169+
170+
if (allFailed) {
171+
await github.rest.actions.disableWorkflow({
172+
owner: org, repo: repo.name, workflow_id: wf.id
173+
});
174+
disabled++;
175+
console.log(`Disabled: ${org}/${repo.name}/${wf.name} (3+ consecutive failures)`);
176+
}
177+
} catch {}
178+
}
179+
} catch {}
180+
}
181+
}
182+
183+
console.log(`\nChecked: ${checked} workflows | Disabled: ${disabled}`);
184+
await core.summary.addRaw(`## Broken Workflow Cleanup\n\nChecked: ${checked}\nDisabled: ${disabled} (3+ consecutive failures)`).write();

0 commit comments

Comments
 (0)