Skip to content

fix(safe_outputs): skip cross-repo items in extract-base-branch to prevent checkout failure#35174

Merged
pelikhan merged 14 commits into
mainfrom
copilot/fix-cross-repo-checkout-failure
May 27, 2026
Merged

fix(safe_outputs): skip cross-repo items in extract-base-branch to prevent checkout failure#35174
pelikhan merged 14 commits into
mainfrom
copilot/fix-cross-repo-checkout-failure

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 27, 2026

In multi-repo create-pull-request workflows (e.g. allowed-repos: ["org/*"]), the extract-base-branch step was picking up base_branch from items targeting other repos. That branch (e.g. feature/FOO-123) doesn't exist in the workflow repo, causing the Checkout repository step to fail with a git fetch exit code 1.

Changes

  • pkg/workflow/compiler_safe_outputs_steps.gobuildExtractBaseBranchStep was refactored to use actions/github-script and delegate extraction logic to a setup JS helper instead of inline bash/node script.
  • actions/setup/js/extract_base_branch_from_agent_output.cjs — Added helper that:
    • reads /tmp/gh-aw/agent_output.json
    • filters to same-repo items using GITHUB_REPOSITORY
    • supports both fully-qualified repo slugs (owner/repo) and bare repo names (repo) by matching repo-name suffix
    • validates branch names before setting base-branch output
  • pkg/workflow/compiler_safe_outputs_steps_test.go — Updated TestBuildExtractBaseBranchStep assertions for the new actions/github-script wiring and helper usage.
  • actions/setup/js/extract_base_branch_from_agent_output.test.cjs — Added JS unit tests for repo matching/normalization and branch extraction behavior, including bare repo-name matching.

Copilot AI and others added 3 commits May 27, 2026 10:36
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…ckout failure

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix cross-repo checkout failure in safe_outputs fix(safe_outputs): skip cross-repo items in extract-base-branch to prevent checkout failure May 27, 2026
Copilot AI requested a review from pelikhan May 27, 2026 10:44
@pelikhan pelikhan marked this pull request as ready for review May 27, 2026 10:45
Copilot AI review requested due to automatic review settings May 27, 2026 10:45
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #35174 does not have the 'implementation' label and has only 14 new lines of code in business logic directories (well below the 100-line threshold).

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

PR Code Quality Reviewer completed the code quality review.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

🧪 Test Quality Sentinel completed test quality analysis.

@github-actions github-actions Bot mentioned this pull request May 27, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /diagnose, /tdd, and /zoom-out — the fix is correct and well-targeted; commenting rather than blocking on two test-coverage suggestions and one unrelated change to clarify.

📋 Key Themes & Highlights

Key Themes

  • Test coverage is structural, not behavioural — the new assertions check that the generated script contains the right strings, but no test runs the script with mixed-repo input to verify the filter works at runtime.
  • Silent fallback — when GITHUB_REPOSITORY is empty the fix correctly excludes cross-repo items, but does so silently; a missed-branch scenario could be hard to diagnose in production.
  • Unrelated cron change — the lock file diff includes a schedule change (daily → weekly-on-Monday) that isn't described in the PR.

Positive Highlights

  • ✅ Root cause is correctly identified and precisely fixed with a minimal guard.
  • ✅ The safe-fallback design (exclude when env is empty) is a reasonable defensive choice.
  • ✅ Code comment updated to document the cross-repo skipping rationale.
  • ✅ Changeset entry is accurate and appropriately scoped as a patch.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 1.2M

// from being used to checkout the workflow repo where that branch doesn't exist.
assert.Contains(t, stepsContent, "GITHUB_REPOSITORY", "must read workflow repo from GITHUB_REPOSITORY to filter cross-repo items")
assert.Contains(t, stepsContent, "!i.repo || (workflowRepo && i.repo === workflowRepo)", "must skip items whose repo differs from the workflow repo")
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] The new assertions verify the structure of the generated code (string presence) but don't exercise the runtime behaviour — no test feeds an agent_output.json with mixed same-repo and cross-repo items to confirm the filter actually selects the right one.

💡 Suggested additional test approach

Consider a table-driven test that invokes the generated Node.js snippet with a temp JSON file containing:

  1. A cross-repo item (repo: "other-org/other-repo") — should be skipped.
  2. A same-repo item (repo: "GITHUB_REPOSITORY value") — should be selected.
  3. An item with no repo field — should be selected.
  4. All items are cross-repo, GITHUB_REPOSITORY is empty — should produce no output.

This turns the structural assertion into a behaviour assertion and would have caught the original bug as a failing test before the fix.

" const item = (data.items || []).find(i =>\n",
" (i.type === 'create_pull_request' || i.type === 'push_to_pull_request_branch') &&\n",
" i.base_branch\n",
" i.base_branch &&\n",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/diagnose] The empty-GITHUB_REPOSITORY fallback (workflowRepo && i.repo === workflowRepo) excludes all items that have an explicit repo field when GITHUB_REPOSITORY is unset. That's documented as a "safe fallback", but it silently produces an empty base-branch output — the downstream checkout step would then fall back to the default branch with no warning.

