I'm writing a node program that simulates what vercel does but in a docker container inside my raspberry so that I don't have the resource limitation.
Here is the code:
import Express from "express";
import {
ChildProcessWithoutNullStreams,
exec as execChildProcess,
spawn,
} from "child_process";
import fs from "fs";
import path from "path";
import util from "util";
const exec = util.promisify(execChildProcess);
const port = 3001;
const repository_url = "repo_url";
const repository_path = "./repository";
const main = async () => {
const cloneRepository = async () => {
console.log("Cloning repository...");
await exec(`git clone ${repository_url} ${repository_path}`);
console.log("Repository cloned!");
};
const pullRepository = async () => {
console.log("Pulling repository...");
await exec("git pull", { cwd: repository_path });
console.log("Repository pulled!");
};
const buildAndRun = async () => {
console.log("Downloading dependencies...");
await exec("npm install", { cwd: repository_path });
console.log("Dependencies downloaded!");
console.log("Building project...");
await exec("npm run build", { cwd: repository_path });
console.log("Project built!");
console.log("Running project...");
const child = spawn("npm", ["run", "start"], { cwd: repository_path });
child.stdout.on("data", (data) => {
console.log(`[LOG] ${data.toString()}`);
});
child.stderr.on("data", (data) => {
console.log(`[ERROR] ${data.toString()}`);
});
child.on("close", (code) => {
console.log(`Project exited with code ${code}`);
});
return child;
};
const stop = async (child: ChildProcessWithoutNullStreams) => {
console.log("Stopping project...");
child.kill("SIGINT");
console.log("Project stopped!");
let out;
let i = 0;
do {
out = await exec("lsof -i :3000");
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(`${i++}: ${out.stdout}`);
} while (out.stdout != "");
};
if (
!fs.existsSync(repository_path) &&
!fs.existsSync(path.join(repository_path, ".git"))
) {
cloneRepository();
} else {
pullRepository();
}
let child = await buildAndRun();
const app = Express();
app.put("/repository/update", async (req, res) => {
(async () => {
await stop(child);
await pullRepository();
child = await buildAndRun();
})();
res.send("ok");
});
app.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
};
main();
The purpose is to be able to push a commit to github, and via the post-receive hook tell this script to stop the running nextjs instance, pull the commit from the repo, and then start nextjs again.
The problem is that whenever the api receives the signal and nextjs is stopped, the process keeps on running, not allowing me to restart it.
To solve the problem I have to stop the script and restart it...
Any ideas on how to solve this?
P.s. I know the script is bad written by now. I wrote this in 10 mins, and then faced this issue... When I'll be done with this I will fix some stuff.
Thanks for help everybody!