Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Scope PR history checks to agent ancestry
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
  • Loading branch information
Copilot and gh-aw-bot authored Oct 9, 2026
commit 79eaa705fe1fa0805876d12edf793a6d064a9fa5
9 changes: 4 additions & 5 deletions actions/setup/js/safe_outputs_handlers.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,7 @@ function createHandlers(server, appendSafeOutput, config = {}) {
}

const prHeadBaseline = resolvePRHeadBaselineForPush(entry.branch, itemRepo, effectivePushPRNumber, server);
const incrementalBaseRef = prHeadBaseline?.sha || prHeadBaseline?.ref || `refs/remotes/origin/${entry.branch}`;
if (prHeadBaseline?.headRepo && prHeadBaseline.headRepo.toLowerCase() !== itemRepo.toLowerCase() && prHeadBaseline.headRepo.toLowerCase() !== configuredHeadRepo.toLowerCase()) {
return {
content: [
Expand Down Expand Up @@ -1556,10 +1557,9 @@ function createHandlers(server, appendSafeOutput, config = {}) {
// only local refs (no extra fetch); a detection miss simply preserves the
// existing behavior.
if (!useBundle && !patchFormatExplicit && entry.branch) {
const rangeBaseRef = prHeadBaseline?.sha || prHeadBaseline?.ref || `refs/remotes/origin/${entry.branch}`;
const hasMerges = hasMergeCommitsInRange(rangeBaseRef, entry.branch, { cwd: repoCwd || undefined });
const hasMerges = hasMergeCommitsInRange(incrementalBaseRef, entry.branch, { cwd: repoCwd || undefined });
if (hasMerges) {
server.debug(`push_to_pull_request_branch: detected merge commit(s) in incremental range ${rangeBaseRef}..${entry.branch}; auto-switching to bundle transport (set patch-format: am to override).`);
server.debug(`push_to_pull_request_branch: detected merge commit(s) in incremental range ${incrementalBaseRef}..${entry.branch}; auto-switching to bundle transport (set patch-format: am to override).`);
useBundle = true;
}
}
Expand Down Expand Up @@ -1604,8 +1604,7 @@ function createHandlers(server, appendSafeOutput, config = {}) {
if (!pushPinnedSha) {
server.debug("Incremental allowed-files check skipped: branch SHA not pinned (non-bundle path)");
} else {
const incrementalBase = prHeadBaseline?.sha || prHeadBaseline?.ref || `refs/remotes/origin/${entry.branch}`;
const agentFiles = execGitSync(["log", "--name-only", "--pretty=format:", `${incrementalBase}..${pushPinnedSha}`, "--"], { cwd: pushGitCwd })
const agentFiles = execGitSync(["log", "--ancestry-path", "--name-only", "--pretty=format:", `${incrementalBaseRef}..${pushPinnedSha}`, "--"], { cwd: pushGitCwd })
.toString()
.split("\n")
.map(s => s.trim())
Expand Down
29 changes: 29 additions & 0 deletions actions/setup/js/safe_outputs_handlers.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2619,6 +2619,8 @@ describe("safe_outputs_handlers", () => {
fs.writeFileSync(path.join(repoDir, "agent.js"), "console.log('agent');\n");
execSync("git add agent.js", { cwd: repoDir, stdio: "pipe" });
execSync("git commit -m 'agent script'", { cwd: repoDir, stdio: "pipe" });
Comment on lines +2617 to +2621

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regression now adds agent.js and removes it in a second commit before invoking the handler, proving per-commit detection survives a net-zero change. Fixed in 79eaa70.

execSync("git rm agent.js", { cwd: repoDir, stdio: "pipe" });
execSync("git commit -m 'revert agent script'", { cwd: repoDir, stdio: "pipe" });

process.env.GITHUB_BASE_REF = "main";
process.env.GITHUB_WORKSPACE = repoDir;
Expand All @@ -2637,6 +2639,33 @@ describe("safe_outputs_handlers", () => {
}
});

it("does not reject disallowed files merged from the updated base branch", async () => {
const { repoDir } = createRepoWithDisallowedHistoryFile();
execSync("git checkout main", { cwd: repoDir, stdio: "pipe" });
fs.writeFileSync(path.join(repoDir, "upstream.js"), "console.log('upstream');\n");
execSync("git add upstream.js", { cwd: repoDir, stdio: "pipe" });
execSync("git commit -m 'update base branch'", { cwd: repoDir, stdio: "pipe" });
execSync("git checkout feature/work", { cwd: repoDir, stdio: "pipe" });
execSync("git merge --no-ff main -m 'merge updated base'", { cwd: repoDir, stdio: "pipe" });

process.env.GITHUB_BASE_REF = "main";
process.env.GITHUB_WORKSPACE = repoDir;
const localHandlers = createHandlers(mockServer, mockAppendSafeOutput, {
push_to_pull_request_branch: { allowed_files: ["*.md"] },
});
try {
const result = await localHandlers.pushToPullRequestBranchHandler({ branch: "feature/work" });
if (result.isError) {
const data = JSON.parse(result.content[0].text);
expect(data.error).not.toContain("allowed-files configuration");
expect(data.disallowed_files).toBeUndefined();
}
} finally {
delete process.env.GITHUB_BASE_REF;
process.env.GITHUB_WORKSPACE = testWorkspaceDir;
}
});

it("does not block when agent files are within allowed_files", async () => {
const repoDir = path.join(testWorkspaceDir, "allowed-files-ok-repo");
fs.mkdirSync(repoDir, { recursive: true });
Expand Down
2 changes: 1 addition & 1 deletion actions/setup/js/work_queue_compaction.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { createHash } = require("node:crypto");
const fs = require("node:fs");
const os = require("node:os");
const path = require("node:path");
const { test } = require("node:test");
import { test } from "vitest";
const { canonical } = require("./work_queue_codec.cjs");
const { main: planCompaction, planFor } = require("./work_queue_compaction_plan.cjs");
const { isRetryablePublicationError, main: apply, PLAN_MAX_BYTES, readPlan } = require("./work_queue_compaction_apply.cjs");
Expand Down
Loading