From b1533ad7958cfa7ab83ebd56f5420d840cb3c1a1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 09:50:26 +0000 Subject: [PATCH 1/6] Initial plan From 51ec344ddfb95db4ada306f48f2e62b43641df85 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 09:59:00 +0000 Subject: [PATCH 2/6] Add includezeromajor configuration for baselining 0.x versions Co-authored-by: peterkir <250545+peterkir@users.noreply.github.com> --- .../test/test/baseline/BaselineTest.java | 28 +++++++++++++++++ .../src/aQute/bnd/build/ProjectBuilder.java | 31 +++++++++++++++++-- .../src/aQute/bnd/differ/Baseline.java | 29 +++++++++++++++++ .../src/aQute/bnd/osgi/Constants.java | 1 + 4 files changed, 87 insertions(+), 2 deletions(-) diff --git a/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java b/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java index 6de8264a61..93e7a57e12 100644 --- a/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java +++ b/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java @@ -263,6 +263,34 @@ public void testNoMismatchForZeroMajor() throws Exception { } } + @Test + public void testMismatchForZeroMajorWhenIncludeZeroMajorEnabled() throws Exception { + try (Builder older = new Builder(); Builder newer = new Builder();) { + older.addClasspath(IO.getFile("java8/older/bin")); + older.setExportPackage("*;version=0.1"); + newer.addClasspath(IO.getFile("java8/newer/bin")); + newer.setExportPackage("*;version=0.1"); + try (Jar o = older.build(); Jar n = newer.build();) { + assertTrue(older.check()); + assertTrue(newer.check()); + + DiffPluginImpl differ = new DiffPluginImpl(); + Baseline baseline = new Baseline(older, differ); + + // Enable includezeromajor via diffpackages instruction + Instructions packageFilters = new Instructions("*;includezeromajor=true"); + Set infoSet = baseline.baseline(n, o, packageFilters); + assertEquals(1, infoSet.size()); + for (Info info : infoSet) { + // With includezeromajor enabled, mismatch should be true for 0.x versions + assertTrue(info.mismatch, "Expected mismatch for 0.x version when includezeromajor is enabled"); + assertEquals(new Version(0, 2, 0), info.suggestedVersion); + assertEquals(info.packageName, "api_default_methods"); + } + } + } + } + /** * Check if we can ignore resources in the baseline. First build two jars * that are identical except for the b/b resource. Then do baseline on them. diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java index b1ae76dee8..18da932488 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java @@ -558,9 +558,18 @@ public Jar getBaselineJar() throws Exception { if (versions.isEmpty()) { // We have a repo - // Baselining 0.x is uninteresting + // Baselining 0.x is uninteresting (unless includezeromajor is enabled) // x.0.0 is a new major version so maybe there is no baseline - if ((version.getMajor() > 0) && ((version.getMinor() > 0) || (version.getMicro() > 0))) { + + // Check if includezeromajor is enabled in diffpackages + boolean includeZeroMajor = isIncludeZeroMajorEnabled(); + + boolean shouldWarn = (version.getMajor() > 0) && ((version.getMinor() > 0) || (version.getMicro() > 0)); + if (!shouldWarn && includeZeroMajor && version.getMajor() == 0 && (version.getMinor() > 0 || version.getMicro() > 0)) { + shouldWarn = true; + } + + if (shouldWarn) { warning( "There is no baseline for %s in the baseline repo %s. The build is for version %s, which is higher than %s which suggests that there should be a prior version.", getBsn(), repo, version.getWithoutQualifier(), new Version(version.getMajor())); @@ -649,6 +658,24 @@ public Jar getBaselineJar() throws Exception { return null; } + private boolean isIncludeZeroMajorEnabled() { + String diffpackagesStr = project.getProperty(Constants.DIFFPACKAGES); + if (diffpackagesStr == null || diffpackagesStr.isEmpty()) { + return false; + } + Parameters diffpackages = new Parameters(diffpackagesStr, this); + for (var entry : diffpackages.entrySet()) { + var attrs = entry.getValue(); + if (attrs != null) { + var value = attrs.get(Constants.DIFFPACKAGES_INCLUDE_ZERO_MAJOR); + if (value != null && "true".equalsIgnoreCase(value)) { + return true; + } + } + } + return false; + } + /** * Remove any staging versions that have a variant with a higher qualifier. * diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java index f9e23bd261..629d5b36e0 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java +++ b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java @@ -77,6 +77,7 @@ public static class BundleInfo { Version olderVersion; Version suggestedVersion; String releaseRepository; + boolean includeZeroMajor; public Baseline(Reporter bnd, Differ differ) throws IOException { this.differ = differ; @@ -116,6 +117,9 @@ public Set baseline(Tree n, Parameters nExports, Tree o, Parameters oExpor newerVersion = getVersion(n); olderVersion = getVersion(o); + // Parse includeZeroMajor configuration from packageFilters + includeZeroMajor = getIncludeZeroMajor(packageFilters); + final boolean binfoMismatch = mismatch(olderVersion, newerVersion); boolean firstRelease = false; @@ -300,6 +304,22 @@ public Set baseline(Tree n, Parameters nExports, Tree o, Parameters oExpor return infos; } + private boolean getIncludeZeroMajor(Instructions packageFilters) { + if (packageFilters == null || packageFilters.isEmpty()) + return false; + // Check if any instruction has includezeromajor attribute set to true + for (var entry : packageFilters.entrySet()) { + var attrs = entry.getValue(); + if (attrs != null) { + var value = attrs.get(Constants.DIFFPACKAGES_INCLUDE_ZERO_MAJOR); + if (value != null && "true".equalsIgnoreCase(value)) { + return true; + } + } + } + return false; + } + private Delta getThreshold(Instructions packageFilters, Instruction matcher) { if (matcher == null) return null; @@ -319,10 +339,19 @@ private Delta getThreshold(Instructions packageFilters, Instruction matcher) { /** * "Major version zero (0.y.z) is for initial development. Anything may * change at any time. The public API should not be considered stable." + *

+ * This method returns {@code true} if baselining should report mismatches + * for the given versions. By default, it returns {@code false} for versions + * with major version 0 (unless {@code includeZeroMajor} is enabled). * * @see SemVer */ private boolean mismatch(Version older, Version newer) { + if (includeZeroMajor) { + // When includeZeroMajor is enabled, only exclude versions where both are 0.0.x + return !(older.getMajor() == 0 && older.getMinor() == 0 && newer.getMajor() == 0 && newer.getMinor() == 0); + } + // Default behavior: exclude all versions with major version 0 return older.getMajor() > 0 && newer.getMajor() > 0; } diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java index 6e701cb8ed..d5cdf876cf 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java +++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java @@ -124,6 +124,7 @@ public interface Constants { String DIFFIGNORE = "-diffignore"; String DIFFPACKAGES = "-diffpackages"; String DIFFPACKAGES_THRESHOLD = "threshold"; + String DIFFPACKAGES_INCLUDE_ZERO_MAJOR = "includezeromajor"; String DEPENDSON = "-dependson"; String DEPLOY = "-deploy"; String DEPLOYREPO = "-deployrepo"; From 4bc46712a658df834ef3d5a8312f5d7cb174898e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 10:01:42 +0000 Subject: [PATCH 3/6] Update documentation for includezeromajor baseline configuration Co-authored-by: peterkir <250545+peterkir@users.noreply.github.com> --- docs/_chapters/180-baselining.md | 8 +++++++- docs/_instructions/_ext/diffpackages.md | 26 ++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/docs/_chapters/180-baselining.md b/docs/_chapters/180-baselining.md index 4077f56baf..b2fb554645 100644 --- a/docs/_chapters/180-baselining.md +++ b/docs/_chapters/180-baselining.md @@ -10,7 +10,13 @@ APIs are compared for backward compatibility using the semantic versioning rules ## Setting Up a Project for Baselining -During the build, bnd will check the [`-baseline` instruction](../instructions/baseline.html) at the end of the build when the JAR is ready. This instruction is a selector on the symbolic name of the building bundle. If it matches, the baselining is started with one exception: the bundle/package version must be 1.0.0 or above. If the version is less (i.e. major version being `0`) no baselining is possible, the purpose is to allow the [primordial baseline to be established without errors](https://semver.org/#spec-item-4). +During the build, bnd will check the [`-baseline` instruction](../instructions/baseline.html) at the end of the build when the JAR is ready. This instruction is a selector on the symbolic name of the building bundle. If it matches, the baselining is started with one exception: by default, the bundle/package version must be 1.0.0 or above. If the version is less (i.e. major version being `0`) no baselining errors are reported, the purpose is to allow the [primordial baseline to be established without errors](https://semver.org/#spec-item-4). + +To enable baselining for versions in the range `[0.1.0, 1.0.0)`, use the `includezeromajor` attribute in the [`-diffpackages` instruction](../instructions/diffpackages.html): + + -diffpackages: *;includezeromajor=true + +This will enable baseline error reporting for packages with major version `0` (except for `0.0.x` versions which are still excluded). By default the baseline is a bundle from one of the repositories with the same symbolic name as the building bundle and the highest possible version. However, it is possible to specify the version or to baseline against a file. diff --git a/docs/_instructions/_ext/diffpackages.md b/docs/_instructions/_ext/diffpackages.md index 75d0a16891..9f3207a773 100644 --- a/docs/_instructions/_ext/diffpackages.md +++ b/docs/_instructions/_ext/diffpackages.md @@ -8,6 +8,30 @@ summary: The names of exported packages to baseline. You can use the `-diffpackages` instruction to specify the names of exported packages to be baseline compared. The default is all exported packages. +## Attributes + +The following attributes can be specified on each package selector: + +### threshold + +Specifies the minimum change level that should be reported. Valid values are `MICRO`, `MINOR`, or `MAJOR`. Changes below this threshold will be ignored during baselining. + +Example: + + -diffpackages: *;threshold=MAJOR + +This will only report MAJOR changes and ignore MINOR and MICRO changes. + +### includezeromajor + +By default, packages with major version `0` (i.e., `0.x.x`) do not generate baseline errors, as per [semantic versioning spec](https://semver.org/#spec-item-4) which states that major version zero is for initial development. Setting `includezeromajor=true` enables baseline error reporting for packages in the version range `[0.1.0, 1.0.0)`. + +Note: Packages with version `0.0.x` are still excluded from baselining even when `includezeromajor` is enabled. + +Example: + + -diffpackages: *;includezeromajor=true + ## Example - -diffpackages: !*.internal.*, * + -diffpackages: !*.internal.*, *;threshold=MINOR;includezeromajor=true From a065e2fd024e6bb7756fd8166d8c5493ebdfd977 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 10:05:16 +0000 Subject: [PATCH 4/6] Address code review feedback: simplify logic and improve documentation Co-authored-by: peterkir <250545+peterkir@users.noreply.github.com> --- .../test/test/baseline/BaselineTest.java | 30 +++++++++++++++++++ .../src/aQute/bnd/differ/Baseline.java | 4 +-- docs/_instructions/_ext/diffpackages.md | 18 +++++++++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java b/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java index 93e7a57e12..fc5593f64d 100644 --- a/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java +++ b/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java @@ -291,6 +291,36 @@ public void testMismatchForZeroMajorWhenIncludeZeroMajorEnabled() throws Excepti } } + @Test + public void testNoMismatchForZeroZeroVersionsEvenWithIncludeZeroMajor() throws Exception { + try (Builder older = new Builder(); Builder newer = new Builder();) { + older.addClasspath(IO.getFile("java8/older/bin")); + older.setExportPackage("*;version=0.0.1"); + newer.addClasspath(IO.getFile("java8/newer/bin")); + newer.setExportPackage("*;version=0.0.1"); + try (Jar o = older.build(); Jar n = newer.build();) { + assertTrue(older.check()); + assertTrue(newer.check()); + + DiffPluginImpl differ = new DiffPluginImpl(); + Baseline baseline = new Baseline(older, differ); + + // Enable includezeromajor via diffpackages instruction + Instructions packageFilters = new Instructions("*;includezeromajor=true"); + Set infoSet = baseline.baseline(n, o, packageFilters); + assertEquals(1, infoSet.size()); + for (Info info : infoSet) { + // Even with includezeromajor enabled, 0.0.x versions should not report mismatch + assertFalse(info.mismatch, "Expected no mismatch for 0.0.x version even with includezeromajor"); + // Note: The suggested version is 0.1.0 because there's a MINOR change in the test data + // The important thing is that mismatch is false, so no error is reported + assertEquals(new Version(0, 1, 0), info.suggestedVersion); + assertEquals(info.packageName, "api_default_methods"); + } + } + } + } + /** * Check if we can ignore resources in the baseline. First build two jars * that are identical except for the b/b resource. Then do baseline on them. diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java index 629d5b36e0..b1e430a866 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java +++ b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java @@ -348,8 +348,8 @@ private Delta getThreshold(Instructions packageFilters, Instruction matcher) { */ private boolean mismatch(Version older, Version newer) { if (includeZeroMajor) { - // When includeZeroMajor is enabled, only exclude versions where both are 0.0.x - return !(older.getMajor() == 0 && older.getMinor() == 0 && newer.getMajor() == 0 && newer.getMinor() == 0); + // When includeZeroMajor is enabled, only exclude 0.0.x versions + return !(newer.getMajor() == 0 && newer.getMinor() == 0); } // Default behavior: exclude all versions with major version 0 return older.getMajor() > 0 && newer.getMajor() > 0; diff --git a/docs/_instructions/_ext/diffpackages.md b/docs/_instructions/_ext/diffpackages.md index 9f3207a773..335d629b03 100644 --- a/docs/_instructions/_ext/diffpackages.md +++ b/docs/_instructions/_ext/diffpackages.md @@ -32,6 +32,20 @@ Example: -diffpackages: *;includezeromajor=true -## Example +## Examples - -diffpackages: !*.internal.*, *;threshold=MINOR;includezeromajor=true +Exclude internal packages from baselining: + + -diffpackages: !*.internal.*, * + +Enable baselining for 0.x versions: + + -diffpackages: *;includezeromajor=true + +Set threshold for changes and enable 0.x baselining: + + -diffpackages: *;threshold=MINOR;includezeromajor=true + +Combine exclusions with attributes (note: attributes only apply to their selector): + + -diffpackages: !*.internal.*, *;threshold=MAJOR;includezeromajor=true From 4f6796fbfd76059eedf2fd0bfce71feb65c3d286 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 19:53:08 +0000 Subject: [PATCH 5/6] Change includezeromajor to global -includezeromajor instruction Co-authored-by: chrisrueger <188422+chrisrueger@users.noreply.github.com> --- .../test/test/baseline/BaselineTest.java | 12 ++++----- .../src/aQute/bnd/build/ProjectBuilder.java | 17 ++----------- .../src/aQute/bnd/differ/Baseline.java | 25 ++++++------------- .../src/aQute/bnd/osgi/Constants.java | 4 +-- docs/_chapters/180-baselining.md | 4 +-- docs/_instructions/_ext/diffpackages.md | 22 ++-------------- docs/_instructions/_ext/includezeromajor.md | 25 +++++++++++++++++++ 7 files changed, 46 insertions(+), 63 deletions(-) create mode 100644 docs/_instructions/_ext/includezeromajor.md diff --git a/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java b/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java index fc5593f64d..b519ee4f62 100644 --- a/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java +++ b/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java @@ -268,6 +268,8 @@ public void testMismatchForZeroMajorWhenIncludeZeroMajorEnabled() throws Excepti try (Builder older = new Builder(); Builder newer = new Builder();) { older.addClasspath(IO.getFile("java8/older/bin")); older.setExportPackage("*;version=0.1"); + // Enable includezeromajor via global property + older.setProperty(Constants.INCLUDEZEROMAJOR, "true"); newer.addClasspath(IO.getFile("java8/newer/bin")); newer.setExportPackage("*;version=0.1"); try (Jar o = older.build(); Jar n = newer.build();) { @@ -277,9 +279,7 @@ public void testMismatchForZeroMajorWhenIncludeZeroMajorEnabled() throws Excepti DiffPluginImpl differ = new DiffPluginImpl(); Baseline baseline = new Baseline(older, differ); - // Enable includezeromajor via diffpackages instruction - Instructions packageFilters = new Instructions("*;includezeromajor=true"); - Set infoSet = baseline.baseline(n, o, packageFilters); + Set infoSet = baseline.baseline(n, o, null); assertEquals(1, infoSet.size()); for (Info info : infoSet) { // With includezeromajor enabled, mismatch should be true for 0.x versions @@ -296,6 +296,8 @@ public void testNoMismatchForZeroZeroVersionsEvenWithIncludeZeroMajor() throws E try (Builder older = new Builder(); Builder newer = new Builder();) { older.addClasspath(IO.getFile("java8/older/bin")); older.setExportPackage("*;version=0.0.1"); + // Enable includezeromajor via global property + older.setProperty(Constants.INCLUDEZEROMAJOR, "true"); newer.addClasspath(IO.getFile("java8/newer/bin")); newer.setExportPackage("*;version=0.0.1"); try (Jar o = older.build(); Jar n = newer.build();) { @@ -305,9 +307,7 @@ public void testNoMismatchForZeroZeroVersionsEvenWithIncludeZeroMajor() throws E DiffPluginImpl differ = new DiffPluginImpl(); Baseline baseline = new Baseline(older, differ); - // Enable includezeromajor via diffpackages instruction - Instructions packageFilters = new Instructions("*;includezeromajor=true"); - Set infoSet = baseline.baseline(n, o, packageFilters); + Set infoSet = baseline.baseline(n, o, null); assertEquals(1, infoSet.size()); for (Info info : infoSet) { // Even with includezeromajor enabled, 0.0.x versions should not report mismatch diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java index 18da932488..4bc665e263 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java @@ -43,6 +43,7 @@ import aQute.bnd.osgi.Instructions; import aQute.bnd.osgi.Jar; import aQute.bnd.osgi.Packages; +import aQute.bnd.osgi.Processor; import aQute.bnd.osgi.Resource; import aQute.bnd.osgi.Verifier; import aQute.bnd.service.RepositoryPlugin; @@ -659,21 +660,7 @@ public Jar getBaselineJar() throws Exception { } private boolean isIncludeZeroMajorEnabled() { - String diffpackagesStr = project.getProperty(Constants.DIFFPACKAGES); - if (diffpackagesStr == null || diffpackagesStr.isEmpty()) { - return false; - } - Parameters diffpackages = new Parameters(diffpackagesStr, this); - for (var entry : diffpackages.entrySet()) { - var attrs = entry.getValue(); - if (attrs != null) { - var value = attrs.get(Constants.DIFFPACKAGES_INCLUDE_ZERO_MAJOR); - if (value != null && "true".equalsIgnoreCase(value)) { - return true; - } - } - } - return false; + return Processor.isTrue(project.getProperty(Constants.INCLUDEZEROMAJOR)); } /** diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java index b1e430a866..0eda1f42ef 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java +++ b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java @@ -117,8 +117,13 @@ public Set baseline(Tree n, Parameters nExports, Tree o, Parameters oExpor newerVersion = getVersion(n); olderVersion = getVersion(o); - // Parse includeZeroMajor configuration from packageFilters - includeZeroMajor = getIncludeZeroMajor(packageFilters); + // Read includeZeroMajor from global property + // The Reporter interface doesn't have getProperty, but the actual instance is always a Processor + if (bnd instanceof Processor) { + includeZeroMajor = Processor.isTrue(((Processor) bnd).getProperty(Constants.INCLUDEZEROMAJOR)); + } else { + includeZeroMajor = false; + } final boolean binfoMismatch = mismatch(olderVersion, newerVersion); @@ -304,22 +309,6 @@ public Set baseline(Tree n, Parameters nExports, Tree o, Parameters oExpor return infos; } - private boolean getIncludeZeroMajor(Instructions packageFilters) { - if (packageFilters == null || packageFilters.isEmpty()) - return false; - // Check if any instruction has includezeromajor attribute set to true - for (var entry : packageFilters.entrySet()) { - var attrs = entry.getValue(); - if (attrs != null) { - var value = attrs.get(Constants.DIFFPACKAGES_INCLUDE_ZERO_MAJOR); - if (value != null && "true".equalsIgnoreCase(value)) { - return true; - } - } - } - return false; - } - private Delta getThreshold(Instructions packageFilters, Instruction matcher) { if (matcher == null) return null; diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java index d5cdf876cf..5119443634 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java +++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java @@ -124,7 +124,6 @@ public interface Constants { String DIFFIGNORE = "-diffignore"; String DIFFPACKAGES = "-diffpackages"; String DIFFPACKAGES_THRESHOLD = "threshold"; - String DIFFPACKAGES_INCLUDE_ZERO_MAJOR = "includezeromajor"; String DEPENDSON = "-dependson"; String DEPLOY = "-deploy"; String DEPLOYREPO = "-deployrepo"; @@ -159,6 +158,7 @@ public interface Constants { String GESTALT_SHELL = "shell"; String GROUPID = "-groupid"; String INCLUDE = "-include"; + String INCLUDEZEROMAJOR = "-includezeromajor"; String INCLUDERESOURCE = "-includeresource"; String INCLUDEPACKAGE = "-includepackage"; String INVALIDFILENAMES = "-invalidfilenames"; @@ -333,7 +333,7 @@ public interface Constants { Set options = Sets.of(BASELINE, BUILDPATH, BUMPPOLICY, CONDUIT, CLASSPATH, COMPRESSION, CONSUMER_POLICY, DEPENDSON, DONOTCOPY, EXPORT_CONTENTS, FAIL_OK, INCLUDE, - INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS, NOUSES, NOBUNDLES, PEDANTIC, PLUGIN, POM, PROVIDER_POLICY, + INCLUDEZEROMAJOR, INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS, NOUSES, NOBUNDLES, PEDANTIC, PLUGIN, POM, PROVIDER_POLICY, REMOVEHEADERS, RESOURCEONLY, SOURCES, SOURCEPATH, SUB, RUNBUNDLES, RUNPATH, RUNSYSTEMPACKAGES, RUNSYSTEMCAPABILITIES, RUNPROPERTIES, REPORTNEWER, UNDERTEST, TESTPATH, TESTPACKAGES, NOMANIFEST, DEPLOYREPO, RELEASEREPO, SAVEMANIFEST, RUNVM, RUNPROGRAMARGS, WAB, WABLIB, RUNFRAMEWORK, RUNFW, RUNKEEP, RUNTRACE, diff --git a/docs/_chapters/180-baselining.md b/docs/_chapters/180-baselining.md index b2fb554645..d24c31229b 100644 --- a/docs/_chapters/180-baselining.md +++ b/docs/_chapters/180-baselining.md @@ -12,9 +12,9 @@ APIs are compared for backward compatibility using the semantic versioning rules During the build, bnd will check the [`-baseline` instruction](../instructions/baseline.html) at the end of the build when the JAR is ready. This instruction is a selector on the symbolic name of the building bundle. If it matches, the baselining is started with one exception: by default, the bundle/package version must be 1.0.0 or above. If the version is less (i.e. major version being `0`) no baselining errors are reported, the purpose is to allow the [primordial baseline to be established without errors](https://semver.org/#spec-item-4). -To enable baselining for versions in the range `[0.1.0, 1.0.0)`, use the `includezeromajor` attribute in the [`-diffpackages` instruction](../instructions/diffpackages.html): +To enable baselining for versions in the range `[0.1.0, 1.0.0)`, use the [`-includezeromajor` instruction](../instructions/includezeromajor.html): - -diffpackages: *;includezeromajor=true + -includezeromajor: true This will enable baseline error reporting for packages with major version `0` (except for `0.0.x` versions which are still excluded). diff --git a/docs/_instructions/_ext/diffpackages.md b/docs/_instructions/_ext/diffpackages.md index 335d629b03..5e9d65d2f4 100644 --- a/docs/_instructions/_ext/diffpackages.md +++ b/docs/_instructions/_ext/diffpackages.md @@ -22,30 +22,12 @@ Example: This will only report MAJOR changes and ignore MINOR and MICRO changes. -### includezeromajor - -By default, packages with major version `0` (i.e., `0.x.x`) do not generate baseline errors, as per [semantic versioning spec](https://semver.org/#spec-item-4) which states that major version zero is for initial development. Setting `includezeromajor=true` enables baseline error reporting for packages in the version range `[0.1.0, 1.0.0)`. - -Note: Packages with version `0.0.x` are still excluded from baselining even when `includezeromajor` is enabled. - -Example: - - -diffpackages: *;includezeromajor=true - ## Examples Exclude internal packages from baselining: -diffpackages: !*.internal.*, * -Enable baselining for 0.x versions: - - -diffpackages: *;includezeromajor=true - -Set threshold for changes and enable 0.x baselining: - - -diffpackages: *;threshold=MINOR;includezeromajor=true - -Combine exclusions with attributes (note: attributes only apply to their selector): +Set threshold for changes: - -diffpackages: !*.internal.*, *;threshold=MAJOR;includezeromajor=true + -diffpackages: *;threshold=MINOR diff --git a/docs/_instructions/_ext/includezeromajor.md b/docs/_instructions/_ext/includezeromajor.md new file mode 100644 index 0000000000..693e51df3c --- /dev/null +++ b/docs/_instructions/_ext/includezeromajor.md @@ -0,0 +1,25 @@ +--- +layout: default +class: Project +title: -includezeromajor BOOLEAN +summary: Enable baselining for packages with major version 0. +--- + +# -includezeromajor + +The `-includezeromajor` instruction enables baseline error reporting for packages with major version `0` (i.e., versions in the range `[0.1.0, 1.0.0)`). + +By default, bnd does not report baselining errors for packages with major version `0`, following the [semantic versioning spec](https://semver.org/#spec-item-4) which states that "Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable." + +When set to `true`, baseline error reporting is enabled for packages with version `0.1.0` or higher. Packages with version `0.0.x` are still excluded from baselining. + +Example: + +``` +-baseline: * +-includezeromajor: true +``` + +This is useful when you want to enforce semantic versioning discipline during the initial development phase (0.x versions) while still excluding the very early `0.0.x` versions. + +Default value is `false`. From 23c62259d04a6cefb289496a28f8b650fce96ca2 Mon Sep 17 00:00:00 2001 From: Christoph Rueger Date: Wed, 11 Feb 2026 21:09:46 +0100 Subject: [PATCH 6/6] rename to -baselineincludezeromajor Signed-off-by: Christoph Rueger --- .../test/test/baseline/BaselineTest.java | 25 ++++++++++++------- .../src/aQute/bnd/build/ProjectBuilder.java | 13 +++++----- .../src/aQute/bnd/differ/Baseline.java | 19 +++++++------- .../src/aQute/bnd/osgi/Constants.java | 4 +-- docs/_chapters/180-baselining.md | 4 +-- ...romajor.md => baselineincludezeromajor.md} | 8 +++--- 6 files changed, 40 insertions(+), 33 deletions(-) rename docs/_instructions/_ext/{includezeromajor.md => baselineincludezeromajor.md} (75%) diff --git a/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java b/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java index b519ee4f62..f181d1ae3a 100644 --- a/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java +++ b/biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java @@ -22,7 +22,6 @@ import java.util.TreeSet; import java.util.regex.Pattern; -import aQute.bnd.osgi.*; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -33,6 +32,13 @@ import aQute.bnd.differ.Baseline.BundleInfo; import aQute.bnd.differ.Baseline.Info; import aQute.bnd.differ.DiffPluginImpl; +import aQute.bnd.osgi.Analyzer; +import aQute.bnd.osgi.Builder; +import aQute.bnd.osgi.Constants; +import aQute.bnd.osgi.Instructions; +import aQute.bnd.osgi.Jar; +import aQute.bnd.osgi.Processor; +import aQute.bnd.osgi.Verifier; import aQute.bnd.service.RepositoryPlugin; import aQute.bnd.service.diff.Delta; import aQute.bnd.service.diff.Diff; @@ -268,8 +274,8 @@ public void testMismatchForZeroMajorWhenIncludeZeroMajorEnabled() throws Excepti try (Builder older = new Builder(); Builder newer = new Builder();) { older.addClasspath(IO.getFile("java8/older/bin")); older.setExportPackage("*;version=0.1"); - // Enable includezeromajor via global property - older.setProperty(Constants.INCLUDEZEROMAJOR, "true"); + // Enable baselineincludezeromajor via global property + older.setProperty(Constants.BASELINEINCLUDEZEROMAJOR, "true"); newer.addClasspath(IO.getFile("java8/newer/bin")); newer.setExportPackage("*;version=0.1"); try (Jar o = older.build(); Jar n = newer.build();) { @@ -282,8 +288,9 @@ public void testMismatchForZeroMajorWhenIncludeZeroMajorEnabled() throws Excepti Set infoSet = baseline.baseline(n, o, null); assertEquals(1, infoSet.size()); for (Info info : infoSet) { - // With includezeromajor enabled, mismatch should be true for 0.x versions - assertTrue(info.mismatch, "Expected mismatch for 0.x version when includezeromajor is enabled"); + // With -baselineincludezeromajor enabled, mismatch should + // be true for 0.x versions + assertTrue(info.mismatch, "Expected mismatch for 0.x version when baselineincludezeromajor is enabled"); assertEquals(new Version(0, 2, 0), info.suggestedVersion); assertEquals(info.packageName, "api_default_methods"); } @@ -296,8 +303,8 @@ public void testNoMismatchForZeroZeroVersionsEvenWithIncludeZeroMajor() throws E try (Builder older = new Builder(); Builder newer = new Builder();) { older.addClasspath(IO.getFile("java8/older/bin")); older.setExportPackage("*;version=0.0.1"); - // Enable includezeromajor via global property - older.setProperty(Constants.INCLUDEZEROMAJOR, "true"); + // Enable baselineincludezeromajor via global property + older.setProperty(Constants.BASELINEINCLUDEZEROMAJOR, "true"); newer.addClasspath(IO.getFile("java8/newer/bin")); newer.setExportPackage("*;version=0.0.1"); try (Jar o = older.build(); Jar n = newer.build();) { @@ -310,8 +317,8 @@ public void testNoMismatchForZeroZeroVersionsEvenWithIncludeZeroMajor() throws E Set infoSet = baseline.baseline(n, o, null); assertEquals(1, infoSet.size()); for (Info info : infoSet) { - // Even with includezeromajor enabled, 0.0.x versions should not report mismatch - assertFalse(info.mismatch, "Expected no mismatch for 0.0.x version even with includezeromajor"); + // Even with baselineincludezeromajor enabled, 0.0.x versions should not report mismatch + assertFalse(info.mismatch, "Expected no mismatch for 0.0.x version even with baselineincludezeromajor"); // Note: The suggested version is 0.1.0 because there's a MINOR change in the test data // The important thing is that mismatch is false, so no error is reported assertEquals(new Version(0, 1, 0), info.suggestedVersion); diff --git a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java index 4bc665e263..6042b97ce1 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java +++ b/biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java @@ -43,7 +43,6 @@ import aQute.bnd.osgi.Instructions; import aQute.bnd.osgi.Jar; import aQute.bnd.osgi.Packages; -import aQute.bnd.osgi.Processor; import aQute.bnd.osgi.Resource; import aQute.bnd.osgi.Verifier; import aQute.bnd.service.RepositoryPlugin; @@ -559,17 +558,17 @@ public Jar getBaselineJar() throws Exception { if (versions.isEmpty()) { // We have a repo - // Baselining 0.x is uninteresting (unless includezeromajor is enabled) + // Baselining 0.x is uninteresting (unless baselineincludezeromajor is enabled) // x.0.0 is a new major version so maybe there is no baseline - - // Check if includezeromajor is enabled in diffpackages + + // Check if baselineincludezeromajor is enabled in diffpackages boolean includeZeroMajor = isIncludeZeroMajorEnabled(); - + boolean shouldWarn = (version.getMajor() > 0) && ((version.getMinor() > 0) || (version.getMicro() > 0)); if (!shouldWarn && includeZeroMajor && version.getMajor() == 0 && (version.getMinor() > 0 || version.getMicro() > 0)) { shouldWarn = true; } - + if (shouldWarn) { warning( "There is no baseline for %s in the baseline repo %s. The build is for version %s, which is higher than %s which suggests that there should be a prior version.", @@ -660,7 +659,7 @@ public Jar getBaselineJar() throws Exception { } private boolean isIncludeZeroMajorEnabled() { - return Processor.isTrue(project.getProperty(Constants.INCLUDEZEROMAJOR)); + return project.is(Constants.BASELINEINCLUDEZEROMAJOR); } /** diff --git a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java index 0eda1f42ef..ece12e1f52 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java +++ b/biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java @@ -77,11 +77,20 @@ public static class BundleInfo { Version olderVersion; Version suggestedVersion; String releaseRepository; - boolean includeZeroMajor; + final boolean includeZeroMajor; public Baseline(Reporter bnd, Differ differ) throws IOException { this.differ = differ; this.bnd = bnd; + + // Read includeZeroMajor from global property + // The Reporter interface doesn't have getProperty, but the actual + // instance is always a Processor + if (bnd instanceof Processor proc) { + includeZeroMajor = proc.is(Constants.BASELINEINCLUDEZEROMAJOR); + } else { + includeZeroMajor = false; + } } /** @@ -117,14 +126,6 @@ public Set baseline(Tree n, Parameters nExports, Tree o, Parameters oExpor newerVersion = getVersion(n); olderVersion = getVersion(o); - // Read includeZeroMajor from global property - // The Reporter interface doesn't have getProperty, but the actual instance is always a Processor - if (bnd instanceof Processor) { - includeZeroMajor = Processor.isTrue(((Processor) bnd).getProperty(Constants.INCLUDEZEROMAJOR)); - } else { - includeZeroMajor = false; - } - final boolean binfoMismatch = mismatch(olderVersion, newerVersion); boolean firstRelease = false; diff --git a/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java b/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java index 5119443634..b174af197e 100644 --- a/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java +++ b/biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java @@ -93,6 +93,7 @@ public interface Constants { REQUIRE_CAPABILITY, SERVICE_COMPONENT, PRIVATE_PACKAGE, IGNORE_PACKAGE, TESTCASES); String BASELINE = "-baseline"; + String BASELINEINCLUDEZEROMAJOR = "-baselineincludezeromajor"; String BASELINEREPO = "-baselinerepo"; String BNDDRIVER = "-bnd-driver"; @@ -158,7 +159,6 @@ public interface Constants { String GESTALT_SHELL = "shell"; String GROUPID = "-groupid"; String INCLUDE = "-include"; - String INCLUDEZEROMAJOR = "-includezeromajor"; String INCLUDERESOURCE = "-includeresource"; String INCLUDEPACKAGE = "-includepackage"; String INVALIDFILENAMES = "-invalidfilenames"; @@ -333,7 +333,7 @@ public interface Constants { Set options = Sets.of(BASELINE, BUILDPATH, BUMPPOLICY, CONDUIT, CLASSPATH, COMPRESSION, CONSUMER_POLICY, DEPENDSON, DONOTCOPY, EXPORT_CONTENTS, FAIL_OK, INCLUDE, - INCLUDEZEROMAJOR, INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS, NOUSES, NOBUNDLES, PEDANTIC, PLUGIN, POM, PROVIDER_POLICY, + BASELINEINCLUDEZEROMAJOR, INCLUDERESOURCE, MAKE, MANIFEST, NOEXTRAHEADERS, NOUSES, NOBUNDLES, PEDANTIC, PLUGIN, POM, PROVIDER_POLICY, REMOVEHEADERS, RESOURCEONLY, SOURCES, SOURCEPATH, SUB, RUNBUNDLES, RUNPATH, RUNSYSTEMPACKAGES, RUNSYSTEMCAPABILITIES, RUNPROPERTIES, REPORTNEWER, UNDERTEST, TESTPATH, TESTPACKAGES, NOMANIFEST, DEPLOYREPO, RELEASEREPO, SAVEMANIFEST, RUNVM, RUNPROGRAMARGS, WAB, WABLIB, RUNFRAMEWORK, RUNFW, RUNKEEP, RUNTRACE, diff --git a/docs/_chapters/180-baselining.md b/docs/_chapters/180-baselining.md index d24c31229b..05b5b7df64 100644 --- a/docs/_chapters/180-baselining.md +++ b/docs/_chapters/180-baselining.md @@ -12,9 +12,9 @@ APIs are compared for backward compatibility using the semantic versioning rules During the build, bnd will check the [`-baseline` instruction](../instructions/baseline.html) at the end of the build when the JAR is ready. This instruction is a selector on the symbolic name of the building bundle. If it matches, the baselining is started with one exception: by default, the bundle/package version must be 1.0.0 or above. If the version is less (i.e. major version being `0`) no baselining errors are reported, the purpose is to allow the [primordial baseline to be established without errors](https://semver.org/#spec-item-4). -To enable baselining for versions in the range `[0.1.0, 1.0.0)`, use the [`-includezeromajor` instruction](../instructions/includezeromajor.html): +To enable baselining for versions in the range `[0.1.0, 1.0.0)`, use the [`-baselineincludezeromajor` instruction](../instructions/baselineincludezeromajor.html): - -includezeromajor: true + -baselineincludezeromajor: true This will enable baseline error reporting for packages with major version `0` (except for `0.0.x` versions which are still excluded). diff --git a/docs/_instructions/_ext/includezeromajor.md b/docs/_instructions/_ext/baselineincludezeromajor.md similarity index 75% rename from docs/_instructions/_ext/includezeromajor.md rename to docs/_instructions/_ext/baselineincludezeromajor.md index 693e51df3c..7c3b382151 100644 --- a/docs/_instructions/_ext/includezeromajor.md +++ b/docs/_instructions/_ext/baselineincludezeromajor.md @@ -1,13 +1,13 @@ --- layout: default class: Project -title: -includezeromajor BOOLEAN +title: -baselineincludezeromajor BOOLEAN summary: Enable baselining for packages with major version 0. --- -# -includezeromajor +# -baselineincludezeromajor -The `-includezeromajor` instruction enables baseline error reporting for packages with major version `0` (i.e., versions in the range `[0.1.0, 1.0.0)`). +The `-baselineincludezeromajor` instruction enables baseline error reporting for packages with major version `0` (i.e., versions in the range `[0.1.0, 1.0.0)`). By default, bnd does not report baselining errors for packages with major version `0`, following the [semantic versioning spec](https://semver.org/#spec-item-4) which states that "Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable." @@ -17,7 +17,7 @@ Example: ``` -baseline: * --includezeromajor: true +-baselineincludezeromajor: true ``` This is useful when you want to enforce semantic versioning discipline during the initial development phase (0.x versions) while still excluding the very early `0.0.x` versions.