facturseal-ci
Client de CI de FacturSeal : il fait échouer votre pipeline quand une facture qui était conforme à l'EN 16931 / Factur-X cesse de l'être.
pip install facturseal-ci
Aucune dépendance, aucun moteur, aucune image Docker : le paquet ne contient que le strict nécessaire pour générer un corpus avec votre code, l'envoyer au service et lire le verdict. Il s'installe en une seconde dans un runner.
En une commande
export FACTURSEAL_URL=https://api.facturseal.com
export FACTURSEAL_TOKEN=$FS_TOKEN # secret de projet
facturseal-ci \
--generate "php examples/php/generate.php" \
--corpus build/factures \
--baseline facturseal-baseline.json \
--report build/facturseal.md \
--junit build/facturseal-junit.xml
Au premier run, la baseline de référence est écrite : commitez-la. Aux runs suivants, elle est comparée au corpus régénéré.
Codes de sortie
| Code | Signification |
|---|---|
0 |
Aucune régression retenue |
1 |
Régression retenue : une facture qui passait casse, le pipeline échoue |
2 |
Panne d'outil : service injoignable, corpus non validable, réponse illisible |
2 n'est jamais 1, et c'est le point : un service indisponible n'est pas une
facture non conforme. Une CI qui confondrait les deux enverrait votre équipe chercher
un bug dans son code de facturation.
Le contrat de génération
--generate reçoit une commande, en n'importe quel langage. FacturSeal n'exécute
jamais votre code métier : il vous passe un scénario et attend une facture.
Pour chaque scénario servi par le service, votre commande est appelée avec :
$FS_SCENARIO_PAYLOAD: chemin d'un fichier JSON décrivant la facture à produire, en termes métier BT/BG (jamais du XML) ;$FS_INVOICE_OUT: chemin où écrire la facture produite.
Elle doit sortir en 0 si et seulement si le fichier a été écrit.
<?php
// examples/php/generate.php
$payload = json_decode(file_get_contents(getenv('FS_SCENARIO_PAYLOAD')), true);
$xml = MonEditeur\Facturation::genererFacturX($payload['blueprint']);
file_put_contents(getenv('FS_INVOICE_OUT'), $xml);
Le catalogue de scénarios est servi par l'API (GET /me/scenarios), pas embarqué
dans ce paquet : il évolue avec la réglementation sans que vous ayez à réinstaller
quoi que ce soit.
Si votre corpus est déjà produit par ailleurs, omettez --generate : le contenu de
--corpus est envoyé tel quel.
Options
| Option | Rôle |
|---|---|
--generate CMD |
Commande de génération de l'éditeur ; absente = corpus déjà peuplé |
--corpus DIR |
Répertoire du corpus (défaut : build/factures) |
--baseline FILE |
Baseline de référence versionnée (défaut : facturseal-baseline.json) |
--extension EXT |
Extension produite : xml ou pdf (défaut : xml) |
--api-url URL |
URL du service (déf. FACTURSEAL_URL) |
--token TOKEN |
Jeton bearer (déf. FACTURSEAL_TOKEN) |
--report FILE |
Rapport markdown, lisible en revue de merge request |
--junit FILE |
JUnit XML : onglet « Tests » de GitLab et GitHub |
--sarif FILE |
SARIF 2.1.0 : onglet « Security / code scanning » de GitHub |
--update-baseline |
Promouvoir : (re)figer la référence au lieu de differ |
--waivers FILE |
Fichier de dérogations gouvernées (déf. FS_WAIVER_STORE) |
--tenant ID |
Tenant dont les dérogations s'appliquent (exigé avec --waivers) |
--allow-insecure |
Tolérer un service en http (le jeton circule alors en clair) |
--timeout N |
Budget en secondes par appel et par génération (défaut : 120) |
Les métadonnées de run (branche, commit, déclencheur) sont auto-détectées sur GitLab
CI, GitHub Actions et Azure DevOps ; --branch, --commit et --trigger les
forcent au besoin.
Dérogations
Une régression peut être acceptée sans être effacée. Le fichier de dérogations est versionné dans votre dépôt, par dessein : une dérogation est une décision, elle passe donc par la revue de code comme le reste.
{
"waivers": {
"mon-tenant": [
{
"rule_id": "BR-FR-01_BT-1",
"justification": "Correctif livré en 2026-09, ticket FACT-4821",
"created_at": "2026-08-11",
"expires_at": "2026-09-30",
"author": "equipe-facturation"
}
]
}
}
facturseal-ci --waivers .facturseal/waivers.json --tenant mon-tenant ...
Trois propriétés valent d'être connues :
- la maille est l'assertion, pas la règle. Sous la couche FR, une règle se décline
en un assert par champ contrôlé :
BR-FR-01ne déroge à rien,BR-FR-01_BT-1déroge à ce champ-là. Élargir tacitement à toute une famille dérogerait à des contrôles que personne n'a nommés ; - un constat dérogé reste nommé. Il sort de la liste bloquante, il reste dans le
rapport, dans le JUnit (
skipped, avec sa justification) et dans le SARIF (suppressions). « Rien trouvé » et « trouvé puis accepté » ne se confondent pas ; - les dérogations mortes sont dénoncées. Une dérogation active qui n'a couvert aucun constat, ou une dérogation échue, est listée en sortie : sans ça, elle élargirait le plafond sans que personne l'ait décidé.
Un fichier de dérogations demandé mais absent est une panne d'outil (exit 2), pas « aucune dérogation ».
GitLab CI
facturseal:
image: python:3.12-slim
script:
- pip install facturseal-ci
- facturseal-ci --generate "php examples/php/generate.php"
--junit build/facturseal-junit.xml
--report build/facturseal.md
artifacts:
when: always
paths: [build/facturseal.md]
reports:
junit: build/facturseal-junit.xml
GitHub Actions
- run: pip install facturseal-ci
- run: facturseal-ci --generate "php examples/php/generate.php" --sarif facturseal.sarif
env:
FACTURSEAL_URL: ${{ vars.FACTURSEAL_URL }}
FACTURSEAL_TOKEN: ${{ secrets.FACTURSEAL_TOKEN }}
- uses: github/codeql-action/upload-sarif@v3
if: always()
with: { sarif_file: facturseal.sarif }
Ce que ce paquet ne contient pas
Ni moteur de validation, ni catalogue de règles, ni matrice de référence, ni scénarios : tout cela appartient au produit FacturSeal et est servi par le service. La baseline elle-même est opaque au client, qui la transporte entre le service et votre dépôt sans l'interpréter, à la seule exception du verdict par facture, lu pour détecter les factures que le moteur n'a pas su valider.
Licence
Apache 2.0 (voir LICENSE et NOTICE). « FacturSeal » est une marque de Tsharp : la
licence n'en concède pas l'usage.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file facturseal_ci-0.0.1.tar.gz.
File metadata
- Download URL: facturseal_ci-0.0.1.tar.gz
- Upload date:
- Size: 42.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.12.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da20ec23f3a83ccd71a062dc26579d419e36a19e3c8def56624b11c585e20991
|
|
| MD5 |
40f6c5dbe5816258f50263c4c5b86391
|
|
| BLAKE2b-256 |
f4b0af3c1d538e931d282a031964b6b50c5a276e843c9695ca6abb35c71b3c40
|
File details
Details for the file facturseal_ci-0.0.1-py3-none-any.whl.
File metadata
- Download URL: facturseal_ci-0.0.1-py3-none-any.whl
- Upload date:
- Size: 35.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.12.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
884d57273683db059f9001504ea770dc55a8612c77b86913cc72b7e9e74e47c2
|
|
| MD5 |
3c122b98f96538aec9c8ea60d358c51c
|
|
| BLAKE2b-256 |
0e3e897b49925f23aecc130478edcd8cec2a029183ed1b4405e73f3784a5f225
|