├── .dependabot └── config.yml ├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── SECURITY.md ├── SUPPORT.md └── workflows │ ├── commitlint.yml │ ├── fix-lint.yml │ └── pull-requests.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc.js ├── .travis.yml ├── .vimrc ├── .yo-rc.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── cli.js ├── package-lock.json ├── package.json └── test.js /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | update_configs: 3 | - package_manager: javascript 4 | directory: / 5 | update_schedule: daily 6 | default_labels: 7 | - dependencies 8 | automerged_updates: 9 | - match: 10 | update_type: all 11 | dependency_type: all 12 | allowed_updates: 13 | - match: 14 | update_type: all 15 | dependency_type: direct 16 | - match: 17 | update_type: security 18 | dependency_type: indirect 19 | version_requirement_updates: increase_versions 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint:recommended', 'plugin:prettier/recommended'], 3 | parserOptions: { 4 | ecmaVersion: 2018, 5 | }, 6 | env: { 7 | node: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: tlvince 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | 11 | > A clear and concise description of what the bug is 12 | 13 | **To Reproduce** 14 | 15 | > Steps to reproduce the behaviour 16 | 17 | **Expected behaviour** 18 | 19 | > A clear and concise description of what you expected to happen. 20 | 21 | **Screenshots** 22 | 23 | > If applicable, add screenshots to help explain your problem. 24 | 25 | **Context** 26 | 27 | - OS: 28 | - Version: 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | 11 | > A clear and concise description of what the problem is, e.g. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | 15 | > A clear and concise description of what you want to happen 16 | 17 | **Describe alternatives you've considered** 18 | 19 | > A clear and concise description of any alternative solutions or features you've considered 20 | 21 | **Additional context** 22 | 23 | > Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | 4 | 5 | ## How has this been tested? 6 | 7 | 8 | 9 | ## Types of changes 10 | 11 | 12 | 13 | - [ ] Test change (non-breaking change which adds additional test scenarios) 14 | - [ ] Refactor change (non-breaking change updates coding styles) 15 | - [ ] Bug fix (non-breaking change which fixes an issue) 16 | - [ ] New feature (non-breaking change which adds functionality) 17 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 18 | 19 | ## Checklist 20 | 21 | 22 | 23 | - [ ] I have ran `npm run lint` and everything passes 24 | - [ ] I have ran `npm run test` and everything passes 25 | - [ ] I have ran `npm run build` and everything built 26 | - [ ] My code follows the code style of this project 27 | - [ ] I have pinned all new external dependencies to an exact version 28 | - [ ] I have updated the documentation where necessary 29 | - [ ] I have read the [CONTRIBUTING](../CONTRIBUTING.md) document 30 | - [ ] I have added tests to cover my changes 31 | - [ ] All new and existing tests pass 32 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Only the latest release of this project is currently being supported with security updates. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | Please report vulnerabilities using the issue tracker. If it's sensitive, please contact me via [Keybase][]. 10 | 11 | [keybase]: https://keybase.io/tlvince 12 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | This is an open source project that I maintain in my free time. I can only offer limited support, but will do my best to fix any bugs and implement new feature requests. 4 | 5 | Please see the [CONTRIBUTING](../CONTRIBUTING.md) document. If in doubt, feel free to get in touch. 6 | -------------------------------------------------------------------------------- /.github/workflows/commitlint.yml: -------------------------------------------------------------------------------- 1 | name: Commitlint 2 | on: pull_request 3 | 4 | jobs: 5 | lint: 6 | runs-on: ubuntu-latest 7 | env: 8 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 9 | steps: 10 | - uses: actions/checkout@v1 11 | - uses: wagoid/commitlint-github-action@v1.2.2 12 | -------------------------------------------------------------------------------- /.github/workflows/fix-lint.yml: -------------------------------------------------------------------------------- 1 | name: Fix lint 2 | on: 3 | push: 4 | branches: 5 | - dependabot/npm_and_yarn/eslint-* 6 | - dependabot/npm_and_yarn/prettier-* 7 | jobs: 8 | fix-lint: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v1 13 | 14 | - name: Setup Node.js 15 | uses: actions/setup-node@v1 16 | with: 17 | node-version: 12 18 | 19 | - name: npm or Yarn install with caching 20 | uses: bahmutov/npm-install@v1.1.0 21 | 22 | - name: Fix lint 23 | run: npm run lint:fix 24 | 25 | - name: Update PR 26 | uses: gr2m/create-or-update-pull-request-action@v1.x 27 | env: 28 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 29 | with: 30 | title: 'Lint fixed' 31 | body: 'An update to eslint or prettier required updates to your code.' 32 | branch: ${{ github.ref }} 33 | commit-message: 'style: fix linting issues' 34 | -------------------------------------------------------------------------------- /.github/workflows/pull-requests.yml: -------------------------------------------------------------------------------- 1 | name: Pull Requests 2 | on: pull_request 3 | jobs: 4 | build-and-test: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Checkout 8 | uses: actions/checkout@v1 9 | 10 | - name: Setup Node.js 11 | uses: actions/setup-node@v1 12 | with: 13 | node-version: 12 14 | 15 | - name: npm or Yarn install with caching 16 | uses: bahmutov/npm-install@v1.1.0 17 | 18 | - name: Lint 19 | run: npm run lint 20 | 21 | - name: Test 22 | run: npm run test 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | coverage 4 | .nyc_output 5 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-exact=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: false, 3 | trailingComma: 'es5', 4 | singleQuote: true, 5 | } 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '12' 4 | cache: npm 5 | notifications: 6 | email: false 7 | after_success: 8 | - npm run semantic-release 9 | branches: 10 | except: 11 | - /^v\d+\.\d+\.\d+$/ 12 | -------------------------------------------------------------------------------- /.vimrc: -------------------------------------------------------------------------------- 1 | let $PATH = './node_modules/.bin:' . $PATH 2 | let g:neomake_javascript_enabled_makers = ['standard'] 3 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-tlvince-node": { 3 | "promptValues": { 4 | "githubUsername": "tlvince", 5 | "website": "https://tlvince.com" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /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 make 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 behaviour 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 behaviour by participants include: 24 | 25 | - The use of sexualised 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 | behaviour and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behaviour. 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 behaviours that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behaviour may be 58 | reported by contacting the project team at github@tlvince.com. 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 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Hey! Thanks for your interest in contributing to this project. 4 | 5 | In lieu of formal rules, please familiarise yourself with the following guidelines: 6 | 7 | - [How to Contribute to Open Source][] 8 | - [necolas/issue-guidelines][] 9 | - Tim Pope's [Git commit message model][tpope] 10 | 11 | Also note, this project is released with a [Contributor Code of Conduct](./CODE_OF_CONDUCT.md). By participating in this project, you agree to abide by its terms. 12 | 13 | In brief, for issues: 14 | 15 | - before opening an issue, please search for existing issues 16 | - if you're reporting a bug, please include steps to reproduce the issue and a [reduced test case][] 17 | - for feature requests, please share the motivation for the feature and how you would implement it 18 | 19 | For pull requests: 20 | 21 | - please make use of the included linting and editor configuration 22 | - add a unit test for new/changed functionality 23 | - format commit messages according to [Conventional Commits][] 24 | 25 | If in doubt, file an issue first. 26 | 27 | Thanks! 28 | 29 | [how to contribute to open source]: https://opensource.guide/how-to-contribute/ 30 | [necolas/issue-guidelines]: https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md 31 | [tpope]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 32 | [conventional commits]: https://www.conventionalcommits.org/ 33 | [reduced test case]: https://css-tricks.com/reduced-test-cases/ 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Tom Vincent (https://tlvince.com) 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # make-coverage-badge 2 | 3 | [![Build Status][travis-image]][travis-url] 4 | [![npm version][npm-image]][npm-url] 5 | [![License][license-image]][license-url] 6 | 7 | [travis-url]: https://travis-ci.org/tlvince/make-coverage-badge 8 | [travis-image]: https://img.shields.io/travis/tlvince/make-coverage-badge.svg 9 | [npm-url]: https://www.npmjs.com/package/make-coverage-badge 10 | [npm-image]: https://img.shields.io/npm/v/make-coverage-badge.svg 11 | [license-url]: https://opensource.org/licenses/MIT 12 | [license-image]: https://img.shields.io/npm/l/make-coverage-badge.svg 13 | 14 | > Create a coverage badge 15 | 16 | Creates a code coverage badge like the following: 17 | 18 | ![Coverage badge][coverage-badge] 19 | 20 | Currently just reads from Istanbul's JSON summary reporter and downloads a badge from https://shields.io/. Don't expect too much! Send a PR if you need configuration etc. 21 | 22 | [coverage-badge]: https://img.shields.io/badge/Coverage-100%25-brightgreen.svg 23 | 24 | ## Usage 25 | 26 | (For Create React Apps) 27 | 28 | 1. Configure Jest (in `package.json`): 29 | 30 | ```json 31 | "jest": { 32 | "coverageReporters": [ 33 | "json-summary" 34 | ] 35 | } 36 | ``` 37 | 38 | 2. Run `npm test -- --coverage` 39 | 3. Run `make-coverage-badge` 40 | 41 | Resulting badge will be in `./coverage/badge.svg`. 42 | 43 | ## Options 44 | 45 | ### `--output-path ` 46 | 47 | Writes the coverage badge to the given path (relative to project root). Defaults to `./coverage/badge.svg`. 48 | 49 | ### `--report-path ` 50 | 51 | Path to a coverage report file. Defaults to `./coverage/coverage-summary.json`. 52 | 53 | ## Prior work 54 | 55 | - [Coveralls][]: paid for private repos 56 | - [coverage-badger][]: same approach, but using an XML report and therefore requires XML dependencies 57 | 58 | [coveralls]: https://coveralls.io/ 59 | [coverage-badger]: https://github.com/notnotse/coverage-badger 60 | 61 | ## Author 62 | 63 | © 2019 Tom Vincent (https://tlvince.com) 64 | 65 | ## License 66 | 67 | Released under the [MIT license](http://tlvince.mit-license.org). 68 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { get } = require('https') 4 | const { readFile, writeFile } = require('fs') 5 | const { basename } = require('path') 6 | const mri = require('mri') 7 | 8 | const getColour = (coverage) => { 9 | if (coverage < 80) { 10 | return 'red' 11 | } 12 | if (coverage < 90) { 13 | return 'yellow' 14 | } 15 | return 'brightgreen' 16 | } 17 | 18 | const getBadge = (report) => { 19 | if (!(report && report.total && report.total.statements)) { 20 | throw new Error('malformed coverage report') 21 | } 22 | 23 | const coverage = report.total.statements.pct 24 | const colour = getColour(coverage) 25 | 26 | return `https://img.shields.io/badge/Coverage-${coverage}${encodeURI( 27 | '%' 28 | )}-${colour}.svg` 29 | } 30 | 31 | const download = (url, cb) => { 32 | get(url, (res) => { 33 | let file = '' 34 | if (res.statusCode > 299) { 35 | cb(new Error(`${res.statusCode}: ${res.statusMessage}`), file) 36 | } 37 | res.on('data', (chunk) => (file += chunk)) 38 | res.on('end', () => cb(null, file)) 39 | }).on('error', (err) => cb(err)) 40 | } 41 | 42 | const options = { 43 | alias: { 44 | h: 'help', 45 | outputPath: 'output-path', 46 | }, 47 | boolean: 'help', 48 | default: { 49 | 'output-path': './coverage/badge.svg', 50 | 'report-path': './coverage/coverage-summary.json', 51 | }, 52 | } 53 | 54 | const [, filename, ...args] = process.argv 55 | const { _, help, ...params } = mri(args, options) // eslint-disable-line no-unused-vars 56 | 57 | if (help) { 58 | console.log( 59 | `usage: ${basename(filename)} [-h,--help] [--report-path] [--output-path]` 60 | ) 61 | process.exit() 62 | } 63 | 64 | const { outputPath, 'report-path': reportPath } = params 65 | 66 | readFile(reportPath, 'utf8', (err, res) => { 67 | if (err) throw err 68 | const report = JSON.parse(res) 69 | const url = getBadge(report) 70 | download(url, (err, res) => { 71 | if (err) throw err 72 | writeFile(outputPath, res, 'utf8', (err) => { 73 | if (err) throw err 74 | console.log('Wrote coverage badge to: ' + outputPath) 75 | }) 76 | }) 77 | }) 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "make-coverage-badge", 3 | "version": "0.0.0-development", 4 | "description": "Create a coverage badge", 5 | "main": "cli.js", 6 | "bin": "cli.js", 7 | "scripts": { 8 | "lint": "npm run eslint && npm run prettier -- --check", 9 | "lint:fix": "npm run eslint -- --fix && npm run prettier -- --write", 10 | "eslint": "eslint '**/*.{js,jsx,ts,tsx}'", 11 | "prettier": "prettier '**/*.{js,jsx,ts,tsx,json,css,md}'", 12 | "test": "./test.js", 13 | "semantic-release": "semantic-release" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/tlvince/make-coverage-badge.git" 18 | }, 19 | "keywords": [ 20 | "coverage", 21 | "badge", 22 | "istanbul" 23 | ], 24 | "author": "Tom Vincent (https://tlvince.com)", 25 | "engines": { 26 | "node": ">=6.11", 27 | "npm": ">=5.3" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/tlvince/make-coverage-badge/issues" 31 | }, 32 | "homepage": "https://github.com/tlvince/make-coverage-badge#readme", 33 | "dependencies": { 34 | "mri": "1.1.6" 35 | }, 36 | "devDependencies": { 37 | "eslint": "7.13.0", 38 | "eslint-config-prettier": "6.15.0", 39 | "eslint-plugin-prettier": "3.1.4", 40 | "husky": "4.3.0", 41 | "prettier": "2.1.2", 42 | "semantic-release": "17.2.2", 43 | "validate-commit-msg": "2.14.0" 44 | }, 45 | "files": [ 46 | "cli.js" 47 | ], 48 | "license": "MIT", 49 | "husky": { 50 | "hooks": { 51 | "commit-msg": "validate-commit-msg", 52 | "pre-commit": "eslint .", 53 | "pre-push": "./test.js" 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const assert = require('assert') 4 | const { exec } = require('child_process') 5 | const { promisify } = require('util') 6 | const { mkdir, rmdir, unlink, readFile, writeFile } = require('fs').promises 7 | 8 | const execP = promisify(exec) 9 | 10 | const setup = async () => { 11 | await mkdir('./coverage') 12 | const report = { 13 | total: { 14 | statements: { 15 | pct: 90, 16 | }, 17 | }, 18 | } 19 | const json = JSON.stringify(report) 20 | await writeFile('./coverage/coverage-summary.json', json) 21 | } 22 | 23 | const teardown = async () => { 24 | await unlink('./coverage/coverage-summary.json') 25 | await unlink('./coverage/badge.svg') 26 | await rmdir('./coverage') 27 | } 28 | 29 | const test = async () => { 30 | await execP('./cli.js') 31 | const buffer = await readFile('./coverage/badge.svg') 32 | const badge = buffer.toString() 33 | assert.ok(badge.includes('90%')) 34 | } 35 | 36 | setup() 37 | .then(test) 38 | .then(teardown) 39 | .catch((error) => { 40 | console.error(error) 41 | process.exit(1) 42 | }) 43 | --------------------------------------------------------------------------------