From 82f8daf75dfe715094246ff550ab2442c6d189c9 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 2 Aug 2026 08:34:23 +0000 Subject: [PATCH] fix(ci): hand the cross-repo token to github-script instead of requiring @actions/github MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `require('@actions/github')` is not resolvable from a github-script `script:` block — the action bundles its dependencies, so it dies with MODULE_NOT_FOUND. Passing the token via `github-token:` makes the injected `github` client the cross-repo one, so no second client is needed at all. Observed in objectui, whose copy reached that line first. Supersedes the rename in #4573: that fixed the parse-time collision, which is what let the run get far enough to hit this. --- .changeset/fix-cross-repo-closer-require.md | 23 ++++++++++++++++++ .github/workflows/cross-repo-issue-closer.yml | 24 ++++++++++++------- 2 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 .changeset/fix-cross-repo-closer-require.md diff --git a/.changeset/fix-cross-repo-closer-require.md b/.changeset/fix-cross-repo-closer-require.md new file mode 100644 index 0000000000..990b00b01c --- /dev/null +++ b/.changeset/fix-cross-repo-closer-require.md @@ -0,0 +1,23 @@ +--- +--- + +fix(ci): hand the cross-repo token to github-script instead of requiring @actions/github + +Release-nothing: touches `.github/workflows/cross-repo-issue-closer.yml` only. + +`require('@actions/github')` is not resolvable from a github-script `script:` +block — the action bundles its dependencies, so the call fails at runtime with +`MODULE_NOT_FOUND`. The token is now handed to the action itself +(`github-token:`), which makes the injected `github` client the cross-repo one, +with `secrets.GITHUB_TOKEN` as the fallback so the report path can still +comment on the pull request when no cross-repo credential is configured. + +Observed in objectui, whose copy of this workflow reached that line first. Its +run also confirmed the credential logging added alongside works, printing +`CROSS_REPO_ISSUE_TOKEN: configured` before failing at the require. + +This supersedes #4573, which renamed the second client without removing it — +the rename fixed the identifier collision that aborted parsing, and only then +did the run get far enough to hit the unresolvable module. Three failures in +three consecutive runs, each one further down the same script: parse, resolve, +then (expected next) the API calls themselves. diff --git a/.github/workflows/cross-repo-issue-closer.yml b/.github/workflows/cross-repo-issue-closer.yml index 8f6ebb957d..066bf527fc 100644 --- a/.github/workflows/cross-repo-issue-closer.yml +++ b/.github/workflows/cross-repo-issue-closer.yml @@ -46,6 +46,12 @@ jobs: # to the repository running the workflow, which is the whole problem. CROSS_REPO_TOKEN: ${{ secrets.CROSS_REPO_ISSUE_TOKEN }} with: + # Hand the cross-repo token to the action itself, so `github` IS the + # cross-repo client. `require('@actions/github')` does NOT work here: + # github-script bundles its dependencies and the module is not + # resolvable from the script scope (`MODULE_NOT_FOUND`). Falling back + # to GITHUB_TOKEN keeps the report path able to comment on this PR. + github-token: ${{ secrets.CROSS_REPO_ISSUE_TOKEN || secrets.GITHUB_TOKEN }} script: | const body = context.payload.pull_request.body || ''; const prUrl = context.payload.pull_request.html_url; @@ -60,6 +66,12 @@ jobs: 'gi', ); + // Report credential state on EVERY run, before any early return. + const token = process.env.CROSS_REPO_TOKEN; + core.info( + `CROSS_REPO_ISSUE_TOKEN: ${token ? 'configured' : 'ABSENT — cross-repo closes will be reported, not performed'}`, + ); + const targets = new Map(); for (const [, owner, repo, number] of body.matchAll(pattern)) { const key = `${owner}/${repo}#${number}`; @@ -75,8 +87,6 @@ jobs: } core.info(`Cross-repo targets: ${[...targets.keys()].join(', ')}`); - const token = process.env.CROSS_REPO_TOKEN; - if (!token) { // Degrade VISIBLY. Someone has to close these by hand, and this // comment is the only thing that will tell them so. @@ -101,27 +111,23 @@ jobs: return; } - // A second client: `github` is bound to GITHUB_TOKEN, which has no - // write access outside this repository. - const octokit = require('@actions/github').getOctokit(token); - for (const [key, t] of targets) { try { - const { data: issue } = await octokit.rest.issues.get({ + const { data: issue } = await github.rest.issues.get({ owner: t.owner, repo: t.repo, issue_number: t.number, }); if (issue.state === 'closed') { core.info(`${key} is already closed — skipping.`); continue; } - await octokit.rest.issues.createComment({ + await github.rest.issues.createComment({ owner: t.owner, repo: t.repo, issue_number: t.number, body: `已由 ${thisRepo} 的 ${prUrl} 修复并合并。\n\n` + `(跨仓库的关闭关键字不会自动生效,本条由 \`cross-repo-issue-closer\` 工作流代为收口。)\n\n` + `---\n_Generated by [Claude Code](https://claude.ai/code)_`, }); - await octokit.rest.issues.update({ + await github.rest.issues.update({ owner: t.owner, repo: t.repo, issue_number: t.number, state: 'closed', state_reason: 'completed', });