-
Notifications
You must be signed in to change notification settings - Fork 296
Description
Summary
Three cascading bugs prevent cross-repo update-issue safe-output operations from working. We discovered these while building a workflow that syncs data from repo A into issues on repo B using gh-aw v0.51.6.
All three bugs had to be worked around before the cross-repo update-issue flow functioned. add-comment is unaffected because it has separate routing logic that uses target-repo from config as the default.
Version: gh-aw v0.51.6
Bug 1: repo field missing from compiled tool schema (CRITICAL)
This is the most impactful bug. The gh aw compile tool schema generator does not include repo as an input parameter for the update_issue tool, even when target-repo is configured. The agent literally cannot set repo because it's not in its tool definition.
The compiled tools.json for update_issue includes these properties:
assignees,body,issue_number,labels,milestone,operation,status,title
repo is NOT included.
Meanwhile, the validation schema (in config.json) DOES include repo:
"repo": { "type": "string", "maxLength": 256 }And the handler factory (update_handler_factory.cjs) checks for item.repo to route cross-repo:
if (item.repo) {
effectiveContext = { ...context, repo: repoResult.repoParts };
}This creates a dead path: validation accepts repo, handler routes on repo, but the tool schema never exposes it to the agent.
Workaround: Manually edit the lock file to add repo to the update_issue tool schema properties. This is fragile and overwritten on every gh aw compile.
Bug 2: update_handler_factory doesn't use defaultTargetRepo for routing
Even if Bug 1 is fixed and the agent includes repo, the handler factory only routes cross-repo when item.repo is explicitly set. It does NOT fall back to defaultTargetRepo from config.
// Current behavior in update_handler_factory.cjs:
if (item.repo) {
// Only enters cross-repo path when agent explicitly sets repo
effectiveContext = { ...context, repo: repoResult.repoParts };
}
// If item.repo is missing, defaults to context.repo (workflow's own repo) → 404Contrast with add_comment: The add_comment handler always resolves the target repo from config, so target-repo: "org/other-repo" works without the agent needing to set anything.
Workaround: Add explicit instructions in the agent prompt to always include the repo field, AND manually patch the tool schema (Bug 1 workaround).
Bug 3: target-repo: "*" wildcard not honored in validation
When target-repo: "*", resolveTargetRepoConfig() sets:
defaultTargetRepo = "*"; // from target-repo config
allowedRepos = new Set(); // empty — config has no allowed_repos keyThen validateRepo("org/other-repo", "*", Set()) runs:
qualifiedRepo === defaultRepo→"org/other-repo" === "*"→ false (literal comparison)isRepoAllowed(qualifiedRepo, allowedRepos)→ empty set → false
Error: Repository 'org/other-repo' is not in the allowed-repos list. Allowed: *
Workaround: Set target-repo to the explicit repo (e.g., "org/other-repo") instead of "*".
Reproduction
-
Create two repos:
org/source-repo(runs the workflow) andorg/target-repo(has the issue to update). -
Configure a workflow in
org/source-repo:safe-outputs: github-token: ${{ secrets.CROSS_REPO_TOKEN }} update-issue: body: footer: false target: "*" target-repo: "org/target-repo" max: 5
-
Run
gh aw compile— the generatedtools.jsonwill NOT includerepoinupdate_issueproperties. -
The agent emits (no
repofield because it's not in the tool schema):{ "type": "update_issue", "issue_number": 42, "operation": "replace-island", "body": "..." } -
The handler defaults to
context.repo(workflow's own repo,org/source-repo) → 404 Not Found because issue 42 doesn't exist there. -
If you use
target-repo: "*"instead of an explicit repo, the wildcard validation rejects the target → "not in the allowed-repos list".
Suggested fixes
Fix 1: Add repo to tool schema when target-repo is configured
In the tool schema generator / compiler, when target-repo is set (especially to "*" or a cross-repo value), include repo as a tool input parameter for update_issue and update_pull_request:
"repo": {
"type": "string",
"description": "Target repository in 'owner/repo' format for cross-repo operations."
}Fix 2: Use defaultTargetRepo for routing in update_handler_factory
Make the factory consistent with add_comment — always resolve via resolveAndValidateRepo, not just when item.repo is set:
// Always resolve repo (matches add_comment behavior)
const repoResult = resolveAndValidateRepo(item, defaultTargetRepo, allowedRepos, itemTypeName);
if (!repoResult.success) { /* handle error */ }
effectiveContext = { ...context, repo: repoResult.repoParts };Fix 3: Handle defaultRepo === "*" in validateRepo()
Add at the top of validateRepo():
if (defaultRepo === "*") {
return { valid: true, error: null, qualifiedRepo };
}Key files involved
actions/setup/js/repo_helpers.cjs—validateRepo(),resolveTargetRepoConfig()(Bug 3)actions/setup/js/update_handler_factory.cjs—if (item.repo)routing logic (Bug 2)- Compiler / tool schema generator — tool properties generation (Bug 1)
Impact
Cross-repo update-issue and update-pull-request operations are completely broken out of the box. The workflow run completes as "success" but no updates are applied to the target repo. Three manual workarounds are required to make it function. add-comment is unaffected due to its separate routing logic.