
Jenkins to GitHub Actions Migration Guide
Your team adopted Copilot Workspace last quarter. Then someone added Cursor to the mix. Now Claude Code is opening PRs at 2 AM. The review queue that handled 15 human PRs a day is staring down 150 agent-generated ones, and your branch protection rules were never designed for this.
This guide covers the specific GitHub Actions configurations, branch protection rulesets, and review threshold settings that platform engineers need when AI coding agents are producing a significant share of the pull request volume. It's not theory. Every pattern here is something teams are running in production right now, and every anti-pattern is something that's already caused incidents.
Human developers open PRs during working hours, in bursts, with natural gaps between them. Status checks finish before the next PR lands. Reviewers process the queue during the day and it's mostly empty by EOD. Agent PRs don't follow that pattern.
Three things break first:
The fix isn't to remove safeguards. It's to restructure your workflow architecture so the safeguards actually hold under agent-scale volume.
Not all agent PRs carry the same risk. Treating a dependency bump the same as a feature implementation wastes reviewer attention on the wrong things. In practice, agents produce three distinct PR types, and your workflow configuration should handle each one differently.
These add or modify application logic. An agent like Copilot Workspace might scaffold an entire feature branch from an issue description, or Claude Code might implement a function based on a prompt. Feature PRs are the highest risk because the agent is making design decisions, not just updating values. They need full CI, automated review, and usually a human sign-off.
Dependabot, Renovate, or an agent instructed to "update all outdated packages" will generate these. The diff is typically a lockfile change plus maybe a config tweak. The risk is supply chain compromise (malicious package version) rather than logic errors. These benefit from dependency review checks and SBOM validation but don't need the same depth of code review as feature work.
An agent sees a failing CI run, diagnoses the issue, and opens a PR to fix it. These are deceptively dangerous. The agent is responding to error output, which can be manipulated. If an attacker controls the test fixtures or error messages, they can steer the agent's fix toward introducing a vulnerability. CI fix PRs need the same scrutiny as feature PRs, plus explicit validation that the fix actually addresses the original failure and doesn't just silence it.
Agents interact with GitHub Actions through the same event triggers humans do, but the patterns they produce expose different attack surfaces. Two triggers deserve special attention.
pull_request_target: the privileged triggerThe pull_request_target event runs in the context of the base repository, not the fork. It has access to secrets and a write-capable GITHUB_TOKEN. If a workflow triggered by pull_request_target checks out the PR's head branch and runs build scripts, an attacker can exfiltrate every secret in the repository. This is the "pwn request" attack pattern, and it's been exploited at Fortune 100 companies.
Agents make this worse in two ways. First, they produce more PRs, which means more workflow runs with elevated privileges. Second, agents sometimes generate workflows that use pull_request_target without understanding why it's dangerous. They see examples in documentation, replicate the pattern, and ship a workflow that checks out untrusted code in a privileged context.
GitHub's November 2025 update now requires pull_request_target workflows to use the default branch as their source, which eliminates one class of exploit. But the core risk remains: if the workflow checks out PR code and executes it, secrets are exposed.
The rule: Use the standard pull_request trigger for all build, lint, and test workflows. It's sandboxed. It doesn't have access to secrets. It's what you want for agent PRs.
pull_request + workflow_run split patternSometimes you genuinely need a workflow that has write permissions or access to secrets after a PR's checks pass. The correct pattern is a two-phase split: the first workflow runs on pull_request (no secrets, sandboxed), and the second runs on workflow_run after the first completes. The second workflow has access to secrets but never executes code from the PR directly.
# Phase 1: Sandboxed checks (no secrets)
name: PR Checks
on:
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
---
# Phase 2: Privileged post-check (has secrets, never checks out PR code)
name: Post-PR Deploy Preview
on:
workflow_run:
workflows: ["PR Checks"]
types: [completed]
jobs:
deploy-preview:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.workflow_run.head_branch }}
# Deploy using secrets - but validate the artifact, don't run PR scriptsThe critical detail: even in the workflow_run phase, don't execute build scripts or test suites from the PR branch. Use the artifacts produced by the sandboxed phase, or validate the checked-out code through static analysis before running anything.
GitHub's repository rulesets (the newer replacement for classic branch protection rules) give you granular control over what can merge and under what conditions. Here's what each setting actually does in an agent-heavy environment, and where the gaps are.
This is your first line of defense. A required status check means the PR cannot merge until a specific CI job reports success. For agent PRs, you want at minimum:
Enable "Require branches to be up to date before merging." Without this, an agent PR can pass checks against a stale base, then merge and break main. With agents producing PRs in parallel, stale-base merges are one of the most common causes of broken builds.
This setting invalidates existing approvals when new commits are pushed. Turn it on. Agents frequently push follow-up commits to fix lint errors or test failures. Without stale review dismissal, an approval given before those fixup commits carries through to the final version, which may have changed substantially. The reviewer approved version 1; version 3 is what actually merges.
GitHub's merge queue batches approved PRs and tests them together against the target branch before merging. This is nearly mandatory for agent-scale volume. Without it, you get the classic merge skew problem: PR A and PR B both pass checks independently, but conflict when merged sequentially.
Configure the merge queue with a batch size that matches your CI capacity. If your full test suite takes 8 minutes and you have enough runner concurrency for 3 parallel merge groups, set the batch size to 3. Going higher creates longer feedback loops when a batch fails and has to be bisected.
Branch protection verifies that checks pass and reviews are present. It does not evaluate the quality or depth of those reviews. A one-line "LGTM" comment counts the same as a thorough code review. It also can't distinguish between an agent PR that made a sound architectural decision and one that introduced a subtle race condition that passes all tests.
This is where automated code review tools fill the gap. Your status checks gate on CI correctness; automated review gates on code quality and security. You need both.
Uniform review settings across all PR sources is the wrong default. A Dependabot patch bump carries different risk than a Copilot feature implementation, and your review infrastructure should reflect that.
The practical approach is to classify PRs by their source actor and archetype, then apply different review sensitivity to each combination. Here's what that looks like in practice:
Focus automated review on supply chain signals: is the new version flagged in any advisory database? Does the dependency review action report new vulnerabilities? Is the package still actively maintained? If the diff is purely a lockfile change and the dependency review passes, these can often auto-merge with just automated checks. The review threshold is lower for severity because the blast radius is constrained to known vulnerability databases.
Run automated review with maximum sensitivity. Flag anything at Warning level or above. These PRs introduce new logic, and agents are prone to specific classes of mistakes: they hardcode values that should be configurable, skip error handling for edge cases, use deprecated APIs they saw in training data, and sometimes introduce subtle security issues like SQL injection in dynamically constructed queries. An automated reviewer like Tenki catches these patterns because it evaluates the diff against the repository's existing conventions, not just syntactic correctness. On the Tenki benchmark, it catches 68.9% of bugs in PR diffs, which matters a lot when you're reviewing 10x the volume you used to.
Same high sensitivity as Copilot feature PRs, but add an additional gate: require a human reviewer for any PR that modifies workflow files, security-sensitive configuration, or authentication logic. Claude Code and similar autonomous agents operate with less human oversight during generation than Copilot (which typically has a human in the loop). The approval requirement should reflect that reduced oversight.
GitHub Actions doesn't natively support different workflow configurations per PR author. The cleanest workaround uses labels applied by a triage workflow, which then determines which review jobs run:
name: PR Triage
on:
pull_request:
types: [opened]
jobs:
label:
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const actor = context.actor;
const labels = [];
if (actor === 'dependabot[bot]' || actor === 'renovate[bot]') {
labels.push('agent:dependency');
} else if (actor.endsWith('[bot]')) {
labels.push('agent:autonomous');
} else {
labels.push('author:human');
}
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels
});Downstream review and CI workflows then filter on these labels to decide which checks to run and what thresholds to apply.
When a human-authored PR triggers a critical review finding, you ping the author and ask them to fix it. Agent PRs don't have that feedback loop. The bot that opened the PR isn't checking Slack. You need a different escalation path.
Three patterns that work:
CODEOWNERS file to assign agent PRs that touch sensitive paths to a specific review team. When a Critical flag fires, the team gets notified through GitHub's standard review request mechanism. This works well for teams that already have CODEOWNERS configured but need to extend it to cover agent-authored changes.name: Critical Finding Handler
on:
check_run:
types: [completed]
jobs:
handle-critical:
if: |
github.event.check_run.conclusion == 'failure' &&
contains(github.event.check_run.output.title, 'Critical')
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
with:
script: |
const pr = context.payload.check_run.pull_requests[0];
if (!pr) return;
// Close the PR with explanation
await github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
state: 'closed'
});
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: `This PR was closed automatically due to a Critical severity finding in automated review. The linked issue remains open for manual triage.`
});Here's the complete set of settings for a team running 100+ agent PRs per day against a monorepo:
Repository ruleset for main:
Workflow architecture:
Review thresholds by source:
None of this requires exotic tooling. It's GitHub's native features (rulesets, merge queue, CODEOWNERS, workflow triggers) combined with an automated review check that can differentiate between severity levels. Tenki's code reviewer plugs into this architecture as a required status check at $1 per review. It reports severity levels that your workflow can act on, so you're not just gating on pass/fail but on how severe the findings are and who authored the PR.
The goal isn't to slow agents down. It's to let them move fast on low-risk changes while applying appropriate friction on the changes that actually need a human brain looking at them.
Tags
Recommended for you
What's next in your stack.