ATC Automatisierung auf BTP: Code-Qualität kontinuierlich überwachen

Kategorie
BTP
Veröffentlicht
Autor
Johannes

Automatisierte ATC-Prüfungen sind unverzichtbar für kontinuierliche Code-Qualität in SAP BTP ABAP Environment. Während du im Entwicklungsalltag ATC manuell in ADT ausführst, ermöglicht die ATC API die Integration in CI/CD-Pipelines für automatisierte Quality Gates.

Warum ATC automatisieren?

Die manuelle Ausführung von ATC-Prüfungen hat Grenzen:

AspektManuellAutomatisiert
TimingVor TransportBei jedem Commit
KonsistenzEntwicklerabhängigImmer gleiche Checks
VergessenMöglichUnmöglich
ReportingPunktuellKontinuierlich
Trend-AnalyseNicht möglichHistorische Daten
TeamstandardSchwer durchsetzbarAutomatisch erzwungen
┌────────────────────────────────────────────────────────────────┐
│ CI/CD Pipeline mit ATC Quality Gate │
├────────────────────────────────────────────────────────────────┤
│ │
│ Git Push ──▶ Build ──▶ ABAP Unit ──▶ ATC API ──▶ Deploy │
│ Tests Checks │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Quality │ │
│ │ Gate │ │
│ │ ──────────── │ │
│ │ Errors: 0 │ │
│ │ Warnings: <5 │ │
│ └──────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘

Voraussetzungen

Bevor du die ATC API nutzen kannst, benötigst du:

  1. SAP BTP ABAP Environment (Steampunk-Instanz)
  2. Communication Arrangement für ADT-Services (SAP_COM_0763)
  3. Communication User mit entsprechenden Berechtigungen
  4. Check-Variante für die automatisierte Ausführung

Communication Arrangement einrichten

Das Communication Arrangement aus dem ABAP Unit Runner gilt auch für ATC:

┌────────────────────────────────────────────────────────────────┐
│ Communication Arrangement: SAP_COM_0763 │
├────────────────────────────────────────────────────────────────┤
│ │
│ Inbound Services (aktiviert): │
│ ☑ ADT Core Services │
│ ☑ ADT ABAP Unit │
│ ☑ ADT ATC (ABAP Test Cockpit) │
│ │
│ Erforderliche Berechtigungen: │
│ • S_DEVELOP (Entwicklungsobjekte lesen) │
│ • S_ATC_ADM (ATC Administration) │
│ │
└────────────────────────────────────────────────────────────────┘

ATC API auf BTP

Die ATC API basiert auf dem ADT REST Framework und ermöglicht die programmatische Ausführung von ATC-Prüfungen.

API-Endpunkt

POST https://<system-url>/sap/bc/adt/atc/runs

Request-Format

<?xml version="1.0" encoding="UTF-8"?>
<atc:run xmlns:atc="http://www.sap.com/adt/atc"
xmlns:adtcore="http://www.sap.com/adt/core"
maximumVerdicts="100">
<objectSets>
<objectSet kind="inclusive">
<adtcore:objectReferences>
<adtcore:objectReference
adtcore:uri="/sap/bc/adt/vit/wb/object_type/devck/object_name/Z_FLIGHT_BOOKING"/>
</adtcore:objectReferences>
</objectSet>
</objectSets>
<checkVariant>
<atc:name>ABAP_CLOUD_READINESS</atc:name>
</checkVariant>
</atc:run>

Wichtige Request-Parameter

ParameterBeschreibungBeispiel
maximumVerdictsMax. Anzahl Findings100, 500, 1000
objectReferenceZu prüfendes Objekt (Paket, Klasse)devck/Z_FLIGHT_BOOKING
checkVariantCheck-VarianteABAP_CLOUD_READINESS

cURL-Beispiel

Terminal window
# ATC-Prüfung für ein Paket starten
curl -X POST \
"https://my-system.abap.eu10.hana.ondemand.com/sap/bc/adt/atc/runs" \
-u "CICD_USER:password" \
-H "Content-Type: application/vnd.sap.atc.run.v1+xml" \
-H "Accept: application/vnd.sap.atc.run.v1+xml" \
-d @atc_config.xml \
-o atc_results.xml

Eigene Check-Varianten definieren

