mimi-seed 0.2.1 → 0.2.3
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/README.md +1 -1
- package/dist/chunk-FW4DVFZD.js +57 -0
- package/dist/index.js +406 -100
- package/dist/mcp-client-U3CS5OZN.js +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -162,7 +162,7 @@ on:
|
|
|
162
162
|
|
|
163
163
|
jobs:
|
|
164
164
|
release:
|
|
165
|
-
uses: jeonghwanko/
|
|
165
|
+
uses: jeonghwanko/mimi-seed/.github/workflows/mimi-seed-release.yml@master
|
|
166
166
|
with:
|
|
167
167
|
locales: 'ko,en-US' # 다국어 릴리즈 노트
|
|
168
168
|
apply-notes: true # 스토어에 자동 적용
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/mcp-client.ts
|
|
4
|
+
async function postMcp(endpoint, token, body, sessionId) {
|
|
5
|
+
const headers = {
|
|
6
|
+
"Content-Type": "application/json",
|
|
7
|
+
Accept: "application/json, text/event-stream",
|
|
8
|
+
Authorization: `Bearer ${token}`
|
|
9
|
+
};
|
|
10
|
+
if (sessionId) headers["Mcp-Session-Id"] = sessionId;
|
|
11
|
+
const res = await fetch(endpoint, { method: "POST", headers, body: JSON.stringify(body) });
|
|
12
|
+
const newSession = res.headers.get("Mcp-Session-Id") ?? sessionId ?? null;
|
|
13
|
+
const contentType = res.headers.get("content-type") ?? "";
|
|
14
|
+
let payload;
|
|
15
|
+
if (contentType.includes("text/event-stream")) {
|
|
16
|
+
const text = await res.text();
|
|
17
|
+
const line = text.split("\n").map((l) => l.trim()).find((l) => l.startsWith("data:"));
|
|
18
|
+
if (!line) throw new Error("MCP SSE \uC751\uB2F5\uC5D0 data \uC5C6\uC74C");
|
|
19
|
+
payload = JSON.parse(line.slice(5).trim());
|
|
20
|
+
} else {
|
|
21
|
+
payload = await res.json();
|
|
22
|
+
}
|
|
23
|
+
return { payload, sessionId: newSession };
|
|
24
|
+
}
|
|
25
|
+
async function mcpCall(endpoint, token, name, args) {
|
|
26
|
+
const { payload: initPayload, sessionId } = await postMcp(endpoint, token, {
|
|
27
|
+
jsonrpc: "2.0",
|
|
28
|
+
id: 1,
|
|
29
|
+
method: "initialize",
|
|
30
|
+
params: {
|
|
31
|
+
protocolVersion: "2024-11-05",
|
|
32
|
+
capabilities: {},
|
|
33
|
+
clientInfo: { name: "mimi-seed-cli", version: "1.0.0" }
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if (initPayload.error) throw new Error(`MCP init \uC2E4\uD328: ${initPayload.error.message}`);
|
|
37
|
+
await postMcp(endpoint, token, {
|
|
38
|
+
jsonrpc: "2.0",
|
|
39
|
+
method: "notifications/initialized"
|
|
40
|
+
}, sessionId ?? void 0).catch(() => null);
|
|
41
|
+
const { payload } = await postMcp(endpoint, token, {
|
|
42
|
+
jsonrpc: "2.0",
|
|
43
|
+
id: 2,
|
|
44
|
+
method: "tools/call",
|
|
45
|
+
params: { name, arguments: args }
|
|
46
|
+
}, sessionId ?? void 0);
|
|
47
|
+
if (payload.error) {
|
|
48
|
+
return { text: payload.error.message, isError: true };
|
|
49
|
+
}
|
|
50
|
+
const content = payload.result?.content ?? [];
|
|
51
|
+
const text = content.filter((c) => c.type === "text").map((c) => c.text ?? "").join("\n");
|
|
52
|
+
return { text, isError: payload.result?.isError ?? false };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export {
|
|
56
|
+
mcpCall
|
|
57
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
mcpCall
|
|
4
|
+
} from "./chunk-FW4DVFZD.js";
|
|
2
5
|
|
|
3
6
|
// src/index.ts
|
|
4
7
|
import os2 from "os";
|
|
5
|
-
import
|
|
8
|
+
import kleur7 from "kleur";
|
|
6
9
|
import open from "open";
|
|
7
10
|
|
|
8
11
|
// src/detect.ts
|
|
@@ -209,40 +212,6 @@ async function awaitHandshake(timeoutMs) {
|
|
|
209
212
|
return { port, promise };
|
|
210
213
|
}
|
|
211
214
|
|
|
212
|
-
// src/mcp-client.ts
|
|
213
|
-
async function mcpCall(endpoint, token, name, args) {
|
|
214
|
-
const res = await fetch(endpoint, {
|
|
215
|
-
method: "POST",
|
|
216
|
-
headers: {
|
|
217
|
-
"Content-Type": "application/json",
|
|
218
|
-
Accept: "application/json, text/event-stream",
|
|
219
|
-
Authorization: `Bearer ${token}`
|
|
220
|
-
},
|
|
221
|
-
body: JSON.stringify({
|
|
222
|
-
jsonrpc: "2.0",
|
|
223
|
-
id: 1,
|
|
224
|
-
method: "tools/call",
|
|
225
|
-
params: { name, arguments: args }
|
|
226
|
-
})
|
|
227
|
-
});
|
|
228
|
-
const contentType = res.headers.get("content-type") ?? "";
|
|
229
|
-
let payload;
|
|
230
|
-
if (contentType.includes("text/event-stream")) {
|
|
231
|
-
const text2 = await res.text();
|
|
232
|
-
const line = text2.split("\n").map((l) => l.trim()).find((l) => l.startsWith("data:"));
|
|
233
|
-
if (!line) throw new Error("MCP SSE \uC751\uB2F5\uC5D0 data \uC5C6\uC74C");
|
|
234
|
-
payload = JSON.parse(line.slice(5).trim());
|
|
235
|
-
} else {
|
|
236
|
-
payload = await res.json();
|
|
237
|
-
}
|
|
238
|
-
if (payload.error) {
|
|
239
|
-
return { text: payload.error.message, isError: true };
|
|
240
|
-
}
|
|
241
|
-
const content = payload.result?.content ?? [];
|
|
242
|
-
const text = content.filter((c) => c.type === "text").map((c) => c.text ?? "").join("\n");
|
|
243
|
-
return { text, isError: payload.result?.isError ?? false };
|
|
244
|
-
}
|
|
245
|
-
|
|
246
215
|
// src/config.ts
|
|
247
216
|
import fs2 from "fs/promises";
|
|
248
217
|
import path2 from "path";
|
|
@@ -259,7 +228,10 @@ async function readConfig() {
|
|
|
259
228
|
}
|
|
260
229
|
async function writeConfig(cfg) {
|
|
261
230
|
await fs2.mkdir(CONFIG_DIR, { recursive: true });
|
|
262
|
-
await fs2.writeFile(CONFIG_PATH, JSON.stringify(cfg, null, 2)
|
|
231
|
+
await fs2.writeFile(CONFIG_PATH, JSON.stringify(cfg, null, 2));
|
|
232
|
+
if (process.platform !== "win32") {
|
|
233
|
+
await fs2.chmod(CONFIG_PATH, 384);
|
|
234
|
+
}
|
|
263
235
|
}
|
|
264
236
|
async function deleteConfig() {
|
|
265
237
|
await fs2.rm(CONFIG_PATH, { force: true });
|
|
@@ -807,62 +779,377 @@ async function cmdReview(argv) {
|
|
|
807
779
|
`) : kleur4.green("\u2713 \uB2F5\uBCC0 \uAC8C\uC2DC \uC644\uB8CC\n"));
|
|
808
780
|
}
|
|
809
781
|
|
|
782
|
+
// src/auth.ts
|
|
783
|
+
import { spawn } from "child_process";
|
|
784
|
+
import kleur5 from "kleur";
|
|
785
|
+
var MCP_PKG = "@yoonion/mimi-seed-mcp";
|
|
786
|
+
function log(msg) {
|
|
787
|
+
process.stdout.write(msg + "\n");
|
|
788
|
+
}
|
|
789
|
+
function printAuthHelp() {
|
|
790
|
+
log(`${kleur5.bold("mimi-seed auth")} \u2014 Google OAuth \uC778\uC99D (Firebase / AdMob / Play Store)
|
|
791
|
+
|
|
792
|
+
${kleur5.bold("\uC11C\uBE0C\uBA85\uB839:")}
|
|
793
|
+
${kleur5.cyan("mimi-seed auth login")} \uBE0C\uB77C\uC6B0\uC800\uB85C \uB85C\uADF8\uC778 (\uC774\uBBF8 \uC788\uC73C\uBA74 \uC790\uB3D9 refresh \uC2DC\uB3C4)
|
|
794
|
+
${kleur5.cyan("mimi-seed auth status")} \uD604\uC7AC \uD1A0\uD070 \uC0C1\uD0DC
|
|
795
|
+
${kleur5.cyan("mimi-seed auth refresh")} refresh_token\uC73C\uB85C \uAC31\uC2E0\uB9CC \uC2DC\uB3C4 (\uBE0C\uB77C\uC6B0\uC800 X)
|
|
796
|
+
${kleur5.cyan("mimi-seed auth logout")} \uD1A0\uD070 \uC0AD\uC81C
|
|
797
|
+
|
|
798
|
+
${kleur5.bold("login \uC635\uC158:")}
|
|
799
|
+
--no-browser URL \uC790\uB3D9 \uC624\uD508 \uC548 \uD568 (\uC9C1\uC811 \uBCF5\uBD99)
|
|
800
|
+
--timeout <\uCD08> \uCF5C\uBC31 \uB300\uAE30 \uC2DC\uAC04 (\uAE30\uBCF8 600)
|
|
801
|
+
--force \uAE30\uC874 \uD1A0\uD070 \uBB34\uC2DC\uD558\uACE0 \uAC15\uC81C \uC7AC\uB85C\uADF8\uC778
|
|
802
|
+
|
|
803
|
+
${kleur5.dim(`\uB0B4\uBD80\uC801\uC73C\uB85C ${MCP_PKG} \uC758 mimi-seed-auth CLI\uB97C \uD638\uCD9C\uD569\uB2C8\uB2E4.`)}`);
|
|
804
|
+
}
|
|
805
|
+
async function runMcpAuth(extraArgs) {
|
|
806
|
+
return new Promise((resolve) => {
|
|
807
|
+
const child = spawn("npx", ["-y", `${MCP_PKG}`, "mimi-seed-auth", ...extraArgs], {
|
|
808
|
+
stdio: "inherit",
|
|
809
|
+
shell: true
|
|
810
|
+
});
|
|
811
|
+
child.on("error", (e) => {
|
|
812
|
+
process.stderr.write(`
|
|
813
|
+
\u274C npx \uC2E4\uD589 \uC2E4\uD328: ${e.message}
|
|
814
|
+
`);
|
|
815
|
+
resolve(1);
|
|
816
|
+
});
|
|
817
|
+
child.on("exit", (code) => resolve(code ?? 0));
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
async function cmdAuth(args) {
|
|
821
|
+
const sub = args[0];
|
|
822
|
+
const rest = args.slice(1);
|
|
823
|
+
if (sub === "--help" || sub === "-h" || sub === "help") {
|
|
824
|
+
printAuthHelp();
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
let mcpArgs;
|
|
828
|
+
switch (sub) {
|
|
829
|
+
case void 0:
|
|
830
|
+
case "login":
|
|
831
|
+
mcpArgs = rest;
|
|
832
|
+
break;
|
|
833
|
+
case "status":
|
|
834
|
+
mcpArgs = ["--status", ...rest];
|
|
835
|
+
break;
|
|
836
|
+
case "refresh":
|
|
837
|
+
mcpArgs = ["--refresh", ...rest];
|
|
838
|
+
break;
|
|
839
|
+
case "logout":
|
|
840
|
+
mcpArgs = ["--logout", ...rest];
|
|
841
|
+
break;
|
|
842
|
+
default:
|
|
843
|
+
log(kleur5.red(`\uC54C \uC218 \uC5C6\uB294 auth \uC11C\uBE0C\uBA85\uB839: ${sub}`));
|
|
844
|
+
printAuthHelp();
|
|
845
|
+
process.exit(1);
|
|
846
|
+
}
|
|
847
|
+
const code = await runMcpAuth(mcpArgs);
|
|
848
|
+
if (code !== 0) process.exit(code);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// src/deploy.ts
|
|
852
|
+
import kleur6 from "kleur";
|
|
853
|
+
import * as readline from "readline";
|
|
854
|
+
var PHASE_ICON = {
|
|
855
|
+
init: "\u{1F680}",
|
|
856
|
+
verify: "\u{1F50D}",
|
|
857
|
+
notes: "\u{1F4DD}",
|
|
858
|
+
apply: "\u{1F4E4}",
|
|
859
|
+
promote: "\u{1F3AF}",
|
|
860
|
+
done: "\u{1F389}",
|
|
861
|
+
error: "\u274C"
|
|
862
|
+
};
|
|
863
|
+
function log2(msg) {
|
|
864
|
+
process.stdout.write(msg + "\n");
|
|
865
|
+
}
|
|
866
|
+
function jenkinsHeaders(cfg) {
|
|
867
|
+
const creds = Buffer.from(`${cfg.user ?? "admin"}:${cfg.token}`).toString("base64");
|
|
868
|
+
return { Authorization: `Basic ${creds}`, "Content-Type": "application/json" };
|
|
869
|
+
}
|
|
870
|
+
async function triggerBuild(cfg, jobName, params) {
|
|
871
|
+
const qs = new URLSearchParams(params).toString();
|
|
872
|
+
const url = `${cfg.url}/job/${encodeURIComponent(jobName)}/buildWithParameters?${qs}`;
|
|
873
|
+
const res = await fetch(url, { method: "POST", headers: jenkinsHeaders(cfg) });
|
|
874
|
+
if (!res.ok) {
|
|
875
|
+
throw new Error(`Jenkins \uD2B8\uB9AC\uAC70 \uC2E4\uD328 ${res.status}: ${await res.text()}`);
|
|
876
|
+
}
|
|
877
|
+
const location = res.headers.get("Location") ?? "";
|
|
878
|
+
const match = location.match(/\/queue\/item\/(\d+)\//);
|
|
879
|
+
return match?.[1] ?? "";
|
|
880
|
+
}
|
|
881
|
+
async function getQueueBuildNumber(cfg, queueItemId) {
|
|
882
|
+
const url = `${cfg.url}/queue/item/${queueItemId}/api/json`;
|
|
883
|
+
const res = await fetch(url, { headers: jenkinsHeaders(cfg) });
|
|
884
|
+
if (!res.ok) return null;
|
|
885
|
+
const data = await res.json();
|
|
886
|
+
return data.executable?.number ?? null;
|
|
887
|
+
}
|
|
888
|
+
async function getBuildStatus(cfg, jobName, buildNumber) {
|
|
889
|
+
const url = `${cfg.url}/job/${encodeURIComponent(jobName)}/${buildNumber}/api/json`;
|
|
890
|
+
const res = await fetch(url, { headers: jenkinsHeaders(cfg) });
|
|
891
|
+
if (!res.ok) throw new Error(`\uBE4C\uB4DC \uC0C1\uD0DC \uC870\uD68C \uC2E4\uD328 ${res.status}`);
|
|
892
|
+
const data = await res.json();
|
|
893
|
+
return {
|
|
894
|
+
building: data.building ?? true,
|
|
895
|
+
result: data.result ?? null,
|
|
896
|
+
duration: data.duration ?? 0
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
async function pollBuildComplete(cfg, jobName, buildNumber, timeoutMs = 30 * 60 * 1e3) {
|
|
900
|
+
const start = Date.now();
|
|
901
|
+
const intervalMs = 15e3;
|
|
902
|
+
let dots = 0;
|
|
903
|
+
let consecutiveErrors = 0;
|
|
904
|
+
while (Date.now() - start < timeoutMs) {
|
|
905
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
906
|
+
let status;
|
|
907
|
+
try {
|
|
908
|
+
status = await getBuildStatus(cfg, jobName, buildNumber);
|
|
909
|
+
consecutiveErrors = 0;
|
|
910
|
+
} catch {
|
|
911
|
+
consecutiveErrors++;
|
|
912
|
+
if (consecutiveErrors >= 3) throw new Error("Jenkins \uC5F0\uACB0 \uC624\uB958 3\uD68C \uC5F0\uC18D \u2014 \uB124\uD2B8\uC6CC\uD06C\uB97C \uD655\uC778\uD558\uC138\uC694");
|
|
913
|
+
process.stdout.write(`\r \u26A0 Jenkins \uC5F0\uACB0 \uC624\uB958 (${consecutiveErrors}/3\uD68C), \uC7AC\uC2DC\uB3C4... `);
|
|
914
|
+
continue;
|
|
915
|
+
}
|
|
916
|
+
dots = (dots + 1) % 4;
|
|
917
|
+
process.stdout.write(`\r \u23F3 \uBE4C\uB4DC \uC9C4\uD589 \uC911${".".repeat(dots + 1)} `);
|
|
918
|
+
if (!status.building) {
|
|
919
|
+
process.stdout.write("\n");
|
|
920
|
+
return status.result ?? "FAILURE";
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
throw new Error("\uBE4C\uB4DC \uD0C0\uC784\uC544\uC6C3 (30\uBD84)");
|
|
924
|
+
}
|
|
925
|
+
async function streamDeploy(webBase, token, body) {
|
|
926
|
+
const res = await fetch(`${webBase}/api/deploy`, {
|
|
927
|
+
method: "POST",
|
|
928
|
+
headers: {
|
|
929
|
+
"Content-Type": "application/json",
|
|
930
|
+
Authorization: `Bearer ${token}`
|
|
931
|
+
},
|
|
932
|
+
body: JSON.stringify(body)
|
|
933
|
+
});
|
|
934
|
+
if (!res.ok) {
|
|
935
|
+
const text = await res.text().catch(() => "");
|
|
936
|
+
throw new Error(`\uC11C\uBC84 \uBC30\uD3EC \uC2E4\uD328 ${res.status}: ${text.slice(0, 200)}`);
|
|
937
|
+
}
|
|
938
|
+
const reader = res.body?.getReader();
|
|
939
|
+
if (!reader) throw new Error("SSE \uC2A4\uD2B8\uB9BC \uC5C6\uC74C");
|
|
940
|
+
const decoder = new TextDecoder();
|
|
941
|
+
let buf = "";
|
|
942
|
+
while (true) {
|
|
943
|
+
const { done, value } = await reader.read();
|
|
944
|
+
if (done) break;
|
|
945
|
+
buf += decoder.decode(value, { stream: true });
|
|
946
|
+
const lines = buf.split("\n");
|
|
947
|
+
buf = lines.pop() ?? "";
|
|
948
|
+
for (const line of lines) {
|
|
949
|
+
if (!line.startsWith("data: ")) continue;
|
|
950
|
+
try {
|
|
951
|
+
const event = JSON.parse(line.slice(6));
|
|
952
|
+
const icon = PHASE_ICON[event.phase] ?? "\u25B8";
|
|
953
|
+
const color = event.status === "done" ? kleur6.green : event.status === "failed" ? kleur6.red : event.status === "skipped" ? kleur6.yellow : kleur6.dim;
|
|
954
|
+
log2(` ${icon} ${color(event.message)}`);
|
|
955
|
+
if (event.phase === "error" || event.phase === "verify" && event.status === "failed" || event.phase === "promote" && event.status === "failed") {
|
|
956
|
+
process.exit(1);
|
|
957
|
+
}
|
|
958
|
+
} catch {
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
function parseArgs4(argv) {
|
|
964
|
+
const args = { platform: "android", language: "ko-KR", dryRun: false, skipBuild: false, setupJenkins: false };
|
|
965
|
+
for (let i = 0; i < argv.length; i++) {
|
|
966
|
+
if ((argv[i] === "--platform" || argv[i] === "-p") && argv[i + 1]) args.platform = argv[++i];
|
|
967
|
+
if (argv[i] === "--app" && argv[i + 1]) args.appId = argv[++i];
|
|
968
|
+
if (argv[i] === "--version-code" && argv[i + 1]) args.versionCode = Number(argv[++i]);
|
|
969
|
+
if (argv[i] === "--from" && argv[i + 1]) args.fromRef = argv[++i];
|
|
970
|
+
if (argv[i] === "--to" && argv[i + 1]) args.toRef = argv[++i];
|
|
971
|
+
if (argv[i] === "--language" && argv[i + 1]) args.language = argv[++i];
|
|
972
|
+
if (argv[i] === "--dry-run") args.dryRun = true;
|
|
973
|
+
if (argv[i] === "--skip-build") args.skipBuild = true;
|
|
974
|
+
if (argv[i] === "setup-jenkins") args.setupJenkins = true;
|
|
975
|
+
}
|
|
976
|
+
return args;
|
|
977
|
+
}
|
|
978
|
+
async function promptJenkinsSetup() {
|
|
979
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
980
|
+
const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a.trim())));
|
|
981
|
+
log2(kleur6.bold("Jenkins \uC124\uC815"));
|
|
982
|
+
const url = await ask(" Jenkins URL (\uC608: http://192.168.30.16:8080): ");
|
|
983
|
+
const user = await ask(" Jenkins \uC0AC\uC6A9\uC790\uBA85 (\uC608: admin): ");
|
|
984
|
+
const token = await ask(" Jenkins API Token: ");
|
|
985
|
+
const jobAndroid = await ask(" Android Job \uC774\uB984 (\uC608: my-app-android): ");
|
|
986
|
+
const jobIos = await ask(" iOS Job \uC774\uB984 (\uC120\uD0DD, \uC5D4\uD130 \uC2A4\uD0B5): ");
|
|
987
|
+
rl.close();
|
|
988
|
+
return { url, user, token, jobAndroid: jobAndroid || void 0, jobIos: jobIos || void 0 };
|
|
989
|
+
}
|
|
990
|
+
async function cmdDeploy(argv) {
|
|
991
|
+
const args = parseArgs4(argv);
|
|
992
|
+
const cfg = await getEffectiveConfig();
|
|
993
|
+
if (!cfg) {
|
|
994
|
+
log2(kleur6.red("\uC5F0\uACB0\uB41C \uACC4\uC815 \uC5C6\uC74C. `mimi-seed init` \uC2E4\uD589."));
|
|
995
|
+
process.exit(1);
|
|
996
|
+
}
|
|
997
|
+
if (args.setupJenkins) {
|
|
998
|
+
const jenkins = await promptJenkinsSetup();
|
|
999
|
+
await writeConfig({ ...cfg, jenkins });
|
|
1000
|
+
log2(kleur6.green("\u2705 Jenkins \uC124\uC815 \uC800\uC7A5\uB428"));
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
log2(kleur6.bold(`mimi-seed deploy \u2014 ${args.platform}`));
|
|
1004
|
+
if (args.dryRun) log2(kleur6.yellow(" [dry-run \uBAA8\uB4DC] \uC2E4\uC81C \uBC30\uD3EC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4"));
|
|
1005
|
+
log2("");
|
|
1006
|
+
let versionCode = args.versionCode;
|
|
1007
|
+
if (!args.skipBuild) {
|
|
1008
|
+
if (!cfg.jenkins?.url || !cfg.jenkins?.token) {
|
|
1009
|
+
log2(kleur6.yellow("Jenkins \uC124\uC815 \uC5C6\uC74C. `mimi-seed deploy setup-jenkins` \uB85C \uC124\uC815\uD558\uAC70\uB098 --skip-build \uC0AC\uC6A9."));
|
|
1010
|
+
log2(kleur6.dim(" \uB610\uB294 \uC11C\uBC84 /workspace/integrations\uC5D0\uC11C jenkins \uD504\uB85C\uBC14\uC774\uB354 \uB4F1\uB85D \uD6C4 \uC11C\uBC84\uC0AC\uC774\uB4DC \uD2B8\uB9AC\uAC70 \uAC00\uB2A5."));
|
|
1011
|
+
process.exit(1);
|
|
1012
|
+
}
|
|
1013
|
+
const jenkins = cfg.jenkins;
|
|
1014
|
+
const jobName = args.platform === "android" ? jenkins.jobAndroid : jenkins.jobIos;
|
|
1015
|
+
if (!jobName) {
|
|
1016
|
+
log2(kleur6.red(`${args.platform} Jenkins job\uC774 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. setup-jenkins \uC2E4\uD589.`));
|
|
1017
|
+
process.exit(1);
|
|
1018
|
+
}
|
|
1019
|
+
log2(`\u{1F528} Jenkins \uBE4C\uB4DC \uD2B8\uB9AC\uAC70: ${kleur6.cyan(jobName)}`);
|
|
1020
|
+
const buildParams = {};
|
|
1021
|
+
if (args.appId) buildParams.MIMI_APP_ID = args.appId;
|
|
1022
|
+
const queueItemId = await triggerBuild(jenkins, jobName, buildParams);
|
|
1023
|
+
if (!queueItemId) {
|
|
1024
|
+
log2(kleur6.yellow(" \u26A0 Queue item ID\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uBE4C\uB4DC\uB294 \uC2DC\uC791\uB410\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4."));
|
|
1025
|
+
} else {
|
|
1026
|
+
log2(kleur6.dim(` Queue item: ${queueItemId}`));
|
|
1027
|
+
}
|
|
1028
|
+
let buildNumber = null;
|
|
1029
|
+
if (queueItemId) {
|
|
1030
|
+
log2(" \uBE4C\uB4DC \uBC88\uD638 \uB300\uAE30 \uC911...");
|
|
1031
|
+
for (let i = 0; i < 6; i++) {
|
|
1032
|
+
await new Promise((r) => setTimeout(r, 5e3));
|
|
1033
|
+
buildNumber = await getQueueBuildNumber(jenkins, queueItemId).catch(() => null);
|
|
1034
|
+
if (buildNumber) break;
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
if (!buildNumber) {
|
|
1038
|
+
log2(kleur6.yellow(" \uBE4C\uB4DC \uBC88\uD638\uB97C \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. --skip-build + --version-code \uB85C \uC7AC\uC2DC\uB3C4 \uAC00\uB2A5."));
|
|
1039
|
+
process.exit(1);
|
|
1040
|
+
}
|
|
1041
|
+
log2(` \uBE4C\uB4DC #${buildNumber} \uC2DC\uC791\uB428. \uC644\uB8CC \uB300\uAE30 \uC911...`);
|
|
1042
|
+
const result = await pollBuildComplete(jenkins, jobName, buildNumber);
|
|
1043
|
+
if (result !== "SUCCESS") {
|
|
1044
|
+
log2(kleur6.red(`\uBE4C\uB4DC \uC2E4\uD328: ${result}`));
|
|
1045
|
+
log2(kleur6.dim(` Jenkins: ${jenkins.url}/job/${encodeURIComponent(jobName)}/${buildNumber}/`));
|
|
1046
|
+
log2(kleur6.dim(` \uBE4C\uB4DC\uAC00 \uC774\uBBF8 \uC644\uB8CC\uB410\uB2E4\uBA74: mimi-seed deploy --skip-build --version-code ${buildNumber} --platform ${args.platform}`));
|
|
1047
|
+
process.exit(1);
|
|
1048
|
+
}
|
|
1049
|
+
log2(kleur6.green(`\u2705 \uBE4C\uB4DC #${buildNumber} \uC131\uACF5`));
|
|
1050
|
+
if (!versionCode) {
|
|
1051
|
+
versionCode = buildNumber;
|
|
1052
|
+
log2(kleur6.dim(` versionCode = buildNumber (${versionCode})`));
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
if (!versionCode) {
|
|
1056
|
+
log2(kleur6.red("versionCode\uB97C \uC54C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. --version-code <N> \uC73C\uB85C \uC9C0\uC815\uD558\uC138\uC694."));
|
|
1057
|
+
process.exit(1);
|
|
1058
|
+
}
|
|
1059
|
+
let appId = args.appId;
|
|
1060
|
+
if (!appId) {
|
|
1061
|
+
const { mcpCall: mcpCall2 } = await import("./mcp-client-U3CS5OZN.js");
|
|
1062
|
+
const r = await mcpCall2(cfg.endpoint, cfg.token, "list_apps", {});
|
|
1063
|
+
if (!r.isError) {
|
|
1064
|
+
try {
|
|
1065
|
+
const apps = JSON.parse(r.text);
|
|
1066
|
+
if (apps.length > 0) {
|
|
1067
|
+
appId = apps[0].id;
|
|
1068
|
+
log2(kleur6.dim(` \uC571: ${apps[0].name} (${appId})`));
|
|
1069
|
+
}
|
|
1070
|
+
} catch {
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
if (!appId) {
|
|
1075
|
+
log2(kleur6.red("appId\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. --app <id> \uB85C \uC9C0\uC815\uD558\uAC70\uB098 `mimi-seed init` \uC73C\uB85C \uC571 \uB4F1\uB85D."));
|
|
1076
|
+
process.exit(1);
|
|
1077
|
+
}
|
|
1078
|
+
log2("");
|
|
1079
|
+
log2("\u{1F4E1} \uC11C\uBC84 \uBC30\uD3EC \uD30C\uC774\uD504\uB77C\uC778 \uC2DC\uC791...");
|
|
1080
|
+
log2("");
|
|
1081
|
+
const deployBuildNumber = !args.skipBuild ? versionCode : void 0;
|
|
1082
|
+
await streamDeploy(cfg.webBase, cfg.token, {
|
|
1083
|
+
appId,
|
|
1084
|
+
platform: args.platform,
|
|
1085
|
+
versionCode,
|
|
1086
|
+
...deployBuildNumber ? { buildNumber: deployBuildNumber } : {},
|
|
1087
|
+
fromRef: args.fromRef,
|
|
1088
|
+
toRef: args.toRef,
|
|
1089
|
+
language: args.language,
|
|
1090
|
+
dryRun: args.dryRun
|
|
1091
|
+
});
|
|
1092
|
+
log2("");
|
|
1093
|
+
log2(kleur6.bold("\uC644\uB8CC. Play Console\uC5D0\uC11C \uBC30\uD3EC \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uC138\uC694."));
|
|
1094
|
+
log2(kleur6.dim(" https://play.google.com/console/developers"));
|
|
1095
|
+
}
|
|
1096
|
+
|
|
810
1097
|
// src/index.ts
|
|
811
1098
|
var DEFAULT_WEB_BASE = process.env.MIMI_SEED_WEB_BASE ?? "https://mimi-seed.pryzm.gg";
|
|
812
1099
|
var DEFAULT_MCP_ENDPOINT = `${DEFAULT_WEB_BASE}/api/mcp`;
|
|
813
|
-
function
|
|
1100
|
+
function log3(msg) {
|
|
814
1101
|
process.stdout.write(msg + "\n");
|
|
815
1102
|
}
|
|
816
1103
|
async function cmdInit() {
|
|
817
1104
|
const cwd = process.cwd();
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1105
|
+
log3(kleur7.bold("Mimi Seed CLI \u2014 init"));
|
|
1106
|
+
log3(kleur7.dim(cwd));
|
|
1107
|
+
log3("");
|
|
821
1108
|
if (!await hasAnyProjectSignal(cwd)) {
|
|
822
|
-
|
|
1109
|
+
log3(kleur7.yellow("\u26A0 package.json / app.json / android / ios \uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uADF8\uB798\uB3C4 \uC9C4\uD589\uD569\uB2C8\uB2E4."));
|
|
823
1110
|
}
|
|
824
|
-
|
|
1111
|
+
log3("\u{1F50D} \uC571 \uAC10\uC9C0 \uC911...");
|
|
825
1112
|
const hints = await detectHints(cwd);
|
|
826
1113
|
if (hints.length === 0) {
|
|
827
|
-
|
|
1114
|
+
log3(kleur7.yellow("\uAC10\uC9C0\uB41C \uC571 \uC5C6\uC74C. \uC6F9\uC5D0\uC11C \uC218\uB3D9 \uB4F1\uB85D \uAC00\uB2A5."));
|
|
828
1115
|
} else {
|
|
829
1116
|
for (const h of hints) {
|
|
830
1117
|
const tag = [h.packageName && `android:${h.packageName}`, h.bundleId && `ios:${h.bundleId}`].filter(Boolean).join(" ");
|
|
831
|
-
|
|
1118
|
+
log3(` \u2022 ${h.name ?? "(\uC774\uB984 \uBBF8\uC0C1)"} ${kleur7.dim(tag)}`);
|
|
832
1119
|
}
|
|
833
1120
|
}
|
|
834
|
-
|
|
1121
|
+
log3("");
|
|
835
1122
|
if (process.env.MIMI_SEED_TOKEN) {
|
|
836
1123
|
const cfg2 = await getEffectiveConfig();
|
|
837
1124
|
if (cfg2 && hints.length > 0) {
|
|
838
|
-
|
|
1125
|
+
log3(kleur7.dim("CI \uBAA8\uB4DC: MIMI_SEED_TOKEN \uC0AC\uC6A9"));
|
|
839
1126
|
const payload = hints.map((h) => ({ name: h.name, packageName: h.packageName, bundleId: h.bundleId }));
|
|
840
1127
|
const result = await mcpCall(cfg2.endpoint, cfg2.token, "sync_apps", { hints: payload });
|
|
841
1128
|
if (result.isError) {
|
|
842
|
-
|
|
1129
|
+
log3(kleur7.red("\uB4F1\uB85D \uC2E4\uD328: " + result.text));
|
|
843
1130
|
} else {
|
|
844
|
-
for (const line of result.text.split("\n"))
|
|
1131
|
+
for (const line of result.text.split("\n")) log3(" " + line);
|
|
845
1132
|
}
|
|
846
1133
|
}
|
|
847
|
-
|
|
1134
|
+
log3(kleur7.bold("\u2713 \uC644\uB8CC (CI \uBAA8\uB4DC)"));
|
|
848
1135
|
return;
|
|
849
1136
|
}
|
|
850
|
-
|
|
1137
|
+
log3("\u{1F510} \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB85C\uADF8\uC778 \uB300\uAE30...");
|
|
851
1138
|
const hostName = os2.hostname().slice(0, 32);
|
|
852
1139
|
const name = `cli-${hostName}`;
|
|
853
1140
|
const { port, promise } = await awaitHandshake(5 * 60 * 1e3);
|
|
854
1141
|
const callback = `http://127.0.0.1:${port}/cb`;
|
|
855
1142
|
const connectUrl = `${DEFAULT_WEB_BASE}/cli/connect?callback=${encodeURIComponent(callback)}&name=${encodeURIComponent(name)}`;
|
|
856
|
-
|
|
1143
|
+
log3(kleur7.dim(` ${connectUrl}`));
|
|
857
1144
|
await open(connectUrl);
|
|
858
1145
|
let handshake;
|
|
859
1146
|
try {
|
|
860
1147
|
handshake = await promise;
|
|
861
1148
|
} catch (e) {
|
|
862
|
-
|
|
1149
|
+
log3(kleur7.red("\uC5F0\uACB0 \uC2E4\uD328: " + e.message));
|
|
863
1150
|
process.exit(1);
|
|
864
1151
|
}
|
|
865
|
-
|
|
1152
|
+
log3(kleur7.green("\u2713 \uD1A0\uD070 \uC218\uC2E0"));
|
|
866
1153
|
const cfg = {
|
|
867
1154
|
token: handshake.token,
|
|
868
1155
|
prefix: handshake.prefix,
|
|
@@ -871,30 +1158,30 @@ async function cmdInit() {
|
|
|
871
1158
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
872
1159
|
};
|
|
873
1160
|
await writeConfig(cfg);
|
|
874
|
-
|
|
875
|
-
|
|
1161
|
+
log3(kleur7.dim(` \uC800\uC7A5\uB428: ${CONFIG_LOCATION}`));
|
|
1162
|
+
log3("");
|
|
876
1163
|
if (hints.length > 0) {
|
|
877
|
-
|
|
1164
|
+
log3("\u{1F504} \uC571 \uB4F1\uB85D \uC911...");
|
|
878
1165
|
const payload = hints.map((h) => ({ name: h.name, packageName: h.packageName, bundleId: h.bundleId }));
|
|
879
1166
|
const result = await mcpCall(cfg.endpoint, cfg.token, "sync_apps", { hints: payload });
|
|
880
1167
|
if (result.isError) {
|
|
881
|
-
|
|
1168
|
+
log3(kleur7.red("\uB4F1\uB85D \uC2E4\uD328: " + result.text));
|
|
882
1169
|
} else {
|
|
883
|
-
for (const line of result.text.split("\n"))
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1170
|
+
for (const line of result.text.split("\n")) log3(" " + line);
|
|
1171
|
+
}
|
|
1172
|
+
log3("");
|
|
1173
|
+
}
|
|
1174
|
+
log3(kleur7.bold("\u2713 \uC900\uBE44 \uC644\uB8CC."));
|
|
1175
|
+
log3("");
|
|
1176
|
+
log3("Claude Code\uC5D0\uC11C \uC774\uB807\uAC8C \uBB3C\uC5B4\uBCF4\uC138\uC694:");
|
|
1177
|
+
log3(kleur7.cyan(' "\uB0B4 \uC571 \uCD9C\uC2DC \uC900\uBE44\uB410\uC5B4?"'));
|
|
1178
|
+
log3(kleur7.cyan(' "\uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC368\uC918"'));
|
|
1179
|
+
log3(kleur7.cyan(' "\uB4F1\uB85D\uB41C \uC571 \uBAA9\uB85D \uBCF4\uC5EC\uC918"'));
|
|
1180
|
+
log3("");
|
|
1181
|
+
log3(`\uB300\uC2DC\uBCF4\uB4DC: ${kleur7.underline(DEFAULT_WEB_BASE + "/apps")}`);
|
|
1182
|
+
log3("");
|
|
1183
|
+
log3(
|
|
1184
|
+
kleur7.dim(
|
|
898
1185
|
`Claude Code MCP \uB4F1\uB85D:
|
|
899
1186
|
claude mcp add --transport http mimi-seed ${DEFAULT_MCP_ENDPOINT} \\
|
|
900
1187
|
--header "Authorization: Bearer ${cfg.prefix}..."`
|
|
@@ -904,39 +1191,41 @@ async function cmdInit() {
|
|
|
904
1191
|
async function cmdStatus() {
|
|
905
1192
|
const cfg = await getEffectiveConfig();
|
|
906
1193
|
if (!cfg) {
|
|
907
|
-
|
|
1194
|
+
log3(kleur7.yellow("\uC5F0\uACB0\uB41C Mimi Seed \uACC4\uC815\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. `mimi-seed init` \uC2E4\uD589."));
|
|
908
1195
|
process.exit(1);
|
|
909
1196
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
1197
|
+
log3(kleur7.bold("Mimi Seed \uC5F0\uACB0 \uC0C1\uD0DC"));
|
|
1198
|
+
log3(` \uD1A0\uD070: ${cfg.prefix}\u2026 (${cfg.createdAt.slice(0, 10)})`);
|
|
1199
|
+
log3(` \uC5D4\uB4DC\uD3EC\uC778\uD2B8: ${cfg.endpoint}`);
|
|
1200
|
+
log3("");
|
|
1201
|
+
log3("\u{1F4CB} \uC571 \uBAA9\uB85D:");
|
|
915
1202
|
const r = await mcpCall(cfg.endpoint, cfg.token, "list_apps", {});
|
|
916
1203
|
if (r.isError) {
|
|
917
|
-
|
|
1204
|
+
log3(kleur7.red("\uC870\uD68C \uC2E4\uD328: " + r.text));
|
|
918
1205
|
process.exit(1);
|
|
919
1206
|
}
|
|
920
|
-
for (const line of r.text.split("\n"))
|
|
1207
|
+
for (const line of r.text.split("\n")) log3(" " + line);
|
|
921
1208
|
}
|
|
922
1209
|
async function cmdLogout() {
|
|
923
1210
|
await deleteConfig();
|
|
924
|
-
|
|
925
|
-
|
|
1211
|
+
log3(kleur7.green("\u2713 \uB85C\uCEEC \uC124\uC815 \uC0AD\uC81C \uC644\uB8CC."));
|
|
1212
|
+
log3(kleur7.dim("\uC6F9\uC5D0\uC11C \uD1A0\uD070 \uD574\uC9C0: /workspace/api-tokens"));
|
|
926
1213
|
}
|
|
927
1214
|
function printHelp() {
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
${
|
|
931
|
-
${
|
|
932
|
-
${
|
|
933
|
-
${
|
|
934
|
-
${
|
|
935
|
-
${
|
|
936
|
-
${
|
|
937
|
-
${
|
|
938
|
-
|
|
939
|
-
${
|
|
1215
|
+
log3(`${kleur7.bold("mimi-seed")} \u2014 Claude Code\uC5D0\uC11C \uC571 \uCD9C\uC2DC \uC6B4\uC601
|
|
1216
|
+
|
|
1217
|
+
${kleur7.bold("\uBA85\uB839\uC5B4:")}
|
|
1218
|
+
${kleur7.cyan("mimi-seed init")} \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uB97C Mimi Seed\uC5D0 \uC5F0\uACB0
|
|
1219
|
+
${kleur7.cyan("mimi-seed status")} \uC5F0\uACB0 \uC0C1\uD0DC + \uB4F1\uB85D \uC571 \uBAA9\uB85D
|
|
1220
|
+
${kleur7.cyan("mimi-seed auth")} Google OAuth \uC778\uC99D (Firebase/AdMob/Play). 'mimi-seed auth --help'
|
|
1221
|
+
${kleur7.cyan("mimi-seed doctor")} \uD658\uACBD \uC9C4\uB2E8 (\uD1A0\uD070\xB7Git\xB7\uD504\uB85C\uC81D\uD2B8\xB7CI \uCCB4\uD06C)
|
|
1222
|
+
${kleur7.cyan("mimi-seed check")} \uCD9C\uC2DC \uC804 Readiness \uC810\uAC80
|
|
1223
|
+
${kleur7.cyan("mimi-seed notes")} \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC0DD\uC131 (git log \u2192 AI \u2192 \uB9C8\uCF13 \uC801\uC6A9)
|
|
1224
|
+
${kleur7.cyan("mimi-seed review")} \uB9AC\uBDF0 \uB2F5\uBCC0 AI \uCD08\uC548 \uC0DD\uC131 \uBC0F Play Store \uAC8C\uC2DC
|
|
1225
|
+
${kleur7.cyan("mimi-seed deploy")} \uC571 \uC790\uB3D9 \uBC30\uD3EC (Jenkins \u2192 Play Store/App Store)
|
|
1226
|
+
${kleur7.cyan("mimi-seed logout")} \uB85C\uCEEC \uC124\uC815 \uC0AD\uC81C
|
|
1227
|
+
|
|
1228
|
+
${kleur7.bold("mimi-seed notes \uC635\uC158:")}
|
|
940
1229
|
--from <ref> \uC2DC\uC791 \uCEE4\uBC0B/\uD0DC\uADF8 (\uAE30\uBCF8: \uCD5C\uC2E0 \uD0DC\uADF8)
|
|
941
1230
|
--to <ref> \uB05D \uCEE4\uBC0B (\uAE30\uBCF8: HEAD)
|
|
942
1231
|
--locale ko,en-US \uB300\uC0C1 \uB85C\uCF00\uC77C (\uC27C\uD45C \uAD6C\uBD84)
|
|
@@ -944,11 +1233,11 @@ ${kleur5.bold("mimi-seed notes \uC635\uC158:")}
|
|
|
944
1233
|
--no-interactive CI \uBAA8\uB4DC (\uD504\uB86C\uD504\uD2B8 \uC5C6\uC74C)
|
|
945
1234
|
--limit <n> \uCD5C\uB300 \uCEE4\uBC0B \uC218 (\uAE30\uBCF8: 30)
|
|
946
1235
|
|
|
947
|
-
${
|
|
1236
|
+
${kleur7.bold("mimi-seed check \uC635\uC158:")}
|
|
948
1237
|
--app <id> \uC571 ID \uC9C0\uC815
|
|
949
1238
|
--fail-on-blocker \uBE14\uB85C\uCEE4 \uC788\uC73C\uBA74 exit 1 (CI\uC6A9)
|
|
950
1239
|
|
|
951
|
-
${
|
|
1240
|
+
${kleur7.bold("mimi-seed review \uC635\uC158:")}
|
|
952
1241
|
--text <\uB0B4\uC6A9> \uB9AC\uBDF0 \uC6D0\uBB38 (\uBBF8\uC785\uB825 \uC2DC \uB300\uD654\uD615 \uD504\uB86C\uD504\uD2B8)
|
|
953
1242
|
--rating <1-5> \uBCC4\uC810
|
|
954
1243
|
--tone <tone> friendly / professional / empathetic / brief (\uAE30\uBCF8: friendly)
|
|
@@ -959,7 +1248,18 @@ ${kleur5.bold("mimi-seed review \uC635\uC158:")}
|
|
|
959
1248
|
--package-name <p> \uD328\uD0A4\uC9C0\uBA85 (--apply \uC2DC \uD544\uC694)
|
|
960
1249
|
--no-interactive CI \uBAA8\uB4DC
|
|
961
1250
|
|
|
962
|
-
${
|
|
1251
|
+
${kleur7.bold("mimi-seed deploy \uC635\uC158:")}
|
|
1252
|
+
--platform android|ios \uBC30\uD3EC \uD50C\uB7AB\uD3FC (\uAE30\uBCF8: android)
|
|
1253
|
+
--app <id> \uC571 ID \uC9C0\uC815
|
|
1254
|
+
--version-code <n> \uBE4C\uB4DC \uBC88\uD638 \uC9C1\uC811 \uC9C0\uC815 (--skip-build \uC640 \uD568\uAED8)
|
|
1255
|
+
--from <ref> \uCEE4\uBC0B \uBC94\uC704 \uC2DC\uC791 (\uB9B4\uB9AC\uC988 \uB178\uD2B8\uC6A9)
|
|
1256
|
+
--to <ref> \uCEE4\uBC0B \uBC94\uC704 \uB05D (\uAE30\uBCF8: HEAD)
|
|
1257
|
+
--language <\uCF54\uB4DC> \uB9B4\uB9AC\uC988 \uB178\uD2B8 \uC5B8\uC5B4 (\uAE30\uBCF8: ko-KR)
|
|
1258
|
+
--dry-run \uC2E4\uC81C \uBC30\uD3EC \uC5C6\uC774 \uD30C\uC774\uD504\uB77C\uC778 \uD14C\uC2A4\uD2B8
|
|
1259
|
+
--skip-build Jenkins \uBE4C\uB4DC \uAC74\uB108\uB700 (--version-code \uD544\uC218)
|
|
1260
|
+
setup-jenkins Jenkins \uC124\uC815 \uB300\uD654\uD615 \uB4F1\uB85D
|
|
1261
|
+
|
|
1262
|
+
${kleur7.bold("\uD658\uACBD\uBCC0\uC218:")}
|
|
963
1263
|
MIMI_SEED_TOKEN PAT \uD1A0\uD070 (CI/CD \uBB34\uC778\uC99D \uBAA8\uB4DC)
|
|
964
1264
|
MIMI_SEED_WEB_BASE \uC11C\uBC84 \uC8FC\uC18C (\uAE30\uBCF8: https://mimi-seed.pryzm.gg)
|
|
965
1265
|
ANTHROPIC_API_KEY AI \uB178\uD2B8 \uC0DD\uC131 \uD65C\uC131\uD654 (\uC120\uD0DD)
|
|
@@ -988,6 +1288,12 @@ async function main() {
|
|
|
988
1288
|
case "review":
|
|
989
1289
|
await cmdReview(restArgs);
|
|
990
1290
|
break;
|
|
1291
|
+
case "auth":
|
|
1292
|
+
await cmdAuth(restArgs);
|
|
1293
|
+
break;
|
|
1294
|
+
case "deploy":
|
|
1295
|
+
await cmdDeploy(restArgs);
|
|
1296
|
+
break;
|
|
991
1297
|
case "logout":
|
|
992
1298
|
await cmdLogout();
|
|
993
1299
|
break;
|
|
@@ -997,13 +1303,13 @@ async function main() {
|
|
|
997
1303
|
printHelp();
|
|
998
1304
|
break;
|
|
999
1305
|
default:
|
|
1000
|
-
|
|
1306
|
+
log3(kleur7.red(`\uC54C \uC218 \uC5C6\uB294 \uBA85\uB839: ${cmd}`));
|
|
1001
1307
|
printHelp();
|
|
1002
1308
|
process.exit(1);
|
|
1003
1309
|
}
|
|
1004
1310
|
} catch (e) {
|
|
1005
|
-
|
|
1006
|
-
if (process.env.DEBUG)
|
|
1311
|
+
log3(kleur7.red(`\uC624\uB958: ${e.message}`));
|
|
1312
|
+
if (process.env.DEBUG) log3(e.stack ?? "");
|
|
1007
1313
|
process.exit(1);
|
|
1008
1314
|
}
|
|
1009
1315
|
}
|