Skip to content

Fix dispatch_workflow to use PR branch ref and resolve default branch correctly - #14062

Merged
pelikhan merged 3 commits into
mainfrom
copilot/fix-pr-branch-ref-dispatch
Feb 6, 2026
Merged

Fix dispatch_workflow to use PR branch ref and resolve default branch correctly#14062
pelikhan merged 3 commits into
mainfrom
copilot/fix-pr-branch-ref-dispatch

Conversation

CopilotAI commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

dispatch_workflow was using GITHUB_REF in all contexts, which points to refs/pull/{PR_NUMBER}/merge when triggered from PRs. The GitHub Actions API rejects merge refs for workflow dispatch, causing failures. Additionally, the fallback logic was hardcoding "main" as the default branch instead of properly resolving the repository's actual default branch.

Changes

  • dispatch_workflow.cjs:
    • Detect PR context via GITHUB_HEAD_REF and construct refs/heads/{branch_name} instead of using merge ref
    • Properly resolve repository default branch by checking context.payload.repository.default_branch first, then falling back to github.rest.repos.get() API, and only using "refs/heads/main" as last resort if API call fails
  • dispatch_workflow.test.cjs:
    • Add test coverage for PR context, non-PR context, and branch names with slashes
    • Add tests for default branch resolution from context and API fallback

Implementation

// Before: Always used GITHUB_REF with hardcoded "main" fallbackconstref=process.env.GITHUB_REF||context.ref||"refs/heads/main";// After: Detect PR context and properly resolve default branchconstgetDefaultBranchRef=async()=>{// Try to get from context payload firstif(context.payload.repository?.default_branch){return`refs/heads/${context.payload.repository.default_branch}`;}// Fall back to querying the repositorytry{const{data: repoData}=awaitgithub.rest.repos.get({owner: repo.owner,repo: repo.repo,});return`refs/heads/${repoData.default_branch}`;}catch(error){core.warning(`Failed to fetch default branch: ${getErrorMessage(error)}`);return"refs/heads/main";}};letref;if(process.env.GITHUB_HEAD_REF){ref=`refs/heads/${process.env.GITHUB_HEAD_REF}`;}elseif(process.env.GITHUB_REF||context.ref){ref=process.env.GITHUB_REF||context.ref;}else{ref=awaitgetDefaultBranchRef();}

This ensures compatibility with repositories using non-standard default branches (e.g., "develop", "master", "staging") while GitHub Actions sets GITHUB_HEAD_REF only in PR contexts, making it a reliable indicator for PR detection.

Original prompt

Reference: https://github.com/github/gh-aw/actions/runs/21740597360/job/62715358674#step:6:1

When calling dispatch_worflow from a pull request, you need to resolve the PR branch ref and not the merge ref created for the run.

See error in the safe output logs.
Also review the step to checkout the PR branch.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

