You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As ai-workflows has grown from an Anthropic-only wrapper into a multi-provider router (Anthropic API, Anthropic-on-Bedrock, generic Bedrock Converse, and now OpenAI/Codex via bedrock-mantle), duplication is accruing across the executor workflows. This is a discovery/design issue to evaluate refactoring shared logic into composite actions for DRY-ness and maintainability — and to weigh whether we're approaching the point where a dedicated GitHub App is the better home.
No implementation here — decide the direction first.
What's driving this
The v3 routing model (one orchestrator → one of N executors) is sound, but the executors now repeat substantial logic. Concretely, bedrock-generic-executor.yml and codex-executor.yml (PR #31) share near-identical copies of:
Sticky-comment helper — the find-or-update bash helper, inlined to /tmp via heredoc in both executors (byte-for-byte the same).
Resolve PR number — identical case/event-discriminator step.
Gather PR diff — identical (gh pr diff + truncation at a line boundary).
In-progress / failure / final sticky updates — near-identical, differing only in title/emoji.
Prompt fallback — the "workflow_call always passes empty" fallback block.
Every new provider/executor copies these again. Bugs (e.g. the recent mantle path/SSE fixes) have to be hand-propagated.
Option A — Composite actions (incremental, stays in this repo)
Extract the shared pieces into .github/actions/* composite actions (the dotCMS/core idiom), e.g.:
.github/actions/sticky-comment/
.github/actions/resolve-pr/
.github/actions/gather-diff/
.github/actions/mantle-review/ (+ the now-inlined Python as a real file)
Hard constraint to design around (verified): a relative local action ref (./.github/actions/...) inside a cross-repo reusable workflow resolves against the caller's checkout (e.g. dotCMS/core), not ai-workflows — actions/checkout pulls the consumer repo. (./ works for workflow→workflow same-repo calls like orchestrator→executor, but not workflow→action.) And uses: cannot take an expression, so you can't dynamically resolve "my own ref."
Therefore composite actions must be referenced fully-qualified: uses: dotCMS/ai-workflows/.github/actions/sticky-comment@v3, pinned to a moving major tag (@v3) advanced on each release. Implications to settle:
Version-skew risk: an executor pinned to @v3.1.0 would pull actions at @v3 (moving). Need a release convention (retag v3 on release; consumers keep pinning the orchestrator to immutable @vX.Y.Z).
Pros: big DRY win, real script files (testable/lintable), matches core's pattern. Cons: the qualified-ref/versioning ergonomics above; more repo surface.
Option B — Dedicated GitHub App (bigger leap)
Move the review logic out of YAML entirely into a hosted service / GitHub App:
Pros: real codebase (unit tests, types, CI, dependency mgmt), no heredocs or cross-repo ref gymnastics, richer features (agentic/multi-turn Codex, inline review comments, check runs, rate-limit handling), centralized observability, secrets/identity managed once. Cons: hosting + on-call + auth (App installation tokens), a much larger build and operational footprint than reusable workflows; overkill if the workflow approach still fits.
Decision to make
Is the duplication painful enough now to do Option A, or defer until N grows further?
If Option A: settle the composite-action versioning/ref convention (moving major tag vs. alternatives) before extracting.
Is Option B (GitHub App) the real destination — and if so, does Option A become throwaway work, or a sensible stepping stone?
Scope / acceptance (discovery)
Inventory all duplicated blocks across executors (the list above is a start).
Prototype one composite action end-to-end (e.g. sticky-comment) to validate the qualified-ref + versioning ergonomics in a real consumer run (e.g. dotCMS/core).
Document the chosen versioning convention.
Decide A vs. B (or A-now / B-later) and write it up here.
Summary
As ai-workflows has grown from an Anthropic-only wrapper into a multi-provider router (Anthropic API, Anthropic-on-Bedrock, generic Bedrock Converse, and now OpenAI/Codex via bedrock-mantle), duplication is accruing across the executor workflows. This is a discovery/design issue to evaluate refactoring shared logic into composite actions for DRY-ness and maintainability — and to weigh whether we're approaching the point where a dedicated GitHub App is the better home.
No implementation here — decide the direction first.
What's driving this
The v3 routing model (one orchestrator → one of N executors) is sound, but the executors now repeat substantial logic. Concretely,
bedrock-generic-executor.ymlandcodex-executor.yml(PR #31) share near-identical copies of:/tmpvia heredoc in both executors (byte-for-byte the same).case/event-discriminator step.gh pr diff+ truncation at a line boundary).Every new provider/executor copies these again. Bugs (e.g. the recent mantle path/SSE fixes) have to be hand-propagated.
Option A — Composite actions (incremental, stays in this repo)
Extract the shared pieces into
.github/actions/*composite actions (the dotCMS/core idiom), e.g.:.github/actions/sticky-comment/.github/actions/resolve-pr/.github/actions/gather-diff/.github/actions/mantle-review/(+ the now-inlined Python as a real file)Hard constraint to design around (verified): a relative local action ref (
./.github/actions/...) inside a cross-repo reusable workflow resolves against the caller's checkout (e.g.dotCMS/core), not ai-workflows —actions/checkoutpulls the consumer repo. (./works for workflow→workflow same-repo calls like orchestrator→executor, but not workflow→action.) Anduses:cannot take an expression, so you can't dynamically resolve "my own ref."Therefore composite actions must be referenced fully-qualified:
uses: dotCMS/ai-workflows/.github/actions/sticky-comment@v3, pinned to a moving major tag (@v3) advanced on each release. Implications to settle:@v3.1.0would pull actions at@v3(moving). Need a release convention (retagv3on release; consumers keep pinning the orchestrator to immutable@vX.Y.Z)./tmp(see PR feat: add codex executor for OpenAI GPT/Codex via bedrock-mantle #31). Extraction trades self-containment for DRY.Pros: big DRY win, real script files (testable/lintable), matches core's pattern. Cons: the qualified-ref/versioning ergonomics above; more repo surface.
Option B — Dedicated GitHub App (bigger leap)
Move the review logic out of YAML entirely into a hosted service / GitHub App:
Pros: real codebase (unit tests, types, CI, dependency mgmt), no heredocs or cross-repo ref gymnastics, richer features (agentic/multi-turn Codex, inline review comments, check runs, rate-limit handling), centralized observability, secrets/identity managed once. Cons: hosting + on-call + auth (App installation tokens), a much larger build and operational footprint than reusable workflows; overkill if the workflow approach still fits.
Decision to make
Scope / acceptance (discovery)
sticky-comment) to validate the qualified-ref + versioning ergonomics in a real consumer run (e.g.dotCMS/core).Context / references
claude-orchestrator.yml,claude-executor.yml,bedrock-generic-executor.yml,codex-executor.yml./resolution: https://github.com/orgs/community/discussions/26245