commitizen
commitizen copied to clipboard
changelog --subdirectory
Description
Allow to filter commits affecting only a subdirectory.
Possible Solution
cz changelog --subdirectory my_module --file-name my_module/CHANGELOG.md
Additional context
I'm considering proposing this for @OCA. There, repositories mostly are split into modules, where each one of them has its own readme and (maybe) changelog.
So, when autogenerating changelogs, only commits affecting the module should be taken into account. AFAICS that wouldn't be possible currently.
git format-patch
allows such filtering (example recipe -- for other purposes). It would be nice if commitizen could leverage that and make this a reality.
@Lee-W @Yajo
About this feature, I was thinking about adding a new setting to the configuration file:
# .cz.toml
[tool.commitizen]
workspace = true # similar word used by rust and js
Given this folder structure (as an exmaple):
app/
└── packages/
├── fizzbuz/
│ ├── pyproject.toml
│ └── src/
├── foobar2/
│ ├── .cz.toml
│ └── src/
└── p1/
├── .cz.toml
└── src/
The user would have to navigate to each of the projects and run cz bump --changelog
.
What I don't have clear is how to handle the tags? Any thoughts on this? should we attach something to the tags? otherwise they may repeat.
I don't get how we could use workspace = true # similar word used by rust and js
. Does that mean we'll need to create a .cz.toml
in the subdirectory?
yes, each sub-package would have it's own .cz.toml
. This means that each would have it's own independent version. This is a sample of a monorepo with poetry: https://github.com/ya-mori/python-monorepo
You can see each package in libs
and projects
has also it's own pyproject.toml
.
The alternative is to have a single .cz.toml
at the top, but then commitizen
should know where each project lives, something like:
members = [
"packages/fizzbuz",
"packages/foobar2",
"packages/p1",
]
But this also means, they would all share the same version.
Thoughts?
Either way works for me. 👍 But we still have the problem of how are we going to handle the git tag? Maybe we could enforce different tag format for each project?
Indeed, the tag issue only happens if you have many .cz.toml
, which is the one I personally would prefer.
Maybe we can add a prefix (folder-name) or something like that. I'm gonna check how lerna does it
Maybe it could be part of the buildmetadata
of semver.
1.0.0+fizzbuz
2.3.5+foobar2
0.1.0+p1
We just need to check if python's pep-0440 has support as well
Edit: it seems it does: https://www.python.org/dev/peps/pep-0440/#:~:text=1.0%2Bubuntu.1
In [1]: from packaging.version import Version
In [2]: v = Version("1.0.0+foobar")
In [3]: v.local
Out[3]: 'foobar'
In [1]: from semver.version import Version
In [2]: v = Version.parse("1.0.0+foobar")
In [3]: v.build
Out[3]: ['foobar']
What about a tag format like
submodule-v1.2.3
which represents version 1.2.3
of the module in submodule
. This would be nice in a monorepo setup.
It's done like this in amundsen for example.
We're using commitizen and are currently investigating how we could consolidate multiple projects of similar nature (terraform modules, python packages, docker images,...) into a single monorepo with independent versioning and changelog.
It's a possibility, but I don't think semver
and pep-0440
would be able to parse a tag like that.
I get:
InvalidVersion: Invalid version: 'submodule-v1.2.3'
From my understanding the way is to add the metadata at the end with a +
sign.
This way, users would be able to choose to also publish those tags as a valid semver or pep-0440.
This, I think is important, because even something as a helm chart requires a valid semver for example (even pep-0440 breaks when adding a rc).
What I don't have clear is how to handle the tags? Any thoughts on this? should we attach something to the tags? otherwise they may repeat.
Regarding this, for my original purpose when opening this issue, we don't use tags on those repositories.
Instead, the version is kept in a metadata file in the repo, which is specific for each module (subdirectory).
So there should be a way to configure the way we obtain the tag. Maybe in .cz.toml
somehow be able to indicate a command that returns the tag for the workspace.
The alternative is to have a single
.cz.toml
at the top, but thencommitizen
should know where each project lives, something like:members = [ "packages/fizzbuz", "packages/foobar2", "packages/p1", ]
I prefer this alternative, to avoid maintaining a lot of .cz.toml
files.
The members
key could support glob patterns to ease maintenance.
But this also means, they would all share the same version.
If combined with the custom tag getter explained above, it wouldn't be a problem.
Side note: we use versions with 5 places (like 14.0.1.2.3
)... is that gonna be a problem? 🤔
From my understanding the way is to add the metadata at the end with a
+
sign. This way, users would be able to choose to also publish those tags as a valid semver or pep-0440. This, I think is important, because even something as a helm chart requires a valid semver for example (even pep-0440 breaks when adding a rc).
Thanks for the input. That makes sense.
Regarding this, for my original purpose when opening this issue, we don't use tags on those repositories.
I foresee some issues with the changelog generation in this situations, as we do use tags to generate the changelog itself.
Instead, the version is kept in a metadata file in the repo, which is specific for each module (subdirectory).
I prefer this alternative, to avoid maintaining a lot of .cz.toml files.
This seems like a contradiction to me. Instead of having one cz.toml
per project or 1 cz.toml, you have 1 top cz.toml
+ 1 metadatafile. And I really don't want users to have 2 different files. A minimal .cz.toml
would look like:
[tool.commitizen]
version = "2.18.0"
workspace = true
I don't think it's such a heavy burden vs a metadata file like:
2.18.0
I think eventually, support for the members
could be introduced, and then cz bump
could navigate the members. But having a .cz.toml
per package enables also some extra benefits, like disabling changelog for specific package, using a different changelog file, different conventions per package, and all of this by just keeping the settings.
Going forward, the feature of generating the changelog based only on the changes of a corresponding directory is not impacted by the choice of version format, since the pattern can be freely configured already.
Thus by having a .cz.toml
in each sub-folder with independent versions and setting workspace = true
seems to provide the necessary functionality without breaking anything.
The question is, what happens with changes in the root folder, which potentially could affect all sub-project equally.
Instead, the version is kept in a metadata file in the repo, which is specific for each module (subdirectory).
I prefer this alternative, to avoid maintaining a lot of .cz.toml files.
This seems like a contradiction to me. Instead of having one
cz.toml
per project or 1 cz.toml, you have 1 topcz.toml
+ 1 metadatafile. And I really don't want users to have 2 different files.
Well it's not something we can change. That's the way Odoo modules work, and that's what we code there. They have a __manifest__.py
file which contains the version, like in this example. And there's one per module (folder).
there should be a way to configure the way we obtain the tag
This is still relevant because otherwise all subpackages will be forced to use the same range of commits when generating the changelog.
The question is: if subpackage A is on version 1.2.3 and subpackage B is on version 0.0.1, when I go to A and execute cz bump
, how does commitizen know which commits correspond to which subpackage? (They don't share the same version, so probably the repo has no git tags, or otherwise they are not relevant for the subpackage version).
One idea: what if we save in .cz.toml
the commit hash of the latest bump?
The question is, what happens with changes in the root folder, which potentially could affect all sub-project equally.
IMHO the subdirectory should have a notion that it's a subdirectory and is related to a parent.
Then, just set include_parent_changes = true
and those will appear. Set it to false
and they won't.
I think eventually, support for the
members
could be introduced, and thencz bump
could navigate the members. But having a.cz.toml
per package enables also some extra benefits, like disabling changelog for specific package, using a different changelog file, different conventions per package, and all of this by just keeping the settings.
OK but at least I think the child .cz.toml
should inherit missing keys from the parent one. The fact that a minimal file is minimal doesn't mean we'll always use minimal files. Maybe we have different commit conventions, patterns, etc., and having to repeat them every time would be boring.
+1 for this feature
I currently use git log
with a filter for the directory in question to create sub-directory changelogs.
Having version capabilities on a sub-directory bases would also be valuable.
We have a Python monorepo with each package having its own version and changelog. The workspace
option would be ideal to enable commitizen here. Right now there seems to be no way of bumping package versions only if a commit actually affected a specific package.