Scanverra
CI/CD Integration

Guías

Integración CI/CD

Todos los endpoints de análisis aceptan una clave de API, por lo que cualquiera de ellos puede ejecutarse como un paso del pipeline. Esta página explica qué significa la salida de cada herramienta, cómo convertirla en un gate de aprobado/rechazado, y ofrece ejemplos funcionales para cuatro plataformas de CI.

Base de puntuación por herramienta

Qué devuelve cada endpoint y sobre qué establecer el umbral.

HerramientaSalidaBaseGate integrado
Auditoría del sitio web4 puntuaciones 0-100: performance, seo, accessibility, bestPracticesPuntuaciones brutas de Lighthouse. Convención: ≥90 bueno, 50-89 mejorable, <50 deficiente.No integrado — elige tu propio umbral por puntuación.
Análisis de seguridadriskScore 0-100 (más alto = más seguro)100 menos descuentos ponderados por gravedad, con tope por categoría. Bandas de calificación: A+ ≥90 … F <30.No integrado — elige tu propio umbral.
Prueba de navegadorArrays: jsErrors, brokenLinks, formIssues, imgIssues (cada uno con severity: "error" | "warning")Sin puntuación agregada.Condiciona según el número de problemas, por ejemplo cualquier severity === "error".
Escáner de repositoriosscore 0-100 + qualityGate: "passed" | "failed"100 menos descuentos ponderados por gravedad, con tope por categoría.Integrado — falla automáticamente ante cualquier hallazgo crítico o score < 60.

Detener el pipeline

La mecánica de CI es la misma independientemente de la plataforma: un paso que termina con un código distinto de cero hace fallar el job. Para bloquear de verdad que un PR o merge request se fusione, añade ese job como comprobación de estado obligatoria en la protección de ramas o en la configuración de aprobación de merge requests de tu proveedor de repositorios — un paso fallido por sí solo solo se muestra en rojo, no impide el merge por sí mismo.

Pipelines de ejemplo

Las mismas cuatro comprobaciones — Audit, Security Scan, Browser Test, Repo Scan — escritas para cuatro plataformas. Elige tu sistema de CI abajo.

name: Scanverra checks
on: [pull_request]

jobs:
  scanverra:
    runs-on: ubuntu-latest
    env:
      API_KEY: ${{ secrets.SCANVERRA_API_KEY }}
      TARGET_URL: https://staging.example.com   # your deployed preview URL
    steps:
      - name: Website Audit (perf/SEO/a11y)
        run: |
          RES=$(curl -sf -X POST https://www.scanverra.com/api/audit \
            -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
            -d "{\"url\":\"$TARGET_URL\"}")
          echo "$RES" | jq .
          PERF=$(echo "$RES" | jq '.scores.performance')
          A11Y=$(echo "$RES" | jq '.scores.accessibility')
          if (( $(echo "$PERF < 50" | bc -l) )) || (( $(echo "$A11Y < 90" | bc -l) )); then
            echo "::error::Audit failed thresholds (perf=$PERF, a11y=$A11Y)"
            exit 1
          fi

      - name: Security Scan
        run: |
          RES=$(curl -sf -X POST https://www.scanverra.com/api/security-scan \
            -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
            -d "{\"url\":\"$TARGET_URL\"}")
          RISK=$(echo "$RES" | jq '.riskScore')
          echo "riskScore=$RISK"
          [ "$RISK" -lt 70 ] && { echo "::error::Security risk score too low ($RISK)"; exit 1; }
          true

      - name: Browser Test (JS errors, broken links)
        run: |
          RES=$(curl -sf -X POST https://www.scanverra.com/api/browser-test \
            -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
            -d "{\"url\":\"$TARGET_URL\"}")
          ERRORS=$(echo "$RES" | jq '[.jsErrors[]? | select(.severity=="error")] | length')
          [ "$ERRORS" -gt 0 ] && { echo "::error::$ERRORS JS errors found"; exit 1; }
          true

      - name: Repo Scan (SAST, secrets, deps, quality gate)
        run: |
          SCAN_ID=$(curl -sf -X POST https://www.scanverra.com/api/repo/scan \
            -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
            -d '{"owner":"your-org","repo":"your-repo","branch":"${{ github.head_ref }}"}' | jq -r .scanId)

          for i in $(seq 1 30); do
            RESULT=$(curl -sf "https://www.scanverra.com/api/repo/result?id=$SCAN_ID" -H "X-API-Key: $API_KEY")
            STATUS=$(echo "$RESULT" | jq -r .status)
            [ "$STATUS" != "running" ] && break
            sleep 10
          done

          echo "$RESULT" | jq '{score, qualityGate}'
          GATE=$(echo "$RESULT" | jq -r .qualityGate)
          [ "$GATE" = "failed" ] && { echo "::error::Repo quality gate failed"; exit 1; }
          true

Dónde guardar la clave de API como secreto, según la plataforma:

  • GitHub Actions: secreto del repositorio — Settings → Secrets and variables → Actions.
  • GitLab CI: variable de CI/CD enmascarada — Settings → CI/CD → Variables.
  • Azure Pipelines: variable de pipeline secreta (icono de candado) o un Variable Group en Pipelines → Library.
  • Jenkins: credencial de texto secreto — Manage Jenkins → Credentials — referenciada mediante credentials(). La imagen del agente también necesita curl, jq y bc instalados; los runners ubuntu-latest alojados en GitHub y Azure ya los incluyen, la imagen alpine de GitLab no (de ahí el paso apk add).

El paso del escáner de repositorios necesita tu cuenta de GitHub/Bitbucket/Azure conectada previamente en la configuración de Scanverra — el análisis se ejecuta con el token guardado ahí, no con uno enviado por solicitud.

Nota sobre la cuota: una clave de API del plan Free tiene la misma limitación de cuota que una cuenta web gratuita — las ejecuciones de CI siguen contando para tu límite mensual de análisis y pueden agotarlo rápido si analizas en cada PR. Las claves de API de los planes Pro, Team y Enterprise no tienen medición. Consulta Límites y comportamiento.

Solo el escáner de repositorios devuelve un campo qualityGate listo para usar. Para las otras tres herramientas, decide tus propios umbrales de antemano y mantenlos consistentes entre entornos (por ejemplo, no compares la puntuación de seguridad de una URL de staging con un umbral ajustado para producción).