Compare commits

...
24 Commits
Author SHA1 Message Date
Benjamin Toby 62eef2f167 Updates 2025-05-07 22:18:55 +01:00
Benjamin Toby 7e320c87f5 Updates 2025-02-22 18:02:00 +01:00
Benjamin Toby 7bcddc9517 Updates 2025-02-22 14:55:26 +01:00
Benjamin Toby 85a64f85d6 Bugfix 2025-02-21 09:17:55 +01:00
Benjamin Toby 4540404522 Updates 2025-02-21 09:00:49 +01:00
Benjamin Toby 7d71316b2c Bugfix 2025-02-07 11:54:13 +01:00
Benjamin Toby 69eb6c1128 Updates 2025-02-04 07:43:18 +01:00
Benjamin Toby 0375c02931 Updates 2025-02-03 16:23:23 +01:00
Benjamin Toby 1e57cdbc1d Updates 2025-02-03 14:21:32 +01:00
Benjamin Toby 619afc8303 Updates 2025-02-03 13:41:13 +01:00
Benjamin Toby cee4bc0478 Updates 2025-01-22 12:31:32 +01:00
Benjamin Toby 1c26586478 Updates 2025-01-16 09:28:46 +01:00
Benjamin Toby 2cd83295bf Updates 2025-01-16 09:18:45 +01:00
Benjamin Toby 6867e8c17c Updates 2025-01-16 09:03:11 +01:00
Benjamin Toby a7b4e3f00b First Commit 2025-01-16 09:01:06 +01:00
Benjamin Toby cab7b131bf Updates 2025-01-16 08:16:23 +01:00
Benjamin Toby 702a62a914 Updates 2025-01-16 08:11:29 +01:00
Benjamin Toby 2264830d9f Updates 2025-01-16 08:06:35 +01:00
Benjamin Toby ae2a328f36 Updates 2025-01-16 07:57:10 +01:00
Benjamin Toby 1aaa257041 Updates 2025-01-16 07:52:57 +01:00
Benjamin Toby 918afc5d2c Updates 2025-01-16 07:48:00 +01:00
Benjamin Toby 2118f04b63 Updates 2025-01-16 06:32:50 +01:00
Benjamin Toby c09409e182 Updates 2025-01-16 06:31:09 +01:00
Benjamin Toby a3e20f15ef Updates 2025-01-16 06:25:16 +01:00
44 changed files with 1140 additions and 340 deletions
+80 -3
View File
@@ -1,9 +1,86 @@
{
"cursor.aipreview.enabled": true,
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"prettier.tabWidth": 4,
"redhat.telemetry.enabled": false,
"vs-kubernetes": {
"vscode-kubernetes.kubectl-path-linux": "/home/archben/.local/state/vs-kubernetes/tools/kubectl/kubectl",
"vscode-kubernetes.helm-path-linux": "/home/archben/.local/state/vs-kubernetes/tools/helm/linux-amd64/helm",
"vscode-kubernetes.minikube-path-linux": "/home/archben/.local/state/vs-kubernetes/tools/minikube/linux-amd64/minikube"
},
"workbench.colorTheme": "Obsidian Dark",
"terminal.integrated.env.linux": {},
"console-ninja.featureSet": "Community",
"files.associations": {
".env*": "dotenv",
".env": "properties",
"*.conf": "nginx",
"ostream": "cpp"
},
"[python]": {
"editor.defaultFormatter": "ms-python.autopep8"
"editor.tokenColorCustomizations": {
"[*Light*]": {
"textMateRules": [
{
"scope": "ref.matchtext",
"settings": {
"foreground": "#000"
}
}
]
},
"[*Dark*]": {
"textMateRules": [
{
"scope": "ref.matchtext",
"settings": {
"foreground": "#fff"
}
}
]
},
"textMateRules": []
},
"python.formatting.provider": "none"
"dotenv.enableAutocloaking": false,
"git.openRepositoryInParentFolders": "never",
"[shellscript]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"shellformat.effectLanguages": [
"shellscript",
"dockerfile",
"dotenv",
"hosts",
"jvmoptions",
"ignore",
"gitignore",
"properties",
"spring-boot-properties",
"azcli",
"bats"
],
"[dockerfile]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"[ignore]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"[dotenv]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"emulator.emulatorPath": "~/Android/Sdk/emulator",
"[properties]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"[toml]": {
"editor.defaultFormatter": "tamasfe.even-better-toml"
},
"terminal.integrated.defaultProfile.linux": "bash",
"diffEditor.ignoreTrimWhitespace": false,
"[sql]": {
"editor.defaultFormatter": "adpyke.vscode-sql-formatter"
},
"editor.fontFamily": "'Noto Sans Mono', 'monospace', monospace",
"stripe.telemetry.enabled": false,
"editor.linkedEditing": true
}
+44 -18
View File
@@ -1,31 +1,28 @@
# 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)
NOTE: This package is for Bun runtime
Integrate a simple CI/CD process into your application without the hassle.
_**NOTE:** This package needs `node` installed to work_
_**NOTE:** This package needs `bun` installed to work_
## Requirements
- **Node JS Runtime and NPM:** You need to have `NodeJS` and `npm` installed on the target machine for this package to work.
- **`nodecid.config.json` file:** This package depends on a configuration file located in the root directory of your application.
- **Node JS Runtime and NPM:** You need to have `NodeJS` and `bun` installed on the target machine for this package to work.
- **`buncid.config.json` file:** This package depends on a configuration file located in the root directory of your application.
## Installation
To install this package globally just run:
```shell
npm install -g nodecid
bun install -g buncid
```
To run the package directly run:
```shell
npx nodecid
bun buncid
```
This will download the package and run the binaries directly. After the first run it won't download the package again.
@@ -35,19 +32,19 @@ This will download the package and run the binaries directly. After the first ru
To run the package after installing it globally just run:
```shell
nodecid
buncid
```
Remember you must have a `nodecid.config.json` file located in your root directory else this will throw an error.
Remember you must have a `buncid.config.json` file located in your root directory else this will throw an error.
### Configuration
Your `nodecid.config.json` file should look like this:
Your `buncid.config.json` file should look like this:
```json
{
"start": "node index.js",
"preflight": ["npm run test", "npm run build"]
"start": "bun index.ts",
"preflight": ["bun run test", "bun run build"]
}
```
@@ -55,7 +52,7 @@ or
```json
{
"start": "node index.js",
"start": "bun index.ts",
"preflight": "./preflight.sh"
}
```
@@ -66,7 +63,7 @@ Optionally you could include a `redeploy_path` in your config file:
```json
{
"start": "node index.js",
"start": "bun index.ts",
"preflight": "./preflight.sh",
"redeploy_path": "./REDEPLOY"
}
@@ -78,7 +75,7 @@ You can change the name and path of the `redeploy_path`, just make sure the path
```json
{
"start": "node index.js",
"start": "bun index.ts",
"preflight": "./preflight.sh",
"redeploy_path": "./deploy/trigger.txt"
}
@@ -95,7 +92,7 @@ _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
#### All Available options in `buncid.config.json` file
- **`start`**: _string_: The start Command
- **`preflight`**: _string | Array_: Array of commands or shell script file to run before reloading application
@@ -107,3 +104,32 @@ This app just runs whatever command you send it in an isolated child process, th
### 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.
## Rebuilds
`buncid` provides rebuild scripts for popular frameworks
### Next JS
use `bun buncid-builds-next` or simply `buncid-builds-next` if you installed globally, to rebuild a next js app incrementally. This has a few requirements though.
#### Update your `next-config.js` file
You need to update the distribution directory in your `next-config.ts`. Like this:
```javascript
import type { NextConfig } from "next";
import grabDist from "@moduletrace/buncid/dist/rebuilds/next-js/grabDist";
const distDir = grabDist();
const nextConfig: NextConfig = {
/* config options here */
reactStrictMode: true,
distDir,
};
export default nextConfig;
```
That's it. This dynamically handles your distribution directory for both `dev` and `start` scripts. Your `development` environment uses the `.next` directory, while your `production` environment uses the `.buncid-next-dist` (or any dist name of your chosing) directory.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Executable
+87
View File
@@ -0,0 +1,87 @@
#!/usr/bin/env bun
import fs from "fs";
import path from "path";
import colors from "./utils/console-colors";
import startProcess from "./utils/start";
import type { NodeCIConfig } from "./types";
const WORK_DIR = process.cwd();
declare global {
var REDEPLOYMENTS: number;
var DEPLOYING: 0 | 1;
}
global.REDEPLOYMENTS = 0;
global.DEPLOYING = 0;
function run() {
try {
const configText = fs.readFileSync(
path.join(WORK_DIR, "buncid.config.json"),
"utf-8"
);
const config: NodeCIConfig = JSON.parse(configText);
const {
start,
preflight,
postflight,
build,
redeploy_path,
first_run,
port,
debounce,
} = config;
let redeployFile: string | undefined;
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"
);
}
redeployFile = path.join(WORK_DIR, "REDEPLOY");
} else {
redeployFile = path.resolve(WORK_DIR, redeploy_path);
}
if (!redeployFile)
throw new Error("Redeploy file variable not provided!");
if (!fs.existsSync(redeployFile))
throw new Error("Redeploy file not found!");
startProcess({
command: start,
preflight,
redeploy_file: redeployFile,
first_run,
port,
postflight,
debounce,
});
} catch (error: any) {
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 ...");
});
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env bun
declare global {
var REDEPLOYMENTS: number;
var DEPLOYING: 0 | 1;
}
export {};
Vendored Executable
+55
View File
@@ -0,0 +1,55 @@
#!/usr/bin/env bun
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const console_colors_1 = __importDefault(require("./utils/console-colors"));
const start_1 = __importDefault(require("./utils/start"));
const WORK_DIR = process.cwd();
global.REDEPLOYMENTS = 0;
global.DEPLOYING = 0;
function run() {
try {
const configText = fs_1.default.readFileSync(path_1.default.join(WORK_DIR, "buncid.config.json"), "utf-8");
const config = JSON.parse(configText);
const { start, preflight, postflight, build, redeploy_path, first_run, port, debounce, } = config;
let redeployFile;
if (!redeploy_path) {
const defaultRedeployPath = path_1.default.join(WORK_DIR, "REDEPLOY");
const checkExistingPath = fs_1.default.existsSync(defaultRedeployPath);
if (!checkExistingPath) {
fs_1.default.writeFileSync(defaultRedeployPath, Date.now().toString(), "utf-8");
}
redeployFile = path_1.default.join(WORK_DIR, "REDEPLOY");
}
else {
redeployFile = path_1.default.resolve(WORK_DIR, redeploy_path);
}
if (!redeployFile)
throw new Error("Redeploy file variable not provided!");
if (!fs_1.default.existsSync(redeployFile))
throw new Error("Redeploy file not found!");
(0, start_1.default)({
command: start,
preflight,
redeploy_file: redeployFile,
first_run,
port,
postflight,
debounce,
});
}
catch (error) {
console.log(`${console_colors_1.default.FgRed}ERROR:${console_colors_1.default.Reset} CI process failed! => ${error.message}`);
}
}
run();
process.on("exit", () => {
console.log("Process exiting ...");
});
process.on("beforeExit", () => {
console.log("Process Before exit ...");
});
+9 -1
View File
@@ -1 +1,9 @@
export {};
import grabDist from "./rebuilds/next-js/grabDist";
declare const buncid: {
builds: {
nextJs: {
grabDist: typeof grabDist;
};
};
};
export default buncid;
+9 -45
View File
@@ -3,48 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const console_colors_1 = __importDefault(require("./utils/console-colors"));
const start_1 = __importDefault(require("./utils/start"));
const WORK_DIR = process.cwd();
function run() {
try {
const configText = fs_1.default.readFileSync(path_1.default.join(WORK_DIR, "nodecid.config.json"), "utf-8");
const config = JSON.parse(configText);
const { start, preflight, postflight, build, redeploy_path, first_run, port, } = config;
/** @type {string | undefined} */
let redeployFile;
if (!redeploy_path) {
const defaultRedeployPath = path_1.default.join(WORK_DIR, "REDEPLOY");
const checkExistingPath = fs_1.default.existsSync(defaultRedeployPath);
if (!checkExistingPath) {
fs_1.default.writeFileSync(defaultRedeployPath, Date.now().toString(), "utf-8");
}
redeployFile = path_1.default.join(WORK_DIR, "REDEPLOY");
}
else {
redeployFile = path_1.default.resolve(WORK_DIR, redeploy_path);
}
if (!redeployFile)
throw new Error("Redeploy file not found!");
(0, start_1.default)({
command: start,
preflight,
redeploy_file: redeployFile,
first_run,
port,
postflight,
});
}
catch (error) {
console.log(`${console_colors_1.default.FgRed}ERROR:${console_colors_1.default.Reset} CI process failed! => ${error.message}`);
}
}
run();
process.on("exit", () => {
console.log("Process exiting ...");
});
process.on("beforeExit", () => {
console.log("Process Before exit ...");
});
const grabDist_1 = __importDefault(require("./rebuilds/next-js/grabDist"));
const buncid = {
builds: {
nextJs: {
grabDist: grabDist_1.default,
},
},
};
exports.default = buncid;
@@ -0,0 +1 @@
export default function grabDefaultDistName(): string;
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = grabDefaultDistName;
function grabDefaultDistName() {
return ".buncid-next-dist";
}
+10
View File
@@ -0,0 +1,10 @@
type Param = {
distDir?: string;
};
/**
* # Grab the current distribution directory
* @description This returns the relative path from the CWD. Eg `./.dist/build-1`
* @returns {string | undefined}
*/
export default function grabDist(params?: Param): string | undefined;
export {};
+47
View File
@@ -0,0 +1,47 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = grabDist;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const grab_default_dist_name_1 = __importDefault(require("./(utils)/grab-default-dist-name"));
const production = process.env.NODE_ENV == "production";
const isBuilding = process.env.BUILDING_APP;
/**
* # Grab the current distribution directory
* @description This returns the relative path from the CWD. Eg `./.dist/build-1`
* @returns {string | undefined}
*/
function grabDist(params) {
const distDirName = (params === null || params === void 0 ? void 0 : params.distDir) || (0, grab_default_dist_name_1.default)();
const DIST_DIR = path_1.default.join(process.cwd(), distDirName);
if (isBuilding) {
const distDir = (() => {
try {
const buildNumber = fs_1.default.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
return `${distDirName}/build-${buildNumber}`;
}
catch (error) {
console.log("Build Number Generation Error =>", error.message);
process.exit();
}
})();
return distDir;
}
if (production) {
const distDir = (() => {
try {
const buildNumber = fs_1.default.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
return `${distDirName}/build-${buildNumber}`;
}
catch (error) {
console.log("Build Number Parse Error =>", error.message);
process.exit();
}
})();
return distDir;
}
return undefined;
}
+2
View File
@@ -0,0 +1,2 @@
#!/usr/bin/env bun
export {};
+132
View File
@@ -0,0 +1,132 @@
#!/usr/bin/env bun
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = __importDefault(require("path"));
const util_1 = require("util");
const fs_1 = __importDefault(require("fs"));
const child_process_1 = require("child_process");
const grab_default_dist_name_1 = __importDefault(require("./(utils)/grab-default-dist-name"));
const args = (0, util_1.parseArgs)({
args: process.argv,
options: {
maxBuilds: {
type: "string",
alias: "m",
},
distDir: {
type: "string",
alias: "d",
},
},
allowPositionals: true,
});
const distDirName = args.values.distDir || (0, grab_default_dist_name_1.default)();
const DIST_DIR = path_1.default.join(process.cwd(), distDirName);
let PREV_BUILD_NO = "0";
const MAX_BUILDS = process.env.BUNCID_MAX_BUILDS
? Number(process.env.BUNCID_MAX_BUILDS)
: args.values.maxBuilds
? Number(args.values.maxBuilds)
: 10;
if (MAX_BUILDS < 1 ||
Number.isNaN(MAX_BUILDS) ||
typeof MAX_BUILDS !== "number") {
throw new Error("Invalid MAX_BUILDS");
}
if (!fs_1.default.existsSync(DIST_DIR))
fs_1.default.mkdirSync(DIST_DIR, { recursive: true });
if (fs_1.default.existsSync(`${DIST_DIR}/BUILD`)) {
PREV_BUILD_NO = fs_1.default.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
}
else {
fs_1.default.writeFileSync(`${DIST_DIR}/BUILD`, "0", "utf-8");
}
try {
const buildNumber = fs_1.default.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
const newBuildNumber = Number(buildNumber) + 1;
if (newBuildNumber < 0) {
throw new Error("Invalid Build Number");
}
fs_1.default.writeFileSync(`${DIST_DIR}/BUILD`, String(newBuildNumber));
if (newBuildNumber > MAX_BUILDS) {
const builds = fs_1.default.readdirSync(DIST_DIR);
const buildDirs = builds.filter((build) => build.match(/build-\d+/));
for (const buildDir of buildDirs) {
const buildDirPath = path_1.default.join(DIST_DIR, buildDir);
const buildDirStat = fs_1.default.statSync(buildDirPath);
if (buildDirStat.isDirectory()) {
const buildDirName = buildDir.split("-")[1];
const buildDirNumber = Number(buildDirName);
if (buildDirNumber <= newBuildNumber - MAX_BUILDS) {
fs_1.default.rmdirSync(buildDirPath, { recursive: true });
console.log("Deleted Build Directory =>", buildDirPath);
}
}
}
}
}
catch (error) {
console.log("Build Number Parse Error =>", error.message);
process.exit(1);
}
const spawnSyncOptions = {
stdio: "inherit",
encoding: "utf-8",
shell: ((_a = process.platform) === null || _a === void 0 ? void 0 : _a.match(/win32/i)) ? "bash.exe" : undefined,
env: Object.assign(Object.assign({}, process.env), { BUILDING_APP: "true" }),
};
const build = (0, child_process_1.spawnSync)("bun", ["next", "build"], spawnSyncOptions);
/**
* @returns {string}
*/
function grabNewDistDir() {
try {
const buildNumber = fs_1.default.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
return `${distDirName}/build-${buildNumber}`;
}
catch ( /** @type {*} */error) {
console.log("Build Number Parse Error =>", error.message);
process.exit();
}
}
const newDistDir = grabNewDistDir();
// if (!fs.existsSync(newDistDir)) {
// fs.mkdirSync(newDistDir, { recursive: true });
// }
// if (!fs.existsSync(`${newDistDir}/BUILD_ID`)) {
// fs.writeFileSync(`${newDistDir}/BUILD_ID`, "4");
// }
/**
* # Revert Directories
* @param {string} dir - New Build Directory Path
*/
function revert(dir) {
var _a;
console.log("Build Failed!", ((_a = build === null || build === void 0 ? void 0 : build.error) === null || _a === void 0 ? void 0 : _a.message) || build.stderr);
fs_1.default.writeFileSync(`${DIST_DIR}/BUILD`, PREV_BUILD_NO, "utf-8");
(0, child_process_1.execSync)(`rm -Rf ${dir}`, { cwd: process.cwd() });
const writeErr = build.error
? build.error.message
: build.stderr
? build.stderr.toString()
: "NO BUILD_ID found in New Build Folder";
fs_1.default.writeFileSync(`${DIST_DIR}/LAST_BUILD_FAIL`, Date() + "\n\n" + writeErr, "utf-8");
process.exit(1);
}
if (build.error ||
build.stderr ||
build.status != 0 ||
!fs_1.default.existsSync(`${newDistDir}/BUILD_ID`)) {
revert(newDistDir);
throw new Error("Build Failed!");
}
process.on("exit", () => {
const onExitDir = grabNewDistDir();
if (!fs_1.default.existsSync(`${onExitDir}/BUILD_ID`)) {
revert(onExitDir);
}
});
+6
View File
@@ -0,0 +1,6 @@
/**
* # Grab the current distribution directory
* @description This returns the relative path from the CWD. Eg `./.dist/build-1`
* @returns {string | undefined}
*/
export default function grabDist(): string | undefined;
+45
View File
@@ -0,0 +1,45 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = grabDist;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const production = process.env.NODE_ENV == "production";
const isBuilding = process.env.BUILDING_APP;
/**
* # Grab the current distribution directory
* @description This returns the relative path from the CWD. Eg `./.dist/build-1`
* @returns {string | undefined}
*/
function grabDist() {
const DIST_DIR = path_1.default.resolve(process.cwd(), "./.dist");
if (isBuilding) {
const distDir = (() => {
try {
const buildNumber = fs_1.default.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
return `.dist/build-${buildNumber}`;
}
catch ( /** @type {*} */error) {
console.log("Build Number Generation Error =>", error.message);
process.exit();
}
})();
return distDir;
}
if (production) {
const distDir = (() => {
try {
const buildNumber = fs_1.default.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
return `.dist/build-${buildNumber}`;
}
catch ( /** @type {*} */error) {
console.log("Build Number Parse Error =>", error.message);
process.exit();
}
})();
return distDir;
}
return undefined;
}
+3
View File
@@ -0,0 +1,3 @@
import type { NextConfig } from "next";
declare const nextConfig: NextConfig;
export default nextConfig;
+12
View File
@@ -0,0 +1,12 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const grabDist_1 = __importDefault(require("../../../rebuilds/next-js/grabDist"));
const distDir = (0, grabDist_1.default)();
const nextConfig = {
reactStrictMode: true,
distDir,
};
exports.default = nextConfig;
+6
View File
@@ -0,0 +1,6 @@
import type { NextApiRequest, NextApiResponse } from "next";
type Data = {
name: string;
};
export default function handler(req: NextApiRequest, res: NextApiResponse<Data>): void;
export {};
+6
View File
@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = handler;
function handler(req, res) {
res.status(200).json({ name: "John Doe" });
}
+13
View File
@@ -0,0 +1,13 @@
declare const _default: {
content: string[];
theme: {
extend: {
colors: {
background: string;
foreground: string;
};
};
};
plugins: never[];
};
export default _default;
+18
View File
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: {
background: "var(--background)",
foreground: "var(--foreground)",
},
},
},
plugins: [],
};
+1 -1
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -6,6 +6,7 @@ export interface NodeCIConfig {
first_run?: boolean;
port?: string | number | (string | number)[];
build?: NodeCIBuild;
debounce?: number;
}
export interface NodeCIBuild {
paradigm: "Next.JS" | "Remix";
+10 -1
View File
@@ -1,6 +1,15 @@
import { ChildProcess } from "child_process";
/**
* ## Kill Child Process Function
* @param {string | number | (string | number)[]} [port]
* @returns {Promise<boolean>}
*/
export default function killChild(port?: string | number | (string | number)[]): Promise<boolean>;
export default function killChild(
/**
* Child Process to be killed
*/
childProcess?: ChildProcess,
/**
* Port/ports to be killed
*/
port?: string | number | (string | number)[]): Promise<boolean>;
+51 -14
View File
@@ -15,35 +15,72 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.default = killChild;
const console_colors_1 = __importDefault(require("./console-colors"));
const kill_port_1 = __importDefault(require("kill-port"));
let childProcess = null;
const pTitle = "nodecid";
process.title = pTitle;
/**
* ## Kill Child Process Function
* @param {string | number | (string | number)[]} [port]
* @returns {Promise<boolean>}
*/
function killChild(port) {
function killChild(
/**
* Child Process to be killed
*/
childProcess,
/**
* Port/ports to be killed
*/
port) {
return __awaiter(this, void 0, void 0, function* () {
if (!childProcess)
return false;
try {
const childProcessPID = childProcess.pid;
childProcess.kill();
if (typeof port == "object" && (port === null || port === void 0 ? void 0 : port[0])) {
for (let i = 0; i < port.length; i++) {
const singlePort = port[i];
yield (0, kill_port_1.default)(Number(singlePort));
}
const childKilled = childProcess.kill();
if (childKilled) {
return true;
}
else if (port) {
yield (0, kill_port_1.default)(Number(port));
else {
return yield killPortFn(childProcess, port);
}
return true;
}
catch (error) {
yield killPortFn(childProcess, port);
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Child Process couldn't be killed! ${error.message}`);
return false;
}
});
}
function killPortFn(
/**
* Child Process to be killed
*/
childProcess,
/**
* Port/ports to be killed
*/
port) {
return __awaiter(this, void 0, void 0, function* () {
if (!childProcess)
return false;
try {
if (typeof port == "object" && (port === null || port === void 0 ? void 0 : port[0])) {
for (let i = 0; i < port.length; i++) {
const singlePort = port[i];
yield (0, kill_port_1.default)(Number(singlePort), "tcp");
}
childProcess.kill();
return true;
}
else if (port) {
yield (0, kill_port_1.default)(Number(port), "tcp");
childProcess.kill();
return true;
}
else {
return false;
}
}
catch (_err) {
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Child Process PORT couldn't be killed! ${_err.message}`);
return false;
}
});
}
+3 -6
View File
@@ -6,10 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.default = run;
const child_process_1 = require("child_process");
const console_colors_1 = __importDefault(require("./console-colors"));
let redeployments = 0;
const KILL_SIGNAL = "SIGTERM";
const pTitle = "nodecid";
process.title = pTitle;
/**
* ## Preflight Function
* @param {string} command
@@ -25,12 +22,12 @@ function run(command) {
if (!firstCommand) {
throw new Error("No Starting Command Found in command string!");
}
let childProcess = (0, child_process_1.spawn)(firstCommand, startCommandArray, {
let newChildProcess = (0, child_process_1.spawn)(firstCommand, startCommandArray, {
stdio: "inherit",
killSignal: KILL_SIGNAL,
});
redeployments++;
return childProcess;
global.REDEPLOYMENTS = global.REDEPLOYMENTS + 1;
return newChildProcess;
}
catch (error) {
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} running start command => ${error.message}`);
+6 -13
View File
@@ -1,18 +1,11 @@
/**
* # Start the process
* @param {object} param0
* @param {string} param0.command
* @param {string[] | string} param0.preflight
* @param {string[] | string} [param0.postflight]
* @param {string} param0.redeploy_file
* @param {string | number | (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`
*/
export default function startProcess({ command, preflight, postflight, redeploy_file, port, first_run, }: {
type Param = {
command: string;
preflight: string[] | string;
preflight?: string[] | string;
postflight?: string[] | string;
redeploy_file: string;
port?: string | number | (string | number)[];
first_run?: boolean;
}): void;
debounce?: number;
};
export default function startProcess({ command, preflight, postflight, redeploy_file, port, first_run, debounce, }: Param): void;
export {};
+47 -48
View File
@@ -9,29 +9,16 @@ const console_colors_1 = __importDefault(require("./console-colors"));
const preflight_1 = __importDefault(require("./preflight"));
const run_1 = __importDefault(require("./run"));
const kill_child_1 = __importDefault(require("./kill-child"));
let redeployments = 0;
let childProcess = null;
const pTitle = "nodecid";
const pTitle = "buncid";
process.title = pTitle;
/**
* # Start the process
* @param {object} param0
* @param {string} param0.command
* @param {string[] | string} param0.preflight
* @param {string[] | string} [param0.postflight]
* @param {string} param0.redeploy_file
* @param {string | number | (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, postflight, redeploy_file, port, first_run, }) {
let timeout;
function startProcess({ command, preflight, postflight, redeploy_file, port, first_run, debounce, }) {
const DEBOUNCE = debounce || 1000;
try {
if (first_run) {
console.log("First Run ...");
const runPreflight = (0, preflight_1.default)(preflight);
}
if (!preflight) {
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} No preflight included in config file. If you don't want to run any preflight command simply add an empty array.`);
process.exit();
const runFirstPreflight = (0, preflight_1.default)(preflight);
}
childProcess = (0, run_1.default)(command);
if (!childProcess) {
@@ -40,42 +27,54 @@ function startProcess({ command, preflight, postflight, redeploy_file, port, fir
}
console.log("Watching", redeploy_file);
fs_1.default.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => {
console.log(`${console_colors_1.default.BgBlue}File Changed${console_colors_1.default.Reset}`);
if (redeployments == 0)
if (global.DEPLOYING == 1)
return;
if (childProcess) {
console.log("******************************");
console.log(`******** ${console_colors_1.default.FgBlue}Rebuilding ${console_colors_1.default.FgMagenta}${redeployments}${console_colors_1.default.Reset} ********`);
console.log("******************************");
try {
const runPreflight = (0, preflight_1.default)(preflight);
if (!runPreflight) {
// TODO: Action to take if preflight fails
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Preflight Failed.`);
}
else {
(0, kill_child_1.default)(port).then((kill) => {
if (kill) {
childProcess = (0, run_1.default)(command);
if (postflight) {
const runPostflight = (0, preflight_1.default)(postflight, true);
if (!runPostflight) {
// TODO: Action to take if postflight fails
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Postflight Failed.`);
clearTimeout(timeout);
timeout = setTimeout(() => {
console.log(`${console_colors_1.default.BgBlue}File Changed${console_colors_1.default.Reset}`);
if (global.REDEPLOYMENTS == 0) {
return;
}
global.DEPLOYING = 1;
if (childProcess) {
console.log("******************************");
console.log(`******** ${console_colors_1.default.FgBlue}Rebuilding ${console_colors_1.default.FgMagenta}${global.REDEPLOYMENTS}${console_colors_1.default.Reset} ********`);
console.log("******************************");
try {
const runPreflight = (0, preflight_1.default)(preflight);
if (!runPreflight) {
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Preflight Failed.`);
setTimeout(() => {
global.DEPLOYING = 0;
}, 2000);
}
else {
(0, kill_child_1.default)(childProcess, port).then((kill) => {
if (kill) {
childProcess = (0, run_1.default)(command);
if (postflight) {
const runPostflight = (0, preflight_1.default)(postflight, true);
if (!runPostflight) {
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Postflight Failed.`);
}
}
global.DEPLOYING = 0;
}
}
else {
process.exit();
}
});
else {
process.exit();
}
});
}
}
catch (error) {
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} killing child processes => ${error.message}`);
process.exit();
}
}
catch (error) {
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} killing child processes => ${error.message}`);
process.exit();
else {
global.DEPLOYING = 0;
}
}
}, DEBOUNCE);
});
}
catch (error) {
+9 -71
View File
@@ -1,73 +1,11 @@
import fs from "fs";
import path from "path";
import colors from "./utils/console-colors";
import startProcess from "./utils/start";
import type { NodeCIConfig } from "./types";
import grabDist from "./rebuilds/next-js/grabDist";
const WORK_DIR = process.cwd();
const buncid = {
builds: {
nextJs: {
grabDist,
},
},
};
function run() {
try {
const configText = fs.readFileSync(
path.join(WORK_DIR, "nodecid.config.json"),
"utf-8"
);
const config: NodeCIConfig = JSON.parse(configText);
const {
start,
preflight,
postflight,
build,
redeploy_path,
first_run,
port,
} = config;
/** @type {string | undefined} */
let redeployFile;
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"
);
}
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,
postflight,
});
} catch (error: any) {
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 ...");
});
export default buncid;
+21 -16
View File
@@ -1,30 +1,35 @@
{
"name": "@moduletrace/nodecid",
"version": "1.0.7",
"description": "Simple CI/CD process",
"name": "@moduletrace/buncid",
"version": "1.1.3",
"author": "Benjamin Toby",
"repository": {
"type": "git",
"url": "https://git.tben.me/Moduletrace/buncid.git"
},
"main": "dist/index.js",
"devDependencies": {
"@types/bun": "latest",
"@types/kill-port": "^2.0.3",
"@types/node": "^22.10.7"
},
"peerDependencies": {
"typescript": "^5.0.0"
},
"bin": {
"nodecid": "./dist/index.js",
"node-ci-cd": "./dist/index.js"
},
"scripts": {
"compile": "bun build --compile --minify --sourcemap --bytecode index.ts --outfile bin/nodecid"
"buncid": "./dist/buncid.js",
"buncid-builds-next": "./dist/rebuilds/next-js/index.js"
},
"description": "Simple CI/CD process For Bun runtime",
"keywords": [
"CI/CD",
"Continuous Integration",
"Continous Deployment"
],
"author": "Benjamin Toby",
"license": "MIT",
"scripts": {
"compile": "bun build --compile --minify --sourcemap --bytecode index.ts --outfile bin/buncid"
},
"dependencies": {
"kill-port": "^2.0.1"
},
"devDependencies": {
"@types/bun": "latest",
"@types/node": "^22.10.7"
},
"peerDependencies": {
"typescript": "^5.0.0"
}
}
+6 -1
View File
@@ -1,9 +1,14 @@
#!/bin/bash
tsc
if [ -z "$1" ]; then
msg="Updates"
else
msg="$1"
fi
git add . && git commit -m "$msg" && git push && npm publish
git add .
git commit -m "$msg"
git push
bun publish
Executable
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
if [ -z "$1" ]; then
msg="Updates"
else
msg="$1"
fi
git add .
git commit -m "$msg"
git push
@@ -0,0 +1,3 @@
export default function grabDefaultDistName(): string {
return ".buncid-next-dist";
}
+28
View File
@@ -0,0 +1,28 @@
# Rebuild your next project incrementally.
Create builds incrementally without stopping your server.
## Requirements
There are a few requirements to get this to work
### Update your `next-config.js` file
You need to update the distribution directory in your `next-config.js`. Like this:
```javascript
import type { NextConfig } from "next";
import grabDist from "@moduletrace/buncid/dist/rebuilds/next-js/grabDist";
const distDir = grabDist();
const nextConfig: NextConfig = {
/* config options here */
reactStrictMode: true,
distDir,
};
export default nextConfig;
```
That's it. This dynamically handles your distribution directory for both `dev` and `start` scripts. Your `development` environment uses the `.next` directory, while your `production` environment uses the `.buncid-next-dist` (or any dist name of your chosing) directory.
+56
View File
@@ -0,0 +1,56 @@
import fs from "fs";
import path from "path";
import grabDefaultDistName from "./(utils)/grab-default-dist-name";
const production = process.env.NODE_ENV == "production";
const isBuilding = process.env.BUILDING_APP;
type Param = {
distDir?: string;
};
/**
* # Grab the current distribution directory
* @description This returns the relative path from the CWD. Eg `./.dist/build-1`
* @returns {string | undefined}
*/
export default function grabDist(params?: Param): string | undefined {
const distDirName = params?.distDir || grabDefaultDistName();
const DIST_DIR = path.join(process.cwd(), distDirName);
if (isBuilding) {
const distDir = (() => {
try {
const buildNumber = fs.readFileSync(
`${DIST_DIR}/BUILD`,
"utf-8"
);
return `${distDirName}/build-${buildNumber}`;
} catch (error: any) {
console.log("Build Number Generation Error =>", error.message);
process.exit();
}
})();
return distDir;
}
if (production) {
const distDir = (() => {
try {
const buildNumber = fs.readFileSync(
`${DIST_DIR}/BUILD`,
"utf-8"
);
return `${distDirName}/build-${buildNumber}`;
} catch (error: any) {
console.log("Build Number Parse Error =>", error.message);
process.exit();
}
})();
return distDir;
}
return undefined;
}
+160
View File
@@ -0,0 +1,160 @@
#!/usr/bin/env bun
import path from "path";
import { parseArgs } from "util";
import fs from "fs";
import {
execSync,
spawnSync,
SpawnSyncOptionsWithStringEncoding,
} from "child_process";
import grabDefaultDistName from "./(utils)/grab-default-dist-name";
const args = parseArgs({
args: process.argv,
options: {
maxBuilds: {
type: "string",
alias: "m",
},
distDir: {
type: "string",
alias: "d",
},
},
allowPositionals: true,
});
const distDirName = args.values.distDir || grabDefaultDistName();
const DIST_DIR = path.join(process.cwd(), distDirName);
let PREV_BUILD_NO = "0";
const MAX_BUILDS = process.env.BUNCID_MAX_BUILDS
? Number(process.env.BUNCID_MAX_BUILDS)
: args.values.maxBuilds
? Number(args.values.maxBuilds)
: 10;
if (
MAX_BUILDS < 1 ||
Number.isNaN(MAX_BUILDS) ||
typeof MAX_BUILDS !== "number"
) {
throw new Error("Invalid MAX_BUILDS");
}
if (!fs.existsSync(DIST_DIR)) fs.mkdirSync(DIST_DIR, { recursive: true });
if (fs.existsSync(`${DIST_DIR}/BUILD`)) {
PREV_BUILD_NO = fs.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
} else {
fs.writeFileSync(`${DIST_DIR}/BUILD`, "0", "utf-8");
}
try {
const buildNumber = fs.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
const newBuildNumber = Number(buildNumber) + 1;
if (newBuildNumber < 0) {
throw new Error("Invalid Build Number");
}
fs.writeFileSync(`${DIST_DIR}/BUILD`, String(newBuildNumber));
if (newBuildNumber > MAX_BUILDS) {
const builds = fs.readdirSync(DIST_DIR);
const buildDirs = builds.filter((build) => build.match(/build-\d+/));
for (const buildDir of buildDirs) {
const buildDirPath = path.join(DIST_DIR, buildDir);
const buildDirStat = fs.statSync(buildDirPath);
if (buildDirStat.isDirectory()) {
const buildDirName = buildDir.split("-")[1];
const buildDirNumber = Number(buildDirName);
if (buildDirNumber <= newBuildNumber - MAX_BUILDS) {
fs.rmdirSync(buildDirPath, { recursive: true });
console.log("Deleted Build Directory =>", buildDirPath);
}
}
}
}
} catch (error: any) {
console.log("Build Number Parse Error =>", error.message);
process.exit(1);
}
const spawnSyncOptions: SpawnSyncOptionsWithStringEncoding = {
stdio: "inherit",
encoding: "utf-8",
shell: process.platform?.match(/win32/i) ? "bash.exe" : undefined,
env: {
...process.env,
BUILDING_APP: "true",
},
};
const build = spawnSync("bun", ["next", "build"], spawnSyncOptions);
/**
* @returns {string}
*/
function grabNewDistDir(): string {
try {
const buildNumber = fs.readFileSync(`${DIST_DIR}/BUILD`, "utf-8");
return `${distDirName}/build-${buildNumber}`;
} catch (/** @type {*} */ error: any) {
console.log("Build Number Parse Error =>", error.message);
process.exit();
}
}
const newDistDir = grabNewDistDir();
// if (!fs.existsSync(newDistDir)) {
// fs.mkdirSync(newDistDir, { recursive: true });
// }
// if (!fs.existsSync(`${newDistDir}/BUILD_ID`)) {
// fs.writeFileSync(`${newDistDir}/BUILD_ID`, "4");
// }
/**
* # Revert Directories
* @param {string} dir - New Build Directory Path
*/
function revert(dir: string) {
console.log("Build Failed!", build?.error?.message || build.stderr);
fs.writeFileSync(`${DIST_DIR}/BUILD`, PREV_BUILD_NO, "utf-8");
execSync(`rm -Rf ${dir}`, { cwd: process.cwd() });
const writeErr = build.error
? build.error.message
: build.stderr
? build.stderr.toString()
: "NO BUILD_ID found in New Build Folder";
fs.writeFileSync(
`${DIST_DIR}/LAST_BUILD_FAIL`,
Date() + "\n\n" + writeErr,
"utf-8"
);
process.exit(1);
}
if (
build.error ||
build.stderr ||
build.status != 0 ||
!fs.existsSync(`${newDistDir}/BUILD_ID`)
) {
revert(newDistDir);
throw new Error("Build Failed!");
}
process.on("exit", () => {
const onExitDir = grabNewDistDir();
if (!fs.existsSync(`${onExitDir}/BUILD_ID`)) {
revert(onExitDir);
}
});
+1
View File
@@ -6,6 +6,7 @@ export interface NodeCIConfig {
first_run?: boolean;
port?: string | number | (string | number)[];
build?: NodeCIBuild;
debounce?: number;
}
export interface NodeCIBuild {
+48 -14
View File
@@ -1,11 +1,6 @@
import { ChildProcess } from "child_process";
import colors from "./console-colors";
import kill from "kill-port";
let childProcess: ChildProcess | null = null;
const pTitle = "nodecid";
process.title = pTitle;
import killPort from "kill-port";
/**
* ## Kill Child Process Function
@@ -13,27 +8,66 @@ process.title = pTitle;
* @returns {Promise<boolean>}
*/
export default async function killChild(
/**
* Child Process to be killed
*/
childProcess?: ChildProcess,
/**
* Port/ports to be killed
*/
port?: string | number | (string | number)[]
): Promise<boolean> {
if (!childProcess) return false;
try {
const childProcessPID = childProcess.pid;
childProcess.kill();
const childKilled = childProcess.kill();
if (childKilled) {
return true;
} else {
return await killPortFn(childProcess, port);
}
} catch (error: any) {
await killPortFn(childProcess, port);
console.log(
`${colors.FgRed}Error:${colors.Reset} Child Process couldn't be killed! ${error.message}`
);
return false;
}
}
async function killPortFn(
/**
* Child Process to be killed
*/
childProcess?: ChildProcess,
/**
* Port/ports to be killed
*/
port?: string | number | (string | number)[]
): Promise<boolean> {
if (!childProcess) return false;
try {
if (typeof port == "object" && port?.[0]) {
for (let i = 0; i < port.length; i++) {
const singlePort = port[i];
await kill(Number(singlePort));
await killPort(Number(singlePort), "tcp");
}
childProcess.kill();
return true;
} else if (port) {
await kill(Number(port));
await killPort(Number(port), "tcp");
childProcess.kill();
return true;
} else {
return false;
}
return true;
} catch (error: any) {
} catch (_err: any) {
console.log(
`${colors.FgRed}Error:${colors.Reset} Child Process couldn't be killed! ${error.message}`
`${colors.FgRed}Error:${colors.Reset} Child Process PORT couldn't be killed! ${_err.message}`
);
return false;
}
+3 -8
View File
@@ -1,13 +1,8 @@
import { spawn, ChildProcess } from "child_process";
import colors from "./console-colors";
let redeployments = 0;
const KILL_SIGNAL: NodeJS.Signals | number = "SIGTERM";
const pTitle = "nodecid";
process.title = pTitle;
/**
* ## Preflight Function
* @param {string} command
@@ -29,14 +24,14 @@ export default function run(command: string): ChildProcess | null {
throw new Error("No Starting Command Found in command string!");
}
let childProcess = spawn(firstCommand, startCommandArray, {
let newChildProcess = spawn(firstCommand, startCommandArray, {
stdio: "inherit",
killSignal: KILL_SIGNAL,
});
redeployments++;
global.REDEPLOYMENTS = global.REDEPLOYMENTS + 1;
return childProcess;
return newChildProcess;
} catch (error: any) {
console.log(
`${colors.FgRed}Error:${colors.Reset} running start command => ${error.message}`
+78 -77
View File
@@ -1,28 +1,27 @@
import fs from "fs";
import { ChildProcess } from "child_process";
import colors from "./console-colors";
import kill from "kill-port";
import preflightFn from "./preflight";
import run from "./run";
import killChild from "./kill-child";
let redeployments = 0;
let childProcess: ChildProcess | null = null;
const pTitle = "nodecid";
const pTitle = "buncid";
process.title = pTitle;
/**
* # Start the process
* @param {object} param0
* @param {string} param0.command
* @param {string[] | string} param0.preflight
* @param {string[] | string} [param0.postflight]
* @param {string} param0.redeploy_file
* @param {string | number | (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`
*/
let timeout: any;
type Param = {
command: string;
preflight?: string[] | string;
postflight?: string[] | string;
redeploy_file: string;
port?: string | number | (string | number)[];
first_run?: boolean;
debounce?: number;
};
export default function startProcess({
command,
preflight,
@@ -30,25 +29,14 @@ export default function startProcess({
redeploy_file,
port,
first_run,
}: {
command: string;
preflight: string[] | string;
postflight?: string[] | string;
redeploy_file: string;
port?: string | number | (string | number)[];
first_run?: boolean;
}) {
debounce,
}: Param) {
const DEBOUNCE = debounce || 1000;
try {
if (first_run) {
console.log("First Run ...");
const runPreflight = preflightFn(preflight);
}
if (!preflight) {
console.log(
`${colors.FgRed}Error:${colors.Reset} No preflight included in config file. If you don't want to run any preflight command simply add an empty array.`
);
process.exit();
const runFirstPreflight = preflightFn(preflight);
}
childProcess = run(command);
@@ -63,57 +51,70 @@ export default function startProcess({
console.log("Watching", redeploy_file);
fs.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => {
console.log(`${colors.BgBlue}File Changed${colors.Reset}`);
if (global.DEPLOYING == 1) return;
if (redeployments == 0) return;
clearTimeout(timeout);
if (childProcess) {
console.log("******************************");
console.log(
`******** ${colors.FgBlue}Rebuilding ${colors.FgMagenta}${redeployments}${colors.Reset} ********`
);
console.log("******************************");
timeout = setTimeout(() => {
console.log(`${colors.BgBlue}File Changed${colors.Reset}`);
try {
const runPreflight = preflightFn(preflight);
if (!runPreflight) {
// TODO: Action to take if preflight fails
console.log(
`${colors.FgRed}Error:${colors.Reset} Preflight Failed.`
);
} else {
killChild(port).then((kill) => {
if (kill) {
childProcess = run(command);
if (postflight) {
const runPostflight = preflightFn(
postflight,
true
);
if (!runPostflight) {
// TODO: Action to take if postflight fails
console.log(
`${colors.FgRed}Error:${colors.Reset} Postflight Failed.`
);
}
}
} else {
process.exit();
}
});
}
} catch (error: any) {
console.log(
`${colors.FgRed}Error:${colors.Reset} killing child processes => ${error.message}`
);
process.exit();
if (global.REDEPLOYMENTS == 0) {
return;
}
}
global.DEPLOYING = 1;
if (childProcess) {
console.log("******************************");
console.log(
`******** ${colors.FgBlue}Rebuilding ${colors.FgMagenta}${global.REDEPLOYMENTS}${colors.Reset} ********`
);
console.log("******************************");
try {
const runPreflight = preflightFn(preflight);
if (!runPreflight) {
console.log(
`${colors.FgRed}Error:${colors.Reset} Preflight Failed.`
);
setTimeout(() => {
global.DEPLOYING = 0;
}, 2000);
} else {
killChild(childProcess, port).then((kill) => {
if (kill) {
childProcess = run(command);
if (postflight) {
const runPostflight = preflightFn(
postflight,
true
);
if (!runPostflight) {
console.log(
`${colors.FgRed}Error:${colors.Reset} Postflight Failed.`
);
}
}
global.DEPLOYING = 0;
} else {
process.exit();
}
});
}
} catch (error: any) {
console.log(
`${colors.FgRed}Error:${colors.Reset} killing child processes => ${error.message}`
);
process.exit();
}
} else {
global.DEPLOYING = 0;
}
}, DEBOUNCE);
});
} catch (error: any) {
console.log(
-3
View File
@@ -1,3 +0,0 @@
function githubWebhook() {
return true;
}