Skip to main content

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-01 ne déroge à rien, BR-FR-01_BT-1 dé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

facturseal_ci-0.0.1.tar.gz (42.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

facturseal_ci-0.0.1-py3-none-any.whl (35.1 kB view details)

Uploaded Python 3

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

Hashes for facturseal_ci-0.0.1.tar.gz
Algorithm Hash digest
SHA256 da20ec23f3a83ccd71a062dc26579d419e36a19e3c8def56624b11c585e20991
MD5 40f6c5dbe5816258f50263c4c5b86391
BLAKE2b-256 f4b0af3c1d538e931d282a031964b6b50c5a276e843c9695ca6abb35c71b3c40

See more details on using hashes here.

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

Hashes for facturseal_ci-0.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 884d57273683db059f9001504ea770dc55a8612c77b86913cc72b7e9e74e47c2
MD5 3c122b98f96538aec9c8ea60d358c51c
BLAKE2b-256 0e3e897b49925f23aecc130478edcd8cec2a029183ed1b4405e73f3784a5f225

See more details on using hashes here.

Release history Release notifications | RSS feed

0.0.2

2 files

This release

0.0.1 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page