Compare commits

..
16 Commits
Author SHA1 Message Date
gitea-actions 55fbf3524b chore(gitops): deploy Medusa v1.0.295 [skip ci] 2026-09-28 01:29:53 +00:00
devops 17dc9a5133 Merge branch 'ci/trivy-backend-timeout'
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 37s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 17m6s
2026-09-28 01:12:17 +00:00
devopsandClaude Opus 5.5 ba96a50a42 ci(medusa): timeout de Trivy CRITICAL 15m -> 30m (análisis de capas ~14 min)
Medido en vivo (run 296): en la imagen del backend el análisis de capas
toma ~14 min en el runner del NAS (descarga de DB 8 s, detección 9 s); con
15m hizo timeout una vez (run 294). No era el secret-scan. Solo este paso:
el HIGH reusa el análisis cacheado (~2 s) y frontend/docs tardan ~2 min.
No cambia qué se revisa ni que CRITICAL bloquea.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018r19s4H8MBGegqToqw5guP
2026-09-28 01:12:16 +00:00
gitea-actions 91335ce023 chore(gitops): deploy Docs Portal v1.0.294 [skip ci] 2026-09-28 00:42:39 +00:00
devops 43c47d99fb chore: promote v1.0.293 to production [skip ci] 2026-09-28 00:34:16 +00:00
devops 4baabf36ce chore: release v1.0.293 [skip ci] 2026-09-28 00:34:14 +00:00
gitea-actions 3cc0a7c861 chore(gitops): deploy Medusa v1.0.292 [skip ci] 2026-09-28 00:20:14 +00:00
devops a3e9580348 Merge branch 'ci/trivy-image-scanners-vuln'
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 43s
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 33s
Build and Push Docs Portal / Escaneo de Secretos (Gitleaks) (push) Successful in 31s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 40m7s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 13m58s
Build and Push Docs Portal / Construir y publicar Docs Portal (push) Successful in 8m35s
2026-09-27 23:38:15 +00:00
devopsandClaude Opus 5.5 aaf6e14742 ci: Trivy image solo con --scanners vuln (evita timeouts de 15m)
El escaneo de secretos que Trivy hace por defecto sobre toda la imagen
(node_modules incluido) hizo timeout (context deadline exceeded, 15m) en
el gate CRITICAL del backend el 2026-09-27; el propio log de Trivy
recomienda --scanners vuln. Aplicado a los 6 pasos trivy image (CRITICAL
bloqueante y HIGH informativo — un FATAL por timeout tumba el job aunque
--exit-code sea 0) de build.yaml, build-medusa.yaml y deploy-docs.yaml.

Sin pérdida real de cobertura (auditado por devsecops-auditor): Gitleaks
ya escanea todo el árbol de cada workload antes del build (needs:
gitleaks), ningún build recibe --build-arg/--secret con credenciales, los
ENV build-only del backend no llegan al stage final, y 11 corridas
recientes de image secret-scan tuvieron 0 hallazgos. Hueco residual
aceptado: secretos en capas de imágenes base oficiales.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018r19s4H8MBGegqToqw5guP
2026-09-27 23:38:14 +00:00
gitea-actions c23803656e chore(gitops): deploy Medusa v1.0.290 [skip ci] 2026-09-27 21:59:56 +00:00
devops e86a0ebc96 chore: promote v1.0.291 to production [skip ci] 2026-09-27 15:13:40 +00:00
devops b02a5e8b5f chore: release v1.0.291 [skip ci] 2026-09-27 15:13:38 +00:00
devops ca10ef6e9a Merge branch 'fix/categorias-sin-tildes-match'
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 27s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 15m24s
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 37s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 19m58s
2026-09-27 14:29:53 +00:00
devopsandClaude Opus 5.5 f6918b9eab fix: categorías con tildes sin duplicados en el importador ni links rotos
Preparación para renombrar las categorías reales con tildes/eñes
("Figuras de acción", "Muñecas y peluches", etc.):
- Importador CSV (admin): categorías y colecciones se matchean ignorando
  tildes/eñes, para que un CSV escrito sin tildes reuse la categoría
  existente en vez de crear un duplicado. Títulos de producto sin cambios.
- Catálogo: ?category= se resuelve contra los nombres reales ignorando
  tildes/mayúsculas, así los links viejos siguen funcionando.
- Plantilla CSV de ejemplo con "Figuras de acción".

Aprobado por devsecops-auditor (sin colisiones con los nombres actuales,
sin riesgo de inyección/XSS). CI guard local OK, tsc backend OK, build de
producción del storefront OK.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_018r19s4H8MBGegqToqw5guP
2026-09-27 14:29:52 +00:00
devops 8e4f3515fe chore: promote v1.0.289 to production [skip ci] 2026-09-27 13:58:23 +00:00
devops e7d7fcdb00 chore: release v1.0.289 [skip ci] 2026-09-27 13:58:21 +00:00
9 changed files with 45 additions and 16 deletions