Check-Varianten bestimmen, welche Prüfungen mit welcher Priorität ausgeführt werden.

Standard Check-Varianten auf BTP

VarianteBeschreibungEmpfohlen für
ABAP_CLOUD_READINESSPrüft Cloud-KompatibilitätMigration zu ABAP Cloud
DEFAULTAlle Standard-ChecksAllgemeine Qualität
SAP_CPSAP Cloud Platform ChecksBTP-Entwicklung

Check-Variante per API abrufen

Terminal window
# Verfügbare Check-Varianten abfragen
curl -X GET \
"https://my-system.abap.eu10.hana.ondemand.com/sap/bc/adt/atc/customizing/variants" \
-u "CICD_USER:password" \
-H "Accept: application/vnd.sap.atc.customizing.v1+xml"

Eigene Check-Variante anlegen

In SAP BTP ABAP Environment legst du Check-Varianten über die Fiori App Maintain ATC Check Variants an:

┌────────────────────────────────────────────────────────────────┐
│ Check-Variante: Z_CI_PIPELINE │
├────────────────────────────────────────────────────────────────┤
│ │
│ Beschreibung: Check-Variante für CI/CD Pipeline │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Check │ Priorität │ Aktiv │ │
│ ├────────────────────────────────┼───────────┼──────────────┤ │
│ │ SLIN_CHECK (Syntax Check) │ 1 │ ☑ │ │
│ │ SEC_CHECK (Security) │ 1 │ ☑ │ │
│ │ PERF_CHECK (Performance) │ 2 │ ☑ │ │
│ │ CONV_CHECK (Conventions) │ 3 │ ☑ │ │
│ │ CLOUD_CHECK (Cloud Readiness) │ 1 │ ☑ │ │
│ │ UNIT_TEST (Unit Tests) │ 2 │ ☐ │ │
│ └────────────────────────────────┴───────────┴──────────────┘ │
│ │
│ Prioritäten-Einstellung: │
│ • Priorität 1 (Fehler) → Build bricht ab │
│ • Priorität 2 (Warning) → Build mit Warnung │
│ • Priorität 3 (Info) → Nur protokolliert │
│ │
└────────────────────────────────────────────────────────────────┘

Check-Kategorien im Detail

" Die wichtigsten Check-Kategorien für ABAP Cloud:
" 1. Cloud Readiness Checks
" - Verwendung von nicht-freigegebenen APIs
" - Direkte DB-Zugriffe (SELECT auf Standardtabellen)
" - Verwendung von Dynpro-Anweisungen
" 2. Security Checks
" - SQL Injection Risiken
" - Cross-Site Scripting (XSS)
" - Fehlende Authority Checks
" - Hardcodierte Credentials
" 3. Performance Checks
" - SELECT * vermeiden
" - Schleifen mit SELECT
" - Fehlende WHERE-Klauseln
" - LOOP AT ohne READ TABLE Alternative
" 4. Naming Convention Checks
" - Z/Y Prefix für Custom Objects
" - Naming Guidelines für Variablen
" - Package-Zuordnung

Automatische Ausführung einrichten

Zweistufiger ATC-Prozess

Die ATC API arbeitet asynchron - du startest einen Run und fragst die Ergebnisse ab:

┌─────────────────────────────────────────────────────────────────┐
│ ATC API Workflow │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. POST /sap/bc/adt/atc/runs │
│ ├─ Request: Check-Konfiguration │
│ └─ Response: Run-ID (Location Header) │
│ │
│ 2. Polling: GET /sap/bc/adt/atc/runs/{run-id} │
│ ├─ Status: running → warten │
│ └─ Status: finished → Ergebnisse abrufen │
│ │
│ 3. GET /sap/bc/adt/atc/runs/{run-id}/results │
│ └─ Response: Findings als XML │
│ │
└─────────────────────────────────────────────────────────────────┘

Vollständiges Bash-Script für ATC-Ausführung

