This commit is contained in:
Benjamin Toby 2023-11-01 06:01:17 +01:00
parent da71e853bc
commit bb3d0712ca
7 changed files with 123 additions and 57 deletions

9
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
"files.associations": {
"ostream": "cpp"
},
"[python]": {
"editor.defaultFormatter": "ms-python.autopep8"
},
"python.formatting.provider": "none"
}

View File

@ -1,5 +1,10 @@
# Simple CI/CD package for any application
[![package version](https://img.shields.io/npm/v/nodecid.svg?style=flat-square)](https://npmjs.org/package/nodecid)
[![package downloads](https://img.shields.io/npm/dm/nodecid.svg?style=flat-square)](https://npmjs.org/package/nodecid)
[![standard-readme compliant](https://img.shields.io/badge/readme%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/RichardLitt/standard-readme)
[![package license](https://img.shields.io/npm/l/nodecid.svg?style=flat-square)](https://npmjs.org/package/nodecid)
Integrate a simple CI/CD process into your application without the hassle.
_**NOTE:** This package needs `node` installed to work_
@ -90,6 +95,14 @@ _NOTE:_ This also works for other languages, example:
This app just runs whatever command you send it in an isolated child process, the command will be run as if being run in a terminal.
#### All Available options in `nodecid.config.json` file
- **`start`**: _string_: The start Command
- **`preflight`**: _string | Array_: Array of commands or shell script file to run before reloading application
- **`redeploy_path`**: _string_: _Optional_: The path to trigger a redeployment. Default `./REDEPLOY`
- **`port`**: _string | number_: _Optional_: A port to kill if running a server. _NOTE_: it is important to provide this option if running a server else the process may not terminate properly
- **`first_run`**: _boolean_: _Optional_: If the preflight should run on first run. Default `false`.
### Redeployment
For continuos deployment and integration there needs to be a text file located in your project which the application can watch. Any time the content of this file is changed the application will rebuild and rerun your `start` command.

View File

@ -11,6 +11,7 @@ const {
ChildProcess,
} = require("child_process");
const colors = require("../utils/console-colors");
const kill = require("kill-port");
////////////////////////////////////////////
////////////////////////////////////////////
@ -20,17 +21,21 @@ let redeployments = 0;
/** @type {NodeJS.Signals | number} */
const KILL_SIGNAL = "SIGTERM";
// const KILL_SIGNAL = "SIGINT";
/** @type {ChildProcess | null} */
let childProcess = null;
const pTitle = "nodecid";
process.title = pTitle;
/**
* # Start the process
* @param {object} param0
* @param {string} param0.command
* @param {string[] | string} param0.preflight
* @param {string} param0.redeploy_file
* @param {string | number} [param0.port]
* @param {string | number} [param0.port] - The port to kill on rebuild
* @param {boolean} [param0.first_run] - Whether to run the preflight on first run. Default `false`
*/
function startProcess({ command, preflight, redeploy_file, port, first_run }) {
@ -130,8 +135,13 @@ function run(command) {
let childProcess = spawn(firstCommand, startCommandArray, {
stdio: "inherit",
killSignal: KILL_SIGNAL,
});
// let childProcess = execSync(command, {
// stdio: "inherit",
// });
redeployments++;
return childProcess;
@ -192,7 +202,7 @@ function preflightFn(preflight) {
////////////////////////////////////////////
/**
* ## Preflight Function
* ## Kill Child Process Function
* @param {string | number} [port]
* @returns {Promise<boolean>}
*/
@ -200,24 +210,12 @@ async function killChild(port) {
if (!childProcess) return false;
try {
childProcess.kill(KILL_SIGNAL);
const childProcessPID = childProcess.pid;
try {
if (childProcessPID) {
if (process.platform.match(/linux/i)) {
execSync(`kill -9 ${childProcessPID}`);
}
if (process.platform.match(/win/i)) {
execSync(`taskkill /F /PID ${childProcessPID}`);
}
}
} catch (error) {
console.log(
`${colors.FgYellow}WARNING:${colors.Reset} Process ${childProcessPID} couldn't be killed => ${error.message}`
);
}
childProcess.kill();
childProcess = null;
if (port) {
await kill(Number(port));
}
return true;
} catch (error) {

View File

@ -16,47 +16,64 @@ const WORK_DIR = process.cwd();
///////////////////////////////////////////////
///////////////////////////////////////////////
try {
const configText = fs.readFileSync(
path.join(WORK_DIR, "nodecid.config.json"),
"utf-8"
);
function run() {
try {
const configText = fs.readFileSync(
path.join(WORK_DIR, "nodecid.config.json"),
"utf-8"
);
/** @type {NodeCIConfig} */
const config = JSON.parse(configText);
/** @type {NodeCIConfig} */
const config = JSON.parse(configText);
const { start, preflight, redeploy_path, first_run } = config;
const { start, preflight, redeploy_path, first_run, port } = config;
/** @type {string | undefined} */
let redeployFile;
/** @type {string | undefined} */
let redeployFile;
if (!redeploy_path) {
const defaultRedeployPath = path.join(WORK_DIR, "REDEPLOY");
const checkExistingPath = fs.existsSync(defaultRedeployPath);
if (!redeploy_path) {
const defaultRedeployPath = path.join(WORK_DIR, "REDEPLOY");
const checkExistingPath = fs.existsSync(defaultRedeployPath);
if (!checkExistingPath) {
fs.writeFileSync(
defaultRedeployPath,
Date.now().toString(),
"utf-8"
);
if (!checkExistingPath) {
fs.writeFileSync(
defaultRedeployPath,
Date.now().toString(),
"utf-8"
);
}
redeployFile = path.join(WORK_DIR, "REDEPLOY");
} else {
redeployFile = path.resolve(WORK_DIR, redeploy_path);
}
redeployFile = path.join(WORK_DIR, "REDEPLOY");
} else {
redeployFile = path.resolve(WORK_DIR, redeploy_path);
if (!redeployFile) throw new Error("Redeploy file not found!");
startProcess({
command: start,
preflight,
redeploy_file: redeployFile,
first_run,
port,
});
} catch (error) {
console.log(
`${colors.FgRed}ERROR:${colors.Reset} CI process failed! => ${error.message}`
);
}
if (!redeployFile) throw new Error("Redeploy file not found!");
startProcess({
command: start,
preflight,
redeploy_file: redeployFile,
first_run,
});
} catch (error) {
console.log(
`${colors.FgRed}ERROR:${colors.Reset} CI process failed! => ${error.message}`
);
}
run();
////////////////////////////////////////////
////////////////////////////////////////////
////////////////////////////////////////////
process.on("exit", () => {
console.log("Process exiting ...");
});
process.on("beforeExit", () => {
console.log("Process Before exit ...");
});

29
package-lock.json generated
View File

@ -1,17 +1,42 @@
{
"name": "nodecid",
"version": "1.0.0",
"version": "1.0.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "nodecid",
"version": "1.0.0",
"version": "1.0.5",
"license": "MIT",
"dependencies": {
"kill-port": "^2.0.1"
},
"bin": {
"node-ci-cd": "index.js",
"nodecid": "index.js"
}
},
"node_modules/get-them-args": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/get-them-args/-/get-them-args-1.3.2.tgz",
"integrity": "sha512-LRn8Jlk+DwZE4GTlDbT3Hikd1wSHgLMme/+7ddlqKd7ldwR6LjJgTVWzBnR01wnYGe4KgrXjg287RaI22UHmAw=="
},
"node_modules/kill-port": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/kill-port/-/kill-port-2.0.1.tgz",
"integrity": "sha512-e0SVOV5jFo0mx8r7bS29maVWp17qGqLBZ5ricNSajON6//kmb7qqqNnml4twNE8Dtj97UQD+gNFOaipS/q1zzQ==",
"dependencies": {
"get-them-args": "1.3.2",
"shell-exec": "1.0.2"
},
"bin": {
"kill-port": "cli.js"
}
},
"node_modules/shell-exec": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/shell-exec/-/shell-exec-1.0.2.tgz",
"integrity": "sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg=="
}
}
}

View File

@ -1,6 +1,6 @@
{
"name": "nodecid",
"version": "1.0.5",
"version": "1.0.6",
"description": "Simple CI/CD process",
"main": "index.js",
"bin": {
@ -13,5 +13,8 @@
"Continous Deployment"
],
"author": "Benjamin Toby",
"license": "MIT"
"license": "MIT",
"dependencies": {
"kill-port": "^2.0.1"
}
}

View File

@ -6,4 +6,5 @@
* @property {string} [redeploy_path] - The path to the file that will trigger a
* redeployment if content is changed. Default file path is `./REDEPLOY`
* @property {boolean} [first_run] - Whether to run the preflight on first run. Default `false`
* @property {string | number} [port] - The port to kill on reload
*/