1
0
mirror of https://github.com/badges/shields.git synced 2025-11-03 15:13:18 +03:00
Files
shields/services/gitlab/gitlab-pipeline-coverage.service.js
chris48s 14892e3943 Implement a pattern for dealing with upstream APIs which are slow on the first hit; affects [endpoint] (#9233)
* allow serviceData to override cacheSeconds with a longer value

* prevent [endpoint] json cacheSeconds property exceeding service default

* allow ShieldsRuntimeError to specify a cacheSeconds property

By default error responses use the cacheLength of
the service class throwing the error.

This allows error to tell the handling layer the maxAge
that should be set on the error badge response.

* add customExceptions param

This

1. allows us to specify custom properties to pass to the exception
   constructor if we throw any of the standard got errors
   e.g: `ETIMEDOUT`, `ECONNRESET`, etc
2. uses a custom `cacheSeconds` property (if set on the exception)
   to set the response maxAge

* customExceptions --> systemErrors

* errorMessages --> httpErrors
2023-06-13 21:08:43 +01:00

131 lines
4.0 KiB
JavaScript

import Joi from 'joi'
import { coveragePercentage } from '../color-formatters.js'
import { optionalUrl } from '../validators.js'
import { BaseSvgScrapingService, NotFound } from '../index.js'
import { documentation, httpErrorsFor } from './gitlab-helper.js'
const schema = Joi.object({
message: Joi.string()
.regex(/^([0-9]+\.[0-9]+%)|unknown$/)
.required(),
}).required()
const queryParamSchema = Joi.object({
gitlab_url: optionalUrl,
job_name: Joi.string(),
branch: Joi.string(),
}).required()
const moreDocs = `
<p>
Important: If your project is publicly visible, but the badge is like this:
<img src="https://img.shields.io/badge/coverage-not&nbsp;set&nbsp;up-red" alt="coverage not set up"/>
</p>
<p>
Check if your pipelines are publicly visible as well.<br />
Navigate to your project settings on GitLab and choose General Pipelines under CI/CD.<br />
Then tick the setting Public pipelines.
</p>
<p>
Now your settings should look like this:
</p>
<img src="https://user-images.githubusercontent.com/12065866/67156911-e225a180-f324-11e9-93ad-10aafbb3e69e.png" alt="Setting Public pipelines set"/>
<p>
Also make sure you have set up code covrage parsing as described <a href="https://docs.gitlab.com/ee/ci/pipelines/settings.html#test-coverage-parsing">here</a>
</p>
<p>
Your badge should be working fine now.
</p>
`
export default class GitlabPipelineCoverage extends BaseSvgScrapingService {
static category = 'coverage'
static route = {
base: 'gitlab/pipeline-coverage',
pattern: ':project+',
queryParamSchema,
}
static examples = [
{
title: 'Gitlab code coverage',
namedParams: { project: 'gitlab-org/gitlab-runner' },
queryParams: { branch: 'master' },
staticPreview: this.render({ coverage: 67 }),
documentation: documentation + moreDocs,
},
{
title: 'Gitlab code coverage (specific job)',
namedParams: { project: 'gitlab-org/gitlab-runner' },
queryParams: { job_name: 'test coverage report', branch: 'master' },
staticPreview: this.render({ coverage: 96 }),
documentation: documentation + moreDocs,
},
{
title: 'Gitlab code coverage (self-managed)',
namedParams: { project: 'GNOME/at-spi2-core' },
queryParams: { gitlab_url: 'https://gitlab.gnome.org', branch: 'master' },
staticPreview: this.render({ coverage: 93 }),
documentation: documentation + moreDocs,
},
{
title: 'Gitlab code coverage (self-managed, specific job)',
namedParams: { project: 'GNOME/libhandy' },
queryParams: {
gitlab_url: 'https://gitlab.gnome.org',
job_name: 'unit-test',
branch: 'master',
},
staticPreview: this.render({ coverage: 93 }),
documentation: documentation + moreDocs,
},
]
static defaultBadgeData = { label: 'coverage' }
static render({ coverage }) {
return {
message: `${coverage.toFixed(0)}%`,
color: coveragePercentage(coverage),
}
}
async fetch({ project, baseUrl = 'https://gitlab.com', jobName, branch }) {
// Since the URL doesn't return a usable value when an invalid job name is specified,
// it is recommended to not use the query param at all if not required
jobName = jobName ? `?job=${jobName}` : ''
const url = `${baseUrl}/${decodeURIComponent(
project
)}/badges/${branch}/coverage.svg${jobName}`
const httpErrors = httpErrorsFor('project not found')
return this._requestSvg({
schema,
url,
httpErrors,
})
}
static transform({ coverage }) {
if (coverage === 'unknown') {
throw new NotFound({ prettyMessage: 'not set up' })
}
return Number(coverage.slice(0, -1))
}
async handle(
{ project },
{ gitlab_url: baseUrl, job_name: jobName, branch }
) {
const { message: coverage } = await this.fetch({
project,
branch,
baseUrl,
jobName,
})
return this.constructor.render({
coverage: this.constructor.transform({ coverage }),
})
}
}