#!/bin/bash
# run_atc.sh - ATC-Prüfung auf BTP ausführen
set -e
# Konfiguration
SYSTEM_URL="${ABAP_ENDPOINT}"
USER="${ABAP_USER}"
PASSWORD="${ABAP_PASSWORD}"
PACKAGE="${1:-Z_FLIGHT_BOOKING}"
CHECK_VARIANT="${2:-ABAP_CLOUD_READINESS}"
MAX_VERDICTS="${3:-500}"
echo "=== Starting ATC Check ==="
echo "Package: $PACKAGE"
echo "Variant: $CHECK_VARIANT"
# 1. ATC Run starten
cat > atc_request.xml << EOF
<?xml version="1.0" encoding="UTF-8"?>
<atc:run xmlns:atc="http://www.sap.com/adt/atc"
xmlns:adtcore="http://www.sap.com/adt/core"
maximumVerdicts="$MAX_VERDICTS">
<objectSets>
<objectSet kind="inclusive">
<adtcore:objectReferences>
<adtcore:objectReference
adtcore:uri="/sap/bc/adt/vit/wb/object_type/devck/object_name/$PACKAGE"/>
</adtcore:objectReferences>
</objectSet>
</objectSets>
<checkVariant>
<atc:name>$CHECK_VARIANT</atc:name>
</checkVariant>
</atc:run>
EOF
# Run starten und Location Header extrahieren
RESPONSE=$(curl -s -D - \
-X POST \
"$SYSTEM_URL/sap/bc/adt/atc/runs" \
-u "$USER:$PASSWORD" \
-H "Content-Type: application/vnd.sap.atc.run.v1+xml" \
-H "Accept: application/vnd.sap.atc.run.v1+xml" \
-d @atc_request.xml)
RUN_ID=$(echo "$RESPONSE" | grep -i "location:" | sed 's/.*runs\///' | tr -d '\r\n')
if [ -z "$RUN_ID" ]; then
echo "::error::Failed to start ATC run"
echo "$RESPONSE"
exit 1
fi
echo "ATC Run started: $RUN_ID"
# 2. Auf Abschluss warten (Polling)
MAX_ATTEMPTS=60
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
STATUS_RESPONSE=$(curl -s \
-X GET \
"$SYSTEM_URL/sap/bc/adt/atc/runs/$RUN_ID" \
-u "$USER:$PASSWORD" \
-H "Accept: application/vnd.sap.atc.run.v1+xml")
STATUS=$(echo "$STATUS_RESPONSE" | grep -oP 'status="\K[^"]+' || echo "unknown")
echo "Status: $STATUS (Attempt $((ATTEMPT+1))/$MAX_ATTEMPTS)"
if [ "$STATUS" = "finished" ]; then
break
fi
sleep 5
ATTEMPT=$((ATTEMPT+1))
done
if [ "$STATUS" != "finished" ]; then
echo "::error::ATC run timed out"
exit 1
fi
# 3. Ergebnisse abrufen
curl -s \
-X GET \
"$SYSTEM_URL/sap/bc/adt/atc/runs/$RUN_ID/results" \
-u "$USER:$PASSWORD" \
-H "Accept: application/vnd.sap.atc.worklist.v1+xml" \
-o atc_results.xml
echo "=== ATC Results saved to atc_results.xml ==="

Ergebnisse auswerten und reporten

ATC Response-Format

<?xml version="1.0" encoding="UTF-8"?>
<atc:worklist xmlns:atc="http://www.sap.com/adt/atc"
xmlns:adtcore="http://www.sap.com/adt/core"
timestamp="2026-02-15T10:30:00Z"
usedCheckVariant="Z_CI_PIPELINE">
<objects>
<object adtcore:uri="/sap/bc/adt/oo/classes/zcl_flight_booking"
adtcore:name="ZCL_FLIGHT_BOOKING"
adtcore:type="CLAS">
<findings>
<finding checkId="CL_CI_CRITICAL_API_USE"
checkTitle="Non-released API usage"
messageId="001"
messageTitle="Usage of non-released API detected"
priority="1"
location="/sap/bc/adt/oo/classes/zcl_flight_booking/source/main#start=45,10">
<atc:quickfixes count="1"/>
</finding>
<finding checkId="CL_CI_SEC_INJECTION"
checkTitle="SQL Injection Risk"
messageId="002"
messageTitle="Potential SQL injection vulnerability"
priority="1"
location="/sap/bc/adt/oo/classes/zcl_flight_booking/source/main#start=78,5">
<atc:quickfixes count="0"/>
</finding>
<finding checkId="CL_CI_CONV_NAMING"
checkTitle="Naming Convention"
messageId="003"
messageTitle="Variable naming does not follow convention"
priority="3"
location="/sap/bc/adt/oo/classes/zcl_flight_booking/source/main#start=12,8">
<atc:quickfixes count="1"/>
</finding>
</findings>
</object>
</objects>
<statistics>
<totalFindings>3</totalFindings>
<findingsByPriority>
<priority1>2</priority1>
<priority2>0</priority2>
<priority3>1</priority3>
</findingsByPriority>
</statistics>
</atc:worklist>

