From e3ab3f7fc0182dfaf70927782902a2ef940322da Mon Sep 17 00:00:00 2001 From: Cristian Felipe Cruz Buitron Date: Fri, 14 Aug 2026 23:50:23 -0500 Subject: [PATCH] fix(ci): correr Semgrep nativo (venv) en vez de docker run anidado MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El runner de Gitea ejecuta cada job dentro de un contenedor propio que habla con el daemon Docker del host (sibling containers) -- un `docker run -v "\${{ github.workspace }}:/src"` desde ahí intenta montar una ruta que solo existe DENTRO del contenedor del job, no en el host real: "mkdir /workspace: read-only file system". Confirmado en el run real (job 128, task_id 128) tras el fix del anchor. Se valida localmente contra docker.gitea.com/runner-images:ubuntu-latest (la misma imagen del runner real) que python3/pip3 están disponibles. pip3 install directo falla por paquetes de apt sin metadata compatible (PyJWT, "RECORD file not found") -- se usa un venv aislado en su lugar, validado end-to-end con los dos steps extraídos del YAML real. --- .gitea/workflows/build.yaml | 49 +++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 9bc5da1..5df8647 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -285,6 +285,27 @@ jobs: --exit-code 0 \ "${MANIFEST_FILE}" + # Instalado directo con pip (no como container aparte): el runner de + # Gitea ejecuta cada job ya dentro de un contenedor propio que habla + # con el daemon Docker del host (sibling containers) -- un + # `docker run -v "${{ github.workspace }}:/src"` desde acá intenta + # montar una ruta que solo existe DENTRO del contenedor del job, no + # en el host real, y falla con "read-only file system". Evitamos por + # completo el problema corriendo Semgrep nativo, igual que + # gitleaks/trivy/syft/cosign. + # venv en vez de "pip3 install --break-system-packages": la imagen del + # runner ya trae paquetes de Python instalados por apt (ej. PyJWT) + # sin metadata compatible con pip, y pip aborta al intentar + # reemplazarlos ("RECORD file not found"). Un venv aislado evita + # tocar los paquetes del sistema por completo. + - name: Instalar Semgrep + shell: bash + run: | + set -euo pipefail + python3 -m venv /tmp/semgrep-venv + /tmp/semgrep-venv/bin/pip install --quiet "semgrep==1.173.0" + /tmp/semgrep-venv/bin/semgrep --version + # Modo auditoría: sin --error a propósito, Semgrep siempre termina # con exit 0 aunque reporte hallazgos. Es la primera vuelta — se # revisan los resultados en conjunto antes de decidir qué reglas @@ -293,27 +314,17 @@ jobs: shell: bash run: | set -euo pipefail - SEMGREP_IMAGE="semgrep/semgrep:1.173.0" - - docker run --rm \ - -v "${{ github.workspace }}:/src" \ - -w /src \ - "${SEMGREP_IMAGE}" \ - semgrep scan \ - --config=p/typescript \ - --config=p/react \ - --config=p/nextjs \ - --config=p/security-audit \ - --json \ - --output=semgrep-report.json \ - "${APP_DIR}" + /tmp/semgrep-venv/bin/semgrep scan \ + --config=p/typescript \ + --config=p/react \ + --config=p/nextjs \ + --config=p/security-audit \ + --json \ + --output=semgrep-report.json \ + "${APP_DIR}" echo "=== Resumen Semgrep ===" - docker run --rm \ - -v "${{ github.workspace }}:/src" \ - -w /src \ - "${SEMGREP_IMAGE}" \ - python3 -c " + /tmp/semgrep-venv/bin/python -c " import json data = json.load(open('semgrep-report.json')) results = data.get('results', []) -- 2.54.0