forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathget-applicable-versions.js
More file actions
134 lines (114 loc) · 4.91 KB
/
get-applicable-versions.js
File metadata and controls
134 lines (114 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { reduce, sortBy } from 'lodash-es'
import { allVersions } from './all-versions.js'
import versionSatisfiesRange from './version-satisfies-range.js'
import { next, nextNext } from './enterprise-server-releases.js'
import { getDeepDataByLanguage } from './get-data.js'
let featureData = null
const allVersionKeys = Object.keys(allVersions)
// return an array of versions that an article's product versions encompasses
function getApplicableVersions(versionsObj, filepath, opts = {}) {
if (typeof versionsObj === 'undefined') {
throw new Error(`No \`versions\` frontmatter found in ${filepath}`)
}
// Catch an old frontmatter value that was used to indicate an article was available in all versions.
if (versionsObj === '*') {
throw new Error(
`${filepath} contains the invalid versions frontmatter: *. Please explicitly list out all the versions that apply to this article.`,
)
}
if (!featureData) {
featureData = getDeepDataByLanguage('features', 'en')
}
// Check for frontmatter that includes a feature name, like:
// fpt: '*'
// feature: 'foo'
// or multiple feature names, like:
// fpt: '*'
// feature: ['foo', 'bar']
// and add the versions affiliated with the feature (e.g., foo) to the frontmatter versions object:
// fpt: '*'
// ghes: '>=2.23'
// ghae: '*'
// where the feature is bringing the ghes and ghae versions into the mix.
const featureVersionsObj = reduce(
versionsObj,
(result, value, key) => {
if (key === 'feature') {
if (typeof value === 'string') {
Object.assign(result, { ...featureData[value].versions })
} else if (Array.isArray(value)) {
value.forEach((str) => {
Object.assign(result, { ...featureData[str].versions })
})
}
delete result[key]
}
return result
},
{},
)
// Get available versions for feature and standard versions.
const foundFeatureVersions = evaluateVersions(featureVersionsObj)
const foundStandardVersions = evaluateVersions(versionsObj)
// Combine them!
const applicableVersions = Array.from(new Set(foundStandardVersions.concat(foundFeatureVersions)))
if (!applicableVersions.length && !opts.doNotThrow) {
throw new Error(
`${filepath} is not available in any currently supported version. Make sure the \`versions\` property includes at least one supported version.`,
)
}
// Sort them by the order in lib/all-versions.
let sortedVersions = sortBy(applicableVersions, (v) => {
return allVersionKeys.indexOf(v)
})
// Strip out not-yet-supported versions if the option to include them is not provided.
if (!opts.includeNextVersion) {
sortedVersions = sortedVersions.filter(
(v) => !(v.endsWith(`@${next}`) || v.endsWith(`@${nextNext}`)),
)
}
return sortedVersions
}
function evaluateVersions(versionsObj) {
// get an array like: [ 'free-pro-team@latest', 'enterprise-server@2.21', 'enterprise-cloud@latest' ]
const versions = []
// where versions obj is something like:
// fpt: '*'
// ghes: '>=2.19'
// ghae: '*'
// ^ where each key corresponds to a plan's short name (defined in lib/all-versions.js)
Object.entries(versionsObj).forEach(([plan, planValue]) => {
// For each available plan (e.g., `ghes`), get the matching versions from allVersions.
// This will be an array of one or more version objects.
const matchingVersionObjs = Object.values(allVersions).filter(
(relevantVersionObj) =>
relevantVersionObj.plan === plan || relevantVersionObj.shortName === plan,
)
// For each matching version found above, compare it to the provided planValue.
// E.g., compare `enterprise-server@2.19` to `ghes: >=2.19`.
matchingVersionObjs.forEach((relevantVersionObj) => {
// If the version doesn't require any semantic comparison, we can assume it applies.
if (!(relevantVersionObj.hasNumberedReleases || relevantVersionObj.internalLatestRelease)) {
versions.push(relevantVersionObj.version)
return
}
// Special handling for a plan value that evaluates to the next GHES release number or a hardcoded `next`.
// Note these will not be included in the final array unless the `includeNextVersion` option is provided.
if (versionSatisfiesRange(next, planValue) || planValue === 'next') {
versions.push(`${relevantVersionObj.plan}@${next}`)
}
if (versionSatisfiesRange(nextNext, planValue)) {
versions.push(`${relevantVersionObj.plan}@${nextNext}`)
}
// Determine which release to use for semantic comparison.
const releaseToCompare = relevantVersionObj.hasNumberedReleases
? relevantVersionObj.currentRelease
: relevantVersionObj.internalLatestRelease
if (versionSatisfiesRange(releaseToCompare, planValue)) {
versions.push(relevantVersionObj.version)
}
})
})
return versions
}
export default getApplicableVersions