07.11 — CI#
Trois workflows :
main_ci.yml(rapide, lint + typecheck),dev_ci.yml(idem pour branches dev/feature/fix),e2e.yml(manuel, service Redis + Firefox).
Vue d’ensemble#
| Workflow | Trigger | Plateforme | Effet |
|---|---|---|---|
main_ci.yml | push/PR main | ubuntu + windows × py 3.14 | make check-coding-style (mypy + ruff). Pas de browser. |
dev_ci.yml | push dev / feature/_ / fix/_ | ubuntu × py 3.14 | id., mais Ubuntu seul |
e2e.yml | workflow_dispatch (manuel) | ubuntu + service Redis + Firefox + geckodriver | Run complet de la suite e2e. Upload .screenshots/, .ocarina_logs/, .reports/. |
main_ci.yml#
name: Main branch CI
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
defaults:
run:
shell: bash
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ["3.14"]
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with: { python-version: "3.14" }
- uses: actions/cache@v5
with:
path: .venv
key: venv-${{ runner.os }}-py3.14-${{ hashFiles('pyproject.toml') }}
- name: Install
run: make install-on-ci
- name: Check coding style
run: |
. .venv/bin/activate
make check-coding-style- Matrice OS : ubuntu + windows. Vérifie la portabilité Python du code projet.
- Pas de browser : on lance juste
make check-coding-style(=mypy + ruff). Rapide, pas besoin de Selenium / Redis / OTP. - Cache
.venv: reuse entre runs.
dev_ci.yml#
on:
push:
branches: [dev, "feature/**", "fix/**"]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
# … identique à main_ci.yml, juste Ubuntu seul …Identique au main_ci.yml mais Ubuntu seul (Windows ne run que sur main).
e2e.yml#
name: e2e CI
on:
workflow_dispatch:
jobs:
e2e:
runs-on: ubuntu-latest
environment: OC # ← env GitHub qui contient IGOR_API_KEY
services:
redis:
image: redis:8.8.0
ports: [6379:6379]
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v6
- uses: actions/setup-python@v6
with: { python-version: 3.14 }
- uses: actions/cache@v5
with:
path: .venv
key: venv-${{ runner.os }}-py-${{ hashFiles('pyproject.toml') }}
- name: Install geckodriver
run: |
GECKO_VERSION=0.35.0
wget https://github.com/mozilla/geckodriver/releases/download/v$GECKO_VERSION/geckodriver-v$GECKO_VERSION-linux64.tar.gz
tar -xvzf geckodriver-v$GECKO_VERSION-linux64.tar.gz
chmod +x geckodriver
- name: Setup Firefox
uses: browser-actions/setup-firefox@...
- name: Install project + ocarina
run: |
make install-on-ci
- name: Run e2e cycle
env:
IGOR_API_KEY: ${{ secrets.IGOR_API_KEY }}
DASH_USERNAME: ${{ secrets.DASH_USERNAME }}
DASH_PASSWORD: ${{ secrets.DASH_PASSWORD }}
REDIS_URL: redis://localhost:6379
run: |
. .venv/bin/activate
python -u src/main.py --driver-path ./geckodriver --browser firefox --workers 3
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-traces
path: |
.screenshots/
.ocarina_logs/
.reports/Flot#
1. services.redis#
services:
redis:
image: redis:8.8.0
ports: [6379:6379]
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
...GitHub Actions lance un container Redis en sidecar.
Accessible sur localhost:6379.
Healthcheck redis-cli ping.
2. environment: OC#
environment: OC→ Le workflow est lié à un GitHub Environment nommé OC.
Cet environment :
- Contient les
secrets(IGOR_API_KEY,DASH_USERNAME,DASH_PASSWORD). - Peut être configuré pour exiger une approbation manuelle avant de tourner (utile pour les workflows qui consomment des quotas).
3. Install geckodriver#
- name: Install geckodriver
run: |
GECKO_VERSION=0.35.0
wget https://github.com/mozilla/geckodriver/releases/download/v$GECKO_VERSION/geckodriver-v$GECKO_VERSION-linux64.tar.gz
tar -xvzf geckodriver-v$GECKO_VERSION-linux64.tar.gz
chmod +x geckodriver4. Setup Firefox#
- uses: browser-actions/setup-firefox@<sha>→ Installe Firefox matchant geckodriver (compatibilité versions).
5. Run e2e cycle#
python -u src/main.py --driver-path ./geckodriver --browser firefox --workers 3-u: unbuffered stdout (logs en temps réel).--workers 3: 3 navigateurs en parallèle.--driver-path ./geckodriver: chemin relatif depuis la racine.--browser firefox.
Note : --logger n’est pas explicite ; le default est terminal+file.
6. Env vars#
env:
IGOR_API_KEY: ${{ secrets.IGOR_API_KEY }}
DASH_USERNAME: ${{ secrets.DASH_USERNAME }}
DASH_PASSWORD: ${{ secrets.DASH_PASSWORD }}
REDIS_URL: redis://localhost:6379IGOR_API_KEY ≡ API_SECRET (cf. ../06-tests-workers/). REDIS_URL pointe le sidecar.
7. Upload artifacts#
- name: Upload artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-traces
path: |
.screenshots/
.ocarina_logs/
.reports/if: always() : même si le run fail, on upload. Permet d’analyser pourquoi ça a fail.
.screenshots/: tous les screenshots pris..ocarina_logs/: arbre de logs (campaigns/suites/tests)..reports/: sortie des plugins DOCX + JSON.
workflow_dispatch#
Pourquoi seulement workflow_dispatch (lancement tests e2e uniquement en manuel) ?
- Coût : un run e2e prend plusieurs minutes, démarre 3 browsers, fait des centaines de requêtes vers l’Igoristan + tests-workers.
- Quotas Vercel : les appels
tests-workersconsomment du quota. - Stabilité : un run e2e peut échouer pour des raisons hors projet (Vercel down, GitHub Pages down, etc.). Pas envie de polluer la CI sur chaque PR.
Exemple de frise chronologique#
0:00 Trigger workflow_dispatch
0:00 Lock environment "OC" (1 run à la fois)
0:00 Spawn Redis sidecar container
0:00 Checkout
0:30 Setup Python 3.14
0:45 Cache restore .venv (hit ou miss)
1:30 pip install requirements + ocarina (si miss)
2:00 Download + install geckodriver 0.35.0
2:30 Setup Firefox
3:00 Warmup Redis client
3:00 ──── Cycle e2e démarre ────
3:00 Smoke campaigns (global + corsicamon)
4:00 Main campaigns :
- Dashboard login (3 suites, ~10 tests)
- Randomness (1 suite, 6 tests)
- Sacred upload (2 suites, ~4 tests)
- Corsicamon (2 suites, ~6 tests)
8:00 ──── Cycle e2e termine ────
8:00 Plugins post-exec (DOCX + JSON en parallèle)
8:30 pretty_print_results + sys.exit
8:30 Upload artifacts (screenshots, logs, reports)
9:00 Done.