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.
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env bash
2
+ # Etapa: Validación — script 1.
3
+ # Compara, por cantidad Y por estructura, los archivos que realmente
4
+ # pertenecen al proyecto (los que git comitearía — ni temporales ni cache)
5
+ # entre live/<SOURCE_ENV>/ y live/<NEW_ENV>/.
6
+ #
7
+ # Uso: 20_validate_file_parity.sh <SOURCE_ENV> <NEW_ENV>
8
+ #
9
+ # Termina con exactamente uno de estos mensajes:
10
+ # "FILE_PARITY_OK: <n> archivos en ambos lados" (exit 0)
11
+ # "FILE_PARITY_MISMATCH: faltan <n>, sobran <m> (ver detalle arriba)" (exit 1)
12
+
13
+ set -uo pipefail
14
+
15
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
+ # shellcheck source=lib/common.sh
17
+ source "$SCRIPT_DIR/lib/common.sh"
18
+
19
+ SOURCE_ENV="${1:-}"
20
+ NEW_ENV="${2:-}"
21
+ [[ -n "$SOURCE_ENV" && -n "$NEW_ENV" ]] || ksc_die "uso: 20_validate_file_parity.sh <SOURCE_ENV> <NEW_ENV>"
22
+
23
+ REPO_ROOT="$(ksc_repo_root)"
24
+ [[ -d "$REPO_ROOT/live/$SOURCE_ENV" ]] || ksc_die "no existe live/$SOURCE_ENV"
25
+ [[ -d "$REPO_ROOT/live/$NEW_ENV" ]] || ksc_die "no existe live/$NEW_ENV"
26
+
27
+ # "Archivos que pertenecen al proyecto" = los que `git add -A` incluiría:
28
+ # ya trackeados (--cached) + nuevos no ignorados (--others --exclude-standard).
29
+ # Así se excluyen automáticamente .terraform/, *.tfstate, plan.binary/.txt,
30
+ # y cualquier otro patrón cubierto por .gitignore — sin mantener una lista
31
+ # de extensiones a mano.
32
+ list_project_files() {
33
+ local env="$1"
34
+ (cd "$REPO_ROOT" && git ls-files --cached --others --exclude-standard -- "live/$env/") \
35
+ | sed "s|^live/$env/||" | sort
36
+ }
37
+
38
+ # El build (10_build_components.sh) excluye por defecto los componentes
39
+ # opcionales de SOURCE_ENV que no sean "base" (intersección real de
40
+ # live/), salvo que EXTRA_COMPONENTS del config los pida. Comparar contra
41
+ # TODOS los archivos de SOURCE_ENV sin esa misma restricción marcaría como
42
+ # "falta" algo que nunca se intentó copiar a propósito — no es un defecto
43
+ # de construcción. Se restringe la lista de SOURCE_ENV a los mismos
44
+ # componentes que el build intentó, usando el config de NEW_ENV si existe.
45
+ ALLOWED_TOPLEVEL=()
46
+ CONFIG_FILE="$(ksc_config_path "$REPO_ROOT" "$NEW_ENV")"
47
+ if [[ -f "$CONFIG_FILE" ]]; then
48
+ EXTRA_COMPONENTS="$(ksc_hcl_get "$CONFIG_FILE" EXTRA_COMPONENTS 2>/dev/null || true)"
49
+ else
50
+ EXTRA_COMPONENTS=""
51
+ ksc_info "no existe $CONFIG_FILE — se compara contra TODOS los componentes de $SOURCE_ENV, sin filtrar por EXTRA_COMPONENTS."
52
+ fi
53
+ mapfile -t BASE_COMPONENTS < <(ksc_base_components "$REPO_ROOT" "$NEW_ENV")
54
+ ALLOWED_TOPLEVEL=("${BASE_COMPONENTS[@]}" "project.hcl" "Makefile" "README.md" ".gitignore")
55
+ IFS=';' read -ra _extra <<<"$EXTRA_COMPONENTS"
56
+ for x in "${_extra[@]}"; do [[ -n "$x" ]] && ALLOWED_TOPLEVEL+=("$x"); done
57
+
58
+ filter_allowed() {
59
+ local line top
60
+ while IFS= read -r line; do
61
+ top="${line%%/*}"
62
+ for a in "${ALLOWED_TOPLEVEL[@]}"; do
63
+ [[ "$top" == "$a" ]] && { printf '%s\n' "$line"; break; }
64
+ done
65
+ done
66
+ }
67
+
68
+ SRC_LIST="/tmp/ksc_parity_src.$$"
69
+ NEW_LIST="/tmp/ksc_parity_new.$$"
70
+ list_project_files "$SOURCE_ENV" | filter_allowed > "$SRC_LIST"
71
+ list_project_files "$NEW_ENV" > "$NEW_LIST"
72
+
73
+ MISSING="/tmp/ksc_parity_missing.$$"
74
+ EXTRA="/tmp/ksc_parity_extra.$$"
75
+ comm -23 "$SRC_LIST" "$NEW_LIST" > "$MISSING" # en SOURCE pero no en NEW
76
+ comm -13 "$SRC_LIST" "$NEW_LIST" > "$EXTRA" # en NEW pero no en SOURCE
77
+
78
+ SRC_COUNT=$(wc -l < "$SRC_LIST")
79
+ NEW_COUNT=$(wc -l < "$NEW_LIST")
80
+ MISSING_COUNT=$(wc -l < "$MISSING")
81
+ EXTRA_COUNT=$(wc -l < "$EXTRA")
82
+
83
+ echo "live/$SOURCE_ENV/: $SRC_COUNT archivos de proyecto"
84
+ echo "live/$NEW_ENV/: $NEW_COUNT archivos de proyecto"
85
+
86
+ STATUS=0
87
+ if [[ "$MISSING_COUNT" -gt 0 ]]; then
88
+ echo
89
+ echo "Archivos de $SOURCE_ENV que NO existen (con ruta equivalente) en $NEW_ENV:"
90
+ sed 's/^/ - /' "$MISSING"
91
+ STATUS=1
92
+ fi
93
+ if [[ "$EXTRA_COUNT" -gt 0 ]]; then
94
+ echo
95
+ echo "Archivos en $NEW_ENV que no tienen equivalente en $SOURCE_ENV:"
96
+ sed 's/^/ + /' "$EXTRA"
97
+ STATUS=1
98
+ fi
99
+
100
+ rm -f "$SRC_LIST" "$NEW_LIST" "$MISSING" "$EXTRA"
101
+
102
+ if [[ "$STATUS" -eq 0 ]]; then
103
+ echo "FILE_PARITY_OK: $SRC_COUNT archivos en ambos lados"
104
+ else
105
+ echo "FILE_PARITY_MISMATCH: faltan $MISSING_COUNT, sobran $EXTRA_COUNT (ver detalle arriba)"
106
+ fi
107
+ exit "$STATUS"
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env bash
2
+ # Etapa: Validación — script 2.
3
+ # Confirma que, sin importar qué proyecto tenga `gcloud` como default en el
4
+ # momento de ejecutar `terragrunt`, cada componente de live/<NEW_ENV>/
5
+ # resuelve siempre al proyecto correcto. Dos cosas se verifican:
6
+ #
7
+ # 1. live/<NEW_ENV>/project.hcl fija project_id = "<NEW_ENV>" como literal
8
+ # (la raíz de la cadena de la que todos los componentes heredan).
9
+ # 2. Cada componente que declara `project_id` en sus `inputs` lo hace vía
10
+ # `local.project_id` (que viene de ese project.hcl por
11
+ # find_in_parent_folders) — nunca un literal distinto, nunca vacío.
12
+ # 3. Ningún archivo de live/<NEW_ENV>/ contiene todavía el nombre del
13
+ # entorno fuente (sustitución incompleta real, no solo teórica).
14
+ #
15
+ # Uso: 21_validate_project_pinning.sh <NEW_ENV>
16
+ #
17
+ # Termina con exactamente uno de estos mensajes:
18
+ # "PROJECT_PINNING_OK: <n> componentes verificados" (exit 0)
19
+ # "PROJECT_PINNING_FAILED: <detalle arriba>" (exit 1)
20
+
21
+ set -uo pipefail
22
+
23
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
24
+ # shellcheck source=lib/common.sh
25
+ source "$SCRIPT_DIR/lib/common.sh"
26
+
27
+ NEW_ENV="${1:-}"
28
+ [[ -n "$NEW_ENV" ]] || ksc_die "uso: 21_validate_project_pinning.sh <NEW_ENV>"
29
+
30
+ REPO_ROOT="$(ksc_repo_root)"
31
+ NEW_DIR="$REPO_ROOT/live/$NEW_ENV"
32
+ [[ -d "$NEW_DIR" ]] || ksc_die "no existe $NEW_DIR"
33
+
34
+ CONFIG_FILE="$(ksc_config_path "$REPO_ROOT" "$NEW_ENV")"
35
+ SOURCE_ENV=""
36
+ [[ -f "$CONFIG_FILE" ]] && SOURCE_ENV="$(ksc_hcl_get "$CONFIG_FILE" SOURCE_ENV 2>/dev/null || true)"
37
+ [[ -n "$SOURCE_ENV" ]] || SOURCE_ENV="$(grep -m1 '^SOURCE_ENV=' "$CONFIG_FILE" 2>/dev/null | sed -E 's/^SOURCE_ENV="(.*)"$/\1/')"
38
+
39
+ FAILURES=()
40
+
41
+ # --- 1. project.hcl fija el project_id como literal ------------------------
42
+ PROJECT_HCL="$NEW_DIR/project.hcl"
43
+ if [[ ! -f "$PROJECT_HCL" ]]; then
44
+ FAILURES+=("falta $PROJECT_HCL")
45
+ else
46
+ pid="$(ksc_hcl_get "$PROJECT_HCL" project_id)"
47
+ if [[ "$pid" != "$NEW_ENV" ]]; then
48
+ FAILURES+=("$PROJECT_HCL: project_id = \"$pid\" (debería ser literal \"$NEW_ENV\")")
49
+ fi
50
+ fi
51
+
52
+ # --- 2. cada componente resuelve project_id vía local.project_id -----------
53
+ CHECKED=0
54
+ for tg in "$NEW_DIR"/*/terragrunt.hcl; do
55
+ [[ -f "$tg" ]] || continue
56
+ comp="$(basename "$(dirname "$tg")")"
57
+ CHECKED=$((CHECKED + 1))
58
+
59
+ if ! grep -q 'find_in_parent_folders("project.hcl")' "$tg"; then
60
+ FAILURES+=("$comp: no encontré find_in_parent_folders(\"project.hcl\") — no hereda project_id de la raíz")
61
+ continue
62
+ fi
63
+
64
+ # No todos los componentes usan una clave llamada exactamente
65
+ # "project_id" en inputs (org_policies usa `parent = "projects/${local.
66
+ # project_id}"`, storage_assets/storage_docs usan `project =
67
+ # local.project_id`). Lo que de verdad importa es que, en algún lado del
68
+ # archivo, se USE la referencia corta `local.project_id` — la línea que
69
+ # la DEFINE ("local.project_vars.locals.project_id") no cuenta como uso,
70
+ # porque ese substring exacto no aparece ahí (locals. != local.).
71
+ refs="$(grep -c 'local\.project_id' "$tg" || true)"
72
+ if [[ "$refs" -eq 0 ]]; then
73
+ FAILURES+=("$comp: nunca referencia local.project_id en el archivo — revisar cómo usa el project id")
74
+ fi
75
+ done
76
+
77
+ # --- 3. nada de live/<NEW_ENV>/ menciona ya al entorno fuente --------------
78
+ if [[ -n "$SOURCE_ENV" ]]; then
79
+ # Se ignoran líneas de comentario (# ...): este skill deja a propósito
80
+ # una nota en project_iam mencionando a SOURCE_ENV por nombre (guía
81
+ # §3.12) — eso no es una sustitución incompleta, es documentación. Un
82
+ # leftover real siempre está en una línea de código (un valor, un
83
+ # nombre), nunca solo en un comentario.
84
+ #
85
+ # Se revisa CADA archivo de texto bajo live/<NEW_ENV>/ (no solo
86
+ # terragrunt.hcl/project.hcl/README.md) — Review V2 (N-3) encontró que
87
+ # una lista fija de nombres de archivo deja fuera Makefile/.gitignore
88
+ # de cada componente, y cualquier archivo nuevo que un componente
89
+ # agregue en el futuro, sin que nadie lo note.
90
+ while IFS= read -r -d '' tg_file; do
91
+ if grep -v '^[[:space:]]*#' "$tg_file" 2>/dev/null | grep -q "$SOURCE_ENV"; then
92
+ FAILURES+=("$tg_file: todavía contiene \"$SOURCE_ENV\" fuera de un comentario (sustitución incompleta)")
93
+ fi
94
+ done < <(find "$NEW_DIR" -maxdepth 2 -type f -print0)
95
+ fi
96
+
97
+ if [[ "${#FAILURES[@]}" -eq 0 ]]; then
98
+ echo "PROJECT_PINNING_OK: $CHECKED componentes verificados"
99
+ exit 0
100
+ fi
101
+
102
+ echo "Problemas encontrados:"
103
+ printf ' - %s\n' "${FAILURES[@]}"
104
+ echo "PROJECT_PINNING_FAILED: ${#FAILURES[@]} problema(s) (ver detalle arriba)"
105
+ exit 1
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env bash
2
+ # Etapa: Validación — script 3.
3
+ # Busca, en TODO archivo de texto de live/<NEW_ENV>/, el nombre corto de
4
+ # la app de SOURCE_ENV (sin el sufijo de entorno -qa/-prod/-dev/etc.),
5
+ # en CUALQUIER capitalización. Complementa a 21_validate_project_pinning.sh
6
+ # (que solo busca el token completo "<app>-<entorno>", exacto): un nombre
7
+ # de marca estilizado como "XoloShop" (con una S interna mayúscula) no es
8
+ # "xoloshop-qa" ni "Xoloshop-QA" como substring, así que 21 nunca lo
9
+ # atrapa — y la sustitución de ksc_copy_component_files, si tiene un bug,
10
+ # tampoco. Caso real: service_accounts generado desde xoloshop-qa dejó
11
+ # "XoloShop" sin tocar en dos display_name/description, porque la
12
+ # sustitución de entonces solo cubría "xoloshop" y "Xoloshop" exactos.
13
+ #
14
+ # Uso: 22_validate_no_app_name_leftover.sh <NEW_ENV>
15
+ #
16
+ # Termina con exactamente uno de estos mensajes:
17
+ # "APP_NAME_LEFTOVER_OK: sin referencias a '<APP_SOURCE>'" (exit 0)
18
+ # "APP_NAME_LEFTOVER_FOUND: <n> archivo(s) (ver detalle arriba)" (exit 1)
19
+
20
+ set -uo pipefail
21
+
22
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
23
+ # shellcheck source=lib/common.sh
24
+ source "$SCRIPT_DIR/lib/common.sh"
25
+
26
+ NEW_ENV="${1:-}"
27
+ [[ -n "$NEW_ENV" ]] || ksc_die "uso: 22_validate_no_app_name_leftover.sh <NEW_ENV>"
28
+
29
+ REPO_ROOT="$(ksc_repo_root)"
30
+ NEW_DIR="$REPO_ROOT/live/$NEW_ENV"
31
+ [[ -d "$NEW_DIR" ]] || ksc_die "no existe $NEW_DIR"
32
+
33
+ CONFIG_FILE="$(ksc_config_path "$REPO_ROOT" "$NEW_ENV")"
34
+ SOURCE_ENV=""
35
+ [[ -f "$CONFIG_FILE" ]] && SOURCE_ENV="$(ksc_hcl_get "$CONFIG_FILE" SOURCE_ENV 2>/dev/null || true)"
36
+ [[ -n "$SOURCE_ENV" ]] || SOURCE_ENV="$(grep -m1 '^SOURCE_ENV=' "$CONFIG_FILE" 2>/dev/null | sed -E 's/^SOURCE_ENV="(.*)"$/\1/')"
37
+ [[ -n "$SOURCE_ENV" ]] || ksc_die "no pude determinar SOURCE_ENV (no está en $CONFIG_FILE) — no se puede validar sin saber qué nombre de app buscar"
38
+
39
+ read -r APP_SOURCE _ < <(ksc_split_env "$SOURCE_ENV")
40
+
41
+ FAILURES=()
42
+
43
+ # Mismo criterio que 21 (comentarios excluidos: la NOTA de project_iam
44
+ # menciona SOURCE_ENV completo a propósito, lo que incluye APP_SOURCE
45
+ # como substring) y misma cobertura de archivos (find, no una lista fija
46
+ # de nombres — Review V2, N-3).
47
+ while IFS= read -r -d '' file; do
48
+ hit="$(grep -v '^[[:space:]]*#' "$file" 2>/dev/null | grep -i -m1 -- "$APP_SOURCE" | sed -E 's/^[[:space:]]+//')"
49
+ if [[ -n "$hit" ]]; then
50
+ FAILURES+=("$file: \"$hit\"")
51
+ fi
52
+ done < <(find "$NEW_DIR" -maxdepth 2 -type f -print0)
53
+
54
+ if [[ "${#FAILURES[@]}" -eq 0 ]]; then
55
+ echo "APP_NAME_LEFTOVER_OK: sin referencias a '$APP_SOURCE' (ninguna capitalización) en $NEW_DIR"
56
+ exit 0
57
+ fi
58
+
59
+ echo "Encontrado el nombre de la app fuente ('$APP_SOURCE', cualquier capitalización) fuera de comentarios:"
60
+ printf ' - %s\n' "${FAILURES[@]}"
61
+ echo "APP_NAME_LEFTOVER_FOUND: ${#FAILURES[@]} archivo(s) (ver detalle arriba) — corrige el shell script que genera ese componente para que sustituya '$APP_SOURCE' por el nombre de la app nueva, en cualquier capitalización (ver ksc_substr_replace_app en lib/common.sh)."
62
+ exit 1