kubiy-paas-cli 0.1.1 → 0.1.2

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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  const path = require("path");
4
4
  const { logInfo, logError } = require("./src/logger");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kubiy-paas-cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "CLI para la plataforma PaaS de Kubiy",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -1,27 +1,27 @@
1
1
  // src/commands/deploy.js
2
2
  const { execSync } = require("child_process");
3
3
  const fs = require("fs");
4
+ const path = require("path");
4
5
  const { logInfo, logSuccess, logError } = require("../logger");
6
+ const { SSH_PRIV } = require("../ssh"); // ya lo usas en git:connect
5
7
 
6
- function runGit(command, options = {}) {
8
+ function runGit(command, extraOptions = {}) {
7
9
  const full = `git ${command}`;
8
10
  try {
9
- return execSync(full, {
10
- stdio: ["pipe", "pipe", "inherit"],
11
- ...options,
12
- }).toString().trim();
11
+ const out = execSync(full, {
12
+ stdio: ["pipe", "pipe", "pipe"],
13
+ encoding: "utf8",
14
+ ...extraOptions,
15
+ });
16
+ return out.trim();
13
17
  } catch (err) {
14
- throw new Error(`Error al ejecutar: ${full}\n${err.message}`);
18
+ const stderr = err.stderr ? String(err.stderr) : "";
19
+ throw new Error(`Error al ejecutar: ${full}\n${stderr || err.message}`);
15
20
  }
16
21
  }
17
22
 
18
23
  function isGitRepo() {
19
- try {
20
- runGit("rev-parse --is-inside-work-tree");
21
- return true;
22
- } catch (_) {
23
- return false;
24
- }
24
+ return fs.existsSync(path.join(process.cwd(), ".git"));
25
25
  }
26
26
 
27
27
  function ensureGitRepo() {
@@ -31,20 +31,16 @@ function ensureGitRepo() {
31
31
 
32
32
  logInfo("Este directorio no es un repositorio git. Inicializando...");
33
33
  runGit("init");
34
-
35
- // Intentar crear master como rama inicial
36
- try {
37
- runGit("checkout -b master");
38
- } catch (_) {
39
- // Si falla, probablemente ya haya HEAD en detached; no pasa nada por ahora.
40
- }
41
-
42
- logSuccess("Repositorio git inicializado y rama master creada (si fue posible).");
34
+ logSuccess("Repositorio git inicializado.");
43
35
  }
44
36
 
37
+ /**
38
+ * Intenta obtener la rama actual.
39
+ * Si no hay commits / HEAD está raro, devuelve null.
40
+ */
45
41
  function getCurrentBranch() {
46
42
  try {
47
- return runGit("rev-parse --abbrev-ref HEAD");
43
+ return runGit("symbolic-ref --short HEAD");
48
44
  } catch (_) {
49
45
  return null;
50
46
  }
@@ -60,18 +56,29 @@ function branchExists(branchName) {
60
56
  }
61
57
 
62
58
  /**
63
- * Normaliza para que la rama activa sea master.
59
+ * Asegura que la rama activa sea master.
64
60
  *
65
61
  * Casos:
66
62
  * - Si ya estamos en master → OK.
67
- * - Si existe masterhacemos checkout master.
68
- * - Si NO existe master renombramos la rama actual a master.
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.
69
65
  */
70
66
  function ensureOnMaster() {
71
- const current = getCurrentBranch();
67
+ let current = getCurrentBranch();
72
68
 
73
- if (!current) {
74
- throw new Error("No se pudo determinar la rama actual.");
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;
75
82
  }
76
83
 
77
84
  if (current === "master") {
@@ -83,11 +90,11 @@ function ensureOnMaster() {
83
90
 
84
91
  if (branchExists("master")) {
85
92
  logInfo("Encontrada rama master. Cambiando a master...");
86
- runGit("checkout master", { stdio: "inherit" });
93
+ runGit("checkout master");
87
94
  logSuccess("Ahora estás en master.");
88
95
  } else {
89
96
  logInfo(`No existe rama master. Renombrando rama actual '${current}' a 'master'...`);
90
- runGit(`branch -m master`, { stdio: "inherit" });
97
+ runGit("branch -m master");
91
98
  logSuccess("Rama actual renombrada a master.");
92
99
  }
93
100
  }
@@ -99,7 +106,7 @@ function ensureKubiyRemote() {
99
106
  } catch (_) {
100
107
  throw new Error(
101
108
  "No se encontró el remote 'kubiy'.\n" +
102
- "Asegúrate de haber ejecutado antes: kubiy git:connect <serviceId>"
109
+ "Asegúrate de haber ejecutado antes:\n kubiy git:connect <serviceId>"
103
110
  );
104
111
  }
105
112
  }
@@ -113,12 +120,11 @@ function createAutoCommit() {
113
120
  const msg = `kubiy deploy - ${new Date().toISOString()}`;
114
121
  logInfo("Creando commit automático...");
115
122
 
116
- runGit("add .", { stdio: "inherit" });
123
+ runGit("add .");
117
124
  try {
118
- runGit(`commit -m "${msg}"`, { stdio: "inherit" });
125
+ runGit(`commit -m "${msg}"`);
119
126
  logSuccess(`Commit creado: ${msg}`);
120
127
  } catch (err) {
121
- // Si no hay nada que commitear, git commit truena. Lo detectamos.
122
128
  if (String(err.message).includes("nothing to commit")) {
123
129
  logInfo("No hay cambios nuevos para commitear.");
124
130
  } else {
@@ -129,35 +135,68 @@ function createAutoCommit() {
129
135
 
130
136
  function pushToKubiy() {
131
137
  logInfo("Haciendo push a 'kubiy' (rama master)...");
132
- runGit("push kubiy master", { stdio: "inherit" });
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 });
133
149
  logSuccess("Push a kubiy master completado.");
134
150
  }
135
151
 
136
152
  async function run() {
137
153
  try {
138
- // 1) Asegurar repo git
154
+ // 1) Repo git
139
155
  ensureGitRepo();
140
156
 
141
- // 2) Asegurar que estamos en master
157
+ // 2) Estar en master o sí
142
158
  ensureOnMaster();
143
159
 
144
- // 3) Asegurar remote kubiy
160
+ // 3) Remote kubiy configurado
145
161
  ensureKubiyRemote();
146
162
 
147
- // 4) Crear commit automático si hay cambios
163
+ // 4) Commit automático si hay cambios
148
164
  if (hasChangesToCommit()) {
149
165
  createAutoCommit();
150
166
  } else {
151
167
  logInfo("No hay cambios locales. Solo se intentará hacer push.");
152
168
  }
153
169
 
154
- // 5) Push a kubiy master
170
+ // 5) Push
155
171
  pushToKubiy();
156
172
 
157
173
  logSuccess("🚀 Deploy completado. Revisa tu servicio Kubiy.");
158
174
  } catch (err) {
175
+ const msg = String(err.message || "").toLowerCase();
159
176
  logError("Error en kubiy deploy:");
160
- logError(err.message);
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
+
161
200
  process.exit(1);
162
201
  }
163
202
  }
package/src/ssh-config.js CHANGED
@@ -7,14 +7,6 @@ const { logInfo, logSuccess } = require("./logger");
7
7
  const SSH_DIR = path.join(os.homedir(), ".ssh");
8
8
  const SSH_CONFIG = path.join(SSH_DIR, "config");
9
9
 
10
- /**
11
- * Asegura que exista una entrada Host en ~/.ssh/config
12
- * para usar la llave de Kubiy con ese host.
13
- *
14
- * hostAlias: nombre lógico (p. ej. "kubiy-srv-<serviceId>")
15
- * hostName: IP pública o hostname real de la EC2
16
- * identityFile: ruta absoluta al id_ed25519 de Kubiy
17
- */
18
10
  function ensureSshHostConfig(hostAlias, hostName, identityFile) {
19
11
  if (!fs.existsSync(SSH_DIR)) {
20
12
  fs.mkdirSync(SSH_DIR, { recursive: true });
@@ -23,7 +15,6 @@ function ensureSshHostConfig(hostAlias, hostName, identityFile) {
23
15
  let existing = "";
24
16
  if (fs.existsSync(SSH_CONFIG)) {
25
17
  existing = fs.readFileSync(SSH_CONFIG, "utf8");
26
- // Si ya hay un bloque para este Host, no duplicamos
27
18
  const already = new RegExp(`^Host\\s+${hostAlias}\\b`, "m").test(existing);
28
19
  if (already) {
29
20
  logInfo(`SSH config ya tiene entrada para Host '${hostAlias}'`);
@@ -31,7 +22,6 @@ function ensureSshHostConfig(hostAlias, hostName, identityFile) {
31
22
  }
32
23
  }
33
24
 
34
- // Convertir backslashes a slashes para que OpenSSH en Windows no se maree
35
25
  const identityPath = identityFile.replace(/\\/g, "/");
36
26
 
37
27
  const block = [
@@ -41,6 +31,10 @@ function ensureSshHostConfig(hostAlias, hostName, identityFile) {
41
31
  ` User deploy`,
42
32
  ` IdentityFile ${identityPath}`,
43
33
  ` IdentitiesOnly yes`,
34
+ // 🎯 Para evitar el prompt interactivo de host key:
35
+ ` StrictHostKeyChecking no`,
36
+ // opcional, para no llenar el known_hosts global:
37
+ ` UserKnownHostsFile ~/.ssh/kubiy_known_hosts`,
44
38
  ""
45
39
  ].join("\n");
46
40
 
@@ -53,5 +47,5 @@ function ensureSshHostConfig(hostAlias, hostName, identityFile) {
53
47
  module.exports = {
54
48
  ensureSshHostConfig,
55
49
  SSH_DIR,
56
- SSH_CONFIG
50
+ SSH_CONFIG,
57
51
  };