From 3dfc7d92e01e241f426cba49b3a986096e030f1c Mon Sep 17 00:00:00 2001 From: alaisgomes Date: Fri, 26 Apr 2024 12:50:36 -0400 Subject: [PATCH 1/3] PLAT-13615: use downloaded cache of the demo app --- config.js | 3 ++- index.js | 15 +++-------- package.json | 3 ++- scripts/demo.js | 58 +++++++++++++------------------------------ yarn.lock | 66 ++++++++++++++++++++++++++++++++++++++----------- 5 files changed, 77 insertions(+), 68 deletions(-) diff --git a/config.js b/config.js index 064c994..167bdce 100644 --- a/config.js +++ b/config.js @@ -14,7 +14,8 @@ export default { CROWDBOTICS_FILE: ".crowdbotics.json", COOKIECUTTER_PACKAGE: "cookiecutter==1.7.3", REACT_NATIVE_SCAFFOLD_REPO_ORIGIN: - "https://github.com/crowdbotics/react-native-scaffold" + "https://github.com/crowdbotics/react-native-scaffold", + DJANGO_SCAFFOLD_REPO_ORIGIN: "https://github.com/crowdbotics/django-scaffold" }, scaffold: { directory: SCAFFOLD_DIRECTORY diff --git a/index.js b/index.js index 86eb6cf..188e56d 100755 --- a/index.js +++ b/index.js @@ -107,14 +107,9 @@ async function dispatcher() { const commands = { demo: () => { - validateEnvironmentDependencies([ - EnvironmentDependency.Python, - EnvironmentDependency.PipEnv - ]); createDemo( path.join(gitRoot(), "demo"), - path.join(sourceDir, "cookiecutter.yaml") - ); + "PLAT-13615", // TODO: change this before merging. Check if we can use environment variables valid("demo app successfully generated"); }, parse: () => { @@ -169,10 +164,7 @@ const commands = { removeModules(modules, args["--source"], args["--project"], gitRoot()); }, create: () => { - validateEnvironmentDependencies([ - EnvironmentDependency.Python, - EnvironmentDependency.CookieCutter - ]); + validateEnvironmentDependencies([EnvironmentDependency.Python]); const args = arg({ "--name": String, @@ -352,7 +344,8 @@ demo`; ); } - await setModuleDetails(id, + await setModuleDetails( + id, args["--name"], args["--description"], args["--acceptance-criteria"], diff --git a/package.json b/package.json index 2b23c0f..d774a3c 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,8 @@ "js-yaml": "^4.1.0", "node-fetch": "^3.3.2", "ora": "^7.0.1", - "prettier": "^2.6.2" + "prettier": "^2.6.2", + "unzipper": "^0.11.4" }, "resolutions": { "shell-quote": "1.7.3" diff --git a/scripts/demo.js b/scripts/demo.js index a8ec2ef..96fb75e 100644 --- a/scripts/demo.js +++ b/scripts/demo.js @@ -1,51 +1,27 @@ import path from "path"; import fs from "fs"; -import fse from "fs-extra"; -import { section, generateCommand } from "../utils.js"; -import { execSync } from "child_process"; -import { configurePython, execOptions } from "./utils/environment.js"; +import { section } from "../utils.js"; +import fetch from "node-fetch"; +import config from "../config.js"; +import unzipper from "unzipper"; -export function createDemo(dir, yaml) { - const options = Object.assign(execOptions, { - cwd: path.dirname(dir) - }); +async function downloadAndExtract(url, target) { + const rnResponse = await fetch(url); + if (rnResponse.ok && rnResponse.body) { + rnResponse.body.pipe(unzipper.Extract({ path: target })); + } +} + +export async function createDemo(dir, target = "master") { + const rnDemoUrl = `${config.constants.REACT_NATIVE_SCAFFOLD_REPO_ORIGIN}/raw/${target}/dist/react-native-demo.zip`; + const djangoDemoUrl = `${config.constants.DJANGO_SCAFFOLD_REPO_ORIGIN}/raw/${target}/dist/django-demo.zip`; if (fs.existsSync(dir)) { section("Removing previous demo app"); fs.rmSync(dir, { recursive: true }); } - section("Preparing environment"); - configurePython(); - execSync("pipenv install cookiecutter", options); - - section("Generating React Native app from scaffold"); - const rnCookieCutterCommand = generateCommand([ - "pipenv run cookiecutter", - "gh:crowdbotics/react-native-scaffold", - "--directory dist/cookie", - "--checkout master", - `--config-file ${yaml}`, - "--no-input" - ]); - execSync(rnCookieCutterCommand, options); - - section("Installing dependencies"); - execSync("yarn install", { - cwd: dir, - encoding: "utf8", - stdio: "inherit" - }); - - section("Generating Django app from scaffold"); - const djangoCookieCutterCommand = generateCommand([ - "pipenv run cookiecutter", - "gh:crowdbotics/django-scaffold", - "--checkout master", - `--config-file ${yaml}`, - `--output-dir ${path.basename(dir)}`, - "--no-input" - ]); - execSync(djangoCookieCutterCommand, options); - fse.moveSync(path.join(dir, path.basename(dir)), path.join(dir, "backend")); + fs.mkdirSync(dir, { recursive: true }); + await downloadAndExtract(rnDemoUrl, dir); + await downloadAndExtract(djangoDemoUrl, path.join(dir, "backend")); } diff --git a/yarn.lock b/yarn.lock index ba9f036..11e691d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2089,6 +2089,11 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +big-integer@^1.6.17: + version "1.6.52" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -2112,6 +2117,11 @@ bl@^5.0.0: inherits "^2.0.4" readable-stream "^3.4.0" +bluebird@~3.4.1: + version "3.4.7" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" + integrity sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2695,6 +2705,13 @@ dset@^3.1.2: resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.3.tgz#c194147f159841148e8e34ca41f638556d9542d2" integrity sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ== +duplexer2@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA== + dependencies: + readable-stream "^2.0.2" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -3364,6 +3381,16 @@ fsevents@^2.1.2, fsevents@^2.3.2, fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -3473,7 +3500,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -3641,7 +3668,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -5077,7 +5104,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.1: +"mkdirp@>=0.5 0", mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -5733,16 +5760,7 @@ react-shallow-renderer@^16.15.0: object-assign "^4.1.1" react-is "^16.12.0 || ^17.0.0 || ^18.0.0" -readable-stream@^3.4.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" - integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@~2.3.6: +readable-stream@^2.0.2, readable-stream@~2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== @@ -5755,6 +5773,15 @@ readable-stream@~2.3.6: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -5934,7 +5961,7 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@^2.5.4: +rimraf@2, rimraf@^2.5.4: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -6712,6 +6739,17 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +unzipper@^0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.11.4.tgz#cc15fb4efae1846e4dce4fcdb29855a87a52993c" + integrity sha512-T6CZQdmCMhlpHM+x4E5E9pIYCXH5INcrI8Cowr4tLQIciuw5nnp+X/LEwgeuFnay3vp9hVo4ydPw3WYSg2agWQ== + dependencies: + big-integer "^1.6.17" + bluebird "~3.4.1" + duplexer2 "~0.1.4" + fstream "^1.0.12" + graceful-fs "^4.2.2" + update-browserslist-db@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" From b1d78438b9fb96f4f677057c4682661d8965ea64 Mon Sep 17 00:00:00 2001 From: alaisgomes Date: Fri, 26 Apr 2024 16:17:29 -0400 Subject: [PATCH 2/3] update: improved error handling; add option to get the source branch --- index.js | 12 ++++++++---- scripts/demo.js | 2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 188e56d..554980c 100755 --- a/index.js +++ b/index.js @@ -106,10 +106,14 @@ async function dispatcher() { } const commands = { - demo: () => { - createDemo( - path.join(gitRoot(), "demo"), - "PLAT-13615", // TODO: change this before merging. Check if we can use environment variables + demo: async () => { + const args = arg({ + "--source": String + }); + + const { "--source": source = "master" } = args; + + await createDemo(path.join(gitRoot(), "demo"), source); valid("demo app successfully generated"); }, parse: () => { diff --git a/scripts/demo.js b/scripts/demo.js index 96fb75e..5db1af5 100644 --- a/scripts/demo.js +++ b/scripts/demo.js @@ -9,6 +9,8 @@ async function downloadAndExtract(url, target) { const rnResponse = await fetch(url); if (rnResponse.ok && rnResponse.body) { rnResponse.body.pipe(unzipper.Extract({ path: target })); + } else { + throw new Error("Failed to download scaffold for demo app."); } } From 9db1bd43cca55862d9fcfbda7685ed2b6f4e4cb7 Mon Sep 17 00:00:00 2001 From: alaisgomes Date: Mon, 29 Apr 2024 09:55:59 -0400 Subject: [PATCH 3/3] Minor update: use local error parsing function for async dispatcher --- index.js | 6 +++++- scripts/utils/sentry.js | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 554980c..5a1165e 100755 --- a/index.js +++ b/index.js @@ -499,7 +499,11 @@ Glossary: }; try { - dispatcher(); + dispatcher().catch((error) => { + sentryMonitoring.captureException(error); + invalid(error); + }); } catch (err) { + sentryMonitoring.captureException(err); invalid(err); } diff --git a/scripts/utils/sentry.js b/scripts/utils/sentry.js index 954df5c..4bf12c4 100644 --- a/scripts/utils/sentry.js +++ b/scripts/utils/sentry.js @@ -20,6 +20,14 @@ class SentryMonitoring { // Do nothing, but prevent any sentry errors from blocking commands from executing } } + + captureException(error) { + try { + Sentry.captureException(error); + } catch { + // Do nothing, but prevent any sentry errors from blocking commands from executing + } + } } export const sentryMonitoring = new SentryMonitoring();