No files matched your search

+8 -1
View File
@@ -234,11 +234,17 @@ jobs:
shell: bash
run: |
set -euo pipefail
# --timeout 30m (no 15m): medido en vivo 2026-09-27, el analisis de
# capas de esta imagen (node_modules de Medusa) toma ~14 min en
# el runner del NAS -- con 15m hizo timeout una vez. El paso HIGH
# de abajo reusa ese analisis cacheado (~2 s), por eso no lo
# necesita. No cambia que revisa ni que bloquea.
/tmp/trivy image \
--scanners vuln \
--severity CRITICAL \
--exit-code 1 \
--ignore-unfixed \
--timeout 15m0s \
--timeout 30m0s \
--ignorefile "${APP_DIR}/.trivyignore" \
"${IMAGE_NAME}:${{ steps.vars.outputs.VERSION }}"
@@ -248,6 +254,7 @@ jobs:
run: |
set -euo pipefail
/tmp/trivy image \
--scanners vuln \
--severity HIGH \
--exit-code 0 \
--ignore-unfixed \
+2
View File
@@ -429,6 +429,7 @@ jobs:
run: |
set -euo pipefail
/tmp/trivy image \
--scanners vuln \
--severity CRITICAL \
--exit-code 1 \
--ignore-unfixed \
@@ -442,6 +443,7 @@ jobs:
run: |
set -euo pipefail
/tmp/trivy image \
--scanners vuln \
--severity HIGH \
--exit-code 0 \
--ignore-unfixed \
+2
View File
@@ -231,6 +231,7 @@ jobs:
run: |
set -euo pipefail
/tmp/trivy image \
--scanners vuln \
--severity CRITICAL \
--exit-code 1 \
--ignore-unfixed \
@@ -243,6 +244,7 @@ jobs:
run: |
set -euo pipefail
/tmp/trivy image \
--scanners vuln \
--severity HIGH \
--exit-code 0 \
--ignore-unfixed \
@@ -115,6 +115,15 @@ function normalizeTitleForMatch(title: string): string {
.toLowerCase();
}
// Categorias/colecciones: ademas de lo anterior, ignora tildes y eñes
// ("Figuras de accion" == "Figuras de acción"). Desde 2026-09-27 los
// nombres reales en Medusa llevan tildes; sin esto, un CSV escrito sin
// tildes (o viejo) crearia una categoria DUPLICADA en vez de reusar la
// existente. Los titulos de producto siguen con normalizeTitleForMatch.
function normalizeNameForMatch(name: string): string {
return normalizeTitleForMatch(name).normalize("NFD").replace(/[\u0300-\u036f]/g, "");
}
function slugify(title: string, uniquePart: string): string {
const base = title
.normalize("NFD")
@@ -166,7 +175,7 @@ export async function GET(req: MedusaRequest, res: MedusaResponse) {
// ofrece descargar y lo que realmente se procesa.
const header = "titulo,descripcion,precio,categoria,coleccion,cantidad,fotos";
const example =
'"Muñeco Buzz Lightyear","Figura articulada de 30cm, edición coleccionista.",89900,"Figuras de accion","Toy Story",3,"https://ejemplo.com/foto1.jpg;https://ejemplo.com/foto2.jpg"';
'"Muñeco Buzz Lightyear","Figura articulada de 30cm, edición coleccionista.",89900,"Figuras de acción","Toy Story",3,"https://ejemplo.com/foto1.jpg;https://ejemplo.com/foto2.jpg"';
const csv = `${header}\n${example}\n`;
res.setHeader("Content-Type", "text/csv; charset=utf-8");
res.setHeader("Content-Disposition", 'attachment; filename="plantilla-importacion.csv"');
@@ -217,10 +226,10 @@ export async function POST(req: MedusaRequest<{ csv: string }>, res: MedusaRespo
}
const categoryByName = new Map(
categories.filter((c) => c.name).map((c) => [normalizeTitleForMatch(c.name), c.id]),
categories.filter((c) => c.name).map((c) => [normalizeNameForMatch(c.name), c.id]),
);
const collectionByName = new Map(
collections.filter((c) => c.title).map((c) => [normalizeTitleForMatch(c.title), c.id]),
collections.filter((c) => c.title).map((c) => [normalizeNameForMatch(c.title), c.id]),
);
const productByTitle = new Map(
existingProducts.filter((p) => p.title).map((p) => [normalizeTitleForMatch(p.title), p]),
@@ -289,7 +298,7 @@ export async function POST(req: MedusaRequest<{ csv: string }>, res: MedusaRespo
if (!inventoryItemId) throw new Error("No se pudo crear el registro de inventario");
const categoryName = row.categoria?.trim();
let categoryId = categoryName ? categoryByName.get(normalizeTitleForMatch(categoryName)) : undefined;
let categoryId = categoryName ? categoryByName.get(normalizeNameForMatch(categoryName)) : undefined;
if (categoryName && !categoryId) {
const { result: createdCategories } = await createProductCategoriesWorkflow(req.scope).run({
input: {
@@ -299,11 +308,11 @@ export async function POST(req: MedusaRequest<{ csv: string }>, res: MedusaRespo
},
});
categoryId = createdCategories[0].id;
categoryByName.set(normalizeTitleForMatch(categoryName), categoryId);
categoryByName.set(normalizeNameForMatch(categoryName), categoryId);
}
const collectionName = row.coleccion?.trim();
let collectionId = collectionName ? collectionByName.get(normalizeTitleForMatch(collectionName)) : undefined;
let collectionId = collectionName ? collectionByName.get(normalizeNameForMatch(collectionName)) : undefined;
if (collectionName && !collectionId) {
const { result: createdCollections } = await createCollectionsWorkflow(req.scope).run({
input: {
@@ -313,7 +322,7 @@ export async function POST(req: MedusaRequest<{ csv: string }>, res: MedusaRespo
},
});
collectionId = createdCollections[0].id;
collectionByName.set(normalizeTitleForMatch(collectionName), collectionId);
collectionByName.set(normalizeNameForMatch(collectionName), collectionId);
}
await createProductsWorkflow(req.scope).run({
@@ -25,7 +25,7 @@ spec:
runAsNonRoot: false
containers:
- name: app
image: gitea.cruzcloud.net/devops/docs-portal:v1.0.283
image: gitea.cruzcloud.net/devops/docs-portal:v1.0.294
# El base saca TODAS las capabilities. Probado en vivo y
# revertido: con drop: ALL (aunque se agregue NET_BIND_SERVICE
# de vuelta) el propio entrypoint de nginx:1.27-alpine falla al
@@ -26,11 +26,11 @@ spec:
runAsUser: 1001
containers:
- name: app
image: gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.286
image: gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.293
env:
# Ver comentario en workloads/ecommerce/frontend/patches/deployment.yaml
- name: APP_VERSION
value: v1.0.286
value: v1.0.293
- name: HEADLESS_PROVIDER
value: medusa
# Backend COMPARTIDO con Producción a propósito (decisión del
+10 -1
View File
@@ -11,6 +11,13 @@ type CatalogPageProps = {
searchParams: Promise<Record<string, string | string[] | undefined>>;
};
// Sin tildes/eñes ni mayusculas: los links viejos (o escritos a mano)
// como ?category=Munecas y peluches siguen llevando a la categoria real
// "Muñecas y peluches" (renombrada con tildes el 2026-09-27).
function normalizeName(value: string): string {
return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").trim().toLowerCase();
}
function single(value: string | string[] | undefined): string {
return Array.isArray(value) ? value[0] ?? "" : value ?? "";
}
@@ -19,7 +26,9 @@ export default async function CatalogPage({ searchParams }: CatalogPageProps) {
const params = await searchParams;
const [products, categories] = await Promise.all([getProducts(), getCategories()]);
const category = single(params.category) || "Todos";
const requestedCategory = single(params.category) || "Todos";
const category =
categories.find((node) => normalizeName(node.name) === normalizeName(requestedCategory))?.name ?? requestedCategory;
const collection = single(params.collection);
const query = single(params.q);
const taxonomy = {
@@ -65,7 +65,7 @@ spec:
memory: 64Mi
- name: migrations
image: gitea.cruzcloud.net/devops/ecommerce-medusa:v1.0.287
image: gitea.cruzcloud.net/devops/ecommerce-medusa:v1.0.295
imagePullPolicy: IfNotPresent
command:
- node
@@ -86,7 +86,7 @@ spec:
containers:
- name: app
image: gitea.cruzcloud.net/devops/ecommerce-medusa:v1.0.287
image: gitea.cruzcloud.net/devops/ecommerce-medusa:v1.0.295
imagePullPolicy: IfNotPresent
envFrom:
- configMapRef:
@@ -25,14 +25,14 @@ spec:
runAsUser: 1001
containers:
- name: app
image: gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.286
image: gitea.cruzcloud.net/devops/ecommerce-frontend:v1.0.293
env:
# La actualiza el mismo paso del CD (.gitea/workflows/build.yaml)
# que bumpea el tag de la imagen -- el footer la lee
# (process.env.APP_VERSION) para mostrar la versión real
# desplegada en vez de un "v4.1" fijo.
- name: APP_VERSION
value: v1.0.286
value: v1.0.293
- name: HEADLESS_PROVIDER
value: medusa
- name: MEDUSA_BACKEND_URL