From 1c15c75162ac929a9adc01f5e3a76352be3011ca Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 16 Jan 2023 16:57:35 -0800 Subject: [PATCH 01/15] Add sanitizeStringForJSONParse and use it in getMergeLogsAsJSON --- .github/libs/GitUtils.js | 8 ++-- src/libs/sanitizeStringForJSONParse.js | 30 ++++++++++++ .../sanitizeStringForGitLogJSONParseTest.js | 48 +++++++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 src/libs/sanitizeStringForJSONParse.js create mode 100644 tests/unit/sanitizeStringForGitLogJSONParseTest.js diff --git a/.github/libs/GitUtils.js b/.github/libs/GitUtils.js index 2b740bd0617..73461c851c4 100644 --- a/.github/libs/GitUtils.js +++ b/.github/libs/GitUtils.js @@ -1,5 +1,6 @@ const _ = require('underscore'); const {spawn} = require('child_process'); +const sanitizeStringForJSONParse = require('../../src/libs/sanitizeStringForJSONParse'); /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -35,11 +36,8 @@ function getMergeLogsAsJSON(fromRef, toRef) { spawnedProcess.on('error', err => reject(err)); }) .then((stdout) => { - // Remove any double-quotes from commit subjects - let sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => subject.replace(/"/g, "'")); - - // Also remove any newlines and escape backslashes - sanitizedOutput = sanitizedOutput.replace(/(\r\n|\n|\r)/gm, '').replace(/\\/g, '\\\\'); + // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. + const sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => sanitizeStringForJSONParse(subject)); // Then format as JSON and convert to a proper JS object const json = `[${sanitizedOutput}]`.replace('},]', '}]'); diff --git a/src/libs/sanitizeStringForJSONParse.js b/src/libs/sanitizeStringForJSONParse.js new file mode 100644 index 00000000000..824a2f8ad09 --- /dev/null +++ b/src/libs/sanitizeStringForJSONParse.js @@ -0,0 +1,30 @@ +const replacer = str => ({ + '\\': '\\\\', + '\t': '\\t', + '\n': '\\n', + '\r': '\\r', + '\f': '\\f', + '"': '\\"', +}[str]); + +/** + * Replace any characters in the string that will break JSON.parse for our Git Log output + * + * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 + * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading + * + * @param {String} inputString + * @returns {String} + */ +function sanitizeStringForJSONParse(inputString) { + if (!inputString || typeof inputString !== 'string') { + return ''; + } + + return inputString + + // Replace any newlines and escape backslashes + .replace(/\\|\t|\n|\r|\f|"/g, replacer); +} + +export default sanitizeStringForJSONParse; diff --git a/tests/unit/sanitizeStringForGitLogJSONParseTest.js b/tests/unit/sanitizeStringForGitLogJSONParseTest.js new file mode 100644 index 00000000000..b25d7104892 --- /dev/null +++ b/tests/unit/sanitizeStringForGitLogJSONParseTest.js @@ -0,0 +1,48 @@ +import sanitizeStringForJSONParse from '../../src/libs/sanitizeStringForJSONParse'; + +const badInputs = [ + ['', ''], + [null, ''], + [undefined, ''], + [42, ''], + [true, ''], +]; + +// Invalid JSON Data should be able to get parsed and the parsed result should match the input text. +const invalidJSONData = [ + ['Hello \t world!', 'Hello \t world!'], + ['Hello \n world!', 'Hello \n world!'], + ['Hello \n\tworld!', 'Hello \n\tworld!'], + ['Hello \\', 'Hello \\'], + ['"Hello world!"', '"Hello world!"'], +]; + +const validJSONData = [ + ['Hello world!', 'Hello world!'], + ['Hello\\\\world!', 'Hello\\\\world!'], +]; + +describe('santizeStringForJSONParse', () => { + describe.each(badInputs)('canHandleBadInputs', (input, expectedOutput) => { + test('sanitizeStringForJSONParse', () => { + const result = sanitizeStringForJSONParse(input); + expect(result).toStrictEqual(expectedOutput); + }); + }); + + describe.each(invalidJSONData)('canHandleInvalidJSON', (input, expectedOutput) => { + test('sanitizeStringForJSONParse', () => { + const badJSON = `{"key": "${input}"}`; + expect(() => JSON.parse(badJSON)).toThrow(); + const goodJSON = JSON.parse(`{"key": "${sanitizeStringForJSONParse(input)}"}`); + expect(goodJSON.key).toStrictEqual(expectedOutput); + }); + }); + + describe.each(validJSONData)('canHandleValidJSON', (input, expectedOutput) => { + test('sanitizeStringForJSONParse', () => { + const goodJSON = JSON.parse(`{"key": "${sanitizeStringForJSONParse(input)}"}`); + expect(goodJSON.key).toStrictEqual(expectedOutput); + }); + }); +}); From 5e22faa6e0189bf1f592129a6ad2bfe1b598e714 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 16 Jan 2023 16:59:21 -0800 Subject: [PATCH 02/15] Rename test to match function --- ...GitLogJSONParseTest.js => sanitizeStringForJSONParseTest.js} | 2 ++ 1 file changed, 2 insertions(+) rename tests/unit/{sanitizeStringForGitLogJSONParseTest.js => sanitizeStringForJSONParseTest.js} (91%) diff --git a/tests/unit/sanitizeStringForGitLogJSONParseTest.js b/tests/unit/sanitizeStringForJSONParseTest.js similarity index 91% rename from tests/unit/sanitizeStringForGitLogJSONParseTest.js rename to tests/unit/sanitizeStringForJSONParseTest.js index b25d7104892..5d41b5ef682 100644 --- a/tests/unit/sanitizeStringForGitLogJSONParseTest.js +++ b/tests/unit/sanitizeStringForJSONParseTest.js @@ -1,5 +1,6 @@ import sanitizeStringForJSONParse from '../../src/libs/sanitizeStringForJSONParse'; +// Bad inputs should just be ignored and an empty string returned. const badInputs = [ ['', ''], [null, ''], @@ -17,6 +18,7 @@ const invalidJSONData = [ ['"Hello world!"', '"Hello world!"'], ]; +// Valid JSON Data should be able to get parsed and the input text should be unmodified. const validJSONData = [ ['Hello world!', 'Hello world!'], ['Hello\\\\world!', 'Hello\\\\world!'], From 594f9ef583aa52c391b175509a3fe1b86915ba70 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 16 Jan 2023 17:18:33 -0800 Subject: [PATCH 03/15] Add real-life examples for tests --- src/libs/sanitizeStringForJSONParse.js | 6 ++---- tests/unit/sanitizeStringForJSONParseTest.js | 10 +++++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/libs/sanitizeStringForJSONParse.js b/src/libs/sanitizeStringForJSONParse.js index 824a2f8ad09..39952d868d8 100644 --- a/src/libs/sanitizeStringForJSONParse.js +++ b/src/libs/sanitizeStringForJSONParse.js @@ -21,10 +21,8 @@ function sanitizeStringForJSONParse(inputString) { return ''; } - return inputString - - // Replace any newlines and escape backslashes - .replace(/\\|\t|\n|\r|\f|"/g, replacer); + // Replace any newlines and escape backslashes + return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); } export default sanitizeStringForJSONParse; diff --git a/tests/unit/sanitizeStringForJSONParseTest.js b/tests/unit/sanitizeStringForJSONParseTest.js index 5d41b5ef682..ccbe8bef464 100644 --- a/tests/unit/sanitizeStringForJSONParseTest.js +++ b/tests/unit/sanitizeStringForJSONParseTest.js @@ -14,8 +14,16 @@ const invalidJSONData = [ ['Hello \t world!', 'Hello \t world!'], ['Hello \n world!', 'Hello \n world!'], ['Hello \n\tworld!', 'Hello \n\tworld!'], - ['Hello \\', 'Hello \\'], ['"Hello world!"', '"Hello world!"'], + ['Test "', 'Test "'], + ['something `\\ something', 'something `\\ something'], + + // Real-life examples from git commits that broke getMergeLogsAsJSON + // From https://github.com/Expensify/App/commit/e472470893867648cfbd85a5c2c5d24da1efece6 + ['Add \\', 'Add \\'], + + // From https://github.com/Expensify/App/pull/13500/commits/b730d5c43643f32baa3b189f0238f4de61aae0b7 + ['Prevent commit messages that end in `\\` from breaking `getMergeLogsAsJSON()`', 'Prevent commit messages that end in `\\` from breaking `getMergeLogsAsJSON()`'], ]; // Valid JSON Data should be able to get parsed and the input text should be unmodified. From 8c5c5fd5cc0ac2558c7eb12db1e7563719a893c8 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 16 Jan 2023 17:22:51 -0800 Subject: [PATCH 04/15] Build GH Actions --- .../createOrUpdateStagingDeploy/index.js | 48 +++++++++++++++++-- .../getDeployPullRequestList/index.js | 48 +++++++++++++++++-- 2 files changed, 86 insertions(+), 10 deletions(-) diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index 05af05a9954..ccc35df5d93 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -194,6 +194,7 @@ module.exports = run; const _ = __nccwpck_require__(3571); const {spawn} = __nccwpck_require__(3129); +const sanitizeStringForJSONParse = __nccwpck_require__(8989); /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -229,11 +230,8 @@ function getMergeLogsAsJSON(fromRef, toRef) { spawnedProcess.on('error', err => reject(err)); }) .then((stdout) => { - // Remove any double-quotes from commit subjects - let sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => subject.replace(/"/g, "'")); - - // Also remove any newlines and escape backslashes - sanitizedOutput = sanitizedOutput.replace(/(\r\n|\n|\r)/gm, '').replace(/\\/g, '\\\\'); + // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. + const sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => sanitizeStringForJSONParse(subject)); // Then format as JSON and convert to a proper JS object const json = `[${sanitizedOutput}]`.replace('},]', '}]'); @@ -19298,6 +19296,46 @@ function wrappy (fn, cb) { } +/***/ }), + +/***/ 8989: +/***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { + +"use strict"; +__nccwpck_require__.r(__webpack_exports__); +/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__ +/* harmony export */ }); +const replacer = str => ({ + '\\': '\\\\', + '\t': '\\t', + '\n': '\\n', + '\r': '\\r', + '\f': '\\f', + '"': '\\"', +}[str]); + +/** + * Replace any characters in the string that will break JSON.parse for our Git Log output + * + * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 + * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading + * + * @param {String} inputString + * @returns {String} + */ +function sanitizeStringForJSONParse(inputString) { + if (!inputString || typeof inputString !== 'string') { + return ''; + } + + // Replace any newlines and escape backslashes + return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); +} + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (sanitizeStringForJSONParse); + + /***/ }), /***/ 2877: diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index f85b4dab709..b558ce89e2b 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -127,6 +127,7 @@ module.exports = { const _ = __nccwpck_require__(3571); const {spawn} = __nccwpck_require__(3129); +const sanitizeStringForJSONParse = __nccwpck_require__(8989); /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -162,11 +163,8 @@ function getMergeLogsAsJSON(fromRef, toRef) { spawnedProcess.on('error', err => reject(err)); }) .then((stdout) => { - // Remove any double-quotes from commit subjects - let sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => subject.replace(/"/g, "'")); - - // Also remove any newlines and escape backslashes - sanitizedOutput = sanitizedOutput.replace(/(\r\n|\n|\r)/gm, '').replace(/\\/g, '\\\\'); + // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. + const sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => sanitizeStringForJSONParse(subject)); // Then format as JSON and convert to a proper JS object const json = `[${sanitizedOutput}]`.replace('},]', '}]'); @@ -13583,6 +13581,46 @@ function wrappy (fn, cb) { } +/***/ }), + +/***/ 8989: +/***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { + +"use strict"; +__nccwpck_require__.r(__webpack_exports__); +/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__ +/* harmony export */ }); +const replacer = str => ({ + '\\': '\\\\', + '\t': '\\t', + '\n': '\\n', + '\r': '\\r', + '\f': '\\f', + '"': '\\"', +}[str]); + +/** + * Replace any characters in the string that will break JSON.parse for our Git Log output + * + * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 + * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading + * + * @param {String} inputString + * @returns {String} + */ +function sanitizeStringForJSONParse(inputString) { + if (!inputString || typeof inputString !== 'string') { + return ''; + } + + // Replace any newlines and escape backslashes + return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); +} + +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (sanitizeStringForJSONParse); + + /***/ }), /***/ 2877: From ce5e7912a91f9289b690fd787df09d4c7f5c9359 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 16 Jan 2023 17:28:30 -0800 Subject: [PATCH 05/15] Fix export --- .../actions/javascript/createOrUpdateStagingDeploy/index.js | 6 ++---- .../actions/javascript/getDeployPullRequestList/index.js | 6 ++---- src/libs/sanitizeStringForJSONParse.js | 4 +--- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index ccc35df5d93..624ce97f33e 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -19304,7 +19304,7 @@ function wrappy (fn, cb) { "use strict"; __nccwpck_require__.r(__webpack_exports__); /* harmony export */ __nccwpck_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__ +/* harmony export */ "default": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__ /* harmony export */ }); const replacer = str => ({ '\\': '\\\\', @@ -19324,7 +19324,7 @@ const replacer = str => ({ * @param {String} inputString * @returns {String} */ -function sanitizeStringForJSONParse(inputString) { +/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(inputString) { if (!inputString || typeof inputString !== 'string') { return ''; } @@ -19333,8 +19333,6 @@ function sanitizeStringForJSONParse(inputString) { return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); } -/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (sanitizeStringForJSONParse); - /***/ }), diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index b558ce89e2b..c2659e0fc50 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -13589,7 +13589,7 @@ function wrappy (fn, cb) { "use strict"; __nccwpck_require__.r(__webpack_exports__); /* harmony export */ __nccwpck_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => __WEBPACK_DEFAULT_EXPORT__ +/* harmony export */ "default": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__ /* harmony export */ }); const replacer = str => ({ '\\': '\\\\', @@ -13609,7 +13609,7 @@ const replacer = str => ({ * @param {String} inputString * @returns {String} */ -function sanitizeStringForJSONParse(inputString) { +/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(inputString) { if (!inputString || typeof inputString !== 'string') { return ''; } @@ -13618,8 +13618,6 @@ function sanitizeStringForJSONParse(inputString) { return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); } -/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (sanitizeStringForJSONParse); - /***/ }), diff --git a/src/libs/sanitizeStringForJSONParse.js b/src/libs/sanitizeStringForJSONParse.js index 39952d868d8..7282dd2b7fc 100644 --- a/src/libs/sanitizeStringForJSONParse.js +++ b/src/libs/sanitizeStringForJSONParse.js @@ -16,7 +16,7 @@ const replacer = str => ({ * @param {String} inputString * @returns {String} */ -function sanitizeStringForJSONParse(inputString) { +export default function (inputString) { if (!inputString || typeof inputString !== 'string') { return ''; } @@ -24,5 +24,3 @@ function sanitizeStringForJSONParse(inputString) { // Replace any newlines and escape backslashes return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); } - -export default sanitizeStringForJSONParse; From 2ff32527c39db374cb01fb26e67a393acdea686b Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 16 Jan 2023 17:39:13 -0800 Subject: [PATCH 06/15] Update .github/libs/GitUtils.js Co-authored-by: Rory Abraham <47436092+roryabraham@users.noreply.github.com> --- .github/libs/GitUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/libs/GitUtils.js b/.github/libs/GitUtils.js index 73461c851c4..da01dbe00a4 100644 --- a/.github/libs/GitUtils.js +++ b/.github/libs/GitUtils.js @@ -1,6 +1,6 @@ const _ = require('underscore'); const {spawn} = require('child_process'); -const sanitizeStringForJSONParse = require('../../src/libs/sanitizeStringForJSONParse'); +const sanitizeStringForJSONParse = require('../../src/libs/sanitizeStringForJSONParse').default; /** * Get merge logs between two refs (inclusive) as a JavaScript object. From 8ccffbfacd3d04a63c7d11dabc4c24f9f4bc5dc0 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 16 Jan 2023 17:41:32 -0800 Subject: [PATCH 07/15] Buld GH actions again --- .../actions/javascript/createOrUpdateStagingDeploy/index.js | 5 ++--- .github/actions/javascript/getDeployPullRequestList/index.js | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index 624ce97f33e..950ed6ceff3 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -194,7 +194,7 @@ module.exports = run; const _ = __nccwpck_require__(3571); const {spawn} = __nccwpck_require__(3129); -const sanitizeStringForJSONParse = __nccwpck_require__(8989); +const sanitizeStringForJSONParse = __nccwpck_require__(8989)/* .default */ .Z; /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -19302,9 +19302,8 @@ function wrappy (fn, cb) { /***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { "use strict"; -__nccwpck_require__.r(__webpack_exports__); /* harmony export */ __nccwpck_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__ +/* harmony export */ "Z": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__ /* harmony export */ }); const replacer = str => ({ '\\': '\\\\', diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index c2659e0fc50..9f9ced23412 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -127,7 +127,7 @@ module.exports = { const _ = __nccwpck_require__(3571); const {spawn} = __nccwpck_require__(3129); -const sanitizeStringForJSONParse = __nccwpck_require__(8989); +const sanitizeStringForJSONParse = __nccwpck_require__(8989)/* .default */ .Z; /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -13587,9 +13587,8 @@ function wrappy (fn, cb) { /***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { "use strict"; -__nccwpck_require__.r(__webpack_exports__); /* harmony export */ __nccwpck_require__.d(__webpack_exports__, { -/* harmony export */ "default": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__ +/* harmony export */ "Z": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__ /* harmony export */ }); const replacer = str => ({ '\\': '\\\\', From ae96b14aa920f8a6afc04891ebdee9296ab57836 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 17 Jan 2023 10:17:24 -0800 Subject: [PATCH 08/15] Throw instead of returning empty string --- src/libs/sanitizeStringForJSONParse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/sanitizeStringForJSONParse.js b/src/libs/sanitizeStringForJSONParse.js index 7282dd2b7fc..d244362ae7a 100644 --- a/src/libs/sanitizeStringForJSONParse.js +++ b/src/libs/sanitizeStringForJSONParse.js @@ -18,7 +18,7 @@ const replacer = str => ({ */ export default function (inputString) { if (!inputString || typeof inputString !== 'string') { - return ''; + throw new TypeError('Input must me of type String'); } // Replace any newlines and escape backslashes From f76f05a8fcc92eb59c39e226c81dca1e94a288e1 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 17 Jan 2023 10:41:09 -0800 Subject: [PATCH 09/15] Move to .github/libs --- .../libs/sanitizeStringForJSONParse.js | 4 ++-- tests/unit/sanitizeStringForJSONParseTest.js | 19 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) rename {src => .github}/libs/sanitizeStringForJSONParse.js (87%) diff --git a/src/libs/sanitizeStringForJSONParse.js b/.github/libs/sanitizeStringForJSONParse.js similarity index 87% rename from src/libs/sanitizeStringForJSONParse.js rename to .github/libs/sanitizeStringForJSONParse.js index d244362ae7a..d62c48f5e0a 100644 --- a/src/libs/sanitizeStringForJSONParse.js +++ b/.github/libs/sanitizeStringForJSONParse.js @@ -16,8 +16,8 @@ const replacer = str => ({ * @param {String} inputString * @returns {String} */ -export default function (inputString) { - if (!inputString || typeof inputString !== 'string') { +module.exports = function (inputString) { + if (typeof inputString !== 'string') { throw new TypeError('Input must me of type String'); } diff --git a/tests/unit/sanitizeStringForJSONParseTest.js b/tests/unit/sanitizeStringForJSONParseTest.js index ccbe8bef464..66a9d6ad229 100644 --- a/tests/unit/sanitizeStringForJSONParseTest.js +++ b/tests/unit/sanitizeStringForJSONParseTest.js @@ -1,12 +1,11 @@ -import sanitizeStringForJSONParse from '../../src/libs/sanitizeStringForJSONParse'; +import sanitizeStringForJSONParse from '../../.github/libs/sanitizeStringForJSONParse'; -// Bad inputs should just be ignored and an empty string returned. +// Bad inputs should cause an error to be thrown const badInputs = [ - ['', ''], - [null, ''], - [undefined, ''], - [42, ''], - [true, ''], + null, + undefined, + 42, + true, ]; // Invalid JSON Data should be able to get parsed and the parsed result should match the input text. @@ -28,15 +27,15 @@ const invalidJSONData = [ // Valid JSON Data should be able to get parsed and the input text should be unmodified. const validJSONData = [ + ['', ''], ['Hello world!', 'Hello world!'], ['Hello\\\\world!', 'Hello\\\\world!'], ]; describe('santizeStringForJSONParse', () => { - describe.each(badInputs)('canHandleBadInputs', (input, expectedOutput) => { + describe.each(badInputs)('willDetectBadInputs', (input) => { test('sanitizeStringForJSONParse', () => { - const result = sanitizeStringForJSONParse(input); - expect(result).toStrictEqual(expectedOutput); + expect(() => sanitizeStringForJSONParse(input)).toThrow(); }); }); From aa96a2924edad40f34d2baf5a4b02d10ce996a0b Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 17 Jan 2023 10:42:50 -0800 Subject: [PATCH 10/15] build gh actions --- .../createOrUpdateStagingDeploy/index.js | 37 ++----------------- .../getDeployPullRequestList/index.js | 37 ++----------------- 2 files changed, 8 insertions(+), 66 deletions(-) diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index 950ed6ceff3..0ccab96838b 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -194,7 +194,7 @@ module.exports = run; const _ = __nccwpck_require__(3571); const {spawn} = __nccwpck_require__(3129); -const sanitizeStringForJSONParse = __nccwpck_require__(8989)/* .default */ .Z; +const sanitizeStringForJSONParse = __nccwpck_require__(1089).default; /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -19298,39 +19298,10 @@ function wrappy (fn, cb) { /***/ }), -/***/ 8989: -/***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { - -"use strict"; -/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { -/* harmony export */ "Z": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__ -/* harmony export */ }); -const replacer = str => ({ - '\\': '\\\\', - '\t': '\\t', - '\n': '\\n', - '\r': '\\r', - '\f': '\\f', - '"': '\\"', -}[str]); - -/** - * Replace any characters in the string that will break JSON.parse for our Git Log output - * - * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 - * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading - * - * @param {String} inputString - * @returns {String} - */ -/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(inputString) { - if (!inputString || typeof inputString !== 'string') { - return ''; - } +/***/ 1089: +/***/ ((module) => { - // Replace any newlines and escape backslashes - return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); -} +module.exports = eval("require")("../../src/libs/sanitizeStringForJSONParse"); /***/ }), diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index 9f9ced23412..fe308993422 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -127,7 +127,7 @@ module.exports = { const _ = __nccwpck_require__(3571); const {spawn} = __nccwpck_require__(3129); -const sanitizeStringForJSONParse = __nccwpck_require__(8989)/* .default */ .Z; +const sanitizeStringForJSONParse = __nccwpck_require__(1089).default; /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -13583,39 +13583,10 @@ function wrappy (fn, cb) { /***/ }), -/***/ 8989: -/***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { - -"use strict"; -/* harmony export */ __nccwpck_require__.d(__webpack_exports__, { -/* harmony export */ "Z": () => /* export default binding */ __WEBPACK_DEFAULT_EXPORT__ -/* harmony export */ }); -const replacer = str => ({ - '\\': '\\\\', - '\t': '\\t', - '\n': '\\n', - '\r': '\\r', - '\f': '\\f', - '"': '\\"', -}[str]); - -/** - * Replace any characters in the string that will break JSON.parse for our Git Log output - * - * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 - * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading - * - * @param {String} inputString - * @returns {String} - */ -/* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(inputString) { - if (!inputString || typeof inputString !== 'string') { - return ''; - } +/***/ 1089: +/***/ ((module) => { - // Replace any newlines and escape backslashes - return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); -} +module.exports = eval("require")("../../src/libs/sanitizeStringForJSONParse"); /***/ }), From 69cab50056e9b829c1b7fcf22ef1356976df977d Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 17 Jan 2023 10:47:27 -0800 Subject: [PATCH 11/15] Correct import --- .github/libs/GitUtils.js | 2 +- .github/libs/promiseWhile.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/libs/GitUtils.js b/.github/libs/GitUtils.js index da01dbe00a4..eb86eef09ff 100644 --- a/.github/libs/GitUtils.js +++ b/.github/libs/GitUtils.js @@ -1,6 +1,6 @@ const _ = require('underscore'); const {spawn} = require('child_process'); -const sanitizeStringForJSONParse = require('../../src/libs/sanitizeStringForJSONParse').default; +const sanitizeStringForJSONParse = require('./sanitizeStringForJSONParse'); /** * Get merge logs between two refs (inclusive) as a JavaScript object. diff --git a/.github/libs/promiseWhile.js b/.github/libs/promiseWhile.js index 1ae57355386..9205bedacfa 100644 --- a/.github/libs/promiseWhile.js +++ b/.github/libs/promiseWhile.js @@ -5,7 +5,7 @@ * @param {Function} action * @returns {Promise} */ -function promiseWhile(condition, action) { +function g(condition, action) { return new Promise((resolve, reject) => { const loop = function () { if (!condition()) { From 97cd948bdbee7eb2c099e01e7dd1b87f61948f3a Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 17 Jan 2023 10:50:37 -0800 Subject: [PATCH 12/15] build GH Actions --- .../createOrUpdateStagingDeploy/index.js | 43 +++++++++++++++---- .../getDeployPullRequestList/index.js | 43 +++++++++++++++---- .github/libs/promiseWhile.js | 2 +- 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index 0ccab96838b..99509252ee0 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -194,7 +194,7 @@ module.exports = run; const _ = __nccwpck_require__(3571); const {spawn} = __nccwpck_require__(3129); -const sanitizeStringForJSONParse = __nccwpck_require__(1089).default; +const sanitizeStringForJSONParse = __nccwpck_require__(9338); /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -859,6 +859,39 @@ module.exports.ISSUE_OR_PULL_REQUEST_REGEX = ISSUE_OR_PULL_REQUEST_REGEX; module.exports.POLL_RATE = POLL_RATE; +/***/ }), + +/***/ 9338: +/***/ ((module) => { + +const replacer = str => ({ + '\\': '\\\\', + '\t': '\\t', + '\n': '\\n', + '\r': '\\r', + '\f': '\\f', + '"': '\\"', +}[str]); + +/** + * Replace any characters in the string that will break JSON.parse for our Git Log output + * + * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 + * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading + * + * @param {String} inputString + * @returns {String} + */ +module.exports = function (inputString) { + if (typeof inputString !== 'string') { + throw new TypeError('Input must me of type String'); + } + + // Replace any newlines and escape backslashes + return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); +} + + /***/ }), /***/ 7351: @@ -19296,14 +19329,6 @@ function wrappy (fn, cb) { } -/***/ }), - -/***/ 1089: -/***/ ((module) => { - -module.exports = eval("require")("../../src/libs/sanitizeStringForJSONParse"); - - /***/ }), /***/ 2877: diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index fe308993422..c1b277bf36c 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -127,7 +127,7 @@ module.exports = { const _ = __nccwpck_require__(3571); const {spawn} = __nccwpck_require__(3129); -const sanitizeStringForJSONParse = __nccwpck_require__(1089).default; +const sanitizeStringForJSONParse = __nccwpck_require__(9338); /** * Get merge logs between two refs (inclusive) as a JavaScript object. @@ -792,6 +792,39 @@ module.exports.ISSUE_OR_PULL_REQUEST_REGEX = ISSUE_OR_PULL_REQUEST_REGEX; module.exports.POLL_RATE = POLL_RATE; +/***/ }), + +/***/ 9338: +/***/ ((module) => { + +const replacer = str => ({ + '\\': '\\\\', + '\t': '\\t', + '\n': '\\n', + '\r': '\\r', + '\f': '\\f', + '"': '\\"', +}[str]); + +/** + * Replace any characters in the string that will break JSON.parse for our Git Log output + * + * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 + * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading + * + * @param {String} inputString + * @returns {String} + */ +module.exports = function (inputString) { + if (typeof inputString !== 'string') { + throw new TypeError('Input must me of type String'); + } + + // Replace any newlines and escape backslashes + return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); +} + + /***/ }), /***/ 7351: @@ -13581,14 +13614,6 @@ function wrappy (fn, cb) { } -/***/ }), - -/***/ 1089: -/***/ ((module) => { - -module.exports = eval("require")("../../src/libs/sanitizeStringForJSONParse"); - - /***/ }), /***/ 2877: diff --git a/.github/libs/promiseWhile.js b/.github/libs/promiseWhile.js index 9205bedacfa..1ae57355386 100644 --- a/.github/libs/promiseWhile.js +++ b/.github/libs/promiseWhile.js @@ -5,7 +5,7 @@ * @param {Function} action * @returns {Promise} */ -function g(condition, action) { +function promiseWhile(condition, action) { return new Promise((resolve, reject) => { const loop = function () { if (!condition()) { From 9b0f53cb24aacdc6eb9ed19dc189c8f1be965f3b Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 17 Jan 2023 10:55:06 -0800 Subject: [PATCH 13/15] Add missing semicolon --- .github/actions/javascript/createOrUpdateStagingDeploy/index.js | 2 +- .github/actions/javascript/getDeployPullRequestList/index.js | 2 +- .github/libs/sanitizeStringForJSONParse.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index 99509252ee0..bff6bb03544 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -889,7 +889,7 @@ module.exports = function (inputString) { // Replace any newlines and escape backslashes return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); -} +}; /***/ }), diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index c1b277bf36c..ca456e3d8b9 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -822,7 +822,7 @@ module.exports = function (inputString) { // Replace any newlines and escape backslashes return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); -} +}; /***/ }), diff --git a/.github/libs/sanitizeStringForJSONParse.js b/.github/libs/sanitizeStringForJSONParse.js index d62c48f5e0a..ed672e7f284 100644 --- a/.github/libs/sanitizeStringForJSONParse.js +++ b/.github/libs/sanitizeStringForJSONParse.js @@ -23,4 +23,4 @@ module.exports = function (inputString) { // Replace any newlines and escape backslashes return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); -} +}; From 8dd8b30640c4b1d561165148cb1a583939ff8433 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 17 Jan 2023 11:36:58 -0800 Subject: [PATCH 14/15] Don't be greedy --- .github/actions/javascript/createOrUpdateStagingDeploy/index.js | 2 +- .github/actions/javascript/getDeployPullRequestList/index.js | 2 +- .github/libs/GitUtils.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index bff6bb03544..c4c351effec 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -231,7 +231,7 @@ function getMergeLogsAsJSON(fromRef, toRef) { }) .then((stdout) => { // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. - const sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => sanitizeStringForJSONParse(subject)); + const sanitizedOutput = stdout.replace(/(?<="subject": ").*?(?="})/g, subject => sanitizeStringForJSONParse(subject)); // Then format as JSON and convert to a proper JS object const json = `[${sanitizedOutput}]`.replace('},]', '}]'); diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index ca456e3d8b9..599e3d4787f 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -164,7 +164,7 @@ function getMergeLogsAsJSON(fromRef, toRef) { }) .then((stdout) => { // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. - const sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => sanitizeStringForJSONParse(subject)); + const sanitizedOutput = stdout.replace(/(?<="subject": ").*?(?="})/g, subject => sanitizeStringForJSONParse(subject)); // Then format as JSON and convert to a proper JS object const json = `[${sanitizedOutput}]`.replace('},]', '}]'); diff --git a/.github/libs/GitUtils.js b/.github/libs/GitUtils.js index eb86eef09ff..b695519f0fc 100644 --- a/.github/libs/GitUtils.js +++ b/.github/libs/GitUtils.js @@ -37,7 +37,7 @@ function getMergeLogsAsJSON(fromRef, toRef) { }) .then((stdout) => { // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. - const sanitizedOutput = stdout.replace(/(?<="subject": ").*(?="})/g, subject => sanitizeStringForJSONParse(subject)); + const sanitizedOutput = stdout.replace(/(?<="subject": ").*?(?="})/g, subject => sanitizeStringForJSONParse(subject)); // Then format as JSON and convert to a proper JS object const json = `[${sanitizedOutput}]`.replace('},]', '}]'); From b909655d24e3afee952205bb49ff225544cd2a6b Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 17 Jan 2023 11:49:44 -0800 Subject: [PATCH 15/15] remove newlines before replacing end bracket --- .../actions/javascript/createOrUpdateStagingDeploy/index.js | 4 ++-- .github/actions/javascript/getDeployPullRequestList/index.js | 4 ++-- .github/libs/GitUtils.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index c4c351effec..3f2b813dd8c 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -233,8 +233,8 @@ function getMergeLogsAsJSON(fromRef, toRef) { // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. const sanitizedOutput = stdout.replace(/(?<="subject": ").*?(?="})/g, subject => sanitizeStringForJSONParse(subject)); - // Then format as JSON and convert to a proper JS object - const json = `[${sanitizedOutput}]`.replace('},]', '}]'); + // Then remove newlines, format as JSON and convert to a proper JS object + const json = `[${sanitizedOutput}]`.replace(/(\r\n|\n|\r)/gm, '').replace('},]', '}]'); return JSON.parse(json); }); diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index 599e3d4787f..1c8909bdc76 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -166,8 +166,8 @@ function getMergeLogsAsJSON(fromRef, toRef) { // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. const sanitizedOutput = stdout.replace(/(?<="subject": ").*?(?="})/g, subject => sanitizeStringForJSONParse(subject)); - // Then format as JSON and convert to a proper JS object - const json = `[${sanitizedOutput}]`.replace('},]', '}]'); + // Then remove newlines, format as JSON and convert to a proper JS object + const json = `[${sanitizedOutput}]`.replace(/(\r\n|\n|\r)/gm, '').replace('},]', '}]'); return JSON.parse(json); }); diff --git a/.github/libs/GitUtils.js b/.github/libs/GitUtils.js index b695519f0fc..c36a82a4056 100644 --- a/.github/libs/GitUtils.js +++ b/.github/libs/GitUtils.js @@ -39,8 +39,8 @@ function getMergeLogsAsJSON(fromRef, toRef) { // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. const sanitizedOutput = stdout.replace(/(?<="subject": ").*?(?="})/g, subject => sanitizeStringForJSONParse(subject)); - // Then format as JSON and convert to a proper JS object - const json = `[${sanitizedOutput}]`.replace('},]', '}]'); + // Then remove newlines, format as JSON and convert to a proper JS object + const json = `[${sanitizedOutput}]`.replace(/(\r\n|\n|\r)/gm, '').replace('},]', '}]'); return JSON.parse(json); });