🤖: Bug report submitted by AI
Summary
Follow-up to #15027 — the same context.repo hardcoding bug that was fixed in add_labels.cjs and close_issue.cjs also exists in remove_labels.cjs and assign_to_user.cjs. Both handlers ignore the target-repo config and always operate against the workflow's own repository.
Affected Files
actions/setup/js/remove_labels.cjs
- Lines 11-12: Only imports
safe_output_validator.cjs and error_helpers.cjs — does NOT import repo_helpers.cjs
- Line 124: Hardcoded
...context.repo in the removeLabel API call:
await github.rest.issues.removeLabel({
...context.repo,
issue_number: itemNumber,
name: label,
});
actions/setup/js/assign_to_user.cjs
- Lines 8-9: Only imports
safe_output_processor.cjs and error_helpers.cjs — does NOT import repo_helpers.cjs
- Lines 104-105: Hardcoded
context.repo.owner / context.repo.repo in the addAssignees API call:
await github.rest.issues.addAssignees({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
assignees: uniqueAssignees,
});
Root Cause
When #15027 was fixed, add_labels.cjs and close_issue.cjs were updated to use resolveTargetRepoConfig / resolveAndValidateRepo from repo_helpers.cjs. The same fix was not applied to remove_labels.cjs and assign_to_user.cjs.
The Plumbing Already Works
Everything upstream of the handler JS is wired correctly:
- Go compiler structs: Both
RemoveLabelsConfig and AssignToUserConfig embed SafeOutputTargetConfig (which provides TargetRepoSlug and AllowedRepos)
- Config generation (
compiler_safe_outputs_config.go): The remove_labels builder calls AddIfNotEmpty("target-repo", c.TargetRepoSlug) and AddStringSlice("allowed_repos", c.AllowedRepos). The assign_to_user builder similarly extracts the config via addRepoParameterIfNeeded in safe_outputs_config_generation.go (line 894-898).
- Docs (
.github/aw/github-agentic-workflows.md): Both remove-labels and assign-to-user document target-repo as a supported field.
- MCP tool schema: The compiler correctly adds the
repo parameter to the safe-outputs MCP tool description when allowed-repos is configured.
The config IS passed correctly at runtime — it's just never read by the handlers.
Fix
Apply the exact same pattern from add_labels.cjs (the fix from #15027):
For each handler:
-
Add the import:
const { resolveTargetRepoConfig, resolveAndValidateRepo } = require("./repo_helpers.cjs");
-
In the main() factory function, resolve the target repo from config:
const { defaultTargetRepo, allowedRepos } = resolveTargetRepoConfig(config);
-
In the message handler function, resolve and validate per-message:
const repoResult = resolveAndValidateRepo(message, defaultTargetRepo, allowedRepos, "label"); // or "assignee"
if (!repoResult.success) {
core.warning(`Skipping: ${repoResult.error}`);
return { success: false, error: repoResult.error };
}
const { repo: itemRepo, repoParts } = repoResult;
-
Replace context.repo / ...context.repo with repoParts.owner / repoParts.repo in the API call.
Reference implementation: actions/setup/js/add_labels.cjs lines 13, 24, 57, 65, 127-128
Use Case
We're building a stale-issue re-triage workflow in a side repo (gh-aw-test) that will eventually run cross-repo from microsoft/vscode-engineering against microsoft/vscode. The workflow needs to:
Reproduction
- Create a workflow with
target-repo set to an external repo:
safe-outputs:
remove-labels:
allowed: ["triage-needed"]
target-repo: "org/other-repo"
assign-to-user:
max: 1
target-repo: "org/other-repo"
- Trigger the workflow and have the agent call
remove_labels or assign_to_user on an issue in the external repo
- Both will 404 because they operate on
context.repo instead of the configured target repo
🤖: Bug report submitted by AI
Summary
Follow-up to #15027 — the same
context.repohardcoding bug that was fixed inadd_labels.cjsandclose_issue.cjsalso exists inremove_labels.cjsandassign_to_user.cjs. Both handlers ignore thetarget-repoconfig and always operate against the workflow's own repository.Affected Files
actions/setup/js/remove_labels.cjssafe_output_validator.cjsanderror_helpers.cjs— does NOT importrepo_helpers.cjs...context.repoin theremoveLabelAPI call:actions/setup/js/assign_to_user.cjssafe_output_processor.cjsanderror_helpers.cjs— does NOT importrepo_helpers.cjscontext.repo.owner/context.repo.repoin theaddAssigneesAPI call:Root Cause
When #15027 was fixed,
add_labels.cjsandclose_issue.cjswere updated to useresolveTargetRepoConfig/resolveAndValidateRepofromrepo_helpers.cjs. The same fix was not applied toremove_labels.cjsandassign_to_user.cjs.The Plumbing Already Works
Everything upstream of the handler JS is wired correctly:
RemoveLabelsConfigandAssignToUserConfigembedSafeOutputTargetConfig(which providesTargetRepoSlugandAllowedRepos)compiler_safe_outputs_config.go): Theremove_labelsbuilder callsAddIfNotEmpty("target-repo", c.TargetRepoSlug)andAddStringSlice("allowed_repos", c.AllowedRepos). Theassign_to_userbuilder similarly extracts the config viaaddRepoParameterIfNeededinsafe_outputs_config_generation.go(line 894-898)..github/aw/github-agentic-workflows.md): Bothremove-labelsandassign-to-userdocumenttarget-repoas a supported field.repoparameter to the safe-outputs MCP tool description whenallowed-reposis configured.The config IS passed correctly at runtime — it's just never read by the handlers.
Fix
Apply the exact same pattern from
add_labels.cjs(the fix from #15027):For each handler:
Add the import:
In the
main()factory function, resolve the target repo from config:In the message handler function, resolve and validate per-message:
Replace
context.repo/...context.repowithrepoParts.owner/repoParts.repoin the API call.Reference implementation:
actions/setup/js/add_labels.cjslines 13, 24, 57, 65, 127-128Use Case
We're building a stale-issue re-triage workflow in a side repo (
gh-aw-test) that will eventually run cross-repo frommicrosoft/vscode-engineeringagainstmicrosoft/vscode. The workflow needs to:add_labelswas fixed inclose_issueandadd_labelssafe output handlers do not support target-repo for cross-repository operations #15027)triage-neededlabel (broken —remove_labelsignorestarget-repo)assign_to_userignorestarget-repo)Reproduction
target-reposet to an external repo:remove_labelsorassign_to_useron an issue in the external repocontext.repoinstead of the configured target repo