💡 Suggestion

Consider emitting a warning to stderr when workflowRepo is empty and a repo-bearing item is skipped, so operators can diagnose the silent fallback:

const workflowRepo = process.env.GITHUB_REPOSITORY || '';
if (!workflowRepo) { process.stderr.write('warning: GITHUB_REPOSITORY is unset; cross-repo items will be excluded\n'); }

Alternatively, add a comment in the generated snippet explaining the intentional fallback for future readers.

schedule:
- cron: "19 2 * * *"
# Friendly format: daily (scattered)
- cron: "6 3 * * 1"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/zoom-out] The cron schedule changed from daily (19 2 * * *) to weekly-on-Monday (6 3 * * 1). This is unrelated to the cross-repo checkout fix and isn't mentioned in the PR description. If intentional, it should be explained (or split into a separate PR) so reviewers don't assume it's a side-effect of the lock file regeneration.

@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 100/100 — Excellent

Analyzed 1 modified test (TestBuildExtractBaseBranchStep): 1 design test, 0 implementation tests, 0 guideline violations.

📊 Metrics & Test Classification (1 test analyzed)
Metric Value
New/modified tests analyzed 1
✅ Design tests (behavioral contracts) 1 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 1 (100%)
Duplicate test clusters 0
Test inflation detected No (test +6 lines, production +9 lines → ratio 0.67)
🚨 Coding-guideline violations 0

Test Classification Details

Test File Classification Issues Detected
TestBuildExtractBaseBranchStep (2 new assertions) pkg/workflow/compiler_safe_outputs_steps_test.go:664 ✅ Design None — both assertions include descriptive messages

Language Support

