Open fenollp opened 7 years ago
Les systèmes de CI sont conçus pour repartir de zéro à chaque commit, ils ne sont pas très adaptés à la mise à jour d'une base de données.
Je n'ai pas mis le nez dans le code, mais a vu de pif on telecharge la derniere tarball de ftp://ftp2.journal-officiel.gouv.fr/ et on genere un nouveau fichier markdown qu'on push ensuite ?
Si c'est le cas c'est tout a fait faisable avec les outils existant. On ne peut pas rejeter les 3 points que j'ai mentiones plus haut uniquement avec "pas tres adapte".
Mettre à jour automatiquement une BDD nécessite un stockage persistant, sinon ce n'est pas une mise à jour mais une coûteuse recréation permanente.
Je ne connais que peu les outils de CI, et il avait aussi été question avec Légilibre d’avoir un serveur sur lequel on ferait tourner les outils. Dans tous les cas, Archéo Lex est un peu lourd à faire tourner. Les contraintes sont actuellement :
Ma machine n’est pas hyper puissante, mais il faudrait de toutes manières améliorer la parallélisation du code. Ce qui prend du temps est surtout la création des historiques Git, et c’est surtout du temps processeur, il n’y a pas besoin outre mesure de RAM. Pour paralléliser, il serait simple dans un premier temps de paralléliser sur des codes différents (indépendants). En interne d’un code, il faudrait plutôt créer des caches par sections du sommaire pour ne calculer que les sections modifiées.
Sur des outils de CI/build, je ne suis pas sûr de bien comprendre comment l’utiliser dans ce cas, la remarque de @Changaco me semble avoir du sens : il y a 73 codes à calculer, refaire tout le process de téléchargement, extraction du tarball, mise en BDD, export Git est du temps perdu pour rien ; après il est possible de calculer plusieurs codes d’un coup, mais s’il s’agit de jouer à sélectionner les codes en fonction des timeouts ça ne va pas être très drôle. Tu as quelle idée de scénario en tête ?
Alors si vous ne connaissez pas trop le CI voici l'idee (et mettez vous-y, c'est gratuit ! Le concept = lancer un script pour chaque push recu).
Les build peuvent etre declenches par un simple POST (ou un truc a la cron deja fait pour). Tout le monde peut lire le code, les logs du build et donc verifier que rien de malfaisant n'a ete commis. Tout cela pour zero euros par mois.
Ok, par contre étant donné la structure lourde actuelle de Archéo Lex (cf les contraintes ci-dessus), je vois pas trop comment mettre ça en place. Tu confirmes qu’on peut bien pusher un résultat vers l’extérieur de la plateforme de CI ? Sinon la partie "clone le repo git de destination et push son markdown", ça serait bien mais ça n’est pas encore implémenté. Pour l’instant, il n’est pas possible de "compléter" un historique Git, il faut toujours le refaire ex nihilo à chaque fois. Ça serait à implémenter mais ça n’est pas aussi simple que ça en a l’air car il faut rechercher à partir de quelle date dans le passé il faut refaire l’historique, cf https://github.com/Legilibre/Archeo-Lex/issues/28#issuecomment-281065786.
@fenollp C'est vrai que c'est une belle idée, mais elle n'est pas très efficace. Quand la machine qui met à jour les données n'est pas proche du disque dur qui contient la BDD il faut transférer plusieurs gigaoctets de données à travers l'Internet, ce qui ralentit le processus et encombre les tuyaux.
Le fait que le CI soit "gratuit" ne signifie pas qu'on peut se permettre de faire n'importe quoi avec (au contraire même, si on veut que ça reste gratuit il ne faut pas en abuser).
Ceci dit ça pourrait être intéressant d'essayer avec legi.py pour voir si ça fonctionne et combien de temps ça prend.
En ce qui concerne l'aspect confiance, même si le CI permet en effet une bonne transparence et sécurité par défaut, ça reste quand même la machine de quelqu'un d'autre (et probablement hébergée hors de France). Le seul vrai moyen de vérifier que "rien de malfaisant n'a été commis" c'est d'exécuter le programme sur une machine que tu contrôles et de comparer le résultat.
En pratique la protection la plus efficace contre l'altération des données est que celle-ci n'a aucun intérêt (en tout cas moi je n'en vois pas). Quand il n'y a pas de gain potentiel il y a peu de malfaiteurs.
Je fermerai cette issue dans un mois (*) étant donné qu’elle est résolue dans un contexte légèrement différent de la proposition originale : en combinant https://github.com/Legilibre/deploiement (avec un provisionning spécifiquement pour Gandi, j’accepte les PR pour d’autres fournisseurs de VMs) et la récente amélioration d’Archéo Lex qui peut désormais mettre à jour les dépôts Git, il est désormais possible de déployer Archéo Lex littéralement en un script (après un git-clone du dépôt deploiement), la suite dépend de ce qu’on veut (one shot sur qq textes, livraison régulière de qq textes, livraison régulière de tout le corpus législatif français, etc.).
(*) @fenollp: si tu veux proposer un déploiement spécifiquement sur des outils de CI, Archéo Lex a désormais la possibilité de calculer les textes d’une liste donnée 07ea750, le reste est affaire de scripts de déploiement (setup legi.py + Archéo Lex, download, BDD, calcul AL, git-push des résultats, cron si on veut). Je te laisse proposer des PR soit sur le dépôt https://github.com/Legilibre/deploiement (il peut y avoir des languages alternatifs à Bourne shell) ou faire un autre dépôt spécifiquement de déploiement, et je ferai un lien de Archéo Lex vers ces dépôts de déploiement.
+1 pour un CRON via Travis-CI et les dépôts sur GitHub dans une organisation dédiée
Update : au temps pour moi, la CI n'est pas forcément une bonne idée.
Le Bureau Ouvert a envie de bosser sur ce sujet. Du coup on a créé : https://github.com/Legifrance-Git pour stocker les dépôts des textes.
Maintenant il faudrait avancer sur un orchestrateur (un simple CRON). Des idées ?
Je viens de push https://github.com/Legilibre/deploiement/compare/master...fenollp:ci-able L'idee est de pouvoir build sur n'importe quelle archi facilement. Ca serait bien que le script depende de sha ou de tags mais je vois que les 2 projets n'ont pas cut de tag depuis longtemps. Aussi leurs requirements.txt ne specifient pas les numeros de version utilises. Long story short:
+ python -m legi.download /app/tarballs
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/app/legi.py.git/legi/download.py", line 22, in <module>
download_legi(args.directory)
File "/app/legi.py.git/legi/download.py", line 14, in download_legi
'ftp://legi:open1234@ftp2.journal-officiel.gouv.fr/*legi_*'
File "/usr/lib/python2.7/subprocess.py", line 181, in check_call
retcode = call(*popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 168, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 390, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1024, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Il manque une dependence vers un client FTP on dirait ?
@fenollp Ça a l’air pas mal ton commit. Pour l’erreur il manque peut-être wget
. Pour les versions des requirements.txt, mon déploiement récent donne les versions suivantes (pip list) :
BeautifulSoup (3.2.1)
beautifulsoup4 (4.6.0)
docopt (0.6.2)
html2text (2018.1.9)
legi (0.2)
libarchive-c (2.7)
lxml (4.1.1)
path.py (10.5)
peewee (2.10.2)
pip (9.0.1)
pytz (2017.3)
setuptools (33.1.1)
tqdm (4.19.5)
wheel (0.29.0)
N’hésites pas à faire des PR s’il faut mieux préciser les versions.
Est-ce que tu peux push un pip freeze >requirements.txt
des deux projets sur master ou une nouvelle branche ? En attendant je vais voir si ajouter wget aide.
Fait pour Archéo Lex. Pour legi.py, il faut contacter @Changaco sur ledit projet.
Thanks! Il manquait bien wget
. Maintenant il faut que je regle un probleme d'encoding des sources de legi.py je crois (ce fichier bizarrement):
connected 0 rows of textes_versions based on (nature, num)
inserted 46099 rows in textes based on (nature, num)
connected 47323 rows of textes_versions based on (nature, num)
connected 1 rows of textes_versions based on nor
connected 0 rows of textes_versions based on titrefull_s
inserted 52366 rows in textes based on nor
connected 52612 rows of textes_versions based on nor
factorized 605 duplicates into 205 uniques based on titrefull_s
connected 0 rows of textes_versions based on titrefull_s
inserted 7822 rows in textes based on titrefull_s
connected 7974 rows of textes_versions based on titrefull_s
factorized 2279 duplicates into 1085 uniques based on cid
deleted 2838 unused rows from textes
done
Traceback (most recent call last):
File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/app/legi.py.git/legi/tar2sqlite.py", line 515, in <module>
main()
File "/app/legi.py.git/legi/tar2sqlite.py", line 510, in main
factorize(db)
File "legi/factorize.py", line 235, in main
print("Il y a désormais %i textes dans la base." % n)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 8: ordinal not in range(128)
J'ai l'impression que le processing des tar + l'ajout dans la DB devrait pouvoir se faire de maniere concurrente, voire creer plusieurs DB pour les merger a la fin. Peut-etre que d'avoir le fichier sqlite en memoire plutot que sur disque aiderait pas mal deja. C'est tres lent pour juste 2GB de tarballs.
Je ne suis pas sûr que bloquer les versions des dépendances de legi.py soit une bonne idée, ça peut vite mener à des conflits. C'est le projet à la racine de l'arbre des dépendances qui doit fixer les versions (ou pas), or legi.py peut être une dépendance d'un autre projet donc il n'est pas toujours la racine.
Peut-etre que d'avoir le fichier sqlite en memoire plutot que sur disque aiderait pas mal deja.
Le fichier est en mémoire, via le cache du système de fichier maintenu par le noyau (Linux). Il est possible de demander à SQLite de garder le fichier en cache côté userspace mais ça n'accélère pas vraiment le travail (cf. https://github.com/Legilibre/legi.py/pull/21).
Pour SQLite, tentez avec:
Désactiver les synchrone sur le disque:
PRAGMA synchronous OFF;
Désactiver le journal des transactions (qui permet de faire des rollbacks):
PRAGMA journal_mode OFF;
Ca devrait bien améliorer les choses, toutefois si il y a un problème (perte de courant) la base sera certainement corrompue.
Désactiver le journal et la synchronisation est dangereux et n'a pas d'effet sur la première conversion puisque la base de données est vide au début et que l'opération est une seule gigantesque transaction donc il n'y a rien à copier dans le journal et rien à synchroniser.
En revanche il est possible que la conversion des archives incrémentales bénéficie de journal_mode = wal
et synchronous = normal
. Augmenter cache_size
un peu au delà des 2Mio par défaut peut aussi être bénéfique en réduisant le nombre des changements de contexte (user space ↔ kernel space).
Histoire que
Je propose qu'on mette en place une tache cron, ou un outil de Continuous Integration (integration continue). Il en existe beaucoup de gratuits pour les projets open source.