fix(ci,oas) move oas ci script to a package under the oas workspace (#3391)
* feat(ci,oas) run oas ci on all PRs * fix(ci,oas) move oas ci script to a package under the oas workspace * chore(changeset): patch
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
/dist
|
||||
node_modules
|
||||
.DS_store
|
||||
.env*
|
||||
.env
|
||||
*.sql
|
||||
@@ -0,0 +1,3 @@
|
||||
# @medusajs/oas-github-ci
|
||||
|
||||
## 1.0.0
|
||||
@@ -0,0 +1,3 @@
|
||||
# oas-github-ci - 1.0.0
|
||||
|
||||
Script used in CI for validating OAS documentation.
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@medusajs/oas-github-ci",
|
||||
"version": "1.0.0",
|
||||
"description": "OAS Github CI",
|
||||
"main": "scripts/build-openapi.js",
|
||||
"files": [
|
||||
"scripts"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/medusajs/medusa",
|
||||
"directory": "packages/oas/oas-github-ci"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "restricted"
|
||||
},
|
||||
"author": "Medusa",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"ci": "node scripts/build-openapi.js",
|
||||
"preview:admin": "yarn redocly preview-docs ../../../docs/api/admin/openapi.yaml --config=../../../docs-util/redocly/config.yaml",
|
||||
"preview:store": "yarn redocly preview-docs ../../../docs/api/store/openapi.yaml --config=../../../docs-util/redocly/config.yaml",
|
||||
"test": "jest --passWithNoTests",
|
||||
"test:unit": "jest --passWithNoTests"
|
||||
},
|
||||
"dependencies": {
|
||||
"@medusajs/medusa-oas-cli": "*",
|
||||
"@readme/openapi-parser": "^2.4.0",
|
||||
"@redocly/cli": "1.0.0-beta.123",
|
||||
"execa": "^5.1.1",
|
||||
"js-yaml": "^4.1.0"
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const fs = require("fs/promises")
|
||||
const os = require("os")
|
||||
const path = require("path")
|
||||
const execa = require("execa")
|
||||
const yaml = require("js-yaml")
|
||||
const OpenAPIParser = require("@readme/openapi-parser")
|
||||
|
||||
const isDryRun = process.argv.indexOf("--dry-run") !== -1
|
||||
const basePath = path.resolve(__dirname, `../`)
|
||||
const repoRootPath = path.resolve(basePath, `../../../`)
|
||||
const docsApiPath = path.resolve(repoRootPath, "docs/api/")
|
||||
const redoclyConfigPath = path.resolve(
|
||||
repoRootPath,
|
||||
"docs-util/redocly/config.yaml"
|
||||
)
|
||||
|
||||
const run = async () => {
|
||||
const outputPath = isDryRun ? await getTmpDirectory() : docsApiPath
|
||||
|
||||
await generateOASSources(outputPath)
|
||||
|
||||
for (const apiType of ["store", "admin"]) {
|
||||
const inputJsonFile = path.resolve(outputPath, `${apiType}.oas.json`)
|
||||
const outputYamlFile = path.resolve(outputPath, `${apiType}.oas.yaml`)
|
||||
|
||||
await jsonFileToYamlFile(inputJsonFile, outputYamlFile)
|
||||
await sanitizeOAS(outputYamlFile)
|
||||
await circularReferenceCheck(outputYamlFile)
|
||||
if (!isDryRun) {
|
||||
await generateReference(outputYamlFile, apiType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const generateOASSources = async (outDir, isDryRun) => {
|
||||
const params = ["oas", `--out-dir=${outDir}`]
|
||||
if (isDryRun) {
|
||||
params.push("--dry-run")
|
||||
}
|
||||
const { all: logs } = await execa("medusa-oas", params, {
|
||||
cwd: basePath,
|
||||
all: true,
|
||||
})
|
||||
console.log(logs)
|
||||
}
|
||||
|
||||
const jsonFileToYamlFile = async (inputJsonFile, outputYamlFile) => {
|
||||
const jsonString = await fs.readFile(inputJsonFile, "utf8")
|
||||
const jsonObject = JSON.parse(jsonString)
|
||||
const yamlString = yaml.dump(jsonObject)
|
||||
await fs.writeFile(outputYamlFile, yamlString, "utf8")
|
||||
}
|
||||
|
||||
const sanitizeOAS = async (srcFile) => {
|
||||
const { all: logs } = await execa(
|
||||
"redocly",
|
||||
["bundle", srcFile, `--output=${srcFile}`, `--config=${redoclyConfigPath}`],
|
||||
{ cwd: basePath, all: true }
|
||||
)
|
||||
console.log(logs)
|
||||
}
|
||||
|
||||
const circularReferenceCheck = async (srcFile) => {
|
||||
const parser = new OpenAPIParser()
|
||||
await parser.validate(srcFile, {
|
||||
dereference: {
|
||||
circular: "ignore",
|
||||
},
|
||||
})
|
||||
if (parser.$refs.circular) {
|
||||
const fileName = path.basename(srcFile)
|
||||
const circularRefs = [...parser.$refs.circularRefs]
|
||||
circularRefs.sort()
|
||||
console.log(circularRefs)
|
||||
throw new Error(
|
||||
`🔴 Unhandled circular references - ${fileName} - Please patch in docs-util/redocly/config.yaml`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const generateReference = async (srcFile, apiType) => {
|
||||
const outDir = path.resolve(docsApiPath, `${apiType}`)
|
||||
await fs.rm(outDir, { recursive: true, force: true })
|
||||
const { all: logs } = await execa(
|
||||
"redocly",
|
||||
["split", srcFile, `--outDir=${outDir}`],
|
||||
{ cwd: basePath, all: true }
|
||||
)
|
||||
console.log(logs)
|
||||
}
|
||||
|
||||
const getTmpDirectory = async () => {
|
||||
/**
|
||||
* RUNNER_TEMP: GitHub action, the path to a temporary directory on the runner.
|
||||
*/
|
||||
const tmpDir = process.env["RUNNER_TEMP"] ?? os.tmpdir()
|
||||
return await fs.mkdtemp(tmpDir)
|
||||
}
|
||||
|
||||
void (async () => {
|
||||
try {
|
||||
await run()
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
process.exit(1)
|
||||
}
|
||||
})()
|
||||
Reference in New Issue
Block a user