QUA-002, seconde moitie. Le depot etant formate, l elargissement porte sur
des defauts et non sur du brassage.
Ajoute a la selection : B (bugbear), C4, RET, SIM, UP. Le lot entier n a
produit que 24 signalements sur 76 fichiers -- le code etait plus propre
que l audit ne le craignait. Neuf corriges automatiquement, quinze a la
main.
SIM108 est ignore : forcer un ternaire se lit moins bien que le if/else
qu il remplace, au seul endroit ou il se declenche.
isort (I) n est PAS active. Il reordonnerait les imports de 48 fichiers,
soit une seconde passe de pur brassage juste apres le commit de formatage.
A faire, mais seul.
Deux vrais defauts trouves par les nouvelles regles
- team_matches.edit_match faisait `except ValueError: pass` sur l heure de
debut et l heure de fin, trois lignes sous un champ date qui, lui,
signale et redirige. Une heure mal saisie etait donc acceptee par le
formulaire, jetee, l ancienne valeur conservee -- et la page annoncait
la reussite. Meme traitement que la date desormais.
- backup.py levait BackupError depuis deux blocs `except` sans `from`,
ce qui perdait la cause d origine dans la trace.
Ainsi que : un `return` explicite dans force_https, `%`-formatage remplace
dans log_auth_event (operations de chaine avant journalisation, pas des
gabarits de logger -- la redaction n est pas affectee), une compréhension
inutile, un `set(...)` en compréhension d ensemble, `open(..., 'r')`, une
variable de boucle inutilisee, et `contextlib.suppress` dans conftest.
CI : `ruff format --check` remplace le commentaire qui expliquait pourquoi
il etait absent.
263 tests passent. Les deux nouveaux messages sont traduits ; attention,
pybabel les avait apparies en `fuzzy` avec des entrees « date » existantes,
et une entree fuzzy est ignoree a l execution.
Co-Authored-By: Claude Opus 5 <[email protected]>
116 lines
3.5 KiB
YAML
116 lines
3.5 KiB
YAML
name: CI - Security & Lint
|
|
|
|
on:
|
|
push:
|
|
branches: [main, master]
|
|
pull_request:
|
|
branches: [main, master]
|
|
workflow_dispatch: # Allow manual triggers
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
# Least privilege: nothing here writes back to the repository.
|
|
permissions:
|
|
contents: read
|
|
|
|
env:
|
|
PYTHON_VERSION: '3.12'
|
|
|
|
jobs:
|
|
security-audit:
|
|
name: Security Audit
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
cache: 'pip'
|
|
|
|
- name: Install pip-audit
|
|
run: pip install pip-audit==2.9.0
|
|
|
|
# Previously: `pip-audit --require-hashes --no-deps || pip-audit`.
|
|
# Neither form named the requirements file, so the fallback audited the
|
|
# runner's environment — which contained pip-audit and nothing else.
|
|
# The job passed green while checking none of the application's
|
|
# dependencies. -r makes it audit what the application actually pins.
|
|
- name: Scan declared dependencies for known vulnerabilities
|
|
run: pip-audit -r requirements.txt
|
|
|
|
lint:
|
|
name: Lint with Ruff
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
|
|
- name: Install ruff
|
|
run: pip install ruff==0.14.4
|
|
|
|
# Rule selection and per-file ignores live in pyproject.toml. Before it
|
|
# existed, this step ran ruff's bare defaults with no configuration.
|
|
- name: Run ruff linter
|
|
run: ruff check . --output-format=github
|
|
|
|
# Enabled now that the repository has been formatted once, in its own
|
|
# commit (QUA-002). Reaching this step before that would have failed on
|
|
# 72 of 76 files for reasons unrelated to correctness.
|
|
- name: Check formatting
|
|
run: ruff format --check .
|
|
|
|
security-scan:
|
|
name: Security Scan
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
cache: 'pip'
|
|
|
|
- name: Install app dependencies
|
|
run: pip install -r requirements.txt -r requirements-dev.txt
|
|
|
|
# The path was `security_scan.py`, but the script lives under
|
|
# app/supporting_scripts/. The step had therefore failed on every run
|
|
# since the file was moved.
|
|
- name: Run security scan
|
|
env:
|
|
SECRET_KEY: ${{ secrets.CI_SECRET_KEY || 'test-key-not-for-production-1234567890' }}
|
|
FLASK_DEBUG: 'false'
|
|
run: python app/supporting_scripts/security_scan.py --skip-http
|
|
|
|
test:
|
|
name: Tests
|
|
runs-on: ubuntu-latest
|
|
needs: [security-audit, lint]
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: ${{ env.PYTHON_VERSION }}
|
|
cache: 'pip'
|
|
|
|
- name: Install dependencies
|
|
run: pip install -r requirements.txt -r requirements-dev.txt
|
|
|
|
# Previously an `echo` guarded by continue-on-error: the job reported
|
|
# success without executing anything. The suite needs no environment
|
|
# variables and no database server: create_app() takes its configuration
|
|
# as an argument and the fixtures use a temporary SQLite file.
|
|
- name: Run tests
|
|
run: pytest --cov=app --cov-report=term-missing --cov-report=xml
|