forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 167
ci: check yarnrc if it exists #2608
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
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,44 +88,94 @@ function loadNxConfig(configFile) { | |
| return JSON.parse(nx); | ||
| } | ||
|
|
||
| /** | ||
| * Detects whether to use npm or yarn to publish based on .npmrc existence | ||
| * @returns {boolean} true if npm should be used, false if yarn should be used | ||
| * @throws {Error} if neither .npmrc nor .yarnrc.yml exists | ||
| */ | ||
| function shouldUseNpm() { | ||
| const hasNpmrc = fs.existsSync('.npmrc'); | ||
| const hasYarnrc = fs.existsSync('.yarnrc.yml'); | ||
|
|
||
| if (!hasNpmrc && !hasYarnrc) { | ||
| error('No package manager configuration found. Expected either .npmrc or .yarnrc.yml file.'); | ||
| throw new Error('No package manager configuration found'); | ||
| } | ||
|
|
||
| if (hasNpmrc && hasYarnrc) { | ||
| // If both exist, prefer npm (could be changed based on project preference) | ||
| info('Both .npmrc and .yarnrc.yml found, using npm configuration'); | ||
| return true; | ||
| } | ||
|
|
||
| return hasNpmrc; | ||
| } | ||
|
|
||
| function verifyNpmAuth(registry = NPM_DEFEAULT_REGISTRY) { | ||
| const npmErrorRegex = /npm error code (\w+)/; | ||
| const useNpm = shouldUseNpm(); | ||
| const spawnOptions = { | ||
| stdio: /** @type {const} */ ("pipe"), | ||
| shell: true, | ||
| windowsVerbatimArguments: true, | ||
| }; | ||
|
|
||
| const whoamiArgs = ["whoami", "--registry", registry]; | ||
| const whoami = spawnSync("npm", whoamiArgs, spawnOptions); | ||
| if (whoami.status !== 0) { | ||
| const error = whoami.stderr.toString(); | ||
| const m = error.match(npmErrorRegex); | ||
| const errorCode = m && m[1]; | ||
| switch (errorCode) { | ||
| case "EINVALIDNPMTOKEN": | ||
| throw new Error(`Invalid auth token for npm registry: ${registry}`); | ||
| case "ENEEDAUTH": | ||
| throw new Error(`Missing auth token for npm registry: ${registry}`); | ||
| default: | ||
| throw new Error(error); | ||
| if (useNpm) { | ||
| info("Using npm for authentication (found .npmrc)"); | ||
| const npmErrorRegex = /npm error code (\w+)/; | ||
|
|
||
| const whoamiArgs = ["whoami", "--registry", registry]; | ||
| const whoami = spawnSync("npm", whoamiArgs, spawnOptions); | ||
| if (whoami.status !== 0) { | ||
| const error = whoami.stderr.toString(); | ||
| const m = error.match(npmErrorRegex); | ||
| const errorCode = m && m[1]; | ||
| switch (errorCode) { | ||
| case "EINVALIDNPMTOKEN": | ||
| throw new Error(`Invalid auth token for npm registry: ${registry}`); | ||
| case "ENEEDAUTH": | ||
| throw new Error(`Missing auth token for npm registry: ${registry}`); | ||
| default: | ||
| throw new Error(error); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const tokenArgs = ["token", "list", "--registry", registry]; | ||
| const token = spawnSync("npm", tokenArgs, spawnOptions); | ||
| if (token.status !== 0) { | ||
| const error = token.stderr.toString(); | ||
| const m = error.match(npmErrorRegex); | ||
| const errorCode = m && m[1]; | ||
| const tokenArgs = ["token", "list", "--registry", registry]; | ||
| const token = spawnSync("npm", tokenArgs, spawnOptions); | ||
| if (token.status !== 0) { | ||
| const error = token.stderr.toString(); | ||
| const m = error.match(npmErrorRegex); | ||
| const errorCode = m && m[1]; | ||
|
|
||
| // E403 means the token doesn't have permission to list tokens, but that's | ||
| // not required for publishing. Only fail for other error codes. | ||
| if (errorCode === "E403") { | ||
| info(`Token verification skipped: token doesn't have permission to list tokens (${errorCode})`); | ||
| } else { | ||
| throw new Error(m ? `Auth token for '${registry}' returned error code ${errorCode}` : error); | ||
| } | ||
| } | ||
| } else { | ||
| info("Using yarn for authentication (no .npmrc found)"); | ||
|
|
||
| // E403 means the token doesn't have permission to list tokens, but that's | ||
| // not required for publishing. Only fail for other error codes. | ||
| if (errorCode === "E403") { | ||
| info(`Token verification skipped: token doesn't have permission to list tokens (${errorCode})`); | ||
| } else { | ||
| throw new Error(m ? `Auth token for '${registry}' returned error code ${errorCode}` : error); | ||
| const whoamiArgs = ["npm", "whoami", "--publish"]; | ||
| const whoami = spawnSync("yarn", whoamiArgs, spawnOptions); | ||
| if (whoami.status !== 0) { | ||
| const stderr = whoami.stderr.toString().trim(); | ||
| const stdout = whoami.stdout.toString().trim(); | ||
| const errorOutput = stderr || stdout || 'No error message available'; | ||
|
|
||
| // Yarn uses different error format | ||
| if (errorOutput.includes("Invalid authentication") || errorOutput.includes("Failed with errors")) { | ||
| throw new Error(`Invalid or missing auth token for registry: ${registry}`); | ||
| } | ||
|
Comment on lines
+167
to
+170
Member
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. I wouldn't have this block at all. The catch all below is fine. |
||
|
|
||
| // Provide more context about the yarn authentication failure | ||
| throw new Error(`Yarn authentication failed (exit code ${whoami.status}): ${errorOutput}`); | ||
| } | ||
|
|
||
| // Skip token listing for yarn since it doesn't support npm token commands | ||
| // The whoami check above is sufficient to verify authentication | ||
| info("Skipping token list check when using yarn (not required for publishing)"); | ||
| } | ||
| } | ||
|
|
||
|
|
||
Oops, something went wrong.
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.
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.
Not that it matters much, but this is throws away less work:
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.
I'll add these suggestions to my other open PR