Tests analyzed:

  • 🐹 Go (*_test.go): 1 test — unit (//go:build !integration)
  • 🟨 JavaScript (*.test.cjs, *.test.js): 0 tests

Verdict

Check passed. 0% of new/modified tests are implementation tests (threshold: 30%). The two added assertions verify a behavioral contract — that cross-repo items are filtered by GITHUB_REPOSITORY — which directly guards against the regression fixed in this PR. Both assertions include descriptive messages and no mock libraries are used.

📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

🧪 Test quality analysis by Test Quality Sentinel · sonnet46 1.2M ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 100/100. Test quality is excellent — 0% of new/modified tests are implementation tests (threshold: 30%). The two added assertions directly enforce the behavioral contract introduced by this fix.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a failure mode in the consolidated safe_outputs apply job where extract-base-branch could mistakenly extract base_branch from safe-output items targeting other repositories, leading to a checkout attempt of a non-existent branch in the workflow repo.

Changes:

  • Update extract-base-branch generation to ignore safe-output entries whose repo differs from GITHUB_REPOSITORY.
  • Extend the unit test to assert the new GITHUB_REPOSITORY-based filtering is present in the generated script.
  • Regenerate the daily-compiler-threat-spec-optimizer compiled lock workflow and add a changeset entry for the patch release.
Show a summary per file
File Description
pkg/workflow/compiler_safe_outputs_steps.go Adds cross-repo filtering to base-branch extraction logic.
pkg/workflow/compiler_safe_outputs_steps_test.go Updates test assertions to cover the new filter and env var usage.
.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml Regenerated compiled workflow output (schedule/config/materialized heredocs).
.changeset/patch-fix-cross-repo-base-branch-checkout.md Adds a patch changeset describing the fix.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 4/4 changed files
  • Comments generated: 2

Comment on lines 40 to 45
" const workflowRepo = process.env.GITHUB_REPOSITORY || '';\n",
" const item = (data.items || []).find(i =>\n",
" (i.type === 'create_pull_request' || i.type === 'push_to_pull_request_branch') &&\n",
" i.base_branch\n",
" i.base_branch &&\n",
" (!i.repo || (workflowRepo && i.repo === workflowRepo))\n",
" );\n",
// This prevents a cross-repo base_branch (e.g. feature/FOO-123 in another repo)
// from being used to checkout the workflow repo where that branch doesn't exist.
assert.Contains(t, stepsContent, "GITHUB_REPOSITORY", "must read workflow repo from GITHUB_REPOSITORY to filter cross-repo items")
assert.Contains(t, stepsContent, "!i.repo || (workflowRepo && i.repo === workflowRepo)", "must skip items whose repo differs from the workflow repo")
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

🔎 Code quality review by PR Code Quality Reviewer · sonnet46 1.4M

Comment thread pkg/workflow/compiler_safe_outputs_steps_test.go Outdated
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot review all comments and review from GitHub-actions.

Merge main

Copilot AI and others added 2 commits May 27, 2026 11:16
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

@copilot review all comments and review from GitHub-actions.

Merge main

Addressed.

  • Updated extract-base-branch repo matching to handle bare repo names and added coverage in tests (2fe4f60).
  • Merged main into this branch (02c9e02).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@copilot refactor script to actions/setup/js .cjs file and convert to actions/github-script

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.

Implemented in bd677ee.

  • Refactored extract-base-branch logic into actions/setup/js/extract_base_branch_from_agent_output.cjs.
  • Converted the step to actions/github-script and wired it through setup_globals.cjs.
  • Added JS coverage for repo normalization (including bare repo-name matching) and updated compiler step test assertions for the new wiring.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Me saw follow-up. Smoke reply here. Thanks for fix.

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • safebrowsingohttpgateway.googleapis.com
  • www.google.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "safebrowsingohttpgateway.googleapis.com"
    - "www.google.com"

See Network Configuration for more information.

📰 BREAKING: Report filed by Smoke Copilot · gpt55 8.6M

Copilot AI and others added 2 commits May 27, 2026 12:18
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI requested a review from pelikhan May 27, 2026 12:28
@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot

  • recompile
  • add tests on new javascript helper

Copilot AI and others added 2 commits May 27, 2026 12:49
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 27, 2026

@copilot

  • recompile
  • add tests on new javascript helper

Done in 3728692.

  • Recompiled workflows (make recompile); no generated diff was produced.
  • Added tests for the new helper in actions/setup/js/extract_base_branch_from_agent_output.test.cjs covering omitted repo handling and whitespace-trimmed repo matching.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

🚀 Smoke Gemini MISSION COMPLETE! Gemini has spoken. ✨

Testing safeoutputs CLI

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

🚀 Smoke Antigravity MISSION COMPLETE! Antigravity has spoken. ✨

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

🌑 The shadows whisper... Smoke Codex failed to deliver outputs. The oracle requires further meditation...

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

💫 TO BE CONTINUED... Smoke Claude was cancelled! Our hero faces unexpected challenges...

@github-actions
Copy link
Copy Markdown
Contributor

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

🚀 Smoke Pi MISSION COMPLETE! Pi delivered. 🥧

@github-actions github-actions Bot removed the smoke label May 27, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Smoke Test: Gemini

  • GitHub MCP Testing: ✅
  • Web Fetch Testing: ✅
  • File Writing Testing: ✅
  • Bash Tool Testing: ✅
  • Build gh-aw: ❌

Overall Status: FAIL

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • localhost

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "localhost"

See Network Configuration for more information.

Smoke Gemini — Powered by Gemini ·

@github-actions
Copy link
Copy Markdown
Contributor

Comment Memory

Mist over green code
Quiet tests hum through the night
GitHub wakes in light

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • safebrowsingohttpgateway.googleapis.com
  • www.google.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "safebrowsingohttpgateway.googleapis.com"
    - "www.google.com"

See Network Configuration for more information.

🔮 The oracle has spoken through Smoke Codex · gpt54 10M ·

@github-actions
Copy link
Copy Markdown
Contributor

Smoke Copilot: FAIL
PRs: Add Copilot integration header for automation JSON imports; [spec-enforcer] Enforce specifications for sliceutil, stats, stringutil
✅ GitHub/Serena/Playwright/file/bash/discussion/build/upload/review/sub-agent/check
❌ mcpscripts-gh missing; web-fetch missing; no comment-memory files
Author: app/copilot-swe-agent. Assignees: pelikhan, Copilot.

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • safebrowsingohttpgateway.googleapis.com
  • www.google.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "safebrowsingohttpgateway.googleapis.com"
    - "www.google.com"

See Network Configuration for more information.

📰 BREAKING: Report filed by Smoke Copilot · gpt55 8.6M ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Smoke review done. Me see no blocker. Tool checks found environment gaps outside diff.

Warning

Firewall blocked 6 domains

The following domains were blocked by the firewall during workflow execution:

  • accounts.google.com
  • android.clients.google.com
  • clients2.google.com
  • contentautofill.googleapis.com
  • safebrowsingohttpgateway.googleapis.com
  • www.google.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "accounts.google.com"
    - "android.clients.google.com"
    - "clients2.google.com"
    - "contentautofill.googleapis.com"
    - "safebrowsingohttpgateway.googleapis.com"
    - "www.google.com"

See Network Configuration for more information.

📰 BREAKING: Report filed by Smoke Copilot · gpt55 8.6M

if (!workflowRepo) return false;
if (itemRepo === workflowRepo) return true;

// Safe-output repo values may be a bare repo name and get qualified at runtime.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Me check repo match helper. Bare repo path now guarded. Good smoke line.

async function main() {
const baseBranch = extractBaseBranchFromAgentOutput();
if (!baseBranch) return;
if (!SAFE_BRANCH_NAME_REGEX.test(baseBranch) || baseBranch.length > 255) return;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Me see branch validation still before output. Good guard stay alive after refactor.

@github-actions
Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@pelikhan pelikhan merged commit 73fb3e6 into main May 27, 2026
32 checks passed
@pelikhan pelikhan deleted the copilot/fix-cross-repo-checkout-failure branch May 27, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

safe_outputs: cross-repo base_branch still causes checkout failure (not fixed in v0.76.1)

3 participants