Allow user to filter github tags and releases (#9193)

Co-authored-by: repo-ranger[bot] <39074581+repo-ranger[bot]@users.noreply.github.com>
This commit is contained in:
chris48s
2023-07-03 21:27:31 +01:00
committed by GitHub
parent e7197f6db4
commit 1543d0f363
8 changed files with 222 additions and 22 deletions

View File

@@ -1,4 +1,5 @@
import Joi from 'joi'
import { matcher } from 'matcher'
import { nonNegativeInteger } from '../validators.js'
import { latest } from '../version.js'
import { NotFound } from '../index.js'
@@ -68,8 +69,39 @@ function getLatestRelease({ releases, sort, includePrereleases }) {
const queryParamSchema = Joi.object({
include_prereleases: Joi.equal(''),
sort: Joi.string().valid('date', 'semver').default('date'),
filter: Joi.string(),
}).required()
const filterDocs = `<div>
<p>
The <code>filter</code> param can be used to apply a filter to the
project's tag or release names before selecting the latest from the list.
Two constructs are available: <code>*</code> is a wildcard matching zero
or more characters, and if the pattern starts with a <code>!</code>,
the whole pattern is negated.
</p>
</div>`
function applyFilter({ releases, filter, displayName }) {
if (!filter) {
return releases
}
if (displayName === 'tag') {
const filteredTagNames = matcher(
releases.map(release => release.tag_name),
filter
)
return releases.filter(release =>
filteredTagNames.includes(release.tag_name)
)
}
const filteredReleaseNames = matcher(
releases.map(release => release.name),
filter
)
return releases.filter(release => filteredReleaseNames.includes(release.name))
}
// Fetch the latest release as defined by query params
async function fetchLatestRelease(
serviceInstance,
@@ -78,8 +110,10 @@ async function fetchLatestRelease(
) {
const sort = queryParams.sort
const includePrereleases = queryParams.include_prereleases !== undefined
const filter = queryParams.filter
const displayName = queryParams.display_name
if (!includePrereleases && sort === 'date') {
if (!includePrereleases && sort === 'date' && !filter) {
const releaseInfo = await fetchLatestGitHubRelease(serviceInstance, {
user,
repo,
@@ -87,13 +121,23 @@ async function fetchLatestRelease(
return releaseInfo
}
const releases = await fetchReleases(serviceInstance, { user, repo })
const releases = applyFilter({
releases: await fetchReleases(serviceInstance, { user, repo }),
filter,
displayName,
})
if (releases.length === 0) {
throw new NotFound({ prettyMessage: 'no releases' })
const prettyMessage = filter
? 'no matching releases found'
: 'no releases found'
throw new NotFound({ prettyMessage })
}
const latestRelease = getLatestRelease({ releases, sort, includePrereleases })
return latestRelease
}
export { fetchLatestRelease, queryParamSchema }
export const _getLatestRelease = getLatestRelease // currently only used for tests
export { fetchLatestRelease, filterDocs, queryParamSchema }
// currently only used for tests
export const _getLatestRelease = getLatestRelease
export const _applyFilter = applyFilter