Python-Script für Ergebnis-Parsing

parse_atc_results.py
import xml.etree.ElementTree as ET
import sys
import json
from dataclasses import dataclass, asdict
from typing import List
@dataclass
class Finding:
check_id: str
check_title: str
message: str
priority: int
object_name: str
location: str
has_quickfix: bool
def parse_atc_results(xml_file: str) -> dict:
tree = ET.parse(xml_file)
root = tree.getroot()
ns = {
'atc': 'http://www.sap.com/adt/atc',
'adtcore': 'http://www.sap.com/adt/core'
}
findings: List[Finding] = []
priority_counts = {1: 0, 2: 0, 3: 0}
for obj in root.findall('.//atc:object', ns):
obj_name = obj.get('{http://www.sap.com/adt/core}name', 'Unknown')
for finding in obj.findall('.//atc:finding', ns):
priority = int(finding.get('priority', 3))
priority_counts[priority] = priority_counts.get(priority, 0) + 1
quickfixes = finding.find('atc:quickfixes', ns)
has_quickfix = quickfixes is not None and int(quickfixes.get('count', 0)) > 0
findings.append(Finding(
check_id=finding.get('checkId', ''),
check_title=finding.get('checkTitle', ''),
message=finding.get('messageTitle', ''),
priority=priority,
object_name=obj_name,
location=finding.get('location', ''),
has_quickfix=has_quickfix
))
return {
'total': len(findings),
'errors': priority_counts.get(1, 0),
'warnings': priority_counts.get(2, 0),
'info': priority_counts.get(3, 0),
'findings': [asdict(f) for f in findings]
}
def print_report(results: dict, error_threshold: int = 0, warning_threshold: int = 5):
print("=" * 60)
print("ATC QUALITY REPORT")
print("=" * 60)
print(f"Total Findings: {results['total']}")
print(f" Errors (P1): {results['errors']}")
print(f" Warnings (P2): {results['warnings']}")
print(f" Info (P3): {results['info']}")
print("=" * 60)
# Findings nach Priorität gruppiert ausgeben
for priority in [1, 2, 3]:
priority_findings = [f for f in results['findings'] if f['priority'] == priority]
if priority_findings:
print(f"\nPriority {priority} Findings:")
print("-" * 40)
for f in priority_findings:
print(f" [{f['check_id']}] {f['object_name']}")
print(f" {f['message']}")
quickfix = "✓ Quickfix available" if f['has_quickfix'] else ""
print(f" {f['location']} {quickfix}")
print("\n" + "=" * 60)
# Thresholds prüfen
exit_code = 0
if results['errors'] > error_threshold:
print(f"::error::Found {results['errors']} error(s) (threshold: {error_threshold})")
exit_code = 1
if results['warnings'] > warning_threshold:
print(f"::warning::Found {results['warnings']} warning(s) (threshold: {warning_threshold})")
return exit_code
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python parse_atc_results.py <xml_file> [--json]")
sys.exit(1)
results = parse_atc_results(sys.argv[1])
if '--json' in sys.argv:
print(json.dumps(results, indent=2))
else:
exit_code = print_report(results)
sys.exit(exit_code)

Integration mit GitHub/GitLab

GitHub Actions Workflow

