feat: Replace IssueOps with deterministic orchestrator + agentic workers - #21
feat: Replace IssueOps with deterministic orchestrator + agentic workers#21AlexDeMichieli wants to merge 42 commits into
Conversation
* Switching to custom agent based system
* Update ops guide * Update docs/operations.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…nd issues to prompt Copilot for migrations. (#6) * explain how the batch migration system works with custom properties and issues to prompt Copilot for migrations. * Update docs/operations.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update docs/operations.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Bumps the github-actions group with 3 updates in the / directory: [actions/checkout](https://github.com/actions/checkout), [actions/github-script](https://github.com/actions/github-script) and [actions/create-github-app-token](https://github.com/actions/create-github-app-token). Updates `actions/checkout` from 4 to 6 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v4...v6) Updates `actions/github-script` from 7.0.1 to 8.0.0 - [Release notes](https://github.com/actions/github-script/releases) - [Commits](actions/github-script@v7.0.1...v8.0.0) Updates `actions/create-github-app-token` from 2 to 3 - [Release notes](https://github.com/actions/create-github-app-token/releases) - [Commits](actions/create-github-app-token@v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/github-script dependency-version: 8.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions - dependency-name: actions/create-github-app-token dependency-version: '3' dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Anthony Grutta <90877891+antgrutta@users.noreply.github.com>
…strap - Add .github/workflows/submit-repos.md: agentic workflow replacement for submit-repos.yml IssueOps batch orchestration (closes #17) - Add .github/scripts/deploy-hooks.js: bootstrap script to deploy hooks to all target repos via Contents API (hooks are per-repo only, do not propagate from .github-private) - Add .github/hooks/: migration eval hooks (security-guard, audit-log, eval-migration, verify-ci-sources) - Update .github/workflows/settings.yml: add deploy-hooks step
…rkflow - Replace duplicate create-issue with add-comment for summary report - Remove close-older-issues (wrong pattern: would disrupt in-progress migrations) - Add explicit skip logic for repos with open migration issues - Add rate limiting instructions for agent's gh API calls - Note 10-second platform delay per agent assignment
example.com legitimately appears in email/notification action configs (e.g., dawidd6/action-send-mail). Move it to a warn-only pattern list so it doesn't fail the scorecard for valid migrations.
…tput writes Move repo scanning logic into steps: (actions/github-script) that runs BEFORE the agent. JS handles pagination, property reads, idempotency checks, error recovery, and prompt loading deterministically. The agent's only job: read the pre-computed scan-results.json and call create_issue for each eligible repo. Near-zero hallucination risk since input is pre-computed and instructions are trivial. Safe outputs provide: max limits, target-repo restrictions, threat detection, gh-aw-workflow-id markers, 10-second assignment delays.
Per gh-aw docs, files in /tmp/gh-aw/agent/ are automatically uploaded as artifacts and available to the AI agent.
Wraps all API calls in withRetry() helper that respects Retry-After header and retries up to 3 times. Addresses #17 acceptance criteria for rate-limit handling.
There was a problem hiding this comment.
Copilot encountered an error: Your billing is not configured or you have Copilot licenses from multiple standalone organizations or enterprises. To use premium requests, select a billing entity via the GitHub site, under Settings > Copilot > Features.
There was a problem hiding this comment.
Copilot encountered an error: Your billing is not configured or you have Copilot licenses from multiple standalone organizations or enterprises. To use premium requests, select a billing entity via the GitHub site, under Settings > Copilot > Features.
|
@AlexDeMichieli, I gave this a try and want to simplify a few things: Remove hooks from this PR. Hooks require commits to individual repositories, and there's nuance there that needs more exploration. Let's treat hooks as a separate feature for later. Rethink PRU usage. Scanning repos for a custom property and creating an issue is a deterministic operation, it shouldn't require AI. When a customer migrates pipelines in batch, we want to give them a single pane of glass to orchestrate and manage everything. Moving to an agentic workflow should let us identify eligible repos (up to the batch size), clone them, run the migration, and open a PR on each target repository — all from one workflow in the orchestration repository (.github-private). Proposed architecture: A standard (deterministic) workflow identifies eligible repositories up to the batch number, then kicks off N agentic workflows. Each agentic workflow takes a target repo as input, performs the migration, and opens a PR on that target repository. |
@antgrutta Thanks for the review. This makes a lot of sense and aligns with where I was heading. On hooks: Agreed, removing from this PR. The hooks work (tested on volcano-coffee) but deploying them per-repo is a separate concern. Will track separately. On the architecture: I like the orchestrator → N workers pattern. To confirm my understanding: submit-repos.yml (deterministic, standard Actions)
├─ Scan repos, identify eligible ones
└─ For each: dispatch-workflow → migration-worker.md
migration-worker.md (agentic workflow, one per repo)
├─ Input: target_repo, migration_type
├─ Checks out target repo (cross-repo checkout)
├─ Reads agent prompt + knowledge base (already local in .github-private)
├─ AI performs the migration
└─ Opens PR on target repo (create-pull-request with target-repo)Since the worker runs in I'll rework the PR to this architecture. |
Architectural Considerations for the Orchestrator → N Workers PatternBased on the proposed architecture — evolved through discussion #14, PR review feedback, and E2E testing on Observability: Single pane of glass with isolated workersWorkers are intentionally isolated. A failure in repo A shouldn't affect repo B. But the orchestrator needs to know the overall status. Since The parent issue becomes the dashboard: Workers don't know about each other. They just know where to post their status. Failed jobs also get gh-aw's built-in Future-scale considerations (not blocking at batch size 5)These become relevant when scaling to 50+ repos per batch:
|
- Remove hooks and deploy-hooks.js (separate concern, per review feedback) - Restore settings.yml to original - New: migration-worker.md — agentic workflow that clones a target repo, performs the migration, and opens a cross-repo PR. Runs from .github-private so knowledge/ is local, no MCP token needed for batch. - Rewrite: submit-repos.md — deterministic JS scanner in steps: dispatches N migration-worker instances via dispatch-workflow. Creates a parent tracking issue for single-pane-of-glass observability. Workers report back via add-comment on the tracking issue.
- Fix: move secrets from steps: to jobs: (strict mode rejects secrets in agent-accessible steps) - Fix: escape secrets expression in agent instructions - Add: migration-worker.lock.yml (compiled from migration-worker.md) - Add: submit-repos.lock.yml (compiled from submit-repos.md) - Both compile with 0 errors on gh-aw v0.67.1
|
Scanning for repos based on custom properties is a very deterministic task, I have moved that workflow to a classic Actions workflow. |
TL;DR
This PR introduces architectural changes from discussion #14 and issue #17, evolved through E2E testing on
volcano-coffeeEMU enterprise and review feedback. It replaces the IssueOps batch orchestrator with a two-tier architecture: a deterministic classic Actions orchestrator scans repos and dispatches N agentic migration workers that each clone a target repo, perform the migration, and open a cross-repo PR — all from.github-private.Before and After
Before: IssueOps — orchestrator creates issues, Copilot runs on target repos
After: Deterministic orchestrator dispatches agentic workers from .github-private
Key change: The AI that performs the migration moves from Copilot coding agent sessions on target repos to gh-aw agentic workers running inside
.github-private. Target repos are passive — they only receive a PR. The orchestrator is a classic Actions workflow (no AI tokens consumed for scanning/dispatching).What this PR does
submit-repos.ymlmigration-worker.md+.lock.ymlscan-repositories.jsGH_MIGRATION_TYPEcustom property, idempotency check, returns eligible listcreate-tracking-issue.js[Migration Batch]tracking issue on.github-privatedispatch-migrations.jsmigration-workerworkflow per eligible repoHow it works
Observability: single pane of glass
Workers are isolated — a failure in repo A doesn't affect repo B. The tracking issue aggregates status:
Why the orchestrator is a classic
.yml(not agentic)Scanning and dispatching is purely mechanical — zero AI needed. Using a classic workflow saves ~2K AI tokens per run and avoids the
COPILOT_GITHUB_TOKENdependency for the orchestrator. The trade-off: we losegh aw replayon the orchestrator, but the idempotency check inscan-repositories.js(search for open migration issues before dispatching) prevents duplicates on re-run. Workers keep full agentic resilience — each failed worker migration can be replayed individually viagh aw replay.Resolved questions
COPILOT_MCP_GITHUB_PERSONAL_ACCESS_TOKEN.settings.ymlcontinues provisioning. Batch mode doesn't need it.Known blockers
Testing checklist
[Actions Migration]issuesdispatch-workflowtriggersmigration-worker.mdper eligible repocreate-pull-requestopens draft PR on target repoadd-commentnoopcalled when no eligible repos found