kubiy-paas-cli 0.1.2 → 0.1.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/.github/workflows/publish.yml +51 -0
- package/fix-link.js +72 -72
- package/index.js +54 -54
- package/package.json +1 -1
- package/src/api.js +79 -79
- package/src/commands/deploy.js +206 -206
- package/src/commands/git-connect.js +113 -113
- package/src/commands/login.js +16 -16
- package/src/commands/service-get.js +24 -24
- package/src/commands/version.js +17 -17
- package/src/commands/whoami.js +15 -15
- package/src/config.js +47 -47
- package/src/git.js +24 -24
- package/src/logger.js +30 -30
- package/src/ssh-config.js +51 -51
- package/src/ssh.js +40 -40
package/src/commands/deploy.js
CHANGED
|
@@ -1,206 +1,206 @@
|
|
|
1
|
-
// src/commands/deploy.js
|
|
2
|
-
const { execSync } = require("child_process");
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
const { logInfo, logSuccess, logError } = require("../logger");
|
|
6
|
-
const { SSH_PRIV } = require("../ssh"); // ya lo usas en git:connect
|
|
7
|
-
|
|
8
|
-
function runGit(command, extraOptions = {}) {
|
|
9
|
-
const full = `git ${command}`;
|
|
10
|
-
try {
|
|
11
|
-
const out = execSync(full, {
|
|
12
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
13
|
-
encoding: "utf8",
|
|
14
|
-
...extraOptions,
|
|
15
|
-
});
|
|
16
|
-
return out.trim();
|
|
17
|
-
} catch (err) {
|
|
18
|
-
const stderr = err.stderr ? String(err.stderr) : "";
|
|
19
|
-
throw new Error(`Error al ejecutar: ${full}\n${stderr || err.message}`);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function isGitRepo() {
|
|
24
|
-
return fs.existsSync(path.join(process.cwd(), ".git"));
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function ensureGitRepo() {
|
|
28
|
-
if (isGitRepo()) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
logInfo("Este directorio no es un repositorio git. Inicializando...");
|
|
33
|
-
runGit("init");
|
|
34
|
-
logSuccess("Repositorio git inicializado.");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Intenta obtener la rama actual.
|
|
39
|
-
* Si no hay commits / HEAD está raro, devuelve null.
|
|
40
|
-
*/
|
|
41
|
-
function getCurrentBranch() {
|
|
42
|
-
try {
|
|
43
|
-
return runGit("symbolic-ref --short HEAD");
|
|
44
|
-
} catch (_) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function branchExists(branchName) {
|
|
50
|
-
try {
|
|
51
|
-
const out = runGit(`branch --list ${branchName}`);
|
|
52
|
-
return out !== "";
|
|
53
|
-
} catch (_) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Asegura que la rama activa sea master.
|
|
60
|
-
*
|
|
61
|
-
* Casos:
|
|
62
|
-
* - Si ya estamos en master → OK.
|
|
63
|
-
* - Si no hay rama actual (repo recién creado) → crea master.
|
|
64
|
-
* - Si hay otra rama → si existe master hacemos checkout, si no renombramos a master.
|
|
65
|
-
*/
|
|
66
|
-
function ensureOnMaster() {
|
|
67
|
-
let current = getCurrentBranch();
|
|
68
|
-
|
|
69
|
-
if (!current || current === "HEAD") {
|
|
70
|
-
logInfo("No hay rama actual válida. Creando / cambiando a 'master'...");
|
|
71
|
-
|
|
72
|
-
if (branchExists("master")) {
|
|
73
|
-
runGit("checkout master");
|
|
74
|
-
logSuccess("Ahora estás en master.");
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Repo recién creado sin ramas reales → creamos master
|
|
79
|
-
runGit("checkout -b master");
|
|
80
|
-
logSuccess("Rama master creada y activada.");
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (current === "master") {
|
|
85
|
-
logInfo("Ya estás en la rama master.");
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
logInfo(`Rama actual: ${current}`);
|
|
90
|
-
|
|
91
|
-
if (branchExists("master")) {
|
|
92
|
-
logInfo("Encontrada rama master. Cambiando a master...");
|
|
93
|
-
runGit("checkout master");
|
|
94
|
-
logSuccess("Ahora estás en master.");
|
|
95
|
-
} else {
|
|
96
|
-
logInfo(`No existe rama master. Renombrando rama actual '${current}' a 'master'...`);
|
|
97
|
-
runGit("branch -m master");
|
|
98
|
-
logSuccess("Rama actual renombrada a master.");
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function ensureKubiyRemote() {
|
|
103
|
-
try {
|
|
104
|
-
const url = runGit("remote get-url kubiy");
|
|
105
|
-
logInfo(`Remote 'kubiy' encontrado: ${url}`);
|
|
106
|
-
} catch (_) {
|
|
107
|
-
throw new Error(
|
|
108
|
-
"No se encontró el remote 'kubiy'.\n" +
|
|
109
|
-
"Asegúrate de haber ejecutado antes:\n kubiy git:connect <serviceId>"
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function hasChangesToCommit() {
|
|
115
|
-
const status = runGit("status --porcelain");
|
|
116
|
-
return status !== "";
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function createAutoCommit() {
|
|
120
|
-
const msg = `kubiy deploy - ${new Date().toISOString()}`;
|
|
121
|
-
logInfo("Creando commit automático...");
|
|
122
|
-
|
|
123
|
-
runGit("add .");
|
|
124
|
-
try {
|
|
125
|
-
runGit(`commit -m "${msg}"`);
|
|
126
|
-
logSuccess(`Commit creado: ${msg}`);
|
|
127
|
-
} catch (err) {
|
|
128
|
-
if (String(err.message).includes("nothing to commit")) {
|
|
129
|
-
logInfo("No hay cambios nuevos para commitear.");
|
|
130
|
-
} else {
|
|
131
|
-
throw err;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function pushToKubiy() {
|
|
137
|
-
logInfo("Haciendo push a 'kubiy' (rama master)...");
|
|
138
|
-
|
|
139
|
-
// Ruta normalizada para que ssh no se maree con backslashes
|
|
140
|
-
const identityPath = SSH_PRIV.replace(/\\/g, "/");
|
|
141
|
-
|
|
142
|
-
const env = {
|
|
143
|
-
...process.env,
|
|
144
|
-
// Forzar que git use ESTE ssh con ESTA llave y SIN validar host key
|
|
145
|
-
GIT_SSH_COMMAND: `ssh -i "${identityPath}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null`,
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
runGit("push kubiy master", { env });
|
|
149
|
-
logSuccess("Push a kubiy master completado.");
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async function run() {
|
|
153
|
-
try {
|
|
154
|
-
// 1) Repo git
|
|
155
|
-
ensureGitRepo();
|
|
156
|
-
|
|
157
|
-
// 2) Estar en master sí o sí
|
|
158
|
-
ensureOnMaster();
|
|
159
|
-
|
|
160
|
-
// 3) Remote kubiy configurado
|
|
161
|
-
ensureKubiyRemote();
|
|
162
|
-
|
|
163
|
-
// 4) Commit automático si hay cambios
|
|
164
|
-
if (hasChangesToCommit()) {
|
|
165
|
-
createAutoCommit();
|
|
166
|
-
} else {
|
|
167
|
-
logInfo("No hay cambios locales. Solo se intentará hacer push.");
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// 5) Push
|
|
171
|
-
pushToKubiy();
|
|
172
|
-
|
|
173
|
-
logSuccess("🚀 Deploy completado. Revisa tu servicio Kubiy.");
|
|
174
|
-
} catch (err) {
|
|
175
|
-
const msg = String(err.message || "").toLowerCase();
|
|
176
|
-
logError("Error en kubiy deploy:");
|
|
177
|
-
|
|
178
|
-
// Caso clásico: el remoto tiene commits que el local no
|
|
179
|
-
if (
|
|
180
|
-
msg.includes("fetch first") ||
|
|
181
|
-
msg.includes("non-fast-forward") ||
|
|
182
|
-
msg.includes("failed to push some refs")
|
|
183
|
-
) {
|
|
184
|
-
logError("Tu rama local 'master' está detrás del remoto 'kubiy/master'.");
|
|
185
|
-
logError("Esto pasa cuando el servidor ya tiene commits que tu repo local no tiene.");
|
|
186
|
-
console.log("");
|
|
187
|
-
console.log("Para alinearlo, ejecuta UNA sola vez:");
|
|
188
|
-
console.log("");
|
|
189
|
-
console.log(" git fetch kubiy");
|
|
190
|
-
console.log(" git reset --hard kubiy/master");
|
|
191
|
-
console.log("");
|
|
192
|
-
console.log("Después de eso, vuelve a correr:");
|
|
193
|
-
console.log("");
|
|
194
|
-
console.log(" kubiy deploy");
|
|
195
|
-
} else {
|
|
196
|
-
// Otros errores, mostramos el mensaje crudo
|
|
197
|
-
logError(err.message);
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
process.exit(1);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
module.exports = {
|
|
205
|
-
run,
|
|
206
|
-
};
|
|
1
|
+
// src/commands/deploy.js
|
|
2
|
+
const { execSync } = require("child_process");
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const { logInfo, logSuccess, logError } = require("../logger");
|
|
6
|
+
const { SSH_PRIV } = require("../ssh"); // ya lo usas en git:connect
|
|
7
|
+
|
|
8
|
+
function runGit(command, extraOptions = {}) {
|
|
9
|
+
const full = `git ${command}`;
|
|
10
|
+
try {
|
|
11
|
+
const out = execSync(full, {
|
|
12
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
13
|
+
encoding: "utf8",
|
|
14
|
+
...extraOptions,
|
|
15
|
+
});
|
|
16
|
+
return out.trim();
|
|
17
|
+
} catch (err) {
|
|
18
|
+
const stderr = err.stderr ? String(err.stderr) : "";
|
|
19
|
+
throw new Error(`Error al ejecutar: ${full}\n${stderr || err.message}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function isGitRepo() {
|
|
24
|
+
return fs.existsSync(path.join(process.cwd(), ".git"));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function ensureGitRepo() {
|
|
28
|
+
if (isGitRepo()) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
logInfo("Este directorio no es un repositorio git. Inicializando...");
|
|
33
|
+
runGit("init");
|
|
34
|
+
logSuccess("Repositorio git inicializado.");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Intenta obtener la rama actual.
|
|
39
|
+
* Si no hay commits / HEAD está raro, devuelve null.
|
|
40
|
+
*/
|
|
41
|
+
function getCurrentBranch() {
|
|
42
|
+
try {
|
|
43
|
+
return runGit("symbolic-ref --short HEAD");
|
|
44
|
+
} catch (_) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function branchExists(branchName) {
|
|
50
|
+
try {
|
|
51
|
+
const out = runGit(`branch --list ${branchName}`);
|
|
52
|
+
return out !== "";
|
|
53
|
+
} catch (_) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Asegura que la rama activa sea master.
|
|
60
|
+
*
|
|
61
|
+
* Casos:
|
|
62
|
+
* - Si ya estamos en master → OK.
|
|
63
|
+
* - Si no hay rama actual (repo recién creado) → crea master.
|
|
64
|
+
* - Si hay otra rama → si existe master hacemos checkout, si no renombramos a master.
|
|
65
|
+
*/
|
|
66
|
+
function ensureOnMaster() {
|
|
67
|
+
let current = getCurrentBranch();
|
|
68
|
+
|
|
69
|
+
if (!current || current === "HEAD") {
|
|
70
|
+
logInfo("No hay rama actual válida. Creando / cambiando a 'master'...");
|
|
71
|
+
|
|
72
|
+
if (branchExists("master")) {
|
|
73
|
+
runGit("checkout master");
|
|
74
|
+
logSuccess("Ahora estás en master.");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Repo recién creado sin ramas reales → creamos master
|
|
79
|
+
runGit("checkout -b master");
|
|
80
|
+
logSuccess("Rama master creada y activada.");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (current === "master") {
|
|
85
|
+
logInfo("Ya estás en la rama master.");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
logInfo(`Rama actual: ${current}`);
|
|
90
|
+
|
|
91
|
+
if (branchExists("master")) {
|
|
92
|
+
logInfo("Encontrada rama master. Cambiando a master...");
|
|
93
|
+
runGit("checkout master");
|
|
94
|
+
logSuccess("Ahora estás en master.");
|
|
95
|
+
} else {
|
|
96
|
+
logInfo(`No existe rama master. Renombrando rama actual '${current}' a 'master'...`);
|
|
97
|
+
runGit("branch -m master");
|
|
98
|
+
logSuccess("Rama actual renombrada a master.");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function ensureKubiyRemote() {
|
|
103
|
+
try {
|
|
104
|
+
const url = runGit("remote get-url kubiy");
|
|
105
|
+
logInfo(`Remote 'kubiy' encontrado: ${url}`);
|
|
106
|
+
} catch (_) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
"No se encontró el remote 'kubiy'.\n" +
|
|
109
|
+
"Asegúrate de haber ejecutado antes:\n kubiy git:connect <serviceId>"
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function hasChangesToCommit() {
|
|
115
|
+
const status = runGit("status --porcelain");
|
|
116
|
+
return status !== "";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function createAutoCommit() {
|
|
120
|
+
const msg = `kubiy deploy - ${new Date().toISOString()}`;
|
|
121
|
+
logInfo("Creando commit automático...");
|
|
122
|
+
|
|
123
|
+
runGit("add .");
|
|
124
|
+
try {
|
|
125
|
+
runGit(`commit -m "${msg}"`);
|
|
126
|
+
logSuccess(`Commit creado: ${msg}`);
|
|
127
|
+
} catch (err) {
|
|
128
|
+
if (String(err.message).includes("nothing to commit")) {
|
|
129
|
+
logInfo("No hay cambios nuevos para commitear.");
|
|
130
|
+
} else {
|
|
131
|
+
throw err;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function pushToKubiy() {
|
|
137
|
+
logInfo("Haciendo push a 'kubiy' (rama master)...");
|
|
138
|
+
|
|
139
|
+
// Ruta normalizada para que ssh no se maree con backslashes
|
|
140
|
+
const identityPath = SSH_PRIV.replace(/\\/g, "/");
|
|
141
|
+
|
|
142
|
+
const env = {
|
|
143
|
+
...process.env,
|
|
144
|
+
// Forzar que git use ESTE ssh con ESTA llave y SIN validar host key
|
|
145
|
+
GIT_SSH_COMMAND: `ssh -i "${identityPath}" -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null`,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
runGit("push kubiy master", { env });
|
|
149
|
+
logSuccess("Push a kubiy master completado.");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function run() {
|
|
153
|
+
try {
|
|
154
|
+
// 1) Repo git
|
|
155
|
+
ensureGitRepo();
|
|
156
|
+
|
|
157
|
+
// 2) Estar en master sí o sí
|
|
158
|
+
ensureOnMaster();
|
|
159
|
+
|
|
160
|
+
// 3) Remote kubiy configurado
|
|
161
|
+
ensureKubiyRemote();
|
|
162
|
+
|
|
163
|
+
// 4) Commit automático si hay cambios
|
|
164
|
+
if (hasChangesToCommit()) {
|
|
165
|
+
createAutoCommit();
|
|
166
|
+
} else {
|
|
167
|
+
logInfo("No hay cambios locales. Solo se intentará hacer push.");
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 5) Push
|
|
171
|
+
pushToKubiy();
|
|
172
|
+
|
|
173
|
+
logSuccess("🚀 Deploy completado. Revisa tu servicio Kubiy.");
|
|
174
|
+
} catch (err) {
|
|
175
|
+
const msg = String(err.message || "").toLowerCase();
|
|
176
|
+
logError("Error en kubiy deploy:");
|
|
177
|
+
|
|
178
|
+
// Caso clásico: el remoto tiene commits que el local no
|
|
179
|
+
if (
|
|
180
|
+
msg.includes("fetch first") ||
|
|
181
|
+
msg.includes("non-fast-forward") ||
|
|
182
|
+
msg.includes("failed to push some refs")
|
|
183
|
+
) {
|
|
184
|
+
logError("Tu rama local 'master' está detrás del remoto 'kubiy/master'.");
|
|
185
|
+
logError("Esto pasa cuando el servidor ya tiene commits que tu repo local no tiene.");
|
|
186
|
+
console.log("");
|
|
187
|
+
console.log("Para alinearlo, ejecuta UNA sola vez:");
|
|
188
|
+
console.log("");
|
|
189
|
+
console.log(" git fetch kubiy");
|
|
190
|
+
console.log(" git reset --hard kubiy/master");
|
|
191
|
+
console.log("");
|
|
192
|
+
console.log("Después de eso, vuelve a correr:");
|
|
193
|
+
console.log("");
|
|
194
|
+
console.log(" kubiy deploy");
|
|
195
|
+
} else {
|
|
196
|
+
// Otros errores, mostramos el mensaje crudo
|
|
197
|
+
logError(err.message);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
module.exports = {
|
|
205
|
+
run,
|
|
206
|
+
};
|
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
// src/commands/git-connect.js
|
|
2
|
-
const { getCliToken } = require("../config");
|
|
3
|
-
const { apiGet, apiPost } = require("../api");
|
|
4
|
-
const { ensureSshKey, SSH_PRIV } = require("../ssh");
|
|
5
|
-
const { ensureSshHostConfig } = require("../ssh-config");
|
|
6
|
-
const { addRemote } = require("../git");
|
|
7
|
-
const { logInfo, logSuccess, logError } = require("../logger");
|
|
8
|
-
|
|
9
|
-
const { execSync } = require("child_process");
|
|
10
|
-
const fs = require("fs");
|
|
11
|
-
|
|
12
|
-
function ensureGitRepo() {
|
|
13
|
-
if (fs.existsSync(".git")) return;
|
|
14
|
-
|
|
15
|
-
logInfo("Este directorio no es un repositorio git. Inicializando...");
|
|
16
|
-
execSync("git init", { stdio: "inherit" });
|
|
17
|
-
try {
|
|
18
|
-
execSync("git checkout -b main", { stdio: "inherit" });
|
|
19
|
-
} catch (_) {
|
|
20
|
-
// Si ya existe main/master, no pasa nada
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function parseRepoUrl(gitRepoUrl) {
|
|
25
|
-
// Esperamos algo como ssh://deploy@1.2.3.4/home/deploy/app.git
|
|
26
|
-
try {
|
|
27
|
-
const url = new URL(gitRepoUrl);
|
|
28
|
-
return {
|
|
29
|
-
host: url.hostname,
|
|
30
|
-
path: url.pathname // /home/deploy/app.git
|
|
31
|
-
};
|
|
32
|
-
} catch (e) {
|
|
33
|
-
// fallback muy básico
|
|
34
|
-
// ssh://deploy@1.2.3.4/home/deploy/app.git
|
|
35
|
-
if (!gitRepoUrl.startsWith("ssh://")) {
|
|
36
|
-
throw new Error(`gitRepoUrl inválido: ${gitRepoUrl}`);
|
|
37
|
-
}
|
|
38
|
-
const withoutScheme = gitRepoUrl.slice("ssh://".length);
|
|
39
|
-
const [userHost, pathPart] = withoutScheme.split("/", 2);
|
|
40
|
-
const host = userHost.split("@").pop();
|
|
41
|
-
return {
|
|
42
|
-
host,
|
|
43
|
-
path: "/" + pathPart
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function run(argv) {
|
|
49
|
-
const serviceId = argv[0];
|
|
50
|
-
|
|
51
|
-
if (!serviceId) {
|
|
52
|
-
logError("Uso: kubiy git:connect <serviceId>");
|
|
53
|
-
process.exit(1);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const token = getCliToken();
|
|
57
|
-
if (!token) {
|
|
58
|
-
logError("No hay CLI token. Ejecuta: kubiy login <cliToken>");
|
|
59
|
-
process.exit(1);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 1) Asegurar llave SSH local (~/.kubiy/id_ed25519)
|
|
63
|
-
const pubKey = ensureSshKey();
|
|
64
|
-
|
|
65
|
-
// 2) Registrar llave en tu API
|
|
66
|
-
logInfo("Registrando llave SSH en Kubiy...");
|
|
67
|
-
await apiPost("/cli/ssh-keys", { publicKey: pubKey });
|
|
68
|
-
logSuccess("Llave SSH registrada.");
|
|
69
|
-
|
|
70
|
-
// 3) Sincronizar llaves con la EC2 del servicio
|
|
71
|
-
logInfo("Sincronizando llaves SSH con la instancia...");
|
|
72
|
-
try {
|
|
73
|
-
const syncResp = await apiPost(`/cli/services/${serviceId}/sync-ssh`, {});
|
|
74
|
-
logSuccess(
|
|
75
|
-
`Llaves sincronizadas. keysApplied=${syncResp.keysApplied}, ssmStatus=${syncResp.ssmStatus}`
|
|
76
|
-
);
|
|
77
|
-
} catch (e) {
|
|
78
|
-
logError(`No se pudo sincronizar llaves con la instancia: ${e.message}`);
|
|
79
|
-
// seguimos, porque igual podrías tener la llave ya metida de antes
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// 4) Obtener info del servicio (para gitRepoUrl)
|
|
83
|
-
logInfo("Obteniendo información del servicio...");
|
|
84
|
-
const service = await apiGet(`/services/${serviceId}`);
|
|
85
|
-
|
|
86
|
-
const gitRepoUrl = service.gitRepoUrl;
|
|
87
|
-
if (!gitRepoUrl) {
|
|
88
|
-
logError("El servicio no tiene gitRepoUrl todavía. Asegúrate que esté en RUNNING.");
|
|
89
|
-
process.exit(1);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const { host: ec2Host, path: repoPath } = parseRepoUrl(gitRepoUrl);
|
|
93
|
-
|
|
94
|
-
// 5) Configurar ~/.ssh/config con un host lógico único para este servicio
|
|
95
|
-
const hostAlias = `kubiy-${serviceId}`.slice(0, 60); // por si se va muy largo
|
|
96
|
-
|
|
97
|
-
ensureSshHostConfig(hostAlias, ec2Host, SSH_PRIV);
|
|
98
|
-
|
|
99
|
-
// 6) Configurar remote con el alias, no con la IP directa
|
|
100
|
-
ensureGitRepo();
|
|
101
|
-
logInfo("Configurando remote 'kubiy'...");
|
|
102
|
-
const remoteUrl = `ssh://${hostAlias}${repoPath}`;
|
|
103
|
-
addRemote("kubiy", remoteUrl);
|
|
104
|
-
|
|
105
|
-
logSuccess("Remote 'kubiy' configurado.");
|
|
106
|
-
|
|
107
|
-
logSuccess("Listo. Puedes hacer ahora:");
|
|
108
|
-
console.log(" git add .");
|
|
109
|
-
console.log(" git commit -m \"tu mensaje\"");
|
|
110
|
-
console.log(" git push kubiy main # o master");
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
module.exports = { run };
|
|
1
|
+
// src/commands/git-connect.js
|
|
2
|
+
const { getCliToken } = require("../config");
|
|
3
|
+
const { apiGet, apiPost } = require("../api");
|
|
4
|
+
const { ensureSshKey, SSH_PRIV } = require("../ssh");
|
|
5
|
+
const { ensureSshHostConfig } = require("../ssh-config");
|
|
6
|
+
const { addRemote } = require("../git");
|
|
7
|
+
const { logInfo, logSuccess, logError } = require("../logger");
|
|
8
|
+
|
|
9
|
+
const { execSync } = require("child_process");
|
|
10
|
+
const fs = require("fs");
|
|
11
|
+
|
|
12
|
+
function ensureGitRepo() {
|
|
13
|
+
if (fs.existsSync(".git")) return;
|
|
14
|
+
|
|
15
|
+
logInfo("Este directorio no es un repositorio git. Inicializando...");
|
|
16
|
+
execSync("git init", { stdio: "inherit" });
|
|
17
|
+
try {
|
|
18
|
+
execSync("git checkout -b main", { stdio: "inherit" });
|
|
19
|
+
} catch (_) {
|
|
20
|
+
// Si ya existe main/master, no pasa nada
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parseRepoUrl(gitRepoUrl) {
|
|
25
|
+
// Esperamos algo como ssh://deploy@1.2.3.4/home/deploy/app.git
|
|
26
|
+
try {
|
|
27
|
+
const url = new URL(gitRepoUrl);
|
|
28
|
+
return {
|
|
29
|
+
host: url.hostname,
|
|
30
|
+
path: url.pathname // /home/deploy/app.git
|
|
31
|
+
};
|
|
32
|
+
} catch (e) {
|
|
33
|
+
// fallback muy básico
|
|
34
|
+
// ssh://deploy@1.2.3.4/home/deploy/app.git
|
|
35
|
+
if (!gitRepoUrl.startsWith("ssh://")) {
|
|
36
|
+
throw new Error(`gitRepoUrl inválido: ${gitRepoUrl}`);
|
|
37
|
+
}
|
|
38
|
+
const withoutScheme = gitRepoUrl.slice("ssh://".length);
|
|
39
|
+
const [userHost, pathPart] = withoutScheme.split("/", 2);
|
|
40
|
+
const host = userHost.split("@").pop();
|
|
41
|
+
return {
|
|
42
|
+
host,
|
|
43
|
+
path: "/" + pathPart
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function run(argv) {
|
|
49
|
+
const serviceId = argv[0];
|
|
50
|
+
|
|
51
|
+
if (!serviceId) {
|
|
52
|
+
logError("Uso: kubiy git:connect <serviceId>");
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const token = getCliToken();
|
|
57
|
+
if (!token) {
|
|
58
|
+
logError("No hay CLI token. Ejecuta: kubiy login <cliToken>");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 1) Asegurar llave SSH local (~/.kubiy/id_ed25519)
|
|
63
|
+
const pubKey = ensureSshKey();
|
|
64
|
+
|
|
65
|
+
// 2) Registrar llave en tu API
|
|
66
|
+
logInfo("Registrando llave SSH en Kubiy...");
|
|
67
|
+
await apiPost("/cli/ssh-keys", { publicKey: pubKey });
|
|
68
|
+
logSuccess("Llave SSH registrada.");
|
|
69
|
+
|
|
70
|
+
// 3) Sincronizar llaves con la EC2 del servicio
|
|
71
|
+
logInfo("Sincronizando llaves SSH con la instancia...");
|
|
72
|
+
try {
|
|
73
|
+
const syncResp = await apiPost(`/cli/services/${serviceId}/sync-ssh`, {});
|
|
74
|
+
logSuccess(
|
|
75
|
+
`Llaves sincronizadas. keysApplied=${syncResp.keysApplied}, ssmStatus=${syncResp.ssmStatus}`
|
|
76
|
+
);
|
|
77
|
+
} catch (e) {
|
|
78
|
+
logError(`No se pudo sincronizar llaves con la instancia: ${e.message}`);
|
|
79
|
+
// seguimos, porque igual podrías tener la llave ya metida de antes
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 4) Obtener info del servicio (para gitRepoUrl)
|
|
83
|
+
logInfo("Obteniendo información del servicio...");
|
|
84
|
+
const service = await apiGet(`/services/${serviceId}`);
|
|
85
|
+
|
|
86
|
+
const gitRepoUrl = service.gitRepoUrl;
|
|
87
|
+
if (!gitRepoUrl) {
|
|
88
|
+
logError("El servicio no tiene gitRepoUrl todavía. Asegúrate que esté en RUNNING.");
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const { host: ec2Host, path: repoPath } = parseRepoUrl(gitRepoUrl);
|
|
93
|
+
|
|
94
|
+
// 5) Configurar ~/.ssh/config con un host lógico único para este servicio
|
|
95
|
+
const hostAlias = `kubiy-${serviceId}`.slice(0, 60); // por si se va muy largo
|
|
96
|
+
|
|
97
|
+
ensureSshHostConfig(hostAlias, ec2Host, SSH_PRIV);
|
|
98
|
+
|
|
99
|
+
// 6) Configurar remote con el alias, no con la IP directa
|
|
100
|
+
ensureGitRepo();
|
|
101
|
+
logInfo("Configurando remote 'kubiy'...");
|
|
102
|
+
const remoteUrl = `ssh://${hostAlias}${repoPath}`;
|
|
103
|
+
addRemote("kubiy", remoteUrl);
|
|
104
|
+
|
|
105
|
+
logSuccess("Remote 'kubiy' configurado.");
|
|
106
|
+
|
|
107
|
+
logSuccess("Listo. Puedes hacer ahora:");
|
|
108
|
+
console.log(" git add .");
|
|
109
|
+
console.log(" git commit -m \"tu mensaje\"");
|
|
110
|
+
console.log(" git push kubiy main # o master");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
module.exports = { run };
|
package/src/commands/login.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
const { setCliToken } = require("../config");
|
|
2
|
-
const { logSuccess, logError } = require("../logger");
|
|
3
|
-
|
|
4
|
-
async function run(args) {
|
|
5
|
-
const token = args[0];
|
|
6
|
-
|
|
7
|
-
if (!token) {
|
|
8
|
-
logError("Uso: kubiy login <cliToken>");
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
setCliToken(token.trim());
|
|
13
|
-
logSuccess("CLI token guardado en ~/.kubiy/config.json");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = { run };
|
|
1
|
+
const { setCliToken } = require("../config");
|
|
2
|
+
const { logSuccess, logError } = require("../logger");
|
|
3
|
+
|
|
4
|
+
async function run(args) {
|
|
5
|
+
const token = args[0];
|
|
6
|
+
|
|
7
|
+
if (!token) {
|
|
8
|
+
logError("Uso: kubiy login <cliToken>");
|
|
9
|
+
process.exit(1);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
setCliToken(token.trim());
|
|
13
|
+
logSuccess("CLI token guardado en ~/.kubiy/config.json");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = { run };
|