Compare commits
14
Commits
a7b4e3f00b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62eef2f167 | ||
|
|
7e320c87f5 | ||
|
|
7bcddc9517 | ||
|
|
85a64f85d6 | ||
|
|
4540404522 | ||
|
|
7d71316b2c | ||
|
|
69eb6c1128 | ||
|
|
0375c02931 | ||
|
|
1e57cdbc1d | ||
|
|
619afc8303 | ||
|
|
cee4bc0478 | ||
|
|
1c26586478 | ||
|
|
2cd83295bf | ||
|
|
6867e8c17c |
Vendored
+80
-3
@@ -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": {
|
"files.associations": {
|
||||||
|
".env*": "dotenv",
|
||||||
|
".env": "properties",
|
||||||
|
"*.conf": "nginx",
|
||||||
"ostream": "cpp"
|
"ostream": "cpp"
|
||||||
},
|
},
|
||||||
"[python]": {
|
"editor.tokenColorCustomizations": {
|
||||||
"editor.defaultFormatter": "ms-python.autopep8"
|
"[*Light*]": {
|
||||||
|
"textMateRules": [
|
||||||
|
{
|
||||||
|
"scope": "ref.matchtext",
|
||||||
|
"settings": {
|
||||||
|
"foreground": "#000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"python.formatting.provider": "none"
|
"[*Dark*]": {
|
||||||
|
"textMateRules": [
|
||||||
|
{
|
||||||
|
"scope": "ref.matchtext",
|
||||||
|
"settings": {
|
||||||
|
"foreground": "#fff"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"textMateRules": []
|
||||||
|
},
|
||||||
|
"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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,32 +2,27 @@
|
|||||||
|
|
||||||
NOTE: This package is for Bun runtime
|
NOTE: This package is for Bun runtime
|
||||||
|
|
||||||
[](https://bunjs.org/package/nodecid)
|
|
||||||
[](https://bunjs.org/package/nodecid)
|
|
||||||
[](https://github.com/RichardLitt/standard-readme)
|
|
||||||
[](https://bunjs.org/package/nodecid)
|
|
||||||
|
|
||||||
Integrate a simple CI/CD process into your application without the hassle.
|
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
|
## Requirements
|
||||||
|
|
||||||
- **Node JS Runtime and NPM:** You need to have `NodeJS` and `bun` installed on the target machine for this package to work.
|
- **Node JS Runtime and NPM:** You need to have `NodeJS` and `bun` 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.
|
- **`buncid.config.json` file:** This package depends on a configuration file located in the root directory of your application.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
To install this package globally just run:
|
To install this package globally just run:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
bun install -g nodecid
|
bun install -g buncid
|
||||||
```
|
```
|
||||||
|
|
||||||
To run the package directly run:
|
To run the package directly run:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
bunx nodecid
|
bun buncid
|
||||||
```
|
```
|
||||||
|
|
||||||
This will download the package and run the binaries directly. After the first run it won't download the package again.
|
This will download the package and run the binaries directly. After the first run it won't download the package again.
|
||||||
@@ -37,18 +32,18 @@ This will download the package and run the binaries directly. After the first ru
|
|||||||
To run the package after installing it globally just run:
|
To run the package after installing it globally just run:
|
||||||
|
|
||||||
```shell
|
```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
|
### Configuration
|
||||||
|
|
||||||
Your `nodecid.config.json` file should look like this:
|
Your `buncid.config.json` file should look like this:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"start": "node index.js",
|
"start": "bun index.ts",
|
||||||
"preflight": ["bun run test", "bun run build"]
|
"preflight": ["bun run test", "bun run build"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -57,7 +52,7 @@ or
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"start": "node index.js",
|
"start": "bun index.ts",
|
||||||
"preflight": "./preflight.sh"
|
"preflight": "./preflight.sh"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -68,7 +63,7 @@ Optionally you could include a `redeploy_path` in your config file:
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"start": "node index.js",
|
"start": "bun index.ts",
|
||||||
"preflight": "./preflight.sh",
|
"preflight": "./preflight.sh",
|
||||||
"redeploy_path": "./REDEPLOY"
|
"redeploy_path": "./REDEPLOY"
|
||||||
}
|
}
|
||||||
@@ -80,7 +75,7 @@ You can change the name and path of the `redeploy_path`, just make sure the path
|
|||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"start": "node index.js",
|
"start": "bun index.ts",
|
||||||
"preflight": "./preflight.sh",
|
"preflight": "./preflight.sh",
|
||||||
"redeploy_path": "./deploy/trigger.txt"
|
"redeploy_path": "./deploy/trigger.txt"
|
||||||
}
|
}
|
||||||
@@ -97,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.
|
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
|
- **`start`**: _string_: The start Command
|
||||||
- **`preflight`**: _string | Array_: Array of commands or shell script file to run before reloading application
|
- **`preflight`**: _string | Array_: Array of commands or shell script file to run before reloading application
|
||||||
@@ -109,3 +104,32 @@ This app just runs whatever command you send it in an isolated child process, th
|
|||||||
### Redeployment
|
### 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.
|
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.
|
||||||
|
|||||||
@@ -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 ...");
|
||||||
|
});
|
||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
declare global {
|
||||||
|
var REDEPLOYMENTS: number;
|
||||||
|
var DEPLOYING: 0 | 1;
|
||||||
|
}
|
||||||
|
export {};
|
||||||
+55
@@ -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 ...");
|
||||||
|
});
|
||||||
Vendored
+9
-2
@@ -1,2 +1,9 @@
|
|||||||
#!/usr/bin/env node
|
import grabDist from "./rebuilds/next-js/grabDist";
|
||||||
export {};
|
declare const buncid: {
|
||||||
|
builds: {
|
||||||
|
nextJs: {
|
||||||
|
grabDist: typeof grabDist;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default buncid;
|
||||||
|
|||||||
Vendored
+9
-46
@@ -1,51 +1,14 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
"use strict";
|
"use strict";
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
const fs_1 = __importDefault(require("fs"));
|
const grabDist_1 = __importDefault(require("./rebuilds/next-js/grabDist"));
|
||||||
const path_1 = __importDefault(require("path"));
|
const buncid = {
|
||||||
const console_colors_1 = __importDefault(require("./utils/console-colors"));
|
builds: {
|
||||||
const start_1 = __importDefault(require("./utils/start"));
|
nextJs: {
|
||||||
const WORK_DIR = process.cwd();
|
grabDist: grabDist_1.default,
|
||||||
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);
|
exports.default = buncid;
|
||||||
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 ...");
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -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";
|
||||||
|
}
|
||||||
Vendored
+10
@@ -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 {};
|
||||||
Vendored
+47
@@ -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;
|
||||||
|
}
|
||||||
Vendored
+2
@@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
export {};
|
||||||
+132
@@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -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
@@ -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
@@ -0,0 +1,3 @@
|
|||||||
|
import type { NextConfig } from "next";
|
||||||
|
declare const nextConfig: NextConfig;
|
||||||
|
export default nextConfig;
|
||||||
+12
@@ -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;
|
||||||
@@ -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 {};
|
||||||
@@ -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
@@ -0,0 +1,13 @@
|
|||||||
|
declare const _default: {
|
||||||
|
content: string[];
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
background: string;
|
||||||
|
foreground: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
plugins: never[];
|
||||||
|
};
|
||||||
|
export default _default;
|
||||||
+18
@@ -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: [],
|
||||||
|
};
|
||||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -6,6 +6,7 @@ export interface NodeCIConfig {
|
|||||||
first_run?: boolean;
|
first_run?: boolean;
|
||||||
port?: string | number | (string | number)[];
|
port?: string | number | (string | number)[];
|
||||||
build?: NodeCIBuild;
|
build?: NodeCIBuild;
|
||||||
|
debounce?: number;
|
||||||
}
|
}
|
||||||
export interface NodeCIBuild {
|
export interface NodeCIBuild {
|
||||||
paradigm: "Next.JS" | "Remix";
|
paradigm: "Next.JS" | "Remix";
|
||||||
|
|||||||
Vendored
+10
-1
@@ -1,6 +1,15 @@
|
|||||||
|
import { ChildProcess } from "child_process";
|
||||||
/**
|
/**
|
||||||
* ## Kill Child Process Function
|
* ## Kill Child Process Function
|
||||||
* @param {string | number | (string | number)[]} [port]
|
* @param {string | number | (string | number)[]} [port]
|
||||||
* @returns {Promise<boolean>}
|
* @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>;
|
||||||
|
|||||||
Vendored
+52
-13
@@ -15,33 +15,72 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
exports.default = killChild;
|
exports.default = killChild;
|
||||||
const console_colors_1 = __importDefault(require("./console-colors"));
|
const console_colors_1 = __importDefault(require("./console-colors"));
|
||||||
const kill_port_1 = __importDefault(require("kill-port"));
|
const kill_port_1 = __importDefault(require("kill-port"));
|
||||||
let childProcess = null;
|
|
||||||
/**
|
/**
|
||||||
* ## Kill Child Process Function
|
* ## Kill Child Process Function
|
||||||
* @param {string | number | (string | number)[]} [port]
|
* @param {string | number | (string | number)[]} [port]
|
||||||
* @returns {Promise<boolean>}
|
* @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* () {
|
return __awaiter(this, void 0, void 0, function* () {
|
||||||
if (!childProcess)
|
if (!childProcess)
|
||||||
return false;
|
return false;
|
||||||
try {
|
try {
|
||||||
const childProcessPID = childProcess.pid;
|
const childKilled = childProcess.kill();
|
||||||
childProcess.kill();
|
if (childKilled) {
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (port) {
|
|
||||||
yield (0, kill_port_1.default)(Number(port));
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return yield killPortFn(childProcess, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (error) {
|
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}`);
|
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Child Process couldn't be killed! ${error.message}`);
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+3
-4
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|||||||
exports.default = run;
|
exports.default = run;
|
||||||
const child_process_1 = require("child_process");
|
const child_process_1 = require("child_process");
|
||||||
const console_colors_1 = __importDefault(require("./console-colors"));
|
const console_colors_1 = __importDefault(require("./console-colors"));
|
||||||
let redeployments = 0;
|
|
||||||
const KILL_SIGNAL = "SIGTERM";
|
const KILL_SIGNAL = "SIGTERM";
|
||||||
/**
|
/**
|
||||||
* ## Preflight Function
|
* ## Preflight Function
|
||||||
@@ -23,12 +22,12 @@ function run(command) {
|
|||||||
if (!firstCommand) {
|
if (!firstCommand) {
|
||||||
throw new Error("No Starting Command Found in command string!");
|
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",
|
stdio: "inherit",
|
||||||
killSignal: KILL_SIGNAL,
|
killSignal: KILL_SIGNAL,
|
||||||
});
|
});
|
||||||
redeployments++;
|
global.REDEPLOYMENTS = global.REDEPLOYMENTS + 1;
|
||||||
return childProcess;
|
return newChildProcess;
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} running start command => ${error.message}`);
|
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} running start command => ${error.message}`);
|
||||||
|
|||||||
Vendored
+6
-13
@@ -1,18 +1,11 @@
|
|||||||
/**
|
type Param = {
|
||||||
* # 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, }: {
|
|
||||||
command: string;
|
command: string;
|
||||||
preflight: string[] | string;
|
preflight?: string[] | string;
|
||||||
postflight?: string[] | string;
|
postflight?: string[] | string;
|
||||||
redeploy_file: string;
|
redeploy_file: string;
|
||||||
port?: string | number | (string | number)[];
|
port?: string | number | (string | number)[];
|
||||||
first_run?: boolean;
|
first_run?: boolean;
|
||||||
}): void;
|
debounce?: number;
|
||||||
|
};
|
||||||
|
export default function startProcess({ command, preflight, postflight, redeploy_file, port, first_run, debounce, }: Param): void;
|
||||||
|
export {};
|
||||||
|
|||||||
Vendored
+23
-24
@@ -9,29 +9,16 @@ const console_colors_1 = __importDefault(require("./console-colors"));
|
|||||||
const preflight_1 = __importDefault(require("./preflight"));
|
const preflight_1 = __importDefault(require("./preflight"));
|
||||||
const run_1 = __importDefault(require("./run"));
|
const run_1 = __importDefault(require("./run"));
|
||||||
const kill_child_1 = __importDefault(require("./kill-child"));
|
const kill_child_1 = __importDefault(require("./kill-child"));
|
||||||
let redeployments = 0;
|
|
||||||
let childProcess = null;
|
let childProcess = null;
|
||||||
const pTitle = "nodecid";
|
const pTitle = "buncid";
|
||||||
process.title = pTitle;
|
process.title = pTitle;
|
||||||
/**
|
let timeout;
|
||||||
* # Start the process
|
function startProcess({ command, preflight, postflight, redeploy_file, port, first_run, debounce, }) {
|
||||||
* @param {object} param0
|
const DEBOUNCE = debounce || 1000;
|
||||||
* @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, }) {
|
|
||||||
try {
|
try {
|
||||||
if (first_run) {
|
if (first_run) {
|
||||||
console.log("First Run ...");
|
console.log("First Run ...");
|
||||||
const runPreflight = (0, preflight_1.default)(preflight);
|
const runFirstPreflight = (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();
|
|
||||||
}
|
}
|
||||||
childProcess = (0, run_1.default)(command);
|
childProcess = (0, run_1.default)(command);
|
||||||
if (!childProcess) {
|
if (!childProcess) {
|
||||||
@@ -40,30 +27,38 @@ function startProcess({ command, preflight, postflight, redeploy_file, port, fir
|
|||||||
}
|
}
|
||||||
console.log("Watching", redeploy_file);
|
console.log("Watching", redeploy_file);
|
||||||
fs_1.default.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => {
|
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 (global.DEPLOYING == 1)
|
||||||
if (redeployments == 0)
|
|
||||||
return;
|
return;
|
||||||
|
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) {
|
if (childProcess) {
|
||||||
console.log("******************************");
|
console.log("******************************");
|
||||||
console.log(`******** ${console_colors_1.default.FgBlue}Rebuilding ${console_colors_1.default.FgMagenta}${redeployments}${console_colors_1.default.Reset} ********`);
|
console.log(`******** ${console_colors_1.default.FgBlue}Rebuilding ${console_colors_1.default.FgMagenta}${global.REDEPLOYMENTS}${console_colors_1.default.Reset} ********`);
|
||||||
console.log("******************************");
|
console.log("******************************");
|
||||||
try {
|
try {
|
||||||
const runPreflight = (0, preflight_1.default)(preflight);
|
const runPreflight = (0, preflight_1.default)(preflight);
|
||||||
if (!runPreflight) {
|
if (!runPreflight) {
|
||||||
// TODO: Action to take if preflight fails
|
|
||||||
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Preflight Failed.`);
|
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Preflight Failed.`);
|
||||||
|
setTimeout(() => {
|
||||||
|
global.DEPLOYING = 0;
|
||||||
|
}, 2000);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
(0, kill_child_1.default)(port).then((kill) => {
|
(0, kill_child_1.default)(childProcess, port).then((kill) => {
|
||||||
if (kill) {
|
if (kill) {
|
||||||
childProcess = (0, run_1.default)(command);
|
childProcess = (0, run_1.default)(command);
|
||||||
if (postflight) {
|
if (postflight) {
|
||||||
const runPostflight = (0, preflight_1.default)(postflight, true);
|
const runPostflight = (0, preflight_1.default)(postflight, true);
|
||||||
if (!runPostflight) {
|
if (!runPostflight) {
|
||||||
// TODO: Action to take if postflight fails
|
|
||||||
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Postflight Failed.`);
|
console.log(`${console_colors_1.default.FgRed}Error:${console_colors_1.default.Reset} Postflight Failed.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
global.DEPLOYING = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
process.exit();
|
process.exit();
|
||||||
@@ -76,6 +71,10 @@ function startProcess({ command, preflight, postflight, redeploy_file, port, fir
|
|||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
global.DEPLOYING = 0;
|
||||||
|
}
|
||||||
|
}, DEBOUNCE);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
|
|||||||
@@ -1,75 +1,11 @@
|
|||||||
#!/usr/bin/env bun
|
import grabDist from "./rebuilds/next-js/grabDist";
|
||||||
|
|
||||||
import fs from "fs";
|
const buncid = {
|
||||||
import path from "path";
|
builds: {
|
||||||
import colors from "./utils/console-colors";
|
nextJs: {
|
||||||
import startProcess from "./utils/start";
|
grabDist,
|
||||||
import type { NodeCIConfig } from "./types";
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const WORK_DIR = process.cwd();
|
export default buncid;
|
||||||
|
|
||||||
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 ...");
|
|
||||||
});
|
|
||||||
|
|||||||
+20
-18
@@ -1,33 +1,35 @@
|
|||||||
{
|
{
|
||||||
"name": "@moduletrace/buncid",
|
"name": "@moduletrace/buncid",
|
||||||
"version": "1.0.0",
|
"version": "1.1.3",
|
||||||
"description": "Simple CI/CD process For Bun runtime",
|
"author": "Benjamin Toby",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.tben.me/Moduletrace/buncid.git"
|
||||||
|
},
|
||||||
"main": "dist/index.js",
|
"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": {
|
"bin": {
|
||||||
"buncid": "./dist/index.js"
|
"buncid": "./dist/buncid.js",
|
||||||
},
|
"buncid-builds-next": "./dist/rebuilds/next-js/index.js"
|
||||||
"scripts": {
|
|
||||||
"compile": "bun build --compile --minify --sourcemap --bytecode index.ts --outfile bin/nodecid"
|
|
||||||
},
|
},
|
||||||
|
"description": "Simple CI/CD process For Bun runtime",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"CI/CD",
|
"CI/CD",
|
||||||
"Continuous Integration",
|
"Continuous Integration",
|
||||||
"Continous Deployment"
|
"Continous Deployment"
|
||||||
],
|
],
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.tben.me/Moduletrace/nodecid.git"
|
|
||||||
},
|
|
||||||
"author": "Benjamin Toby",
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"compile": "bun build --compile --minify --sourcemap --bytecode index.ts --outfile bin/buncid"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"kill-port": "^2.0.1"
|
"kill-port": "^2.0.1"
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/bun": "latest",
|
|
||||||
"@types/node": "^22.10.7"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"typescript": "^5.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
export default function grabDefaultDistName(): string {
|
||||||
|
return ".buncid-next-dist";
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -6,6 +6,7 @@ export interface NodeCIConfig {
|
|||||||
first_run?: boolean;
|
first_run?: boolean;
|
||||||
port?: string | number | (string | number)[];
|
port?: string | number | (string | number)[];
|
||||||
build?: NodeCIBuild;
|
build?: NodeCIBuild;
|
||||||
|
debounce?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NodeCIBuild {
|
export interface NodeCIBuild {
|
||||||
|
|||||||
+49
-12
@@ -1,8 +1,6 @@
|
|||||||
import { ChildProcess } from "child_process";
|
import { ChildProcess } from "child_process";
|
||||||
import colors from "./console-colors";
|
import colors from "./console-colors";
|
||||||
import kill from "kill-port";
|
import killPort from "kill-port";
|
||||||
|
|
||||||
let childProcess: ChildProcess | null = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ## Kill Child Process Function
|
* ## Kill Child Process Function
|
||||||
@@ -10,27 +8,66 @@ let childProcess: ChildProcess | null = null;
|
|||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
export default async function killChild(
|
export default async function killChild(
|
||||||
|
/**
|
||||||
|
* Child Process to be killed
|
||||||
|
*/
|
||||||
|
childProcess?: ChildProcess,
|
||||||
|
/**
|
||||||
|
* Port/ports to be killed
|
||||||
|
*/
|
||||||
port?: string | number | (string | number)[]
|
port?: string | number | (string | number)[]
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
if (!childProcess) return false;
|
if (!childProcess) return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const childProcessPID = childProcess.pid;
|
const childKilled = childProcess.kill();
|
||||||
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]) {
|
if (typeof port == "object" && port?.[0]) {
|
||||||
for (let i = 0; i < port.length; i++) {
|
for (let i = 0; i < port.length; i++) {
|
||||||
const singlePort = port[i];
|
const singlePort = port[i];
|
||||||
await kill(Number(singlePort));
|
await killPort(Number(singlePort), "tcp");
|
||||||
}
|
}
|
||||||
} else if (port) {
|
childProcess.kill();
|
||||||
await kill(Number(port));
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error: any) {
|
} else if (port) {
|
||||||
|
await killPort(Number(port), "tcp");
|
||||||
|
childProcess.kill();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (_err: any) {
|
||||||
console.log(
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-5
@@ -1,8 +1,6 @@
|
|||||||
import { spawn, ChildProcess } from "child_process";
|
import { spawn, ChildProcess } from "child_process";
|
||||||
import colors from "./console-colors";
|
import colors from "./console-colors";
|
||||||
|
|
||||||
let redeployments = 0;
|
|
||||||
|
|
||||||
const KILL_SIGNAL: NodeJS.Signals | number = "SIGTERM";
|
const KILL_SIGNAL: NodeJS.Signals | number = "SIGTERM";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,14 +24,14 @@ export default function run(command: string): ChildProcess | null {
|
|||||||
throw new Error("No Starting Command Found in command string!");
|
throw new Error("No Starting Command Found in command string!");
|
||||||
}
|
}
|
||||||
|
|
||||||
let childProcess = spawn(firstCommand, startCommandArray, {
|
let newChildProcess = spawn(firstCommand, startCommandArray, {
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
killSignal: KILL_SIGNAL,
|
killSignal: KILL_SIGNAL,
|
||||||
});
|
});
|
||||||
|
|
||||||
redeployments++;
|
global.REDEPLOYMENTS = global.REDEPLOYMENTS + 1;
|
||||||
|
|
||||||
return childProcess;
|
return newChildProcess;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.log(
|
console.log(
|
||||||
`${colors.FgRed}Error:${colors.Reset} running start command => ${error.message}`
|
`${colors.FgRed}Error:${colors.Reset} running start command => ${error.message}`
|
||||||
|
|||||||
+38
-37
@@ -1,28 +1,27 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { ChildProcess } from "child_process";
|
import { ChildProcess } from "child_process";
|
||||||
import colors from "./console-colors";
|
import colors from "./console-colors";
|
||||||
import kill from "kill-port";
|
|
||||||
import preflightFn from "./preflight";
|
import preflightFn from "./preflight";
|
||||||
import run from "./run";
|
import run from "./run";
|
||||||
import killChild from "./kill-child";
|
import killChild from "./kill-child";
|
||||||
|
|
||||||
let redeployments = 0;
|
|
||||||
|
|
||||||
let childProcess: ChildProcess | null = null;
|
let childProcess: ChildProcess | null = null;
|
||||||
|
|
||||||
const pTitle = "nodecid";
|
const pTitle = "buncid";
|
||||||
process.title = pTitle;
|
process.title = pTitle;
|
||||||
|
|
||||||
/**
|
let timeout: any;
|
||||||
* # Start the process
|
|
||||||
* @param {object} param0
|
type Param = {
|
||||||
* @param {string} param0.command
|
command: string;
|
||||||
* @param {string[] | string} param0.preflight
|
preflight?: string[] | string;
|
||||||
* @param {string[] | string} [param0.postflight]
|
postflight?: string[] | string;
|
||||||
* @param {string} param0.redeploy_file
|
redeploy_file: string;
|
||||||
* @param {string | number | (string | number)[]} [param0.port] - The port to kill on rebuild
|
port?: string | number | (string | number)[];
|
||||||
* @param {boolean} [param0.first_run] - Whether to run the preflight on first run. Default `false`
|
first_run?: boolean;
|
||||||
*/
|
debounce?: number;
|
||||||
|
};
|
||||||
|
|
||||||
export default function startProcess({
|
export default function startProcess({
|
||||||
command,
|
command,
|
||||||
preflight,
|
preflight,
|
||||||
@@ -30,25 +29,14 @@ export default function startProcess({
|
|||||||
redeploy_file,
|
redeploy_file,
|
||||||
port,
|
port,
|
||||||
first_run,
|
first_run,
|
||||||
}: {
|
debounce,
|
||||||
command: string;
|
}: Param) {
|
||||||
preflight: string[] | string;
|
const DEBOUNCE = debounce || 1000;
|
||||||
postflight?: string[] | string;
|
|
||||||
redeploy_file: string;
|
|
||||||
port?: string | number | (string | number)[];
|
|
||||||
first_run?: boolean;
|
|
||||||
}) {
|
|
||||||
try {
|
try {
|
||||||
if (first_run) {
|
if (first_run) {
|
||||||
console.log("First Run ...");
|
console.log("First Run ...");
|
||||||
const runPreflight = preflightFn(preflight);
|
const runFirstPreflight = 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
childProcess = run(command);
|
childProcess = run(command);
|
||||||
@@ -63,14 +51,23 @@ export default function startProcess({
|
|||||||
console.log("Watching", redeploy_file);
|
console.log("Watching", redeploy_file);
|
||||||
|
|
||||||
fs.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => {
|
fs.watchFile(redeploy_file, { interval: 100 }, (curr, prev) => {
|
||||||
|
if (global.DEPLOYING == 1) return;
|
||||||
|
|
||||||
|
clearTimeout(timeout);
|
||||||
|
|
||||||
|
timeout = setTimeout(() => {
|
||||||
console.log(`${colors.BgBlue}File Changed${colors.Reset}`);
|
console.log(`${colors.BgBlue}File Changed${colors.Reset}`);
|
||||||
|
|
||||||
if (redeployments == 0) return;
|
if (global.REDEPLOYMENTS == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
global.DEPLOYING = 1;
|
||||||
|
|
||||||
if (childProcess) {
|
if (childProcess) {
|
||||||
console.log("******************************");
|
console.log("******************************");
|
||||||
console.log(
|
console.log(
|
||||||
`******** ${colors.FgBlue}Rebuilding ${colors.FgMagenta}${redeployments}${colors.Reset} ********`
|
`******** ${colors.FgBlue}Rebuilding ${colors.FgMagenta}${global.REDEPLOYMENTS}${colors.Reset} ********`
|
||||||
);
|
);
|
||||||
console.log("******************************");
|
console.log("******************************");
|
||||||
|
|
||||||
@@ -78,13 +75,14 @@ export default function startProcess({
|
|||||||
const runPreflight = preflightFn(preflight);
|
const runPreflight = preflightFn(preflight);
|
||||||
|
|
||||||
if (!runPreflight) {
|
if (!runPreflight) {
|
||||||
// TODO: Action to take if preflight fails
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`${colors.FgRed}Error:${colors.Reset} Preflight Failed.`
|
`${colors.FgRed}Error:${colors.Reset} Preflight Failed.`
|
||||||
);
|
);
|
||||||
|
setTimeout(() => {
|
||||||
|
global.DEPLOYING = 0;
|
||||||
|
}, 2000);
|
||||||
} else {
|
} else {
|
||||||
killChild(port).then((kill) => {
|
killChild(childProcess, port).then((kill) => {
|
||||||
if (kill) {
|
if (kill) {
|
||||||
childProcess = run(command);
|
childProcess = run(command);
|
||||||
|
|
||||||
@@ -95,13 +93,13 @@ export default function startProcess({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!runPostflight) {
|
if (!runPostflight) {
|
||||||
// TODO: Action to take if postflight fails
|
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`${colors.FgRed}Error:${colors.Reset} Postflight Failed.`
|
`${colors.FgRed}Error:${colors.Reset} Postflight Failed.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
global.DEPLOYING = 0;
|
||||||
} else {
|
} else {
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
@@ -113,7 +111,10 @@ export default function startProcess({
|
|||||||
);
|
);
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
global.DEPLOYING = 0;
|
||||||
}
|
}
|
||||||
|
}, DEBOUNCE);
|
||||||
});
|
});
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.log(
|
console.log(
|
||||||
|
|||||||
Reference in New Issue
Block a user