Passa al contenuto principale

Integrazione CI/CD

Zenzic è pronto all'automazione. Il flag --format json e l'opzione --save espongono output machine-readable che qualsiasi sistema CI/CD può consumare per pilotare badge dinamici, quality gate e rilevamento delle regressioni.


Output JSON

Ogni comando di controllo supporta --format json:

# Report aggregato per tutti i controlli
zenzic check all --format json

# Controlli singoli
zenzic check links --format json
zenzic check references --format json

# Punteggio e regressioni
zenzic score --format json
zenzic diff --format json

zenzic check all --format json

{
"links": ["guides/setup.md:12 — Link target 'install.md' not found"],
"orphans": ["old-page.md"],
"snippets": [{"file": "api/ref.md", "line": 5, "message": "Snippet target not found"}],
"placeholders": [{"file": "index.md", "line": 1, "issue": "TODO", "detail": "Fix this"}],
"unused_assets": ["images/old-logo.png"],
"references": [],
"nav_contract": []
}

zenzic score --format json

{
"project": "zenzic",
"score": 100,
"threshold": 0,
"status": "success",
"timestamp": "2026-03-24T12:00:00+00:00",
"categories": [
{"name": "structural", "weight": 0.30, "issues": 0, "category_score": 30.0, "contribution": 30.0},
{"name": "content", "weight": 0.20, "issues": 0, "category_score": 20.0, "contribution": 20.0},
{"name": "navigation", "weight": 0.25, "issues": 0, "category_score": 25.0, "contribution": 25.0},
{"name": "brand", "weight": 0.25, "issues": 0, "category_score": 25.0, "contribution": 25.0}
]
}

Ogni comando di controllo singolo restituisce una struttura findings uniforme:

{
"findings": [
{"rel_path": "guides/setup.md", "line_no": 42, "code": "Z104", "severity": "error", "message": "guides/setup.md:42: 'install.md' not found in docs"}
],
"summary": {
"errors": 1, "warnings": 0, "info": 0,
"security_incidents": 0, "security_breaches": 0,
"elapsed_seconds": 0.042
}
}

I codici di uscita sono preservati in modalità JSON: exit 0 quando vengono trovati solo warning, exit 1 in caso di errori (o warning con --strict), exit 2 per violazioni credential scanner, exit 3 per path traversal guard — lo stesso contratto dell'output da terminale.


GitHub Actions: Zenzic Credential Gate

L'integrazione diretta — blocca la build a qualsiasi errore di documentazione.

Nessun setup Python richiesto. uvx scarica ed esegue Zenzic in un ambiente temporaneo ad ogni esecuzione. Ideale per repository documentazione-only o team che non hanno altrimenti bisogno di Python in CI:

.github/workflows/zenzic.yml
name: Qualità Documentazione

on:
push:
branches: [main]
paths: ['docs/**', 'mkdocs.yml']

jobs:
zenzic:
runs-on: ubuntu-latest
steps:

- uses: actions/checkout@v6

- name: Lint documentazione

run: uvx zenzic check all --strict

- name: Controllo riferimenti e credential scanner

run: uvx zenzic check references

Zenzic Quality Gate — Il Protocollo Diff

Il Zenzic Quality Gate usa zenzic diff per confrontare il punteggio corrente con un baseline salvato. I team possono collegare questo verdetto come gate bloccante o osservazionale in base alla policy del workflow.

Come funziona

  1. Su main: Zenzic esegue, salva il punteggio come .zenzic-score.json e lo carica come artefatto CI.
  2. Su ogni PR: L'artefatto di main viene scaricato come baseline. Zenzic esegue sul branch PR e chiama zenzic diff --base <baseline> per confrontare.
  3. Verdetto: Il workflow legge i segnali di regressione da zenzic diff e applica la policy di merge scelta dal repository.
.github/workflows/zenzic-quality-gate.yml
name: Zenzic Quality Gate

on:
push:
branches: [main]
pull_request:

jobs:
# Su main: salva il baseline autorevole
baseline:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v6

- name: Esegui Zenzic e salva il baseline
uses: PythonWoods/zenzic-action@<version>
with:
version: "0.9.2"
format: json # genera lo snapshot .zenzic-score.json
upload-sarif: "false"

- name: Carica artefatto baseline
uses: actions/upload-artifact@v4
with:
name: zenzic-baseline
path: .zenzic-score.json
retention-days: 90

# Su PR: confronta contro il baseline di main
quality-gate:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v6

- name: Scarica il baseline di main
uses: actions/download-artifact@v4
with:
name: zenzic-baseline
path: .zenzic-baseline/
continue-on-error: true # la prima PR su un nuovo repo non ha ancora un baseline

- name: Zenzic — Quality Gate
uses: PythonWoods/zenzic-action@<version>
id: zenzic
with:
version: "0.9.2"
format: sarif
upload-sarif: "true"
diff-base: ".zenzic-baseline/.zenzic-score.json"

