bndtools / bnd

Bnd/Bndtools. Tooling to build OSGi bundles including Eclipse, Maven, and Gradle plugins.
https://bndtools.org
Other
532 stars 305 forks source link

bnd-baseline-maven-plugin: Skip baselining if major version is 0? #2452

Closed io7m closed 6 years ago

io7m commented 6 years ago

Hello!

See item 4 of the semantic versioning spec:

Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.

It would be really great if the baseline plugin followed the should in this part of the spec: If the current major version of the bundle is 0, the baseline check should not be performed (or should at least not treat failures as an error). If I'm developing version0.0.1 of a package, and I then try to move up to 0.0.2, I don't want to be told that I've made a breaking change and must now release 1.0.0! :smile:

One option is to set bnd.baseline.skip in the POM until 1.0.0 is released. The problem with this is that it's easy to forget to do so - it would be very unpleasant to release 1.1.0 only to find that it really should have been 2.0.0 and that the plugin was accidentally left disabled.

bjhargrave commented 6 years ago

I think for baselining, both the bundle being baselined and the baseline bundle both must have version >= 1.0. This fix will affect more than maven plugin (also gradle plugin and possible bndlib).

io7m commented 6 years ago

Yep, I agree. Requiring both to be >= 1.0 makes sense.

bjhargrave commented 6 years ago

@pkriens @rotty3000 @timothyjward What are your thoughts on this? Basically the change would cause baselining to report no changes when either input (older, newer) has a version < 1.0.

That is, if older < 1.0, then it is not a suitable baseline since "real" API does not start until 1.0. If newer < 1.0, then it is not real API and thus there is no point in baselining it.

rotty3000 commented 6 years ago

It sounds reasonable. Will there be an override? Because this sounds like a good default policy rather than a hard and fast rule (kind of like import range policy, though I'm not quite sure how you'd express it.)

bjhargrave commented 6 years ago

Well, if we are to follow semver, then major version 0 is a "playground" outside the space of semantic versioning. So our baseliner should treat it as such. So we can still make a full diff of something with major version 0, any changes detected must not be baselining failures.

bjhargrave commented 6 years ago

I also think this fits well with the idea in #2422 which also suggests using major version 0 for wrapped jars whose semantic versioning status is broken or unknown.

rotty3000 commented 6 years ago

Got it. I'm good with that.

io7m commented 6 years ago

Thanks for implementing this. I'm looking forward to 4.1!

timothyjward commented 6 years ago

Well, if we are to follow semver, then major version 0 is a "playground" outside the space of semantic versioning. So our baseliner should treat it as such. So we can still make a full diff of something with major version 0, any changes detected must not be baselining failures.

Does this also imply that we should not fail the build if the current version is 1.0.0 and we can't find a previously released version?

bjhargrave commented 6 years ago

Does this also imply that we should not fail the build if the current version is 1.0.0 and we can't find a previously released version?

I am not sure we should ever fail a build when there is no previous release. That is, I should be free to make the first release of my package/bundle at version 2.1 if I want. Or do I misunderstand your question?

timothyjward commented 6 years ago

I am not sure we should ever fail a build when there is no previous release.

The default behaviour of the plugin is to automatically locate the highest previous version. If no version can be found then we cannot create a baseline. This should be a failure scenario if baselining is enabled - why else would baselining be configured and enabled for the project?

That is, I should be free to make the first release of my package/bundle at version 2.1 if I want.

You are absolutely correct, and in this unusual scenario you have the choice of:

bjhargrave commented 6 years ago
I am not sure we should ever fail a build when there is no previous release.

The default behaviour of the plugin is to automatically locate the highest previous version. If no version can be found then we cannot create a baseline. This should be a failure scenario if baselining is enabled - why else would baselining be configured and enabled for the project?

Because you set up baselining in the parent pom for all projects. The gradle BndBuilderPlugin will configure the baseline task to not fail when there is no prior version of the bundle released. So it can safely be applied to all projects, even new project which have never been previously released. Also, Bnd Workspace build do not fail when baselining is configured for the workspace and some projects have never been released.

That is, I should be free to make the first release of my package/bundle at version 2.1 if I want.

You are absolutely correct, and in this unusual scenario you have the choice of:

not enabling baselining until after the first release
setting the skip property for this project in its first release
setting failOnMissing to false

As pointed out, this is special casing and error prone since someone will forget to enable baselining after the first release.

io7m commented 6 years ago

What is the use case for failOnMissing?

I have it set to true everywhere, but the more I think about it, I'm less sure about how useful it actually is... Perhaps if I rename a project's artifact and want to be told if I forget to specify the old name for the baselining comparison.

timothyjward commented 6 years ago

Because you set up baselining in the parent pom for all projects. The gradle BndBuilderPlugin will configure the baseline task to not fail when there is no prior version of the bundle released. So it can safely be applied to all projects, even new project which have never been previously released.

The recommended maven model is somewhat different - plugin configuration is specified in the pluginManagement section of the parent, and only applied to projects that enable the plugins in their build section. If all plugins were applied universally then that would force you to generate indexes for projects that make no sense to resolve and baselines for projects that don't offer API.

Also, Bnd Workspace build do not fail when baselining is configured for the workspace and some projects have never been released.

Fundamentally I disagree with the thought that it's ok for Maven baselining to "pass" when it is unable to run due to a missing previous version. In Bnd's workspace every user views the same repositories, so if there is no previous version in the baseline repository then there really is nothing to baseline against. In Maven this is simply not the case. Deployment repositories (the best places to search for previous versions) may not be available to users, or they may simply not be used as sources of dependencies. A failure to find a version to baseline against in this case is far more likely to be an error in the build configuration, as you would only be baselining a project that you expect to have a version to baseline against.

As pointed out, this is special casing and error prone since someone will forget to enable baselining after the first release.

And my suggestion is to only force special casing in the situation where the first non 0.x release is not version 1.0.0. This case is already pretty special...

What is the use case for failOnMissing?

I have it set to true everywhere, but the more I think about it, I'm less sure about how useful it actually is... Perhaps if I rename a project's artifact and want to be told if I forget to specify the old name for the baselining comparison.

The use case for failOnMissing is the case where the artifact being built is not present in of the dependency repositories used in the build. This can easily happen when your distribution management section uses a different repository, or is set using system properties. This regularly happens when deploying to corporate repsositories, as deploys are typically only permitted in CI. In these cases the bundle can be quite happily built by a developer who has no ability to connect to a repository containing the previous versions, and a profile can be used to enforce the existence of a baseline in CI/Deployment.