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.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 = require(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 = require(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)
- }
- }
- }
|