- name: Riporta il punteggio di qualità
if: always()
run: |
echo "Score: ${{ steps.zenzic.outputs.score }}"
echo "Suppression debt: ${{ steps.zenzic.outputs.suppression-debt-pts }} pts"
echo "Finding: ${{ steps.zenzic.outputs.findings-count }}"
Regressione di Qualità via zenzic diff

Quando viene rilevata una regressione del punteggio, il workflow riceve un verdetto diff non zero e può applicare comportamento bloccante oppure osservazionale, secondo policy.


Modalità Audit in CI — Sovereign Audit

L'input audit: "true" forza un sovereign audit: tutti i commenti zenzic:ignore inline attivi e tutte le voci governance.per_file_ignores vengono bypassati. Ogni finding che normalmente sarebbe nascosto da una soppressione viene portato in superficie.

Usa la modalità audit in:

  • Build notturne — verifica settimanale che il debt soppresso rimanga intenzionale.
  • Workflow di Security Review — prima di un rilascio, verifica lo stato non filtrato della documentazione.
  • Sprint di riduzione del debt — visualizza l'intera portata di ciò che viene soppresso prima di alzare o abbassare suppression_cap.
.github/workflows/zenzic-audit.yml
name: Zenzic Sovereign Audit

on:
schedule:
- cron: "0 3 * * 1" # ogni lunedì alle 03:00 UTC
workflow_dispatch:

jobs:
audit:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v6

- name: Sovereign Audit (soppressioni bypassate)
uses: PythonWoods/zenzic-action@<version>
with:
version: "0.9.2"
format: sarif
upload-sarif: "true"
audit: "true" # bypassa tutti i zenzic:ignore e per_file_ignores
fail-on-error: "false" # l'audit è osservazionale, non bloccante

I risultati appaiono nella scheda Security → Code Scanning. Ogni finding soppresso è visibile accanto a quelli attivi. Questa è la verità non filtrata della tua documentazione.


Defense-in-Depth: Secret Guard

L'input guard-scan: "true" esegue zenzic guard scan come step standalone prima del gate principale. Usalo nei repository in cui i contributor possono bypassare i pre-commit hook con git commit --no-verify:

.github/workflows/zenzic.yml
- name: Run Zenzic Documentation Quality Gate
uses: PythonWoods/zenzic-action@<version>
with:
version: "0.9.2"
guard-scan: "true" # zenzic guard scan viene eseguito prima di check all
format: sarif
upload-sarif: "true"

Se guard scan rileva una credenziale hardcodata o un pattern vietato, esce con valore non zero e termina il job. fail-on-error: "false" non sopprime questo comportamento — lo scan di guardia è sempre fatale, coerente con il contratto di sicurezza Exit 2.


Gate Nativo di Freschezza Badge

Il workflow badge dinamico legacy è deprecato. Usa stamp e controllo freschezza nativi:

zenzic score --stamp
zenzic score --check-stamp

Comportamento CI consigliato: esegui zenzic score --check-stamp dopo zenzic check per imporre la freschezza dei badge stampati senza token esterni o plumbing badge esterno.

Il Gate di Freschezza Badge

zenzic score --check-stamp confronta l'URL del badge incorporato nel tuo README.md (o in qualsiasi file elencato in badge_stamp_files) con il punteggio calcolato da Zenzic in quel momento. Se differiscono, il comando termina con exit 1 e stampa un messaggio con le istruzioni di risoluzione:

[FAILED] Badge (score) in README.md is stale.
Run 'zenzic score --stamp' locally and commit the updated files to resolve this.

Il gate è di sola lettura — non modifica mai i file. Valida solo ciò che è già stato committato.

Opzionale: automatizza con pre-commit

Zenzic funziona zero-config out of the box — il gate CI da solo è sufficiente. Se usi l'integrazione pre-commit e vuoi automatizzare lo stamp del badge per non dover eseguire --stamp manualmente, puoi aggiungere opzionalmente questo hook:

.pre-commit-config.yaml
- repo: local
hooks:
- id: zenzic-score-stamp
name: Zenzic Score Badge (stamp)
entry: zenzic score --stamp --no-header
language: system
stages: [pre-commit]
pass_filenames: false
always_run: true

Con questo hook, il badge viene aggiornato automaticamente a ogni git commit. Se il punteggio è cambiato, pre-commit segnala che README.md è stato modificato — aggiungi il file e riesegui git commit per procedere.

Senza pre-commit

Esegui lo stamp manualmente prima di fare push:

zenzic score --stamp
git add README.md README.it.md # o i file in badge_stamp_files
git commit --amend --no-edit # o un nuovo commit
git push

Se salti questo passaggio e la CI trova un badge obsoleto, il workflow fallisce con l'errore sopra. Segui le istruzioni del messaggio, esegui lo stamp in locale e ripeti il push.

Configurazione CI (gate di sola lettura)

In GitHub Actions, usa solo --check-stampmai --stamp. La CI è un validatore immutabile, non un editor di file:

.github/workflows/zenzic.yml
- name: Check badge freshness
run: uvx zenzic score --check-stamp --no-header

Con zenzic-action, il gate di freschezza badge è abilitato di default — nessuna configurazione aggiuntiva necessaria:

- name: Run Zenzic
uses: PythonWoods/zenzic-action@v1

