forked from github/docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
update-files.js
executable file
·113 lines (92 loc) · 4.93 KB
/
update-files.js
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
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const program = require('commander')
const { execSync } = require('child_process')
const mkdirp = require('mkdirp').sync
const rimraf = require('rimraf').sync
const tempDocsDir = path.join(process.cwd(), 'openapiTmp')
const githubRepoDir = path.join(process.cwd(), '../github')
const dereferencedPath = path.join(process.cwd(), 'lib/rest/static/dereferenced')
const schemas = fs.readdirSync(dereferencedPath)
const getOperations = require('./utils/get-operations')
const decoratedPath = path.join(process.cwd(), 'lib/rest/static/decorated')
// [start-readme]
//
// Run this script to pull openAPI files from github/github, dereference them, and decorate them.
//
// [end-readme]
program
.description('Generate dereferenced OpenAPI and decorated schema files.')
.option('--decorate-only', '⚠️ Only used by a 🤖 to generate decorated schema files from existing dereferenced schema files.')
.parse(process.argv)
const decorateOnly = program.opts().decorateOnly
main()
async function main () {
// Generate the dereferenced OpenAPI schema files
if (!decorateOnly) {
if (!fs.existsSync(githubRepoDir)) {
console.log(`🛑 The ${githubRepoDir} does not exist. Make sure you have a local, bootstrapped checkout of github/github at the same level as your github/docs-internal repo before running this script.`)
process.exit(1)
}
await getDereferencedFiles()
}
await decorate()
console.log('\n🏁 The static REST API files are now up-to-date with your local `github/github` checkout. To revert uncommitted changes, run `git checkout lib/rest/static/*.\n\n')
}
async function getDereferencedFiles () {
// Get the github/github repo branch name and pull latest
const githubBranch = execSync('git rev-parse --abbrev-ref HEAD', { cwd: githubRepoDir }).toString().trim()
// Only pull master branch because development mode branches are assumed
// to be up-to-date during active work.
if (githubBranch === 'master') {
execSync('git pull', { cwd: githubRepoDir })
}
// create a tmp directory to store schema files generated from github/github
rimraf(tempDocsDir)
mkdirp(tempDocsDir)
console.log(`\n🏃♀️🏃🏃♀️Running \`bin/openapi bundle\` in branch '${githubBranch}' of your github/github checkout to generate the dereferenced OpenAPI schema files.\n`)
try {
execSync(`${path.join(githubRepoDir, 'bin/openapi')} bundle -o ${tempDocsDir} --include_unpublished`, { stdio: 'inherit' })
} catch (error) {
console.error(error)
console.log('🛑 Whoops! It looks like the `bin/openapi bundle` command failed to run in your `github/github` repository checkout. To troubleshoot, ensure that your OpenAPI schema YAML is formatted correctly. A CI test runs on your `github/github` PR that flags malformed YAML. You can check the PR diff view for comments left by the openapi CI test to find and fix any formatting errors.')
process.exit(1)
}
execSync(`find ${tempDocsDir} -type f -name "*deref.json" -exec mv '{}' ${dereferencedPath} ';'`)
rimraf(tempDocsDir)
// When running in development mode (locally), the the info.version
// property in the dereferenced schema is replaced with the branch
// name of the `github/github` checkout. A CI test
// checks the version and fails if it's not a semantic version.
schemas.forEach(filename => {
const schema = JSON.parse(fs.readFileSync(path.join(dereferencedPath, filename)))
schema.info.version = `${githubBranch} !!DEVELOPMENT MODE - DO NOT MERGE!!`
fs.writeFileSync(path.join(dereferencedPath, filename), JSON.stringify(schema, null, 2))
})
}
async function decorate () {
console.log('\n🎄 Decorating the OpenAPI schema files in lib/rest/static/dereferenced.\n')
const dereferencedSchemas = schemas.reduce((acc, filename) => {
const schema = JSON.parse(fs.readFileSync(path.join(dereferencedPath, filename)))
const key = filename.replace('.deref.json', '')
return { ...acc, [key]: schema }
}, {})
for (const [schemaName, schema] of Object.entries(dereferencedSchemas)) {
try {
// munge OpenAPI definitions object in an array of operations objects
const operations = await getOperations(schema)
// process each operation, asynchronously rendering markdown and stuff
await Promise.all(operations.map(operation => operation.process()))
const filename = path.join(decoratedPath, `${schemaName}.json`)
.replace('.deref', '')
// write processed operations to disk
fs.writeFileSync(filename, JSON.stringify(operations, null, 2))
console.log('Wrote', path.relative(process.cwd(), filename))
} catch (error) {
console.error(error)
console.log('🐛 Whoops! It looks like the decorator script wasn\'t able to parse the dereferenced schema. A recent change may not yet be supported by the decorator. Please reach out in the #docs-engineering slack channel for help.')
process.exit(1)
}
}
}