From 2cdbd96cb294c5387679dab7cfebaf10b11119a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6=20=28skjnldsv=29?= Date: Fri, 18 Jun 2021 18:41:56 +0200 Subject: [PATCH] Allow fallback if undefined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ (skjnldsv) --- .github/workflows/test.yml | 40 ++++++++++------------- .gitignore | 14 +++++--- README.md | 40 +++++++++++++++++++++++ action.yml | 6 ++++ dist/index.js | 36 +++++++++++++++----- dist/index.js.map | 2 +- src/__tests__/fixture-empty/package.json | 3 ++ src/__tests__/getNodeVersionEmpty.test.ts | 36 ++++++++++++++++++++ src/getNodeVersion.ts | 37 +++++++++++++++++---- src/main.ts | 7 ++-- 10 files changed, 176 insertions(+), 45 deletions(-) create mode 100644 src/__tests__/fixture-empty/package.json create mode 100644 src/__tests__/getNodeVersionEmpty.test.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2eea907c..01f17e82 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,37 +4,31 @@ on: push: branches: - master - - 'releases/*' + - "releases/*" jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - uses: actions/cache@v2 - id: cache - with: - path: node_modules - key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-npm- + - name: Install dependencies + run: npm ci - - name: Install dependencies - if: steps.cache.outputs.cache-hit != 'true' - run: npm ci + - name: Build + run: npm run build - - name: Build - run: npm run package + - name: Unit Test + run: npm test - - name: Unit Test - run: npm test + - name: Package + run: npm run package - - name: Local action test - uses: ./ - id: versions + - name: Local action test + uses: ./ + id: versions - - name: Get versions - run: | - echo "Node version is ${{ steps.versions.outputs.nodeVersion }}" - echo "Npm version is ${{ steps.versions.outputs.npmVersion }}" \ No newline at end of file + - name: Get versions + run: | + echo "Node version is ${{ steps.versions.outputs.nodeVersion }}" + echo "Npm version is ${{ steps.versions.outputs.npmVersion }}" diff --git a/.gitignore b/.gitignore index ffdd18cd..18e337dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ -__tests__/runner/* - -# comment out in distribution branches -node_modules/ +# Dependency directory +node_modules # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore # Logs @@ -91,3 +89,11 @@ typings/ # DynamoDB Local files .dynamodb/ + +# OS metadata +.DS_Store +Thumbs.db + +# Ignore built ts files +__tests__/runner/* +lib/**/* \ No newline at end of file diff --git a/README.md b/README.md index 26fb9bf5..cc11d707 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,46 @@ jobs: run: echo "Npm version is ${{ steps.package-engines-versions.outputs.npmVersion }}" # Version is ^6.1.3 ``` +### fallbackNode, fallbackNpm + +`fallbackNode` and `fallbackNpm` allows you to define a fallback value if not defined + +```json + +{ + "name": "your-package", + "engines": { + } +} +``` + +```yml +name: Get node and npm versions from package.json + +on: push + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Read node and npm versions from package.json + uses: skjnldsv/read-package-engines-version-actions@v1 + with: + fallbackNode: '^14' + fallbackNpm: '^6' + id: package-engines-versions + + - name: Show node version number + run: echo "Node version is ${{ steps.package-engines-versions.outputs.nodeVersion }}" + # Version is ^14 + + - name: Show npm version number + run: echo "Npm version is ${{ steps.package-engines-versions.outputs.npmVersion }}" + # Version is ^6 +``` # License diff --git a/action.yml b/action.yml index a076a2a5..5420f9b9 100644 --- a/action.yml +++ b/action.yml @@ -8,6 +8,12 @@ inputs: required: false description: 'Path of package.json' default: "./" + fallbackNode: + required: false + description: 'Fallback if engines npm version is not defined' + fallbackNpm: + required: false + description: 'Fallback if engines npm version is not defined' outputs: nodeVersion: description: "Node version from engines field in package.json" diff --git a/dist/index.js b/dist/index.js index 9f7d38cd..59d008e0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -20,20 +20,37 @@ exports.findPackageJson = (path) => { return fs_1.default.readFileSync(path_1.join(path, 'package.json')).toString(); }; /** - * Get engines node version field within package.json + * Get engines versions field within package.json + * @param type * @param path + * @param fallback */ -exports.getNodeVersion = (path) => { +const getEngineVersionFor = (type, path, fallback) => { const packageJson = exports.findPackageJson(path); - return JSON.parse(packageJson).engines.node; + const engines = JSON.parse(packageJson).engines; + if (engines && engines[type]) { + return engines[type]; + } + if (fallback) { + return fallback; + } + return ''; +}; +/** + * Get engines node version field within package.json + * @param path + * @param fallback + */ +exports.getNodeVersion = (path, fallback) => { + return getEngineVersionFor('node', path, fallback); }; /** * Get engines npm version field within package.json * @param path + * @param fallback */ -exports.getNpmVersion = (path) => { - const packageJson = exports.findPackageJson(path); - return JSON.parse(packageJson).engines.npm; +exports.getNpmVersion = (path, fallback) => { + return getEngineVersionFor('npm', path, fallback); }; @@ -65,9 +82,12 @@ function run() { return __awaiter(this, void 0, void 0, function* () { try { const path = core.getInput('path'); + const fallbackNode = core.getInput('fallbackNode'); + const fallbackNpm = core.getInput('fallbackNpm'); core.debug(`Load package.json at ${path}`); - const nodeVersion = getNodeVersion_1.getNodeVersion(path); - const npmVersion = getNodeVersion_1.getNpmVersion(path); + core.debug(`Fallback to ${fallbackNode} / ${fallbackNpm} if undefined`); + const nodeVersion = getNodeVersion_1.getNodeVersion(path, fallbackNode); + const npmVersion = getNodeVersion_1.getNpmVersion(path, fallbackNpm); core.debug(`nodeVersion: ${nodeVersion}, npmVersion: ${npmVersion}`); core.setOutput('nodeVersion', nodeVersion); core.setOutput('npmVersion', npmVersion); diff --git a/dist/index.js.map b/dist/index.js.map index dc55ca03..0b593886 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sources":["../webpack://read-package-node-version-actions/./lib/getNodeVersion.js","../webpack://read-package-node-version-actions/./lib/main.js","../webpack://read-package-node-version-actions/./node_modules/@actions/core/lib/command.js","../webpack://read-package-node-version-actions/./node_modules/@actions/core/lib/core.js","../webpack://read-package-node-version-actions/external \"fs\"","../webpack://read-package-node-version-actions/external \"os\"","../webpack://read-package-node-version-actions/external \"path\"","../webpack://read-package-node-version-actions/webpack/bootstrap","../webpack://read-package-node-version-actions/webpack/runtime/compat","../webpack://read-package-node-version-actions/webpack/startup"],"sourcesContent":["\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst fs_1 = __importDefault(require(\"fs\"));\nconst path_1 = require(\"path\");\n/**\n * Find package.json with path.\n * @param path\n */\nexports.findPackageJson = (path) => {\n return fs_1.default.readFileSync(path_1.join(path, 'package.json')).toString();\n};\n/**\n * Get engines node version field within package.json\n * @param path\n */\nexports.getNodeVersion = (path) => {\n const packageJson = exports.findPackageJson(path);\n return JSON.parse(packageJson).engines.node;\n};\n/**\n * Get engines npm version field within package.json\n * @param path\n */\nexports.getNpmVersion = (path) => {\n const packageJson = exports.findPackageJson(path);\n return JSON.parse(packageJson).engines.npm;\n};\n","\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\n result[\"default\"] = mod;\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst core = __importStar(require(\"@actions/core\"));\nconst getNodeVersion_1 = require(\"./getNodeVersion\");\nfunction run() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n const path = core.getInput('path');\n core.debug(`Load package.json at ${path}`);\n const nodeVersion = getNodeVersion_1.getNodeVersion(path);\n const npmVersion = getNodeVersion_1.getNpmVersion(path);\n core.debug(`nodeVersion: ${nodeVersion}, npmVersion: ${npmVersion}`);\n core.setOutput('nodeVersion', nodeVersion);\n core.setOutput('npmVersion', npmVersion);\n }\n catch (error) {\n core.setFailed(error.message);\n }\n });\n}\nrun();\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nconst os = require(\"os\");\r\n/**\r\n * Commands\r\n *\r\n * Command Format:\r\n * ##[name key=value;key=value]message\r\n *\r\n * Examples:\r\n * ##[warning]This is the user warning message\r\n * ##[set-secret name=mypassword]definatelyNotAPassword!\r\n */\r\nfunction issueCommand(command, properties, message) {\r\n const cmd = new Command(command, properties, message);\r\n process.stdout.write(cmd.toString() + os.EOL);\r\n}\r\nexports.issueCommand = issueCommand;\r\nfunction issue(name, message) {\r\n issueCommand(name, {}, message);\r\n}\r\nexports.issue = issue;\r\nconst CMD_PREFIX = '##[';\r\nclass Command {\r\n constructor(command, properties, message) {\r\n if (!command) {\r\n command = 'missing.command';\r\n }\r\n this.command = command;\r\n this.properties = properties;\r\n this.message = message;\r\n }\r\n toString() {\r\n let cmdStr = CMD_PREFIX + this.command;\r\n if (this.properties && Object.keys(this.properties).length > 0) {\r\n cmdStr += ' ';\r\n for (const key in this.properties) {\r\n if (this.properties.hasOwnProperty(key)) {\r\n const val = this.properties[key];\r\n if (val) {\r\n // safely append the val - avoid blowing up when attempting to\r\n // call .replace() if message is not a string for some reason\r\n cmdStr += `${key}=${escape(`${val || ''}`)};`;\r\n }\r\n }\r\n }\r\n }\r\n cmdStr += ']';\r\n // safely append the message - avoid blowing up when attempting to\r\n // call .replace() if message is not a string for some reason\r\n const message = `${this.message || ''}`;\r\n cmdStr += escapeData(message);\r\n return cmdStr;\r\n }\r\n}\r\nfunction escapeData(s) {\r\n return s.replace(/\\r/g, '%0D').replace(/\\n/g, '%0A');\r\n}\r\nfunction escape(s) {\r\n return s\r\n .replace(/\\r/g, '%0D')\r\n .replace(/\\n/g, '%0A')\r\n .replace(/]/g, '%5D')\r\n .replace(/;/g, '%3B');\r\n}\r\n//# sourceMappingURL=command.js.map","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nconst command_1 = require(\"./command\");\r\nconst path = require(\"path\");\r\n/**\r\n * The code to exit an action\r\n */\r\nvar ExitCode;\r\n(function (ExitCode) {\r\n /**\r\n * A code indicating that the action was successful\r\n */\r\n ExitCode[ExitCode[\"Success\"] = 0] = \"Success\";\r\n /**\r\n * A code indicating that the action was a failure\r\n */\r\n ExitCode[ExitCode[\"Failure\"] = 1] = \"Failure\";\r\n})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));\r\n//-----------------------------------------------------------------------\r\n// Variables\r\n//-----------------------------------------------------------------------\r\n/**\r\n * sets env variable for this action and future actions in the job\r\n * @param name the name of the variable to set\r\n * @param val the value of the variable\r\n */\r\nfunction exportVariable(name, val) {\r\n process.env[name] = val;\r\n command_1.issueCommand('set-env', { name }, val);\r\n}\r\nexports.exportVariable = exportVariable;\r\n/**\r\n * exports the variable and registers a secret which will get masked from logs\r\n * @param name the name of the variable to set\r\n * @param val value of the secret\r\n */\r\nfunction exportSecret(name, val) {\r\n exportVariable(name, val);\r\n command_1.issueCommand('set-secret', {}, val);\r\n}\r\nexports.exportSecret = exportSecret;\r\n/**\r\n * Prepends inputPath to the PATH (for this action and future actions)\r\n * @param inputPath\r\n */\r\nfunction addPath(inputPath) {\r\n command_1.issueCommand('add-path', {}, inputPath);\r\n process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;\r\n}\r\nexports.addPath = addPath;\r\n/**\r\n * Gets the value of an input. The value is also trimmed.\r\n *\r\n * @param name name of the input to get\r\n * @param options optional. See InputOptions.\r\n * @returns string\r\n */\r\nfunction getInput(name, options) {\r\n const val = process.env[`INPUT_${name.replace(' ', '_').toUpperCase()}`] || '';\r\n if (options && options.required && !val) {\r\n throw new Error(`Input required and not supplied: ${name}`);\r\n }\r\n return val.trim();\r\n}\r\nexports.getInput = getInput;\r\n/**\r\n * Sets the value of an output.\r\n *\r\n * @param name name of the output to set\r\n * @param value value to store\r\n */\r\nfunction setOutput(name, value) {\r\n command_1.issueCommand('set-output', { name }, value);\r\n}\r\nexports.setOutput = setOutput;\r\n//-----------------------------------------------------------------------\r\n// Results\r\n//-----------------------------------------------------------------------\r\n/**\r\n * Sets the action status to failed.\r\n * When the action exits it will be with an exit code of 1\r\n * @param message add error issue message\r\n */\r\nfunction setFailed(message) {\r\n process.exitCode = ExitCode.Failure;\r\n error(message);\r\n}\r\nexports.setFailed = setFailed;\r\n//-----------------------------------------------------------------------\r\n// Logging Commands\r\n//-----------------------------------------------------------------------\r\n/**\r\n * Writes debug message to user log\r\n * @param message debug message\r\n */\r\nfunction debug(message) {\r\n command_1.issueCommand('debug', {}, message);\r\n}\r\nexports.debug = debug;\r\n/**\r\n * Adds an error issue\r\n * @param message error issue message\r\n */\r\nfunction error(message) {\r\n command_1.issue('error', message);\r\n}\r\nexports.error = error;\r\n/**\r\n * Adds an warning issue\r\n * @param message warning issue message\r\n */\r\nfunction warning(message) {\r\n command_1.issue('warning', message);\r\n}\r\nexports.warning = warning;\r\n//# sourceMappingURL=core.js.map","module.exports = require(\"fs\");;","module.exports = require(\"os\");;","module.exports = require(\"path\");;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tvar threw = true;\n\ttry {\n\t\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\t\tthrew = false;\n\t} finally {\n\t\tif(threw) delete __webpack_module_cache__[moduleId];\n\t}\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","\nif (typeof __webpack_require__ !== 'undefined') __webpack_require__.ab = __dirname + \"/\";","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(109);\n"],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;;;;AC/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;;;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;;;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;;;;ACpHA;AACA;A;;;;;ACDA;AACA;A;;;;;ACDA;AACA;A;;;;ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC7BA;AACA;;ACDA;AACA;AACA;AACA;;;;A","sourceRoot":""} \ No newline at end of file +{"version":3,"file":"index.js","sources":["../webpack://read-package-node-version-actions/./lib/getNodeVersion.js","../webpack://read-package-node-version-actions/./lib/main.js","../webpack://read-package-node-version-actions/./node_modules/@actions/core/lib/command.js","../webpack://read-package-node-version-actions/./node_modules/@actions/core/lib/core.js","../webpack://read-package-node-version-actions/external \"fs\"","../webpack://read-package-node-version-actions/external \"os\"","../webpack://read-package-node-version-actions/external \"path\"","../webpack://read-package-node-version-actions/webpack/bootstrap","../webpack://read-package-node-version-actions/webpack/runtime/compat","../webpack://read-package-node-version-actions/webpack/startup"],"sourcesContent":["\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst fs_1 = __importDefault(require(\"fs\"));\nconst path_1 = require(\"path\");\n/**\n * Find package.json with path.\n * @param path\n */\nexports.findPackageJson = (path) => {\n return fs_1.default.readFileSync(path_1.join(path, 'package.json')).toString();\n};\n/**\n * Get engines versions field within package.json\n * @param type\n * @param path\n * @param fallback\n */\nconst getEngineVersionFor = (type, path, fallback) => {\n const packageJson = exports.findPackageJson(path);\n const engines = JSON.parse(packageJson).engines;\n if (engines && engines[type]) {\n return engines[type];\n }\n if (fallback) {\n return fallback;\n }\n return '';\n};\n/**\n * Get engines node version field within package.json\n * @param path\n * @param fallback\n */\nexports.getNodeVersion = (path, fallback) => {\n return getEngineVersionFor('node', path, fallback);\n};\n/**\n * Get engines npm version field within package.json\n * @param path\n * @param fallback\n */\nexports.getNpmVersion = (path, fallback) => {\n return getEngineVersionFor('npm', path, fallback);\n};\n","\"use strict\";\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __importStar = (this && this.__importStar) || function (mod) {\n if (mod && mod.__esModule) return mod;\n var result = {};\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\n result[\"default\"] = mod;\n return result;\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nconst core = __importStar(require(\"@actions/core\"));\nconst getNodeVersion_1 = require(\"./getNodeVersion\");\nfunction run() {\n return __awaiter(this, void 0, void 0, function* () {\n try {\n const path = core.getInput('path');\n const fallbackNode = core.getInput('fallbackNode');\n const fallbackNpm = core.getInput('fallbackNpm');\n core.debug(`Load package.json at ${path}`);\n core.debug(`Fallback to ${fallbackNode} / ${fallbackNpm} if undefined`);\n const nodeVersion = getNodeVersion_1.getNodeVersion(path, fallbackNode);\n const npmVersion = getNodeVersion_1.getNpmVersion(path, fallbackNpm);\n core.debug(`nodeVersion: ${nodeVersion}, npmVersion: ${npmVersion}`);\n core.setOutput('nodeVersion', nodeVersion);\n core.setOutput('npmVersion', npmVersion);\n }\n catch (error) {\n core.setFailed(error.message);\n }\n });\n}\nrun();\n","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nconst os = require(\"os\");\r\n/**\r\n * Commands\r\n *\r\n * Command Format:\r\n * ##[name key=value;key=value]message\r\n *\r\n * Examples:\r\n * ##[warning]This is the user warning message\r\n * ##[set-secret name=mypassword]definatelyNotAPassword!\r\n */\r\nfunction issueCommand(command, properties, message) {\r\n const cmd = new Command(command, properties, message);\r\n process.stdout.write(cmd.toString() + os.EOL);\r\n}\r\nexports.issueCommand = issueCommand;\r\nfunction issue(name, message) {\r\n issueCommand(name, {}, message);\r\n}\r\nexports.issue = issue;\r\nconst CMD_PREFIX = '##[';\r\nclass Command {\r\n constructor(command, properties, message) {\r\n if (!command) {\r\n command = 'missing.command';\r\n }\r\n this.command = command;\r\n this.properties = properties;\r\n this.message = message;\r\n }\r\n toString() {\r\n let cmdStr = CMD_PREFIX + this.command;\r\n if (this.properties && Object.keys(this.properties).length > 0) {\r\n cmdStr += ' ';\r\n for (const key in this.properties) {\r\n if (this.properties.hasOwnProperty(key)) {\r\n const val = this.properties[key];\r\n if (val) {\r\n // safely append the val - avoid blowing up when attempting to\r\n // call .replace() if message is not a string for some reason\r\n cmdStr += `${key}=${escape(`${val || ''}`)};`;\r\n }\r\n }\r\n }\r\n }\r\n cmdStr += ']';\r\n // safely append the message - avoid blowing up when attempting to\r\n // call .replace() if message is not a string for some reason\r\n const message = `${this.message || ''}`;\r\n cmdStr += escapeData(message);\r\n return cmdStr;\r\n }\r\n}\r\nfunction escapeData(s) {\r\n return s.replace(/\\r/g, '%0D').replace(/\\n/g, '%0A');\r\n}\r\nfunction escape(s) {\r\n return s\r\n .replace(/\\r/g, '%0D')\r\n .replace(/\\n/g, '%0A')\r\n .replace(/]/g, '%5D')\r\n .replace(/;/g, '%3B');\r\n}\r\n//# sourceMappingURL=command.js.map","\"use strict\";\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nconst command_1 = require(\"./command\");\r\nconst path = require(\"path\");\r\n/**\r\n * The code to exit an action\r\n */\r\nvar ExitCode;\r\n(function (ExitCode) {\r\n /**\r\n * A code indicating that the action was successful\r\n */\r\n ExitCode[ExitCode[\"Success\"] = 0] = \"Success\";\r\n /**\r\n * A code indicating that the action was a failure\r\n */\r\n ExitCode[ExitCode[\"Failure\"] = 1] = \"Failure\";\r\n})(ExitCode = exports.ExitCode || (exports.ExitCode = {}));\r\n//-----------------------------------------------------------------------\r\n// Variables\r\n//-----------------------------------------------------------------------\r\n/**\r\n * sets env variable for this action and future actions in the job\r\n * @param name the name of the variable to set\r\n * @param val the value of the variable\r\n */\r\nfunction exportVariable(name, val) {\r\n process.env[name] = val;\r\n command_1.issueCommand('set-env', { name }, val);\r\n}\r\nexports.exportVariable = exportVariable;\r\n/**\r\n * exports the variable and registers a secret which will get masked from logs\r\n * @param name the name of the variable to set\r\n * @param val value of the secret\r\n */\r\nfunction exportSecret(name, val) {\r\n exportVariable(name, val);\r\n command_1.issueCommand('set-secret', {}, val);\r\n}\r\nexports.exportSecret = exportSecret;\r\n/**\r\n * Prepends inputPath to the PATH (for this action and future actions)\r\n * @param inputPath\r\n */\r\nfunction addPath(inputPath) {\r\n command_1.issueCommand('add-path', {}, inputPath);\r\n process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`;\r\n}\r\nexports.addPath = addPath;\r\n/**\r\n * Gets the value of an input. The value is also trimmed.\r\n *\r\n * @param name name of the input to get\r\n * @param options optional. See InputOptions.\r\n * @returns string\r\n */\r\nfunction getInput(name, options) {\r\n const val = process.env[`INPUT_${name.replace(' ', '_').toUpperCase()}`] || '';\r\n if (options && options.required && !val) {\r\n throw new Error(`Input required and not supplied: ${name}`);\r\n }\r\n return val.trim();\r\n}\r\nexports.getInput = getInput;\r\n/**\r\n * Sets the value of an output.\r\n *\r\n * @param name name of the output to set\r\n * @param value value to store\r\n */\r\nfunction setOutput(name, value) {\r\n command_1.issueCommand('set-output', { name }, value);\r\n}\r\nexports.setOutput = setOutput;\r\n//-----------------------------------------------------------------------\r\n// Results\r\n//-----------------------------------------------------------------------\r\n/**\r\n * Sets the action status to failed.\r\n * When the action exits it will be with an exit code of 1\r\n * @param message add error issue message\r\n */\r\nfunction setFailed(message) {\r\n process.exitCode = ExitCode.Failure;\r\n error(message);\r\n}\r\nexports.setFailed = setFailed;\r\n//-----------------------------------------------------------------------\r\n// Logging Commands\r\n//-----------------------------------------------------------------------\r\n/**\r\n * Writes debug message to user log\r\n * @param message debug message\r\n */\r\nfunction debug(message) {\r\n command_1.issueCommand('debug', {}, message);\r\n}\r\nexports.debug = debug;\r\n/**\r\n * Adds an error issue\r\n * @param message error issue message\r\n */\r\nfunction error(message) {\r\n command_1.issue('error', message);\r\n}\r\nexports.error = error;\r\n/**\r\n * Adds an warning issue\r\n * @param message warning issue message\r\n */\r\nfunction warning(message) {\r\n command_1.issue('warning', message);\r\n}\r\nexports.warning = warning;\r\n//# sourceMappingURL=core.js.map","module.exports = require(\"fs\");;","module.exports = require(\"os\");;","module.exports = require(\"path\");;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\tvar threw = true;\n\ttry {\n\t\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\t\tthrew = false;\n\t} finally {\n\t\tif(threw) delete __webpack_module_cache__[moduleId];\n\t}\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","\nif (typeof __webpack_require__ !== 'undefined') __webpack_require__.ab = __dirname + \"/\";","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(109);\n"],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;;;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;;;;ACxCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;;;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;A;;;;;ACpHA;AACA;A;;;;;ACDA;AACA;A;;;;;ACDA;AACA;A;;;;ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC7BA;AACA;;ACDA;AACA;AACA;AACA;;;;A","sourceRoot":""} \ No newline at end of file diff --git a/src/__tests__/fixture-empty/package.json b/src/__tests__/fixture-empty/package.json new file mode 100644 index 00000000..d102758c --- /dev/null +++ b/src/__tests__/fixture-empty/package.json @@ -0,0 +1,3 @@ +{ + "name": "fixture" +} \ No newline at end of file diff --git a/src/__tests__/getNodeVersionEmpty.test.ts b/src/__tests__/getNodeVersionEmpty.test.ts new file mode 100644 index 00000000..8576262f --- /dev/null +++ b/src/__tests__/getNodeVersionEmpty.test.ts @@ -0,0 +1,36 @@ +import fs from 'fs'; + +import { + findPackageJson, + getNodeVersion, + getNpmVersion +} from '../getNodeVersion'; + +const fixturePath = './src/__tests__/fixture-empty'; +const fixture = `./src/__tests__/fixture-empty/package.json`; + +describe('getNodeVersion with fallback', () => { + describe('findPackageJson', () => { + test('find package.json', () => { + const result = findPackageJson(fixturePath); + + expect(result).toBe(fs.readFileSync(fixture).toString()); + }); + }); + + describe('getNodeVersion', () => { + test('get undefined node version text within package.json with fallback', () => { + const result = getNodeVersion(fixturePath, '^12.22.1'); + + expect(result).toBe('^12.22.1'); + }); + }); + + describe('getNpmVersion', () => { + test('get undefined npm version text within package.json', () => { + const result = getNpmVersion(fixturePath); + + expect(result).toBe(''); + }); + }); +}); diff --git a/src/getNodeVersion.ts b/src/getNodeVersion.ts index eb00e8a3..250e2d0a 100644 --- a/src/getNodeVersion.ts +++ b/src/getNodeVersion.ts @@ -10,21 +10,44 @@ export const findPackageJson = (path: string): string => { }; /** - * Get engines node version field within package.json + * Get engines versions field within package.json + * @param type * @param path + * @param fallback */ -export const getNodeVersion = (path: string): string => { +const getEngineVersionFor = ( + type: string, + path: string, + fallback?: string +): string => { const packageJson = findPackageJson(path); + const engines = JSON.parse(packageJson).engines; + + if (engines && engines[type]) { + return engines[type]; + } + + if (fallback) { + return fallback; + } - return JSON.parse(packageJson).engines.node; + return ''; }; /** - * Get engines npm version field within package.json + * Get engines node version field within package.json * @param path + * @param fallback */ -export const getNpmVersion = (path: string): string => { - const packageJson = findPackageJson(path); +export const getNodeVersion = (path: string, fallback?: string): string => { + return getEngineVersionFor('node', path, fallback); +}; - return JSON.parse(packageJson).engines.npm; +/** + * Get engines npm version field within package.json + * @param path + * @param fallback + */ +export const getNpmVersion = (path: string, fallback?: string): string => { + return getEngineVersionFor('npm', path, fallback); }; diff --git a/src/main.ts b/src/main.ts index 11b7cd4c..be1db27d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,11 +4,14 @@ import { getNodeVersion, getNpmVersion } from './getNodeVersion'; async function run() { try { const path = core.getInput('path'); + const fallbackNode = core.getInput('fallbackNode'); + const fallbackNpm = core.getInput('fallbackNpm'); core.debug(`Load package.json at ${path}`); + core.debug(`Fallback to ${fallbackNode} / ${fallbackNpm} if undefined`); - const nodeVersion = getNodeVersion(path); - const npmVersion = getNpmVersion(path); + const nodeVersion = getNodeVersion(path, fallbackNode); + const npmVersion = getNpmVersion(path, fallbackNpm); core.debug(`nodeVersion: ${nodeVersion}, npmVersion: ${npmVersion}`); core.setOutput('nodeVersion', nodeVersion);