-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathindex.js
More file actions
231 lines (113 loc) · 4.63 KB
/
index.js
File metadata and controls
231 lines (113 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
const { access, rm } = require("fs/promises")
const { exec, fork } = require("child_process");
const path = require("path");
const config = require("./config.json");
let app;
const dir = `${path.dirname(require.main.filename).replaceAll("\\", "/")}/`;
const repo_dir = dir + "repo/";
start();
async function start() {
validate_config(config)
.then(() => scan())
.catch(console.error);
}
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function get_version(cwd = repo_dir, remote = false) {
return execute(`git rev-parse --short --verify ${remote ? "origin/" : ""}${config.branch}`, { cwd });
}
async function validate_config() {
const repo = config.repo.match(/(https?:\/{2}github\.com\/.+?\/([^\/]+))\/?/);
if (!config.repo) throw new Error("[@] Github repository not provided!")
else config.repo = repo[1];
if (!config.branch) throw new Error("[@] Github branch not provided!");
if (!config.start) throw new Error("[@] Start command not provided!");
if (!config.setup) console.warn("[!] Setup command not provided.");
if (config.frequency > 1000) console.warn("[!] The scan frequency should be in seconds. The value provided is VERY HIGH!");
return true;
}
async function match_version(cwd = repo_dir) {
await execute("git remote update", { cwd })
.catch((res) => console.log("[-] " + res.split("\n")[1].trim()));
const remote = await get_version(cwd, true), local = await get_version(cwd, false);
return remote === local;
}
async function match_origin(cwd = repo_dir) {
const origin = await execute("git remote get-url origin", { cwd })
.catch(console.error);
return config.repo === origin;
}
async function fork_app(cwd = repo_dir) {
if (app && !app?.killed) return console.warn("[!] App has already been terminated.");
console.log("[.] Preparing environment.");
await execute(config.setup, { cwd })
.then(() => {
if (config.verbose) console.log("[+] Environment ready for runtime.")
})
.catch(console.warn);
console.log("[.] Initialising child process.");
if (config.verbose) console.log(`Executing: ${config.start.trim()}`);
return app = fork(cwd, config.start.split(/ +/g)).addListener("spawn", () => console.log("[+] Process spawned successfully."));
}
async function clone(repo = config.repo, cwd = dir) {
return execute(`git clone ${repo} repo`, { cwd });
}
function execute(command, options = {}) {
return new Promise((resolve, reject) => {
if (config.verbose) console.log("Executing:", command)
exec(command, options,
(err, stdout, stderr) => {
if (err) reject(err);
else if (stderr) reject(stderr);
else resolve(stdout.trim());
});
});
}
function remove_dir(dir = repo_dir) {
return new Promise(async (resolve, reject) => {
rm(dir, { recursive: true, force: true },
(err) => {
if (err) reject(err);
})
.then(() => resolve(true))
})
}
function repo_exists(dir = repo_dir) {
return new Promise((resolve) => {
access(dir)
.then(() => resolve(true))
.catch(() => {
console.warn("[!] Repository folder not found.");
resolve(false);
});
})
}
async function reset_app() {
if (app && !app.killed) {
console.log("[.] Attempting app termination.");
if (app.kill()) {
if (config.verbose) console.log("[+] App terminated successfully.");
}
else throw new Error("[@] Something went wrong while terminating app.");
}
if (config.verbose) console.log("[.] Clearing remnants.");
await remove_dir()
.then(() => {
if (config.verbose) console.log("[+] Outdated files removed.");
})
.catch(new Error);
console.log("[.] Cloning up-to-date repository.");
await clone(config.repo)
.catch(() => {
if (config.verbose) console.log("[+] Repository cloned successfully.")
})
}
async function scan() {
if (!await repo_exists()) await reset_app();
else if (!await match_origin() || !await match_version()) await reset_app();
else if (config.verbose) console.debug("[+] Your branch is on the latest commit.")
if (!app || app.killed) await fork_app();
return sleep(config.frequency * 1000)
.then(() => scan());
}