kcreate-scaffolding-gcp-script 0.0.0-stage → 0.2.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kronops
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,430 @@
1
- # Temporary Holding Version
1
+ # KCreateScaffoldingGCPScripts
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Skill de Claude Code (`kcreate-scaffolding-gcp-script`) que genera el
4
+ scaffolding de Terragrunt para un entorno GCP nuevo, copiando y adaptando
5
+ uno ya existente del mismo repo (`live/<entorno-nuevo>/` a partir de
6
+ `live/<entorno-existente>/`). Pensado para repos con la convención de
7
+ [`club-tijuana/infra-cloud`](https://github.com/club-tijuana/infra-cloud):
8
+ `live/<entorno>/<componente>/terragrunt.hcl` + `Makefile` + `.gitignore`
9
+ por componente.
10
+
11
+ Este repo es el **instalador** del skill: contiene el skill, sus scripts y su
12
+ dependencia vendorizada, y los copia a `<repo-destino>/.claude/skills/`. No
13
+ contiene `live/` ni se instala a sí mismo.
14
+
15
+ **Este skill no despliega nada en GCP.** Solo crea/edita archivos locales.
16
+ El despliegue es un proceso aparte, posterior y manual.
17
+
18
+ > El directorio local y el nombre viejo del repo eran
19
+ > `KTerragruntScaffoldingScripts`; el repo en GitHub es
20
+ > [`kronops/KCreateScaffoldingGCPScripts`](https://github.com/kronops/KCreateScaffoldingGCPScripts).
21
+
22
+ | Documento | Para qué |
23
+ |---|---|
24
+ | `README.md` (este) | Manual de usuario: qué hace, cómo se instala y cómo se usa. |
25
+ | [`AGENT.md`](AGENT.md) | Guía operativa para agentes de IA: ciclo completo, contrato de exit codes, fallas comunes, receta de validación. |
26
+ | [`CONTRIBUTING.md`](CONTRIBUTING.md) | Flujo de contribución, convenciones e invariantes del código. |
27
+ | [`CHANGELOG.md`](CHANGELOG.md) | Historia de versiones (Keep a Changelog). |
28
+ | [`IDEA.md`](IDEA.md) | Especificación de origen del skill. |
29
+ | [`kcreate-scaffolding-gcp-script/SKILL.md`](kcreate-scaffolding-gcp-script/SKILL.md) | Instrucciones del agente, etapa por etapa (lo que ejecuta el skill instalado). |
30
+ | [`kcreate-scaffolding-gcp-script/references/lessons-learned.md`](kcreate-scaffolding-gcp-script/references/lessons-learned.md) | El "por qué" de cada script y validación, con los errores reales que los motivaron. |
31
+
32
+ ## Qué resuelve
33
+
34
+ Generar estos scripts a mano es mecánico pero con muchas oportunidades de
35
+ error que **no se detectan hasta el momento real de desplegar en GCP**
36
+ (un rango CIDR que colisiona, una IP mal transcrita, una API faltante, un
37
+ nombre de red que se quedó con el del entorno viejo). Este skill
38
+ automatiza esa generación con scripts de shell determinísticos — no con
39
+ juicio de un agente de IA en cada paso — para eliminar esa clase de
40
+ errores por diseño. El detalle completo de cada error real que este
41
+ diseño evita está en
42
+ [`kcreate-scaffolding-gcp-script/references/lessons-learned.md`](kcreate-scaffolding-gcp-script/references/lessons-learned.md).
43
+
44
+ ## Instalación
45
+
46
+ Hay dos instaladores **intercambiables** (`npx` y `install.sh`): dejan
47
+ exactamente el mismo resultado en el repo destino (mismos archivos, mismos
48
+ permisos, mismos exit codes). Elige el que te acomode.
49
+
50
+ En ambos casos se instala el skill (+ su dependencia
51
+ [`github-proyect-tracking`](https://github.com/kronops/KGithubTracking),
52
+ vendorizada en `vendor/`) en el repo donde se va a usar, como skill de
53
+ proyecto de Claude Code.
54
+
55
+ | Vía | Cuándo usarla | Requisitos |
56
+ |---|---|---|
57
+ | **A — `npx`** (paquete publicado en npm) | La normal: no hay que clonar este repo. | Node ≥ 18 |
58
+ | **A-bis — `npx` sobre un tarball** | Sin acceso al registro, o para probar una versión local antes de publicarla. | Node ≥ 18 + copia de este repo |
59
+ | **B — `install.sh`** | Prefieres bash puro, o trabajas con el repo ya clonado. | bash + git |
60
+
61
+ ### Opción A — `npx` (recomendada, sin clonar el repo)
62
+
63
+ El paquete está publicado en el registro público de npm como
64
+ [`kcreate-scaffolding-gcp-script`](https://www.npmjs.com/package/kcreate-scaffolding-gcp-script)
65
+ (versión actual: `0.2.1`). Único requisito: **Node ≥ 18** (`npx` viene con
66
+ npm). El instalador no tiene dependencias npm; el skill en sí no usa Node:
67
+ es bash + Python 3.8+ stdlib.
68
+
69
+ ```bash
70
+ # 0) (opcional) diagnóstico: no modifica nada, solo reporta el estado del destino
71
+ npx --yes kcreate-scaffolding-gcp-script doctor --target-repo /ruta/a/tu/repo-de-infra
72
+
73
+ # 1) instalar el skill en el repo destino
74
+ npx --yes kcreate-scaffolding-gcp-script --target-repo /ruta/a/tu/repo-de-infra
75
+ ```
76
+
77
+ Salida esperada del paso 1:
78
+
79
+ ```
80
+ [OK] kcreate-scaffolding-gcp-script instalado en <repo>/.claude/skills/kcreate-scaffolding-gcp-script
81
+ [OK] github-proyect-tracking instalado en <repo>/.claude/skills/github-proyect-tracking
82
+ [OK] Instalación completa en <repo>
83
+ ```
84
+
85
+ Notas de uso:
86
+
87
+ - `--yes` evita el prompt de npx (`Need to install the following packages`)
88
+ la primera vez. `npx` cachea el paquete, así que las siguientes corridas son
89
+ instantáneas.
90
+ - Para instalaciones reproducibles fija la versión:
91
+ `npx --yes kcreate-scaffolding-gcp-script@0.2.1 --target-repo <repo>`. Sin
92
+ sufijo toma `latest`.
93
+ - **Actualizar** = volver a correr el mismo comando con `--force`. Sin
94
+ `--force`, una instalación existente nunca se toca: termina con
95
+ `[ERROR] No se instaló nada…` y **exit 1**.
96
+ - También sirve instalarlo global: `npm install -g kcreate-scaffolding-gcp-script`
97
+ y después `kcreate-scaffolding-gcp-script --target-repo <repo>`.
98
+ - Ayuda y versión del instalador: `npx --yes kcreate-scaffolding-gcp-script --help`
99
+ y `--version` (hoy responde `kcreate-scaffolding-gcp-script/0.2.1 (instalador npx)`).
100
+
101
+ > `npx ... github:kronops/KCreateScaffoldingGCPScripts` **no** sirve: npm
102
+ exige el `package.json` en la raíz del repo y aquí vive en `npm/` (npm no
103
+ soporta subdirectorios en dependencias git). Por eso la opción `npx` usa el
104
+ paquete del registro o un tarball local.
105
+
106
+ ### Opción A-bis — `npx` sobre un tarball local
107
+
108
+ Para probar una versión que aún no está publicada (o sin red):
109
+
110
+ ```bash
111
+ git clone git@github-work:kronops/KCreateScaffoldingGCPScripts.git
112
+ cd KCreateScaffoldingGCPScripts/npm
113
+ npm pack # prepack empaqueta skill/ + vendor/ + README + LICENSE
114
+ npx --yes ./kcreate-scaffolding-gcp-script-0.2.1.tgz --target-repo /ruta/a/tu/repo-de-infra
115
+ ```
116
+
117
+ Detalle que muerde: `npx` solo acepta el tarball con ruta **relativa con
118
+ `./`** o como URL `file:`. Una ruta absoluta "pelada"
119
+ (`npx /tmp/x.tgz`) falla con `sh: Permission denied` y **exit 126**:
120
+
121
+ ```bash
122
+ # mal
123
+ npx --yes /tmp/kcreate-scaffolding-gcp-script-0.2.1.tgz --target-repo /ruta/al/repo
124
+ # bien
125
+ npx --yes "file:/tmp/kcreate-scaffolding-gcp-script-0.2.1.tgz" --target-repo /ruta/al/repo
126
+ ```
127
+
128
+ ### Opción B — clonando el repo (`install.sh`)
129
+
130
+ ```bash
131
+ git clone git@github-work:kronops/KCreateScaffoldingGCPScripts.git
132
+ cd KCreateScaffoldingGCPScripts
133
+ ./install.sh --target-repo /ruta/a/tu/repo-de-infra
134
+ ```
135
+
136
+ ### Resultado (idéntico en las tres vías)
137
+
138
+ ```
139
+ <tu-repo>/.claude/skills/
140
+ ├── kcreate-scaffolding-gcp-script/ # este skill
141
+ └── github-proyect-tracking/ # dependencia, para poder reanudar
142
+ ```
143
+
144
+ Si el repo destino no tiene `live/`, el instalador avisa con `[WARN]` (el
145
+ skill asume la convención `live/<entorno>/<componente>/terragrunt.hcl`) pero
146
+ igual instala: la herramienta sirve para cualquier repo, aunque falle al
147
+ usarse.
148
+
149
+ ### Exit codes del instalador npx
150
+
151
+ | Exit | Significado |
152
+ |---|---|
153
+ | `0` | El skill quedó instalado/actualizado en el destino. |
154
+ | `1` | No se instaló nada: el skill ya existía sin `--force`, el destino no existe o no es la raíz de un repo git. |
155
+ | `2` | Argumentos inválidos (falta `--target-repo`, flag desconocido, comando desconocido). |
156
+
157
+ ### Flags
158
+
159
+ Los mismos nombres y semántica en `install.sh` y en el instalador npx:
160
+
161
+ | Flag | Para qué |
162
+ |---|---|
163
+ | `--target-repo RUTA` | Raíz del repo destino (obligatorio; debe ser un repo git). |
164
+ | `--skip-tracking` | No instala/actualiza `github-proyect-tracking`, por si el repo destino ya lo gestiona por su cuenta. |
165
+ | `--force` | Sobreescribe si el skill ya existe en el destino. Sin esta bandera, una instalación existente nunca se toca: se reporta con `[ERROR]` y **exit 1** (no se instala nada). |
166
+
167
+ Para desinstalar:
168
+
169
+ ```bash
170
+ # npx
171
+ npx --yes kcreate-scaffolding-gcp-script uninstall --target-repo /ruta/a/tu/repo
172
+
173
+ # clonado
174
+ ./uninstall.sh --target-repo /ruta/a/tu/repo
175
+ ```
176
+
177
+ | Flag de uninstall | Para qué |
178
+ |---|---|
179
+ | `--with-tracking` | También elimina `github-proyect-tracking`. Por defecto **no** se toca, porque otro skill del mismo repo podría seguir usándolo. |
180
+ | `--clean-gitignore` | También quita la línea `.kcreate-scaffolding/` del `.gitignore` del destino y borra la carpeta `.kcreate-scaffolding/` (configs y warnings de ejecuciones anteriores). Es destructivo a propósito: úsalo solo si ya no necesitas revisar esos archivos. |
181
+
182
+ ### Diagnóstico previo (`npx … doctor`)
183
+
184
+ Solo en el instalador npx. No modifica nada: dice qué hay instalado en el
185
+ repo destino y si están las dependencias que usan los scripts.
186
+
187
+ ```bash
188
+ npx --yes kcreate-scaffolding-gcp-script doctor --target-repo /ruta/a/tu/repo
189
+ ```
190
+
191
+ Revisa `bash`, `git`, `python3` (con `ipaddress`), `curl` y `terragrunt`
192
+ (**opcional**: si falta, el build omite `hcl fmt`/`hcl validate` y avisa).
193
+ Termina con `[OK] Entorno listo para usar el skill.` (exit 0) o con exit 1
194
+ listando los requisitos faltantes.
195
+
196
+ ### Publicar el paquete npm (mantenedores)
197
+
198
+ El paquete está publicado y su mantenedor es `kronops`. Procedimiento:
199
+
200
+ ```bash
201
+ cd npm
202
+ npm whoami # ¿hay sesión? (si da E401, hay que loguearse)
203
+ npm login --auth-type=legacy # usuario, password, email y, si la cuenta tiene 2FA, OTP
204
+ npm publish --dry-run # ensayo obligatorio: construye el tarball sin subir nada
205
+ npm publish # publicar (con 2FA: npm publish --otp=123456)
206
+ npm view kcreate-scaffolding-gcp-script version # confirmar la versión en el registro
207
+ ```
208
+
209
+ Ojo: si la cuenta tiene 2FA, el login por navegador **no** sirve sin GUI; hay
210
+ que usar `--auth-type=legacy` y pasar el OTP. El `.npmrc` que deja el login
211
+ contiene `_authToken` y ya está en `.gitignore`.
212
+
213
+ `npm/bin/build.js` reconstruye `npm/skill/`, `npm/vendor/`,
214
+ `npm/README.md` y `npm/LICENSE` desde la raíz del repo en cada
215
+ `npm pack`/`npm publish` — son artefactos generados y están en `.gitignore`,
216
+ nunca se comitean. Prueba local sin publicar:
217
+
218
+ ```bash
219
+ cd npm && npm pack
220
+ npx --yes ./kcreate-scaffolding-gcp-script-0.2.1.tgz --target-repo /ruta/al/repo
221
+ ```
222
+
223
+ Para subir una versión nueva: `node -p "require('./package.json').version"`,
224
+ luego `npm version patch --no-git-tag-version` (o `minor`/`major` según el
225
+ cambio) y refleja la versión en `CHANGELOG.md` y en las rutas de este README.
226
+ El `--no-git-tag-version` es obligatorio aquí: el `package.json` no está en la
227
+ raíz git y sin ese flag `npm version` crea commits y tags inesperados. Subir la
228
+ versión no es opcional cuando ya se publicó: una versión del registro no se
229
+ puede reutilizar (`E409`).
230
+
231
+ ## Uso
232
+
233
+ Desde una sesión de Claude Code abierta en el repo destino (con el skill
234
+ ya instalado ahí), con el cwd en la raíz de ese repo:
235
+
236
+ ```
237
+ /kcreate-scaffolding-gcp-script <SOURCE_ENV> <NEW_ENV>
238
+ ```
239
+
240
+ - `SOURCE_ENV`: el entorno ya existente a copiar (ej. `boletera-qa`).
241
+ Cualquiera que ya exista en `live/` sirve — no hay uno "oficial".
242
+ - `NEW_ENV`: el id del entorno nuevo, patrón `<app>-qa` o `<app>-prod` en
243
+ minúsculas (ej. `xoloshop-prod`).
244
+
245
+ El agente sigue entonces las 3 etapas descritas en
246
+ [`kcreate-scaffolding-gcp-script/SKILL.md`](kcreate-scaffolding-gcp-script/SKILL.md):
247
+
248
+ 1. **Pre requisitos** — genera (o reanuda) un archivo de configuración en
249
+ `.kcreate-scaffolding/<NEW_ENV>.config`, autodetectando del propio
250
+ `SOURCE_ENV` todo lo que se pueda (org id, billing account,
251
+ región/zona, owner, IPs fijas, versiones actuales). Solo pide al
252
+ humano lo que de verdad no se puede inferir: el repo de GitHub de la
253
+ app nueva y la URL del proyecto de GitHub usado para llevar el
254
+ seguimiento de esta ejecución. Antes de construir nada, muestra el
255
+ archivo completo y pide confirmación explícita.
256
+ 2. **Construcción** — un solo comando genera `live/<NEW_ENV>/` completo,
257
+ componente por componente, con sustituciones de texto determinísticas
258
+ (nunca ediciones "a mano" de HCL). Avisa con `[WARN]` en los pocos
259
+ casos que de verdad requieren revisión humana (ver la lista completa en
260
+ `lessons-learned.md`).
261
+ 3. **Validación** — dos scripts confirman que el resultado está completo
262
+ (mismos archivos que `SOURCE_ENV`, ni más ni menos) y que cada
263
+ componente apunta siempre al proyecto GCP correcto, sin importar qué
264
+ proyecto tenga `gcloud` como default en ese momento.
265
+
266
+ Si el proceso se interrumpe a la mitad (sesión caída, error de red), basta
267
+ con pedirle al agente que vuelva a correr el mismo comando. El progreso
268
+ se registra en `github-proyect-tracking` (un Issue del repo de GitHub que
269
+ pusiste en `TRACKING_GITHUB_PROJECT_URL`) cuando está disponible — si
270
+ falla (sin red, token, URL inválida), la construcción sigue igual sin
271
+ tracking, solo con un aviso. La construcción en sí es idempotente: cada
272
+ componente se reconstruye siempre desde `SOURCE_ENV`, así que reintentar
273
+ después de un fallo a medias no requiere borrar nada ni produce un
274
+ resultado distinto (el rango CIDR elegido también se reusa, no se vuelve
275
+ a calcular).
276
+
277
+ ### El archivo de configuración
278
+
279
+ Se genera una sola vez por ejecución, en
280
+ `.kcreate-scaffolding/<NEW_ENV>.config` (gitignorado automáticamente —
281
+ nunca se comitea). Plantilla de referencia:
282
+ [`kcreate-scaffolding-gcp-script/templates/scaffolding.config.template`](kcreate-scaffolding-gcp-script/templates/scaffolding.config.template).
283
+
284
+ Campos que **siempre** hay que llenar a mano (no se pueden inferir de
285
+ `SOURCE_ENV`):
286
+
287
+ | Campo | Qué es |
288
+ |---|---|
289
+ | `APP_GITHUB_REPO` | Repo(s) de GitHub (`owner/repo`) que hacen `push` de imágenes Docker al Artifact Registry del proyecto nuevo. Uno solo en el caso común; si la app tiene varios repos, sepáralos con `;` — se genera un binding de `github_workload_identity` por cada uno. Se asume que ya existen — no se valida contra GitHub. |
290
+ | `TRACKING_GITHUB_PROJECT_URL` | URL (`https://github.com/{owner}/{repo}`) donde `github-proyect-tracking` va a crear el Issue de seguimiento de esta ejecución. |
291
+
292
+ Campos opcionales, con default vacío (no bloquean `CONFIG_READY`):
293
+
294
+ | Campo | Qué es |
295
+ |---|---|
296
+ | `EXTRA_COMPONENTS` | Componentes a incluir además de los base (ver "Componentes base vs. opcionales" abajo), separados por `;`. Vacío por defecto. |
297
+ | `DNS_DOMAIN` | Si `sql_postgres` usa `dns_domain_name`, el dominio real que `NEW_ENV` usa. Vacío por defecto — el skill genera un valor por patrón marcado con `[WARN]` para confirmar. |
298
+
299
+ Todo lo demás se autodetecta y queda ahí para revisión, no para
300
+ llenarlo desde cero. El `02_print_config.sh` también corre un chequeo de
301
+ salud ("doctor") sobre `SOURCE_ENV` antes de mostrar el config — avisa si
302
+ le falta algo que el resto de `live/` ya tiene (ver
303
+ `lessons-learned.md`, sección C).
304
+
305
+ ### Componentes base vs. opcionales
306
+
307
+ El build solo incluye, por defecto, los componentes que existen en
308
+ **todos** los entornos reales de `live/` (la intersección real, calculada
309
+ en el momento — no una lista hardcodeada). Un componente que `SOURCE_ENV`
310
+ tenga pero que no sea base (`cloud_armor`, `secrets`, etc.) queda
311
+ excluido, siguiendo la guía de experiencia (§1.2: "no incluir salvo
312
+ pedido explícito"). Para incluirlo de todas formas, agrégalo a
313
+ `EXTRA_COMPONENTS` en el config y vuelve a correr la construcción.
314
+
315
+ ## Ejecutar los scripts manualmente (sin el agente)
316
+
317
+ Cada script es independiente y se puede correr a mano, desde la raíz del
318
+ repo destino:
319
+
320
+ ```bash
321
+ S=.claude/skills/kcreate-scaffolding-gcp-script/scripts
322
+
323
+ $S/01_init_config.sh boletera-qa xoloshop-prod # pre requisitos
324
+ # ... editar los campos __PENDIENTE__ del .config ...
325
+ $S/01_init_config.sh boletera-qa xoloshop-prod # confirma CONFIG_READY
326
+ $S/02_print_config.sh xoloshop-prod # revisar antes de construir
327
+
328
+ $S/10_build_components.sh xoloshop-prod # construcción
329
+
330
+ $S/20_validate_file_parity.sh boletera-qa xoloshop-prod
331
+ $S/21_validate_project_pinning.sh xoloshop-prod
332
+ $S/22_validate_no_app_name_leftover.sh xoloshop-prod
333
+ ```
334
+
335
+ Cada script termina con un mensaje de una sola línea y un código de salida
336
+ acorde — pensado para scripting, no solo para lectura humana:
337
+
338
+ | Script | `0` | `2` | `1` | `3` |
339
+ |---|---|---|---|---|
340
+ | `install.sh` | skill instalado/actualizado | — | no se instaló nada (ya existía, sin `--force`) o argumento inválido | — |
341
+ | `npm/bin/cli.js install` | skill instalado/actualizado | argumento/flag inválido o paquete corrupto | no se instaló nada (ya existía, sin `--force`) o destino no es repo git | — |
342
+ | `uninstall.sh` | desinstalado (o no estaba) | — | argumento inválido / destino no es repo git | — |
343
+ | `npm/bin/cli.js uninstall` | desinstalado (o no estaba) | argumento/flag inválido | destino no es repo git | — |
344
+ | `npm/bin/cli.js doctor` | entorno listo | argumento/flag inválido | falta algún requisito (bash/git/python3/curl) | — |
345
+ | `01_init_config.sh` | `CONFIG_READY` | `CONFIG_PENDING` (faltan campos) | error de validación | — |
346
+ | `02_print_config.sh` | config impreso | — | falta config / `NEW_ENV` | — |
347
+ | `10_build_components.sh` | `BUILD_OK: <ruta>` | — | `BUILD_FAILED: <paso> - <detalle>` | — |
348
+ | `20_validate_file_parity.sh` | `FILE_PARITY_OK: <n>` | — | `FILE_PARITY_MISMATCH` | — |
349
+ | `21_validate_project_pinning.sh` | `PROJECT_PINNING_OK: <n>` | — | `PROJECT_PINNING_FAILED` | — |
350
+ | `22_validate_no_app_name_leftover.sh` | `APP_NAME_LEFTOVER_OK` | — | `APP_NAME_LEFTOVER_FOUND: <n>` | — |
351
+ | `run_tracking.sh` | comando OK | — | error de tracking | tracking no instalado |
352
+
353
+ `2` no es un error: es la señal de "faltan datos, llénalos y vuelve a correr
354
+ el mismo comando".
355
+
356
+ ## Estructura de este repo
357
+
358
+ ```
359
+ KCreateScaffoldingGCPScripts/
360
+ ├── README.md / AGENT.md / CONTRIBUTING.md / CHANGELOG.md
361
+ ├── IDEA.md # especificación de origen del skill
362
+ ├── CreateScriptsNewGCPProjectInstructions.md # guía manual de referencia (base de experiencia)
363
+ ├── LICENSE # MIT
364
+ ├── .gitignore
365
+ ├── install.sh / uninstall.sh # instalan/quitan el skill de un repo destino
366
+ ├── lib/common.sh # helpers de install.sh/uninstall.sh
367
+ ├── npm/ # instalador npx (mismo contrato que install.sh)
368
+ │ ├── package.json # bin: kcreate-scaffolding-gcp-script
369
+ │ └── bin/{cli.js,build.js} # cli = instalador; build = prepack (empaqueta skill/ y vendor/)
370
+ ├── vendor/github-proyect-tracking/ # dependencia vendorizada (ver vendor/VENDORED_FROM.md)
371
+ └── kcreate-scaffolding-gcp-script/
372
+ ├── SKILL.md # instrucciones para el agente, por etapa
373
+ ├── references/
374
+ │ └── lessons-learned.md # el "por qué" de cada script/validación
375
+ ├── templates/
376
+ │ └── scaffolding.config.template
377
+ └── scripts/
378
+ ├── lib/common.sh # helpers del skill (CIDR, extracción HCL, etc.)
379
+ ├── 01_init_config.sh # Pre requisitos, paso 1
380
+ ├── 02_print_config.sh # Pre requisitos, paso 2
381
+ ├── 10_build_components.sh # Construcción
382
+ ├── 20_validate_file_parity.sh # Validación 1
383
+ ├── 21_validate_project_pinning.sh # Validación 2
384
+ ├── 22_validate_no_app_name_leftover.sh # Validación 3
385
+ └── run_tracking.sh # envoltura sobre github-proyect-tracking
386
+ ```
387
+
388
+ ## Limitaciones conocidas
389
+
390
+ - Asume que `NEW_ENV` usa la misma región/zona que `SOURCE_ENV` — no hay
391
+ forma de pedir una región distinta todavía.
392
+ - Sin suite de pruebas automatizada. La verificación es por ejecución real;
393
+ la receta reproducible (install/uninstall de humo y ciclo completo contra
394
+ una copia descartable de un entorno real) está en
395
+ [`CONTRIBUTING.md`](CONTRIBUTING.md#validación-reproducible) y
396
+ [`AGENT.md`](AGENT.md#desarrollo-y-pruebas).
397
+ - El instalador npx **no** puede consumirse como
398
+ `npx github:kronops/KCreateScaffoldingGCPScripts`: npm exige el
399
+ `package.json` en la raíz del repo y aquí vive en `npm/` (no soporta
400
+ subdirectorios en dependencias git). Por eso se publica en el registro y
401
+ se instala como `npx kcreate-scaffolding-gcp-script`, o vía tarball local
402
+ (`npm pack`).
403
+ - El paquete del registro se actualiza solo cuando alguien corre
404
+ `npm publish` a mano: un cambio en este repo no llega a los usuarios de
405
+ `npx` hasta que sube la versión (y una versión publicada no se reutiliza,
406
+ `E409`).
407
+ - El nombre del proyecto (`PROJECT_NAME`, ej. `Xoloshop-Prod`) se infiere de
408
+ `NEW_ENV` con la convención `<App>-<QA|Prod>`; si la app tiene siglas o una
409
+ capitalización no obvia, corrígelo a mano en el config antes de construir.
410
+ - Los componentes incluidos vía `EXTRA_COMPONENTS` (sin manejo dedicado)
411
+ se copian con una sustitución genérica y quedan marcados `[WARN]` para
412
+ revisión manual — no tienen el mismo nivel de automatización que los
413
+ componentes base.
414
+ - `project_iam` requiere siempre una revisión humana (bindings
415
+ específicos del equipo/app de `SOURCE_ENV`) — no es mecanizable sin
416
+ conocer el negocio de la app nueva. Ver `lessons-learned.md` (A10).
417
+ `artifact_registry`, en cambio, ya se resuelve solo incluso cuando
418
+ `SOURCE_ENV` tiene valores genéricos: aprende el patrón de otro
419
+ entorno de `live/` que sí tenga el suyo específico (ver
420
+ `lessons-learned.md`, D7) — solo queda en `[WARN]` manual si **ningún**
421
+ entorno de `live/` tiene uno específico del que aprender.
422
+ - `service_accounts`/`project_iam` pueden copiar (renombradas) entradas
423
+ que son específicas de `SOURCE_ENV` y no corresponden a la app nueva
424
+ (ej. SAs o namespaces de un componente que `SOURCE_ENV` tiene pero
425
+ `NEW_ENV` no construye) — hoy solo se advierte si hay más de 5 service
426
+ accounts, no se filtra cuál sobra.
427
+ - El "doctor" de `02_print_config.sh` compara contra el resto de `live/`
428
+ por mayoría/recencia, no contra una lista de requisitos conocida — no
429
+ detecta un requisito nuevo si NINGÚN entorno de `live/` lo tiene todavía
430
+ (ver `lessons-learned.md`, sección C, nota en el ítem del doctor).
package/bin/build.js ADDED
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Empaqueta el contenido del skill dentro de npm/ para su distribución
4
+ * (prepack). Se ejecuta automáticamente con `npm pack` / `npm publish`.
5
+ *
6
+ * kcreate-scaffolding-gcp-script/ → npm/skill/
7
+ * vendor/github-proyect-tracking/ → npm/vendor/github-proyect-tracking/
8
+ * README.md, LICENSE → npm/README.md, npm/LICENSE
9
+ *
10
+ * Ninguno de estos artefactos se comitea (ver .gitignore): se recrean en cada
11
+ * prepack, para que el paquete nunca quede desincronizado del repo.
12
+ */
13
+ 'use strict';
14
+
15
+ const fs = require('node:fs');
16
+ const path = require('node:path');
17
+
18
+ const here = path.join(__dirname, '..');
19
+ const root = path.join(here, '..');
20
+ const srcSkill = path.join(root, 'kcreate-scaffolding-gcp-script');
21
+ const srcTracking = path.join(root, 'vendor', 'github-proyect-tracking');
22
+ const dstSkill = path.join(here, 'skill');
23
+ const dstTracking = path.join(here, 'vendor', 'github-proyect-tracking');
24
+
25
+ function fail(msg) {
26
+ console.error(`ERROR: ${msg}`);
27
+ process.exit(1);
28
+ }
29
+
30
+ if (!fs.existsSync(path.join(srcSkill, 'SKILL.md'))) {
31
+ fail(`no se encontró ${srcSkill}/SKILL.md`);
32
+ }
33
+ if (!fs.existsSync(path.join(srcTracking, 'SKILL.md'))) {
34
+ fail(`no se encontró ${srcTracking}/SKILL.md (dependencia vendorizada)`);
35
+ }
36
+
37
+ function clean(dir) {
38
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
39
+ const p = path.join(dir, e.name);
40
+ if (e.isDirectory()) {
41
+ if (e.name === '__pycache__') fs.rmSync(p, { recursive: true, force: true });
42
+ else clean(p);
43
+ } else if (/\.py[co]$/.test(e.name)) {
44
+ fs.rmSync(p, { force: true });
45
+ }
46
+ }
47
+ }
48
+
49
+ function stage(src, dst) {
50
+ fs.rmSync(dst, { recursive: true, force: true });
51
+ fs.cpSync(src, dst, { recursive: true });
52
+ clean(dst);
53
+ }
54
+
55
+ stage(srcSkill, dstSkill);
56
+ stage(srcTracking, dstTracking);
57
+
58
+ // Los modos se preservan tal cual desde el origen (fs.cpSync los copia), igual
59
+ // que `cp -R` en install.sh: el resultado instalado desde el repo debe ser
60
+ // idéntico con los dos instaladores. Ojo: `npm pack`/`npm publish` normaliza
61
+ // los modos del tarball; por eso npm/bin/cli.js vuelve a poner los bits de
62
+ // ejecución al instalar (chmodScripts/addExecBits) — la red de seguridad para
63
+ // el caso del paquete publicado.
64
+
65
+ fs.copyFileSync(path.join(root, 'README.md'), path.join(here, 'README.md'));
66
+ fs.copyFileSync(path.join(root, 'LICENSE'), path.join(here, 'LICENSE'));
67
+
68
+ console.log(`skill → ${dstSkill}`);
69
+ console.log(`tracking → ${dstTracking}`);
70
+ console.log('README.md + LICENSE → npm/');