Skip to content

feat(update_project): add content-repo for cross-repo project item resolution#21387

Closed
Copilot wants to merge 5 commits intomainfrom
copilot/update-project-safe-output-again
Closed

feat(update_project): add content-repo for cross-repo project item resolution#21387
Copilot wants to merge 5 commits intomainfrom
copilot/update-project-safe-output-again

Conversation

Copy link
Contributor

Copilot AI commented Mar 17, 2026

update_project hardcoded context.repo when resolving content_number to a GraphQL node ID, making it impossible to update project fields for items originating from other repositories — a common pattern for org-level projects aggregating issues across multiple repos.

Changes

  • Schema (schemas/agent-output.json, safe_outputs_tools.json): Added optional content_repo field ("owner/repo" format) to update_project input/output schemas
  • Runtime (update_project.cjs): When content_repo is present, uses it to resolve content_number instead of context.repo; trims whitespace from the value and each part before use; warns and falls back to context.repo on invalid format
  • Normalization: Added aliases in normalizeUpdateProjectOutput()contentRepo → content_repo (camelCase) and content-repo → content_repo (YAML dash-style) — so all three forms are accepted transparently

Usage

- type: update_project
  project: https://github.com/orgs/myorg/projects/42
  content_type: issue
  content_number: 99
  content-repo: github/docs        # issue lives here, not in the workflow host repo
  fields:
    Status: "In Triage"

The field accepts any of content_repo, content-repo (YAML dash-style), or contentRepo (camelCase). Without content_repo, behavior is unchanged — context.repo is used as before.

Testing

  • JS tests: 7 new tests covering cross-repo issue/PR resolution, content-repo dash alias, whitespace trimming, and invalid format fallback (warning + context.repo used)

📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

…roject item resolution

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title [WIP] Update project safe output to include content_repo feat(update_project): add content_repo for cross-repo project item resolution Mar 17, 2026
Copilot AI requested a review from pelikhan March 17, 2026 13:00
@pelikhan
Copy link
Contributor

@copilot

  • ensure the go parser handles this field and puts it into the config
  • add tests, including full agentic workflow tests
  • ensure the JavaScript uses this field

@pelikhan pelikhan marked this pull request as ready for review March 17, 2026 13:28
Copilot AI review requested due to automatic review settings March 17, 2026 13:28
Copy link
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

Adds cross-repo support to update_project by allowing callers to specify the repository that owns the issue/PR being added/updated, instead of always using the workflow host repository.

Changes:

  • Extend update_project schemas to accept optional content_repo (owner/repo) for cross-repo item resolution.
  • Update update_project.cjs to resolve content_number against content_repo when provided, with warning + fallback on invalid format.
  • Add tests for cross-repo issue/PR resolution and for contentRepocontent_repo normalization.

Reviewed changes

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

Show a summary per file
File Description
schemas/agent-output.json Adds content_repo to the update_project output schema.
pkg/workflow/js/safe_outputs_tools.json Adds content_repo to the safe-outputs tool schema for update_project.
actions/setup/js/safe_outputs_tools.json Mirrors the safe-outputs schema update for the action runtime copy.
actions/setup/js/update_project.cjs Uses content_repo (when present) to resolve the GraphQL node ID for cross-repo issues/PRs; adds contentRepo alias normalization.
actions/setup/js/update_project.test.cjs Adds coverage for cross-repo resolution and camelCase alias normalization.

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

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +1017 to +1021
const parts = output.content_repo.split("/");
if (parts.length === 2 && parts[0] && parts[1]) {
contentOwner = parts[0];
contentRepo = parts[1];
core.info(`Using content_repo for resolution: ${contentOwner}/${contentRepo}`);
Comment on lines +1022 to +1024
} else {
core.warning(`Invalid content_repo format "${output.content_repo}": expected "owner/repo". Falling back to workflow host repository.`);
}
@pelikhan
Copy link
Contributor

@copilot make sure the field naming in the front matter uses dash not underscore (content-repo). Review comments.

…idation, Go parser support, and agentic workflow test

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot

  • ensure the go parser handles this field and puts it into the config
  • add tests, including full agentic workflow tests...

Addressed in commit ae6c1f5:

Go parser — Added AllowedRepos []string to UpdateProjectConfig, parsed via parseAllowedReposFromConfig() in parseUpdateProjectConfig().

Compiler — Added AddStringSlice("allowed_repos", c.AllowedRepos) to the update_project handler config builder, so the value flows into GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG.

Schema — Added allowed-repos array property to the update-project section in main_workflow_schema.json.

JavaScriptmain(config) now reads config.allowed_repos and builds an allowedContentRepos Set. When non-empty, updateProject() validates content_repo against this set (context.repo is always allowed); unauthorized repos throw ERR_PERMISSION.

