From cd80904369bdb68e79fa75a6114d442bd5bfe7fd Mon Sep 17 00:00:00 2001 From: Sagar Khalasi Date: Tue, 20 Aug 2024 16:49:13 +0530 Subject: [PATCH] chore: Run a local server with docker compose while running from yarn setup (#35636) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description As a user, I want to run my backend server in local machine for running cypress test cases. Fixes #`35635` ## Automation /ok-to-test tags="@tag.Sanity" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 33c2dbbcf389a6840830e8914738a068d8ab41d9 > Cypress dashboard. > Tags: `@tag.Sanity` > Spec: >
Tue, 20 Aug 2024 10:54:22 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No Screenshot 2024-08-12 at 10 12 04 PM Screenshot 2024-08-12 at 10 12 10 PM Screenshot 2024-08-12 at 10 13 03 PM Screenshot 2024-08-12 at 10 13 10 PM Screenshot 2024-08-12 at 10 14 11 PM ## Summary by CodeRabbit - **New Features** - Introduced a new function to manage local server setup using Docker Compose, enhancing the setup process. - Added user prompts to guide decisions regarding local server setup. - **Improvements** - Implemented a retry mechanism to check Docker services, improving reliability during setup. - Enhanced error handling to provide clear feedback when setup conditions are not met. - **Refactor** - Integrated new functionalities into the existing setup process for a smoother user experience. --- .../cypress/scripts/cypress-local-setup.js | 99 ++++++++++++++++++- 1 file changed, 95 insertions(+), 4 deletions(-) diff --git a/app/client/cypress/scripts/cypress-local-setup.js b/app/client/cypress/scripts/cypress-local-setup.js index 72c6a47370..e8424e0834 100644 --- a/app/client/cypress/scripts/cypress-local-setup.js +++ b/app/client/cypress/scripts/cypress-local-setup.js @@ -1,13 +1,12 @@ -const { execSync } = require("child_process"); +const { exec, execSync } = require("child_process"); const { existsSync, readFileSync, writeFileSync } = require("fs"); const path = require("path"); const prompt = require("prompt-sync")(); -// Function to check if a Docker container is running function isContainerRunning(containerName) { try { const output = execSync( - `docker ps --format '{{.Names}}' | grep -w "${containerName}"`, + `docker ps --filter "name=^/${containerName}$" --format '{{.Names}}'`, ); return output.length > 0; } catch (error) { @@ -15,6 +14,98 @@ function isContainerRunning(containerName) { } } +// Helper function to execute commands and return a Promise +async function execCommand(command, options) { + return new Promise((resolve, reject) => { + exec(command, options, (error, stdout, stderr) => { + if (error) { + reject(error); + } else { + resolve({ stdout, stderr }); + } + }); + }); +} + +function checkDockerCompose() { + try { + execSync("docker-compose --version", { stdio: "ignore" }); + return true; + } catch (error) { + console.error( + "ERROR: docker-compose is not installed. Please install Docker Compose.", + ); + process.exit(1); + } +} + +async function runLocalServer() { + try { + let user_input = prompt( + `Do you wish to continue without setting up the local server with docker? (yes/no): `, + ); + user_input = (user_input || "").trim().toLowerCase(); + + if (user_input === "yes" || user_input === "y") { + console.log( + "INFO", + "Continuing without setting up local backend docker based server.", + ); + } else { + // Adjust the path to point to the correct directory + const dockerDir = path.join(__dirname, "../../../../deploy/docker"); + + if (!existsSync(dockerDir)) { + console.error(`ERROR: Directory ${dockerDir} does not exist.`); + process.exit(1); // Exit if the directory is missing + } + + await checkDockerCompose(); // Ensure Docker Compose is available + + console.log("INFO: Starting local server using Docker Compose..."); + execSync(`cd ${dockerDir} && pwd && docker-compose up -d`, { + stdio: "inherit", + }); + + // Wait for the services to be fully up and running + let servicesRunning = false; + const maxRetries = 30; + const retryInterval = 7000; // 7 seconds + + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const { stdout } = await execCommand("docker-compose ps", { + cwd: dockerDir, + }); + if (stdout.includes("Up")) { + servicesRunning = true; + break; + } + } catch (error) { + console.error("ERROR: Error checking service status:", error.message); + process.exit(1); // Exit if checking service status fails + } + console.log( + `INFO: Waiting for services to be fully up and running... (attempt ${attempt}/${maxRetries})`, + ); + await new Promise((resolve) => setTimeout(resolve, retryInterval)); + } + if (servicesRunning) { + console.log("INFO: Local server is up and running."); + return true; + } else { + console.error( + "ERROR: Services did not become available within the expected time.", + ); + process.exit(1); // Exit if services are not up + } + } + } catch (error) { + console.error("ERROR: Error starting local server:", error.message); + process.exit(1); // Exit if starting local server fails + } +} + function ensureTEDIsRunning() { // Check if TED is running. If not, then ask user if they wish to pull and run the TED container const isTedRunning = isContainerRunning("ted"); @@ -147,7 +238,7 @@ async function setupCypress() { // Get the baseUrl from cypress.config.ts file let repoRoot = path.join(__dirname, "..", ".."); let baseUrl = getBaseUrl(repoRoot); - + await runLocalServer(); await checkIfAppsmithIsRunning(baseUrl); // Install Cypress using yarn install on the app/client repository