coverage-github-reporter
Advanced tools
Comparing version 1.0.0 to 1.1.0-alpha1
@@ -8,6 +8,22 @@ # Changelog | ||
## [1.0.0-alpha3] - 2017-12-19 | ||
## [1.0.0-alpha2] - 2017-12-19 | ||
## [1.0.0-alpha1] - 2017-12-19 | ||
## [1.1.0] - UNRELEASED | ||
### Changes | ||
- New comment format | ||
- Use markdown in comment where possible | ||
- Added link to project in comments | ||
- New Emojis to cover more scenarios | ||
### Fixes | ||
- No longer return 1 when file is empty/skipped | ||
- Fix file artifact links | ||
- Fix non-workflow build artifact discovery | ||
- Fix computation of artifact links with multiple folders | ||
### Misc | ||
- More code coverage/tests | ||
## [1.0.0] - 2017-12-19 | ||
- Initial release |
{ | ||
"name": "coverage-github-reporter", | ||
"version": "1.0.0", | ||
"version": "1.1.0-alpha1", | ||
"description": "Report Jest/Istanbul coverage statistics from CircleCI to GitHub", | ||
@@ -16,4 +16,10 @@ "main": "index.js", | ||
"test-dev": "cross-env NODE_ENV=test jest --watch --onlyChanged", | ||
"test-ci": "cross-env NODE_ENV=test TEST_REPORT_PATH=coverage jest --coverage --ci --silent" | ||
"test-ci": "cross-env NODE_ENV=test TEST_REPORT_PATH=coverage jest --coverage --ci --silent", | ||
"precommit": "lint-staged" | ||
}, | ||
"lint-staged": { | ||
"*.js": [ | ||
"standard" | ||
] | ||
}, | ||
"dependencies": { | ||
@@ -24,7 +30,10 @@ "args": "^3.0.8", | ||
"istanbul-lib-coverage": "^1.1.1", | ||
"istanbul-lib-report": "^1.1.2", | ||
"pad": "^2.0.3" | ||
}, | ||
"devDependencies": { | ||
"husky": "^0.14.3", | ||
"jest": "^22.0.0", | ||
"jest-junit-reporter": "^1.1.0", | ||
"lint-staged": "^6.0.0", | ||
"standard": "^10.0.3" | ||
@@ -31,0 +40,0 @@ }, |
# coverage-github-reporter | ||
[![CircleCI](https://circleci.com/gh/vivlabs/coverage-github-reporter.svg?style=svg)](https://circleci.com/gh/vivlabs/coverage-github-reporter) | ||
[![npm version](https://badge.fury.io/js/coverage-github-reporter.svg)](https://badge.fury.io/js/coverage-github-reporter) [![CircleCI](https://circleci.com/gh/vivlabs/coverage-github-reporter.svg?style=svg)](https://circleci.com/gh/vivlabs/coverage-github-reporter) | ||
@@ -9,2 +9,35 @@ Report Jest/Istanbul coverage statistics from CircleCI to GitHub | ||
### GitHub Auth Token | ||
A GitHub auth token is required to post a comment on github. I recommend creating a separate "bot" GitHub account with | ||
access to your repos. | ||
1. Navigate to [Personal access tokens](https://github.com/settings/tokens) on GitHub | ||
2. Click "Generate new token" and generate a new token (with **repo** access if your repo is private) | ||
3. Open the CircleCI project settings | ||
4. Navigate to Build Settings > Environment variables | ||
5. Add a new variable called `GH_AUTH_TOKEN` with the new token | ||
For subsequent projects: | ||
1. Open the CircleCI project settings | ||
2. Navigate to Build Settings > Environment variables | ||
3. Click "Import Variable(s)" | ||
4. Select a project that you've previous added `GH_AUTH_TOKEN` to | ||
5. Click the checkbox next to `GH_AUTH_TOKEN` and import | ||
### CircleCI Artifact API Token | ||
To access artifacts for private repos, a CircleCI API token is required. | ||
1. Open the CircleCI project settings | ||
2. Navigate to Permissions > API Permissions | ||
3. Click "Create Token" | ||
- Select "Build Artifacts" from scope dropdown | ||
- Name the token "artifacts" (or whatever you prefer) | ||
4. Navigate to Build Settings > Environment variables | ||
5. Add a new variable called `CIRCLE_CI_API_TOKEN` with the new token | ||
### Run Jest with Coverage reporting | ||
Add to your `package.json`: | ||
@@ -24,2 +57,4 @@ ```bash | ||
### CircleCI configuration | ||
Update your `.circleci/config.yml`: | ||
@@ -26,0 +61,0 @@ ```yml |
// circle-github-bot is pretty gnarly, ideally we'll swap it out | ||
const Bot = require('circle-github-bot') | ||
const { curl } = require('./curl') | ||
const { coverageJsonToReport } = require('./parse-coverage') | ||
const { coverageJsonToReport } = require('./coverage/parse') | ||
@@ -22,3 +22,3 @@ // Workaround for circle-github-bot failing if environment variables are not found | ||
// updated every time we add a workflow step. | ||
const WORKFLOW_BUILD_RETRIEVAL_LIMIT = 30 | ||
const BUILD_RETRIEVAL_LIMIT = 30 | ||
@@ -32,3 +32,3 @@ Bot.prototype.getPullRequest = function () { | ||
} | ||
Bot.prototype.latestBranchBuilds = function (branch, count = 1) { | ||
Bot.prototype.latestBranchBuilds = function (branch, count = 30) { | ||
return JSON.parse(curl(this.circleProjectUrl(`tree/${branch}?limit=${count}`))) | ||
@@ -64,10 +64,11 @@ } | ||
Bot.prototype.getPriorBuild = function (branch, coverageJsonFilename) { | ||
const workflowJob = process.env.CIRCLE_JOB | ||
// Get latest builds for branch | ||
const baseBranchBuilds = this.latestBranchBuilds(branch, workflowJob ? WORKFLOW_BUILD_RETRIEVAL_LIMIT : 1) | ||
const baseBranchBuilds = this.latestBranchBuilds(branch, BUILD_RETRIEVAL_LIMIT) | ||
if (baseBranchBuilds) { | ||
console.log(`Got ${baseBranchBuilds.length} build(s) for ${branch}`) | ||
for (const build of baseBranchBuilds) { | ||
const buildNum = build.build_num | ||
if (workflowJob) { | ||
if (!build.build_parameters || build.build_parameters.CIRCLE_JOB !== workflowJob) { | ||
if (process.env.CIRCLE_WORKFLOW_ID) { | ||
if (!build.build_parameters || build.build_parameters.CIRCLE_JOB !== process.env.CIRCLE_JOB) { | ||
console.log(`Build ${buildNum} doesn't match workflow job`) | ||
// Different job… | ||
@@ -78,23 +79,28 @@ continue | ||
if (String(buildNum) === process.env.CIRCLE_BUILD_NUM) { | ||
console.log(`Build ${buildNum} is self`) | ||
// Don't want to compare against self | ||
continue | ||
} | ||
console.log('Base branch build:', buildNum) | ||
console.log(`Comparing to build ${buildNum}`) | ||
// Get artifact | ||
const artifacts = this.artifacts(buildNum) | ||
if (artifacts) { | ||
console.log('Got artifacts') | ||
const artifact = artifacts.find(({ path }) => path === coverageJsonFilename) | ||
if (artifact) { | ||
const coverageJson = this.getJsonArtifact(artifact.url) | ||
if (coverageJson) { | ||
const base = process.env.CIRCLE_WORKING_DIRECTORY.replace(/~\//, process.env.HOME + '/') | ||
const priorCoverage = coverageJsonToReport(coverageJson, base) | ||
const priorBuild = buildNum | ||
console.log(`Loaded prior coverage from build ${priorBuild} artifacts (relative to ${base})`) | ||
return { priorCoverage, priorBuild } | ||
} | ||
} | ||
if (!artifacts) { | ||
console.error(`No artifacts found for build ${buildNum}`) | ||
break | ||
} | ||
break | ||
const artifact = artifacts.find(({ path }) => path === coverageJsonFilename) | ||
if (!artifact) { | ||
console.error(`Could not find "${coverageJsonFilename}" in artifacts`) | ||
console.log('Available artifacts:', artifacts.map(({ path }) => path)) | ||
break | ||
} | ||
const coverageJson = this.getJsonArtifact(artifact.url) | ||
if (!coverageJson) { | ||
throw new Error(`Could not load artifact from ${artifact.url}`) | ||
} | ||
const base = process.env.CIRCLE_WORKING_DIRECTORY.replace(/~\//, process.env.HOME + '/') | ||
const priorCoverage = coverageJsonToReport(coverageJson, base) | ||
const priorBuild = buildNum | ||
console.log(`Loaded prior coverage from build ${priorBuild} artifacts`) | ||
return { priorCoverage, priorBuild } | ||
} | ||
@@ -101,0 +107,0 @@ } |
@@ -25,3 +25,2 @@ #!/usr/bin/env node | ||
} | ||
console.log('Running with', params) | ||
const url = postComment(params) | ||
@@ -28,0 +27,0 @@ console.log('Posted to ', url) |
@@ -0,5 +1,33 @@ | ||
const { resolve } = require('path') | ||
const { Bot } = require('./bot') | ||
const { parseFile } = require('./parse-coverage') | ||
const { format } = require('./format-coverage') | ||
const { parseFile } = require('./coverage/parse') | ||
const { format } = require('./coverage/format') | ||
exports.formatComment = function ({ | ||
formatted: { | ||
status, | ||
changed, | ||
folders | ||
}, | ||
baseArtifactUrl, | ||
buildNum, | ||
buildUrl, | ||
priorBuildNum, | ||
priorBuildUrl, | ||
branch | ||
}) { | ||
return ` | ||
**[Code Coverage](${baseArtifactUrl}/index.html): ${status}** | ||
${changed} | ||
<details> | ||
<summary><strong>🗂 Folder Coverage</strong></summary> | ||
${folders} | ||
</details> | ||
<p> | ||
From **Circle CI [build ${buildNum}](${buildUrl})** ${priorBuildNum | ||
? `compared to [build ${priorBuildNum}](${priorBuildUrl}) (from \`${branch}\` branch)` | ||
: ''} – 🤖[coverage-github-reporter](https://github.com/vivlabs/coverage-github-reporter)` | ||
} | ||
exports.postComment = function postComment ({ | ||
@@ -13,3 +41,3 @@ coverageJsonFilename = 'coverage/coverage-final.json', | ||
const coverage = parseFile(root) | ||
const coverage = parseFile(root, resolve(root, coverageJsonFilename)) | ||
@@ -23,13 +51,15 @@ const branch = bot.getBaseBranch(defaultBaseBranch) | ||
const result = JSON.parse(bot.comment(` | ||
<a> | ||
<strong><a href="${bot.artifactUrl(`/${coverageHtmlRoot}/index.html`)}">Code Coverage</a></strong> | ||
from Circle CI <a href="${process.env.CIRCLE_BUILD_URL}">build ${process.env.CIRCLE_BUILD_NUM}</a> | ||
${priorBuild | ||
? `(compared to <a href="${process.env.CIRCLE_BUILD_URL.replace(/\/\d+$/, `/${priorBuild}`)}">build ${priorBuild}</a> of <code>${branch}</code> branch)` | ||
: ''} | ||
</p> | ||
${format(coverage, priorCoverage, bot.artifactUrl(`/${coverageHtmlRoot}`))} | ||
`)) | ||
const baseArtifactUrl = bot.artifactUrl(`/${coverageHtmlRoot}`) | ||
const text = exports.formatComment({ | ||
formatted: format(coverage, priorCoverage, baseArtifactUrl), | ||
baseArtifactUrl, | ||
buildNum: process.env.CIRCLE_BUILD_NUM, | ||
buildUrl: process.env.CIRCLE_BUILD_URL, | ||
priorBuildNum: priorBuild, | ||
priorBuildUrl: process.env.CIRCLE_BUILD_URL.replace(/\/\d+$/, `/${priorBuild}`), | ||
branch | ||
}) | ||
const result = JSON.parse(bot.comment(text)) | ||
return result && result.html_url | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
323563
29
1600
96
6
5
2
22
2
+ Addedistanbul-lib-report@^1.1.2
+ Addedhas-flag@1.0.0(transitive)
+ Addedistanbul-lib-report@1.1.5(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedpath-parse@1.0.7(transitive)
+ Addedsupports-color@3.2.3(transitive)