Skip to content

Bug: Cross-repo update-issue safe-outputs broken — repo missing from tool schema + wildcard validation fails #19347

@chrizbo

Description

@chrizbo

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) → 404

Contrast 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 key

Then 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

  1. Create two repos: org/source-repo (runs the workflow) and org/target-repo (has the issue to update).

  2. 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
  3. Run gh aw compile — the generated tools.json will NOT include repo in update_issue properties.

  4. The agent emits (no repo field because it's not in the tool schema):

    { "type": "update_issue", "issue_number": 42, "operation": "replace-island", "body": "..." }
  5. The handler defaults to context.repo (workflow's own repo, org/source-repo) → 404 Not Found because issue 42 doesn't exist there.

  6. 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.cjsvalidateRepo(), resolveTargetRepoConfig() (Bug 3)
  • actions/setup/js/update_handler_factory.cjsif (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.

Related

  • #19276 — Original issue for repo/operation fields not consumed
  • #19282 — PR that fixed attribution URLs and diagnostics (did not fix these bugs)

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions