Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 66 additions & 1 deletion biz.aQute.bndlib.tests/test/test/baseline/BaselineTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -263,6 +269,65 @@ 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");
// 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();) {
assertTrue(older.check());
assertTrue(newer.check());

DiffPluginImpl differ = new DiffPluginImpl();
Baseline baseline = new Baseline(older, differ);

Set<Info> infoSet = baseline.baseline(n, o, null);
assertEquals(1, infoSet.size());
for (Info info : infoSet) {
// 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");
}
}
}
}

@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");
// 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();) {
assertTrue(older.check());
assertTrue(newer.check());

DiffPluginImpl differ = new DiffPluginImpl();
Baseline baseline = new Baseline(older, differ);

Set<Info> infoSet = baseline.baseline(n, o, null);
assertEquals(1, infoSet.size());
for (Info info : infoSet) {
// 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);
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.
Expand Down
17 changes: 15 additions & 2 deletions biz.aQute.bndlib/src/aQute/bnd/build/ProjectBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 baselineincludezeromajor 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 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.",
getBsn(), repo, version.getWithoutQualifier(), new Version(version.getMajor()));
Expand Down Expand Up @@ -649,6 +658,10 @@ public Jar getBaselineJar() throws Exception {
return null;
}

private boolean isIncludeZeroMajorEnabled() {
return project.is(Constants.BASELINEINCLUDEZEROMAJOR);
}

/**
* Remove any staging versions that have a variant with a higher qualifier.
*
Expand Down
19 changes: 19 additions & 0 deletions biz.aQute.bndlib/src/aQute/bnd/differ/Baseline.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,20 @@ public static class BundleInfo {
Version olderVersion;
Version suggestedVersion;
String releaseRepository;
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;
}
}

/**
Expand Down Expand Up @@ -319,10 +329,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."
* <p>
* 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 <a href="https://semver.org/#spec-item-4">SemVer</a>
*/
private boolean mismatch(Version older, Version newer) {
if (includeZeroMajor) {
// 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;
}

Expand Down
3 changes: 2 additions & 1 deletion biz.aQute.bndlib/src/aQute/bnd/osgi/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -332,7 +333,7 @@ public interface Constants {

Set<String> 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,
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,
Expand Down
8 changes: 7 additions & 1 deletion docs/_chapters/180-baselining.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 [`-baselineincludezeromajor` instruction](../instructions/baselineincludezeromajor.html):

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

Expand Down
25 changes: 25 additions & 0 deletions docs/_instructions/_ext/baselineincludezeromajor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
layout: default
class: Project
title: -baselineincludezeromajor BOOLEAN
summary: Enable baselining for packages with major version 0.
---

# -baselineincludezeromajor

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

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

Default value is `false`.
22 changes: 21 additions & 1 deletion docs/_instructions/_ext/diffpackages.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,26 @@ 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.

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

## Examples

Exclude internal packages from baselining:

-diffpackages: !*.internal.*, *

Set threshold for changes:

-diffpackages: *;threshold=MINOR
Loading