diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..aa88cc8 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitea/workflows/reusable-ai-review.yml b/.gitea/workflows/reusable-ai-review.yml new file mode 100644 index 0000000..c037a99 --- /dev/null +++ b/.gitea/workflows/reusable-ai-review.yml @@ -0,0 +1,39 @@ +# GLOBALER, wiederverwendbarer KI-PR-Review (Feature A). +# Aufruf aus einem beliebigen Repo (siehe workflows/caller.example.yml): +# jobs: +# review: +# if: github.event_name == 'pull_request' +# uses: user2595/ci-ai/.gitea/workflows/reusable-ai-review.yml@main +# secrets: inherit +# +# Voraussetzungen: globaler Runner `eulernest`, anon-Clone für public Repos. +# Ohne ANTHROPIC_API_KEY überspringt das Skript den KI-Schritt sauber (Job grün). +name: ci-ai · review (reusable) + +on: + workflow_call: + secrets: + ANTHROPIC_API_KEY: + required: false + +jobs: + review: + runs-on: eulernest + container: + image: python:3.12-slim + options: "--memory=512m --memory-swap=768m" + steps: + - name: Tooling (git) + run: apt-get update -qq && apt-get install -y -qq --no-install-recommends git ca-certificates + + - name: ci-ai-Skripte holen (anon) + run: git clone --depth 1 https://git.eulernest.eu/user2595/ci-ai.git /opt/ci-ai + + - name: KI-Review (überspringt sauber ohne Key) + env: + AI_PROVIDER: anthropic + AI_MODEL: claude-3-5-haiku-latest + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITEA_TOKEN: ${{ github.token }} + GITEA_API: https://git.eulernest.eu/api/v1 + run: python /opt/ci-ai/scripts/ai_review.py diff --git a/.gitea/workflows/reusable-security.yml b/.gitea/workflows/reusable-security.yml new file mode 100644 index 0000000..2b82b66 --- /dev/null +++ b/.gitea/workflows/reusable-security.yml @@ -0,0 +1,84 @@ +# GLOBALER, wiederverwendbarer Security-Scan (Feature B + C). +# Aufruf aus einem beliebigen Repo (siehe workflows/caller.example.yml): +# jobs: +# security: +# uses: user2595/ci-ai/.gitea/workflows/reusable-security.yml@main +# secrets: inherit +# +# Voraussetzungen (einmalig zentral): +# - Runner instanzweit registriert (Label `eulernest`) +# - anonymer Clone für public Repos erlaubt (für den ci-ai-Clone) +# - optional ANTHROPIC_API_KEY als Org-/Instanz-Secret (für die KI-Erklärung) +# +# python:3.12-slim (Debian: bash) + Memory-Cap (Pi). ⚠ ARM64-Binaries. +# Gitleaks (Secrets) + Trivy config (IaC) — hart blockierend über den Gate-Schritt. +name: ci-ai · security (reusable) + +on: + workflow_call: + secrets: + ANTHROPIC_API_KEY: + required: false + +env: + GITLEAKS_VERSION: "8.18.4" + +jobs: + scan: + runs-on: eulernest + container: + image: python:3.12-slim + options: "--memory=768m --memory-swap=1024m" + steps: + - name: Tooling + run: apt-get update -qq && apt-get install -y -qq --no-install-recommends git curl ca-certificates tar + + - name: Ziel-Repo auschecken (Auto-Token des aufrufenden Repos) + env: + GITEA_TOKEN: ${{ github.token }} + run: git clone --depth 1 "https://x-access-token:${GITEA_TOKEN}@git.eulernest.eu/${GITHUB_REPOSITORY}.git" src + + - name: Gitleaks (Secret-Scan, ARM64) + id: gl + continue-on-error: true + run: | + set +e + curl -sSL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_arm64.tar.gz" \ + | tar -xz -C /usr/local/bin gitleaks + cd src + gitleaks detect --no-git --source . --redact > /tmp/gl.log 2>&1 + echo "code=$?" >> "$GITHUB_OUTPUT" + tail -n 3 /tmp/gl.log; cat /tmp/gl.log >> /tmp/scan.log + + - name: Trivy (IaC/config, leicht) + id: tv + continue-on-error: true + run: | + set +e + curl -sSL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \ + | sh -s -- -b /usr/local/bin + cd src + trivy config --severity HIGH,CRITICAL --exit-code 1 . > /tmp/tv.log 2>&1 + echo "code=$?" >> "$GITHUB_OUTPUT" + tail -n 8 /tmp/tv.log; cat /tmp/tv.log >> /tmp/scan.log + + - name: Gate — hart blockieren bei Funden + run: | + echo "gitleaks=${{ steps.gl.outputs.code }} trivy=${{ steps.tv.outputs.code }}" + if [ "${{ steps.gl.outputs.code }}" != "0" ] || [ "${{ steps.tv.outputs.code }}" != "0" ]; then + echo "Security-Funde -> Check schlägt fehl (hart blockierend)."; exit 1 + fi + echo "Keine HIGH/CRITICAL-Funde." + + - name: KI erklärt die Funde (bei Fehler; skippt sauber ohne Key) + if: failure() + continue-on-error: true + env: + AI_PROVIDER: anthropic + AI_MODEL: claude-3-5-haiku-latest + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + GITEA_TOKEN: ${{ github.token }} + GITEA_API: https://git.eulernest.eu/api/v1 + run: | + git clone --depth 1 https://git.eulernest.eu/user2595/ci-ai.git /opt/ci-ai + python3 /opt/ci-ai/scripts/ai_explain.py security /tmp/scan.log diff --git a/README.md b/README.md index 8af93d5..07d9552 100644 --- a/README.md +++ b/README.md @@ -24,20 +24,40 @@ scripts/ context.py Gitea-Actions-Event-Kontext (GITHUB_*-Vars) ai_review.py Feature A ai_explain.py Features B & C -workflows/ Beispiel-Workflows zum Kopieren in Ziel-Repos +.gitea/workflows/ + reusable-security.yml on: workflow_call — zentraler Security-Scan + reusable-ai-review.yml on: workflow_call — zentraler PR-Review +workflows/ + caller.example.yml der EINE 12-Zeiler fürs Ziel-Repo (empfohlen) + *.example.yml standalone-Workflows (Alternative: kopieren) ``` Keine Abhängigkeiten — reine Python-Standardbibliothek, kein `pip install`. ## In ein Repo einbauen -1. Beispiel aus `workflows/` nach `.gitea/workflows/` im Ziel-Repo kopieren. -2. Im Repo (oder org-weit) die **Actions-Unit** aktivieren. -3. **Actions-Secret** `ANTHROPIC_API_KEY` setzen. Kommentiert wird per Auto-Token - (`${{ github.token }}`); reichen dessen Rechte nicht, ein `GITEA_BOT_TOKEN` - (PAT mit `write:issue`) als Secret hinterlegen. -4. Für „hart blockieren": in der Branch-Protection den `Security`-Check als - *required* markieren. +### Empfohlen: globaler Aufruf (reusable workflow) + +Nur **eine** Datei ins Ziel-Repo: `workflows/caller.example.yml` → +`.gitea/workflows/ci-ai.yml`. Sie ruft die zentrale Logik aus diesem Repo auf +(`uses: user2595/ci-ai/.gitea/workflows/reusable-*.yml@main` + `secrets: inherit`). +Logik-Updates passieren **einmal hier**, alle Repos ziehen automatisch nach. + +Einmalig zentral einzurichten: + +1. Runner **instanzweit** registrieren (Admin → Actions → Runners), Label `eulernest` + — sonst haben Repos außerhalb der org keinen Runner. +2. **Anonymen Clone für public Repos** erlauben (`REQUIRE_SIGNIN_VIEW=false`) — der Job + klont `ci-ai` für die Skripte. +3. `ANTHROPIC_API_KEY` als **Org-/Instanz-Actions-Secret** (KI-Schritte; ohne ihn laufen + die Scans normal, die KI-Teile überspringen sich sauber). +4. Für „hart blockieren": `security`-Check in der Branch-Protection als *required*. + +### Alternative: standalone (kopieren) + +`workflows/ai-review.example.yml` + `workflows/security.example.yml` direkt nach +`.gitea/workflows/` kopieren. Enthält die volle Logik (klont die Skripte selbst) — +mehr Copy-Paste, aber unabhängig von reusable-workflow-Support. ## Umstieg auf den Jetson (später) diff --git a/workflows/caller.example.yml b/workflows/caller.example.yml new file mode 100644 index 0000000..7367654 --- /dev/null +++ b/workflows/caller.example.yml @@ -0,0 +1,29 @@ +# GLOBALER CI-AI-Aufruf — das EINZIGE, was ein Ziel-Repo braucht. +# Kopie nach: /.gitea/workflows/ci-ai.yml +# +# Holt die komplette Logik zentral aus user2595/ci-ai (reusable workflows) — keine +# Skripte/Workflows ins Repo kopieren. Update der Logik passiert einmal in ci-ai. +# +# Voraussetzungen (einmalig zentral eingerichtet): +# 1. Runner instanzweit registriert (Label `eulernest`) +# 2. anonymer Clone für public Repos erlaubt +# 3. ANTHROPIC_API_KEY als Org-/Instanz-Actions-Secret (für die KI-Schritte; +# ohne ihn laufen die Scans, die KI-Teile überspringen sich sauber) +# 4. für „hart blockieren": den `security`-Check in der Branch-Protection +# als required markieren +name: CI-AI + +on: + pull_request: + push: + branches: [main, master] + +jobs: + security: + uses: user2595/ci-ai/.gitea/workflows/reusable-security.yml@main + secrets: inherit + + review: + if: github.event_name == 'pull_request' + uses: user2595/ci-ai/.gitea/workflows/reusable-ai-review.yml@main + secrets: inherit