This is an automated email from the ASF dual-hosted git repository. bsalzano pushed a commit to branch fix-deploy2 in repository https://gitbox.apache.org/repos/asf/openserverless-task.git
commit 2114118980dae129802db28f04c51089b23440d7 Author: Bruno Salzano <d4rks...@gmail.com> AuthorDate: Sat Aug 9 16:26:37 2025 +0200 fix: only bun functions and async modified deployer to use only async and bun functions. This branch will increase performances and resolve some problems with vite build. --- ide/deploy/bun.lockb | Bin 16741 -> 17094 bytes ide/deploy/client.js | 62 ++++++++++++++++++---------------------- ide/deploy/deploy.js | 74 ++++++++++++++++++++++++++++-------------------- ide/deploy/index.js | 2 +- ide/deploy/info.js | 5 ++-- ide/deploy/package.json | 3 +- ide/deploy/scan.js | 18 ++++++------ ide/deploy/serve.js | 8 ++++-- ide/deploy/watch.js | 24 ++++++++++------ 9 files changed, 106 insertions(+), 90 deletions(-) diff --git a/ide/deploy/bun.lockb b/ide/deploy/bun.lockb index 446c781..47fe67b 100755 Binary files a/ide/deploy/bun.lockb and b/ide/deploy/bun.lockb differ diff --git a/ide/deploy/client.js b/ide/deploy/client.js index a29b61b..51930aa 100644 --- a/ide/deploy/client.js +++ b/ide/deploy/client.js @@ -15,13 +15,12 @@ // specific language governing permissions and limitations // under the License. -import {readFileSync} from 'fs'; -import {spawn} from 'child_process'; +import {readFile} from 'fs/promises'; import {resolve} from 'path'; import process from 'process'; import {createInterface} from 'readline'; import {globalWatcher} from "./watch"; - +const { parse } = await import('shell-quote'); export let globalProc = undefined; /** @@ -31,11 +30,12 @@ export let globalProc = undefined; * @param defaultValue a default value to be returned when the key is not found * @returns {*} */ -export function getOpenServerlessConfig(key, defaultValue) { +export async function getOpenServerlessConfig(key, defaultValue) { try { const dir = process.env.OPS_PWD || '/do_not_exists'; const file = resolve(dir, 'package.json'); - const info = JSON.parse(readFileSync(file, 'utf8')); + const json = await readFile(file, 'utf8'); + const info = JSON.parse(json); return info.openserverless?.[key] || defaultValue; } catch { return defaultValue; @@ -61,33 +61,31 @@ function readlines(inp) { * @param key * @param defaultValue */ -export function launch(key, defaultValue) { - const cmd = getOpenServerlessConfig(key, defaultValue); - const proc = spawn(cmd, { +export async function launch(key, defaultValue) { + const cmd = await getOpenServerlessConfig(key, defaultValue); + const cmdArgs = parse(cmd).filter(arg => typeof arg === "string"); + const proc = Bun.spawn(cmdArgs, { shell: true, - cwd: process.env.OPS_PWD, env: process.env, - stdio: ['pipe', 'pipe', 'pipe'] + cwd: process.env.OPS_PWD, + stdio: ['inherit', 'inherit', 'inherit'] }); - - readlines(proc.stdout); - readlines(proc.stderr); } /** * start `ops ide serve` or a custom devel function specified * through `getOpenServerlessConfig` mechanism */ -export function serve() { - launch('devel', 'ops ide serve'); +export async function serve() { + await launch('devel', 'ops ide serve'); } /** * start `ops activation poll` or a custom logs function * through `getOpenServerlessConfig` mechanism */ -export function logs() { - launch('logs', 'ops activation poll'); +export async function logs() { + await launch('logs', 'ops activation poll'); } async function signalHandler() { @@ -105,37 +103,33 @@ async function signalHandler() { * through `getOpenServerlessConfig` mechanism */ export async function build() { - const deploy = getOpenServerlessConfig('deploy', 'true'); + const deploy = await getOpenServerlessConfig('deploy', 'true'); + + const deployArgs = parse(deploy).filter(arg => typeof arg === "string"); if (globalProc !== undefined) { globalProc.kill(); } - globalProc = spawn(deploy, { + globalProc = Bun.spawn(deployArgs, { shell: true, env: process.env, cwd: process.env.OPS_PWD, - stdio: ['pipe', 'pipe', 'pipe'] + stdio: ['inherit', 'inherit', 'inherit'] }); console.log(`✈️ Deploy Child process: ${deploy} has PID: ${globalProc.pid}`); - globalProc.stdout.on('data', (data) => { - console.log(data.toString()); - }); - - globalProc.stderr.on('data', (data) => { - console.error(data.toString()); - }); - - globalProc.on('close', (code) => { - console.log(`build process exited with code ${code}`); - }); - + // Register signal handlers process.on('SIGINT', signalHandler); process.on('SIGTERM', signalHandler); - await globalProc.exited; - + // Await its completion + try { + const code = await globalProc.exited; + console.log(`build process exited with code ${code}`); + } catch (err) { + console.error("Error awaiting process exit:", err); + } } diff --git a/ide/deploy/deploy.js b/ide/deploy/deploy.js index 0e1423e..50d629c 100644 --- a/ide/deploy/deploy.js +++ b/ide/deploy/deploy.js @@ -15,8 +15,8 @@ // specific language governing permissions and limitations // under the License. -const { spawnSync } = require("child_process"); -const fs = require("fs"); +import fs from 'fs/promises'; +const { parse } = await import('shell-quote'); const MAINS = ["__main__.py", "index.js", "index.php", "main.go"]; @@ -29,18 +29,25 @@ export function setDryRun(b) { dryRun = b; } -function exec(cmd) { +async function exec(cmd) { console.log("$", cmd); - if (!dryRun) { - spawnSync(cmd, { shell: true, env: process.env, stdio: "inherit" }); - } + const cmdArgs = parse(cmd).filter(arg => typeof arg === "string"); + + const proc = Bun.spawn(cmdArgs, { + shell: true, + env: process.env, + cwd: process.env.OPS_PWD, + stdio: ['inherit', 'inherit', 'inherit'] + }); + await proc.exited; } -function extractArgs(files) { +async function extractArgs(files) { const res = []; for (const file of files) { - if (fs.existsSync(file)) { - const lines = fs.readFileSync(file, "utf-8").split("\n"); + if (await fs.exists(file)) { + const fileContent = await fs.readFile(file, "utf-8"); + const lines = fileContent.split("\n"); for (const line of lines) { if (line.startsWith("#-")) { res.push(line.trim().substring(1)); @@ -56,27 +63,28 @@ function extractArgs(files) { const packageDone = new Set(); -export function deployPackage(pkg) { +export async function deployPackage(pkg) { const ppath = `packages/${pkg}.args`; - const pargs = extractArgs([ppath]).join(" "); - const cmd = `$OPS package update ${pkg} ${pargs}`; + const pargs = await extractArgs([ppath]); + const args = pargs.join(" "); + const cmd = `ops package update ${pkg} ${args}`; if (!packageDone.has(cmd)) { - exec(cmd); + await exec(cmd); packageDone.add(cmd); } } -export function buildZip(pkg, action) { - exec(`$OPS ide util zip A=${pkg}/${action}`); +export async function buildZip(pkg, action) { + await exec(`ops ide util zip A=${pkg}/${action}`); return `packages/${pkg}/${action}.zip`; } -export function buildAction(pkg, action) { - exec(`$OPS ide util action A=${pkg}/${action}`); +export async function buildAction(pkg, action) { + await exec(`ops ide util action A=${pkg}/${action}`); return `packages/${pkg}/${action}.zip`; } -export function deployAction(artifact) { +export async function deployAction(artifact) { let pkg = '', name='', typ = ''; if (activeDeployments.has(artifact)) { @@ -101,7 +109,7 @@ export function deployAction(artifact) { return; } - deployPackage(pkg); + await deployPackage(pkg); let toInspect; if (typ === "zip") { @@ -111,16 +119,16 @@ export function deployAction(artifact) { toInspect = [artifact]; } - const args = extractArgs(toInspect).join(" "); + const args = (await extractArgs(toInspect)).join(" "); const actionName = `${pkg}/${name}`; - exec(`$OPS action update ${actionName} ${artifact} ${args}`); + await exec(`ops action update ${actionName} ${artifact} ${args}`); activeDeployments.delete(artifact); if (queue.length > 0) { const nextArtifact = queue.shift(); console.debug(`📦 deploying from queue artifact ${nextArtifact}`); - deploy(nextArtifact); + await deploy(nextArtifact); } } @@ -129,16 +137,19 @@ export function deployAction(artifact) { * Deploy a `file` * @param file */ -export function deploy(file) { +export async function deploy(file) { // Uncomment the lines below to test specific files // const file = "packages/deploy/hello.py"; // const file = "packages/deploy/multi.zip"; // const file = "packages/deploy/multi/__main__.py"; // const file = "packages/deploy/multi/requirements.txt"; - if (fs.lstatSync(file).isDirectory()) { + + const stat = await fs.stat(file) + + if (stat.isDirectory()) { for (const start of MAINS) { const sub = `${file}/${start}`; - if (fs.existsSync(sub)) { + if (await fs.exists(sub)) { file = sub; break; } @@ -148,20 +159,21 @@ export function deploy(file) { const sp = file.split("/"); if (sp.length > 3) { buildZip(sp[1], sp[2]); - file = buildAction(sp[1], sp[2]); + file = await buildAction(sp[1], sp[2]); } - deployAction(file); + console.log(`Deploying ${file}`); + await deployAction(file); } /** * Deploy a `manifest.yaml` file using `ops -wsk project` * @param artifact */ -export function deployProject(artifact) { - if (fs.existsSync(artifact)) { - const manifestContent = fs.readFileSync(artifact); +export async function deployProject(artifact) { + if (await fs.exists(artifact)) { + const manifestContent = await Bun.file(artifact).text(); if (manifestContent.indexOf('packages:')!==-1) { - exec(`$OPS -wsk project deploy --manifest ${artifact}`); + await exec(`ops -wsk project deploy --manifest ${artifact}`); } else { console.log(`⚠️ Warning: it seems that the ${artifact} file is not a valid manifest file. Skipping`); } diff --git a/ide/deploy/index.js b/ide/deploy/index.js index d3eebff..2889f02 100644 --- a/ide/deploy/index.js +++ b/ide/deploy/index.js @@ -88,7 +88,7 @@ async function main() { await scan(); await build(); } - watchAndDeploy(); + await watchAndDeploy(); } else if (options.deploy) { await scan(); diff --git a/ide/deploy/info.js b/ide/deploy/info.js index 1f67de4..757ba9b 100644 --- a/ide/deploy/info.js +++ b/ide/deploy/info.js @@ -11,5 +11,6 @@ program const key = program.args[0]; const def = program.args[1] || ''; -const paramValue = getOpenServerlessConfig(key,def); -console.log(paramValue); \ No newline at end of file +getOpenServerlessConfig(key,def).then(paramValue => { + console.log(paramValue); +}); \ No newline at end of file diff --git a/ide/deploy/package.json b/ide/deploy/package.json index 5b37e62..264d8d3 100644 --- a/ide/deploy/package.json +++ b/ide/deploy/package.json @@ -3,7 +3,8 @@ "chokidar": "=4.0.3", "commander": "=13.1.0", "dotenv": "^16.4.7", - "glob": "=11.0.1" + "glob": "=11.0.1", + "shell-quote": "^1.8.3" }, "devDependencies": { "@types/bun": "=1.2.2" diff --git a/ide/deploy/scan.js b/ide/deploy/scan.js index 3fdce76..8962819 100644 --- a/ide/deploy/scan.js +++ b/ide/deploy/scan.js @@ -50,7 +50,7 @@ export async function scan() { "packages/*/*/go.mod" ]; // load user defined requirements or use `defaultReqsGlobs` - const packageGlobs = getOpenServerlessConfig("requirements", defaultReqsGlobs); + const packageGlobs = await getOpenServerlessConfig("requirements", defaultReqsGlobs); // requirements const reqs = []; @@ -69,7 +69,7 @@ export async function scan() { for (const req of reqs) { console.log(">> Requirements:", req); const sp = req.split("/"); - const act = buildZip(sp[1], sp[2]); + const act = await buildZip(sp[1], sp[2]); deployments.add(act); packages.add(sp[1]); } @@ -82,7 +82,7 @@ export async function scan() { "packages/*/*/main.go" ]; // load user defined main functions or use `defaultMainsGlobs` - const mainsGlobs = getOpenServerlessConfig("mains", defaultMainsGlobs); + const mainsGlobs = await getOpenServerlessConfig("mains", defaultMainsGlobs); const mains = []; for (const mainGlob of mainsGlobs) { @@ -97,7 +97,7 @@ export async function scan() { for (const main of mains) { console.log(">> Main:", main); const sp = main.split("/"); - const act = buildAction(sp[1], sp[2]); + const act = await buildAction(sp[1], sp[2]); deployments.add(act); packages.add(sp[1]); } @@ -109,7 +109,7 @@ export async function scan() { "packages/*/*.php", "packages/*/*.go" ]; - const singlesGlobs = getOpenServerlessConfig("singles", defaultSinglesGlobs); + const singlesGlobs = await getOpenServerlessConfig("singles", defaultSinglesGlobs); const singles = []; for (const singleGlob of singlesGlobs) { @@ -131,12 +131,12 @@ export async function scan() { console.log("> Deploying:"); for (const pkg of packages) { console.log(">> Package:", pkg); - deployPackage(pkg); + await deployPackage(pkg); } for (const action of deployments) { console.log(">>> Action:", action); - deployAction(action); + await deployAction(action); } @@ -145,7 +145,7 @@ export async function scan() { "packages/*.yaml", "packages/*/*.yaml", ]; - const manifestsGlobs = getOpenServerlessConfig("manifests", defaultProjectGlobs); + const manifestsGlobs = await getOpenServerlessConfig("manifests", defaultProjectGlobs); const manifests = []; for (const manifestGlobs of manifestsGlobs) { @@ -164,7 +164,7 @@ export async function scan() { } for (const manifest of manifests) { console.log(">>> Manifest:", manifest); - deployProject(manifest); + await deployProject(manifest); } } } diff --git a/ide/deploy/serve.js b/ide/deploy/serve.js index f65777a..a04c157 100644 --- a/ide/deploy/serve.js +++ b/ide/deploy/serve.js @@ -15,10 +15,11 @@ // specific language governing permissions and limitations // under the License. -import {statSync, readFileSync} from "fs"; +import {stat} from "fs/promises"; import {resolve, extname} from "path"; import {parse} from "url"; import process from 'process'; +import { file } from "bun"; /** * Helper function to find the first available port starting from 8080 @@ -149,7 +150,7 @@ async function main() { // Check if file exists locally try { // console.debug(`Asset dir: ${assetsDirectory} - Filepath is ${filePath}`); - const fileStats = statSync(filePath); + const fileStats = await stat(filePath); if (fileStats.isFile()) { const mimeType = flags.mimeType || getMimeType(filePath); @@ -160,7 +161,8 @@ async function main() { headers["Cache-Control"] = `max-age=${flags.cacheTime}`; } console.log(`[200] - Serving file ${pathname} from filesystem`); - return new Response(readFileSync(filePath), {headers}); + const data = Bun.file(filePath).text(); + return new Response(data, {headers}); } } catch (err) { let shouldExclude = (excludedAssets.indexOf(pathname) !== -1); diff --git a/ide/deploy/watch.js b/ide/deploy/watch.js index c0f063e..e8af88d 100644 --- a/ide/deploy/watch.js +++ b/ide/deploy/watch.js @@ -44,7 +44,8 @@ export function shouldIgnoreFile(path) { * @param changeType * @param path */ -export function checkAndDeploy(changeType, path) { +export async function checkAndDeploy(changeType, path) { + console.log(`(checkAndDeploy) > ${changeType} ${path}`); path = resolve(path); if (shouldIgnoreFile(path)) return; const curDirLen = process.cwd().length + 1; @@ -58,7 +59,9 @@ export function checkAndDeploy(changeType, path) { } // this should not even happen if (shouldIgnoreFile(src)) return; - deploy(src); + + console.log(`(checkAndDeploy -> deploy) > ${changeType} ${path}`); + await deploy(src); } /** @@ -79,9 +82,9 @@ async function redeploy() { }); - globalWatcher.on('all', (event, path) => { + globalWatcher.on('all', async (event, path) => { try { - checkAndDeploy(event, path); + await checkAndDeploy(event, path); } catch (error) { console.error(error); } @@ -96,11 +99,14 @@ async function redeploy() { * This function is the entry point and is called when * the program is started with the watch flag on */ -export function watchAndDeploy() { - serve(); - logs(); +export async function watchAndDeploy() { + await serve(); + await logs(); - redeploy().catch((error) => { + try { + await redeploy(); + } + catch(error) { console.error("Watcher failed:", error); - }); + }; }