diff --git a/README.md b/README.md index c0cb324c..5c124300 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ * [Buildkite](https://buildkite.com/) * [GitHub Actions CI](https://github.com/features/actions) * [CodeFresh](https://codefresh.io/) +* [AWS CodeBuild](https://docs.aws.amazon.com/codebuild/index.html) ## Installation: @@ -50,6 +51,7 @@ There are optional environment variables for other build systems as well: - `COVERALLS_SERVICE_JOB_NUMBER` (a number that uniquely identifies the build's job) - `COVERALLS_RUN_AT` (a date string for the time that the job ran. RFC 3339 dates work. This defaults to your build system's date/time if you don't set it) - `COVERALLS_PARALLEL` (set to `true` when running jobs in parallel, requires a completion webhook. More info here: ) +- `COVERALLS_PROJECT_ROOT_PATH` (an absolute path to the root of your project. Useful if you have multiple projects in one repo (ie: /frontend, /backend) or run your coverage from a subdirectory) ### GitHub Actions CI diff --git a/lib/convertLcovToCoveralls.js b/lib/convertLcovToCoveralls.js index bcbb9933..466376a1 100644 --- a/lib/convertLcovToCoveralls.js +++ b/lib/convertLcovToCoveralls.js @@ -27,7 +27,7 @@ const detailsToBranches = details => { return branches; }; -const convertLcovFileObject = (file, filepath) => { +const convertLcovFileObject = (file, filepath, projectRootPath) => { const rootpath = filepath; filepath = path.resolve(rootpath, file.file); const source = fs.readFileSync(filepath, 'utf8'); @@ -36,7 +36,7 @@ const convertLcovFileObject = (file, filepath) => { const branches = detailsToBranches(file.branches.details); return { - name: path.relative(rootpath, path.resolve(rootpath, file.file)).split(path.sep).join('/'), + name: path.relative(projectRootPath || rootpath, path.resolve(rootpath, file.file)).split(path.sep).join('/'), source, coverage, branches @@ -112,7 +112,7 @@ const convertLcovToCoveralls = (input, options, cb) => { file.file = cleanFilePath(file.file); const currentFilePath = path.resolve(filepath, file.file); if (fs.existsSync(currentFilePath)) { - postJson.source_files.push(convertLcovFileObject(file, filepath)); + postJson.source_files.push(convertLcovFileObject(file, filepath, options.project_root_path)); } }); diff --git a/lib/getOptions.js b/lib/getOptions.js index 3ac55794..2eb5968a 100644 --- a/lib/getOptions.js +++ b/lib/getOptions.js @@ -143,6 +143,20 @@ const getBaseOptions = cb => { git_message = process.env.CF_COMMIT_MESSAGE; } + if (process.env.CODEBUILD_BUILD_ARN) { + options.service_name = 'AWS CodeBuild'; + options.service_job_id = process.env.CODEBUILD_BUILD_ID; + + if (process.env.CODEBUILD_WEBHOOK_TRIGGER && process.env.CODEBUILD_WEBHOOK_TRIGGER.startsWith('pr/')) { + options.service_pull_request = process.env.CODEBUILD_WEBHOOK_TRIGGER.substr(3); + } + + git_commit = process.env.CODEBUILD_RESOLVED_SOURCE_VERSION; + git_branch = process.env.CODEBUILD_WEBHOOK_HEAD_REF && process.env.CODEBUILD_WEBHOOK_HEAD_REF.startsWith('refs/heads/') ? + process.env.CODEBUILD_WEBHOOK_HEAD_REF.substr(11) : + process.env.CODEBUILD_SOURCE_VERSION; + } + options.run_at = process.env.COVERALLS_RUN_AT || JSON.stringify(new Date()).slice(1, -1); if (process.env.COVERALLS_SERVICE_NUMBER) { @@ -157,6 +171,14 @@ const getBaseOptions = cb => { options.service_job_id = process.env.COVERALLS_SERVICE_JOB_ID; } + if (process.env.COVERALLS_GIT_COMMIT) { + git_commit = process.env.COVERALLS_GIT_COMMIT; + } + + if (process.env.COVERALLS_GIT_BRANCH) { + git_branch = process.env.COVERALLS_GIT_BRANCH; + } + if (!git_commit || !git_branch) { const data = detectLocalGit(); if (data) { @@ -169,6 +191,10 @@ const getBaseOptions = cb => { options.parallel = true; } + if (process.env.COVERALLS_PROJECT_ROOT_PATH) { + options.project_root_path = process.env.COVERALLS_PROJECT_ROOT_PATH; + } + // load a .coveralls.yml file const coveralls_yaml_conf = (() => { const yml = path.join(process.cwd(), '.coveralls.yml'); diff --git a/test/convertLcovToCoveralls.js b/test/convertLcovToCoveralls.js index 2adaa835..b59ab116 100644 --- a/test/convertLcovToCoveralls.js +++ b/test/convertLcovToCoveralls.js @@ -72,6 +72,19 @@ describe('convertLcovToCoveralls', () => { }); }); + it('should allow specifying the project root', done => { + delete process.env.TRAVIS; + const lcovpath = path.join(__dirname, './fixtures/onefile.lcov'); + const input = fs.readFileSync(lcovpath, 'utf8'); + const libpath = 'test/fixtures/lib'; + convertLcovToCoveralls(input, { filepath: libpath, project_root_path: path.join(__dirname, '..') }, (err, output) => { + should.not.exist(err); + output.source_files[0].name.should.equal('test/fixtures/lib/index.js'); + output.source_files[0].source.split('\n').length.should.equal(173); + done(); + }); + }); + it('should convert absolute input paths to relative', done => { delete process.env.TRAVIS; const lcovpath = path.join(__dirname, './fixtures/istanbul.lcov'); diff --git a/test/getOptions.js b/test/getOptions.js index 5bf0312f..41001d8e 100644 --- a/test/getOptions.js +++ b/test/getOptions.js @@ -69,6 +69,9 @@ describe('getBaseOptions', () => { it('should set service_name and service_job_id if it\'s running on Azure Pipelines', done => { testAzurePipelines(getBaseOptions, done); }); + it('should set service_name and service_job_id if it\'s running on AWS CodeBuild', done => { + testAwsCodeBuild(getBaseOptions, done); + }); }); describe('getOptions', () => { @@ -179,6 +182,9 @@ describe('getOptions', () => { it('should set service_name and service_job_id if it\'s running via Azure Pipelines', done => { testAzurePipelines(getOptions, done); }); + it('should set service_name and service_job_id if it\'s running via AWS CodeBuild', done => { + testAwsCodeBuild(getOptions, done); + }); it('should set service_name and service_job_id if it\'s running via CodeFresh', done => { testCodefresh(getOptions, done); }); @@ -713,6 +719,36 @@ const testAzurePipelines = (sut, done) => { }); }; +const testAwsCodeBuild = (sut, done) => { + process.env.CODEBUILD_BUILD_ARN = 'arn:build:1'; + process.env.CODEBUILD_BUILD_ID = '1234'; + process.env.CODEBUILD_RESOLVED_SOURCE_VERSION = 'e3e3e3e3e3e3e3e3e'; + process.env.CODEBUILD_WEBHOOK_HEAD_REF = 'refs/heads/hotfix'; + process.env.CODEBUILD_WEBHOOK_TRIGGER = 'pr/123'; + + const git = { + head: { + id: 'e3e3e3e3e3e3e3e3e', + author_name: 'Unknown Author', + author_email: '', + committer_name: 'Unknown Committer', + committer_email: '', + message: 'Unknown Commit Message' + }, + branch: 'hotfix', + remotes: [] + }; + + sut((err, options) => { + should.not.exist(err); + options.service_name.should.equal('AWS CodeBuild'); + options.service_job_id.should.equal('1234'); + options.service_pull_request.should.equal('123'); + options.git.should.eql(git); + done(); + }); +}; + const testCodefresh = (sut, done) => { process.env.CF_BRANCH = 'hotfix'; process.env.CF_REVISION = 'e3e3e3e3e3e3e3e3e';