.github/workflows/atc-quality-gate.yml
name: ATC Quality Gate
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
PACKAGE: Z_FLIGHT_BOOKING
CHECK_VARIANT: ABAP_CLOUD_READINESS
ERROR_THRESHOLD: 0
WARNING_THRESHOLD: 5
jobs:
atc-check:
name: ATC Quality Check
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Create ATC Configuration
run: |
cat > atc_config.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<atc:run xmlns:atc="http://www.sap.com/adt/atc"
xmlns:adtcore="http://www.sap.com/adt/core"
maximumVerdicts="500">
<objectSets>
<objectSet kind="inclusive">
<adtcore:objectReferences>
<adtcore:objectReference
adtcore:uri="/sap/bc/adt/vit/wb/object_type/devck/object_name/${{ env.PACKAGE }}"/>
</adtcore:objectReferences>
</objectSet>
</objectSets>
<checkVariant>
<atc:name>${{ env.CHECK_VARIANT }}</atc:name>
</checkVariant>
</atc:run>
EOF
- name: Start ATC Run
id: start-atc
run: |
RESPONSE=$(curl -s -D - \
-X POST \
"${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/atc/runs" \
-u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \
-H "Content-Type: application/vnd.sap.atc.run.v1+xml" \
-H "Accept: application/vnd.sap.atc.run.v1+xml" \
-d @atc_config.xml)
RUN_ID=$(echo "$RESPONSE" | grep -i "location:" | sed 's/.*runs\///' | tr -d '\r\n')
if [ -z "$RUN_ID" ]; then
echo "::error::Failed to start ATC run"
exit 1
fi
echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT
echo "Started ATC run: $RUN_ID"
- name: Wait for ATC Completion
run: |
RUN_ID="${{ steps.start-atc.outputs.run_id }}"
MAX_ATTEMPTS=60
for i in $(seq 1 $MAX_ATTEMPTS); do
STATUS=$(curl -s \
-X GET \
"${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/atc/runs/$RUN_ID" \
-u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \
-H "Accept: application/vnd.sap.atc.run.v1+xml" \
| grep -oP 'status="\K[^"]+' || echo "unknown")
echo "Status: $STATUS (Attempt $i/$MAX_ATTEMPTS)"
if [ "$STATUS" = "finished" ]; then
break
fi
sleep 5
done
if [ "$STATUS" != "finished" ]; then
echo "::error::ATC run timed out"
exit 1
fi
- name: Fetch ATC Results
run: |
RUN_ID="${{ steps.start-atc.outputs.run_id }}"
curl -s \
-X GET \
"${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/atc/runs/$RUN_ID/results" \
-u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \
-H "Accept: application/vnd.sap.atc.worklist.v1+xml" \
-o atc_results.xml
- name: Parse and Evaluate Results
id: parse
run: |
python << 'PYTHON_SCRIPT'
import xml.etree.ElementTree as ET
import os
tree = ET.parse('atc_results.xml')
root = tree.getroot()
ns = {'atc': 'http://www.sap.com/adt/atc', 'adtcore': 'http://www.sap.com/adt/core'}
errors = warnings = info = 0
for finding in root.findall('.//atc:finding', ns):
priority = int(finding.get('priority', 3))
if priority == 1:
errors += 1
elif priority == 2:
warnings += 1
else:
info += 1
with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
f.write(f"errors={errors}\n")
f.write(f"warnings={warnings}\n")
f.write(f"info={info}\n")
f.write(f"total={errors + warnings + info}\n")
print(f"Errors: {errors}, Warnings: {warnings}, Info: {info}")
# Quality Gate prüfen
if errors > int(os.environ.get('ERROR_THRESHOLD', 0)):
print(f"::error::Quality Gate failed: {errors} error(s) found")
exit(1)
PYTHON_SCRIPT
- name: Upload ATC Results
uses: actions/upload-artifact@v4
with:
name: atc-results
path: atc_results.xml
- name: Create Summary
if: always()
run: |
cat >> $GITHUB_STEP_SUMMARY << EOF
## ATC Quality Gate Results
| Metric | Value | Threshold |
|--------|-------|-----------|
| Errors (P1) | ${{ steps.parse.outputs.errors }} | ${{ env.ERROR_THRESHOLD }} |
| Warnings (P2) | ${{ steps.parse.outputs.warnings }} | ${{ env.WARNING_THRESHOLD }} |
| Info (P3) | ${{ steps.parse.outputs.info }} | - |
| **Total** | ${{ steps.parse.outputs.total }} | |
**Status:** ${{ steps.parse.outputs.errors == 0 && '✅ Passed' || '❌ Failed' }}
EOF

