├── .eslintrc.json ├── .github ├── dependabot.yml └── workflows │ └── nodejs.yml ├── .gitignore ├── .idea └── .gitignore ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── appveyor.yml ├── bin └── codecov ├── circle.yml ├── codecov.yml ├── index.js ├── lib ├── codecov.js ├── detect.js ├── git.js ├── offline.js └── services │ ├── appveyor.js │ ├── azurePipelines.js │ ├── buildkite.js │ ├── circle.js │ ├── cirrus.js │ ├── codebuild.js │ ├── codeship.js │ ├── drone.js │ ├── github_actions.js │ ├── gitlab.js │ ├── heroku.js │ ├── jenkins.js │ ├── localGit.js │ ├── semaphore.js │ ├── semaphore2x.js │ ├── shippable.js │ ├── snap.js │ ├── teamcity.js │ ├── travis.js │ └── wercker.js ├── npm-shrinkwrap.json ├── package.json └── test ├── detect.test.js ├── example.coverage.txt ├── git.test.js ├── index.test.js ├── services ├── appveyor.test.js ├── azure-pipelines.test.js ├── buildkite.test.js ├── circle.test.js ├── cirrus.test.js ├── codebuild.test.js ├── codeship.test.js ├── drone.test.js ├── github_actions.test.js ├── gitlab.test.js ├── heroku.test.js ├── jenkins.test.js ├── localGit.test.js ├── semaphore.test.js ├── semaphore2x.test.js ├── shippable.test.js ├── snap.test.js ├── teamcity.test.js ├── travis.test.js └── wercker.test.js └── upload.test.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended", "prettier"], 3 | "env": { 4 | "node": true, 5 | "jest": true 6 | }, 7 | "globals": { 8 | "expect": true 9 | }, 10 | "rules": { 11 | "no-console": "off", 12 | "no-empty": ["error", { "allowEmptyCatch": true }] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: daily 12 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Node CI 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | node-version: [10.x, 12.x, 14.x] 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v2.5.1 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | - name: npm install, build, and test 20 | run: | 21 | npm install 22 | npm run build --if-present 23 | npm test 24 | env: 25 | CI: true 26 | - name: Upload coverage to Codecov 27 | run: ./bin/codecov 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | .nyc_output 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # Compiled binary addons (http://nodejs.org/api/addons.html) 21 | build/Release 22 | 23 | # Dependency directory 24 | # Deployed apps should consider commenting this line out: 25 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 26 | node_modules 27 | 28 | lib-cov/ 29 | coverage.json 30 | .vs-code 31 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | 7 | .idea/ -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .git/ 3 | coverage/ -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "trailingComma": "es5", 4 | "singleQuote": true, 5 | "useTabs": false 6 | } 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | sudo: false 4 | 5 | node_js: 6 | - 'node' 7 | - '14' 8 | - '12' 9 | - '10' 10 | 11 | after_success: 12 | - ./bin/codecov -e TRAVIS_NODE_VERSION -f coverage/*.json 13 | - ./bin/codecov -e TRAVIS_NODE_VERSION 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.8.3 2 | ### Fixes 3 | - #329 fix: Test if response has two lines 4 | 5 | ### Dependencies 6 | - #306 Bump eslint-config-prettier from 7.2.0 to 8.3.0 7 | - #305 Bump eslint from 7.21.0 to 7.25.0 8 | - #302 Bump mock-fs from 4.13.0 to 4.14.0 9 | - #308 Bump lodash from 4.17.19 to 4.17.21 10 | - #309 Bump ignore-walk from 3.0.3 to 3.0.4 11 | - #310 Bump hosted-git-info from 2.8.8 to 2.8.9 12 | - #325 Bump prettier from 2.2.1 to 2.3.2 13 | - #326 Bump actions/setup-node from 2.1.5 to 2.2.0 14 | - #328 Bump lint-staged from 10.5.4 to 11.0.1 15 | - #330 Bump eslint from 7.25.0 to 7.31.0 16 | - #331 Bump ws from 7.3.1 to 7.5.3 17 | - #332 Bump urlgrey from 0.4.4 to 1.0.0 18 | - #334 Bump husky from 6.0.0 to 7.0.1 19 | - #333 Bump teeny-request from 7.0.1 to 7.1.1 20 | 21 | ## 3.8.2 22 | ### Fixes 23 | - #304 Add coverage-final.json as a possible coverage file during file lookup 24 | 25 | ## 3.8.1 26 | 27 | ### Fixes 28 | 29 | - [#246](https://github.com/codecov/codecov-node/pull/246) Revert "Bump teeny-request from 6.0.1 to 7.0.0" 30 | 31 | ## 3.8.0 32 | 33 | ### Features 34 | 35 | - [#160](https://github.com/codecov/codecov-node/pull/160) Add Github Actions support 36 | 37 | ### Fixes 38 | 39 | - [#173](https://github.com/codecov/codecov-node/pull/173) Fix broken gcov command 40 | - [#195](https://github.com/codecov/codecov-node/pull/195) Update Node testing versions 41 | - [#200](https://github.com/codecov/codecov-node/pull/200) Remove flaky tests 42 | - [#204](https://github.com/codecov/codecov-node/pull/204) Create CHANGELOG and remove flaky v4 test 43 | - [#208](https://github.com/codecov/codecov-node/pull/208) Add license scan report and status 44 | - [#220](https://github.com/codecov/codecov-node/pull/220) Remove errant bitly 45 | 46 | #### Dependencies 47 | 48 | - [#189](https://github.com/codecov/codecov-node/pull/189) Bump lint-staged from 10.0.7 to 10.2.11 49 | - [#190](https://github.com/codecov/codecov-node/pull/190) [Security] Bump handlebars from 4.5.3 to 4.7.6 50 | - [#191](https://github.com/codecov/codecov-node/pull/191) Bump prettier from 1.19.1 to 2.0.5 51 | - [#192](https://github.com/codecov/codecov-node/pull/192) Bump mock-fs from 4.10.4 to 4.12.0 52 | - [#196](https://github.com/codecov/codecov-node/pull/196) Bump teeny-request from 6.0.1 to 7.0.0 53 | - [#197](https://github.com/codecov/codecov-node/pull/197) Bump eslint-config-prettier from 4.3.0 to 6.11.0 54 | - [#198](https://github.com/codecov/codecov-node/pull/198) Bump js-yaml from 3.13.1 to 3.14.0 55 | - [#199](https://github.com/codecov/codecov-node/pull/199) Bump husky from 4.2.1 to 4.2.5 56 | - [#202](https://github.com/codecov/codecov-node/pull/202) Bump eslint from 5.16.0 to 7.7.0 57 | - [#203](https://github.com/codecov/codecov-node/pull/203) Bump jest from 24.9.0 to 26.4.1 58 | - [#205](https://github.com/codecov/codecov-node/pull/205) Bump mock-fs from 4.12.0 to 4.13.0 59 | - [#206](https://github.com/codecov/codecov-node/pull/206) Bump jest from 26.4.1 to 26.4.2 60 | - [#207](https://github.com/codecov/codecov-node/pull/207) Bump prettier from 2.0.5 to 2.1.0 61 | - [#209](https://github.com/codecov/codecov-node/pull/209) Bump lint-staged from 10.2.11 to 10.2.13 62 | - [#210](https://github.com/codecov/codecov-node/pull/210) Bump prettier from 2.1.0 to 2.1.1 63 | - [#212](https://github.com/codecov/codecov-node/pull/212) Bump eslint from 7.7.0 to 7.8.1 64 | - [#214](https://github.com/codecov/codecov-node/pull/214) Bump lint-staged from 10.2.13 to 10.3.0 65 | - [#215](https://github.com/codecov/codecov-node/pull/215) Bump husky from 4.2.5 to 4.3.0 66 | - [#216](https://github.com/codecov/codecov-node/pull/216) Bump node-fetch from 2.6.0 to 2.6.1 67 | - [#217](https://github.com/codecov/codecov-node/pull/217) Bump eslint from 7.8.1 to 7.9.0 68 | - [#218](https://github.com/codecov/codecov-node/pull/218) Bump prettier from 2.1.1 to 2.1.2 69 | - [#219](https://github.com/codecov/codecov-node/pull/219) Bump lint-staged from 10.3.0 to 10.4.0 70 | - [#222](https://github.com/codecov/codecov-node/pull/222) Bump eslint-config-prettier from 6.11.0 to 6.12.0 71 | - [#223](https://github.com/codecov/codecov-node/pull/223) Bump eslint from 7.9.0 to 7.10.0 72 | - [#224](https://github.com/codecov/codecov-node/pull/224) Bump teeny-request from 7.0.0 to 7.0.1 73 | 74 | ## 3.7.2 75 | 76 | - Fix issue with network and file finding 77 | 78 | ## 3.7.1 79 | 80 | - Move to execFileSync and security fixes 81 | 82 | ## 3.7.0 83 | 84 | - Remove the X-Amz-Acl: public-read header 85 | 86 | ## 3.6.4 87 | 88 | - Fix Cirrus CI 89 | 90 | ## 3.6.3 91 | 92 | - Fix for AWS Codebuild & package updates 93 | 94 | ## 3.6.2 95 | 96 | - Command line args sanitized fix 97 | 98 | ## 3.6.1 99 | 100 | - Fix for Semaphore 101 | 102 | ## 3.6.0 103 | 104 | - Added AWS CodeBuild and Semaphore2 105 | 106 | ## 3.5.0 107 | 108 | - Added TeamCity support 109 | 110 | ## 3.4.0 111 | 112 | - Added Heroku CI support 113 | 114 | ## 3.3.0 115 | 116 | - Added pipe with `--pipe`, `-l` 117 | 118 | ## 3.2.0 119 | 120 | - Added azure pipelines 121 | . 122 | 123 | ## 3.1.0 124 | 125 | - Custom yaml file. Allow codecov token from yml file. 126 | 127 | ## 3.0.4 128 | 129 | - Security fixes 130 | 131 | ## 3.0.3 132 | 133 | - Support non-git/hg root dirs 134 | 135 | ## 3.0.2 136 | 137 | - Security fixes 138 | 139 | ## 3.0.1 140 | 141 | - Security fixes 142 | 143 | ## 3.0.0 144 | 145 | - No longer supports node v0.12 because of new version of request 146 | 147 | ## 2.3.0 148 | 149 | - Added support for Windows. Updated dependencies. 150 | 151 | ## 2.2.0 152 | 153 | - Support for Jenkins Blue Ocean. Clean reports after upload. Fix for Gitlab. 154 | 155 | ## 2.1.0 156 | 157 | - Flags supported http://docs.codecov.io/docs/flags 158 | 159 | ## 2.0.2 160 | 161 | - Display correct version number in console. 162 | 163 | ## 2.0.1 164 | 165 | - Publish as latest instead of next. 166 | 167 | ## 2.0.0 168 | 169 | - No longer supports node v0.10 because of the execSync. 170 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at hello@codecov.io. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Gregg Caines 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 🚨🚨 Deprecation Notice 🚨🚨 2 | 3 | This uploader is being deprecated by the Codecov team. We recommend migrating to our [new uploader](https://docs.codecov.com/docs/codecov-uploader) as soon as possible to prevent any lapses in coverage. [The new uploader is open source](https://github.com/codecov/uploader), and we highly encourage submitting Issues and Pull Requests. 4 | 5 | You can visit our blog post to learn more about our [deprecation plan](https://about.codecov.io/blog/codecov-uploader-deprecation-plan/) 6 | 7 | **On February 1, 2022 this uploader will be completely deprecated and will no longer be able to upload coverage to Codecov.** 8 | 9 | # Codecov NodeJS Uploader 10 | 11 | [![codecov.io](https://codecov.io/github/codecov/codecov-node/coverage.svg?branch=master)](https://codecov.io/github/codecov/codecov-node?branch=master) 12 | [![NPM version][npm-image]][npm-url] 13 | [![Build Status][github-actions-image]][github-actions-url] 14 | [![Build Status][travis-image]][travis-url] 15 | [![Dependency Status][depstat-image]][depstat-url] 16 | [![Dev Dependency Status][devdepstat-image]][devdepstat-url] 17 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-node.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-node?ref=badge_shield) 18 | 19 | [Codecov.io](https://codecov.io/) support for node.js. 20 | 21 | ## Installation: 22 | 23 | Add the latest version of `codecov` to your package.json: 24 | 25 | ``` 26 | npm install codecov --save-dev 27 | ``` 28 | 29 | or 30 | 31 | ``` 32 | yarn add codecov --dev 33 | ``` 34 | 35 | ## Usage: 36 | 37 | This script ( `bin/codecov` ) detect your CI provider and all coverage reports and uploads them to Codecov. 38 | 39 | Once your app is instrumented for coverage, and building, simply call `./node_modules/.bin/codecov`. 40 | 41 | This library currently supports the following CI companies: [Travis CI](https://travis-ci.org/), [Travis](https://travis-ci.com/), [Appveyor](https://appveyor.com/), [CircleCI](https://circleci.com/), [Cirrus CI](https://cirrus-ci.org/), [Codeship](https://codeship.io/), [Drone](https://drone.io/), [Jenkins](http://jenkins-ci.org/), [Shippable](https://shippable.com/), [Semaphore](https://semaphoreapp.com/), [Wercker](https://wercker.com/), [Snap CI](https://snap-ci.com/), [Buildkite](https://buildkite.com/), [AWS CodeBuild](https://aws.amazon.com/codebuild/). 42 | 43 | #### Upload repo tokens 44 | 45 | > Repo tokens are **not** required for public repos tested on Travis-Org, CircleCI or AppVeyor. 46 | 47 | Repo tokens are necessary to distinguish your repository from others. You can find your repo token on your repository page at Codecov. Set this unique uuid to `CODECOV_TOKEN` in your environment variables. 48 | 49 | ``` 50 | export CODECOV_TOKEN=":uuid-repo-token" 51 | # or 52 | ./node_modules/.bin/codecov --token=:token 53 | # or 54 | ./node_modules/.bin/nyc report --reporter=text-lcov | ./node_modules/.bin/codecov --pipe 55 | ``` 56 | 57 | #### [Istanbul](https://github.com/gotwarlost/istanbul) 58 | 59 | **With Mocha:** 60 | 61 | ```sh 62 | istanbul cover ./node_modules/mocha/bin/_mocha -- -R spec 63 | ./node_modules/.bin/codecov 64 | ``` 65 | 66 | **With Jasmine:** 67 | 68 | ```sh 69 | istanbul cover jasmine-node --captureExceptions spec/ 70 | ./node_modules/.bin/codecov 71 | ``` 72 | 73 | **With Tape:** 74 | 75 | ```sh 76 | istanbul cover test.js 77 | ./node_modules/.bin/codecov 78 | ``` 79 | 80 | [appveyor-url]: https://ci.appveyor.com/project/eddiemoore/codecov-node-s38o6/branch/master 81 | [github-actions-image]: https://github.com/codecov/codecov-node/workflows/Node%20CI/badge.svg 82 | [github-actions-url]: https://github.com/codecov/codecov-node/actions?query=workflow%3A%22Node+CI%22 83 | [travis-image]: https://travis-ci.org/codecov/codecov-node.svg?branch=master 84 | [travis-url]: https://travis-ci.org/codecov/codecov-node 85 | [npm-url]: https://npmjs.org/package/codecov 86 | [npm-image]: https://img.shields.io/npm/v/codecov.svg 87 | [depstat-url]: https://david-dm.org/codecov/codecov-node 88 | [depstat-image]: https://david-dm.org/codecov/codecov-node/status.svg 89 | [devdepstat-url]: https://david-dm.org/codecov/codecov-node?type=dev 90 | [devdepstat-image]: https://david-dm.org/codecov/codecov-node/dev-status.svg 91 | 92 | **With NYC** 93 | 94 | ``` 95 | nyc npm test 96 | nyc report --reporter=lcov 97 | ./node_modules/.bin/codecov 98 | ``` 99 | 100 | ## Troubleshooting 101 | 102 | If you're seeing an **HTTP 400 error when uploading reports to S3**, make sure you've updated to at least version 3.7.0. 103 | 104 | 105 | ## License 106 | [![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-node.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcodecov%2Fcodecov-node?ref=badge_large) 107 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - nodejs_version: '14' 4 | - nodejs_version: '12' 5 | - nodejs_version: '10' 6 | 7 | max_jobs: 4 8 | 9 | clone_depth: 50 10 | 11 | init: 12 | - git config --global core.autocrlf true 13 | 14 | install: 15 | - ps: Install-Product node $env:nodejs_version x64 16 | - npm install 17 | 18 | test_script: 19 | - cmd: SET PATH=C:\MinGW\bin;%PATH% 20 | - npm run test 21 | 22 | after_test: 23 | - node .\bin\codecov -f coverage\*.json 24 | 25 | build: off 26 | 27 | deploy: off 28 | -------------------------------------------------------------------------------- /bin/codecov: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var argv = require('argv'); 3 | var codecov = require('../lib/codecov'); 4 | 5 | 6 | var args = argv.option([ 7 | {name: 'token', short: 't', type: 'string', description: "Private repository token. Not required for public repos on Travis, CircleCI and AppVeyor"}, 8 | {name: 'file', short: 'f', type: 'path', description: "Target a specific file for uploading and disabling automatic detection of coverage files."}, 9 | {name: 'env', short: 'e', type: 'string', description: "Store environment variables to help distinguish CI builds.", example: "--env=VAR1,VAR2,VAR3"}, 10 | {name: 'root', short: 'p', type: 'path', description: "Project root, if not current directory"}, 11 | {name: 'gcov-root', type: 'path', description: "Project root directory when preparing gcov"}, 12 | {name: 'gcov-glob', type: 'string', description: "Paths to ignore during gcov gathering"}, 13 | {name: 'gcov-exec', type: 'string', description: "gcov executable to run. Defaults to 'gcov'"}, 14 | {name: 'gcov-args', type: 'string', description: "extra arguments to pass to gcov"}, 15 | {name: 'disable', short: 'X', type: 'string', description: "Disable features. Accepting `search` to disable crawling through directories, `detect` to disable detecting CI provider, `gcov` disable gcov commands"}, 16 | {name: 'commit', short: 'c', type: 'string', description: "Commit sha, set automatically"}, 17 | {name: 'clear', short: 'C', type: 'boolean', description: "Remove all discovered reports after uploading"}, 18 | {name: 'branch', short: 'b', type: 'string', description: "Branch name"}, 19 | {name: 'build', short: 'B', type: 'string', description: "Specify a custom build number to distinguish ci jobs, provided automatically for supported ci companies"}, 20 | {name: 'slug', short: 'r', type: 'string', description: "Specify repository slug for Enterprise ex. owner/repo"}, 21 | {name: 'url', short: 'u', type: 'string', description: "Your Codecov endpoint"}, 22 | {name: 'flags', short: 'F', type: 'string', description: "Codecov Flags"}, 23 | {name: 'dump', type: 'boolean', description: "Dump collected data and do not send to Codecov"}, 24 | {name: 'pipe', short: 'l', type: 'boolean', description: "Listen to stdin for coverage data"}, 25 | {name: 'yml', short: 'y', type: 'string', description: "Configuration file Used to specify the location of the .codecov.yml config file. Defaults to codecov.yml and .codecov.yml"}, 26 | ]).run(); 27 | 28 | if (args.options.pipe) { 29 | process.stdin.setEncoding('utf8'); 30 | args.options.pipe = []; 31 | 32 | process.stdin.on('data', function(report) { 33 | args.options.pipe.push(report); 34 | }); 35 | 36 | process.stdin.on('end', function() { 37 | codecov.upload(args); 38 | }); 39 | } else { 40 | codecov.upload(args); 41 | } 42 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | node: 3 | version: 14 4 | 5 | test: 6 | post: 7 | - ./bin/codecov -f coverage/*.json 8 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | parsers: 3 | javascript: 4 | enable_partials: no 5 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var handleInput = require('./lib/codecov') 2 | 3 | exports.handleInput = handleInput 4 | -------------------------------------------------------------------------------- /lib/codecov.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var request = require('teeny-request').teenyRequest 4 | var urlgrey = require('urlgrey') 5 | var jsYaml = require('js-yaml') 6 | var walk = require('ignore-walk') 7 | var execFileSync = require('child_process').execFileSync 8 | var execSync = require('child_process').execSync 9 | 10 | var detectProvider = require('./detect') 11 | 12 | var version = 'v' + require('../package.json').version 13 | 14 | var patterns = '' 15 | var more_patterns = '' 16 | var winPatterns = '' 17 | 18 | var isWindows = 19 | process.platform.match(/win32/) || process.platform.match(/win64/) 20 | 21 | if (!isWindows) { 22 | patterns = ( 23 | '-type f ( ' + 24 | '-name *coverage.* ' + 25 | '-or -name *.gcov ' + 26 | '-or -name *.lcov ' + 27 | '-or -name *.lst ' + 28 | '-or -name clover.xml ' + 29 | '-or -name cobertura.xml ' + 30 | '-or -name coverage-final.json ' + 31 | '-or -name gcov.info ' + 32 | '-or -name jacoco*.xml ' + 33 | '-or -name lcov.info ' + 34 | '-or -name luacov.report.out ' + 35 | '-or -name nosetests.xml ' + 36 | '-or -name report.xml ' + 37 | ') ' + 38 | '-not -name *.sh ' + 39 | '-not -name *.data ' + 40 | '-not -name *.py ' + 41 | '-not -name *.class ' + 42 | '-not -name *.xcconfig ' + 43 | '-not -name Coverage.profdata ' + 44 | '-not -name phpunit-code-coverage.xml ' + 45 | '-not -name coverage.serialized ' + 46 | '-not -name *.pyc ' + 47 | '-not -name *.cfg ' + 48 | '-not -name *.egg ' + 49 | '-not -name *.whl ' + 50 | '-not -name *.html ' + 51 | '-not -name *.js ' + 52 | '-not -name *.cpp ' + 53 | '-not -name coverage.jade ' + 54 | '-not -name include.lst ' + 55 | '-not -name inputFiles.lst ' + 56 | '-not -name createdFiles.lst ' + 57 | '-not -name coverage.html ' + 58 | '-not -name scoverage.measurements.* ' + 59 | '-not -name test_*_coverage.txt ' + 60 | '-not -path */vendor/* ' + 61 | '-not -path */htmlcov/* ' + 62 | '-not -path */home/cainus/* ' + 63 | '-not -path */virtualenv/* ' + 64 | '-not -path */js/generated/coverage/* ' + 65 | '-not -path */.virtualenv/* ' + 66 | '-not -path */virtualenvs/* ' + 67 | '-not -path */.virtualenvs/* ' + 68 | '-not -path */.env/* ' + 69 | '-not -path */.envs/* ' + 70 | '-not -path */env/* ' + 71 | '-not -path */envs/* ' + 72 | '-not -path */.venv/* ' + 73 | '-not -path */.venvs/* ' + 74 | '-not -path */venv/* ' + 75 | '-not -path */venvs/* ' + 76 | '-not -path */.git/* ' + 77 | '-not -path */.hg/* ' + 78 | '-not -path */.tox/* ' + 79 | '-not -path */__pycache__/* ' + 80 | '-not -path */.egg-info* ' + 81 | '-not -path */$bower_components/* ' + 82 | '-not -path */node_modules/* ' + 83 | '-not -path */conftest_*.c.gcov' 84 | ).split(' ') 85 | } else { 86 | winPatterns = ( 87 | '/a:-d /b /s *coverage.* ' + 88 | '/s nosetests.xml ' + 89 | '/s jacoco*.xml ' + 90 | '/s clover.xml ' + 91 | '/s report.xml ' + 92 | '/s cobertura.xml ' + 93 | '/s luacov.report.out ' + 94 | '/s lcov.info ' + 95 | '/s *.lcov ' + 96 | '/s gcov.info ' + 97 | '/s *.gcov ' + 98 | '/s *.lst' + 99 | '| findstr /i /v \\.sh$ ' + 100 | '| findstr /i /v \\.data$ ' + 101 | '| findstr /i /v \\.py$ ' + 102 | '| findstr /i /v \\.class$ ' + 103 | '| findstr /i /v \\.xcconfig$ ' + 104 | '| findstr /i /v Coverage\\.profdata$ ' + 105 | '| findstr /i /v phpunit-code-coverage\\.xml$ ' + 106 | '| findstr /i /v coverage\\.serialized$ ' + 107 | '| findstr /i /v \\.pyc$ ' + 108 | '| findstr /i /v \\.cfg$ ' + 109 | '| findstr /i /v \\.egg$ ' + 110 | '| findstr /i /v \\.whl$ ' + 111 | '| findstr /i /v \\.html$ ' + 112 | '| findstr /i /v \\.js$ ' + 113 | '| findstr /i /v \\.cpp$ ' + 114 | '| findstr /i /v coverage\\.jade$ ' + 115 | '| findstr /i /v include\\.lst$ ' + 116 | '| findstr /i /v inputFiles\\.lst$ ' + 117 | '| findstr /i /v createdFiles\\.lst$ ' + 118 | '| findstr /i /v coverage\\.html$ ' + 119 | '| findstr /i /v scoverage\\.measurements\\..* ' + 120 | '| findstr /i /v test_.*_coverage\\.txt ' + 121 | '| findstr /i /v \\vendor\\ ' + 122 | '| findstr /i /v \\htmlcov\\ ' + 123 | '| findstr /i /v \\home\\cainus\\ ' + 124 | '| findstr /i /v \\js\\generated\\coverage\\ ' + 125 | '| findstr /i /v \\virtualenv\\ ' + 126 | '| findstr /i /v \\virtualenvs\\ ' + 127 | '| findstr /i /v \\\\.virtualenv\\ ' + 128 | '| findstr /i /v \\\\.virtualenvs\\ ' + 129 | '| findstr /i /v \\\\.env\\ ' + 130 | '| findstr /i /v \\\\.envs\\ ' + 131 | '| findstr /i /v \\env\\ ' + 132 | '| findstr /i /v \\envs\\ ' + 133 | '| findstr /i /v \\\\.venv\\ ' + 134 | '| findstr /i /v \\\\.venvs\\ ' + 135 | '| findstr /i /v \\venv\\ ' + 136 | '| findstr /i /v \\venvs\\ ' + 137 | '| findstr /i /v \\\\.git\\ ' + 138 | '| findstr /i /v \\\\.hg\\ ' + 139 | '| findstr /i /v \\\\.tox\\ ' + 140 | '| findstr /i /v \\__pycache__\\ ' + 141 | '| findstr /i /v \\\\.egg-info* ' + 142 | '| findstr /i /v \\\\$bower_components\\ ' + 143 | '| findstr /i /v \\node_modules\\ ' + 144 | '| findstr /i /v \\conftest_.*\\.c\\.gcov ' 145 | ).split(' ') 146 | } 147 | 148 | var sendToCodecovV2 = function ( 149 | codecov_endpoint, 150 | query, 151 | upload_body, 152 | on_success, 153 | on_failure 154 | ) { 155 | // Direct to Codecov 156 | request( 157 | { 158 | uri: urlgrey(codecov_endpoint + '/upload/v2') 159 | .query(query) 160 | .toString(), 161 | method: 'POST', 162 | body: upload_body, 163 | headers: { 164 | 'Content-Type': 'text/plain', 165 | Accept: 'text/plain', 166 | }, 167 | }, 168 | function (err, response) { 169 | if (err || response.statusCode !== 200) { 170 | console.log(' ' + (err || response.body)) 171 | return response 172 | ? on_failure(response.statusCode, response.body) 173 | : on_failure(err.code, err.message) 174 | } else { 175 | console.log(' Success!') 176 | console.log(' View report at: ' + response.body) 177 | return on_success(response.body) 178 | } 179 | } 180 | ) 181 | } 182 | 183 | var sendToCodecovV4 = function ( 184 | codecov_endpoint, 185 | query, 186 | upload_body, 187 | on_success, 188 | on_failure 189 | ) { 190 | // Direct to S3 191 | request( 192 | { 193 | uri: urlgrey(codecov_endpoint + '/upload/v4') 194 | .query(query) 195 | .toString(), 196 | method: 'POST', 197 | body: '', 198 | headers: { 199 | 'Content-Type': 'text/plain', 200 | Accept: 'text/plain', 201 | }, 202 | }, 203 | function (err, response, result) { 204 | if (err) { 205 | sendToCodecovV2( 206 | codecov_endpoint, 207 | query, 208 | upload_body, 209 | on_success, 210 | on_failure 211 | ) 212 | } else if (result.split('\n').length !== 2) { 213 | console.log(' Could not upload to Codecov: ' + result) 214 | } else { 215 | var codecov_report_url = result.split('\n')[0] 216 | request( 217 | { 218 | uri: result.split('\n')[1], 219 | method: 'PUT', 220 | body: upload_body, 221 | headers: { 222 | 'Content-Type': 'text/plain', 223 | }, 224 | }, 225 | function (err) { 226 | if (err) { 227 | sendToCodecovV2( 228 | codecov_endpoint, 229 | query, 230 | upload_body, 231 | on_success, 232 | on_failure 233 | ) 234 | } else { 235 | console.log(' Success!') 236 | console.log(' View report at: ' + codecov_report_url) 237 | on_success(codecov_report_url) 238 | } 239 | } 240 | ) 241 | } 242 | } 243 | ) 244 | } 245 | 246 | var upload = function (args, on_success, on_failure) { 247 | // Build query 248 | var codecov_endpoint = 249 | args.options.url || 250 | process.env.codecov_url || 251 | process.env.CODECOV_URL || 252 | 'https://codecov.io' 253 | var query = {} 254 | var debug = [] 255 | var yamlFile = 256 | args.options.yml || 257 | process.env.codecov_yml || 258 | process.env.CODECOV_YML || 259 | 'codecov.yml' 260 | 261 | console.log( 262 | '' + 263 | ' _____ _ \n' + 264 | ' / ____| | | \n' + 265 | '| | ___ __| | ___ ___ _____ __ \n' + 266 | '| | / _ \\ / _` |/ _ \\/ __/ _ \\ \\ / / \n' + 267 | '| |___| (_) | (_| | __/ (_| (_) \\ V / \n' + 268 | ' \\_____\\___/ \\__,_|\\___|\\___\\___/ \\_/ \n' + 269 | ' ' + 270 | version 271 | ) 272 | 273 | if ((args.options.disable || '').split(',').indexOf('detect') === -1) { 274 | console.log('==> Detecting CI Provider') 275 | query = detectProvider() 276 | } else { 277 | debug.push('disabled detect') 278 | } 279 | 280 | query.yaml = [yamlFile, '.codecov.yml'].reduce(function (result, file) { 281 | return ( 282 | result || 283 | (fs.existsSync(path.resolve(process.cwd(), file)) 284 | ? path.resolve(process.cwd(), file) 285 | : undefined) 286 | ) 287 | }, undefined) 288 | 289 | if (args.options.build) { 290 | query.build = args.options.build 291 | } 292 | 293 | if (args.options.commit) { 294 | query.commit = args.options.commit 295 | } 296 | 297 | if (args.options.branch) { 298 | query.branch = args.options.branch 299 | } 300 | 301 | if (args.options.slug) { 302 | query.slug = args.options.slug 303 | } 304 | 305 | var flags = 306 | args.options.flags || process.env.codecov_flags || process.env.CODECOV_FLAGS 307 | if (flags) { 308 | query.flags = flags 309 | } 310 | 311 | var yamlToken 312 | try { 313 | var loadedYamlFile = jsYaml.safeLoad(fs.readFileSync(query.yaml, 'utf8')) 314 | yamlToken = 315 | loadedYamlFile && loadedYamlFile.codecov && loadedYamlFile.codecov.token 316 | } catch (e) { 317 | // silently fail 318 | } 319 | var token = 320 | args.options.token || 321 | yamlToken || 322 | process.env.codecov_token || 323 | process.env.CODECOV_TOKEN 324 | if (token) { 325 | query.token = token 326 | } 327 | 328 | query.package = 'node-' + version 329 | 330 | console.log('==> Configuration: ') 331 | console.log(' Endpoint: ' + codecov_endpoint) 332 | // Don't output `query` directly as it contains the upload token 333 | console.log({ 334 | commit: query.commit, 335 | branch: query.branch, 336 | package: query.package, 337 | }) 338 | 339 | var upload = '' 340 | 341 | // Add specified env vars 342 | var env_found = false 343 | if (args.options.env || process.env.CODECOV_ENV || process.env.codecov_env) { 344 | var env = ( 345 | args.options.env + 346 | ',' + 347 | (process.env.CODECOV_ENV || '') + 348 | ',' + 349 | (process.env.codecov_env || '') 350 | ).split(',') 351 | for (var i = env.length - 1; i >= 0; i--) { 352 | if (env[i]) { 353 | upload += env[i] + '=' + (process.env[env[i]] || '').toString() + '\n' 354 | env_found = true 355 | } 356 | } 357 | if (env_found) { 358 | upload += '<<<<<< ENV\n' 359 | } 360 | } 361 | 362 | // List git files 363 | var root = path.resolve(args.options.root || query.root || '.') 364 | console.log('==> Building file structure') 365 | try { 366 | var network = execFileSync('git', ['ls-files'], { cwd: root }) 367 | if (network === '') { 368 | network = execFileSync('hg', ['locate'], { cwd: root }) 369 | } 370 | upload += network.toString().trim() + '\n<<<<<< network\n' 371 | } catch (err) { 372 | // not a git/hg dir, emulating git/hg ignore behavior 373 | upload += 374 | walk 375 | .sync({ path: root, ignoreFiles: ['.gitignore', '.hgignore'] }) 376 | .join('\n') 377 | .trim() + '\n<<<<<< network\n' 378 | } 379 | // Make gcov reports 380 | if ((args.options.disable || '').split(',').indexOf('gcov') === -1) { 381 | try { 382 | console.log('==> Generating gcov reports (skip via --disable=gcov)') 383 | var gcg = args.options['gcov-glob'] || '' 384 | if (gcg) { 385 | if (!isWindows) { 386 | gcg = gcg 387 | .split(' ') 388 | .map(function (p) { 389 | return "-not -path '" + p + "'" 390 | }) 391 | .join(' ') 392 | } else { 393 | gcg = gcg 394 | .split(' ') 395 | .map(function (p) { 396 | return '^| findstr /i /v ' + p 397 | }) 398 | .join(' ') 399 | } 400 | } 401 | var gcov 402 | if (!isWindows) { 403 | gcov = 404 | 'find ' + 405 | (sanitizeVar(args.options['gcov-root']) || root) + 406 | " -type f -name '*.gcno' " + 407 | gcg + 408 | ' -exec ' + 409 | (sanitizeVar(args.options['gcov-exec']) || 'gcov') + 410 | ' ' + 411 | (sanitizeVar(args.options['gcov-args']) || '') + 412 | ' {} +' 413 | } else { 414 | // @TODO support for root 415 | // not straight forward due to nature of windows command dir 416 | gcov = 417 | 'for /f "delims=" %g in (\'dir /a-d /b /s *.gcno ' + 418 | gcg + 419 | "') do " + 420 | (sanitizeVar(args.options['gcov-exec']) || 'gcov') + 421 | ' ' + 422 | (sanitizeVar(args.options['gcov-args']) || '') + 423 | ' %g' 424 | } 425 | debug.push(gcov) 426 | console.log(' $ ' + gcov) 427 | execFileSync(gcov) 428 | } catch (e) { 429 | console.log(' Failed to run gcov command.') 430 | } 431 | } else { 432 | debug.push('disabled gcov') 433 | } 434 | 435 | // Detect .bowerrc 436 | var bowerrc 437 | if (!isWindows) { 438 | bowerrc = execSync('test -f .bowerrc && cat .bowerrc || echo ""', { 439 | cwd: root, 440 | }) 441 | .toString() 442 | .trim() 443 | } else { 444 | bowerrc = fs.existsSync('.bowerrc') 445 | } 446 | if (bowerrc) { 447 | bowerrc = JSON.parse(bowerrc).directory 448 | if (bowerrc) { 449 | if (!isWindows) { 450 | more_patterns = ( 451 | " -not -path '*/" + 452 | bowerrc.toString().replace(/\/$/, '') + 453 | "/*'" 454 | ).split(' ') 455 | } else { 456 | more_patterns = ( 457 | '| findstr /i /v \\' + 458 | bowerrc.toString().replace(/\/$/, '') + 459 | '\\' 460 | ).split(' ') 461 | } 462 | } 463 | } 464 | 465 | var files = [], 466 | file = null 467 | if (args.options.pipe) { 468 | // Append piped reports 469 | upload += '# path=piped\n' + args.options.pipe.join('') + '\n<<<<<< EOF\n' 470 | console.log('==> Reading report from stdin') 471 | } else if (args.options.file) { 472 | // Append manually entered reports 473 | file = args.options.file 474 | console.log('==> Targeting specific file') 475 | try { 476 | upload += 477 | '# path=' + 478 | file + 479 | '\n' + 480 | fs.readFileSync(file, 'utf8').toString() + 481 | '\n<<<<<< EOF\n' 482 | console.log(' + ' + file) 483 | files.push(file) 484 | } catch (e) { 485 | debug.push('failed: ' + file.split('/').pop()) 486 | console.log(' X Failed to read file at ' + file) 487 | } 488 | } else if ((args.options.disable || '').split(',').indexOf('search') === -1) { 489 | console.log('==> Scanning for reports') 490 | var _files 491 | var _findArgs 492 | if (!isWindows) { 493 | // @TODO support for a root directory 494 | // It's not straightforward due to the nature of the find command 495 | _findArgs = [root].concat(patterns) 496 | if (more_patterns) { 497 | _findArgs.concat(more_patterns) 498 | } 499 | _files = execFileSync('find', _findArgs).toString().trim().split('\n') 500 | } else { 501 | // @TODO support for a root directory 502 | // It's not straightforward due to the nature of the dir command 503 | _findArgs = [root].concat(winPatterns) 504 | if (more_patterns) { 505 | _findArgs.concat(more_patterns) 506 | } 507 | _files = execSync('dir ' + winPatterns.join(' ') + more_patterns) 508 | .toString() 509 | .trim() 510 | .split('\r\n') 511 | } 512 | if (_files) { 513 | for (var i2 = _files.length - 1; i2 >= 0; i2--) { 514 | file = _files[i2] 515 | try { 516 | upload += 517 | '# path=' + 518 | file + 519 | '\n' + 520 | fs.readFileSync(file, 'utf8').toString() + 521 | '\n<<<<<< EOF\n' 522 | console.log(' + ' + file) 523 | files.push(file) 524 | } catch (e) { 525 | debug.push('failed: ' + file.split('/').pop()) 526 | console.log(' X Failed to read file at ' + file) 527 | } 528 | } 529 | } 530 | } else { 531 | debug.push('disabled search') 532 | } 533 | 534 | if (files) { 535 | // Upload to Codecov 536 | if (args.options.dump) { 537 | console.log('-------- DEBUG START --------') 538 | console.log(upload) 539 | console.log('-------- DEBUG END --------') 540 | } else { 541 | console.log('==> Uploading reports') 542 | var _upload 543 | if ((args.options.disable || '').split(',').indexOf('s3') === -1) { 544 | _upload = sendToCodecovV4 545 | } else { 546 | _upload = sendToCodecovV2 547 | } 548 | _upload( 549 | codecov_endpoint, 550 | query, 551 | upload, 552 | function () { 553 | // remove files after Uploading 554 | if (args.options.clear) { 555 | for (var i = files.length - 1; i >= 0; i--) { 556 | try { 557 | fs.unlinkSync(files[i]) 558 | } catch (e) {} 559 | } 560 | } 561 | if (on_success) { 562 | on_success.apply(this, arguments) 563 | } 564 | }, 565 | on_failure || function () {} 566 | ) 567 | } 568 | } 569 | 570 | return { 571 | body: upload, 572 | files: files, 573 | query: query, 574 | debug: debug, 575 | url: codecov_endpoint, 576 | } 577 | } 578 | 579 | function sanitizeVar(arg) { 580 | if (!arg) { 581 | return '' 582 | } 583 | return arg.replace(/&/g, '') 584 | } 585 | 586 | module.exports = { 587 | sanitizeVar: sanitizeVar, 588 | upload: upload, 589 | version: version, 590 | sendToCodecovV2: sendToCodecovV2, 591 | sendToCodecovV4: sendToCodecovV4, 592 | } 593 | -------------------------------------------------------------------------------- /lib/detect.js: -------------------------------------------------------------------------------- 1 | var services = { 2 | travis: require('./services/travis'), 3 | circle: require('./services/circle'), 4 | cirrus: require('./services/cirrus'), 5 | buildkite: require('./services/buildkite'), 6 | azurePipelines: require('./services/azurePipelines'), 7 | codeship: require('./services/codeship'), 8 | drone: require('./services/drone'), 9 | appveyor: require('./services/appveyor'), 10 | wercker: require('./services/wercker'), 11 | jenkins: require('./services/jenkins'), 12 | semaphore: require('./services/semaphore'), 13 | semaphore2x: require('./services/semaphore2x'), 14 | snap: require('./services/snap'), 15 | gitlab: require('./services/gitlab'), 16 | heroku: require('./services/heroku'), 17 | teamcity: require('./services/teamcity'), 18 | codebuild: require('./services/codebuild'), 19 | github_actions: require('./services/github_actions'), 20 | } 21 | 22 | var detectProvider = function() { 23 | var config 24 | for (var name in services) { 25 | if (services[name].detect()) { 26 | config = services[name].configuration() 27 | break 28 | } 29 | } 30 | if (!config) { 31 | var local = require('./services/localGit') 32 | config = local.configuration() 33 | if (!config) { 34 | throw new Error('Unknown CI service provider. Unable to upload coverage.') 35 | } 36 | } 37 | return config 38 | } 39 | 40 | module.exports = detectProvider 41 | -------------------------------------------------------------------------------- /lib/git.js: -------------------------------------------------------------------------------- 1 | var execSync = require('child_process').execSync 2 | 3 | module.exports = { 4 | branch: function() { 5 | return execSync('git rev-parse --abbrev-ref HEAD || hg branch') 6 | .toString() 7 | .trim() 8 | }, 9 | 10 | head: function() { 11 | return execSync("git log -1 --pretty=%H || hg id -i --debug | tr -d '+'") 12 | .toString() 13 | .trim() 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /lib/offline.js: -------------------------------------------------------------------------------- 1 | // see: http://man7.org/linux/man-pages/man2/accept.2.html#ERRORS 2 | var offlineErrorCodes = [ 3 | 'EAI_AGAIN', 4 | 'ENETDOWN', 5 | 'EPROTO', 6 | 'ENOPROTOOPT', 7 | 'EHOSTDOWN', 8 | 'ENONET', 9 | 'EHOSTUNREACH', 10 | 'EOPNOTSUPP', 11 | 'ENETUNREACH', 12 | ] 13 | 14 | module.exports = offlineErrorCodes 15 | -------------------------------------------------------------------------------- /lib/services/appveyor.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.APPVEYOR 4 | }, 5 | 6 | configuration: function() { 7 | console.log(' AppVeyor CI Detected') 8 | return { 9 | service: 'appveyor', 10 | commit: process.env.APPVEYOR_REPO_COMMIT, 11 | branch: process.env.APPVEYOR_REPO_BRANCH, 12 | pr: process.env.APPVEYOR_PULL_REQUEST_NUMBER, 13 | job: 14 | process.env.APPVEYOR_ACCOUNT_NAME + 15 | '/' + 16 | process.env.APPVEYOR_PROJECT_SLUG + 17 | '/' + 18 | process.env.APPVEYOR_BUILD_VERSION, 19 | build: process.env.APPVEYOR_JOB_ID, 20 | slug: process.env.APPVEYOR_REPO_NAME, 21 | } 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /lib/services/azurePipelines.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.TF_BUILD 4 | }, 5 | 6 | configuration: function() { 7 | console.log(' Azure Pipelines CI Detected') 8 | return { 9 | service: 'azure_pipelines', 10 | commit: process.env.BUILD_SOURCEVERSION, 11 | branch: process.env.BUILD_SOURCEBRANCH, 12 | pr: process.env.SYSTEM_PULLREQUEST_PULLREQUESTNUMBER, 13 | job: process.env.SYSTEM_JOBID, 14 | build: process.env.BUILD_BUILDID, 15 | build_url: 16 | process.env.SYSTEM_TEAMFOUNDATIONSERVERURI + 17 | process.env.SYSTEM_TEAMPROJECT + 18 | '/_build/results?buildId=' + 19 | process.env.BUILD_BUILDID, 20 | slug: process.env.BUILD_REPOSITORY_ID, 21 | } 22 | }, 23 | } 24 | -------------------------------------------------------------------------------- /lib/services/buildkite.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.BUILDKITE 4 | }, 5 | 6 | configuration: function() { 7 | // https://buildkite.com/docs/guides/environment-variables 8 | console.log(' Buildkite CI Detected') 9 | return { 10 | service: 'buildkite', 11 | build: process.env.BUILDKITE_BUILD_NUMBER, 12 | build_url: process.env.BUILDKITE_BUILD_URL, 13 | commit: process.env.BUILDKITE_COMMIT, 14 | branch: process.env.BUILDKITE_BRANCH, 15 | slug: process.env.BUILDKITE_PROJECT_SLUG, 16 | } 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /lib/services/circle.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.CIRCLECI 4 | }, 5 | 6 | configuration: function() { 7 | console.log(' Circle CI Detected') 8 | return { 9 | service: 'circleci', 10 | build: process.env.CIRCLE_BUILD_NUM + '.' + process.env.CIRCLE_NODE_INDEX, 11 | job: process.env.CIRCLE_BUILD_NUM + '.' + process.env.CIRCLE_NODE_INDEX, 12 | commit: process.env.CIRCLE_SHA1, 13 | branch: process.env.CIRCLE_BRANCH, 14 | pr: process.env.CIRCLE_PR_NUMBER, 15 | slug: detectRepoSlug(), 16 | } 17 | function detectRepoSlug() { 18 | if (process.env.CIRCLE_PROJECT_REPONAME) { 19 | // CircleCI 1.0 20 | // CIRCLE_PROJECT_REPONAME=codecov 21 | // CIRCLE_PROJECT_USERNAME=codecov-node 22 | // CIRCLE_REPOSITORY_URL=https://github.com/codecov/codecov-node (note: GitHub Web URL) 23 | return ( 24 | process.env.CIRCLE_PROJECT_USERNAME + 25 | '/' + 26 | process.env.CIRCLE_PROJECT_REPONAME 27 | ) 28 | } 29 | if (process.env.CIRCLE_REPOSITORY_URL) { 30 | // CircleCI 2.0 31 | // CIRCLE_REPOSITORY_URL=git@github.com:codecov/codecov-node.git (note: Git/SSH URL) 32 | return process.env.CIRCLE_REPOSITORY_URL.replace(/^.*:/, '').replace( 33 | /\.git$/, 34 | '' 35 | ) 36 | } 37 | throw new Error('Cannot detect repository slug.') 38 | } 39 | }, 40 | } 41 | -------------------------------------------------------------------------------- /lib/services/cirrus.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.CIRRUS_CI 4 | }, 5 | configuration: function() { 6 | console.log(' Cirrus CI Detected') 7 | return { 8 | service: 'cirrus-ci', 9 | build: process.env.CIRRUS_BUILD_ID, 10 | job: process.env.CIRRUS_TASK_ID, 11 | commit: process.env.CIRRUS_CHANGE_IN_REPO, 12 | branch: process.env.CIRRUS_BRANCH, 13 | pr: process.env.CIRRUS_PR, 14 | slug: process.env.CIRRUS_REPO_FULL_NAME, 15 | } 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /lib/services/codebuild.js: -------------------------------------------------------------------------------- 1 | var git = require('../git.js') 2 | 3 | module.exports = { 4 | detect: function() { 5 | return !!process.env.CODEBUILD_CI 6 | }, 7 | 8 | configuration: function() { 9 | console.log(' AWS CodeBuild Detected') 10 | return { 11 | service: 'codebuild', 12 | build: process.env.CODEBUILD_BUILD_ID, 13 | job: process.env.CODEBUILD_BUILD_ID, 14 | commit: process.env.CODEBUILD_RESOLVED_SOURCE_VERSION, 15 | branch: detectBranchName(), 16 | pr: detectPRNumber(), 17 | slug: detectRepoSlug(), 18 | } 19 | function detectBranchName() { 20 | if (process.env.CODEBUILD_WEBHOOK_HEAD_REF) { 21 | return process.env.CODEBUILD_WEBHOOK_HEAD_REF.replace( 22 | /^refs\/heads\//, 23 | '' 24 | ) 25 | } 26 | return git.branch() 27 | } 28 | function detectPRNumber() { 29 | if ( 30 | process.env.CODEBUILD_WEBHOOK_HEAD_REF && 31 | process.env.CODEBUILD_SOURCE_VERSION.startsWith('pr/') 32 | ) { 33 | return process.env.CODEBUILD_SOURCE_VERSION.replace(/^pr\//, '') 34 | } 35 | return undefined 36 | } 37 | function detectRepoSlug() { 38 | if (process.env.CODEBUILD_SOURCE_REPO_URL) { 39 | return process.env.CODEBUILD_SOURCE_REPO_URL.replace( 40 | /^.*github.com\//, 41 | '' 42 | ).replace(/\.git$/, '') 43 | } 44 | throw new Error('Cannot detect repository slug.') 45 | } 46 | }, 47 | } 48 | -------------------------------------------------------------------------------- /lib/services/codeship.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return process.env.CI_NAME && process.env.CI_NAME === 'codeship' 4 | }, 5 | 6 | configuration: function() { 7 | console.log(' Codeship CI Detected') 8 | return { 9 | service: 'codeship', 10 | build: process.env.CI_BUILD_NUMBER, 11 | build_url: process.env.CI_BUILD_URL, 12 | commit: process.env.CI_COMMIT_ID, 13 | branch: process.env.CI_BRANCH, 14 | } 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /lib/services/drone.js: -------------------------------------------------------------------------------- 1 | var git = require('../git') 2 | 3 | module.exports = { 4 | detect: function() { 5 | return !!process.env.DRONE 6 | }, 7 | 8 | configuration: function() { 9 | console.log(' Drone.io CI Detected') 10 | return { 11 | service: 'drone.io', 12 | build: process.env.DRONE_BUILD_NUMBER, 13 | commit: git.head(), 14 | build_url: process.env.DRONE_BUILD_URL, 15 | branch: process.env.DRONE_BRANCH, 16 | root: process.env.DRONE_BUILD_DIR, 17 | } 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /lib/services/github_actions.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.GITHUB_ACTIONS 4 | }, 5 | 6 | configuration: function() { 7 | // https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables 8 | console.log(' GitHub Actions CI Detected') 9 | 10 | var params = { 11 | branch: 12 | process.env.GITHUB_HEAD_REF || 13 | process.env.GITHUB_REF.replace('refs/heads/', ''), 14 | build: process.env.GITHUB_RUN_ID, 15 | commit: process.env.GITHUB_SHA, 16 | service: 'github-actions', 17 | slug: process.env.GITHUB_REPOSITORY, 18 | } 19 | 20 | if (process.env.GITHUB_HEAD_REF) { 21 | // PR refs are in the format: refs/pull/7/merge for pull_request events 22 | params['pr'] = process.env.GITHUB_REF.split('/')[2] 23 | } 24 | 25 | return params 26 | }, 27 | } 28 | -------------------------------------------------------------------------------- /lib/services/gitlab.js: -------------------------------------------------------------------------------- 1 | // https://docs.gitlab.com/ce/ci/variables/README.html 2 | 3 | module.exports = { 4 | detect: function() { 5 | return !!process.env.GITLAB_CI 6 | }, 7 | 8 | configuration: function() { 9 | console.log(' Gitlab CI Detected') 10 | var remote = 11 | process.env.CI_BUILD_REPO || process.env.CI_REPOSITORY_URL || '' 12 | return { 13 | service: 'gitlab', 14 | build: process.env.CI_BUILD_ID, 15 | commit: process.env.CI_BUILD_REF, 16 | branch: process.env.CI_BUILD_REF_NAME, 17 | root: process.env.CI_PROJECT_DIR, 18 | slug: remote 19 | .split('/') 20 | .slice(3, 5) 21 | .join('/') 22 | .replace('.git', ''), 23 | } 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /lib/services/heroku.js: -------------------------------------------------------------------------------- 1 | // https://devcenter.heroku.com/articles/heroku-ci 2 | 3 | module.exports = { 4 | detect: function() { 5 | return !!process.env.HEROKU_TEST_RUN_ID 6 | }, 7 | 8 | configuration: function() { 9 | console.log(' heroku CI Detected') 10 | return { 11 | service: 'heroku', 12 | build: process.env.HEROKU_TEST_RUN_ID, 13 | commit: process.env.HEROKU_TEST_RUN_COMMIT_VERSION, 14 | branch: process.env.HEROKU_TEST_RUN_BRANCH, 15 | } 16 | }, 17 | } 18 | -------------------------------------------------------------------------------- /lib/services/jenkins.js: -------------------------------------------------------------------------------- 1 | var git = require('../git') 2 | 3 | module.exports = { 4 | detect: function() { 5 | return !!process.env.JENKINS_URL 6 | }, 7 | 8 | configuration: function() { 9 | console.log(' Jenkins CI Detected') 10 | return { 11 | service: 'jenkins', 12 | commit: 13 | process.env.ghprbActualCommit || process.env.GIT_COMMIT || git.head(), 14 | branch: 15 | process.env.ghprbSourceBranch || 16 | process.env.GIT_BRANCH || 17 | process.env.BRANCH_NAME, 18 | build: process.env.BUILD_NUMBER, 19 | build_url: process.env.BUILD_URL, 20 | root: process.env.WORKSPACE, 21 | pr: process.env.ghprbPullId || process.env.CHANGE_ID, 22 | } 23 | }, 24 | } 25 | -------------------------------------------------------------------------------- /lib/services/localGit.js: -------------------------------------------------------------------------------- 1 | var git = require('../git') 2 | 3 | module.exports = { 4 | configuration: function() { 5 | console.log(' No CI Detected. Using git/mercurial') 6 | var branch = git.branch() 7 | if (branch === 'HEAD') { 8 | branch = 'master' 9 | } 10 | var head = git.head() 11 | return { 12 | commit: head, 13 | branch: branch, 14 | } 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /lib/services/semaphore.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.SEMAPHORE && !!process.env.SEMAPHORE_REPO_SLUG 4 | }, 5 | 6 | configuration: function() { 7 | console.log(' Semaphore 1.x CI Detected') 8 | return { 9 | service: 'semaphore', 10 | build: 11 | process.env.SEMAPHORE_BUILD_NUMBER + 12 | '.' + 13 | process.env.SEMAPHORE_CURRENT_THREAD, 14 | commit: process.env.REVISION, 15 | branch: process.env.BRANCH_NAME, 16 | slug: process.env.SEMAPHORE_REPO_SLUG, 17 | } 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /lib/services/semaphore2x.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.SEMAPHORE && !!process.env.SEMAPHORE_WORKFLOW_ID 4 | }, 5 | 6 | configuration: function() { 7 | console.log(' Semaphore 2.x CI Detected') 8 | return { 9 | service: 'semaphore', 10 | branch: process.env.SEMAPHORE_GIT_BRANCH, 11 | build: process.env.SEMAPHORE_WORKFLOW_ID, 12 | commit: process.env.SEMAPHORE_GIT_SHA, 13 | } 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /lib/services/shippable.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.SHIPPABLE 4 | }, 5 | 6 | configuration: function() { 7 | // http://docs.shippable.com/en/latest/config.html#common-environment-variables 8 | console.log(' Shippable CI Detected') 9 | return { 10 | service: 'shippable', 11 | build: process.env.BUILD_NUMBER, 12 | build_url: process.env.BUILD_URL, 13 | pr: process.env.PULL_REQUEST, 14 | commit: process.env.COMMIT, 15 | branch: process.env.BRANCH, 16 | slug: process.env.REPO_NAME, 17 | } 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /lib/services/snap.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.SNAP_CI 4 | }, 5 | 6 | configuration: function() { 7 | console.log(' Snap CI Detected') 8 | return { 9 | service: 'snap', 10 | build: process.env.SNAP_PIPELINE_COUNTER, 11 | commit: process.env.SNAP_COMMIT || process.env.SNAP_UPSTREAM_COMMIT, 12 | branch: process.env.SNAP_BRANCH || process.env.SNAP_UPSTREAM_BRANCH, 13 | pr: process.env.SNAP_PULL_REQUEST_NUMBER, 14 | } 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /lib/services/teamcity.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 3 | detect: function () { 4 | return !!process.env.TEAMCITY_VERSION; 5 | }, 6 | 7 | configuration: function () { 8 | console.log(' TeamCity CI Detected'); 9 | return { 10 | service: 'teamcity', 11 | commit: process.env.BUILD_VCS_NUMBER, 12 | branch: process.env.BRANCH_NAME, 13 | build: process.env.BUILD_NUMBER 14 | }; 15 | } 16 | 17 | }; -------------------------------------------------------------------------------- /lib/services/travis.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | detect: function() { 3 | return !!process.env.TRAVIS 4 | }, 5 | 6 | configuration: function() { 7 | console.log(' Travis CI Detected') 8 | return { 9 | service: 'travis', 10 | commit: process.env.TRAVIS_COMMIT, 11 | build: process.env.TRAVIS_JOB_NUMBER, 12 | branch: process.env.TRAVIS_BRANCH, 13 | job: process.env.TRAVIS_JOB_ID, 14 | pr: process.env.TRAVIS_PULL_REQUEST, 15 | slug: process.env.TRAVIS_REPO_SLUG, 16 | root: process.env.TRAVIS_BUILD_DIR, 17 | } 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /lib/services/wercker.js: -------------------------------------------------------------------------------- 1 | // http://devcenter.wercker.com/articles/steps/variables.html 2 | 3 | module.exports = { 4 | detect: function() { 5 | return !!process.env.WERCKER_MAIN_PIPELINE_STARTED 6 | }, 7 | 8 | configuration: function() { 9 | console.log(' Wercker CI Detected') 10 | return { 11 | service: 'wercker', 12 | build: process.env.WERCKER_MAIN_PIPELINE_STARTED, 13 | commit: process.env.WERCKER_GIT_COMMIT, 14 | build_url: process.env.WERCKER_BUILD_URL, 15 | branch: process.env.WERCKER_GIT_BRANCH, 16 | slug: 17 | process.env.WERCKER_GIT_OWNER + 18 | '/' + 19 | process.env.WERCKER_GIT_REPOSITORY, 20 | } 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codecov", 3 | "version": "3.8.3", 4 | "description": "Uploading report to Codecov: https://codecov.io", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "eslint .", 8 | "pretest": "npm run lint", 9 | "test": "jest --coverage" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/codecov/codecov-node" 14 | }, 15 | "keywords": [ 16 | "coverage", 17 | "code-coverage", 18 | "codecov.io", 19 | "codecov" 20 | ], 21 | "bin": { 22 | "codecov": "./bin/codecov" 23 | }, 24 | "engines": { 25 | "node": ">=4.0" 26 | }, 27 | "author": "Codecov ", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/codecov/codecov-node/issues" 31 | }, 32 | "homepage": "https://github.com/codecov/codecov-node", 33 | "dependencies": { 34 | "argv": "0.0.2", 35 | "ignore-walk": "4.0.1", 36 | "js-yaml": "3.14.1", 37 | "teeny-request": "7.1.3", 38 | "urlgrey": "1.0.0" 39 | }, 40 | "devDependencies": { 41 | "eslint": "7.32.0", 42 | "eslint-config-prettier": "8.3.0", 43 | "husky": "7.0.4", 44 | "jest": "27.5.1", 45 | "lint-staged": "12.2.0", 46 | "mock-fs": "4.14.0", 47 | "prettier": "2.5.1" 48 | }, 49 | "husky": { 50 | "hooks": { 51 | "pre-commit": "npm run lint && lint-staged", 52 | "pre-push": "npm test" 53 | } 54 | }, 55 | "lint-staged": { 56 | "*.{ts,js,json,md}": [ 57 | "prettier --write", 58 | "git add" 59 | ] 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /test/detect.test.js: -------------------------------------------------------------------------------- 1 | var detect = require('../lib/detect') 2 | var git = require('../lib/git') 3 | 4 | describe('Codecov', function() { 5 | it('can detect existing appveyor service', function() { 6 | process.env.TRAVIS = 'true' 7 | 8 | expect(detect().service).toBe('travis') 9 | 10 | process.env.TRAVIS = '' 11 | }) 12 | 13 | it('can select local git service if no service is found', function() { 14 | expect(detect().commit).toMatch(/^\w{40}$/) 15 | expect(detect().commit).toBe(git.head()) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /test/example.coverage.txt: -------------------------------------------------------------------------------- 1 | this file is intentionally left blank 2 | -------------------------------------------------------------------------------- /test/git.test.js: -------------------------------------------------------------------------------- 1 | var git = require('../lib/git') 2 | var execSync = require('child_process').execSync 3 | 4 | describe('Git', function() { 5 | it('can get the branch', function() { 6 | expect(git.branch()).toEqual( 7 | execSync('git rev-parse --abbrev-ref HEAD || hg branch') 8 | .toString() 9 | .trim() 10 | ) 11 | }) 12 | 13 | it('can get the head', function() { 14 | expect(git.head()).toEqual( 15 | execSync("git log -1 --pretty=%H || hg id -i --debug | tr -d '+'") 16 | .toString() 17 | .trim() 18 | ) 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var mockFs = require('mock-fs') 3 | var codecov = require('../lib/codecov') 4 | 5 | var isWindows = 6 | process.platform.match(/win32/) || process.platform.match(/win64/) 7 | var pathSeparator = !isWindows ? '/' : '\\' 8 | 9 | describe('Codecov', function() { 10 | beforeEach(function() { 11 | try { 12 | fs.unlinkSync('.bowerrc') 13 | } catch (e) {} 14 | }) 15 | 16 | afterAll(function() { 17 | try { 18 | fs.unlinkSync('.bowerrc') 19 | } catch (e) {} 20 | }) 21 | 22 | it('can get a token passed via env variable', function() { 23 | jest.setTimeout(10000) 24 | process.env.codecov_token = 'abc123' 25 | expect(codecov.upload({ options: { dump: true } }).query.token).toBe( 26 | 'abc123' 27 | ) 28 | delete process.env.codecov_token 29 | process.env.CODECOV_TOKEN = 'ABC123' 30 | expect(codecov.upload({ options: { dump: true } }).query.token).toBe( 31 | 'ABC123' 32 | ) 33 | delete process.env.CODECOV_TOKEN 34 | }) 35 | 36 | it('can get a token passed in cli', function() { 37 | expect( 38 | codecov.upload({ options: { dump: true, token: 'qwerty' } }).query.token 39 | ).toBe('qwerty') 40 | }) 41 | 42 | it('can read a codecov.yml file', function() { 43 | mockFs({ 44 | 'codecov.yml': 'codecov:\n token: fake-token', 45 | }) 46 | expect(codecov.upload({ options: { dump: true } }).query.token).toBe( 47 | 'fake-token' 48 | ) 49 | mockFs.restore() 50 | }) 51 | it('can read a .codecov.yml file', function() { 52 | mockFs({ 53 | '.codecov.yml': 'codecov:\n token: fake-token-dotfile', 54 | }) 55 | expect(codecov.upload({ options: { dump: true } }).query.token).toBe( 56 | 'fake-token-dotfile' 57 | ) 58 | mockFs.restore() 59 | }) 60 | it('should have no token if yaml file does not supplied', function() { 61 | mockFs({ 62 | '.codecov.yml': 'codecov:\n noconfig: true', 63 | }) 64 | expect(codecov.upload({ options: { dump: true } }).query.token).toBe( 65 | undefined 66 | ) 67 | mockFs.restore() 68 | }) 69 | 70 | it('token precedence should be respected', function() { 71 | // options.token || .codecov.yml/codecov.yml file || codecov_token || CODECOV_TOKEN 72 | mockFs({ 73 | '.codecov.yml': 'codecov:\n token: fake-token-dotfile', 74 | }) 75 | var upload = codecov.upload({ options: { dump: true, token: 'qwerty' } }) 76 | expect(upload.query.token).toBe('qwerty') 77 | mockFs.restore() 78 | 79 | process.env.codecov_token = 'abc123' 80 | upload = codecov.upload({ options: { dump: true, token: 'qwerty2' } }) 81 | expect(upload.query.token).toBe('qwerty2') 82 | delete process.env.codecov_token 83 | 84 | process.env.CODECOV_TOKEN = 'ABC123' 85 | upload = codecov.upload({ options: { dump: true, token: 'qwerty3' } }) 86 | expect(upload.query.token).toBe('qwerty3') 87 | delete process.env.CODECOV_TOKEN 88 | 89 | mockFs({ 90 | '.codecov.yml': 'codecov:\n token: fake-token-dotfile', 91 | }) 92 | process.env.codecov_token = 'abc123' 93 | upload = codecov.upload({ options: { dump: true } }) 94 | expect(upload.query.token).toBe('fake-token-dotfile') 95 | mockFs.restore() 96 | 97 | process.env.codecov_token = 'abc123' 98 | process.env.CODECOV_TOKEN = 'ABC123' 99 | upload = codecov.upload({ options: { dump: true } }) 100 | if (process.platform === 'win32') { 101 | expect(upload.query.token).toBe('ABC123') 102 | } else { 103 | expect(upload.query.token).toBe('abc123') 104 | } 105 | delete process.env.codecov_token 106 | delete process.env.CODECOV_TOKEN 107 | }) 108 | 109 | // it('can auto detect reports', function() { 110 | // var res = codecov.upload({ options: { dump: true } }) 111 | // expect(res.files[0].split(pathSeparator).pop()).toBe('example.coverage.txt') 112 | // expect(res.body).toContain('this file is intentionally left blank') 113 | // }) 114 | 115 | it('can specify report in cli', function() { 116 | var res = codecov.upload({ 117 | options: { 118 | dump: true, 119 | file: 'test' + pathSeparator + 'example.coverage.txt', 120 | }, 121 | }) 122 | expect(res.files[0].split(pathSeparator).pop()).toBe('example.coverage.txt') 123 | expect(res.body).toContain('this file is intentionally left blank') 124 | }) 125 | 126 | it('can specify report in cli fail', function() { 127 | var res = codecov.upload({ options: { dump: true, file: 'notreal.txt' } }) 128 | expect(res.debug).toContain('failed: notreal.txt') 129 | }) 130 | 131 | it('can disable search', function() { 132 | var res = codecov.upload({ options: { dump: true, disable: 'search' } }) 133 | expect(res.debug).toContain('disabled search') 134 | expect(res.files).toEqual([]) 135 | }) 136 | 137 | it('can disable gcov', function() { 138 | var res = codecov.upload({ options: { dump: true, disable: 'gcov' } }) 139 | console.log(res.debug) 140 | expect(res.debug).toContain('disabled gcov') 141 | }) 142 | 143 | it('can disable detection', function() { 144 | var res = codecov.upload({ options: { dump: true, disable: 'detect' } }) 145 | expect(res.debug).toContain('disabled detect') 146 | }) 147 | 148 | it('can get build from cli args', function() { 149 | var res = codecov.upload({ options: { dump: true, build: 'value' } }) 150 | expect(res.query.build).toBe('value') 151 | }) 152 | 153 | it('can get commit from cli args', function() { 154 | var res = codecov.upload({ options: { dump: true, commit: 'value' } }) 155 | expect(res.query.commit).toBe('value') 156 | }) 157 | 158 | it('can get branch from cli args', function() { 159 | var res = codecov.upload({ options: { dump: true, branch: 'value' } }) 160 | expect(res.query.branch).toBe('value') 161 | }) 162 | 163 | it('can get slug from cli args', function() { 164 | var res = codecov.upload({ options: { dump: true, slug: 'value' } }) 165 | expect(res.query.slug).toBe('value') 166 | }) 167 | 168 | it('can get flags from cli args', function() { 169 | var res = codecov.upload({ options: { dump: true, flags: 'value' } }) 170 | expect(res.query.flags).toBe('value') 171 | }) 172 | 173 | it('can include env in cli', function() { 174 | process.env.HELLO = 'world' 175 | var res = codecov.upload({ options: { dump: true, env: 'HELLO,VAR1' } }) 176 | expect(res.body).toContain('HELLO=world\n') 177 | expect(res.body).toContain('VAR1=\n') 178 | delete process.env.HELLO 179 | }) 180 | 181 | it('can include env in env', function() { 182 | process.env.HELLO = 'world' 183 | process.env.CODECOV_ENV = 'HELLO,VAR1' 184 | var res = codecov.upload({ options: { dump: true, env: 'VAR2' } }) 185 | expect(res.body).toContain('HELLO=world\n') 186 | expect(res.body).toContain('VAR1=\n') 187 | expect(res.body).toContain('VAR2=\n') 188 | delete process.env.HELLO 189 | delete process.env.CODECOV_ENV 190 | }) 191 | 192 | it('can have custom args for gcov', function() { 193 | var res = codecov.upload({ 194 | options: { 195 | dump: true, 196 | 'gcov-root': 'folder/path', 197 | 'gcov-glob': 'ignore/this/folder', 198 | 'gcov-exec': 'llvm-gcov', 199 | 'gcov-args': '-o', 200 | }, 201 | }) 202 | if (!isWindows) { 203 | expect(res.debug).toContain( 204 | "find folder/path -type f -name '*.gcno' -not -path 'ignore/this/folder' -exec llvm-gcov -o {} +" 205 | ) 206 | } else { 207 | expect(res.debug).toContain( 208 | 'for /f "delims=" %g in (\'dir /a-d /b /s *.gcno ^| findstr /i /v ignore/this/folder\') do llvm-gcov -o %g' 209 | ) 210 | } 211 | }) 212 | 213 | it('can read piped reports', function(done) { 214 | var exec = require('child_process').exec 215 | var childProcess = exec( 216 | 'cat test/example.coverage.txt | bin/codecov -l --dump --disable=gcov', 217 | function(err, stdout) { 218 | try { 219 | expect(stdout.toString()).toContain('path=piped') 220 | expect(stdout.toString()).toContain( 221 | 'this file is intentionally left blank' 222 | ) 223 | } catch (e) { 224 | var isWin = process.platform === 'win32' || 'win64' 225 | expect(isWin) 226 | } 227 | childProcess.kill() 228 | done() 229 | } 230 | ) 231 | }) 232 | 233 | it('should have the correct version number', function() { 234 | var version = require('../package.json').version 235 | expect(codecov.version).toBe('v' + version) 236 | }) 237 | 238 | it('Should use codecov.yml via env variable', function() { 239 | var CWD = process 240 | .cwd() 241 | .toString() 242 | .replace(/\\/g, '/') 243 | expect( 244 | codecov 245 | .upload({ options: { dump: true, disable: 'detect' } }) 246 | .query.yaml.toString() 247 | .replace(/\\/g, '/') 248 | ).toBe(CWD + '/codecov.yml') 249 | 250 | mockFs({ 251 | 'foo.yml': '', 252 | }) 253 | process.env.codecov_yml = 'foo.yml' 254 | expect( 255 | codecov 256 | .upload({ options: { dump: true, disable: 'detect' } }) 257 | .query.yaml.toString() 258 | .replace(/\\/g, '/') 259 | ).toBe(CWD + '/foo.yml') 260 | mockFs.restore() 261 | delete process.env.codecov_yml 262 | 263 | mockFs({ 264 | 'FOO.yml': '', 265 | }) 266 | process.env.CODECOV_YML = 'FOO.yml' 267 | expect( 268 | codecov 269 | .upload({ options: { dump: true, disable: 'detect' } }) 270 | .query.yaml.toString() 271 | .replace(/\\/g, '/') 272 | ).toBe(CWD + '/FOO.yml') 273 | mockFs.restore() 274 | delete process.env.CODECOV_YML 275 | }) 276 | 277 | it('can get config from cli args', function() { 278 | mockFs({ 279 | 'foo.yml': '', 280 | }) 281 | var res = codecov.upload({ 282 | options: { dump: true, yml: 'foo.yml', disable: 'detect' }, 283 | }) 284 | var CWD = process 285 | .cwd() 286 | .toString() 287 | .replace(/\\/g, '/') 288 | expect(res.query.yaml.toString().replace(/\\/g, '/')).toBe(CWD + '/foo.yml') 289 | mockFs.restore() 290 | }) 291 | 292 | it('can sanitize inputs', function() { 293 | expect(codecov.sanitizeVar('real & run unsafe & command')).toEqual( 294 | 'real run unsafe command' 295 | ) 296 | }) 297 | 298 | it('gracefully sanitizes undefined', function() { 299 | expect(function() { 300 | codecov.sanitizeVar(undefined) 301 | }).not.toThrow() 302 | }) 303 | }) 304 | -------------------------------------------------------------------------------- /test/services/appveyor.test.js: -------------------------------------------------------------------------------- 1 | var appveyor = require('../../lib/services/appveyor') 2 | 3 | describe('AppVeyor CI Provider', function() { 4 | it('can detect appveyor', function() { 5 | process.env.APPVEYOR = 'true' 6 | expect(appveyor.detect()).toBe(true) 7 | }) 8 | 9 | it('can get appveyor env info', function() { 10 | process.env.APPVEYOR_ACCOUNT_NAME = 'a' 11 | process.env.APPVEYOR_PROJECT_SLUG = 'b' 12 | process.env.APPVEYOR_REPO_COMMIT = '5678' 13 | process.env.APPVEYOR_REPO_BRANCH = 'master' 14 | process.env.APPVEYOR_PULL_REQUEST_NUMBER = '1' 15 | process.env.APPVEYOR_BUILD_VERSION = 'job' 16 | process.env.APPVEYOR_JOB_ID = 'build' 17 | process.env.APPVEYOR_REPO_NAME = 'owner/repo' 18 | 19 | expect(appveyor.configuration()).toEqual({ 20 | service: 'appveyor', 21 | commit: '5678', 22 | build: 'build', 23 | job: 'a/b/job', 24 | pr: '1', 25 | branch: 'master', 26 | slug: 'owner/repo', 27 | }) 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /test/services/azure-pipelines.test.js: -------------------------------------------------------------------------------- 1 | var azurePipelines = require('../../lib/services/azurePipelines') 2 | 3 | describe('Azure Pipelines CI Provider', function() { 4 | it('can detect azure pipelines', function() { 5 | process.env.TF_BUILD = '1' 6 | expect(azurePipelines.detect()).toBe(true) 7 | }) 8 | 9 | it('can get azure pipelines env info', function() { 10 | process.env.BUILD_SOURCEBRANCH = 'master' 11 | process.env.SYSTEM_JOBID = '92a2fa25-f940-5df6-a185-81eb9ae2031d' 12 | process.env.BUILD_BUILDID = '1' 13 | process.env.SYSTEM_TEAMFOUNDATIONSERVERURI = 14 | 'https://dev.azure.com/codecov/' 15 | process.env.SYSTEM_TEAMPROJECT = 'repo' 16 | process.env.BUILD_SOURCEVERSION = '743b04806ea677403aa2ff26c6bdeb85005de658' 17 | process.env.BUILD_REPOSITORY_ID = 'owner/repo' 18 | process.env.SYSTEM_PULLREQUEST_PULLREQUESTNUMBER = '1234' 19 | 20 | expect(azurePipelines.configuration()).toEqual({ 21 | service: 'azure_pipelines', 22 | build: '1', 23 | build_url: 'https://dev.azure.com/codecov/repo/_build/results?buildId=1', 24 | job: '92a2fa25-f940-5df6-a185-81eb9ae2031d', 25 | commit: '743b04806ea677403aa2ff26c6bdeb85005de658', 26 | pr: '1234', 27 | branch: 'master', 28 | slug: 'owner/repo', 29 | }) 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /test/services/buildkite.test.js: -------------------------------------------------------------------------------- 1 | var buildkite = require('../../lib/services/buildkite') 2 | 3 | describe('Buildkite CI Provider', function() { 4 | it('can detect buildkite', function() { 5 | process.env.BUILDKITE = 'true' 6 | expect(buildkite.detect()).toBe(true) 7 | }) 8 | 9 | it('can get buildkite env info', function() { 10 | process.env.BUILDKITE_BUILD_NUMBER = '1' 11 | process.env.BUILDKITE_BUILD_URL = 'url' 12 | process.env.BUILDKITE_COMMIT = 'commit' 13 | process.env.BUILDKITE_BRANCH = 'branch' 14 | process.env.BUILDKITE_PROJECT_SLUG = 'slug' 15 | 16 | expect(buildkite.configuration()).toEqual({ 17 | service: 'buildkite', 18 | build: '1', 19 | build_url: 'url', 20 | commit: 'commit', 21 | branch: 'branch', 22 | slug: 'slug', 23 | }) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /test/services/circle.test.js: -------------------------------------------------------------------------------- 1 | var circle = require('../../lib/services/circle') 2 | 3 | describe('Circle CI Provider', function() { 4 | it('can detect circle', function() { 5 | process.env.CIRCLECI = 'true' 6 | expect(circle.detect()).toBe(true) 7 | }) 8 | 9 | it('can get circle env info (CircleCI 1.0)', function() { 10 | process.env.CIRCLECI = 'true' 11 | process.env.CIRCLE_BUILD_NUM = '1234' 12 | process.env.CIRCLE_SHA1 = '5678' 13 | process.env.CIRCLE_BRANCH = 'master' 14 | process.env.CIRCLE_NODE_INDEX = '1' 15 | process.env.CIRCLE_PR_NUMBER = 'blah' 16 | process.env.CIRCLE_PROJECT_USERNAME = 'owner' 17 | process.env.CIRCLE_PROJECT_REPONAME = 'repo' 18 | expect(circle.configuration()).toEqual({ 19 | service: 'circleci', 20 | commit: '5678', 21 | build: '1234.1', 22 | job: '1234.1', 23 | branch: 'master', 24 | pr: 'blah', 25 | slug: 'owner/repo', 26 | }) 27 | }) 28 | 29 | it('can get circle env info (CircleCI 2.0)', function() { 30 | process.env.CIRCLECI = 'true' 31 | process.env.CIRCLE_BRANCH = 'master' 32 | process.env.CIRCLE_BUILD_NUM = '1234' 33 | process.env.CIRCLE_SHA1 = 'abcd' 34 | process.env.CIRCLE_NODE_INDEX = '1' 35 | process.env.CIRCLE_BUILD_URL = 'https://circleci.com/gh/owner/repo/1234' 36 | process.env.CIRCLE_COMPARE_URL = 37 | 'https://github.com/owner/repo/2408ca9...3c36cfa' 38 | process.env.CIRCLE_NODE_INDEX = '1' 39 | process.env.CIRCLE_REPOSITORY_URL = 'git@github.com:owner/repo.git' 40 | delete process.env.CIRCLE_PR_NUMBER 41 | delete process.env.CIRCLE_PROJECT_USERNAME 42 | delete process.env.CIRCLE_PROJECT_REPONAME 43 | expect(circle.configuration()).toEqual({ 44 | service: 'circleci', 45 | commit: 'abcd', 46 | build: '1234.1', 47 | job: '1234.1', 48 | branch: 'master', 49 | pr: undefined, 50 | slug: 'owner/repo', 51 | }) 52 | }) 53 | 54 | it('throws if repo slug cannot be detected', function() { 55 | delete process.env.CIRCLE_PR_NUMBER 56 | delete process.env.CIRCLE_PROJECT_USERNAME 57 | delete process.env.CIRCLE_PROJECT_REPONAME 58 | delete process.env.CIRCLE_REPOSITORY_URL 59 | expect(function() { 60 | circle.configuration() 61 | }).toThrow() 62 | }) 63 | }) 64 | -------------------------------------------------------------------------------- /test/services/cirrus.test.js: -------------------------------------------------------------------------------- 1 | var cirrus = require('../../lib/services/cirrus') 2 | 3 | describe('Cirrus CI Provider', function() { 4 | it('can detect cirrus', function() { 5 | process.env.CIRRUS_CI = 'true' 6 | expect(cirrus.detect()).toBe(true) 7 | }) 8 | 9 | it('can get cirrus env info', function() { 10 | process.env.CIRRUS_CI = 'true' 11 | process.env.CIRRUS_BUILD_ID = '1234.1' 12 | process.env.CIRRUS_CHANGE_IN_REPO = '5678' 13 | process.env.CIRRUS_BRANCH = 'master' 14 | process.env.CIRRUS_TASK_ID = '1234.1' 15 | process.env.CIRRUS_PR = 'blah' 16 | process.env.CIRRUS_REPO_FULL_NAME = 'owner/repo' 17 | expect(cirrus.configuration()).toEqual({ 18 | service: 'cirrus-ci', 19 | commit: '5678', 20 | build: '1234.1', 21 | job: '1234.1', 22 | branch: 'master', 23 | pr: 'blah', 24 | slug: 'owner/repo', 25 | }) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /test/services/codebuild.test.js: -------------------------------------------------------------------------------- 1 | var codebuild = require('../../lib/services/codebuild') 2 | var git = require('../../lib/git.js') 3 | 4 | // Set all module functions to jest.fn 5 | jest.mock('../../lib/git.js') 6 | 7 | describe('AWS CodeBuild Provider', function() { 8 | it('can detect codebuild', function() { 9 | process.env.CODEBUILD_CI = 'true' 10 | expect(codebuild.detect()).toBe(true) 11 | }) 12 | 13 | it('can get codebuild env info', function() { 14 | process.env.CODEBUILD_CI = 'true' 15 | process.env.CODEBUILD_BUILD_ID = 16 | 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969' 17 | process.env.CODEBUILD_RESOLVED_SOURCE_VERSION = 18 | '39ec2418eca4c539d765574a1c68f3bd77e8c549' 19 | process.env.CODEBUILD_WEBHOOK_HEAD_REF = 'refs/heads/master' 20 | process.env.CODEBUILD_SOURCE_VERSION = 'pr/1' 21 | process.env.CODEBUILD_SOURCE_REPO_URL = 22 | 'https://github.com/my-org/my-project.git' 23 | expect(codebuild.configuration()).toEqual({ 24 | service: 'codebuild', 25 | build: 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969', 26 | job: 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969', 27 | commit: '39ec2418eca4c539d765574a1c68f3bd77e8c549', 28 | branch: 'master', 29 | pr: '1', 30 | slug: 'my-org/my-project', 31 | }) 32 | }) 33 | 34 | it('throws if branch name cannot be detected', function() { 35 | delete process.env.CODEBUILD_WEBHOOK_HEAD_REF 36 | git.branch.mockImplementation(function() { 37 | throw new Error() 38 | }) 39 | expect(function() { 40 | codebuild.configuration() 41 | }).toThrow() 42 | }) 43 | 44 | it('Test build triggered via AWS SDK', function() { 45 | delete process.env.CODEBUILD_WEBHOOK_HEAD_REF 46 | git.branch.mockReturnValue('master') 47 | expect(codebuild.configuration()).toEqual({ 48 | service: 'codebuild', 49 | build: 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969', 50 | job: 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969', 51 | commit: '39ec2418eca4c539d765574a1c68f3bd77e8c549', 52 | branch: 'master', 53 | pr: undefined, 54 | slug: 'my-org/my-project', 55 | }) 56 | }) 57 | 58 | it('Test PR build triggered via Github Webhook', function() { 59 | process.env.CODEBUILD_WEBHOOK_HEAD_REF = 'refs/heads/master' 60 | expect(codebuild.configuration()).toEqual({ 61 | service: 'codebuild', 62 | build: 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969', 63 | job: 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969', 64 | commit: '39ec2418eca4c539d765574a1c68f3bd77e8c549', 65 | branch: 'master', 66 | pr: '1', 67 | slug: 'my-org/my-project', 68 | }) 69 | }) 70 | 71 | it('Test non-PR build triggered via Github Webhook', function() { 72 | process.env.CODEBUILD_WEBHOOK_HEAD_REF = 'refs/heads/master' 73 | process.env.CODEBUILD_SOURCE_VERSION = 74 | '39ec2418eca4c539d765574a1c68f3bd77e8c549' 75 | expect(codebuild.configuration()).toEqual({ 76 | service: 'codebuild', 77 | build: 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969', 78 | job: 'my-project:e016b9d9-f2c8-4749-8373-7ca673b6d969', 79 | commit: '39ec2418eca4c539d765574a1c68f3bd77e8c549', 80 | branch: 'master', 81 | pr: undefined, 82 | slug: 'my-org/my-project', 83 | }) 84 | }) 85 | 86 | it('throws if slug cannot be detected', function() { 87 | process.env.CODEBUILD_RESOLVED_SOURCE_VERSION = 88 | '39ec2418eca4c539d765574a1c68f3bd77e8c549' 89 | delete process.env.CODEBUILD_SOURCE_REPO_URL 90 | expect(function() { 91 | codebuild.configuration() 92 | }).toThrow() 93 | }) 94 | }) 95 | -------------------------------------------------------------------------------- /test/services/codeship.test.js: -------------------------------------------------------------------------------- 1 | var codeship = require('../../lib/services/codeship') 2 | 3 | describe('Codeship CI Provider', function() { 4 | it('can detect codeship', function() { 5 | process.env.CI_NAME = 'codeship' 6 | expect(codeship.detect()).toBe(true) 7 | }) 8 | 9 | it('can get codeship env info', function() { 10 | process.env.CI_BUILD_NUMBER = '1234' 11 | process.env.CI_COMMIT_ID = '5678' 12 | process.env.CI_BRANCH = 'master' 13 | process.env.CI_BUILD_URL = 'https://...' 14 | 15 | expect(codeship.configuration()).toEqual({ 16 | service: 'codeship', 17 | commit: '5678', 18 | build: '1234', 19 | branch: 'master', 20 | build_url: 'https://...', 21 | }) 22 | }) 23 | }) 24 | -------------------------------------------------------------------------------- /test/services/drone.test.js: -------------------------------------------------------------------------------- 1 | var drone = require('../../lib/services/drone') 2 | var git = require('../../lib/git') 3 | 4 | describe('Drone.io CI Provider', function() { 5 | it('can detect drone', function() { 6 | process.env.DRONE = 'true' 7 | expect(drone.detect()).toBe(true) 8 | }) 9 | 10 | it('can get drone env info', function() { 11 | process.env.DRONE_BUILD_NUMBER = '1234' 12 | process.env.DRONE_BRANCH = 'master' 13 | process.env.DRONE_BUILD_URL = 'https://...' 14 | process.env.DRONE_BUILD_DIR = '/' 15 | expect(drone.configuration()).toEqual({ 16 | service: 'drone.io', 17 | commit: git.head(), 18 | build: '1234', 19 | root: '/', 20 | branch: 'master', 21 | build_url: 'https://...', 22 | }) 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /test/services/github_actions.test.js: -------------------------------------------------------------------------------- 1 | var github_actions = require('../../lib/services/github_actions') 2 | 3 | describe('GitHub Actions CI Provider', function() { 4 | it('can detect GitHub Actions', function() { 5 | process.env.GITHUB_ACTIONS = '1' 6 | expect(github_actions.detect()).toBe(true) 7 | }) 8 | 9 | it('can get GitHub Actions env info on push event', function() { 10 | delete process.env.GITHUB_HEAD_REF 11 | process.env.GITHUB_REF = 'refs/heads/master' 12 | process.env.GITHUB_REPOSITORY = 'codecov/codecov-repo' 13 | process.env.GITHUB_RUN_ID = '257701960' 14 | process.env.GITHUB_SHA = '743b04806ea677403aa2ff26c6bdeb85005de658' 15 | 16 | expect(github_actions.configuration()).toEqual({ 17 | branch: 'master', 18 | build: '257701960', 19 | commit: '743b04806ea677403aa2ff26c6bdeb85005de658', 20 | service: 'github-actions', 21 | slug: 'codecov/codecov-repo', 22 | }) 23 | }) 24 | 25 | it('can get GitHub Actions env info on pull request', function() { 26 | process.env.GITHUB_HEAD_REF = 'develop' 27 | process.env.GITHUB_REF = 'refs/pull/7/merge' 28 | process.env.GITHUB_REPOSITORY = 'codecov/codecov-repo' 29 | process.env.GITHUB_RUN_ID = '257701960' 30 | process.env.GITHUB_SHA = '743b04806ea677403aa2ff26c6bdeb85005de658' 31 | 32 | expect(github_actions.configuration()).toEqual({ 33 | branch: 'develop', 34 | build: '257701960', 35 | commit: '743b04806ea677403aa2ff26c6bdeb85005de658', 36 | pr: '7', 37 | service: 'github-actions', 38 | slug: 'codecov/codecov-repo', 39 | }) 40 | }) 41 | }) 42 | -------------------------------------------------------------------------------- /test/services/gitlab.test.js: -------------------------------------------------------------------------------- 1 | var gitlab = require('../../lib/services/gitlab') 2 | 3 | describe('Gitlab CI Provider', function() { 4 | it('can detect gitlab', function() { 5 | process.env.GITLAB_CI = 'true' 6 | expect(gitlab.detect()).toBe(true) 7 | }) 8 | 9 | it('cannot detect gitlab', function() { 10 | delete process.env.GITLAB_CI 11 | expect(gitlab.detect()).toBe(false) 12 | }) 13 | 14 | it('can get service env info', function() { 15 | process.env.CI_BUILD_ID = '1234' 16 | process.env.CI_BUILD_REPO = 'https://gitlab.com/owner/repo.git' 17 | process.env.CI_BUILD_REF = '5678' 18 | process.env.CI_BUILD_REF_NAME = 'master' 19 | process.env.CI_PROJECT_DIR = '/' 20 | expect(gitlab.configuration()).toEqual({ 21 | service: 'gitlab', 22 | build: '1234', 23 | root: '/', 24 | commit: '5678', 25 | slug: 'owner/repo', 26 | branch: 'master', 27 | }) 28 | delete process.env.CI_BUILD_REPO 29 | process.env.CI_REPOSITORY_URL = 'https://gitlab.com/owner/repo2.git' 30 | expect(gitlab.configuration()).toEqual({ 31 | service: 'gitlab', 32 | build: '1234', 33 | root: '/', 34 | commit: '5678', 35 | slug: 'owner/repo2', 36 | branch: 'master', 37 | }) 38 | delete process.env.CI_REPOSITORY_URL 39 | expect(gitlab.configuration()).toEqual({ 40 | service: 'gitlab', 41 | build: '1234', 42 | root: '/', 43 | commit: '5678', 44 | slug: '', 45 | branch: 'master', 46 | }) 47 | }) 48 | }) 49 | -------------------------------------------------------------------------------- /test/services/heroku.test.js: -------------------------------------------------------------------------------- 1 | var heroku = require('../../lib/services/heroku') 2 | 3 | describe('Heroku CI Provider', function() { 4 | it('can detect heroku', function() { 5 | process.env.HEROKU_TEST_RUN_ID = '454f5dc9-afa4-433f-bb28-84678a00fd98' 6 | expect(heroku.detect()).toBe(true) 7 | }) 8 | 9 | it('can get wercker env info', function() { 10 | process.env.HEROKU_TEST_RUN_ID = '454f5dc9-afa4-433f-bb28-84678a00fd98' 11 | process.env.HEROKU_TEST_RUN_COMMIT_VERSION = 12 | '743b04806ea677403aa2ff26c6bdeb85005de658' 13 | process.env.HEROKU_TEST_RUN_BRANCH = 'master' 14 | expect(heroku.configuration()).toEqual({ 15 | service: 'heroku', 16 | commit: '743b04806ea677403aa2ff26c6bdeb85005de658', 17 | build: '454f5dc9-afa4-433f-bb28-84678a00fd98', 18 | branch: 'master', 19 | }) 20 | }) 21 | }) 22 | -------------------------------------------------------------------------------- /test/services/jenkins.test.js: -------------------------------------------------------------------------------- 1 | var jenkins = require('../../lib/services/jenkins') 2 | var git = require('../../lib/git') 3 | 4 | describe('Jenkins CI Provider', function() { 5 | it('can detect jenkins', function() { 6 | process.env.JENKINS_URL = 'http://jenkins.jenkins.example/' 7 | expect(jenkins.detect()).toBe(true) 8 | }) 9 | 10 | it('can get service env info', function() { 11 | process.env.BUILD_NUMBER = '1234' 12 | process.env.BUILD_URL = 'http://asdf/' 13 | process.env.GIT_COMMIT = '5678' 14 | process.env.GIT_BRANCH = 'master' 15 | process.env.WORKSPACE = '/' 16 | expect(jenkins.configuration()).toEqual({ 17 | service: 'jenkins', 18 | build_url: 'http://asdf/', 19 | build: '1234', 20 | root: '/', 21 | commit: '5678', 22 | pr: undefined, 23 | branch: 'master', 24 | }) 25 | }) 26 | 27 | it('can get service env info when using Blue Ocean', function() { 28 | delete process.env.GIT_COMMIT 29 | delete process.env.GIT_BRANCH 30 | process.env.BUILD_NUMBER = '1234' 31 | process.env.BUILD_URL = 'http://asdf/' 32 | process.env.BRANCH_NAME = 'master' 33 | process.env.WORKSPACE = '/' 34 | expect(jenkins.configuration()).toEqual({ 35 | service: 'jenkins', 36 | build_url: 'http://asdf/', 37 | build: '1234', 38 | root: '/', 39 | commit: git.head(), 40 | pr: undefined, 41 | branch: 'master', 42 | }) 43 | }) 44 | 45 | it('github pull request env variables win out over jenkins variables', function() { 46 | process.env.BUILD_NUMBER = '1234' 47 | process.env.BUILD_URL = 'http://asdf/' 48 | process.env.GIT_COMMIT = '5678' 49 | process.env.ghprbActualCommit = '8765' 50 | process.env.GIT_BRANCH = 'master' 51 | process.env.ghprbSourceBranch = 'retsam' 52 | process.env.ghprbPullId = '1111' 53 | process.env.WORKSPACE = '/' 54 | expect(jenkins.configuration()).toEqual({ 55 | service: 'jenkins', 56 | build_url: 'http://asdf/', 57 | build: '1234', 58 | root: '/', 59 | commit: '8765', 60 | pr: '1111', 61 | branch: 'retsam', 62 | }) 63 | }) 64 | }) 65 | -------------------------------------------------------------------------------- /test/services/localGit.test.js: -------------------------------------------------------------------------------- 1 | var local = require('../../lib/services/localGit') 2 | var execSync = require('child_process').execSync 3 | 4 | describe('Local git/mercurial CI Provider', function() { 5 | it('can get commit', function() { 6 | expect(local.configuration().commit).toMatch(/^\w{40}$/) 7 | expect(local.configuration().commit).toEqual( 8 | execSync("git rev-parse HEAD || hg id -i --debug | tr -d '+'") 9 | .toString() 10 | .trim() 11 | ) 12 | }) 13 | 14 | it('can get branch', function() { 15 | expect(local.configuration().branch).not.toEqual(null) 16 | }) 17 | }) 18 | -------------------------------------------------------------------------------- /test/services/semaphore.test.js: -------------------------------------------------------------------------------- 1 | var semaphore = require('../../lib/services/semaphore') 2 | 3 | describe('Semaphore CI Provider', function() { 4 | var OLD_ENV = process.env 5 | 6 | beforeEach(function() { 7 | process.env = Object.assign({}, OLD_ENV) 8 | }) 9 | 10 | afterEach(function() { 11 | process.env = Object.assign({}, OLD_ENV) 12 | }) 13 | 14 | it('can detect semaphore', function() { 15 | process.env.SEMAPHORE = 'true' 16 | process.env.SEMAPHORE_REPO_SLUG = 'owner/repo' 17 | expect(semaphore.detect()).toBe(true) 18 | }) 19 | 20 | it('does not detect semaphore 2.x', function() { 21 | process.env.SEMAPHORE = 'true' 22 | process.env.SEMAPHORE_WORKFLOW_ID = '65c9bb1c-aeb6-41f0-b8d9-6fa177241cdf' 23 | expect(semaphore.detect()).toBe(false) 24 | }) 25 | 26 | it('can get semaphore env info', function() { 27 | process.env.SEMAPHORE_BUILD_NUMBER = '1234' 28 | process.env.REVISION = '5678' 29 | process.env.SEMAPHORE_CURRENT_THREAD = '1' 30 | process.env.BRANCH_NAME = 'master' 31 | process.env.SEMAPHORE_REPO_SLUG = 'owner/repo' 32 | expect(semaphore.configuration()).toEqual({ 33 | service: 'semaphore', 34 | commit: '5678', 35 | build: '1234.1', 36 | branch: 'master', 37 | slug: 'owner/repo', 38 | }) 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /test/services/semaphore2x.test.js: -------------------------------------------------------------------------------- 1 | var semaphore2 = require('../../lib/services/semaphore2x') 2 | 3 | describe('Semaphore 2.x CI Provider', function() { 4 | var OLD_ENV = process.env 5 | 6 | beforeEach(function() { 7 | process.env = Object.assign({}, OLD_ENV) 8 | }) 9 | 10 | afterEach(function() { 11 | process.env = Object.assign({}, OLD_ENV) 12 | }) 13 | 14 | it('can detect semaphore 2x', function() { 15 | process.env.SEMAPHORE = 'true' 16 | process.env.SEMAPHORE_WORKFLOW_ID = '65c9bb1c-aeb6-41f0-b8d9-6fa177241cdf' 17 | expect(semaphore2.detect()).toBe(true) 18 | }) 19 | 20 | it('does not detect semaphore 1.x', function() { 21 | process.env.SEMAPHORE = 'true' 22 | process.env.SEMAPHORE_REPO_SLUG = 'owner/repo' 23 | expect(semaphore2.detect()).toBe(false) 24 | }) 25 | 26 | it('can get semaphore env info', function() { 27 | process.env.SEMAPHORE_GIT_BRANCH = 'development' 28 | process.env.SEMAPHORE_GIT_SHA = '5c84719708b9b649b9ef3b56af214f38cee6acde' 29 | process.env.SEMAPHORE_WORKFLOW_ID = '65c9bb1c-aeb6-41f0-b8d9-6fa177241cdf' 30 | expect(semaphore2.configuration()).toEqual({ 31 | service: 'semaphore', 32 | branch: 'development', 33 | build: '65c9bb1c-aeb6-41f0-b8d9-6fa177241cdf', 34 | commit: '5c84719708b9b649b9ef3b56af214f38cee6acde', 35 | }) 36 | }) 37 | }) 38 | -------------------------------------------------------------------------------- /test/services/shippable.test.js: -------------------------------------------------------------------------------- 1 | var shippable = require('../../lib/services/shippable') 2 | 3 | describe('Shippable CI Provider', function() { 4 | it('can detect shippable', function() { 5 | process.env.SHIPPABLE = 'true' 6 | expect(shippable.detect()).toBe(true) 7 | }) 8 | it('can get shippable env info get_commit_status', function() { 9 | process.env.SHIPPABLE = 'true' 10 | process.env.BUILD_URL = 'http://...' 11 | process.env.COMMIT = '5678' 12 | process.env.BUILD_NUMBER = '91011' 13 | process.env.BUILD_URL = 'http://...' 14 | process.env.BRANCH = 'master' 15 | process.env.PULL_REQUEST = '2' 16 | process.env.REPO_NAME = 'owner/repo' 17 | expect(shippable.configuration()).toEqual({ 18 | service: 'shippable', 19 | commit: '5678', 20 | build: '91011', 21 | build_url: 'http://...', 22 | branch: 'master', 23 | pr: '2', 24 | slug: 'owner/repo', 25 | }) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /test/services/snap.test.js: -------------------------------------------------------------------------------- 1 | var snap = require('../../lib/services/snap') 2 | 3 | describe('Snap CI Provider', function() { 4 | it('can detect snap', function() { 5 | process.env.SNAP_CI = 'true' 6 | expect(snap.detect()).toBe(true) 7 | }) 8 | 9 | it('can get snap env info get_commit_status', function() { 10 | process.env.SNAP_CI = 'true' 11 | process.env.SNAP_PIPELINE_COUNTER = '1234' 12 | process.env.SNAP_COMMIT = '5678' 13 | process.env.SNAP_BRANCH = 'master' 14 | process.env.SNAP_PULL_REQUEST_NUMBER = 'blah' 15 | expect(snap.configuration()).toEqual({ 16 | service: 'snap', 17 | commit: '5678', 18 | build: '1234', 19 | branch: 'master', 20 | pr: 'blah', 21 | }) 22 | }) 23 | 24 | it('can get snap env info get_commit_status for pull requests', function() { 25 | process.env.SNAP_COMMIT = '' 26 | process.env.SNAP_BRANCH = '' 27 | process.env.SNAP_CI = 'true' 28 | process.env.SNAP_PIPELINE_COUNTER = '1234' 29 | process.env.SNAP_UPSTREAM_COMMIT = '5678' 30 | process.env.SNAP_UPSTREAM_BRANCH = 'upstream-branch' 31 | process.env.SNAP_PULL_REQUEST_NUMBER = 'blah' 32 | expect(snap.configuration()).toEqual({ 33 | service: 'snap', 34 | commit: '5678', 35 | build: '1234', 36 | branch: 'upstream-branch', 37 | pr: 'blah', 38 | }) 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /test/services/teamcity.test.js: -------------------------------------------------------------------------------- 1 | var teamcity = require('../../lib/services/teamcity') 2 | 3 | describe('TeamCity CI Provider', function() { 4 | it('can detect teamcity', function() { 5 | process.env.TEAMCITY_VERSION = '8910' 6 | expect(teamcity.detect()).toBe(true) 7 | }) 8 | 9 | it('can get teamcity env info get_commit_status', function() { 10 | process.env.TEAMCITY_VERSION = '8910' 11 | process.env.BUILD_VCS_NUMBER = '4567' 12 | process.env.BRANCH_NAME = 'ABranch' 13 | process.env.BUILD_NUMBER = '1234' 14 | 15 | expect(teamcity.configuration()).toEqual({ 16 | service: 'teamcity', 17 | commit: '4567', 18 | branch: 'ABranch', 19 | build: '1234', 20 | }) 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /test/services/travis.test.js: -------------------------------------------------------------------------------- 1 | var travis = require('../../lib/services/travis') 2 | 3 | describe('Travis CI Provider', function() { 4 | it('can detect travis', function() { 5 | process.env.TRAVIS = 'true' 6 | expect(travis.detect()).toBe(true) 7 | }) 8 | it('can get travis env info get_commit_status', function() { 9 | process.env.TRAVIS = 'true' 10 | process.env.TRAVIS_JOB_ID = '1234' 11 | process.env.TRAVIS_COMMIT = '5678' 12 | process.env.TRAVIS_JOB_NUMBER = '91011' 13 | process.env.TRAVIS_BRANCH = 'master' 14 | process.env.TRAVIS_PULL_REQUEST = 'blah' 15 | process.env.TRAVIS_BUILD_DIR = '/' 16 | process.env.TRAVIS_REPO_SLUG = 'owner/repo' 17 | expect(travis.configuration()).toEqual({ 18 | service: 'travis', 19 | commit: '5678', 20 | build: '91011', 21 | branch: 'master', 22 | root: '/', 23 | job: '1234', 24 | pr: 'blah', 25 | slug: 'owner/repo', 26 | }) 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /test/services/wercker.test.js: -------------------------------------------------------------------------------- 1 | var wercker = require('../../lib/services/wercker') 2 | 3 | describe('Wercker CI Provider', function() { 4 | it('can detect wercker', function() { 5 | process.env.WERCKER_MAIN_PIPELINE_STARTED = '1399372237' 6 | expect(wercker.detect()).toBe(true) 7 | }) 8 | 9 | it('can get wercker env info', function() { 10 | process.env.WERCKER_MAIN_PIPELINE_STARTED = '1399372237' 11 | process.env.WERCKER_GIT_COMMIT = '5678' 12 | process.env.WERCKER_GIT_BRANCH = 'master' 13 | process.env.WERCKER_BUILD_URL = 'https://...' 14 | process.env.WERCKER_GIT_OWNER = 'owner' 15 | process.env.WERCKER_GIT_REPOSITORY = 'repo' 16 | expect(wercker.configuration()).toEqual({ 17 | service: 'wercker', 18 | commit: '5678', 19 | build: '1399372237', 20 | branch: 'master', 21 | build_url: 'https://...', 22 | slug: 'owner/repo', 23 | }) 24 | }) 25 | }) 26 | -------------------------------------------------------------------------------- /test/upload.test.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | // var codecov = require('../lib/codecov') 3 | // var offlineErrors = require('../lib/offline') 4 | 5 | describe('Codecov', function() { 6 | beforeEach(function() { 7 | try { 8 | fs.unlinkSync('report.tmp') 9 | } catch (e) {} 10 | }) 11 | 12 | afterAll(function() { 13 | try { 14 | fs.unlinkSync('report.tmp') 15 | } catch (e) {} 16 | }) 17 | 18 | it('passes', function(done) { 19 | done() 20 | }) 21 | 22 | /* 23 | thomasrockhu - 2020-08-20 24 | These tests are flaky and fail intermittently. Commenting them out until we fix some infrastructure work on the Codecov side. 25 | 26 | it('can get upload to v2', function(done) { 27 | var self = this 28 | codecov.sendToCodecovV2( 29 | 'https://codecov.io', 30 | { 31 | token: 'f881216b-b5c0-4eb1-8f21-b51887d1d506', 32 | commit: 'c739768fcac68144a3a6d82305b9c4106934d31a', 33 | branch: 'master', 34 | }, 35 | 'testing node-' + codecov.version, 36 | function(body) { 37 | expect(body).toContain( 38 | 'https://codecov.io/github/codecov/ci-repo/commit/c739768fcac68144a3a6d82305b9c4106934d31a' 39 | ) 40 | done() 41 | }, 42 | function(errCode, errMsg) { 43 | if (offlineErrors.indexOf(errCode) !== -1) { 44 | self.skip() // offline - we can not test upload 45 | return 46 | } 47 | throw new Error(errMsg) 48 | } 49 | ) 50 | }) 51 | 52 | it('can get upload to v4', function(done) { 53 | var self = this 54 | jest.setTimeout(10000) // give this test extra time to run (default is 2000ms) 55 | codecov.sendToCodecovV4( 56 | 'https://codecov.io', 57 | { 58 | token: 'f881216b-b5c0-4eb1-8f21-b51887d1d506', 59 | commit: 'c739768fcac68144a3a6d82305b9c4106934d31a', 60 | branch: 'master', 61 | }, 62 | 'testing node-' + codecov.version, 63 | function(body) { 64 | expect(body).toContain( 65 | 'https://codecov.io/github/codecov/ci-repo/commit/c739768fcac68144a3a6d82305b9c4106934d31a' 66 | ) 67 | done() 68 | }, 69 | function(errCode, errMsg) { 70 | if (offlineErrors.indexOf(errCode) !== -1) { 71 | self.skip() // offline - we can not test upload 72 | return 73 | } 74 | throw new Error(errMsg) 75 | } 76 | ) 77 | }) 78 | **/ 79 | }) 80 | --------------------------------------------------------------------------------