When running in a pull request context, GITHUB_REF points to the merge ref
(refs/pull/{PR_NUMBER}/merge) which is not a valid branch ref for dispatching
workflows. This change detects PR contexts using GITHUB_HEAD_REF and constructs
the proper branch ref (refs/heads/{branch_name}) for workflow dispatch.
Added comprehensive tests for:
- PR context branch ref resolution
- Non-PR context ref usage
- Branch names with slashes
- Proper cleanup of PR environment variables in tests
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
CopilotAI changed the title [WIP] Fix dispatch workflow branch reference in pull requestFix dispatch_workflow to use PR branch ref instead of merge refFeb 6, 2026
CopilotAI requested a review from pelikhanFebruary 6, 2026 06:25
core.info(`Using PR branch ref: ${ref}`);
} else {
// Use GITHUB_REF for non-PR contexts (push, workflow_dispatch, etc.)
ref = process.env.GITHUB_REF || context.ref || "refs/heads/main";

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 you need to resolve the default branch correctly if needed

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Fixed in 7ed0b69. Now properly resolves the repository's default branch by:

  1. Checking context.payload.repository.default_branch first
  2. Falling back to github.rest.repos.get() API if context unavailable
  3. Only using "refs/heads/main" as last resort if API call fails

Added tests to verify default branch resolution from both context and API fallback.

@github-actions

Copy link
Copy Markdown
Contributor

🔍 PR Triage Results

Category: bug | Risk: high | Priority: 53/100

Scores Breakdown

  • Impact: 35/50 - Critical bug fix for dispatch_workflow functionality in PR contexts. Prevents workflow dispatch failures when triggered from PRs. High impact - blocks PR-based workflow automation.
  • Urgency: 10/30 - Very recent PR (< 1 hour old). Fixes workflow dispatch in PR contexts but not yet ready (draft). Age penalty: 0 hours. Low urgency due to draft status.
  • Quality: 8/20 - Draft status with pending CI. Good description and comprehensive test coverage (3 test cases). Touches security-sensitive dispatch code. Needs CI validation and review.

📋 Recommended Action: defer

Draft PR with high risk due to dispatch workflow changes. Defer until marked ready for review and CI passes. Well-tested but needs validation.


Triaged by PR Triage Agent on 2026-02-06

AI generated by PR Triage Agent

Instead of hardcoding "refs/heads/main" as fallback, now properly resolves the
repository's default branch by:
1. Checking context.payload.repository.default_branch first
2. Falling back to querying github.rest.repos.get() API
3. Only using "refs/heads/main" as last resort if API call fails
Added tests for:
- Using repository default branch from context when no GITHUB_REF
- Falling back to API when context payload is missing
- All existing tests continue to pass
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
CopilotAI changed the title Fix dispatch_workflow to use PR branch ref instead of merge refFix dispatch_workflow to use PR branch ref and resolve default branch correctlyFeb 6, 2026
CopilotAI requested a review from pelikhanFebruary 6, 2026 06:37
@github-actions

github-actionsBot commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

Changeset Generator failed. Please review the logs for details.

@github-actions

Copy link
Copy Markdown
Contributor

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

@github-actions

github-actionsBot commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

🎬 THE ENDSmoke ClaudeMISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions

github-actionsBot commented Feb 6, 2026

Copy link
Copy Markdown
Contributor

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

@github-actions

Copy link
Copy Markdown
Contributor

Agent Container Tool Check Results

ToolStatusVersion/Notes
bash5.2.21
shavailable (basic shell works)
git2.52.0
jq1.7
yq4.50.1
curl8.5.0
gh2.86.0
node20.20.0
python33.12.3
go1.24.12
javabinary exists but execution blocked
dotnetbinary exists but execution blocked

Result: 10/12 tools fully functional ⚠️

Notes:

  • Java and .NET binaries are present in the container but cannot execute
  • This appears to be a container security restriction or configuration issue
  • Error: "cannot execute dotnet when renamed to bash" suggests a runtime protection mechanism
  • All other development tools (shell, version control, JSON/YAML processing, HTTP, GitHub CLI, Node.js, Python, Go) work correctly

AI generated by Agent Container Smoke Test

@github-actions

Copy link
Copy Markdown
Contributor

🔥 Smoke Test Results

PRs Tested:

Results:
✅ GitHub MCP | ✅ Safe Inputs GH | ⚠️ Serena MCP | ✅ Playwright | ✅ File I/O | ✅ Bash | ✅ Discussion Query | ✅ Discussion Comment | ✅ Build | ✅ Workflow Dispatch

Overall: PASS (9/10)

§21741356357

cc @pelikhan@Copilot

AI generated by Smoke Copilot

@github-actions

Copy link
Copy Markdown
Contributor

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

@pelikhan
pelikhan marked this pull request as ready for review February 6, 2026 06:49
CopilotAI review requested due to automatic review settings February 6, 2026 06:49
@pelikhan
pelikhan merged commit 9269b6f into mainFeb 6, 2026
164 of 167 checks passed
@pelikhan
pelikhan deleted the copilot/fix-pr-branch-ref-dispatch branch February 6, 2026 06:50

CopilotAI left a comment

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.

Pull request overview

This PR fixes dispatch_workflow to correctly handle branch references in different GitHub Actions contexts, particularly when triggered from pull requests. Previously, the code used GITHUB_REF which points to a merge ref (refs/pull/{PR_NUMBER}/merge) in PR contexts, causing workflow dispatch failures. The PR also improves default branch resolution to properly detect the repository's actual default branch instead of hardcoding "main".

Changes:

  • Implemented PR context detection using GITHUB_HEAD_REF to construct proper branch refs (refs/heads/{branch_name})
  • Added cascading default branch resolution: context payload → API call → "refs/heads/main" fallback
  • Added comprehensive test coverage for PR contexts, non-PR contexts, branch names with slashes, and default branch resolution scenarios

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
actions/setup/js/dispatch_workflow.cjsImplements PR branch ref detection using GITHUB_HEAD_REF and multi-level default branch resolution with proper error handling
actions/setup/js/dispatch_workflow.test.cjsAdds test setup for repos.get API mock and 6 new test cases covering PR contexts, branch name edge cases, and default branch resolution paths
Comments suppressed due to low confidence (1)

actions/setup/js/dispatch_workflow.test.cjs:443

  • This test modifies global.context.ref and global.context.payload but doesn't restore them afterward. This can cause test pollution if subsequent tests rely on the original state. Consider adding an afterEach hook to restore the original global.context state or save/restore these values within the test.
 it("should fall back to API when context payload is missing", async () => {
delete process.env.GITHUB_REF;
delete process.env.GITHUB_HEAD_REF;
global.context.ref = undefined;
global.context.payload = {};
github.rest.repos.get.mockResolvedValueOnce({
data: {
default_branch: "staging",
},
});
const config = {
workflows: ["test-workflow"],
workflow_files: {
"test-workflow": ".lock.yml",
},
};
const handler = await main(config);
const message = {
type: "dispatch_workflow",
workflow_name: "test-workflow",
inputs: {},
};
await handler(message, {});
// Should fetch default branch from API
expect(github.rest.repos.get).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
});
expect(github.rest.actions.createWorkflowDispatch).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
workflow_id: "test-workflow.lock.yml",
ref: "refs/heads/staging",
inputs: {},
});
});

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

