feat(ci): public-ref-guard — warn on cross-repo refs to non-public repos in PR title/body#1087
Merged
Merged
Conversation
…lic repos in PR title/body
Warn-only for the first week per issue plan; the blocking flip is a
one-line uncomment. Allowlist = the public repos; plain #N same-repo
refs always pass.
Work produced by the deepseek lane (Gate 0b round 2, cli#1067) and
gate-reviewed: fixed a require('@actions/core') that would shadow the
github-script-provided global, and deduped the bare repo#N pattern
re-matching the tail of owner/repo#N refs (negative lookbehind).
Fixes #1044
Co-Authored-By: Claude <noreply@anthropic.com>
Comment on lines
+9
to
+62
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Check cross-repo references | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const { title, body } = context.payload.pull_request; | ||
| const text = `${title}\n${body || ''}`; | ||
|
|
||
| const allowlist = new Set([ | ||
| 'squads-cli', | ||
| 'agents-squads', | ||
| 'engram', | ||
| 'slack-bot', | ||
| 'awesome-ai-agents' | ||
| ]); | ||
|
|
||
| const violations = new Set(); | ||
|
|
||
| // owner/repo#N e.g. agents-squads/some-repo#42 | ||
| const ownerRepoRef = /\b([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)#(\d+)\b/g; | ||
| let m; | ||
| while ((m = ownerRepoRef.exec(text)) !== null) { | ||
| if (!allowlist.has(m[2])) violations.add(m[0]); | ||
| } | ||
|
|
||
| // repo#N e.g. some-other-repo#123 — the lookbehind keeps this | ||
| // from re-matching the tail of an owner/repo#N reference. | ||
| const repoRef = /(?<![\/\w])([a-zA-Z0-9_-]+)#(\d+)\b/g; | ||
| while ((m = repoRef.exec(text)) !== null) { | ||
| if (!allowlist.has(m[1])) violations.add(m[0]); | ||
| } | ||
|
|
||
| // github.com/agents-squads/<repo> | ||
| const ghLink = /github\.com\/agents-squads\/([a-zA-Z0-9_-]+)/g; | ||
| while ((m = ghLink.exec(text)) !== null) { | ||
| if (!allowlist.has(m[1])) violations.add(m[0]); | ||
| } | ||
|
|
||
| // `core` is provided by actions/github-script — never require() it. | ||
| for (const ref of violations) { | ||
| core.warning( | ||
| `Cross-repo reference to non-public repo: ${ref}. ` + | ||
| `Guidance: move the pointer to the internal tracker or write [internal]` | ||
| ); | ||
| } | ||
|
|
||
| if (violations.size > 0) { | ||
| console.log(`Found ${violations.size} violation(s) — warn-only, exiting 0.`); | ||
| // Flip to blocking after the warn-week (issue #1044): | ||
| // core.setFailed(`Found ${violations.size} cross-repo reference violation(s).`); | ||
| } else { | ||
| console.log('No cross-repo reference violations.'); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes #1044 — new
public-ref-guardworkflow warns (::warning::annotations) when a PR title/body references repos outside the public allowlist (<owner>/<repo>#N,<repo>#N, orgithub.com/agents-squads/<repo>links). Warn-only for the first week; the blocking flip is a one-line uncomment marked in the file.Provenance
Authored by the deepseek lane during Gate 0b round 2 (#1067) — 58.5s, $0.0029 — then gate-reviewed with two fixes: dropped a
require('@actions/core')that would shadow the github-script-providedcoreglobal, and added a negative lookbehind so the barerepo#Npattern doesn't re-match the tail of everyowner/repo#Nref (dedup via Set).Verified
Matcher logic run offline against a fixture covering all three patterns + allowlisted refs + plain
#N: flags exactlyhq#465-style refs, private-repo links, and non-allowlisted owner/repo refs; zero false positives on allowlisted/same-repo refs.🤖 Generated with Claude Code