diff --git a/__tests__/authutil.test.ts b/__tests__/authutil.test.ts index 1ec4e1e18..7271cdd6e 100644 --- a/__tests__/authutil.test.ts +++ b/__tests__/authutil.test.ts @@ -72,7 +72,13 @@ describe('authutil tests', () => { for (const line of contents.split(os.EOL)) { let parts = line.split('='); if (parts.length == 2) { - rc[parts[0].trim()] = parts[1].trim(); + let key = parts[0].trim(); + + if (rc[key]) { + throw new Error(`Duplicate key ${key} in ${rcFile}`); + } + + rc[key] = parts[1].trim(); } } return rc; @@ -132,4 +138,58 @@ describe('authutil tests', () => { expect(rc['always-auth']).toBe('false'); expect(process.env.NODE_AUTH_TOKEN).toEqual('foobar'); }); + + describe('Existing .npmrc', () => { + it('should overwrite registry', async () => { + fs.copyFileSync(path.join(__dirname, 'data/.npmrc'), rcFile); + expect(fs.statSync(rcFile)).toBeDefined(); + + let rc = readRcFile(rcFile); + expect(rc['registry']).toBe('http://example.com'); + await auth.configAuthentication('https://registry.npmjs.org/', 'true'); + let updatedRc = readRcFile(rcFile); + expect(updatedRc['registry']).toBe('https://registry.npmjs.org/'); + expect(updatedRc['always-auth']).toBe('true'); + }); + + it('should overwrite scoped registry', async () => { + process.env['INPUT_SCOPE'] = 'myScope'; + + fs.copyFileSync(path.join(__dirname, 'data/.npmrc-scoped'), rcFile); + expect(fs.statSync(rcFile)).toBeDefined(); + + let rc = readRcFile(rcFile); + expect(rc['@myscope:registry']).toBe('http://example.com'); + + await auth.configAuthentication('https://registry.npmjs.org/', 'true'); + + let updatedRc = readRcFile(rcFile); + expect(updatedRc['@myscope:registry']).toBe( + 'https://registry.npmjs.org/' + ); + expect(updatedRc['always-auth']).toBe('true'); + }); + + it('should not delete registry when scoped', async () => { + process.env['INPUT_SCOPE'] = 'myScope'; + + fs.copyFileSync( + path.join(__dirname, 'data/.npmrc-scoped-with-registry'), + rcFile + ); + expect(fs.statSync(rcFile)).toBeDefined(); + + let rc = readRcFile(rcFile); + expect(rc['@myscope:registry']).toBe('http://example.com'); + + await auth.configAuthentication('https://registry.npmjs.org/', 'true'); + + let updatedRc = readRcFile(rcFile); + expect(updatedRc['registry']).toBe('http://base.com'); + expect(updatedRc['@myscope:registry']).toBe( + 'https://registry.npmjs.org/' + ); + expect(updatedRc['always-auth']).toBe('true'); + }); + }); }); diff --git a/__tests__/data/.npmrc b/__tests__/data/.npmrc new file mode 100644 index 000000000..9823ee746 --- /dev/null +++ b/__tests__/data/.npmrc @@ -0,0 +1 @@ +registry=http://example.com \ No newline at end of file diff --git a/__tests__/data/.npmrc-scoped b/__tests__/data/.npmrc-scoped new file mode 100644 index 000000000..f0bff2a7b --- /dev/null +++ b/__tests__/data/.npmrc-scoped @@ -0,0 +1 @@ +@myscope:registry=http://example.com \ No newline at end of file diff --git a/__tests__/data/.npmrc-scoped-with-registry b/__tests__/data/.npmrc-scoped-with-registry new file mode 100644 index 000000000..7b0af2e7a --- /dev/null +++ b/__tests__/data/.npmrc-scoped-with-registry @@ -0,0 +1,2 @@ +registry=http://base.com +@myscope:registry=http://example.com \ No newline at end of file diff --git a/dist/setup/index.js b/dist/setup/index.js index 0daaa2f23..cee1a7ddb 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -72923,22 +72923,21 @@ function writeRegistryToFile(registryUrl, fileLocation, alwaysAuth) { if (scope) { scope = scope.toLowerCase(); } + const registryKey = scope ? `${scope}:registry` : 'registry'; core.debug(`Setting auth in ${fileLocation}`); let newContents = ''; if (fs.existsSync(fileLocation)) { const curContents = fs.readFileSync(fileLocation, 'utf8'); curContents.split(os.EOL).forEach((line) => { // Add current contents unless they are setting the registry - if (!line.toLowerCase().startsWith('registry')) { + if (!line.startsWith(registryKey)) { newContents += line + os.EOL; } }); } // Remove http: or https: from front of registry. const authString = registryUrl.replace(/(^\w+:|^)/, '') + ':_authToken=${NODE_AUTH_TOKEN}'; - const registryString = scope - ? `${scope}:registry=${registryUrl}` - : `registry=${registryUrl}`; + const registryString = `${registryKey}=${registryUrl}`; const alwaysAuthString = `always-auth=${alwaysAuth}`; newContents += `${authString}${os.EOL}${registryString}${os.EOL}${alwaysAuthString}`; fs.writeFileSync(fileLocation, newContents); @@ -73882,7 +73881,7 @@ module.exports = {"i8":"2.1.3"}; /***/ ((module) => { "use strict"; -module.exports = JSON.parse('{"name":"@octokit/rest","version":"16.38.1","publishConfig":{"access":"public"},"description":"GitHub REST API client for Node.js","keywords":["octokit","github","rest","api-client"],"author":"Gregor Martynus (https://github.com/gr2m)","contributors":[{"name":"Mike de Boer","email":"info@mikedeboer.nl"},{"name":"Fabian Jakobs","email":"fabian@c9.io"},{"name":"Joe Gallo","email":"joe@brassafrax.com"},{"name":"Gregor Martynus","url":"https://github.com/gr2m"}],"repository":"https://github.com/octokit/rest.js","dependencies":{"@octokit/auth-token":"^2.4.0","@octokit/request":"^5.2.0","@octokit/request-error":"^1.0.2","atob-lite":"^2.0.0","before-after-hook":"^2.0.0","btoa-lite":"^1.0.0","deprecation":"^2.0.0","lodash.get":"^4.4.2","lodash.set":"^4.3.2","lodash.uniq":"^4.5.0","octokit-pagination-methods":"^1.1.0","once":"^1.4.0","universal-user-agent":"^4.0.0"},"devDependencies":{"@gimenete/type-writer":"^0.1.3","@octokit/auth":"^1.1.1","@octokit/fixtures-server":"^5.0.6","@octokit/graphql":"^4.2.0","@types/node":"^13.1.0","bundlesize":"^0.18.0","chai":"^4.1.2","compression-webpack-plugin":"^3.1.0","cypress":"^3.0.0","glob":"^7.1.2","http-proxy-agent":"^3.0.0","lodash.camelcase":"^4.3.0","lodash.merge":"^4.6.1","lodash.upperfirst":"^4.3.1","mkdirp":"^0.5.1","mocha":"^6.0.0","mustache":"^4.0.0","nock":"^11.3.3","npm-run-all":"^4.1.2","nyc":"^15.0.0","prettier":"^1.14.2","proxy":"^1.0.0","semantic-release":"^16.0.0","sinon":"^8.0.0","sinon-chai":"^3.0.0","sort-keys":"^4.0.0","string-to-arraybuffer":"^1.0.0","string-to-jsdoc-comment":"^1.0.0","typescript":"^3.3.1","webpack":"^4.0.0","webpack-bundle-analyzer":"^3.0.0","webpack-cli":"^3.0.0"},"types":"index.d.ts","scripts":{"coverage":"nyc report --reporter=html && open coverage/index.html","lint":"prettier --check \'{lib,plugins,scripts,test}/**/*.{js,json,ts}\' \'docs/*.{js,json}\' \'docs/src/**/*\' index.js README.md package.json","lint:fix":"prettier --write \'{lib,plugins,scripts,test}/**/*.{js,json,ts}\' \'docs/*.{js,json}\' \'docs/src/**/*\' index.js README.md package.json","pretest":"npm run -s lint","test":"nyc mocha test/mocha-node-setup.js \\"test/*/**/*-test.js\\"","test:browser":"cypress run --browser chrome","build":"npm-run-all build:*","build:ts":"npm run -s update-endpoints:typescript","prebuild:browser":"mkdirp dist/","build:browser":"npm-run-all build:browser:*","build:browser:development":"webpack --mode development --entry . --output-library=Octokit --output=./dist/octokit-rest.js --profile --json > dist/bundle-stats.json","build:browser:production":"webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=Octokit --output-path=./dist --output-filename=octokit-rest.min.js --devtool source-map","generate-bundle-report":"webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html","update-endpoints":"npm-run-all update-endpoints:*","update-endpoints:fetch-json":"node scripts/update-endpoints/fetch-json","update-endpoints:code":"node scripts/update-endpoints/code","update-endpoints:typescript":"node scripts/update-endpoints/typescript","prevalidate:ts":"npm run -s build:ts","validate:ts":"tsc --target es6 --noImplicitAny index.d.ts","postvalidate:ts":"tsc --noEmit --target es6 test/typescript-validate.ts","start-fixtures-server":"octokit-fixtures-server"},"license":"MIT","files":["index.js","index.d.ts","lib","plugins"],"nyc":{"ignore":["test"]},"release":{"publish":["@semantic-release/npm",{"path":"@semantic-release/github","assets":["dist/*","!dist/*.map.gz"]}]},"bundlesize":[{"path":"./dist/octokit-rest.min.js.gz","maxSize":"33 kB"}]}'); +module.exports = JSON.parse('{"_args":[["@octokit/rest@16.38.1","/Users/alexmeah/Code/setup-node"]],"_from":"@octokit/rest@16.38.1","_id":"@octokit/rest@16.38.1","_inBundle":false,"_integrity":"sha512-zyNFx+/Bd1EXt7LQjfrc6H4wryBQ/oDuZeZhGMBSFr1eMPFDmpEweFQR3R25zjKwBQpDY7L5GQO6A3XSaOfV1w==","_location":"/@octokit/rest","_phantomChildren":{"os-name":"3.1.0"},"_requested":{"type":"version","registry":true,"raw":"@octokit/rest@16.38.1","name":"@octokit/rest","escapedName":"@octokit%2frest","scope":"@octokit","rawSpec":"16.38.1","saveSpec":null,"fetchSpec":"16.38.1"},"_requiredBy":["/@actions/github"],"_resolved":"https://registry.npmjs.org/@octokit/rest/-/rest-16.38.1.tgz","_spec":"16.38.1","_where":"/Users/alexmeah/Code/setup-node","author":{"name":"Gregor Martynus","url":"https://github.com/gr2m"},"bugs":{"url":"https://github.com/octokit/rest.js/issues"},"bundlesize":[{"path":"./dist/octokit-rest.min.js.gz","maxSize":"33 kB"}],"contributors":[{"name":"Mike de Boer","email":"info@mikedeboer.nl"},{"name":"Fabian Jakobs","email":"fabian@c9.io"},{"name":"Joe Gallo","email":"joe@brassafrax.com"},{"name":"Gregor Martynus","url":"https://github.com/gr2m"}],"dependencies":{"@octokit/auth-token":"^2.4.0","@octokit/request":"^5.2.0","@octokit/request-error":"^1.0.2","atob-lite":"^2.0.0","before-after-hook":"^2.0.0","btoa-lite":"^1.0.0","deprecation":"^2.0.0","lodash.get":"^4.4.2","lodash.set":"^4.3.2","lodash.uniq":"^4.5.0","octokit-pagination-methods":"^1.1.0","once":"^1.4.0","universal-user-agent":"^4.0.0"},"description":"GitHub REST API client for Node.js","devDependencies":{"@gimenete/type-writer":"^0.1.3","@octokit/auth":"^1.1.1","@octokit/fixtures-server":"^5.0.6","@octokit/graphql":"^4.2.0","@types/node":"^13.1.0","bundlesize":"^0.18.0","chai":"^4.1.2","compression-webpack-plugin":"^3.1.0","cypress":"^3.0.0","glob":"^7.1.2","http-proxy-agent":"^3.0.0","lodash.camelcase":"^4.3.0","lodash.merge":"^4.6.1","lodash.upperfirst":"^4.3.1","mkdirp":"^0.5.1","mocha":"^6.0.0","mustache":"^4.0.0","nock":"^11.3.3","npm-run-all":"^4.1.2","nyc":"^15.0.0","prettier":"^1.14.2","proxy":"^1.0.0","semantic-release":"^16.0.0","sinon":"^8.0.0","sinon-chai":"^3.0.0","sort-keys":"^4.0.0","string-to-arraybuffer":"^1.0.0","string-to-jsdoc-comment":"^1.0.0","typescript":"^3.3.1","webpack":"^4.0.0","webpack-bundle-analyzer":"^3.0.0","webpack-cli":"^3.0.0"},"files":["index.js","index.d.ts","lib","plugins"],"homepage":"https://github.com/octokit/rest.js#readme","keywords":["octokit","github","rest","api-client"],"license":"MIT","name":"@octokit/rest","nyc":{"ignore":["test"]},"publishConfig":{"access":"public"},"release":{"publish":["@semantic-release/npm",{"path":"@semantic-release/github","assets":["dist/*","!dist/*.map.gz"]}]},"repository":{"type":"git","url":"git+https://github.com/octokit/rest.js.git"},"scripts":{"build":"npm-run-all build:*","build:browser":"npm-run-all build:browser:*","build:browser:development":"webpack --mode development --entry . --output-library=Octokit --output=./dist/octokit-rest.js --profile --json > dist/bundle-stats.json","build:browser:production":"webpack --mode production --entry . --plugin=compression-webpack-plugin --output-library=Octokit --output-path=./dist --output-filename=octokit-rest.min.js --devtool source-map","build:ts":"npm run -s update-endpoints:typescript","coverage":"nyc report --reporter=html && open coverage/index.html","generate-bundle-report":"webpack-bundle-analyzer dist/bundle-stats.json --mode=static --no-open --report dist/bundle-report.html","lint":"prettier --check \'{lib,plugins,scripts,test}/**/*.{js,json,ts}\' \'docs/*.{js,json}\' \'docs/src/**/*\' index.js README.md package.json","lint:fix":"prettier --write \'{lib,plugins,scripts,test}/**/*.{js,json,ts}\' \'docs/*.{js,json}\' \'docs/src/**/*\' index.js README.md package.json","postvalidate:ts":"tsc --noEmit --target es6 test/typescript-validate.ts","prebuild:browser":"mkdirp dist/","pretest":"npm run -s lint","prevalidate:ts":"npm run -s build:ts","start-fixtures-server":"octokit-fixtures-server","test":"nyc mocha test/mocha-node-setup.js \\"test/*/**/*-test.js\\"","test:browser":"cypress run --browser chrome","update-endpoints":"npm-run-all update-endpoints:*","update-endpoints:code":"node scripts/update-endpoints/code","update-endpoints:fetch-json":"node scripts/update-endpoints/fetch-json","update-endpoints:typescript":"node scripts/update-endpoints/typescript","validate:ts":"tsc --target es6 --noImplicitAny index.d.ts"},"types":"index.d.ts","version":"16.38.1"}'); /***/ }), diff --git a/src/authutil.ts b/src/authutil.ts index aaebdfd21..e3131c6ce 100644 --- a/src/authutil.ts +++ b/src/authutil.ts @@ -32,13 +32,15 @@ function writeRegistryToFile( scope = scope.toLowerCase(); } + const registryKey: string = scope ? `${scope}:registry` : 'registry'; + core.debug(`Setting auth in ${fileLocation}`); let newContents: string = ''; if (fs.existsSync(fileLocation)) { const curContents: string = fs.readFileSync(fileLocation, 'utf8'); curContents.split(os.EOL).forEach((line: string) => { // Add current contents unless they are setting the registry - if (!line.toLowerCase().startsWith('registry')) { + if (!line.startsWith(registryKey)) { newContents += line + os.EOL; } }); @@ -46,9 +48,7 @@ function writeRegistryToFile( // Remove http: or https: from front of registry. const authString: string = registryUrl.replace(/(^\w+:|^)/, '') + ':_authToken=${NODE_AUTH_TOKEN}'; - const registryString: string = scope - ? `${scope}:registry=${registryUrl}` - : `registry=${registryUrl}`; + const registryString: string = `${registryKey}=${registryUrl}`; const alwaysAuthString: string = `always-auth=${alwaysAuth}`; newContents += `${authString}${os.EOL}${registryString}${os.EOL}${alwaysAuthString}`; fs.writeFileSync(fileLocation, newContents);