Comment on lines +370 to +400
it("should use repository default branch when no GITHUB_REF is set", async () => {
delete process.env.GITHUB_REF;
delete process.env.GITHUB_HEAD_REF;
global.context.ref = undefined;
global.context.payload.repository.default_branch = "develop";

const config = {
workflows: ["test-workflow"],
workflow_files: {
"test-workflow": ".lock.yml",
},
};
const handler = await main(config);

const message = {
type: "dispatch_workflow",
workflow_name: "test-workflow",
inputs: {},
};

await handler(message, {});

// Should use the repository's default branch from context
expect(github.rest.actions.createWorkflowDispatch).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
workflow_id: "test-workflow.lock.yml",
ref: "refs/heads/develop",
inputs: {},
});
});

CopilotAIFeb 6, 2026

Copy link

Choose a reason for hiding this comment

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

This test modifies global.context.ref and global.context.payload.repository.default_branch but doesn't restore them afterward. This can cause test pollution if subsequent tests rely on the original state. Consider adding an afterEach hook to restore the original global.context state or save/restore these values within the test.

Copilot uses AI. Check for mistakes.
Comment on lines +402 to +443
it("should fall back to API when context payload is missing", async () => {
delete process.env.GITHUB_REF;
delete process.env.GITHUB_HEAD_REF;
global.context.ref = undefined;
global.context.payload = {};

github.rest.repos.get.mockResolvedValueOnce({
data: {
default_branch: "staging",
},
});

const config = {
workflows: ["test-workflow"],
workflow_files: {
"test-workflow": ".lock.yml",
},
};
const handler = await main(config);

const message = {
type: "dispatch_workflow",
workflow_name: "test-workflow",
inputs: {},
};

await handler(message, {});

// Should fetch default branch from API
expect(github.rest.repos.get).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
});

expect(github.rest.actions.createWorkflowDispatch).toHaveBeenCalledWith({
owner: "test-owner",
repo: "test-repo",
workflow_id: "test-workflow.lock.yml",
ref: "refs/heads/staging",
inputs: {},
});
});

CopilotAIFeb 6, 2026

Copy link

Choose a reason for hiding this comment

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

Missing test coverage for the error handling path when the API call to fetch the default branch fails. The implementation falls back to "refs/heads/main" and logs a warning (lines 54-55 in dispatch_workflow.cjs), but this scenario is not tested. Consider adding a test that mocks github.rest.repos.get to reject with an error and verifies the fallback behavior.

Copilot uses AI. Check for mistakes.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pelikhan