354 lines
18 KiB
YAML
354 lines
18 KiB
YAML
|
|
j'ai gitea + sonarqube auto hébger tu me conseiler quoi en plus pour analyser le code php
|
|
|
|
13:35
|
|
Bonne question ! Avec Gitea + SonarQube déjà en place, voici ce que je te recommanderais pour compléter ta chaîne d'analyse PHP :
|
|
|
|
Analyse statique complémentaire — Tu utilises déjà PHPStan via SonarQube, mais le lancer aussi en standalone (niveau max) te donne un feedback plus rapide dans ta CI. Psalm est une alternative/complément intéressant, surtout pour l'analyse de type et la détection de dead code. Les deux peuvent coexister.
|
|
|
|
Style & standards — PHP CS Fixer ou PHP_CodeSniffer pour enforcer un coding standard (PSR-12 ou custom). PHP CS Fixer s'intègre bien dans un pre-commit hook ou un job CI Gitea Actions/Drone.
|
|
|
|
Sécurité — Snyk ou Trivy pour scanner les dépendances Composer (CVE). Trivy est self-hostable et peut aussi scanner tes images Docker, ce qui colle bien avec ton stack. Semgrep est aussi un bon choix pour des règles de sécurité custom sur le code PHP (OWASP patterns, injections SQL, XSS).
|
|
|
|
Complexité & dette technique — PHPMetrics génère des rapports HTML visuels sur la complexité cyclomatique, le couplage, la maintenabilité. Ça complète bien SonarQube avec une vue plus "architecturale". dePHPend analyse les dépendances entre classes/packages pour détecter les couplages problématiques.
|
|
|
|
Tests & couverture — Si pas déjà en place, PHPUnit + Infection (mutation testing) pour mesurer la qualité réelle de tes tests, pas juste le coverage brut. SonarQube peut ingérer les rapports de coverage PHPUnit.
|
|
|
|
En priorité pour ton contexte (multi-tenant, ~85 sites ESY-WEB), je partirais sur :
|
|
|
|
PHPStan niveau max en CI (si pas déjà fait en standalone)
|
|
Trivy (scan dépendances Composer + images Docker — tu as déjà le stack Docker)
|
|
PHP CS Fixer en pre-commit
|
|
PHPMetrics pour le reporting visuel
|
|
Tout ça s'orchestre bien avec des Gitea Actions ou un pipeline Makefile, ce qui colle avec ton workflow habituel. Tu veux que je t'aide à mettre en place un de ces outils en particulier ?
|
|
|
|
|
|
name: CI on: push: branches: - master - main pull_request: jobs: sonarqube: runs_on: ubuntu-latest services: database: image: postgres:16-alpine env: POSTGRES_USER: app POSTGRES_PASSWORD: secret POS
|
|
|
|
pasted
|
|
|
|
j'ai deja tout sa
|
|
|
|
13:36
|
|
Ah ok, t'es déjà bien équipé ! Ton pipeline est solide. Voici ce qui manque et qui aurait une vraie valeur ajoutée :
|
|
|
|
Sécurité applicative — Semgrep pour de l'analyse SAST orientée patterns PHP (injections SQL, XSS, SSRF, deserialize unsafe). OWASP Dependency-Check couvre les dépendances, mais pas le code lui-même. Semgrep est gratuit en CLI et s'ajoute en une step.
|
|
|
|
Qualité / dette — PHPMetrics pour un rapport HTML visuel (complexité cyclomatique, couplage, maintenabilité par classe). SonarQube donne des métriques mais PHPMetrics a une vue "bubble chart" par classe qui aide à prioriser le refacto. Très rapide à ajouter, pas besoin de services.
|
|
|
|
Tests — Infection (mutation testing). Tu as déjà PHPUnit + coverage, mais le coverage seul ne dit pas si tes tests détectent vraiment les régressions. Infection mute ton code et vérifie que les tests cassent. Ça s'intègre bien avec le coverage.xml que tu génères déjà.
|
|
|
|
Infra/Docker — Trivy en remplacement ou complément de Hadolint. Hadolint lint les Dockerfiles, Trivy scanne les images buildées (CVE dans les packages OS + dépendances). Vu ton stack multi-container c'est pertinent.
|
|
|
|
Frontend — Lighthouse CI si tu as des pages publiques côté E-Cosplay. Perf, accessibilité, SEO en une step.
|
|
|
|
En résumé les ajouts concrets :
|
|
|
|
yaml
|
|
- name: Semgrep SAST
|
|
run: |
|
|
pip install semgrep --break-system-packages
|
|
semgrep scan --config=auto --json -o semgrep-report.json src/ || true
|
|
|
|
- name: PHPMetrics
|
|
run: |
|
|
composer global require phpmetrics/phpmetrics --no-interaction
|
|
phpmetrics --report-html=phpmetrics-report src/
|
|
|
|
- name: Infection (mutation testing)
|
|
run: |
|
|
vendor/bin/infection --threads=4 --min-msi=50 --min-covered-msi=60 --logger-json=infection-report.json || true
|
|
Semgrep est le plus impactant vu que t'as zéro SAST sur le code source actuellement — OWASP DC ne couvre que les dépendances. Tu veux que je t'intègre ça proprement dans ton workflow complet ?
|
|
|
|
|
|
name: CI on: push: branches: - master - main pull_request: jobs: sonarqube: runs_on: ubuntu-latest services: database: image: postgres:16-alpine env: POSTGRES_USER: app POSTGRES_PASSWORD: secret POS
|
|
|
|
pasted
|
|
|
|
13:37
|
|
Nickel, t'as intégré les trois. Ton pipeline est maintenant très complet. Quelques remarques d'optimisation :
|
|
|
|
Problème potentiel avec Infection — il a besoin du coverage.xml généré par PHPUnit, mais il faut lui passer explicitement. Vérifie que ton infection.json5 pointe bien dessus, sinon ajoute --coverage=coverage.xml ou mieux, utilise le flag --skip-initial-tests si tu veux qu'il réutilise le coverage existant.
|
|
|
|
PHPMetrics — composer global require peut être lent en CI. Une alternative plus rapide :
|
|
|
|
yaml
|
|
- name: PHPMetrics
|
|
run: |
|
|
wget -qO phpmetrics.phar https://github.com/phpmetrics/PhpMetrics/releases/latest/download/phpmetrics.phar
|
|
php phpmetrics.phar --report-html=phpmetrics-report src/
|
|
Semgrep — pip install en CI c'est aussi un peu lent. L'image Docker officielle est plus rapide :
|
|
|
|
yaml
|
|
- name: Semgrep SAST
|
|
run: |
|
|
docker run --rm -v "${GITHUB_WORKSPACE}:/src" semgrep/semgrep semgrep scan --config=auto --json -o /src/semgrep-report.json /src/src/ || true
|
|
Mais vu que t'es sur Gitea Actions (pas GitHub), vérifie que le Docker-in-Docker fonctionne dans ton runner. Sinon le pip install reste le plus safe.
|
|
|
|
Ce qui manque pour boucler — tous ces rapports (semgrep, phpmetrics, infection, hadolint) sont générés mais pas exploités. Deux options :
|
|
|
|
SonarQube — configure sonar.externalIssuesReportPaths dans ton sonar-project.properties pour ingérer les JSON de Semgrep et Hadolint. SonarQube les affichera comme "external issues".
|
|
Artifacts — upload les rapports comme artifacts de build pour les consulter après :
|
|
yaml
|
|
- name: Upload reports
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: ci-reports
|
|
path: |
|
|
semgrep-report.json
|
|
phpmetrics-report/
|
|
infection-report.json
|
|
hadolint-*.json
|
|
dependency-check-report.*
|
|
eslint-report.json
|
|
phpstan-report.json
|
|
Ça te permettrait de consulter le rapport PHPMetrics HTML directement. Tu veux que je te génère le sonar-project.properties adapté avec l'import des rapports externes ?
|
|
|
|
|
|
name: CI on: push: branches: - master - main pull_request: jobs: sonarqube: runs_on: ubuntu-latest services: database: image: postgres:16-alpine env: POSTGRES_USER: app POSTGRES_PASSWORD: secret POS
|
|
|
|
pasted
|
|
|
|
13:38
|
|
OK, quelques corrections à faire sur ton workflow actuel :
|
|
|
|
PHPMetrics — tu mélanges les deux approches. Tu fais composer global require mais ensuite php phpmetrics.phar (qui n'existe pas puisque t'as pas téléchargé le phar). Choisis l'un ou l'autre :
|
|
|
|
yaml
|
|
# Option A : phar (plus rapide)
|
|
- name: PHPMetrics
|
|
run: |
|
|
wget -qO phpmetrics.phar https://github.com/phpmetrics/PhpMetrics/releases/latest/download/phpmetrics.phar
|
|
php phpmetrics.phar --report-html=phpmetrics-report src/
|
|
|
|
# Option B : composer global
|
|
- name: PHPMetrics
|
|
run: |
|
|
composer global require phpmetrics/phpmetrics --no-interaction
|
|
~/.composer/vendor/bin/phpmetrics --report-html=phpmetrics-report src/
|
|
Semgrep Docker — attention, sur Gitea Actions le ${GITHUB_WORKSPACE} n'existe probablement pas. Selon ton runner Gitea, ça sera plutôt ${GITEA_WORKSPACE} ou ${{ github.workspace }} (si ton runner est compatible). Vérifie, sinon reviens au pip install qui est plus portable :
|
|
|
|
yaml
|
|
- name: Semgrep SAST
|
|
run: |
|
|
pip install semgrep --break-system-packages
|
|
semgrep scan --config=auto --json -o semgrep-report.json src/ || true
|
|
Upload des artifacts + sonar-project.properties — tu veux que je te génère les deux fichiers ? Le sonar-project.properties avec l'import de tous tes rapports externes (Semgrep, PHPStan, ESLint, Hadolint, coverage), et la step d'upload artifacts à ajouter en fin de pipeline ?
|
|
|
|
sort tout le workflow stp
|
|
|
|
13:38
|
|
Voici le workflow complet corrigé :
|
|
|
|
|
|
Presenting files
|
|
Presenting files
|
|
|
|
Workflow CI complet corrigé avec tous les outils d'analyse
|
|
ci.yml
|
|
|
|
sonar-project.properties avec import de tous les rapports externes
|
|
sonar-project.properties
|
|
|
|
Presenting file(s)...
|
|
|
|
|
|
|
|
Claude est une IA et peut faire des erreurs. Veuillez vérifier les réponses.
|
|
Ci · YML
|
|
Copier
|
|
|
|
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
- main
|
|
pull_request:
|
|
|
|
jobs:
|
|
ci:
|
|
runs_on: ubuntu-latest
|
|
services:
|
|
database:
|
|
image: postgres:16-alpine
|
|
env:
|
|
POSTGRES_USER: app
|
|
POSTGRES_PASSWORD: secret
|
|
POSTGRES_DB: crm_ecosplay
|
|
options: >-
|
|
--health-cmd "pg_isready -U app -d crm_ecosplay"
|
|
--health-interval 5s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
redis:
|
|
image: redis:7-alpine
|
|
options: >-
|
|
--health-cmd "redis-cli ping"
|
|
--health-interval 5s
|
|
--health-timeout 5s
|
|
--health-retries 5
|
|
meilisearch:
|
|
image: getmeili/meilisearch:latest
|
|
env:
|
|
MEILI_MASTER_KEY: test
|
|
MEILI_ENV: development
|
|
env:
|
|
DATABASE_URL: "postgresql://app:secret@database:5432/crm_ecosplay?serverVersion=16&charset=utf8"
|
|
MESSENGER_TRANSPORT_DSN: "redis://redis:6379/messages"
|
|
MAILER_DSN: "null://null"
|
|
MEILISEARCH_URL: "http://meilisearch:7700"
|
|
MEILISEARCH_API_KEY: "test"
|
|
APP_ENV: test
|
|
|
|
steps:
|
|
# ─── Setup ───────────────────────────────────────────────
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Setup PHP
|
|
uses: shivammathur/setup-php@v2
|
|
with:
|
|
php-version: '8.4'
|
|
extensions: intl, pdo_pgsql, zip, gd, redis, imagick
|
|
coverage: xdebug
|
|
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@v3
|
|
with:
|
|
node-version: '22'
|
|
|
|
- name: Setup Bun
|
|
uses: oven-sh/setup-bun@v1
|
|
|
|
# ─── Dependencies ────────────────────────────────────────
|
|
- name: Install PHP dependencies
|
|
run: composer install --no-interaction --prefer-dist
|
|
|
|
- name: Install JS dependencies
|
|
run: |
|
|
bun install
|
|
npm install
|
|
|
|
# ─── Security audits ─────────────────────────────────────
|
|
- name: Composer security audit
|
|
run: composer audit
|
|
|
|
# ─── Linting ─────────────────────────────────────────────
|
|
- name: Lint Twig
|
|
run: php bin/console lint:twig templates/
|
|
|
|
- name: Lint YAML
|
|
run: php bin/console lint:yaml config/
|
|
|
|
- name: Lint Container
|
|
run: php bin/console lint:container
|
|
|
|
- name: PHP CS Fixer
|
|
run: vendor/bin/php-cs-fixer fix --dry-run --diff
|
|
|
|
- name: ESLint report
|
|
run: bunx eslint assets/ --ext .js,.ts -f json -o eslint-report.json || true
|
|
|
|
- name: Stylelint
|
|
run: bunx stylelint "assets/**/*.scss"
|
|
|
|
# ─── Static analysis ─────────────────────────────────────
|
|
- name: PHPStan report
|
|
run: vendor/bin/phpstan analyse src/ --level=6 --no-progress --error-format=json > phpstan-report.json || true
|
|
|
|
- name: Semgrep SAST
|
|
run: |
|
|
pip install semgrep --break-system-packages
|
|
semgrep scan --config=auto --json -o semgrep-report.json src/ || true
|
|
|
|
# ─── Build ───────────────────────────────────────────────
|
|
- name: Build assets
|
|
run: bun run build
|
|
|
|
# ─── Tests ───────────────────────────────────────────────
|
|
- name: JS tests with coverage
|
|
run: bun run test:coverage
|
|
|
|
- name: Create test database
|
|
run: php bin/console doctrine:database:create --env=test --if-not-exists
|
|
|
|
- name: Create database schema
|
|
run: php bin/console doctrine:schema:create --env=test
|
|
|
|
- name: PHPUnit with coverage
|
|
run: vendor/bin/phpunit --testdox --coverage-clover coverage.xml --coverage-text
|
|
|
|
- name: Infection (mutation testing)
|
|
run: |
|
|
vendor/bin/infection \
|
|
--threads=4 \
|
|
--skip-initial-tests \
|
|
--coverage=. \
|
|
--min-msi=50 \
|
|
--min-covered-msi=60 \
|
|
--logger-json=infection-report.json || true
|
|
|
|
# ─── Metrics ─────────────────────────────────────────────
|
|
- name: PHPMetrics
|
|
run: |
|
|
wget -qO phpmetrics.phar https://github.com/phpmetrics/PhpMetrics/releases/latest/download/phpmetrics.phar
|
|
php phpmetrics.phar --report-html=phpmetrics-report src/
|
|
|
|
# ─── Docker linting ──────────────────────────────────────
|
|
- name: Hadolint
|
|
run: |
|
|
wget -qO hadolint https://github.com/hadolint/hadolint/releases/latest/download/hadolint-Linux-x86_64
|
|
chmod +x hadolint
|
|
./hadolint docker/php/dev/Dockerfile -f json > hadolint-dev.json || true
|
|
./hadolint docker/php/prod/Dockerfile -f json > hadolint-prod.json || true
|
|
|
|
# ─── Dependency vulnerability scan ───────────────────────
|
|
- name: OWASP Dependency-Check
|
|
uses: dependency-check/Dependency-Check_Action@main
|
|
with:
|
|
project: 'crm-ecosplay'
|
|
path: '.'
|
|
format: 'JSON,HTML'
|
|
args: >
|
|
--scan composer.lock
|
|
--scan package.json
|
|
--out .
|
|
--disableAssembly
|
|
--nvdApiKey ${{ secrets.NVD_API_KEY }}
|
|
continue-on-error: true
|
|
|
|
- name: Rename Dependency-Check reports
|
|
run: |
|
|
mv dependency-check-report.json dc-report.json 2>/dev/null || true
|
|
mv dependency-check-report.html dc-report.html 2>/dev/null || true
|
|
|
|
# ─── SonarQube ───────────────────────────────────────────
|
|
- name: SonarQube Scan
|
|
uses: sonarsource/sonarqube-scan-action@v5
|
|
env:
|
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
|
SONAR_HOST_URL: https://sn.esy-web.dev
|
|
|
|
# ─── Upload reports ──────────────────────────────────────
|
|
- name: Upload CI reports
|
|
uses: actions/upload-artifact@v3
|
|
if: always()
|
|
with:
|
|
name: ci-reports
|
|
retention-days: 30
|
|
path: |
|
|
coverage.xml
|
|
phpstan-report.json
|
|
eslint-report.json
|
|
semgrep-report.json
|
|
infection-report.json
|
|
hadolint-dev.json
|
|
hadolint-prod.json
|
|
dc-report.*
|
|
phpmetrics-report/
|
|
|