[Scoop] Add scoop badge service (#5081)

* [Scoop] Add scoop badge service

* Rename scoop.service.js into scoop-version.service.js

Also rename scoop.tester.js into scoop-version.tester.js

* Cache buckets file

* Fix test

* Improve regex to handle trailing slash

* Switch to static fields

Co-authored-by: PyvesB <PyvesDev@gmail.com>
This commit is contained in:
Cédric Luthi
2020-09-06 19:01:37 +02:00
committed by GitHub
parent 56a303df87
commit 6e88aee7c8
2 changed files with 137 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
'use strict'
const Joi = require('@hapi/joi')
const { NotFound } = require('..')
const {
ConditionalGithubAuthV3Service,
} = require('../github/github-auth-service')
const { fetchJsonFromRepo } = require('../github/github-common-fetch')
const { renderVersionBadge } = require('../version')
const gitHubRepoRegExp = new RegExp(
'https://github.com/(?<user>.*?)/(?<repo>.*?)(/|$)'
)
const bucketsSchema = Joi.object()
.pattern(/.+/, Joi.string().pattern(gitHubRepoRegExp).required())
.required()
const scoopSchema = Joi.object({
version: Joi.string().required(),
}).required()
const queryParamSchema = Joi.object({
bucket: Joi.string(),
})
module.exports = class ScoopVersion extends ConditionalGithubAuthV3Service {
// The buckets file (https://github.com/lukesampson/scoop/blob/master/buckets.json) changes very rarely.
// Cache it for the lifetime of the current Node.js process.
buckets = null
static category = 'version'
static route = {
base: 'scoop/v',
pattern: ':app',
queryParamSchema,
}
static examples = [
{
title: 'Scoop Version',
namedParams: { app: 'ngrok' },
staticPreview: this.render({ version: '2.3.35' }),
},
{
title: 'Scoop Version (extras bucket)',
namedParams: { app: 'dnspy' },
queryParams: { bucket: 'extras' },
staticPreview: this.render({ version: '6.1.4' }),
},
]
static defaultBadgeData = { label: 'scoop' }
static render({ version }) {
return renderVersionBadge({ version })
}
async handle({ app }, queryParams) {
if (!this.buckets) {
this.buckets = await fetchJsonFromRepo(this, {
schema: bucketsSchema,
user: 'lukesampson',
repo: 'scoop',
branch: 'master',
filename: 'buckets.json',
})
}
const bucket = queryParams.bucket || 'main'
const bucketUrl = this.buckets[bucket]
if (!bucketUrl) {
throw new NotFound({ prettyMessage: `bucket "${bucket}" not found` })
}
const {
groups: { user, repo },
} = gitHubRepoRegExp.exec(bucketUrl)
try {
const { version } = await fetchJsonFromRepo(this, {
schema: scoopSchema,
user,
repo,
branch: 'master',
filename: `bucket/${app}.json`,
})
return this.constructor.render({ version })
} catch (error) {
if (error instanceof NotFound) {
throw new NotFound({
prettyMessage: `${app} not found in bucket "${bucket}"`,
})
}
throw error
}
}
}

View File

@@ -0,0 +1,44 @@
'use strict'
const { ServiceTester } = require('../tester')
const { isVPlusDottedVersionNClauses } = require('../test-validators')
const t = (module.exports = new ServiceTester({
id: 'scoop',
title: 'Scoop',
}))
// version
t.create('version (valid)').get('/v/apache.json').expectBadge({
label: 'scoop',
message: isVPlusDottedVersionNClauses,
})
t.create('version (not found)').get('/v/not-a-real-app.json').expectBadge({
label: 'scoop',
message: 'not-a-real-app not found in bucket "main"',
})
// version (custom bucket)
t.create('version (valid custom bucket)')
.get('/v/dnspy.json?bucket=extras')
.expectBadge({
label: 'scoop',
message: isVPlusDottedVersionNClauses,
})
t.create('version (not found in custom bucket)')
.get('/v/not-a-real-app.json?bucket=extras')
.expectBadge({
label: 'scoop',
message: 'not-a-real-app not found in bucket "extras"',
})
t.create('version (wrong bucket)')
.get('/v/not-a-real-app.json?bucket=not-a-real-bucket')
.expectBadge({
label: 'scoop',
message: 'bucket "not-a-real-bucket" not found',
})