Co-authored-by: Rachael Sewell <rachmari@github.com> Co-authored-by: Sarah Edwards <skedwards88@github.com> Co-authored-by: Grace Park <gracepark@Graces-MacBook-Pro-2.local> Co-authored-by: Sarah Schneider <sarahs@users.noreply.github.com> Co-authored-by: Sarah Schneider <sarahs@github.com>
176 lines
5.7 KiB
JavaScript
Executable File
176 lines
5.7 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
// [start-readme]
|
|
//
|
|
// Run this script to check if OpenAPI operations match versions in content/rest operations
|
|
//
|
|
// [end-readme]
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import _ from 'lodash'
|
|
|
|
import frontmatter from '../../lib/read-frontmatter.js'
|
|
import getApplicableVersions from '../../lib/get-applicable-versions.js'
|
|
import { allVersions, getDocsVersion } from '../../lib/all-versions.js'
|
|
|
|
const contentFiles = []
|
|
|
|
export async function getDiffOpenAPIContentRest() {
|
|
const contentPath = path.join(process.cwd(), 'content/rest')
|
|
|
|
// Recursively go through the content/rest directory and add all categories/subcategories to contentFiles
|
|
throughDirectory(contentPath)
|
|
|
|
// Creating the categories/subcategories based on the current content directory
|
|
const checkContentDir = await createCheckContentDirectory(contentFiles)
|
|
|
|
// Create categories/subcategories from OpenAPI Schemas
|
|
const openAPISchemaCheck = await createOpenAPISchemasCheck()
|
|
|
|
// One off edge case for secret-scanning Docs-content issue 6637
|
|
const fptApiVersions = getOnlyApiVersions('free-pro-team@latest')
|
|
|
|
fptApiVersions.forEach((fptApiVersion) => {
|
|
delete openAPISchemaCheck[fptApiVersion]['secret-scanning']
|
|
})
|
|
|
|
// Get Differences between categories/subcategories from dereferenced schemas and the content/rest directory frontmatter versions
|
|
const differences = getDifferences(openAPISchemaCheck, checkContentDir)
|
|
const errorMessages = {}
|
|
|
|
if (Object.keys(differences).length > 0) {
|
|
for (const schemaName in differences) {
|
|
errorMessages[schemaName] = {}
|
|
|
|
differences[schemaName].forEach((category) => {
|
|
if (!errorMessages[schemaName]) errorMessages[schemaName] = category
|
|
|
|
errorMessages[schemaName][category] = {
|
|
contentDir: checkContentDir[schemaName][category],
|
|
openAPI: openAPISchemaCheck[schemaName][category],
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
return errorMessages
|
|
}
|
|
|
|
async function createOpenAPISchemasCheck() {
|
|
const schemasPath = path.join(process.cwd(), 'lib/rest/static/decorated')
|
|
const openAPICheck = createCheckObj()
|
|
const schemas = fs.readdirSync(schemasPath)
|
|
|
|
schemas.forEach((file) => {
|
|
const fileData = fs.readFileSync(path.join(schemasPath, file))
|
|
const fileSchema = JSON.parse(fileData.toString())
|
|
const categories = Object.keys(fileSchema).sort()
|
|
const version = getDocsVersion(file.split(/.json/)[0])
|
|
|
|
categories.forEach((category) => {
|
|
const subcategories = Object.keys(fileSchema[category])
|
|
if (isApiVersioned(version)) {
|
|
getOnlyApiVersions(version).forEach(
|
|
(apiVersion) => (openAPICheck[apiVersion][category] = subcategories.sort())
|
|
)
|
|
} else {
|
|
openAPICheck[version][category] = subcategories.sort()
|
|
}
|
|
})
|
|
})
|
|
|
|
return openAPICheck
|
|
}
|
|
|
|
async function createCheckContentDirectory(contentFiles) {
|
|
const checkContent = createCheckObj()
|
|
|
|
for (const filename of contentFiles) {
|
|
const { data } = frontmatter(await fs.promises.readFile(filename, 'utf8'))
|
|
const applicableVersions = getApplicableVersions(data.versions, filename)
|
|
const splitPath = filename.split('/')
|
|
const subCategory = splitPath[splitPath.length - 1].replace('.md', '')
|
|
const category =
|
|
splitPath[splitPath.length - 2] === 'rest' ? subCategory : splitPath[splitPath.length - 2]
|
|
// All versions with appended calendar date versions if it exists
|
|
const allCompleteVersions = applicableVersions.flatMap((version) => {
|
|
return isApiVersioned(version)
|
|
? allVersions[version].apiVersions.map(
|
|
(apiVersion) => `${allVersions[version].version}.${apiVersion}`
|
|
)
|
|
: version
|
|
})
|
|
|
|
allCompleteVersions.forEach((version) => {
|
|
!checkContent[version][category]
|
|
? (checkContent[version][category] = [subCategory])
|
|
: checkContent[version][category].push(subCategory)
|
|
checkContent[version][category].sort()
|
|
})
|
|
}
|
|
|
|
return checkContent
|
|
}
|
|
|
|
function isApiVersioned(version) {
|
|
return allVersions[version] && allVersions[version].apiVersions.length > 0
|
|
}
|
|
|
|
function getOnlyApiVersions(version) {
|
|
return allVersions[version].apiVersions.map(
|
|
(apiVersion) => `${allVersions[version].version}.${apiVersion}`
|
|
)
|
|
}
|
|
|
|
function createCheckObj() {
|
|
const versions = {}
|
|
Object.keys(allVersions).forEach((version) => {
|
|
isApiVersioned(version)
|
|
? getOnlyApiVersions(version).forEach((apiVersion) => (versions[apiVersion] = {}))
|
|
: (versions[`${allVersions[version].version}`] = {})
|
|
})
|
|
|
|
return versions
|
|
}
|
|
|
|
function getDifferences(openAPISchemaCheck, contentCheck) {
|
|
const differences = {}
|
|
for (const version in openAPISchemaCheck) {
|
|
const diffOpenApiContent = difference(openAPISchemaCheck[version], contentCheck[version])
|
|
if (Object.keys(diffOpenApiContent).length > 0) differences[version] = diffOpenApiContent
|
|
}
|
|
|
|
return differences
|
|
}
|
|
|
|
function throughDirectory(directory) {
|
|
fs.readdirSync(directory).forEach((file) => {
|
|
const absolute = path.join(directory, file)
|
|
if (fs.statSync(absolute).isDirectory()) {
|
|
return throughDirectory(absolute)
|
|
} else if (
|
|
!directory.includes('rest/guides') &&
|
|
!directory.includes('rest/overview') &&
|
|
!file.includes('index.md') &&
|
|
!file.includes('quickstart.md') &&
|
|
!file.includes('README.md')
|
|
) {
|
|
return contentFiles.push(absolute)
|
|
}
|
|
})
|
|
}
|
|
|
|
function difference(obj1, obj2) {
|
|
const diff = Object.keys(obj1).reduce((result, key) => {
|
|
if (!Object.prototype.hasOwnProperty.call(obj2, key)) {
|
|
result.push(key)
|
|
} else if (_.isEqual(obj1[key], obj2[key])) {
|
|
const resultKeyIndex = result.indexOf(key)
|
|
result.splice(resultKeyIndex, 1)
|
|
}
|
|
return result
|
|
}, Object.keys(obj2))
|
|
|
|
return diff
|
|
}
|