Files
shields/services/github/github-release.service.js
chris48s 5168675d0d move [githubtag] and [githubrelease] under /v, move variants to query params (#3610)
* move GH tag and release under /v, move variants to query params
    - move github /tag and /release under /v
    - both sort by date as default
    - specify sort=date/semver, include_prereleases as query params
    - use graphql api for tags

* pass string params from example defs to modal
2019-08-17 22:16:41 +01:00

199 lines
5.5 KiB
JavaScript

'use strict'
const Joi = require('@hapi/joi')
const { addv } = require('../text-formatters')
const { version: versionColor } = require('../color-formatters')
const { latest } = require('../version')
const { GithubAuthV3Service } = require('./github-auth-service')
const {
fetchLatestRelease,
releaseInfoSchema,
} = require('./github-common-fetch')
const { documentation, errorMessagesFor } = require('./github-helpers')
const { NotFound, redirector } = require('..')
const queryParamSchema = Joi.object({
include_prereleases: Joi.equal(''),
sort: Joi.string()
.valid('date', 'semver')
.default('date'),
}).required()
const releaseInfoArraySchema = Joi.array()
.items(releaseInfoSchema)
.required()
class GithubRelease extends GithubAuthV3Service {
static get category() {
return 'version'
}
static get route() {
return {
base: 'github/v/release',
pattern: ':user/:repo',
queryParamSchema,
}
}
static get examples() {
return [
{
title: 'GitHub release (latest by date)',
namedParams: { user: 'expressjs', repo: 'express' },
queryParams: {},
staticPreview: this.render({
version: 'v4.16.4',
sort: 'date',
isPrerelease: false,
}),
documentation,
},
{
title: 'GitHub release (latest by date including pre-releases)',
namedParams: { user: 'expressjs', repo: 'express' },
queryParams: { include_prereleases: null },
staticPreview: this.render({
version: 'v5.0.0-alpha.7',
sort: 'date',
isPrerelease: true,
}),
documentation,
},
{
title: 'GitHub release (latest SemVer)',
namedParams: { user: 'expressjs', repo: 'express' },
queryParams: { sort: 'semver' },
staticPreview: this.render({
version: 'v4.16.4',
sort: 'semver',
isPrerelease: false,
}),
documentation,
},
{
title: 'GitHub release (latest SemVer including pre-releases)',
namedParams: { user: 'expressjs', repo: 'express' },
queryParams: { sort: 'semver', include_prereleases: null },
staticPreview: this.render({
version: 'v5.0.0-alpha.7',
sort: 'semver',
isPrerelease: true,
}),
documentation,
},
]
}
static get defaultBadgeData() {
return {
label: 'release',
namedLogo: 'github',
}
}
static render({ version, sort, isPrerelease }) {
let color = 'blue'
color = sort === 'semver' ? versionColor(version) : color
color = isPrerelease ? 'orange' : color
return { message: addv(version), color }
}
async fetchReleases({ user, repo }) {
return this._requestJson({
url: `/repos/${user}/${repo}/releases`,
schema: releaseInfoArraySchema,
errorMessages: errorMessagesFor('repo not found'),
})
}
static 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]
}
return releases[0]
}
async handle({ user, repo }, queryParams) {
const sort = queryParams.sort
const includePrereleases = queryParams.include_prereleases !== undefined
let latestRelease
if (!includePrereleases && sort === 'date') {
latestRelease = await fetchLatestRelease(this, { user, repo })
return this.constructor.render({
version: latestRelease.tag_name,
sort,
isPrerelease: latestRelease.prerelease,
})
}
const releases = await this.fetchReleases({ user, repo })
if (releases.length === 0)
throw new NotFound({ prettyMessage: 'no releases found' })
latestRelease = this.constructor.getLatestRelease({
releases,
sort,
includePrereleases,
})
return this.constructor.render({
version: latestRelease.tag_name,
sort,
isPrerelease: latestRelease.prerelease,
})
}
}
const redirects = {
GithubReleaseRedirect: redirector({
name: 'GithubReleaseRedirect',
category: 'version',
route: {
base: 'github/release',
pattern: ':user/:repo',
},
transformPath: ({ user, repo }) => `/github/v/release/${user}/${repo}`,
dateAdded: new Date('2019-08-17'),
}),
GithubReleasePreRedirect: redirector({
category: 'version',
route: {
base: 'github/release-pre',
pattern: ':user/:repo',
},
transformPath: ({ user, repo }) => `/github/v/release/${user}/${repo}`,
transformQueryParams: params => ({ include_prereleases: null }),
dateAdded: new Date('2019-08-17'),
}),
GithubReleaseRedirectAll: redirector({
name: 'GithubReleaseRedirectAll',
category: 'version',
route: {
base: 'github/release',
pattern: ':user/:repo/all',
},
transformPath: ({ user, repo }) => `/github/v/release/${user}/${repo}`,
transformQueryParams: params => ({ include_prereleases: null }),
dateAdded: new Date('2019-08-17'),
}),
}
module.exports = {
GithubRelease,
...redirects,
}