GitLab CI/CD Pipeline

.gitlab-ci.yml
stages:
- quality
variables:
PACKAGE: Z_FLIGHT_BOOKING
CHECK_VARIANT: ABAP_CLOUD_READINESS
ERROR_THRESHOLD: "0"
atc-quality-gate:
stage: quality
image: python:3.11-slim
before_script:
- apt-get update && apt-get install -y curl
script:
# ATC Run starten
- |
RESPONSE=$(curl -s -D - \
-X POST \
"${ABAP_ENDPOINT}/sap/bc/adt/atc/runs" \
-u "${ABAP_USER}:${ABAP_PASSWORD}" \
-H "Content-Type: application/vnd.sap.atc.run.v1+xml" \
-H "Accept: application/vnd.sap.atc.run.v1+xml" \
-d "<atc:run xmlns:atc=\"http://www.sap.com/adt/atc\"
xmlns:adtcore=\"http://www.sap.com/adt/core\"
maximumVerdicts=\"500\">
<objectSets>
<objectSet kind=\"inclusive\">
<adtcore:objectReferences>
<adtcore:objectReference
adtcore:uri=\"/sap/bc/adt/vit/wb/object_type/devck/object_name/${PACKAGE}\"/>
</adtcore:objectReferences>
</objectSet>
</objectSets>
<checkVariant>
<atc:name>${CHECK_VARIANT}</atc:name>
</checkVariant>
</atc:run>")
RUN_ID=$(echo "$RESPONSE" | grep -i "location:" | sed 's/.*runs\///' | tr -d '\r\n')
echo "ATC Run ID: $RUN_ID"
# Auf Abschluss warten
- |
for i in $(seq 1 60); do
STATUS=$(curl -s \
"${ABAP_ENDPOINT}/sap/bc/adt/atc/runs/${RUN_ID}" \
-u "${ABAP_USER}:${ABAP_PASSWORD}" \
-H "Accept: application/vnd.sap.atc.run.v1+xml" \
| grep -oP 'status="\K[^"]+' || echo "unknown")
echo "Attempt $i: Status = $STATUS"
[ "$STATUS" = "finished" ] && break
sleep 5
done
# Ergebnisse abrufen
- |
curl -s \
"${ABAP_ENDPOINT}/sap/bc/adt/atc/runs/${RUN_ID}/results" \
-u "${ABAP_USER}:${ABAP_PASSWORD}" \
-H "Accept: application/vnd.sap.atc.worklist.v1+xml" \
-o atc_results.xml
# Ergebnisse prüfen
- |
python3 << 'EOF'
import xml.etree.ElementTree as ET
import sys
import os
tree = ET.parse('atc_results.xml')
root = tree.getroot()
ns = {'atc': 'http://www.sap.com/adt/atc'}
errors = sum(1 for f in root.findall('.//atc:finding', ns) if f.get('priority') == '1')
print(f"Found {errors} error(s)")
if errors > int(os.environ.get('ERROR_THRESHOLD', 0)):
sys.exit(1)
EOF
artifacts:
paths:
- atc_results.xml
reports:
junit: atc_results.xml
when: always
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == "main"

Best Practices

AspektEmpfehlung
Check-VarianteEigene Variante für CI/CD mit klaren Prioritäten
Error-Threshold0 für Priority 1 (keine Fehler erlaubt)
Warning-ThresholdRealistisch setzen, schrittweise senken
TimeoutMax. 5 Minuten für große Pakete
QuickfixesIn Report anzeigen, nicht automatisch anwenden
Trend-TrackingFindings über Zeit protokollieren
Team-StandardsCheck-Variante im Team abstimmen
Exception-HandlingBerechtigte Ausnahmen dokumentieren

Troubleshooting

ProblemMögliche UrsacheLösung
401 UnauthorizedFalsche CredentialsUser/Passwort prüfen
403 ForbiddenFehlende ATC-BerechtigungS_ATC_ADM prüfen
404 Not FoundPaket/Variante existiert nichtNamen prüfen
TimeoutPaket zu großIn kleinere Pakete aufteilen
Keine FindingsCheck-Variante leerChecks in Variante aktivieren
Run bleibt “running”System überlastetSpäter erneut versuchen

Weiterführende Ressourcen