-
-
Notifications
You must be signed in to change notification settings - Fork 396
fix: parsing of .npmrc file #115
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
base: master
Are you sure you want to change the base?
Changes from all commits
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.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import fs from "fs"; | ||
| import path from "path"; | ||
| import * as ini from "ini"; | ||
| import fixtures from "fixturez"; | ||
| import { checkNpmConfig } from "./npmUtils"; | ||
|
|
||
| const f = fixtures(__dirname); | ||
| const authToken = "npm_abc"; | ||
|
|
||
| describe("checkNpmConfig", () => { | ||
| let tmpDir: string; | ||
| let npmrcPath: string; | ||
|
|
||
| beforeEach(() => { | ||
| tmpDir = f.temp(); | ||
| npmrcPath = path.join(tmpDir, ".npmrc"); | ||
| }); | ||
|
|
||
| describe("when .npmrc exists", () => { | ||
| describe("when authToken is defined", () => { | ||
| beforeEach(() => { | ||
| fs.writeFileSync( | ||
| npmrcPath, | ||
| ini.stringify({ | ||
| email: "npm@company.com", | ||
| "//registry.npmjs.org/:_authToken": authToken, | ||
| }) | ||
| ); | ||
| }); | ||
| test("should not change the .npmrc file", () => { | ||
| checkNpmConfig({ HOME: tmpDir }); | ||
|
|
||
| const npmConfig = ini.parse(fs.readFileSync(npmrcPath, "utf-8")); | ||
| expect(npmConfig).toMatchInlineSnapshot(` | ||
| Object { | ||
| "//registry.npmjs.org/:_authToken": "npm_abc", | ||
| "email": "npm@company.com", | ||
| } | ||
| `); | ||
| }); | ||
| }); | ||
| describe("when authToken is not defined", () => { | ||
| beforeEach(() => { | ||
| fs.writeFileSync( | ||
| npmrcPath, | ||
| ini.stringify({ | ||
| email: "npm@company.com", | ||
| }) | ||
| ); | ||
| }); | ||
| describe("when NPM_TOKEN environment variable is not defined", () => { | ||
| test("it should log a warning", () => { | ||
| console.warn = jest.fn(); | ||
| checkNpmConfig({ | ||
| HOME: tmpDir, | ||
| NPM_TOKEN: undefined, | ||
| }); | ||
| expect(console.warn).toHaveBeenCalledWith( | ||
| "Missing `NPM_TOKEN` environment variable, skipping update of .npmrc file." | ||
| ); | ||
| }); | ||
| }); | ||
| test("should inject NPM_TOKEN value in .npmrc file", () => { | ||
| checkNpmConfig({ | ||
| HOME: tmpDir, | ||
| NPM_TOKEN: authToken, | ||
| }); | ||
|
|
||
| const npmConfig = ini.parse(fs.readFileSync(npmrcPath, "utf-8")); | ||
| expect(npmConfig).toMatchInlineSnapshot(` | ||
| Object { | ||
| "//registry.npmjs.org/:_authToken": "npm_abc", | ||
| "email": "npm@company.com", | ||
| } | ||
| `); | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe("when .npmrc does not exist", () => { | ||
| describe("when NPM_TOKEN environment variable is not defined", () => { | ||
| test("it should log a warning", () => { | ||
| console.warn = jest.fn(); | ||
| checkNpmConfig({ | ||
| HOME: tmpDir, | ||
| NPM_TOKEN: undefined, | ||
| }); | ||
| expect(console.warn).toHaveBeenCalledWith( | ||
| "Missing `NPM_TOKEN` environment variable, skipping creation of .npmrc file." | ||
| ); | ||
| }); | ||
| }); | ||
| test("should create a new .npmrc config", () => { | ||
| checkNpmConfig({ | ||
| HOME: tmpDir, | ||
| NPM_TOKEN: authToken, | ||
| }); | ||
|
|
||
| const npmConfig = ini.parse(fs.readFileSync(npmrcPath, "utf-8")); | ||
| expect(npmConfig).toMatchInlineSnapshot(` | ||
| Object { | ||
| "//registry.npmjs.org/:_authToken": "npm_abc", | ||
| } | ||
| `); | ||
| }); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| import fs from "fs"; | ||
| import * as ini from "ini"; | ||
|
|
||
| // https://docs.npmjs.com/using-private-packages-in-a-ci-cd-workflow#create-and-check-in-a-project-specific-npmrc-file | ||
| const npmRegistryTokenKey = "//registry.npmjs.org/:_authToken"; | ||
|
Contributor
Author
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 did some research and couldn't find a case where the value isn't exactly like this (for the npm registry). Therefore I think we can omit the regex and simply do a 1:1 check. |
||
|
|
||
| export const checkNpmConfig = ( | ||
| // Allow to inject a custom object, useful in tests. | ||
| processEnv = process.env | ||
| ) => { | ||
| const userNpmrcPath = `${processEnv.HOME}/.npmrc`; | ||
|
|
||
| if (fs.existsSync(userNpmrcPath)) { | ||
| console.log(`Found existing user .npmrc file at ${userNpmrcPath}.`); | ||
|
|
||
| // Parse the `.npmrc` content using the `npm/ini` package. | ||
| const npmConfig = ini.parse(fs.readFileSync(userNpmrcPath, "utf-8")); | ||
|
Contributor
Author
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. We use |
||
|
|
||
| let hasAuthTokenForDefaultNpmRegistry = false; | ||
| // Check if there is at least a registry defined with an `_authToken`. | ||
| for (const [key, value] of Object.entries(npmConfig)) { | ||
| if (npmRegistryTokenKey === key && Boolean(value)) { | ||
| hasAuthTokenForDefaultNpmRegistry = true; | ||
| } | ||
| } | ||
|
|
||
| if (hasAuthTokenForDefaultNpmRegistry) { | ||
| console.log( | ||
| "The .npmrc file has an entry for the npm registry with an authToken defined." | ||
| ); | ||
| } else { | ||
| console.log( | ||
| "The .npmrc file does not have an authToken defined, appending one using the `NPM_TOKEN` environment variable..." | ||
| ); | ||
| if (processEnv.NPM_TOKEN) { | ||
| npmConfig["//registry.npmjs.org/:_authToken"] = processEnv.NPM_TOKEN; | ||
| fs.writeFileSync(userNpmrcPath, ini.stringify(npmConfig)); | ||
| } else { | ||
| console.warn( | ||
| "Missing `NPM_TOKEN` environment variable, skipping update of .npmrc file." | ||
|
Contributor
Author
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. So now in case the |
||
| ); | ||
| } | ||
| } | ||
| } else { | ||
| console.log("No user .npmrc file found, creating one..."); | ||
| if (processEnv.NPM_TOKEN) { | ||
| fs.writeFileSync( | ||
| userNpmrcPath, | ||
| ini.stringify({ | ||
| "//registry.npmjs.org/:_authToken": processEnv.NPM_TOKEN, | ||
| }) | ||
| ); | ||
| } else { | ||
| console.warn( | ||
| "Missing `NPM_TOKEN` environment variable, skipping creation of .npmrc file." | ||
| ); | ||
| } | ||
| } | ||
| }; | ||
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.
@Andarist I added this option to opt-out of the .npmrc checks.
I find it useful in case I don't need the use the default npm registry (for example when using github packages).
What do you think?