Un package dbt est un projet dbt — mêmes fichiers, même structure, même modèle d’exécution, avec dbt_project.yml comme seul fichier obligatoire. La différence est l’intention : un package est conçu pour être installé dans le projet de quelqu’un d’autre via dbt deps. Cela change chaque décision de conception. Dans un projet ordinaire, coder en dur un nom de schéma est acceptable. Dans un package, cela échoue dès qu’un autre utilisateur l’installe.
Trois principes
Trois principes distinguent un package bien construit d’un projet ordinaire :
- Configurable. Aucun nom de base de données, référence de schéma ou identifiant de table codé en dur. Tout ce que les utilisateurs pourraient avoir besoin de personnaliser passe par
var(). Voir Patterns de modèles packageables dbt pour les détails d’implémentation. - Namespaced. Les noms de modèles incluent le préfixe du package pour éviter les collisions.
my_package__customers, pascustomers. Quand un utilisateur a cinq packages installés, les noms génériques commecustomersoudaily_summaryentreront en collision. - Adapter-aware. Le SQL qui diffère selon les warehouses utilise
adapter.dispatch()pour que le package fonctionne sur Snowflake, BigQuery, Redshift et d’autres. Le pattern dispatch gère cela proprement.
Ces principes ne sont pas aspirationnels — ils sont le niveau minimum requis pour un package que d’autres personnes peuvent réellement utiliser. Fivetran maintient plus de 100 packages qui suivent tous ce pattern. Les propres packages de dbt Labs font de même. Le pattern est éprouvé à l’échelle.
Structure de répertoires standard
La structure utilisée par dbt Labs et Fivetran pour leurs propres packages est devenue le standard communautaire :
dbt-my_package/├── dbt_project.yml # Obligatoire : configuration du package├── packages.yml # Dépendances en amont├── macros/│ ├── my_macro.sql│ └── _macros.yml # Documentation des macros├── models/│ ├── base/│ └── marts/├── tests/generic/ # Tests génériques personnalisés├── integration_tests/ # Sous-projet pour les tests│ ├── dbt_project.yml│ ├── packages.yml # Référence le parent via local: ../│ ├── seeds/ # Données mock│ ├── models/│ └── tests/├── .github/workflows/ # Configuration CI├── README.md├── CHANGELOG.md└── LICENSELe sous-répertoire integration_tests/ est la pièce la plus distinctive. Contrairement aux projets ordinaires qui testent sur place, un package ne peut pas se tester lui-même en isolation — il est conçu pour être installé à l’intérieur d’un autre projet. Le pattern des tests d’intégration résout cela avec un sous-projet qui installe le package parent comme dépendance locale.
L’organisation des modèles à l’intérieur d’un package suit la même architecture en trois couches qu’un projet ordinaire, mais avec une structure plus plate. La plupart des packages sautent entièrement la couche intermédiaire puisqu’ils fournissent des briques de construction, non des transformations complètes.
dbt_project.yml pour les packages
Le fichier projet contient quelques paramètres importants spécifiquement pour les packages :
name: 'my_package'version: '0.1.0'require-dbt-version: [">=1.3.0", "<3.0.0"]
config-version: 2
models: my_package: +materialized: view
vars: my_package_schema: 'my_data' my_package_database: null my_package__some_model_enabled: truePlages de versions
La plage require-dbt-version devrait inclure à la fois dbt Core 1.x et Fusion 2.x (dbt 2.0). Définir la borne supérieure à <3.0.0 couvre les deux runtimes. Sans cela, les utilisateurs sur des versions incompatibles obtiennent des erreurs de compilation obscures plutôt qu’un message clair « version incompatible ».
Matérialisation par défaut
La matérialisation par défaut doit être view, pas table. Quand quelqu’un exécute dbt deps && dbt run, votre package ne devrait pas créer 30 tables physiques dans leur warehouse. Les utilisateurs peuvent toujours surcharger vers table pour les performances dans leur propre dbt_project.yml :
models: my_package: +materialized: tableC’est l’inverse des recommandations pour les projets ordinaires, où les tables sont la valeur par défaut recommandée. La différence est la propriété : dans votre propre projet, vous voulez de la visibilité pour le débogage. Dans le projet de quelqu’un d’autre, vous voulez une empreinte légère.
Valeurs par défaut des variables
Chaque option configurable doit avoir une valeur par défaut sensée déclarée sous vars. La convention de nommage est {nom_package}_{paramètre} pour les paramètres de schéma/base de données et {nom_package}__{modèle}_enabled pour les feature flags (double underscore pour séparer le nom du package du nom du paramètre).
vars: my_package_schema: 'my_data' # Où se trouvent les données source my_package_database: null # null = utiliser target.database my_package__daily_summary_enabled: true # Bascule des modèles individuels my_package_events_identifier: 'events' # Surcharges de noms de tablesDéclarer les valeurs par défaut ici signifie que les utilisateurs n’ont besoin de surcharger que les paramètres différents de leur environnement. Un utilisateur dont la table d’événements s’appelle raw_events définit une seule variable ; tout le monde reçoit la valeur par défaut.
Qu’en est-il du nom du package ?
Le champ name dans dbt_project.yml devient le namespace pour tout ce qui se trouve dans votre package. Il préfixe les références de modèles, les noms de variables et les définitions de sources. Choisissez-le avec soin car le modifier après la publication est un changement breaking pour chaque utilisateur.
Utilisez le snake_case, gardez-le court et rendez-le descriptif. revenue_tools est meilleur que my_company_revenue_analytics_package_v2. Le nom doit indiquer à quelqu’un ce que fait le package en deux ou trois mots.
Quand un projet ordinaire devient un package
La plupart des packages commencent sous forme de code que vous avez déjà écrit et testé en production dans vos propres projets. L’étape de packaging consiste essentiellement à :
- Remplacer les références codées en dur par des appels
var() - Préfixer les noms de modèles avec le nom du package
- Ajouter des implémentations dispatch pour la portabilité entre warehouses
- Construire une suite de tests d’intégration
- Rédiger la documentation
Inutile de construire un package de zéro. Extrayez ce qui fonctionne déjà, rendez-le configurable et vérifiez-le avec des tests. Le Hub est accessible via une seule PR lorsque vous êtes prêt, mais un package Git partagé entre les projets de votre équipe est un excellent point de départ.