Tests:

  • Go: TestUpdateProjectAllowedReposConfig (parser) and TestUpdateProjectAllowedReposInHandlerConfig (compiler → JSON)
  • JS: 5 new tests covering allowed/rejected/default-repo/unrestricted/logging scenarios
  • Agentic workflow: pkg/cli/workflows/test-update-project-cross-repo.md

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw /home/REDACTED/wor-c /home/REDACTED/wor&#34;prettier&#34; --write &#39;scripts/**/*.js&#39; --ignore-path .prettierignore --log-level=error x_amd64/vet --no�� h ../../../.prettierignore /home/REDACTED/work/gh-aw/gh-aw/pk-ifaceassert x_amd64/vet /home/REDACTED/wornode /home/REDACTED/wor/home/REDACTED/work/gh-aw/gh-aw/actions/setup/js/node_modules/.bin/prettier /home/REDACTED/wor--write x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw /home/REDACTED/wor-c /home/REDACTED/wor&#34;prettier&#34; --write &#39;scripts/**/*.js&#39; --ignore-path .prettierignore --log-level=error x_amd64/vet --no�� h ../../../.prettierignore /home/REDACTED/work/gh-aw/gh-aw/pk-ifaceassert x_amd64/vet (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw /home/REDACTED/wor/home/REDACTED/.npm/_npx/b388654678d519d9/node_modules/.bin/prettier /home/REDACTED/wor--write x_amd64/vet --no�� h ../../../.pret.prettierignore /home/REDACTED/wor--log-level=error x_amd64/vet est.go en_test.go (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha h ../../../.pret.prettierignore (http block)
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha -json GO111MODULE ache/go/1.25.0/xGOMODCACHE GOINSECURE GOMOD GOMODCACHE go env &#39;**/*.ts&#39; &#39;**/*.GOINSECURE GO111MODULE ache/go/1.25.0/xGOMODCACHE GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/github/gh-aw
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .visibility --noprofile .cfg 64/pkg/tool/linux_amd64/vet (http block)
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .visibility -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE r: $owner, name: $name) { hasDiscussionsEnabled } } GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/# --jq .object.sha --noprofile (http block)
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/# --jq .object.sha -json GO111MODULE $name) { hasDiscussionsEnabled } } GOINSECURE GOMOD GOMODCACHE go 0/x6�� -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)

If you need me to access, download, or install something from one of these locations, you can either:

@pelikhan
Copy link
Contributor

@copilot revert ae6c1f5 and focus on content-repo

…d missing test for invalid format

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot make sure the field naming in the front matter uses dash not underscore (content-repo). Review comments.

Done in ba434cb:

  • Dash alias (content-repo): normalizeUpdateProjectOutput() now maps output["content-repo"]output.content_repo so YAML-style output using content-repo: owner/repo works transparently alongside the existing content_repo and contentRepo aliases.
  • Trimming: output.content_repo is .trim()-ed before splitting, and each part is also trimmed, so values like " owner/repo " no longer cause silent GraphQL failures.
  • Invalid-format test: Added test asserting exactly one warning is emitted (Invalid content_repo format "noslashrepo": expected "owner/repo". Falling back to workflow host repository.) and that the fallback uses context.repo for the content lookup.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD GOMODCACHE erignore env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD GOMODCACHE erignore env tformat GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD ode-gyp-bin/node-json ache/go/1.25.0/xGO111MODULE env 011585/b369/_pkgGOINSECURE GO111MODULE 64/bin/go GOINSECURE b/gh-aw/tmp GOMODCACHE go (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE sh (http block)
  • https://api.github.com/repos/github/gh-aw
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .visibility &#34;prettier&#34; --check &#39;scripts/**/*GOINSECURE /opt/hostedtoolcGO111MODULE 64/bin/go tierignore pkg/workflow/disapi 64/bin/go go env -json GO111MODULE r: $owner, name: $name) { hasDiscussionsEnabled } } GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/# --jq .object.sha -json GO111MODULE $name) { hasDiscussionsEnabled } } GOINSECURE GOMOD GOMODCACHE sh -c npx prettier --c- GOPROXY 64/bin/go GOSUMDB GOWORK 64/bin/go sh (http block)

If you need me to access, download, or install something from one of these locations, you can either:

…-repo support only

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 17, 2026

@copilot revert ae6c1f5 and focus on content-repo

Done in 282c9a5. Reverted the ae6c1f5 changes: removed AllowedRepos from UpdateProjectConfig, removed AddStringSlice("allowed_repos", ...) from the compiler, removed allowed-repos from the schema, dropped the 5 allowed_repos JS tests and the agentic workflow test file. What remains is the content-repo / content_repo / contentRepo multi-alias normalization, whitespace trimming, and the cross-repo resolution tests.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD erignore ache/go/1.25.0/xGO111MODULE env 4919487/b420/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD erignore ache/go/1.25.0/xGO111MODULE env 4919487/b403/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh api graphql -f query=query($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { hasDiscussionsEnabled } } -f owner=github -f name=gh-aw GOMOD erignore ache/go/1.25.0/xGO111MODULE env 4919487/b356/_pkGOINSECURE GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b
    • Triggering command: /usr/bin/gh gh api /repos/astral-sh/setup-uv/git/ref/tags/eac588ad8def6316056a12d4907a9d4d84ff7a3b --jq .object.sha -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE node (http block)
  • https://api.github.com/repos/github/gh-aw
    • Triggering command: /usr/bin/gh gh api /repos/github/gh-aw --jq .visibility -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go env -json GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE go (http block)
  • https://api.github.com/repos/githubnext/agentics/git/ref/tags/
    • Triggering command: /usr/bin/gh gh api /repos/githubnext/agentics/git/ref/tags/# --jq .object.sha dMuX/wDZh-6xMiPyGOSUMDB GO111MODULE 64/bin/go GOINSECURE GOMOD GOMODCACHE 4919487/b356/importcfg /hom�� k/gh-aw/gh-aw/internal/tools/actGOINSECURE **/*.cjs 64/bin/go **/*.json --ignore-path ../../../.pretti/home/REDACTED/work/gh-aw/gh-aw/.github/workflows /opt/hostedtoolcconfig (http block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI changed the title feat(update_project): add content_repo for cross-repo project item resolution feat(update_project): add content-repo for cross-repo project item resolution Mar 17, 2026
@pelikhan pelikhan closed this Mar 17, 2026
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.

update_project safe output: add content_repo for cross-repo project item resolution

3 participants