Support [Feedz] response with multiple pages without items (#7476)

* Support Feedz response with multiple pages without items

* Parallelize fetches from Feedz when getting multiple pages

* Simplify schema management

* Retrun early if we don't need to fetch any more pages

Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
This commit is contained in:
Jakub Fijałkowski
2022-01-16 19:55:57 +01:00
committed by GitHub
parent d418794cca
commit d5c38c92be
2 changed files with 42 additions and 11 deletions

View File

@@ -7,22 +7,23 @@ import {
selectVersion,
} from '../nuget/nuget-helpers.js'
const schema = Joi.object({
const singlePageSchema = Joi.object({
'@id': Joi.string().required(),
items: Joi.array()
.items(
Joi.object({
items: Joi.array().items(
Joi.object({
catalogEntry: Joi.object({
version: Joi.string().required(),
}).required(),
})
),
}).required()
catalogEntry: Joi.object({
version: Joi.string().required(),
}).required(),
})
)
.default([]),
}).required()
const packageSchema = Joi.object({
items: Joi.array().items(singlePageSchema).default([]),
}).required()
class FeedzVersionService extends BaseJsonService {
static category = 'version'
@@ -72,7 +73,7 @@ class FeedzVersionService extends BaseJsonService {
'RegistrationsBaseUrl'
)
return await this._requestJson({
schema,
schema: packageSchema,
url: `${registrationsBaseUrl}${packageName}/index.json`,
errorMessages: {
404: 'repository or package not found',
@@ -80,6 +81,25 @@ class FeedzVersionService extends BaseJsonService {
})
}
async fetchItems({ json }) {
if (json.items.length === 0 || json.items.some(i => i.catalogEntry)) {
return json
} else {
const items = await Promise.all(
json.items.map(i =>
this._requestJson({
schema: singlePageSchema,
url: i['@id'],
errorMessages: {
404: 'repository or package not found',
},
})
)
)
return { items }
}
}
transform({ json, includePrereleases }) {
const versions = json.items.flatMap(tl =>
tl.items.map(i => stripBuildMetadata(i.catalogEntry.version))
@@ -95,7 +115,8 @@ class FeedzVersionService extends BaseJsonService {
const includePrereleases = which === 'vpre'
const baseUrl = this.apiUrl({ organization, repository })
const json = await this.fetch({ baseUrl, packageName })
const version = this.transform({ json, includePrereleases })
const fetchedJson = await this.fetchItems({ json })
const version = this.transform({ json: fetchedJson, includePrereleases })
return this.constructor.render({
version,
feed: FeedzVersionService.defaultBadgeData.label,

View File

@@ -11,6 +11,8 @@ export const t = new ServiceTester({
// - Shields.TestPackage: 0.0.1, 0.1.0-pre, 1.0.0
// - Shields.TestPreOnly: 0.1.0-pre
// - Shields.MultiPage: 0.1.0-0.1.100 plus 1.0.0 but the response has multiple top-level `items`
// - Shields.MultiPageNoItems: 0.0.0-0.0.256 plus 1.0.0 but the response has multiple top-level
// `items` without `catalogEntries`
// The source code of these packages is here: https://github.com/jakubfijalkowski/shields-test-packages
// version
@@ -46,6 +48,14 @@ t.create('multi-page')
color: 'blue',
})
t.create('multi-page-no-items')
.get('/feedz/v/shieldstests/public/Shields.MultiPageNoItems.json')
.expectBadge({
label: 'feedz',
message: 'v1.0.0',
color: 'blue',
})
t.create('repository (not found)')
.get('/feedz/v/foo/bar/not-a-real-package.json')
.expectBadge({ label: 'feedz', message: 'repository or package not found' })