Fichiers joints aux specs et raffinages (stockage local/S3) #9
No reviewers
Labels
No labels
breaking
bug
ci
dependencies
documentation
feature
security
skip-changelog
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
thierryade/backend!9
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/attachments"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #8
Contenu
StoredFile(un fichier physique par projet, dédupliqué sur son SHA-256, immuable) etAttachment(lien vers une version de spec ou un raffinage, avec un nom propre au lien).Spec.reopen()recopie les liens (pas les fichiers) vers le nouveau brouillon.inherited/replaced/new/deleted(entrée fantôme sansid, restaurable),renamed_fromsi le même fichier existait sous un autre nom. Raffinages : comparaison avec le raffinage de la version N-1 de la spec parente vers la même place enfant.exists_in_specs,exists_in_refinements,exists_in_versions(spec).GET /api/attachments/?spec_version=ou?refinement=: liste avec statuts (+exists_in_versionspour une version).POST /api/attachments/(multipartfile, oustored_filepour réutiliser/restaurer ;nameoptionnel) →deduplicateddans la réponse ;409name_conflict/already_attachedavec l'id du fichier joint concerné.PATCH(renommer),DELETE,POST …/{id}/replace/,GET …/{id}/download/.GET /api/files/?project=&sha256=(détection de doublon avant envoi),GET /api/files/{id}/(usages),GET /api/files/{id}/versions/?spec=,GET /api/files/{id}/download/.attachment+application/octet-stream+nosniff, GetObject direct sur S3 (bug HeadObject de Garage).ATTACHMENTS_MAX_SIZE_MB(20).StoredFilesans lien est supprimé avec son fichier (on_commit) ; suppression d'un projet OK (RESTRICT).ATTACHMENTS_STORAGE=local|s3,S3_*(path-style, régiongaragepar défaut),MEDIA_ROOTexplicite. Passage au dictSTORAGES:STATICFILES_STORAGEn'était plus lu depuis Django 5.1 ;staticfilesreste surStaticFilesStorage, ce qui était réellement en vigueur.Tests
E2E (
e2e/attachments.spec.ts, Firefox, vraie stack gunicorn + SPA) : envoi et téléchargement, gel à la validation, héritage après « Nouvelle version », suppression/restauration, remplacement sur conflit de nom, détection d'un doublon entre deux specs. Données d'amorçage :e2e/seed.py, lancé par le job e2e aprèsmigrate. Vérifié en local (5/5) avec la SPA construite depuis thierryade/frontend#6.Unitaires : 24 nouveaux tests (
apps/specs/test_attachments.py) : statuts, dédoublonnage, conflits, immuabilité, droits, héritage/remplacement/suppression/restauration/renommage, raffinages, nettoyage physique, en-têtes de téléchargement, lecture S3 par GetObject. 103 tests au total, pylint 10/10, bandit et autopep8 propres.⚠️ À faire sur le serveur avant le merge
Le compose référence deux nouveaux secrets : sans eux,
docker compose upéchoue.garage bucket create thierryade-attachments,garage key new --name thierryade,garage bucket allow --read --write --key thierryade thierryade-attachmentssecrets/thierryadeS3AccessKeyetsecrets/thierryadeS3SecretKeydans/srv/docker/thierryadedeploy/docker-compose.ymlsur le serveur (sinonATTACHMENTS_STORAGEreste àlocalet les fichiers sont perdus au redéploiement).Ordre de merge
Merger thierryade/frontend#6 d'abord. Le job e2e (sur
masteruniquement) installe la dernière SPA publiée : si le backend passe en premier, le nouvel e2e échoue faute d'interface, etdocker/deploy(qui en dépendent) sont sautés. Le merge du frontend seul ne déploie rien : la SPA n'arrive en prod qu'avec la prochaine image backend.🤖 Generated with Claude Code
https://claude.ai/code/session_014BSmBtGWeFBD9z4mYm9SjA
📊 Rapports Argus pour cette PR