From 7c1f16ea34ea33aa78506daac4eb9404be9a8cba Mon Sep 17 00:00:00 2001 From: dale tan Date: Tue, 4 Sep 2018 16:11:50 -0700 Subject: [PATCH] fix: support `.codecov.yml`/`codecov.yml` files for token (#108) * fix: support `.codecov.yml`/`codecov.yml` files for token * fix: added more test coverage for gitlab * fix: cleanup env vars to avoid leaking into other tests * fix: updated test to use process.cwd() * package bumps --- lib/codecov.js | 29 +++++++++---- package-lock.json | 29 +++++++------ package.json | 2 + test/index.js | 95 ++++++++++++++++++++++++++++++++++++----- test/services/gitlab.js | 24 +++++++++++ 5 files changed, 147 insertions(+), 32 deletions(-) diff --git a/lib/codecov.js b/lib/codecov.js index 75fb08cf..73e745ee 100644 --- a/lib/codecov.js +++ b/lib/codecov.js @@ -2,6 +2,7 @@ var fs = require('fs') var path = require('path') var request = require('request') var urlgrey = require('urlgrey') +var jsYaml = require('js-yaml') var walk = require('ignore-walk') var execSync = require('child_process').execSync @@ -258,13 +259,6 @@ var upload = function(args, on_success, on_failure) { version ) - query.yaml = [yamlFile, '.codecov.yml'].reduce(function(result, file) { - return ( - result || - (fs.existsSync(path.resolve(process.cwd(), file)) ? file : undefined) - ) - }, undefined) - if ((args.options.disable || '').split(',').indexOf('detect') === -1) { console.log('==> Detecting CI Provider') query = detectProvider() @@ -272,6 +266,15 @@ var upload = function(args, on_success, on_failure) { debug.push('disabled detect') } + query.yaml = [yamlFile, '.codecov.yml'].reduce(function(result, file) { + return ( + result || + (fs.existsSync(path.resolve(process.cwd(), file)) + ? path.resolve(process.cwd(), file) + : undefined) + ) + }, undefined) + if (args.options.build) { query.build = args.options.build } @@ -294,8 +297,18 @@ var upload = function(args, on_success, on_failure) { query.flags = flags } + var yamlToken + try { + var loadedYamlFile = jsYaml.safeLoad(fs.readFileSync(query.yaml, 'utf8')) + yamlToken = loadedYamlFile && loadedYamlFile.codecov && loadedYamlFile.codecov.token + } catch (e) { + // silently fail + } var token = - args.options.token || process.env.codecov_token || process.env.CODECOV_TOKEN + args.options.token || + yamlToken || + process.env.codecov_token || + process.env.CODECOV_TOKEN if (token) { query.token = token } diff --git a/package-lock.json b/package-lock.json index 1e361784..d71c4285 100644 --- a/package-lock.json +++ b/package-lock.json @@ -230,7 +230,6 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "1.0.3" } @@ -1063,6 +1062,12 @@ "acorn-jsx": "3.0.1" } }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": + "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, "esquery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", @@ -2093,19 +2098,9 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", - "dev": true, "requires": { "argparse": "1.0.10", - "esprima": "4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": - "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", - "dev": true - } + "esprima": "4.0.1" } }, "jsbn": { @@ -2632,6 +2627,13 @@ } } }, + "mock-fs": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.6.0.tgz", + "integrity": + "sha512-aYutNIwFaMsVgtMoc5vMsobA/yRJR2FTUFoTZgnjdb3gID0g8WMmeafWmHPgzKgZ7zwQ5kggYUgeq5sN9k9uDw==", + "dev": true + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -5513,8 +5515,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.14.2", diff --git a/package.json b/package.json index adc3b93a..01b6ec57 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "dependencies": { "argv": "^0.0.2", "ignore-walk": "^3.0.1", + "js-yaml": "^3.12.0", "request": "^2.87.0", "urlgrey": "^0.4.4" }, @@ -38,6 +39,7 @@ "husky": "^0.14.3", "lint-staged": "^7.2.0", "mocha": "^5.2.0", + "mock-fs": "^4.6.0", "nyc": "^12.0.2", "prettier": "^1.13.7" }, diff --git a/test/index.js b/test/index.js index f8ffac1b..45000926 100644 --- a/test/index.js +++ b/test/index.js @@ -1,4 +1,5 @@ var fs = require('fs') +var mockFs = require('mock-fs') var codecov = require('../lib/codecov') var isWindows = @@ -29,6 +30,7 @@ describe('Codecov', function() { expect(codecov.upload({ options: { dump: true } }).query.token).to.eql( 'ABC123' ) + delete process.env.CODECOV_TOKEN }) it('can get a token passed in cli', function() { @@ -37,6 +39,69 @@ describe('Codecov', function() { ).to.eql('qwerty') }) + it('can read a codecov.yml file', function() { + mockFs({ + 'codecov.yml': 'codecov:\n token: fake-token', + }) + expect(codecov.upload({ options: { dump: true } }).query.token).to.eql( + 'fake-token' + ) + mockFs.restore() + }) + it('can read a .codecov.yml file', function() { + mockFs({ + '.codecov.yml': 'codecov:\n token: fake-token-dotfile', + }) + expect(codecov.upload({ options: { dump: true } }).query.token).to.eql( + 'fake-token-dotfile' + ) + mockFs.restore() + }) + it('should have no token if yaml file does not supplied', function() { + mockFs({ + '.codecov.yml': 'codecov:\n noconfig: true', + }) + expect(codecov.upload({ options: { dump: true } }).query.token).to.eql( + undefined + ) + mockFs.restore() + }) + + it('token precedence should be respected', function() { + // options.token || .codecov.yml/codecov.yml file || codecov_token || CODECOV_TOKEN + mockFs({ + '.codecov.yml': 'codecov:\n token: fake-token-dotfile', + }) + var upload = codecov.upload({ options: { dump: true, token: 'qwerty' } }) + expect(upload.query.token).to.eql('qwerty') + mockFs.restore() + + process.env.codecov_token = 'abc123' + upload = codecov.upload({ options: { dump: true, token: 'qwerty2' } }) + expect(upload.query.token).to.eql('qwerty2') + delete process.env.codecov_token + + process.env.CODECOV_TOKEN = 'ABC123' + upload = codecov.upload({ options: { dump: true, token: 'qwerty3' } }) + expect(upload.query.token).to.eql('qwerty3') + delete process.env.CODECOV_TOKEN + + mockFs({ + '.codecov.yml': 'codecov:\n token: fake-token-dotfile', + }) + process.env.codecov_token = 'abc123' + upload = codecov.upload({ options: { dump: true } }) + expect(upload.query.token).to.eql('fake-token-dotfile') + mockFs.restore() + + process.env.codecov_token = 'abc123' + process.env.CODECOV_TOKEN = 'ABC123' + upload = codecov.upload({ options: { dump: true } }) + expect(upload.query.token).to.eql('abc123') + delete process.env.codecov_token + delete process.env.CODECOV_TOKEN + }) + it('can auto detect reports', function() { var res = codecov.upload({ options: { dump: true } }) expect(res.files[0].split(pathSeparator).pop()).to.eql( @@ -125,6 +190,7 @@ describe('Codecov', function() { var res = codecov.upload({ options: { dump: true, env: 'HELLO,VAR1' } }) expect(res.body).to.contain('HELLO=world\n') expect(res.body).to.contain('VAR1=\n') + delete process.env.HELLO }) it('can include env in env', function() { @@ -134,6 +200,8 @@ describe('Codecov', function() { expect(res.body).to.contain('HELLO=world\n') expect(res.body).to.contain('VAR1=\n') expect(res.body).to.contain('VAR2=\n') + delete process.env.HELLO + delete process.env.CODECOV_ENV }) it('can have custom args for gcov', function() { @@ -163,33 +231,40 @@ describe('Codecov', function() { }) it('Should use codecov.yml via env variable', function() { + var CWD = process.cwd() expect( codecov.upload({ options: { dump: true, disable: 'detect' } }).query.yaml - ).to.eql('codecov.yml') + ).to.eql(CWD + '/codecov.yml') - fs.writeFileSync('foo.yml', '') + mockFs({ + 'foo.yml': '', + }) process.env.codecov_yml = 'foo.yml' expect( codecov.upload({ options: { dump: true, disable: 'detect' } }).query.yaml - ).to.eql('foo.yml') - fs.unlinkSync('foo.yml') + ).to.eql(CWD + '/foo.yml') + mockFs.restore() delete process.env.codecov_yml - fs.writeFileSync('FOO.yml', '') + mockFs({ + 'FOO.yml': '', + }) process.env.CODECOV_YML = 'FOO.yml' expect( codecov.upload({ options: { dump: true, disable: 'detect' } }).query.yaml - ).to.eql('FOO.yml') - fs.unlinkSync('FOO.yml') + ).to.eql(CWD + '/FOO.yml') + mockFs.restore() delete process.env.CODECOV_YML }) it('can get config from cli args', function() { - fs.writeFileSync('foo.yml', '') + mockFs({ + 'foo.yml': '', + }) var res = codecov.upload({ options: { dump: true, yml: 'foo.yml', disable: 'detect' }, }) - expect(res.query.yaml).to.eql('foo.yml') - fs.unlinkSync('foo.yml') + expect(res.query.yaml).to.eql(process.cwd() + '/foo.yml') + mockFs.restore() }) }) diff --git a/test/services/gitlab.js b/test/services/gitlab.js index ff3b767f..2dce2e24 100644 --- a/test/services/gitlab.js +++ b/test/services/gitlab.js @@ -6,6 +6,11 @@ describe('Gitlab CI Provider', function() { expect(gitlab.detect()).to.be(true) }) + it('cannot detect gitlab', function() { + delete process.env.GITLAB_CI + expect(gitlab.detect()).to.be(false) + }) + it('can get service env info', function() { process.env.CI_BUILD_ID = '1234' process.env.CI_BUILD_REPO = 'https://gitlab.com/owner/repo.git' @@ -20,5 +25,24 @@ describe('Gitlab CI Provider', function() { slug: 'owner/repo', branch: 'master', }) + delete process.env.CI_BUILD_REPO + process.env.CI_REPOSITORY_URL = 'https://gitlab.com/owner/repo2.git' + expect(gitlab.configuration()).to.eql({ + service: 'gitlab', + build: '1234', + root: '/', + commit: '5678', + slug: 'owner/repo2', + branch: 'master', + }) + delete process.env.CI_REPOSITORY_URL + expect(gitlab.configuration()).to.eql({ + service: 'gitlab', + build: '1234', + root: '/', + commit: '5678', + slug: '', + branch: 'master', + }) }) })