Files
shields/services/github/github-common-release.js
Anton Gilgur 7f7ecfd111 add sort and prerelease query params to [GitHubCommitsSince] (also refactors [GitHubRelease], [GitHubTag]) (#4395)
* 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>
2020-02-13 22:18:29 -06:00

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
}