diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0cdf66e..fa67eab 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,8 @@ jobs: - run: npm run test - run: npm run coverage - run: npm run pushCoverageReport + env: + COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} publish: if: github.event_name == 'release' && github.event.action == 'created' diff --git a/src/lib/bundle.js b/src/lib/bundle.js index 0adca71..5639a41 100644 --- a/src/lib/bundle.js +++ b/src/lib/bundle.js @@ -1,47 +1,42 @@ // #!/usr/bin/env node 'use strict'; -import shell from "shelljs"; import path from 'path'; import config from './config'; import Log from './log'; +import subprocess from './subprocess'; const log = new Log(); var OPENAPI_JSON_PATH = path.join(config.branchPath, 'openapi.json'); var OPENAPI_YAML_PATH = path.join(config.branchPath, 'openapi.yaml'); -const bundleSpec = async () => { +const bundleSpec = () => { log.preview({ 'title': '\nBranch folder', 'text': `${config.branchPath}/` }) - shell.mkdir('-p', config.branchPath); - var specDir = path.join(config.root, 'spec'); - shell.mkdir('-p', specDir); + subprocess.makeDirs(config.branchPath); + var specDir = path.join(config.root, 'spec'); + subprocess.makeDirs(specDir); var specPath = path.join(config.root, config.apiSpecPath); - + log.preview({ 'title': '\nAPI spec (root) location', 'text': specPath }) - shell.cp(specPath, path.join(config.root, 'spec/openapi.yaml')); + subprocess.copy(specPath, path.join(config.root, 'spec/openapi.yaml')); log.info("\nBundling API spec..."); log.preview({ 'title': "\nStoring bundled 'openapi.json' and 'openapi.yaml' in", 'text': `${config.branchPath}/\n` }); - shell.exec( - `npx openapi bundle -f --output ${OPENAPI_JSON_PATH} ${config.apiSpecPath}`, - {silent: true} - ); - shell.exec( - `npx openapi bundle -f --output ${OPENAPI_YAML_PATH} ${config.apiSpecPath}`, - {silent: true} - ); - shell.rm('-rf', specDir); + + subprocess.exec(`npx openapi bundle -f --output ${OPENAPI_JSON_PATH} ${config.apiSpecPath}`); + subprocess.exec(`npx openapi bundle -f --output ${OPENAPI_YAML_PATH} ${config.apiSpecPath}`); + subprocess.removeDirs(specDir); }; export default bundleSpec; \ No newline at end of file diff --git a/src/lib/gh-pages.js b/src/lib/gh-pages.js index 9e51597..89d69ef 100644 --- a/src/lib/gh-pages.js +++ b/src/lib/gh-pages.js @@ -3,27 +3,31 @@ import shell from 'shelljs'; import config from './config'; import Log from './log'; import fs from 'fs'; - +import subprocess from './subprocess'; const log = new Log(); const fetchPages = () => { - shell.rm('-rf', '.ghpages-tmp'); - shell.mkdir('-p', '.ghpages-tmp'); + + subprocess.removeDirs('.ghpages-tmp'); + subprocess.makeDirs('.ghpages-tmp'); var startDir = shell.pwd(); - shell.cd('.ghpages-tmp'); + subprocess.changeDir('.ghpages-tmp'); + log.log(`\nCloning 'gh-pages' branch into '${shell.pwd().stdout}'`); - shell.exec( - `git clone --depth=1 --branch=gh-pages ${config.repoOrigin} .`, - {silent: true} - ); - shell.cp('-Rn', config.branchPathBase, config.root); + + subprocess.exec(`git clone --depth=1 --branch=gh-pages ${config.repoOrigin} .`); + + if (fs.existsSync(config.branchPathBase)) { + subprocess.copyDirsN(config.branchPathBase, config.root); + } if (fs.existsSync(config.docsRoot)) { - shell.cp('-Rn', config.docsRoot, config.root); - shell.cp('-Rn', 'openapi.*', config.root); + subprocess.copyDirsN(config.docsRoot, config.root); + subprocess.copyDirsN('openapi.*', config.root); } - shell.cd(startDir); - shell.rm('-rf', '.ghpages-tmp') + + subprocess.changeDir(startDir); + subprocess.removeDirs('.ghpages-tmp'); }; export { fetchPages }; diff --git a/src/lib/redoc-ui.js b/src/lib/redoc-ui.js index e526168..0f8748d 100644 --- a/src/lib/redoc-ui.js +++ b/src/lib/redoc-ui.js @@ -1,10 +1,10 @@ // #!/usr/bin/env node 'use strict'; -import shell from 'shelljs'; import path from 'path'; import config from './config'; import themes from './theme'; import Log from './log'; +import subprocess from './subprocess'; const log = new Log(); var OPENAPI_YAML_PATH = path.join(config.branchPath, 'openapi.yaml'); @@ -21,16 +21,15 @@ const constructOptsArg = (themes, themeName) => { const setupUI = () => { var redocOpts = constructOptsArg(themes, config.redocTheme); var uiPath = path.join(config.branchPath, config.docsRoot); - shell.mkdir('-p', uiPath); + subprocess.makeDirs(uiPath); var indexPath = path.join(uiPath, 'index.html'); + log.preview({ title: 'Generating standalone ReDoc HTML', text: `${indexPath}\n` }); - shell.exec( - `npx redoc-cli bundle --output ${indexPath} ${OPENAPI_YAML_PATH} ${redocOpts}`, - {silent: true} - ); + + subprocess.exec(`npx redoc-cli bundle --output ${indexPath} ${OPENAPI_YAML_PATH} ${redocOpts}`); }; export { setupUI }; \ No newline at end of file diff --git a/src/lib/subprocess.js b/src/lib/subprocess.js new file mode 100644 index 0000000..018c6c4 --- /dev/null +++ b/src/lib/subprocess.js @@ -0,0 +1,48 @@ +'use strict'; +import shell from 'shelljs'; + +const cd = "cd"; +const cp = "cp"; +const exec = "exec"; +const mkdir = "mkdir"; +const rm = "rm"; + +const shellFunctions = { + cd: shell.cd, + cp: shell.cp, + exec: shell.exec, + mkdir: shell.mkdir, + rm: shell.rm +} + +class Subprocess { + + constructor(command, ...args) { + this.command = command; + this.args = args; + } + + run() { + return shellFunctions[this.command](...this.args); + } + + runAndAssert() { + var exit = this.run() + if (exit.code != 0) { + throw `Subprocess '${this.command} ${this.args.join(" ")}' ` + + `exited with a code of ${exit.code}`; + } + } +} + +const subprocess = { + changeDir: (...args) => new Subprocess(cd, ...args).runAndAssert(), + makeDirs: (...args) => new Subprocess(mkdir, '-p', ...args).runAndAssert(), + copy: (...args) => new Subprocess(cp, ...args).runAndAssert(), + copyDirs: (...args) => new Subprocess(cp, '-R', ...args).runAndAssert(), + copyDirsN: (...args) => new Subprocess(cp, '-Rn', ...args).runAndAssert(), + removeDirs: (...args) => new Subprocess(rm, '-rf', ...args).runAndAssert(), + exec: (...args) => new Subprocess(exec, ...args).runAndAssert() +} + +export default subprocess; diff --git a/test/mocha/src/lib/testEnvironment.js b/test/mocha/src/lib/testEnvironment.js index 16729eb..5633622 100644 --- a/test/mocha/src/lib/testEnvironment.js +++ b/test/mocha/src/lib/testEnvironment.js @@ -4,7 +4,7 @@ import environment from '@lib/environment'; describe('environment', () => { describe('environment properties', () => { it(`assert environment properties are correctly set`, () => { - assert.equal(environment.env, 'production'); + assert.strictEqual(environment.env, 'production'); }) }) }) \ No newline at end of file diff --git a/test/mocha/src/lib/testSubprocess.js b/test/mocha/src/lib/testSubprocess.js new file mode 100644 index 0000000..3c57ee7 --- /dev/null +++ b/test/mocha/src/lib/testSubprocess.js @@ -0,0 +1,33 @@ +import assert from 'assert'; +import subprocess from '@lib/subprocess'; + +// test cases for runAndAssert function +let subprocessTC = [ + {command: subprocess.changeDir, args: ["/dir/that/doesnt/exist"], expError: true}, + {command: subprocess.makeDirs, args: [".testtmp"], expError: false}, + {command: subprocess.copy, args: [".testtmp0", ".testtmp1"], expError: true}, + {command: subprocess.copyDirs, args: [".testtmp", ".testtmp1"], expError: false}, + {command: subprocess.copyDirsN, args: [".testtmp", ".testtmp2"], expError: false}, + {command: subprocess.removeDirs, args: [".testtmp"], expError: false}, + {command: subprocess.removeDirs, args: [".testtmp1"], expError: false}, + {command: subprocess.removeDirs, args: [".testtmp2"], expError: false}, + {command: subprocess.removeDirs, args: ["/dir/that/doesnt/exist"], expError: true}, + {command: subprocess.exec, args: ['ls -1 > /dev/null'], expError: false}, + {command: subprocess.exec, args: ['pwd'], expError: false}, +] + +describe('subprocess', () => { + describe('subprocess', () => { + it(`asserts subprocess functions throw an error when expected`, () => { + subprocessTC.forEach(tc => { + try { + tc.command(...tc.args); + assert.strictEqual(false, tc.expError); + } catch (err) { + assert.strictEqual(true, tc.expError); + } + }) + }) + }) +}) +