Repository navigation
Merge v4-beta to v4 (2026-10-20) #220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ae981ad
68ee3a6
85fafd0
c7a39cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| // Entry point of actions/node/prepare-trusted-publishing, for workflows that | ||
| // run `npm publish` themselves on a GitHub-hosted runner. | ||
| // | ||
| // Env: PACKAGE_DIR (default: the current directory), REGISTRY (the registry | ||
| // the job publishes to; package.json publishConfig.registry wins; default | ||
| // npmjs), GITHUB_WORKSPACE (the repository root, for `repository.directory`), | ||
| // GITHUB_SERVER_URL, GITHUB_REPOSITORY, GITHUB_EVENT_PATH. | ||
|
|
||
| import * as core from '@actions/core'; | ||
| import * as path from 'path'; | ||
|
|
||
| import { publicSourceRepository } from '../github'; | ||
| import { prepareRepository } from '../repository'; | ||
|
|
||
| const MESSAGES = { | ||
| 'other-registry': 'Not publishing to registry.npmjs.org: npm adds no provenance there, package.json left as is.', | ||
| 'private-repository': 'Private repository: npm adds no provenance, package.json left as is.', | ||
| added: 'Added `repository` to package.json for npm provenance.', | ||
| present: 'package.json `repository` already names this repository.', | ||
| }; | ||
|
|
||
| try { | ||
| const pkgDir = path.resolve(process.env.PACKAGE_DIR || '.'); | ||
| const result = prepareRepository({ | ||
| pkgDir, | ||
| workspaceRoot: process.env.GITHUB_WORKSPACE || process.cwd(), | ||
| registry: process.env.REGISTRY, | ||
| sourceRepository: publicSourceRepository(), | ||
| }); | ||
| core.info(`${path.join(pkgDir, 'package.json')}: ${MESSAGES[result]}`); | ||
| } catch (error) { | ||
| core.setFailed((error as Error).message); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import * as fs from 'fs'; | ||
|
|
||
| /** | ||
| * https://github.com/<owner>/<repo> when the repository being built is public | ||
| * on github.com, the only case where npm adds provenance on its own. The | ||
| * event payload says whether the repository is private. | ||
| */ | ||
| export function publicSourceRepository(env: NodeJS.ProcessEnv = process.env): string | undefined { | ||
| const { GITHUB_SERVER_URL: server, GITHUB_REPOSITORY: repository, GITHUB_EVENT_PATH: eventPath } = env; | ||
| if (server !== 'https://github.com' || !repository || !eventPath || !fs.existsSync(eventPath)) { | ||
| return undefined; | ||
| } | ||
| const event = JSON.parse(fs.readFileSync(eventPath, 'utf8')) as { repository?: { private?: boolean } }; | ||
| return event.repository?.private === false ? `${server}/${repository}` : undefined; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,26 +35,34 @@ export async function resolveRegistry(pkg: PackageJson & { name: string }, npmrc | |
| return configGet('registry'); | ||
| } | ||
|
|
||
| export type VersionState = 'published' | 'new-version' | 'new-package'; | ||
|
|
||
| /** | ||
| * Whether name@version is in the registry. Throws on any lookup failure other | ||
| * than "package not found". | ||
| * Where name@version stands in the registry: published, a new version of an | ||
| * existing package, or a package the registry does not have at all. Throws on | ||
| * any lookup failure other than "not found". | ||
| */ | ||
| export async function isPublished( | ||
| export async function versionState( | ||
| name: string, | ||
| version: string, | ||
| registry: string, | ||
| cwd: string, | ||
| run: Runner, | ||
| ): Promise<boolean> { | ||
| ): Promise<VersionState> { | ||
| // npm view: exit 0 + the version when it exists; exit 0 + no output when the | ||
| // package exists without that version; E404 when the package does not exist. | ||
| const args = ['view', `${name}@${version}`, 'version', `--registry=${registry}`]; | ||
| const result = await run('npm', args, { cwd }); | ||
| if (result.code === 0) { | ||
| return result.stdout.trim() !== ''; | ||
| return result.stdout.trim() !== '' ? 'published' : 'new-version'; | ||
| } | ||
| if (/\bE404\b/.test(result.stderr + result.stdout)) { | ||
| return false; | ||
| return 'new-package'; | ||
|
Comment on lines
59
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
After a version lookup returns Prompt To Fix With AIThis is a comment left during a code review.
Path: actions/node/npm-split-publish/src/registry.ts
Line: 59-60
Comment:
**Normal version bumps get rejected**
`versionState` treats every `E404` from `npm view name@version version` as a missing package. npm also returns `E404` when the package exists but that exact version does not. The new gate in `packWorkspace` therefore rejects normal npmjs releases with instructions to publish the first version by hand.
After a version lookup returns `E404`, query the package without the version before returning `new-package`. Add a test that distinguishes these two failures.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly. |
||
| } | ||
| throw new CommandError(['npm', ...args].join(' '), result); | ||
| } | ||
|
|
||
| /** Whether name@version is in the registry (see versionState). */ | ||
| export async function isPublished(name: string, version: string, registry: string, cwd: string, run: Runner): Promise<boolean> { | ||
| return (await versionState(name, version, registry, cwd, run)) === 'published'; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replacing
pnpm -r publishwithpublish-tarballsremoves custom-registry support here and innode-docker-simple-fast-pnpm.yaml. If a caller supplies a custom registry throughnpmrc-config, packing still accepts it, butnpmrcForrejects every host except npmjs and GitHub Packages. The release fails after its prepublish scripts have already run.Preserve that upload path, or reject the unsupported configuration before packing and document the changed input contract.
Prompt To Fix With AI