Skip to content

Commit

Permalink
chore: Remove shelljs from appsmithctl (#37401)
Browse files Browse the repository at this point in the history
Remove `shelljs` dependency from `appsmithctl`, instead using our own
much smaller utility functions to run external commands.

Now `esbuild` should be able to build `appsmithctl` project nicely! For
a future PR.


## Automation

/test sanity

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/11854060567>
> Commit: d25bb8d
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=11854060567&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Sanity`
> Spec:
> <hr>Fri, 15 Nov 2024 10:27:05 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced an asynchronous database import process for improved
control flow and error handling.
- Added a new function to execute commands and return their output as a
promise.

- **Bug Fixes**
- Enhanced error handling to ensure the supervisor is running before
proceeding with database operations.

- **Tests**
- Added a new test suite for the command execution function, validating
various output scenarios.

- **Chores**
	- Removed unnecessary dependencies from the project configuration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Arpit Mohan <mohanarpit@users.noreply.github.com>
  • Loading branch information
sharat87 and mohanarpit authored Nov 15, 2024
1 parent 1c9e8c1 commit d6f6920
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 114 deletions.
71 changes: 36 additions & 35 deletions deploy/docker/fs/opt/appsmith/utils/bin/import_db.js
Original file line number Diff line number Diff line change
@@ -1,47 +1,50 @@
// Init function export mongodb
const shell = require('shelljs');
const readlineSync = require('readline-sync');
const process = require('process');
const Constants = require('./constants');
const utils = require('./utils');


function import_database() {
console.log('import_database ....')
dbUrl = utils.getDburl();
const cmd = `mongorestore --uri='${dbUrl}' --drop --archive='${Constants.RESTORE_PATH}/${Constants.DUMP_FILE_NAME}' --gzip`
shell.exec(cmd)
console.log('import_database done')
}

function stop_application() {
shell.exec('/usr/bin/supervisorctl stop backend rts')
}

function start_application() {
shell.exec('/usr/bin/supervisorctl start backend rts')
async function importDatabase() {
console.log("Importing the database");
try {
await utils.execCommand([
"mongorestore",
"--uri=" + utils.getDburl(),
"--drop",
`--archive=${Constants.RESTORE_PATH}/${Constants.DUMP_FILE_NAME}`,
"--gzip",
]);
} catch (error) {
console.error("Database import failed:", error);
throw error;
}
console.log("Imported the database successfully");
}

// Main application workflow
const main = (forceOption) => {
async function run(forceOption) {
let errorCode = 0
try {

check_supervisord_status_cmd = '/usr/bin/supervisorctl'
shell.exec(check_supervisord_status_cmd, function (code) {
if (code > 0) {
console.log('application is not running, starting supervisord')
shell.exec('/usr/bin/supervisord')
}
})
await utils.ensureSupervisorIsRunning();

try {
console.log('stop backend & rts application before import database')
stop_application()
const shellCmdResult = shell.exec(`mongo ${process.env.APPSMITH_DB_URL} --quiet --eval "db.getCollectionNames().length"`)
await utils.stop(["backend", "rts"]);
try {
const shellCmdResult = await utils.execCommandReturningOutput([
"mongo",
process.env.APPSMITH_DB_URL,
"--quiet",
"--eval",
"db.getCollectionNames().length",
]);
} catch (error) {
console.error("Failed to execute mongo command:", error);
throw error;
}
const collectionsLen = parseInt(shellCmdResult.stdout.toString().trimEnd())
if (collectionsLen > 0) {
if (forceOption) {
import_database()
await importDatabase()
return
}
console.log()
Expand All @@ -50,27 +53,25 @@ const main = (forceOption) => {
const input = readlineSync.question('Importing this DB will erase this data. Are you sure you want to proceed?[Yes/No] ')
const answer = input && input.toLocaleUpperCase()
if (answer === 'Y' || answer === 'YES') {
import_database()
await importDatabase()
return
} else if (answer === 'N' || answer === 'NO') {
return
}
console.log(`Your input is invalid. Please try to run import command again.`)
return
} else {
import_database()
return
await importDatabase()
}
} catch (err) {
console.log(err)
errorCode = 1
} finally {
console.log('start backend & rts application after import database')
start_application()
await utils.start(["backend", "rts"]);
process.exit(errorCode)
}
}

module.exports = {
runImportDatabase: main,
run,
}
9 changes: 7 additions & 2 deletions deploy/docker/fs/opt/appsmith/utils/bin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@ if (["import-db", "import_db", "im"].includes(command)) {
console.log("Importing database");
// Get Force option flag to run import DB immediately
const forceOption = process.argv[3] === "-f";
import_db.runImportDatabase(forceOption);
console.log("Importing database done");
try {
import_db.run(forceOption);
console.log("Importing database done");
} catch (error) {
console.error("Failed to import database:", error.message);
process.exit(1);
}
return;
}

Expand Down
30 changes: 30 additions & 0 deletions deploy/docker/fs/opt/appsmith/utils/bin/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,35 @@ function execCommand(cmd, options) {
});
}

function execCommandReturningOutput(cmd, options) {
return new Promise((resolve, reject) => {
const p = childProcess.spawn(cmd[0], cmd.slice(1), options);

p.stdin.end()

const outChunks = [], errChunks = [];

p.stdout.setEncoding("utf8");
p.stdout.on("data", (data) => {
outChunks.push(data.toString());
});

p.stderr.setEncoding("utf8");
p.stderr.on("data", (data) => {
errChunks.push(data.toString());
})

p.on("close", (code) => {
const output = (outChunks.join("").trim() + "\n" + errChunks.join("").trim()).trim();
if (code === 0) {
resolve(output);
} else {
reject(output);
}
});
});
}

async function listLocalBackupFiles() {
// Ascending order
const backupFiles = [];
Expand Down Expand Up @@ -196,6 +225,7 @@ module.exports = {
start,
stop,
execCommand,
execCommandReturningOutput,
listLocalBackupFiles,
updateLastBackupErrorMailSentInMilliSec,
getLastBackupErrorMailSentInMilliSec,
Expand Down
30 changes: 30 additions & 0 deletions deploy/docker/fs/opt/appsmith/utils/bin/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
const { describe, test, expect } = require("@jest/globals");
const utils = require("./utils");


describe("execCommandReturningOutput", () => {

test("Output of echo", async () => {
const result = await utils.execCommandReturningOutput(["echo", "hello", "world"]);
expect(result).toBe("hello world");
});

test("Node console out", async () => {
const result = await utils.execCommandReturningOutput(["node", "--eval", "console.log('to out')"]);
expect(result).toBe("to out");
});

test("Node console err", async () => {
const result = await utils.execCommandReturningOutput(["node", "--eval", "console.error('to err')"]);
expect(result).toBe("to err");
});

test("Node console out and err", async () => {
const result = await utils.execCommandReturningOutput(["node", "--eval", "console.log('to out'); console.error('to err')"]);
expect(result).toBe("to out\nto err");
});

test("Node console err and out", async () => {
const result = await utils.execCommandReturningOutput(["node", "--eval", "console.error('to err'); console.log('to out')"]);
expect(result).toBe("to out\nto err");
});

});

describe("execCommandSilent", () => {

test("Runs a command", async () => {
Expand Down
Loading

0 comments on commit d6f6920

Please sign in to comment.