FerrFlow considère un repository comme un monorepo lorsque la configuration définit plus d'un package. Chaque package est versionné indépendamment en fonction de son propre historique git.
Isolation des packages
FerrFlow utilise les préfixes de chemin pour déterminer quels commits appartiennent à quel package. Seuls les commits qui touchent des fichiers sous path (ou sharedPaths) déclenchent une release pour ce package.
JSON
{
"package": [
{
"name": "api",
"path": "packages/api"
},
{
"name": "site",
"path": "packages/site"
}
]
}
TOML
[[package]] name = "api" path = "packages/api"
[[package]] name = "site" path = "packages/site"
JSON5
{
package: [
{
name: "api",
path: "packages/api",
},
{
name: "site",
path: "packages/site",
},
],
}
YAML
package:
- name: api
path: packages/api
- name: site
path: packages/site
Dépendances partagées
Si vous avez du code partagé entre packages (ex. une bibliothèque packages/shared/), déclarez-le comme entrée sharedPaths. Un changement dans un chemin partagé déclenche une release pour chaque package qui le référence :
JSON
{
"package": [
{
"name": "api",
"path": "packages/api",
"sharedPaths": ["packages/shared/"]
},
{
"name": "site",
"path": "packages/site",
"sharedPaths": ["packages/shared/"]
}
]
}
TOML
[[package]] name = "api" path = "packages/api" shared_paths = ["packages/shared/"]
[[package]] name = "site" path = "packages/site" shared_paths = ["packages/shared/"]
JSON5
{
package: [
{
name: "api",
path: "packages/api",
sharedPaths: ["packages/shared/"],
},
{
name: "site",
path: "packages/site",
sharedPaths: ["packages/shared/"],
},
],
}
YAML
package:
- name: api
path: packages/api
sharedPaths:
- packages/shared/
- name: site
path: packages/site
sharedPaths:
- packages/shared/
Dependances entre packages
Utilisez dependsOn pour declarer qu'un package depend d'un autre. Quand une dependance est publiee, le package dependant recoit automatiquement un bump patch — meme si aucun de ses propres fichiers n'a change. La cascade est transitive : si app depend de cli et cli depend de core, publier core bumpe aussi cli et app.
JSON
{
"package": [
{
"name": "core",
"path": "packages/core"
},
{
"name": "cli",
"path": "packages/cli",
"dependsOn": ["core"]
},
{
"name": "app",
"path": "packages/app",
"dependsOn": ["cli"]
}
]
}
TOML
[[package]] name = "core" path = "packages/core"[[package]] name = "cli" path = "packages/cli" depends_on = ["core"]
[[package]] name = "app" path = "packages/app" depends_on = ["cli"]
JSON5
{
package: [
{
name: "core",
path: "packages/core",
},
{
name: "cli",
path: "packages/cli",
dependsOn: ["core"],
},
{
name: "app",
path: "packages/app",
dependsOn: ["cli"],
},
],
}
YAML
package:
- name: core
path: packages/core
- name: cli
path: packages/cli
dependsOn:
- core
- name: app
path: packages/app
dependsOn:
- cli
Cycles de dépendances
dependsOn doit décrire un graphe orienté acyclique. Si deux packages dépendent l'un de l'autre — directement ou transitivement — il n'existe aucun ordre de release possible : FerrFlow s'arrête alors avec l'erreur E8003 en nommant la boucle :
cycle detected: api → web → api
La vérification s'exécute avant toute écriture de version : une configuration cyclique ne produit jamais de release partielle. Cassez la boucle en supprimant l'une des arêtes dependsOn. Sinon, le graphe est publié dépendances d'abord : un package est toujours publié après les packages dont il dépend.
Groupes de versions liées et fixes
Parfois, plusieurs packages doivent partager le même numéro de version, pas seulement propager un bump. linked et fixed listent des groupes de packages qui évoluent ensemble :
[workspace]
linked = [["react", "react-dom"]]
fixed = [["@scope/a", "@scope/b", "@scope/c"]]
Dès qu'un membre d'un groupe a un commit publiable, tous les membres sont bumpés à la même version — la plus haute que le groupe atteindrait. Un feat sur un membre et un fix sur un autre publient tout le groupe sur le minor. Les noms de packages restent distincts ; seule la version est partagée, et les membres sans commit propre sont intégrés à la release à la version partagée.
linked— les packages partagent une ligne de version lorsqu'ils sont publiés ensemble (par exemplereactetreact-dompassent tous deux de1.2.3à1.2.4).fixed— les packages sont verrouillés sur une version identique en permanence. Le comportement est celui delinked, etferrflow validateavertit en plus lorsque les versions d'un groupefixedont déjà divergé, pour repérer une édition manuelle avant que la prochaine release ne les réaligne.
Chaque groupe doit lister au moins deux packages, et un package ne peut appartenir qu'à un seul groupe linked ou fixed. Nommer un package absent de package[], ou en lister un dans deux groupes, arrête la release avec une erreur claire avant toute écriture — la même garantie amont que les cycles de dépendances.
linked/fixed et dependsOn se combinent : un package qui dépend d'un package groupé reçoit toujours son bump en cascade après l'alignement du groupe.
Format des tags git
Par défaut, les tags en monorepo utilisent le format {name}@v{version} :
api@v1.2.0
site@v0.4.1
Configurez cela avec le champ tagTemplate :
JSON
{
"workspace": {
"tagTemplate": "{name}@v{version}"
}
}
TOML
[workspace]
tag_template = "{name}@v{version}"
JSON5
{
workspace: {
tagTemplate: "{name}@v{version}",
},
}
YAML
workspace:
tagTemplate: "{name}@v{version}"
Pour un repo mono-package, le défaut est v{version} (sans préfixe de nom).
FerrFlow recherche le tag le plus récent correspondant au modèle pour déterminer quels commits sont nouveaux.
Cadences indépendantes
Les packages sont publiés indépendamment. Dans une seule exécution de ferrflow release :
apipeut passer de1.2.0→1.3.0(nouveau commitfeat:)sitepeut passer de0.4.0→0.4.1(uniquement des commitsfix:)sharedpeut ne pas être publié (uniquement des commitschore:)
Surcharges par package
Chaque package peut surcharger la stratégie de versioning et le tagTemplate du workspace :
JSON
{
"workspace": {
"versioning": "semver",
"tagTemplate": "{name}@v{version}"
},
"package": [
{
"name": "api",
"path": "packages/api",
"versioning": "calver"
},
{
"name": "site",
"path": "packages/site",
"tagTemplate": "site-v{version}"
}
]
}
TOML
[workspace] versioning = "semver" tag_template = "{name}@v{version}"[[package]] name = "api" path = "packages/api" versioning = "calver"
[[package]] name = "site" path = "packages/site" tag_template = "site-v{version}"
JSON5
{
workspace: {
versioning: "semver",
tagTemplate: "{name}@v{version}",
},
package: [
{
name: "api",
path: "packages/api",
versioning: "calver",
},
{
name: "site",
path: "packages/site",
tagTemplate: "site-v{version}",
},
],
}
YAML
workspace:
versioning: semver
tagTemplate: "{name}@v{version}"package:
- name: api path: packages/api versioning: calver
name: site path: packages/site tagTemplate: "site-v{version}"