commitizen icon indicating copy to clipboard operation
commitizen copied to clipboard

changelog --subdirectory

Open yajo opened this issue 3 years ago • 19 comments

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.

yajo avatar Mar 31 '21 09:03 yajo

@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.

woile avatar Aug 17 '21 06:08 woile

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?

Lee-W avatar Aug 17 '21 09:08 Lee-W

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?

woile avatar Aug 17 '21 09:08 woile

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?

Lee-W avatar Aug 17 '21 09:08 Lee-W

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

woile avatar Aug 17 '21 09:08 woile

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']

woile avatar Aug 17 '21 09:08 woile

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.

m1racoli avatar Aug 23 '21 13:08 m1racoli

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).

woile avatar Aug 23 '21 13:08 woile

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 then commitizen 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? 🤔

yajo avatar Aug 24 '21 08:08 yajo

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.

m1racoli avatar Aug 24 '21 08:08 m1racoli

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.

woile avatar Aug 24 '21 08:08 woile

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.

m1racoli avatar Aug 27 '21 12:08 m1racoli

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.

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 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.

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.

yajo avatar Aug 31 '21 06:08 yajo

+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.

jon-nfc avatar Jan 14 '22 07:01 jon-nfc

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.

robertschweizer avatar Nov 11 '22 13:11 robertschweizer