Files
shields/services/codecov/codecov.service.js
chris48s 8621fe42d7 Upgrade Joi (#3505)
* upgrade joi
* find & replace ALL THE THINGS
* update related deps
2019-06-02 21:59:55 +01:00

140 lines
3.6 KiB
JavaScript

'use strict'
const Joi = require('@hapi/joi')
const { coveragePercentage } = require('../color-formatters')
const { BaseJsonService } = require('..')
// https://docs.codecov.io/reference#totals
// A new repository that's been added but never had any coverage reports
// uploaded will not have a `commit` object in the response and sometimes
// the `totals` object can also be missing for the latest commit.
// Accordingly the schema is a bit relaxed to support those scenarios
// and then they are handled in the transform and render functions.
const schema = Joi.object({
commit: Joi.object({
totals: Joi.object({
c: Joi.number().required(),
}),
}),
}).required()
const queryParamSchema = Joi.object({
token: Joi.string(),
}).required()
const documentation = `
<p>
You may specify a Codecov token to get coverage for a private repository.
</p>
<p>
See the <a href="https://docs.codecov.io/reference#authorization">Codecov Docs</a>
for more information about creating a token.
</p>
`
module.exports = class Codecov extends BaseJsonService {
static get category() {
return 'coverage'
}
static get route() {
return {
base: 'codecov/c',
// https://docs.codecov.io/docs#section-common-questions
// Github, BitBucket, and GitLab are the only supported options (long or short form)
pattern:
':vcsName(github|gh|bitbucket|bb|gl|gitlab)/:user/:repo/:branch*',
queryParamSchema,
}
}
static get examples() {
return [
{
title: 'Codecov',
pattern: ':vcsName(github|gh|bitbucket|bb|gl|gitlab)/:user/:repo',
namedParams: {
vcsName: 'github',
user: 'codecov',
repo: 'example-python',
},
queryParams: {
token: 'abc123def456',
},
staticPreview: this.render({ coverage: 90 }),
documentation,
},
{
title: 'Codecov branch',
pattern:
':vcsName(github|gh|bitbucket|bb|gl|gitlab)/:user/:repo/:branch',
namedParams: {
vcsName: 'github',
user: 'codecov',
repo: 'example-python',
branch: 'master',
},
queryParams: {
token: 'abc123def456',
},
staticPreview: this.render({ coverage: 90 }),
documentation,
},
]
}
static get defaultBadgeData() {
return { label: 'coverage' }
}
static render({ coverage }) {
if (coverage === 'unknown') {
return {
message: coverage,
color: 'lightgrey',
}
}
return {
message: `${coverage.toFixed(0)}%`,
color: coveragePercentage(coverage),
}
}
async fetch({ vcsName, user, repo, branch, token }) {
// Codecov Docs: https://docs.codecov.io/reference#section-get-a-single-repository
let url = `https://codecov.io/api/${vcsName}/${user}/${repo}`
if (branch) {
url += `/branches/${branch}`
}
const options = {}
if (token) {
options.headers = {
Authorization: `token ${token}`,
}
}
return this._requestJson({
schema,
options,
url,
errorMessages: {
401: 'not authorized to access repository',
404: 'repository not found',
},
})
}
transform({ json }) {
if (!json.commit || !json.commit.totals) {
return { coverage: 'unknown' }
}
return { coverage: +json.commit.totals.c }
}
async handle({ vcsName, user, repo, branch }, { token }) {
const json = await this.fetch({ vcsName, user, repo, branch, token })
const { coverage } = this.transform({ json })
return this.constructor.render({ coverage })
}
}