1
0
mirror of synced 2025-12-20 18:36:31 -05:00
Files
docs/script/enterprise-server-releases/ghes-to-ghae-versioning.js
Kevin Heis b29e37318a Remove import x statements (#20594)
* Clear out most import x

* Update rimraf use

* Move up readme blocks in scripts
2021-07-29 20:28:30 +00:00

180 lines
5.6 KiB
JavaScript
Executable File

#!/usr/bin/env node
// [start-readme]
//
// Run this script to add versions frontmatter and Liquid conditionals for
// GitHub AE, based on anything currently versioned for the specified release
// of Enterprise Server. This script should be run as part of the Enterprise
// Server release process.
//
// [end-readme]
import fs from 'fs'
import path from 'path'
import walk from 'walk-sync'
import program from 'commander'
import { escapeRegExp } from 'lodash-es'
import frontmatter from '../../lib/read-frontmatter.js'
import versionSatisfiesRange from '../../lib/version-satisfies-range.js'
import { getLiquidConditionals } from '../helpers/get-liquid-conditionals.js'
const contentPath = path.join(process.cwd(), 'content')
const dataPath = path.join(process.cwd(), 'data')
const translationsPath = path.join(process.cwd(), 'translations')
program
.description(
'Add versions frontmatter and Liquid conditionals for GitHub AE based on a given Enterprise Server release. Runs on all content by default.'
)
.option(
'-r, --ghes-release <RELEASE>',
'The Enterprise Server release to base AE versioning on. Example: 2.23'
)
.option(
'-p, --products [OPTIONAL PRODUCT_IDS...]',
'Optional list of space-separated product IDs. Example: admin github developers'
)
.option('-t, --translations', 'Run the script on content and data in translations too.')
.parse(process.argv)
const { ghesRelease, products, translations } = program.opts()
if (!ghesRelease) {
console.error('Must provide an Enterprise Server release number!')
process.exit(1)
}
console.log(`✅ Adding AE versioning based on GHES ${ghesRelease} versioning`)
if (products) {
console.log(`✅ Running on the following products: ${products}`)
} else {
console.log('✅ Running on all products')
}
if (translations) {
console.log('✅ Running on both English and translated content and data\n')
} else {
console.log('✅ Running on English content and data\n')
}
// Match: ghes <operator> <release>
// Example: ghes > 2.21
const ghesRegex = new RegExp(`ghes (<|>|=|!=) ${ghesRelease}`)
console.log('Working...\n')
const englishContentFiles = walkContent(contentPath)
const englishDataFiles = walkData(dataPath)
function walkContent(dirPath) {
const productArray = products || ['']
return productArray
.map((product) => {
dirPath = path.join(contentPath, product)
return walk(dirPath, { includeBasePath: true, directories: false })
.filter((file) => file.includes('/content/'))
.filter((file) => file.endsWith('.md'))
.filter((file) => !file.endsWith('README.md'))
})
.flat()
}
function walkData(dirPath) {
return walk(dirPath, { includeBasePath: true, directories: false })
.filter((file) => file.includes('/data/reusables') || file.includes('/data/variables'))
.filter((file) => !file.endsWith('README.md'))
}
let allContentFiles, allDataFiles
if (translations) {
const translatedContentFiles = walkContent(translationsPath)
const translatedDataFiles = walkData(translationsPath)
allContentFiles = englishContentFiles.concat(translatedContentFiles)
allDataFiles = englishDataFiles.concat(translatedDataFiles)
} else {
allContentFiles = englishContentFiles
allDataFiles = englishDataFiles
}
// Update the data files
allDataFiles.forEach((file) => {
const dataContent = fs.readFileSync(file, 'utf8')
const conditionalsToUpdate = getConditionalsToUpdate(dataContent)
if (!conditionalsToUpdate.length) return
// Update Liquid in data files
const newDataContent = updateLiquid(conditionalsToUpdate, dataContent)
fs.writeFileSync(file, newDataContent)
})
// Update the content files
allContentFiles.forEach((file) => {
const { data, content } = frontmatter(fs.readFileSync(file, 'utf8'))
// Return early if the current page frontmatter does not apply to either GHAE or the given GHES release
if (
!(
data.versions['github-ae'] ||
versionSatisfiesRange(ghesRelease, data.versions['enterprise-server'])
)
)
return
const conditionalsToUpdate = getConditionalsToUpdate(content)
if (!conditionalsToUpdate.length) return
// Update Liquid in content files
const newContent = updateLiquid(conditionalsToUpdate, content)
// Add frontmatter version
data.versions['github-ae'] = '*'
// Update Liquid in frontmatter props
Object.keys(data)
.filter((key) => typeof data[key] === 'string')
.forEach((key) => {
const conditionalsToUpdate = getConditionalsToUpdate(data[key])
if (!conditionalsToUpdate.length) return
data[key] = updateLiquid(conditionalsToUpdate, data[key])
})
fs.writeFileSync(file, frontmatter.stringify(newContent, data, { lineWidth: 10000 }))
})
function getConditionalsToUpdate(content) {
return getLiquidConditionals(content, 'ifversion')
.filter((c) => !c.includes('ghae'))
.filter((c) => doesReleaseSatisfyConditional(c.match(ghesRegex)))
}
function updateLiquid(conditionalsToUpdate, content) {
let newContent = content
conditionalsToUpdate.forEach((cond) => {
const oldConditional = `{% ifversion ${cond} %}`
const newConditional = `{% ifversion ${cond.concat(' or ghae')} %}`
const oldConditionalRegex = new RegExp(escapeRegExp(oldConditional), 'g')
// Then replace all instances of the conditional in the content
newContent = newContent.replace(oldConditionalRegex, newConditional)
})
return newContent
}
console.log('Done!')
function doesReleaseSatisfyConditional(ghesMatch) {
if (!ghesMatch) return false
// Operator (e.g., <)
const operator = ghesMatch[1]
// Release number (e.g., 2.21)
const number = ghesMatch[2]
return versionSatisfiesRange(ghesRelease, `${operator}${number}`)
}