petadep 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli.js +80 -42
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -40,10 +40,31 @@ export async function initConfig({ configPath }) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
function createInterface() {
|
|
43
|
-
|
|
43
|
+
const rl = readline.createInterface({
|
|
44
44
|
input: process.stdin,
|
|
45
45
|
output: process.stdout,
|
|
46
|
+
terminal: true,
|
|
46
47
|
});
|
|
48
|
+
rl._writeToOutput = function writeToOutput(stringToWrite) {
|
|
49
|
+
if (this.stdoutMuted) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.output.write(stringToWrite);
|
|
53
|
+
};
|
|
54
|
+
return rl;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const colors = {
|
|
58
|
+
reset: "\u001b[0m",
|
|
59
|
+
bold: "\u001b[1m",
|
|
60
|
+
cyan: "\u001b[36m",
|
|
61
|
+
green: "\u001b[32m",
|
|
62
|
+
yellow: "\u001b[33m",
|
|
63
|
+
magenta: "\u001b[35m",
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
function color(text, code) {
|
|
67
|
+
return `${code}${text}${colors.reset}`;
|
|
47
68
|
}
|
|
48
69
|
|
|
49
70
|
function prompt(rl, question, defaultValue) {
|
|
@@ -56,50 +77,71 @@ function prompt(rl, question, defaultValue) {
|
|
|
56
77
|
});
|
|
57
78
|
}
|
|
58
79
|
|
|
59
|
-
function promptHidden(question) {
|
|
80
|
+
function promptHidden(rl, question) {
|
|
60
81
|
return new Promise((resolve) => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
input.setRawMode(true);
|
|
67
|
-
input.resume();
|
|
68
|
-
|
|
69
|
-
function onData(chunk) {
|
|
70
|
-
const char = chunk.toString("utf8");
|
|
71
|
-
if (char === "\r" || char === "\n") {
|
|
72
|
-
input.setRawMode(false);
|
|
73
|
-
input.pause();
|
|
74
|
-
input.removeListener("data", onData);
|
|
75
|
-
output.write("\n");
|
|
76
|
-
resolve(value.trim());
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
if (char === "\u0003") {
|
|
80
|
-
process.exit(1);
|
|
81
|
-
}
|
|
82
|
-
if (char === "\u007f") {
|
|
83
|
-
value = value.slice(0, -1);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
value += char;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
input.on("data", onData);
|
|
82
|
+
rl.stdoutMuted = true;
|
|
83
|
+
rl.question(`${question}: `, (answer) => {
|
|
84
|
+
rl.stdoutMuted = false;
|
|
85
|
+
resolve(answer.trim());
|
|
86
|
+
});
|
|
90
87
|
});
|
|
91
88
|
}
|
|
92
89
|
|
|
90
|
+
function normalizeRepo(input) {
|
|
91
|
+
const trimmed = input.trim();
|
|
92
|
+
const sshMatch = trimmed.match(/^git@github\.com:([^/]+\/[^/]+?)(\.git)?$/);
|
|
93
|
+
if (sshMatch) {
|
|
94
|
+
return sshMatch[1];
|
|
95
|
+
}
|
|
96
|
+
const httpsMatch = trimmed.match(/^https?:\/\/github\.com\/([^/]+\/[^/]+?)(\.git)?$/);
|
|
97
|
+
if (httpsMatch) {
|
|
98
|
+
return httpsMatch[1];
|
|
99
|
+
}
|
|
100
|
+
return trimmed;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function isValidRepoFormat(value) {
|
|
104
|
+
return /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(value);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function promptRequired(rl, question, { normalize, validate, hint } = {}) {
|
|
108
|
+
let value = "";
|
|
109
|
+
while (!value) {
|
|
110
|
+
const answer = await prompt(rl, question, "");
|
|
111
|
+
const normalized = normalize ? normalize(answer || "") : (answer || "").trim();
|
|
112
|
+
value = normalized;
|
|
113
|
+
if (!value) {
|
|
114
|
+
console.log(color("This value is required. Try again.", colors.yellow));
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (validate && !validate(value)) {
|
|
118
|
+
const message = hint || "Invalid value. Try again.";
|
|
119
|
+
console.log(color(message, colors.yellow));
|
|
120
|
+
value = "";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
125
|
+
|
|
93
126
|
export async function initConfigInteractive() {
|
|
94
127
|
const rl = createInterface();
|
|
95
128
|
try {
|
|
129
|
+
console.log(color("petadep setup", colors.bold + colors.magenta));
|
|
130
|
+
console.log(color("Let's create your webhook config.", colors.cyan));
|
|
96
131
|
const port = await prompt(rl, "Port", "8787");
|
|
97
132
|
const hookPath = await prompt(rl, "Webhook path", "/webhook");
|
|
98
|
-
const secretInput = await promptHidden(
|
|
99
|
-
|
|
133
|
+
const secretInput = await promptHidden(
|
|
134
|
+
rl,
|
|
135
|
+
"Secret (leave blank to auto-generate)"
|
|
136
|
+
);
|
|
137
|
+
const repo = await promptRequired(rl, "Repo (owner/repo)", {
|
|
138
|
+
normalize: normalizeRepo,
|
|
139
|
+
validate: isValidRepoFormat,
|
|
140
|
+
hint: "Use owner/repo (example: toonami2907/ecommerce-pole). Git URLs are also accepted.",
|
|
141
|
+
});
|
|
100
142
|
const branch = await prompt(rl, "Branch", "main");
|
|
101
143
|
const env = await prompt(rl, "Env name", "production");
|
|
102
|
-
const workdir = await
|
|
144
|
+
const workdir = await promptRequired(rl, "Workdir");
|
|
103
145
|
const script = await prompt(rl, "Script path", "./deploy.sh");
|
|
104
146
|
const logsDir = await prompt(rl, "Logs dir", "./logs");
|
|
105
147
|
const sshKeyPath = await prompt(rl, "SSH key path (optional)", "");
|
|
@@ -120,19 +162,15 @@ export async function initConfigInteractive() {
|
|
|
120
162
|
delete config.sshKeyPath;
|
|
121
163
|
}
|
|
122
164
|
|
|
123
|
-
|
|
124
|
-
config.deployments = [
|
|
125
|
-
{ repo, branch, env, workdir, script },
|
|
126
|
-
];
|
|
127
|
-
}
|
|
165
|
+
config.deployments = [{ repo, branch, env, workdir, script }];
|
|
128
166
|
|
|
129
167
|
const resolvedPath = path.resolve(savePath);
|
|
130
168
|
await fs.mkdir(path.dirname(resolvedPath), { recursive: true });
|
|
131
169
|
await fs.writeFile(resolvedPath, JSON.stringify(config, null, 2));
|
|
132
170
|
|
|
133
|
-
console.log("Config created:", resolvedPath);
|
|
134
|
-
console.log("Webhook secret:", secret);
|
|
135
|
-
console.log(
|
|
171
|
+
console.log(color("Config created:", colors.green), resolvedPath);
|
|
172
|
+
console.log(color("Webhook secret:", colors.green), secret);
|
|
173
|
+
console.log(color("Start agent:", colors.cyan), `petadep agent --config ${resolvedPath}`);
|
|
136
174
|
} finally {
|
|
137
175
|
rl.close();
|
|
138
176
|
}
|