Suivi de candidatures — application web Django pour gérer le cycle de candidature (envois, relances, entretiens, statistiques).
Le mode d'exécution recommandé est le conteneur Docker : image de production (gunicorn + statiques servis par WhiteNoise), migrations et seed des sites appliqués automatiquement au démarrage.
Toute la configuration passe par un fichier .env (jamais commité). Partir du
modèle fourni :
cp .env.example .envPuis renseigner les valeurs :
| Variable | Rôle |
|---|---|
SECRET_KEY |
Clé secrète Django — en générer une fraîche pour tout déploiement réel |
DEBUG |
False en production |
ALLOWED_HOSTS |
Hôtes autorisés (liste séparée par des virgules), requis si DEBUG=False |
CANDITRACK_FERNET_KEY |
Clé de chiffrement des mots de passe des sites (obligatoire) |
CANDITRACK_API_TOKEN |
Jeton partagé pour l'extension Chrome (issue #2) |
SQLITE_PATH |
Laisser vide : docker-compose le pointe vers le volume persistant |
Générer la clé Fernet :
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"…et un jeton pour l'extension :
python -c "import secrets; print(secrets.token_urlsafe(32))"docker compose up -d --buildL'entrypoint applique les migrations (dont le seed des sites) et collecte les
statiques au démarrage. La base SQLite et les CV uploadés sont persistés dans
des volumes nommés (data, media), donc préservés entre les redémarrages.
L'application écoute sur le port 53487 → http://127.0.0.1:53487/
docker-compose.yml pointe SQLITE_PATH vers /app/data/db.sqlite3 (volume
data) ; il n'y a donc rien à renseigner pour cette variable dans .env.
Sur la machine cible (ex. Raspberry Pi), inutile de cloner les sources ni de
construire l'image : docker-compose.deploy.yml tire directement l'image
publiée plenoir/canditrack:latest.
cp .env.example .env # renseigner SECRET_KEY, CANDITRACK_FERNET_KEY,
# DEBUG=False et ALLOWED_HOSTS
docker compose -f docker-compose.deploy.yml pull
docker compose -f docker-compose.deploy.yml up -dMise à jour : relancer pull puis up -d (pull_policy: always récupère le
dernier latest). Mêmes volumes persistants (data, media) et port 53487
que le compose de build.
Sur ARM (Raspberry Pi), l'image tirée doit avoir été construite pour
linux/arm64— la CI doit publier en multi-arch, sinon construire sur place avecdocker-compose.yml.
docker build -t canditrack .
docker run -d -p 53487:53487 --env-file .env \
-e SQLITE_PATH=/app/data/db.sqlite3 \
-v canditrack-data:/app/data -v canditrack-media:/app/media canditrackLe workflow .github/workflows/docker-publish.yml publie l'image sur Docker Hub
à la fermeture d'un milestone : le titre du milestone (ex. 1.0.0) sert de
version. Le workflow rattache au passage les issues fermées sans milestone à
celui-ci, pousse l'image taguée latest et <version>, puis crée une
release GitHub du nom du milestone listant les issues traitées (l'archive
source est jointe automatiquement). L'historique des versions est aussi tenu
dans CHANGELOG.md.
Configuration unique — Settings → Secrets and variables → Actions :
| Secret | Valeur |
|---|---|
DOCKERHUB_USERNAME |
identifiant Docker Hub (= namespace de l'image …/canditrack) |
DOCKERHUB_TOKEN |
access token Docker Hub (Account → Security → New Access Token) |
Le workflow .github/workflows/sonarqube.yml lance la suite de tests avec
mesure de couverture (coverage.xml) puis l'analyse statique SonarQube Cloud
(sonarcloud.io) à chaque push sur main, sur les pull
requests et manuellement. La configuration de l'analyse (clé de projet,
organisation, exclusions, chemin du rapport de couverture) est dans
sonar-project.properties.
Configuration unique :
- Importer le dépôt sur SonarQube Cloud (organisation
lenoirpatrick, clé de projetlenoirpatrick_CandiTrack). - Désactiver Automatic Analysis côté SonarCloud (l'analyse est pilotée par la CI).
Settings → Secrets and variables → Actions→ ajouter le secret :
| Secret | Valeur |
|---|---|
SONAR_TOKEN |
jeton SonarCloud (My Account → Security → Generate Tokens) |
python -m venv .venv
# Windows
.venv\Scripts\activate
# Linux/macOS
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # renseigner au minimum CANDITRACK_FERNET_KEY
python manage.py migrate
python manage.py runserverPuis ouvrir http://127.0.0.1:8000/ (port par défaut du serveur de développement).
Le fichier .env, la base db.sqlite3, les dossiers media/ et staticfiles/
sont ignorés par Git.
L'extension du dossier chrome-extension/ permet d'ajouter l'offre de la page
courante à CandiTrack en un clic.
- Renseigner
CANDITRACK_API_TOKENdans.env(voir tableau ci-dessus) puis (re)lancer l'application. - Dans Chrome :
chrome://extensions→ activer le mode développeur → Charger l'extension non empaquetée → choisir le dossierchrome-extension/. - Ouvrir les options de l'extension : renseigner l'URL du backend et coller le jeton.
- Sur une page d'offre, cliquer l'icône CandiTrack : l'entreprise et l'URL sont pré-remplies (via les métadonnées JobPosting / Open Graph de la page), puis Ajouter. Le plugin ne renseigne pas le poste ni la date d'envoi (à compléter ensuite dans CandiTrack).
L'extension appelle POST /api/candidatures/ en envoyant le jeton dans l'en-tête
X-Api-Token. L'URL du backend et le jeton se configurent dans les options de
l'extension ; l'hôte doit figurer dans les host_permissions du manifest.json.
CandiTrack peut générer un coaching et des mails de relance via l'IA, au choix avec Google Gemini, Mistral AI, OpenAI (ChatGPT), Anthropic (Claude) ou Perplexity. La fonctionnalité est désactivée par défaut : chacun renseigne sa propre clé API.
- Obtenir une clé chez le fournisseur voulu (le lien est rappelé dans Options → IA, à côté des infos de quota du tier gratuit).
- Dans Options → IA, choisir le fournisseur et coller la clé (et, facultativement, le modèle dans le menu déroulant). Chaque fournisseur garde sa propre clé, son modèle et sa limite, stockés chiffrés en base (Fernet) ; on bascule de l'un à l'autre sans ressaisie.
- Depuis la liste des candidatures, « ✨ Coaching IA » ouvre une fenêtre modale : à partir du dernier CV chargé (analysé par Gemini) et des statistiques (volume, motifs de refus, délais…), l'IA propose un positionnement et des actions à réaliser.
- Sur une candidature, « ✉️ Mail de relance (IA) » génère un brouillon de mail de relance, régénérable à volonté.
Quotas (issue #36). Chaque appel journalise les tokens consommés. Dans Options → IA, la consommation du mois courant (appels + tokens) s'affiche par fournisseur, et une limite mensuelle de tokens est configurable (0 = illimitée) : lorsqu'elle est atteinte, un avertissement s'affiche sans bloquer l'appel.
Les appels se font en HTTP direct vers l'API du fournisseur choisi (aucune dépendance ajoutée). La clé ne sert qu'aux appels sortants ; vos crédits, vos données.
| URL | Rôle |
|---|---|
/ (/candidatures/) |
Liste des candidatures (créer / modifier / consulter) |
/sites/ |
Sites d'emploi : ajout, modification, suppression, logo (#366) |
/stats/ |
Statistiques (#367 — premiers KPI) |
/cv/ |
CV : chargement, analyse IA des informations principales et suppression (#368, #44) |
/aide/ |
Options : apparence (thème), jetons de l'extension Chrome et configuration du coaching IA (#33) |
- #367 : KPI complets (taux de réponse par source, délais moyens, graphes)
- #368 : reformatage du CV (technique/pro) + import LinkedIn
- #365 : intégration API France Travail, rappels actifs et notifications
L'analyse IA du CV (extraction des informations principales) est disponible depuis l'issue #44.