Skip to content

feat(#441): lot 5 netcross_core, tls_diagnostics et quic_diagnostics #579

feat(#441): lot 5 netcross_core, tls_diagnostics et quic_diagnostics

feat(#441): lot 5 netcross_core, tls_diagnostics et quic_diagnostics #579

Workflow file for this run

name: CI
# Issue #463 : concentration des workflows. Anciennement trois workflows
# parallèles (ci.yml, docs.yml, i18n.yml) se déclenchaient sur les mêmes
# push/PR vers main/dev. Ils sont fusionnés ici en un seul, réduisant le
# nombre de runs simultanés et le temps d'attente des checks requis.
#
# Jobs :
# quality — lint, format, import-linter, tests (check requis)
# gtk4 — tests GTK4 sous Xvfb (check requis)
# packaging — construction + test de fumée deb/rpm (check requis)
# types — mypy (non bloquant, continue-on-error)
# documentation — mkdocs build --strict (check requis, ex docs.yml)
# i18n — catalogues gettext à jour et valides (ex i18n.yml check)
"on":
push:
branches: [main, dev]
pull_request:
branches: [main, dev]
workflow_dispatch:
jobs:
quality:
name: Qualité (lint, format, import-linter, tests)
runs-on: ubuntu-latest
steps:
- name: Checkout du dépôt
uses: actions/checkout@v7
- name: Installation de Wireshark CLI (tshark, editcap, capinfos) et de pdftotext
# Issue #262 : tshark n'était installé dans AUCUN environnement de
# développement du projet, donc toute la suite @requires_tshark /
# @requires_editcap était systématiquement sautée. Deux bugs réels
# (#261 filtre inutilisable, #262 format de sortie ignoré) ont ainsi
# survécu des mois à une CI verte. Les installer ici rend ces tests
# exécutables : c'est la seule correction qui empêche la classe entière
# de régressions de redevenir invisible.
# DEBIAN_FRONTEND + preseed : l'installeur de wireshark-common pose
# sinon une question interactive sur les droits de capture.
run: |
echo "wireshark-common wireshark-common/install-setuid boolean false" \
| sudo debconf-set-selections
sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq tshark poppler-utils gettext
tshark --version | head -1
editcap --version | head -1
# poppler-utils fournit pdftotext, utilise par tests/test_security_outputs.py
# (issue #218) pour REEXTRAIRE le texte du PDF produit au lieu de
# s'arreter avant le rendu. C'est precisement le niveau de
# verification qui manquait a l'issue #259 : un champ present dans
# les donnees et absent du rendu final. Meme raisonnement que
# tshark ci-dessus (#262) -- sauter ces tests quand l'outil manque
# rendrait la CI verte en supprimant la seule verification qui
# regarde le fichier livre a l'utilisateur.
pdftotext -v 2>&1 | head -1
- name: Installation de uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
- name: Installation de Python
run: uv python install 3.14
- name: Installation des dépendances (extras dev + api + ai)
run: uv sync --extra dev --extra api --extra ai
- name: Lint (ruff check)
run: uv run ruff check .
- name: Formatage (ruff format --check)
run: uv run ruff format --check .
- name: Architecture en couches (import-linter)
run: uv run lint-imports
env:
PYTHONPATH: src
- name: Diagramme de classes à jour (issue #140)
# Vérifie que docs/class-diagram.md correspond au code source de src/.
# Le hook pre-commit `class-diagram` le fait en local, mais CI est le
# filet de sécurité pour les contributions qui n'ont pas lancé le hook.
run: python3 scripts/generate_class_diagram.py --check
- name: Spécification OpenAPI à jour (issue #209)
# Même filet de sécurité que le diagramme de classes ci-dessus :
# docs/openapi.yaml est dérivé du code de netcross_api, il doit donc
# être régénéré et commité dès qu'une route ou un modèle change.
env:
PYTHONPATH: src
run: uv run python scripts/generate_openapi.py --check
- name: Tests (pytest + couverture)
# --cov sans chemin : source lue depuis [tool.coverage.run] (source =
# ["src"]) dans pyproject.toml. term-missing dans les logs CI,
# coverage.xml publie comme artifact (issue #224). Seuil bloquant :
# fail_under dans [tool.coverage.report] (issue #246), l'etape echoue
# si la couverture totale passe dessous.
run: uv run pytest --cov --cov-report=term-missing --cov-report=xml
- name: Aucun test sauté silencieusement (issues #261/#262)
# Trace le nombre de tests sautés et échoue si la suite @requires_tshark
# l'est encore : un test sauté est une vérification qui n'a pas eu lieu,
# et le rapport doit le dire plutôt que de le laisser passer pour un
# succès (règle de traçabilité du projet).
run: |
set -o pipefail
uv run pytest -q -rs --no-header \
tests/test_export_filtered.py tests/test_adjust_timestamps.py \
| tee /tmp/reel.txt
if grep -q "tshark non installe\|editcap non installe" /tmp/reel.txt; then
echo "::error::des tests exigeant tshark/editcap ont été sautés alors que CI les installe"
exit 1
fi
echo "tests réels tshark/editcap : tous exécutés"
- name: Vérification réelle du contenu des PDF (pdftotext non sauté)
# Issue #218 : les tests de la section de sécurité du PDF réextraient
# le texte du fichier produit. Sans ce garde-fou, une disparition de
# poppler-utils de l'image CI rendrait ces tests « sautés » et la CI
# resterait verte en ayant perdu la seule vérification qui regarde le
# fichier livré à l'utilisateur.
run: |
set -o pipefail
uv run pytest -q -rs --no-header tests/test_security_outputs.py | tee /tmp/pdf.txt
if grep -q "pdftotext non installe" /tmp/pdf.txt; then
echo "::error::des tests vérifiant le contenu des PDF ont été sautés alors que CI installe poppler-utils"
exit 1
fi
echo "tests réels pdftotext : tous exécutés"
- name: Publication du rapport de couverture (artifact)
# coverage.xml (format Cobertura) produit par l'etape pytest --cov ;
# conserve 14 jours, temps de telechargement court.
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage.xml
retention-days: 14
if-no-files-found: warn
gtk4:
# Tests GTK4 réellement exécutés (issues #357, #363, #421).
# Le job Qualité n'installe ni pygobject ni libgtk-4 : tous les tests
# pilotés via pygobject y sont SAUTÉS -- c'est voulu (#285/#421 : aucun
# test n'exige GTK4 dans ce job). Mais un test sauté est une vérification
# qui n'a pas eu lieu (#261/#262) : sans ce job, les ~180 tests des lots
# de #421 ne tourneraient jamais en CI et pourraient régresser
# indéfiniment sous une CI verte (un test du lot 7 échouait déjà sous
# GTK4 tout en passant en CI). Ici : GTK4 + pygobject + serveur X
# virtuel (Xvfb), suite complète, et échec si un test GTK est sauté.
name: Tests GTK4 (Xvfb)
runs-on: ubuntu-latest
steps:
- name: Checkout du dépôt
uses: actions/checkout@v7
- name: GTK4, introspection, Xvfb, tshark, pdftotext
# libgirepository-2.0-dev + libcairo2-dev : compilation de
# pygobject/pycairo depuis les sources si aucune roue ne convient.
run: |
echo "wireshark-common wireshark-common/install-setuid boolean false" \
| sudo debconf-set-selections
sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
gir1.2-gtk-4.0 libgirepository-2.0-dev libcairo2-dev pkg-config \
xvfb xauth tshark poppler-utils gettext
- name: Installation de uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
- name: Installation de Python
run: uv python install 3.14
- name: Installation des dépendances (extras dev + api + ai, pygobject)
# pygobject n'est pas une dépendance du projet (la GUI utilise celui
# du système via le paquet) : installé ici dans le venv de test.
run: |
uv sync --extra dev --extra api --extra ai
uv pip install pygobject pycairo
- name: Tests sous Xvfb, aucun test GTK sauté
# Motifs de saut : tests/gtk4_display.py. -p no:cacheprovider :
# rien à conserver entre deux exécutions de ce job.
run: |
set -o pipefail
xvfb-run -a uv run pytest -q -rs --no-header -p no:cacheprovider \
--cov=netcross_gtk4 --cov-report=term --cov-fail-under=0 \
| tee /tmp/gtk4.txt
if grep -qE "pygobject absent|GTK4 absent|pas d'affichage pour GTK4" /tmp/gtk4.txt; then
echo "::error::des tests GTK4 ont été sautés alors que ce job installe GTK4 et Xvfb"
exit 1
fi
echo "tests GTK4 : tous exécutés"
types:
# Verification statique des types (issue #281).
# NON BLOQUANT pour l instant : continue-on-error = true.
# Deviendra bloquant des que la baseline atteint 0 sur les modules
# stricts (bascule : retirer continue-on-error + ajouter les modules
# dans [[tool.mypy.overrides]] de pyproject.toml).
name: Types (mypy)
runs-on: ubuntu-latest
steps:
- name: Checkout du dépôt
uses: actions/checkout@v7
- name: Installation de uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
- name: Installation de Python
run: uv python install 3.14
- name: Installation des dépendances (extras dev)
run: uv sync --extra dev
- name: Vérification des types (mypy)
run: uv run mypy
packaging:
# Issue #342 : la casse du .deb (#336, sous-paquets et pcap_parser non
# installes) est passee inapercue faute de job qui construise PUIS
# installe le paquet. Ce job teste le paquet tel que l'utilisateur le
# recoit : installation apt, --help de chaque lanceur, import de chaque
# module avec /usr/bin/python3, analyse reelle d'une capture.
name: Paquets (deb installé, rpm vérifié)
runs-on: ubuntu-latest
steps:
- name: Checkout du dépôt
uses: actions/checkout@v7
- name: Outils de construction (debhelper, rpm) et tshark
run: |
echo "wireshark-common wireshark-common/install-setuid boolean false" \
| sudo debconf-set-selections
sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
build-essential debhelper dpkg-dev gettext rpm tshark
- name: Construction du .deb
run: ./build-deb/build.sh
- name: Test de fumée du .deb installé
run: ./scripts/smoke-test-packages.sh deb build-deb/dist/netcross_*_all.deb
- name: Construction du .rpm
run: ./build-rpm/build.sh
- name: Vérification du contenu du .rpm
run: ./scripts/smoke-test-packages.sh rpm build-rpm/dist/netcross-*.noarch.rpm
- name: Publication des paquets (artifact)
if: always()
uses: actions/upload-artifact@v4
with:
name: paquets
path: |
build-deb/dist/*.deb
build-rpm/dist/*.rpm
retention-days: 7
if-no-files-found: warn
documentation:
# Ex docs.yml (issue #282). Check requis par la protection de dev :
# le nom du job doit rester « Construction (mkdocs build --strict) ».
# Pas de if: -- check_branch_protection.py --hors-ligne ignore les jobs
# conditionnels.
name: Construction (mkdocs build --strict)
runs-on: ubuntu-latest
steps:
- name: Checkout du dépôt
uses: actions/checkout@v7
- name: Installation de Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Installation de mkdocs-material
run: pip install mkdocs-material pymdown-extensions
- name: Construction (strict -- échoue sur lien mort)
run: mkdocs build --strict
- name: Upload de l'artefact (site HTML)
uses: actions/upload-artifact@v4
with:
name: mkdocs-site
path: site/
i18n:
# Ex i18n.yml check (issue #299). Vérifie que les catalogues de traduction
# gettext sont à jour avec les sources, valides et compilables.
# Non requis par la protection de dev : peut avoir un if: de filtre, mais
# les fichiers concernés (src/**/*.py, lang/**) couvrent la majeure partie
# du code, donc le job tourne sur toutes les PR/push.
name: i18n (catalogues à jour)
runs-on: ubuntu-latest
steps:
- name: Checkout du dépôt (historique complet pour le diff)
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Installation de Python
uses: actions/setup-python@v5
with:
python-version: "3.14"
- name: Installer gettext
run: |
sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq gettext
- name: Catalogues à jour et valides
id: sync
continue-on-error: ${{ github.event_name != 'pull_request' }}
run: ./scripts/i18n-update.sh --check
- name: Compilation de toutes les locales
run: ./scripts/i18n-update.sh --compile "$RUNNER_TEMP/locale"
- name: Résumé
if: always()
env:
BASE: ${{ github.event.pull_request.base.sha || github.event.before }}
run: |
since=()
if [ -n "$BASE" ] && git cat-file -e "$BASE^{commit}" 2>/dev/null; then since=(--since "$BASE"); fi
python3 scripts/i18n_report.py --compiled "$RUNNER_TEMP/locale" "${since[@]}"
python3 scripts/i18n_report.py --markdown --compiled "$RUNNER_TEMP/locale" "${since[@]}" >> "$GITHUB_STEP_SUMMARY"
python3 scripts/i18n_report.py --strict > /dev/null
- name: Catalogues désynchronisés
if: steps.sync.outcome == 'failure'
run: echo "::warning::catalogues à régénérer -- le job update ouvre la PR de mise à jour"