![CI status](https://secure.travis-ci.org/jeluard/semantic-versioning.png)

Version number changes implications are not always clearly identified. Can I be sure this new minor version didn't break the public API? 
As a library writer, how to continuously validate I don't break binary compatibility?

`semantic-versioning` is a Java library allowing to validate (using bytecode inspection) if library version numbers follows Semantic Versioning principles as defined by [Semantic Versioning](http://semver.org).
It can check JAR files or classes to identify changes between versions and validate if the new version number is correct according to semver.

`semantic-versioning` is available as an [API](#api), a [command line tool](#cli) and a [maven enforcer](http://maven.apache.org/enforcer/maven-enforcer-plugin/) [rule](#rule).

<a name="api"></a>
## API overview

Semantic Versioning also provides an API for programmatically validating your project's version number.

```java
final File previousJar = ...;
final File currentJar = ...;
        
final Comparer comparer = new Comparer(previousJar, currentJar, ..., ...);
final Delta delta = comparer.diff();

final String compatibilityType = ...;

//Validates that computed and provided compatibility type are compatible.
final Delta.CompatibilityType expectedCompatibilityType = Delta.CompatibilityType.valueOf(compatibilityType);
final Delta.CompatibilityType detectedCompatibilityType = delta.computeCompatibilityType();
if (detectedCompatibilityType.compareTo(expectedCompatibilityType) > 0) {
  //Not compatible.
}

//Provide version number for previous and current Jar files.
final Version previous = Version.parse(...);
final Version current = Version.parse(...);

//Validates that current version number is valid based on semantic versioning principles.
final boolean compatible = delta.validate(previous, current);
```

<a name="cli"></a>
## CLI

This simple command line tool looks at Java JAR files and determine API changes.

### Built-in help

```
% java -jar semver.jar --help
Semantic Version validator.

Usage: semver [options]

Options:
  --base-jar JAR          The base jar.
  --base-version VERSION  Version of the base jar (given with --base-jar).
  --check,-c              Check the compatibility of two jars.
  --diff,-d               Show the differences between two jars.
  --excludes EXCLUDE;...  Semicolon separated list of full qualified class names
						  or partly qualified class names with wild cards
                          to be excluded.
  --help,-h               Show this help and exit.
  --includes INCLUDE;...  Semicolon separated list of full qualified class names
						  or partly qualified class names with wild cards
                          to be included.
  --infer,-i              Infer the version of the new jar based on the previous
                          jar.
  --new-jar JAR           The new jar.
  --new-version VERSION   Version of the new jar (given with --new-jar).
  --validate,-v           Validate that the versions of two jars fulfil the
                          semver specification.
```

### Diff

Dump all changes between two JARs on standard output.

```
% java -jar semver.jar --diff --base-jar previousJar --new-jar current.jar
Class org.project.MyClass
 Added Class 
Class org.project.MyClass2
 Added Method method1
 Removed Field field1
 Changed Field field2 removed: final
```

### Excludes / Includes

In- or exclude classes for the validation by specifying a fully qualified 
class name or using wild cards. There are two wild cards: `*` and `**`.
`*` is a wild card for an arbitrary number of characters but at most one 
folder hierarchy. 
`**` is a wild card for an arbitrary number of characters and an arbitrary 
number of folder hierarchies. 

```
% java -jar semver.jar --excludes **/MyClass; org/**/MyClass; org/**/*Class;
```

### Check

Check compatibility type between two JARs.

```
% java -jar semver.jar --check --base-jar previousJar --new-jar current.jar
BACKWARD_COMPATIBLE_IMPLEMENTER
```

### Infer

Infer JAR version based on a previously versioned JAR.

```
% java -jar semver.jar --infer --base-version 1.0.0 --base-jar previous.jar --new-jar current.jar
1.0.1
```

### Validate

Validate JAR version based on a previously versioned JAR.

```
% java -jar semver.jar --validate --base-version 1.0.0 --base-jar previous.jar --new-version 1.0.1 --new-jar current.jar
true
```

<a name="rule"></a>
## Maven Enforcer Rule

The enforcer rule offers a rule for checking project's version against a previously released artifact.

### Checking a project's compatibility

In order to check your project's compatibility, you must add the enforcer rule as a dependency to
the maven-enforcer-plugin and then configure the maven-enforcer-plugin to run the rule:

```xml
<project>
  ...
  <build>
    ...
    <plugins>
      ...
      <plugin>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>1.0.1</version>
        ...
        <dependencies>
            ...
            <dependency>
                <groupId>org.semver</groupId>
                <artifactId>enforcer-rule</artifactId>
                <version>0.9.29</version>
            </dependency>
            ...
        </dependencies>
        ...
        <executions>
           ....
          <execution>
            <id>check</id>
            <phase>verify</phase>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <requireBackwardCompatibility implementation="org.semver.enforcer.RequireBackwardCompatibility">
                  <compatibilityType>BACKWARD_COMPATIBLE_IMPLEMENTER</compatibilityType>
                </requireBackwardCompatibility>
              </rules>
            </configuration>
          </execution>
          ...
        </executions>
        ...
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>
```

Once you have configured your project, maven-enforcer will be able to throw a build error if current version is not backward compatible with last released one. 

You can force strict checking (i.e. compatibility type must exactly match specified one):

```xml
<configuration>
  <rules>
    <requireBackwardCompatibility implementation="org.semver.enforcer.RequireBackwardCompatibility">
      ...
      <strictChecking>true</strictChecking>
      ...
    </requireBackwardCompatibility>
  </rules>
</configuration>
```

### Checking a project's version

In order to check your project's version, you must add the enforcer rule as a dependency to
the maven-enforcer-plugin and then configure the maven-enforcer-plugin to run the rule:

```xml
<project>
  ...
  <build>
    ...
    <plugins>
      ...
      <plugin>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>1.0.1</version>
        ...
        <dependencies>
            ...
            <dependency>
                <groupId>org.semver</groupId>
                <artifactId>enforcer-rule</artifactId>
                <version>0.9.29</version>
            </dependency>
            ...
        </dependencies>
        ...
        <executions>
           ....
          <execution>
            <id>check</id>
            <phase>verify</phase>
            <goals>
              <goal>enforce</goal>
            </goals>
            <configuration>
              <rules>
                <requireSemanticVersioningConformance implementation="org.semver.enforcer.RequireSemanticVersioningConformance" />
              </rules>
            </configuration>
          </execution>
          ...
        </executions>
        ...
      </plugin>
      ...
    </plugins>
    ...
  </build>
  ...
</project>
```

Once you have configured your project, maven-enforcer will be able to throw a build error if current version follows semantic versioning principles. 

## Dumping details

Dump details of detected changes:

```xml
<configuration>
  <rules>
    <require...>
      ...
      <dumpDetails>true</dumpDetails>
      ...
    </require...>
  </rules>
</configuration>
```

### Checking against a well known version

You can force check with a well known version:

```xml
<configuration>
  <rules>
    <require...>
      ...
      <previousVersion>1.0.0</previousVersion>
      ...
    </require...>
  </rules>
</configuration>
```

### Filtering

Both rules allow to filter classes/packages:

```xml
<require...>
  ...
  <includes>
    <include>org/project/MyClass</include>
    <include>org/project/internal</include>
  </includes>
  <excludes>
    <exclude>org/project/MyClass</exclude>
    <exclude>org/project/internal</exclude>
  </excludes>
  ...
</require...>
```

## Maven dependency

```xml
<dependency>
    <groupId>org.semver</groupId>
    <artifactId>enforcer-rule</artifactId>
    <version>0.9.29</version>
</dependency>
```

## License

Released under [Apache 2 license](http://www.apache.org/licenses/LICENSE-2.0.html).