1
0
mirror of https://github.com/badges/shields.git synced 2025-04-18 19:44:04 +03:00

Add puppetforge quality score badges (#10201)

The Puppet Forge run static analysis on modules and provide a score
through a (currently) internal API.

Waybe it will be in the public API in the future, but when this happen
adjusting the URL should be easy.  In the meantime, use this internal
API.
This commit is contained in:
Romain Tartière 2024-06-04 08:13:06 -10:00 committed by GitHub
parent 81585acd6b
commit d23f26b8d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 107 additions and 1 deletions

View File

@ -24,6 +24,27 @@ const modulesSchema = Joi.object({
),
}).required()
const modulesValidationSchema = Joi.array()
.items(
Joi.alternatives().try(
Joi.object({
name: Joi.string().valid('total').required(),
score: nonNegativeInteger,
}).required(),
Joi.object({}).required(),
),
)
.custom((value, helpers) => {
// Custom validation to check for exactly one type1 object
const totalCount = value.filter(item => item.name === 'total').length
if (totalCount !== 1) {
return helpers.message(
'Array must contain exactly one object of type "total"',
)
}
return value
})
class BasePuppetForgeUsersService extends BaseJsonService {
async fetch({ user }) {
return this._requestJson({
@ -42,4 +63,17 @@ class BasePuppetForgeModulesService extends BaseJsonService {
}
}
export { BasePuppetForgeModulesService, BasePuppetForgeUsersService }
class BasePuppetForgeModulesValidationService extends BaseJsonService {
async fetch({ user, moduleName }) {
return this._requestJson({
schema: modulesValidationSchema,
url: `https://forgeapi.puppetlabs.com/private/validations/${user}-${moduleName}`,
})
}
}
export {
BasePuppetForgeModulesService,
BasePuppetForgeUsersService,
BasePuppetForgeModulesValidationService,
}

View File

@ -0,0 +1,45 @@
import { coveragePercentage as coveragePercentageColor } from '../color-formatters.js'
import { pathParams } from '../index.js'
import { BasePuppetForgeModulesValidationService } from './puppetforge-base.js'
export default class PuppetforgeModuleQualityScoreService extends BasePuppetForgeModulesValidationService {
static category = 'rating'
static route = {
base: 'puppetforge/qualityscore',
pattern: ':user/:moduleName',
}
static openApi = {
'/puppetforge/qualityscore/{user}/{moduleName}': {
get: {
summary: 'Puppet Forge quality score',
parameters: pathParams(
{
name: 'user',
example: 'camptocamp',
},
{
name: 'moduleName',
example: 'openssl',
},
),
},
},
}
static defaultBadgeData = { label: 'quality score' }
static render({ score }) {
return {
message: `${score}%`,
color: coveragePercentageColor(score),
}
}
async handle({ user, moduleName }) {
const data = await this.fetch({ user, moduleName })
const qualityScore = data.find(el => el.name === 'total').score
return this.constructor.render({ score: qualityScore })
}
}

View File

@ -0,0 +1,27 @@
import { isPercentage } from '../test-validators.js'
import { createServiceTester } from '../tester.js'
export const t = await createServiceTester()
t.create('module quality-score').get('/camptocamp/openssl.json').expectBadge({
label: 'quality score',
message: isPercentage,
})
t.create('module quality score (no ratings)')
.get('/camptocamp/openssl.json')
.intercept(nock =>
nock('https://forgeapi.puppetlabs.com/private/validations')
.get('/camptocamp-openssl')
.reply(200, []),
)
.expectBadge({
label: 'quality score',
message: 'invalid response data',
})
t.create('module quality score (not found)')
.get('/notarealuser/notarealpackage.json')
.expectBadge({
label: 'quality score',
message: 'not found',
})