CI/CD Integration
Anleitungen
CI/CD-Integration
Jeder Scanner-Endpunkt akzeptiert einen API-Schlüssel, sodass jeder davon als Pipeline-Schritt laufen kann. Diese Seite erklärt, was die Ausgabe jedes Tools bedeutet, wie Sie daraus ein Pass/Fail-Gate bauen, und liefert funktionierende Beispiele für vier CI-Plattformen.
Code-Scanning mit der GitHub Action
Der schnellste Weg, Code in der CI zu scannen. Die Action führt @scanverra/cli auf dem Runner aus (Ihr Code verlässt ihn nie), lässt den Job ab dem gewählten Schweregrad fehlschlagen und lädt SARIF in GitHub Code Scanning hoch.
on: [push, pull_request]
jobs:
scanverra:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- uses: scanverra/scan-action@v1
with:
api-key: ${{ secrets.SCANVERRA_API_KEY }}
fail-on: highBewertungsgrundlage pro Tool
Was jeder Endpunkt zurückgibt und worauf Sie einen Schwellenwert setzen sollten.
| Tool | Ausgabe | Grundlage | Eingebautes Gate |
|---|---|---|---|
| Website-Audit | 4 Scores 0-100: performance, seo, accessibility, bestPractices | Kategoriewerte von 0-100. Konvention: ≥90 gut, 50-89 verbesserungswürdig, <50 schlecht. | Kein eingebautes Gate — wählen Sie Ihren eigenen Schwellenwert pro Score. |
| Sicherheits-Scan | riskScore 0-100 (höher = sicherer) | 100 minus schweregradgewichtete, pro Kategorie gedeckelte Abzüge. Notenbänder: A+ ≥90 … F <30. | Kein eingebautes Gate — wählen Sie Ihren eigenen Schwellenwert. |
| Browser-Audit | Arrays: jsErrors, brokenLinks, formIssues, imgIssues (jeweils severity: "error" | "warning") | Kein Gesamt-Score. | Absicherung anhand der Problemanzahl, z. B. jede severity === "error". |
| Repo-Scanner | score 0-100 + qualityGate: "passed" | "failed" | 100 minus schweregradgewichtete Abzüge, pro Kategorie gedeckelt. | Eingebaut — schlägt automatisch bei jedem kritischen Fund oder score < 60 fehl. |
| SEO-Optimierer | score 0-100 (On-Page-SEO + GEO/E-E-A-T-Signale) | 100 minus schweregradgewichtete, pro Kategorie gedeckelte Abzüge über On-Page-, GEO- und E-E-A-T-Befunde. | Nicht eingebaut — eigenen Schwellenwert festlegen. |
Die Pipeline stoppen
Die CI-Mechanik ist plattformunabhängig gleich: Ein Schritt, der mit einem Nicht-Null-Code beendet wird, lässt den Job fehlschlagen. Um einen PR oder Merge Request tatsächlich am Mergen zu hindern, fügen Sie diesen Job als erforderlichen Status-Check im Branch-Schutz oder in den Merge-Request-Genehmigungseinstellungen Ihres Repo-Hosts hinzu — ein fehlgeschlagener Schritt zeigt allein nur Rot an, verhindert aber nicht selbst ein Merge.
Beispiel-Pipelines
Dieselben fünf Prüfungen — Audit, Security Scan, Browser Audit, Repo Scan, SEO-Optimierer — für vier Plattformen. Wählen Sie unten Ihr CI-System.
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 '.performanceScore')
A11Y=$(echo "$RES" | jq '.accessibilityScore')
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: |
SCAN_ID=$(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\"}" | jq -r .scanId)
for i in $(seq 1 30); do
RESULT=$(curl -sf "https://www.scanverra.com/api/security-scan?id=$SCAN_ID" -H "X-API-Key: $API_KEY")
STATUS=$(echo "$RESULT" | jq -r .status)
[ "$STATUS" != "running" ] && break
sleep 10
done
RISK=$(echo "$RESULT" | jq '.riskScore')
echo "riskScore=$RISK"
[ "$STATUS" = "failed" ] && { echo "::error::Security scan failed to complete"; exit 1; }
[ "$RISK" -lt 70 ] && { echo "::error::Security risk score too low ($RISK)"; exit 1; }
true
- name: Browser Audit (JS errors, broken links)
run: |
TEST_ID=$(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\"}" | jq -r .testId)
for i in $(seq 1 30); do
RESULT=$(curl -sf "https://www.scanverra.com/api/browser-test?id=$TEST_ID" -H "X-API-Key: $API_KEY")
STATUS=$(echo "$RESULT" | jq -r .status)
[ "$STATUS" != "running" ] && break
sleep 10
done
ERRORS=$(echo "$RESULT" | jq '[.jsErrors[]? | select(.severity=="error")] | length')
[ "$STATUS" = "failed" ] && { echo "::error::Browser audit failed to complete"; exit 1; }
[ "$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
- name: SEO Optimizer (on-page, GEO, E-E-A-T)
run: |
SCAN_ID=$(curl -sf -X POST https://www.scanverra.com/api/seo-optimizer \
-H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
-d "{\"url\":\"$TARGET_URL\"}" | jq -r .scanId)
for i in $(seq 1 30); do
RESULT=$(curl -sf "https://www.scanverra.com/api/seo-optimizer?id=$SCAN_ID" -H "X-API-Key: $API_KEY")
STATUS=$(echo "$RESULT" | jq -r .status)
[ "$STATUS" != "running" ] && break
sleep 10
done
SCORE=$(echo "$RESULT" | jq '.score')
echo "seoScore=$SCORE"
[ "$STATUS" = "failed" ] && { echo "::error::SEO scan failed to complete"; exit 1; }
[ "$SCORE" -lt 70 ] && { echo "::error::SEO score too low ($SCORE)"; exit 1; }
trueWo der API-Schlüssel als Secret gespeichert wird, je Plattform:
- GitHub Actions: Repo-Secret — Settings → Secrets and variables → Actions.
- GitLab CI: maskierte CI/CD-Variable — Settings → CI/CD → Variables.
- Azure Pipelines: geheime Pipeline-Variable (Schloss-Symbol) oder eine Variable Group unter Pipelines → Library.
- Bitbucket Pipelines: Repository-Einstellungen > Pipelines > Repository-Variablen, als gesichert markiert.
- Jenkins: Secret-Text-Credential — Manage Jenkins → Credentials — referenziert über
credentials(). Das Agent-Image benötigt außerdemcurl,jqundbc; die GitHub- und Azure-gehostetenubuntu-latest-Runner enthalten diese bereits, dasalpine-Image von GitLab nicht (daher derapk add-Schritt).
Der Repo-Scanner-Schritt benötigt vorab ein in den Scanverra-Einstellungen verbundenes GitHub-/Bitbucket-/Azure-Konto — der Scan läuft über das dort gespeicherte Token, nicht über eines, das pro Anfrage übergeben wird.
SARIF-Ausgabe für Code-Scanning
SARIF (Static Analysis Results Interchange Format) ist das Standard-JSON-Format, mit dem Code-Scanning-Tools Befunde austauschen. Die Scanverra-CLI schreibt mit --sarif SARIF 2.1.0, sodass Ergebnisse überall erscheinen, wo SARIF gelesen wird.
- GitHub Code Scanning: Setzen Sie sarif: true in scanverra/scan-action, dann erscheinen Befunde im Security-Tab und als Pull-Request-Anmerkungen.
- SonarQube und andere Plattformen mit SARIF-Import können dieselbe Datei einlesen.
- Bitbucket und GitLab: Bewahren Sie die SARIF-Datei als Pipeline-Artefakt auf oder nutzen Sie --json für einen eigenen Report-Schritt.
- uses: actions/checkout@v4
- uses: scanverra/scan-action@v1
with:
api-key: ${{ secrets.SCANVERRA_API_KEY }}
sarif: true # uploads the report to GitHub code scanning
# The job needs: permissions: { security-events: write }Nur der Repo-Scanner liefert ein fertiges qualityGate-Feld. Für die anderen vier Tools legen Sie eigene Schwellenwerte im Voraus fest und halten diese über alle Umgebungen hinweg konsistent (vergleichen Sie z. B. nicht den Sicherheits-Score einer Staging-URL mit einem für die Produktion abgestimmten Schwellenwert).