Rilevamento Regressioni

zenzic diff confronta il punteggio corrente con il baseline .zenzic-score.json salvato e fallisce se il punteggio è sceso:

.github/workflows/zenzic.yml
- name: Rileva regressione del punteggio
run: |
uvx zenzic score --save # aggiorna snapshot
uvx zenzic diff --threshold 5 # fallisce se il punteggio scende > 5 punti

Per il setup completo del Zenzic Quality Gate con blocco PR e upload dell'artefatto baseline, vedi la sezione Protocollo Diff sopra.


Codici di Uscita

CodiceSignificatoAzione badge
0Tutti i controlli superatiMantieni il badge verde
1Uno o più controlli fallitiImposta il badge a failing / ef4444
2Credential scanner: credenziale rilevataRuota la credenziale immediatamente
3Path traversal guard: path traversal rilevatoRimuovi il link incriminato immediatamente

Per il riferimento completo dei badge pronti all'uso, vedi Badge Ufficiali.


Recupero dalla credential scanner — Quando Viene Rilevata una Credenziale

Un rilevamento di credenziale (exit code 2) non è una build fallita. È un incidente di sicurezza. Il protocollo di recupero è breve e non negoziabile:

Step 1 — Identifica l'esposizione

Il Zenzic Report ti dice tutto ciò di cui hai bisogno:

✘ Z201 docs/how-to/configure.md:4 Secret rilevato (aws-access-key)
Credenziale: AKIA************MPLE
→ Exit code 2 — ruota immediatamente.

Nota il file, la riga e il tipo di credenziale. La credenziale è sempre mascherata nel report — Zenzic non stampa mai il valore completo.

Step 2 — Ruota la credenziale

Prima di fare qualsiasi altra cosa — ruota la chiave nella console del tuo cloud provider. Non committare prima la correzione. Una chiave ruotata è inerte anche se rimane brevemente nella tua git history.

Step 3 — Rimuovila dalla sorgente

Elimina o sostituisci il segreto nel file segnalato da Zenzic. Committa la correzione.

Step 4 — Riscrivi la history se necessario

Se la credenziale è apparsa in un commit precedente già pushato:

# Rebase interattivo fino al commit che ha introdotto il segreto
git rebase -i <commit-prima-del-segreto>^

# Oppure usa git-filter-repo (preferito rispetto a BFG per i nuovi progetti)
git filter-repo --path docs/how-to/configure.md --force
Il force-push richiede coordinamento

Riscrivere la history pubblica richiede un force-push. Coordina con il tuo team prima di farlo su un branch condiviso. Se il repository è pubblico, considera la credenziale già compromessa a prescindere dalla riscrittura della history — la rotazione è obbligatoria.

Step 5 — Verifica che il credential scanner sia soddisfatto

uvx zenzic check all
# Atteso: exit 0, sezione credential scanner mostra ✔ nessuna credenziale rilevata

Solo exit 0 dal pass credential scanner significa che il recupero è completo.

Perché Zenzic ti salva da BFG Repo Cleaner

BFG Repo Cleaner è uno strumento irreversibile per eliminare segreti dalla git history. Il suo utilizzo è un sintomo di un fallimento di processo: il segreto ha raggiunto il repository senza essere rilevato. Il credential scanner di Zenzic previene questo intercettando le credenziali prima che entrino nella pipeline CI — idealmente tramite un hook pre-commit. Vedi Integrazione pre-commit per aggiungere il credential scanner come gate locale che gira ad ogni git commit.


Integrazione Pre-commit

Il credential scanner in CI è la tua ultima linea di difesa. L'hook pre-commit è la prima:

.pre-commit-config.yaml
repos:

- repo: local

hooks:

- id: zenzic-credentials

name: Zenzic Credentials
language: system
entry: uvx zenzic check all
pass_filenames: false
stages: [pre-commit]

Con questo hook, git commit si rifiuterà di procedere se Zenzic rileva una credenziale, un link rotto o qualsiasi finding di qualità con exit 1. Il feedback è istantaneo, la correzione è locale, e il segreto non tocca mai il remoto.


Parity Doc-Code

Ogni codice di finding Zxxx documentato in docs/ deve avere un'entità registrata in src/zenzic/core/codes.py nel pacchetto core — e viceversa. Questo invariante bidirezionale è applicato dalla sessione Nox verify-codes-parity:

# Esecuzione autonoma
nox -s verify-codes-parity

# Esegue automaticamente come parte del gate locale completo
just verify

La sessione usa la Risoluzione Sovrana (Fail-Closed) per localizzare codes.py:

CondizioneStrategiaComando usato
ZENZIC_CORE_PATH impostato, o ../zenzic esisteCore Maintainer — usa il source tree localeuv run --project <percorso> python scripts/verify_codes_parity.py
Core locale non trovatoFail-Closed — nessun fallback consentitoLa sessione fallisce con errore sul path del core

I contributori esterni devono fornire un checkout locale del core (ZENZIC_CORE_PATH, ./_zenzic_core oppure ../zenzic) per eseguire nox -s verify-codes-parity.