* move getLatestRelease logic from [GitHubRelease] to common-fetch - so that the sorting and prerelease logic can be used for other services too, like commits-since * add sort and prerelease query params to [GitHubCommitsSince] - they only work when using the 'latest' version of course - uses same logic as release service * reuse queryParamSchema from common-fetch for [GitHubTag] - as they were the exact same schema * refactor [GitHubCommitsSince] tests to use withRegex - and the same variable everywhere * split out release/tag logic from common-fetch to common-release (affects [GitHubCommitsSince], [GitHubRelease], [GitHubTag]) - this logic is only used for code related to releases & tags, so made sense as a split point Co-authored-by: Caleb Cartwright <calebcartwright@users.noreply.github.com>
104 lines
2.8 KiB
JavaScript
104 lines
2.8 KiB
JavaScript
'use strict'
|
|
|
|
const Joi = require('@hapi/joi')
|
|
const { latest } = require('../version')
|
|
const { errorMessagesFor } = require('./github-helpers')
|
|
const { NotFound } = require('..')
|
|
|
|
const releaseInfoSchema = Joi.object({
|
|
tag_name: Joi.string().required(),
|
|
prerelease: Joi.boolean().required(),
|
|
}).required()
|
|
|
|
// Fetch the 'latest' release as defined by the GitHub API
|
|
async function fetchLatestGitHubRelease(serviceInstance, { user, repo }) {
|
|
const commonAttrs = {
|
|
errorMessages: errorMessagesFor('no releases or repo not found'),
|
|
}
|
|
const releaseInfo = await serviceInstance._requestJson({
|
|
schema: releaseInfoSchema,
|
|
url: `/repos/${user}/${repo}/releases/latest`,
|
|
...commonAttrs,
|
|
})
|
|
return releaseInfo
|
|
}
|
|
|
|
const releaseInfoArraySchema = Joi.alternatives().try(
|
|
Joi.array().items(releaseInfoSchema),
|
|
Joi.array().length(0)
|
|
)
|
|
|
|
async function fetchReleases(serviceInstance, { user, repo }) {
|
|
const commonAttrs = {
|
|
errorMessages: errorMessagesFor('repo not found'),
|
|
}
|
|
const releases = await serviceInstance._requestJson({
|
|
url: `/repos/${user}/${repo}/releases`,
|
|
schema: releaseInfoArraySchema,
|
|
...commonAttrs,
|
|
})
|
|
return releases
|
|
}
|
|
|
|
function getLatestRelease({ releases, sort, includePrereleases }) {
|
|
if (sort === 'semver') {
|
|
const latestRelease = latest(
|
|
releases.map(release => release.tag_name),
|
|
{
|
|
pre: includePrereleases,
|
|
}
|
|
)
|
|
const kvpairs = Object.assign(
|
|
...releases.map(release => ({ [release.tag_name]: release.prerelease }))
|
|
)
|
|
return { tag_name: latestRelease, prerelease: kvpairs[latestRelease] }
|
|
}
|
|
|
|
if (!includePrereleases) {
|
|
const stableReleases = releases.filter(release => !release.prerelease)
|
|
if (stableReleases.length > 0) {
|
|
return stableReleases[0]
|
|
}
|
|
}
|
|
|
|
return releases[0]
|
|
}
|
|
|
|
const queryParamSchema = Joi.object({
|
|
include_prereleases: Joi.equal(''),
|
|
sort: Joi.string()
|
|
.valid('date', 'semver')
|
|
.default('date'),
|
|
}).required()
|
|
|
|
// Fetch the latest release as defined by query params
|
|
async function fetchLatestRelease(
|
|
serviceInstance,
|
|
{ user, repo },
|
|
queryParams
|
|
) {
|
|
const sort = queryParams.sort
|
|
const includePrereleases = queryParams.include_prereleases !== undefined
|
|
|
|
if (!includePrereleases && sort === 'date') {
|
|
const releaseInfo = await fetchLatestGitHubRelease(serviceInstance, {
|
|
user,
|
|
repo,
|
|
})
|
|
return releaseInfo
|
|
}
|
|
|
|
const releases = await fetchReleases(serviceInstance, { user, repo })
|
|
if (releases.length === 0) {
|
|
throw new NotFound({ prettyMessage: 'no releases' })
|
|
}
|
|
const latestRelease = getLatestRelease({ releases, sort, includePrereleases })
|
|
return latestRelease
|
|
}
|
|
|
|
module.exports = {
|
|
fetchLatestRelease,
|
|
queryParamSchema,
|
|
_getLatestRelease: getLatestRelease, // currently only used for tests
|
|
}
|