Roubtec's shared GitHub Actions infrastructure: reusable workflows that give every consumer repo the same Claude-powered PR automation without copy-pasting workflow files that then drift apart.
This repo is the GitHub-facing sibling of Roubtec/agent-skills, which distributes the agent-facing skills as a Claude Code plugin marketplace. The split follows the trust boundary: workflows here run in consumer repos' CI with access to their secrets, so changes to this repo propagate executable behavior — a sharper release contract than skill text.
.github/
workflows/
claude-code-review.yml # automatic PR review (read-only reviewer)
claude.yml # @claude mention bot (can build, fix, push)
actions/
stage-review-format/ # composite action bundling the canonical review-format contract
action.yml
review-format.md
tasks/ # task specs (numbered), tasks/done/, tasks/deferred/
Both workflows are dual-trigger: they run directly against this repo's own PRs (dogfooding), and they expose workflow_call so consumer repos get the identical job through a thin caller. In the called case the github context is the caller's event, so guards, gates, and concurrency keys work unchanged.
claude-code-review.yml— automatic review onpull_request(opened / reopened / ready for review; draft PRs are skipped until marked ready, so the one automatic review lands on the finished diff; later pushes are not auto-reviewed — ask for a re-review with an@claudemention). Runs Anthropic'scode-reviewplugin and posts severity-prefixed inline comments as independently resolvable threads. Deliberately read-only: this job runs with no human in the loop while holdingCLAUDE_CODE_OAUTH_TOKEN, so it never gets tools that execute PR-authored code — a prompt injection smuggled into PR content could otherwise exfiltrate the token. Skipped on PRs from forks, which don't receive the secret.claude.yml— mention bot. Comment@claude ...on an issue or PR (or in a PR review) to summon it; only OWNER/MEMBER/COLLABORATOR authors can trigger it, since the job runs with write permissions. On a fork PR, summon it with a top-level PR comment — mentions inside PR reviews or inline review comments are skipped there, because GitHub strips secrets from fork-PR review-event runs and they would fail rather than work. The author-association gate authenticates the human who summoned the bot but not the code or text being acted on, so the tool grants are scoped to content trust: code-execution tools (pnpm/npx/corepack) are withheld when the run touches untrusted content — a fork PR, a Dependabot PR, an issue opened by an outside user, or any acted-on issue/PR conversation carrying comments or reviews from outside users (bot comments are exempt) — and on all of those paths except the Dependabot one thegh prsurface also narrows to read + comment, withholding the mutating verbs (edit/merge/close/reopen). A clean Dependabot PR keeps the fullgh prsurface, since its content is machine-generated and a maintainer may still want to merge or close it. Node/Corepack setup runs only when the consumer repo has apackage.json, so non-Node repos (docs, skills, infra) share the same workflow with no dead steps.stage-review-format— stages the review-format contract (one finding = one resolvable inline thread, severity markers, overview-only summary) into$RUNNER_TEMP. The contract is bundled with the action and resolved from this repo at@main, never from the consumer checkout, so a consumer PR can never edit the rules it is reviewed under.
One-time prerequisites:
- Install the Claude GitHub App on the consumer repo. The workflows call
anthropics/claude-code-actionwith onlyclaude_code_oauth_tokenand nogithub_token, so they rely on the app to mint the GitHub token that reads PRs and posts comments; without it the@claudeand review jobs fail even when the secret is present. - Add the
CLAUDE_CODE_OAUTH_TOKENsecret to the consumer repo (Settings → Secrets and variables → Actions). - Confirm the consumer's Actions permissions allow these workflows and the actions they run. For a consumer under the same owner with the default policy this already holds. A repo — or its organization — locked to a stricter allowlist (Settings → Actions → General → Actions permissions) must permit public reusable workflows and every external
uses:the run resolves, or it fails partway through: not only this repo's two reusable workflows but their bundledstage-review-formataction (also underRoubtec/workflow-infra/) and the third-party actions those workflows invoke —actions/checkout,actions/setup-node, andanthropics/claude-code-action. Because these span three owners (Roubtec,actions, andanthropics), the simplest reliable route for such consumers is to select "Allow all actions and reusable workflows" rather than curate a narrow allowlist (access rules). No private-repository access grant is needed beyond this — the repo is public — and GitHub-hosted runners satisfy the node24 actions' runner requirement (>= 2.328.0 per GitHub's Node20-deprecation guidance; bare Node24 execution support landed in 2.327.1). Self-hosted runners would need updating first.
Then drop these two thin callers into the consumer's .github/workflows/. The trigger block and permissions cannot be centralized — GitHub requires them in the caller, and a called workflow can only downgrade granted permissions, never elevate — so this is the irreducible per-repo surface.
The callers map CLAUDE_CODE_OAUTH_TOKEN explicitly instead of secrets: inherit: these workflows track @main, so least privilege says a consumer should hand them exactly the one secret they declare, not its whole secret store.
claude-code-review.yml:
name: Claude Code Review
on:
pull_request:
types: [opened, ready_for_review, reopened]
jobs:
claude-review:
uses: Roubtec/workflow-infra/.github/workflows/claude-code-review.yml@main
permissions:
contents: read
pull-requests: write
issues: read
id-token: write
secrets:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}claude.yml:
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened]
pull_request_review:
types: [submitted]
jobs:
claude:
uses: Roubtec/workflow-infra/.github/workflows/claude.yml@main
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
secrets:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}Merging to main is the release, mirroring the agent-skills marketplace convention: callers reference @main, so every merged commit propagates to all consumers immediately, and only curated (PR → review → merge) changes land on main. If a change ever needs a staged rollout, tag a release and move individual callers to the tag temporarily — but the default posture is one shared, always-current definition.
Know the scope of such a pin: it freezes the workflow logic, but the review-format contract still tracks main, because the workflows reference the bundled stage-review-format action at @main and GitHub allows no expressions in uses:, so the action ref cannot follow the caller's pin. This is deliberate under the merge-is-the-release model — contract updates propagate like the workflows themselves.
A full freeze needs a temporary branch of this repo that also pins that action ref, with the caller pointed at the branch. The heavier alternative — a workflow_call ref input plus an actions/checkout of this repo at that ref and a local-path uses: — is intentionally not offered: it would add a second checkout and ref-validation machinery to every run solely for the rare full-freeze case.
Because every merge here executes in all consumers' CI with their secrets, workflow changes deserve review at the same bar as code: check both the direct-trigger and the called path, and keep the caller templates above in sync with any input, secret, or permission change.
Task specifications on which many PRs are based live in tasks/, following the shared numbering convention described there (odd-numbered primaries, letter-suffixed follow-ups, done/ and deferred/ subfolders).