diff options
-rw-r--r-- | enforcer-rule/src/main/java/org/semver/enforcer/AbstractEnforcerRule.java (renamed from enforcer-rule/src/main/java/org/semver/enforcer/CheckVersionRule.java) | 32 | ||||
-rw-r--r-- | enforcer-rule/src/main/java/org/semver/enforcer/RequireBackwardCompatibility.java | 61 | ||||
-rw-r--r-- | enforcer-rule/src/main/java/org/semver/enforcer/RequireSemanticVersioningConformance.java | 43 | ||||
-rw-r--r-- | enforcer-rule/src/site/apt/examples/backward-compatibility.apt.vm | 304 | ||||
-rw-r--r-- | enforcer-rule/src/site/apt/examples/semantic-versioning-conformance.apt.vm (renamed from enforcer-rule/src/site/apt/examples/checking-version.apt.vm) | 18 | ||||
-rw-r--r-- | enforcer-rule/src/site/apt/index.apt | 11 | ||||
-rw-r--r-- | enforcer-rule/src/site/apt/usage.apt.vm | 65 | ||||
-rw-r--r-- | pom.xml | 2 |
8 files changed, 500 insertions, 36 deletions
diff --git a/enforcer-rule/src/main/java/org/semver/enforcer/CheckVersionRule.java b/enforcer-rule/src/main/java/org/semver/enforcer/AbstractEnforcerRule.java index e819ca9..0fd0b36 100644 --- a/enforcer-rule/src/main/java/org/semver/enforcer/CheckVersionRule.java +++ b/enforcer-rule/src/main/java/org/semver/enforcer/AbstractEnforcerRule.java @@ -47,12 +47,10 @@ import org.semver.Version; /** * - * Checks {@link Version} for current {@link Artifact} compared to a previous {@link Artifact}. - * <br /> - * Fails if {@link Version} semantic is not respected. + * Abstract {@link EnforcerRule} implementation providing facilities for compatibility checking. * */ -public final class CheckVersionRule implements EnforcerRule { +public abstract class AbstractEnforcerRule implements EnforcerRule { private static final String SNAPSHOT_VERSION_SUFFIX = "-SNAPSHOT"; @@ -118,7 +116,7 @@ public final class CheckVersionRule implements EnforcerRule { final List<ArtifactVersion> availableVersions = getAvailableReleasedVersions(artifactMetadataSource, project, localRepository); if (availableVersions.isEmpty()) { - helper.getLog().info("No previously released version. Backward compatibility check not performed."); + helper.getLog().warn("No previously released version. Backward compatibility check not performed."); return; } @@ -150,22 +148,26 @@ public final class CheckVersionRule implements EnforcerRule { try { final Comparer comparer = new Comparer(previousJar, currentJar, extractFilters(this.includes), extractFilters(this.excludes)); final Delta delta = comparer.diff(); - final boolean compatible = delta.validate(previous, current); - if (!compatible) { - if (this.dumpDetails) { - Dumper.dump(delta); - } - throw new EnforcerRuleException("Current codebase incompatible with version <"+current+">. Version should be at least <"+delta.infer(previous)+">."); - } + + enforce(delta, previous, current); } catch (IOException e) { throw new EnforcerRuleException("Exception while checking compatibility: "+e.toString(), e); } } + protected abstract void enforce(final Delta delta, final Version previous, final Version current) throws EnforcerRuleException; + + protected final void fail(final Delta delta, final String message) throws EnforcerRuleException { + if (this.dumpDetails) { + Dumper.dump(delta); + } + throw new EnforcerRuleException(message); + } + protected final String getVersion(final Artifact artifact) { final String version = artifact.getVersion(); - if (version.contains(CheckVersionRule.SNAPSHOT_VERSION_SUFFIX)) { - return version.substring(0, version.indexOf(CheckVersionRule.SNAPSHOT_VERSION_SUFFIX)); + if (version.contains(AbstractEnforcerRule.SNAPSHOT_VERSION_SUFFIX)) { + return version.substring(0, version.indexOf(AbstractEnforcerRule.SNAPSHOT_VERSION_SUFFIX)); } return version; } @@ -175,7 +177,7 @@ public final class CheckVersionRule implements EnforcerRule { * @return true if specified version is a snapshot version */ protected final boolean isSnapshotVersion(final ArtifactVersion artifactVersion) { - return artifactVersion.toString().endsWith(CheckVersionRule.SNAPSHOT_VERSION_SUFFIX); + return artifactVersion.toString().endsWith(AbstractEnforcerRule.SNAPSHOT_VERSION_SUFFIX); } /** diff --git a/enforcer-rule/src/main/java/org/semver/enforcer/RequireBackwardCompatibility.java b/enforcer-rule/src/main/java/org/semver/enforcer/RequireBackwardCompatibility.java new file mode 100644 index 0000000..57050f7 --- /dev/null +++ b/enforcer-rule/src/main/java/org/semver/enforcer/RequireBackwardCompatibility.java @@ -0,0 +1,61 @@ +/** + * This software is licensed under the Apache 2 license, quoted below. + * + * Copyright 2010 Julien Eluard + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * [http://www.apache.org/licenses/LICENSE-2.0] + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.semver.enforcer; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.enforcer.rule.api.EnforcerRuleException; +import org.semver.Delta; +import org.semver.Version; + +/** + * + * Checks {@link Version} for current {@link Artifact} compared to a previous {@link Artifact}. + * <br /> + * Fails if current version is not backward compatible with previous one. {@link Delta.CompatibilityType} level can be specified. + * + */ +public final class RequireBackwardCompatibility extends AbstractEnforcerRule { + + /** + * Compatibility type expected. Must be one of {@link Delta.CompatibilityType} enum values. + * + * @parameter + */ + private String compatibilityType; + + @Override + protected void enforce(final Delta delta, final Version previous, final Version current) throws EnforcerRuleException { + if (this.compatibilityType == null) { + throw new IllegalArgumentException("A value for compatibilityType attribute must be provided."); + } + + final Delta.CompatibilityType expectedCompatibilityType; + try { + expectedCompatibilityType = Delta.CompatibilityType.valueOf(this.compatibilityType); + } catch (IllegalStateException e) { + throw new EnforcerRuleException("Compatibility type value must be one of "+Delta.CompatibilityType.values()); + } + + final Delta.CompatibilityType detectedCompatibilityType = delta.computeCompatibilityType(); + if (detectedCompatibilityType != expectedCompatibilityType) { + fail(delta, "Current codebase is not backward compatible ("+this.compatibilityType+") with version <"+previous+">. Compatibility type has been detected as <"+detectedCompatibilityType+">"); + } + } + +} diff --git a/enforcer-rule/src/main/java/org/semver/enforcer/RequireSemanticVersioningConformance.java b/enforcer-rule/src/main/java/org/semver/enforcer/RequireSemanticVersioningConformance.java new file mode 100644 index 0000000..608557e --- /dev/null +++ b/enforcer-rule/src/main/java/org/semver/enforcer/RequireSemanticVersioningConformance.java @@ -0,0 +1,43 @@ +/** + * This software is licensed under the Apache 2 license, quoted below. + * + * Copyright 2010 Julien Eluard + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * [http://www.apache.org/licenses/LICENSE-2.0] + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package org.semver.enforcer; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.enforcer.rule.api.EnforcerRuleException; +import org.semver.Delta; +import org.semver.Version; + +/** + * + * Checks {@link Version} for current {@link Artifact} compared to a previous {@link Artifact}. + * <br /> + * Fails if {@link Version} semantic is not respected. + * + */ +public final class RequireSemanticVersioningConformance extends AbstractEnforcerRule { + + @Override + protected void enforce(final Delta delta, final Version previous, final Version current) throws EnforcerRuleException { + final boolean compatible = delta.validate(previous, current); + if (!compatible) { + fail(delta, "Current codebase is incompatible with version <"+previous+">. Version should be at least <"+delta.infer(previous)+">."); + } + } + +} diff --git a/enforcer-rule/src/site/apt/examples/backward-compatibility.apt.vm b/enforcer-rule/src/site/apt/examples/backward-compatibility.apt.vm new file mode 100644 index 0000000..bfbf818 --- /dev/null +++ b/enforcer-rule/src/site/apt/examples/backward-compatibility.apt.vm @@ -0,0 +1,304 @@ +#* + * This software is licensed under the Apache 2 license, quoted below. + * + * Copyright 2010 Julien Eluard + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * [http://www.apache.org/licenses/LICENSE-2.0] + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + *# + +Checking a project's compatibility against older releases + +* Basic example + + In order to check your project's compatibility against an older release, you must add the enforcer rule as a dependency to + the maven-enforcer-plugin and then configure your the maven-enforcer-plugin to run the rule. + + By default current artifact will be checked against most recently released version (retrieved from either local or one of configured remote repositories). + +--- +<project> + ... + <build> + ... + <plugins> + ... + <plugin> + <artifactId>maven-enforcer-plugin</artifactId> + <version>1.0-beta-1</version> + ... + <dependencies> + ... + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </dependency> + ... + </dependencies> + ... + <executions> + .... + <execution> + <id>check-version</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> +--- + +* Checking against a specific released version + + You can check your project against a specific released version: + +--- +<project> + ... + <build> + ... + <plugins> + ... + <plugin> + <artifactId>maven-enforcer-plugin</artifactId> + <version>1.0-beta-1</version> + ... + <dependencies> + ... + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </dependency> + ... + </dependencies> + ... + <executions> + .... + <execution> + <id>check-version</id> + <phase>verify</phase> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireBackwardCompatibility implementation="org.semver.enforcer.RequireBackwardCompatibility"> + ... + <compatibilityType>BACKWARD_COMPATIBLE_IMPLEMENTER</compatibilityType> + <previousVersion>1.0.0</previousVersion> + ... + </requireBackwardCompatibility> + </rules> + </configuration> + </execution> + ... + </executions> + ... + </plugin> + ... + </plugins> + ... + </build> + ... +</project> +--- + +* Including classes + + By default all classes will be considered during checking process. You might want to only check a subset of classes/packages. This is achieved by specifying <<<includes>>>. + +--- +<project> + ... + <build> + ... + <plugins> + ... + <plugin> + <artifactId>maven-enforcer-plugin</artifactId> + <version>1.0-beta-1</version> + ... + <dependencies> + ... + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </dependency> + ... + </dependencies> + ... + <executions> + .... + <execution> + <id>check-version</id> + <phase>verify</phase> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireBackwardCompatibility implementation="org.semver.enforcer.RequireBackwardCompatibility"> + ... + <compatibilityType>BACKWARD_COMPATIBLE_IMPLEMENTER</compatibilityType> + <includes> + <include>org.project.MyClass</include> + </includes> + ... + </requireBackwardCompatibility> + </rules> + </configuration> + </execution> + ... + </executions> + ... + </plugin> + ... + </plugins> + ... + </build> + ... +</project> +--- + + We can specify multiple <includes> classes or packages. For example, to include <<<org.project.MyClass>>> class and <<<org.project.internal>>> package you would use a configuration like: + +--- +<project> + ... + <build> + ... + <plugins> + ... + <plugin> + <artifactId>maven-enforcer-plugin</artifactId> + <version>1.0-beta-1</version> + ... + <dependencies> + ... + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </dependency> + ... + </dependencies> + ... + <executions> + .... + <execution> + <id>check-version</id> + <phase>verify</phase> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireBackwardCompatibility implementation="org.semver.enforcer.RequireBackwardCompatibility"> + ... + <compatibilityType>BACKWARD_COMPATIBLE_IMPLEMENTER</compatibilityType> + <includes> + <include>org.project.MyClass</include> + <include>org.project.internal</include> + </includes> + ... + </requireBackwardCompatibility> + </rules> + </configuration> + </execution> + ... + </executions> + ... + </plugin> + ... + </plugins> + ... + </build> + ... +</project> +--- + +* Excluding classes + + You may also want to exclude some classes/packages. For instance internal code might evolve independently from published API. This is achieved by specifying <<<excludes>>>. + +--- +<project> + ... + <build> + ... + <plugins> + ... + <plugin> + <artifactId>maven-enforcer-plugin</artifactId> + <version>1.0-beta-1</version> + ... + <dependencies> + ... + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</version> + </dependency> + ... + </dependencies> + ... + <executions> + .... + <execution> + <id>check-version</id> + <phase>verify</phase> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireBackwardCompatibility implementation="org.semver.enforcer.RequireBackwardCompatibility"> + ... + <compatibilityType>BACKWARD_COMPATIBLE_IMPLEMENTER</compatibilityType> + <excludes> + <exclude>org.project.MyClass</exclude> + </excludes> + ... + </requireBackwardCompatibility> + </rules> + </configuration> + </execution> + ... + </executions> + ... + </plugin> + ... + </plugins> + ... + </build> + ... +</project> +--- diff --git a/enforcer-rule/src/site/apt/examples/checking-version.apt.vm b/enforcer-rule/src/site/apt/examples/semantic-versioning-conformance.apt.vm index 328abea..fdfd7dd 100644 --- a/enforcer-rule/src/site/apt/examples/checking-version.apt.vm +++ b/enforcer-rule/src/site/apt/examples/semantic-versioning-conformance.apt.vm @@ -56,7 +56,7 @@ Checking a project's version against older releases </goals> <configuration> <rules> - <checkVersionRule implementation="org.semver.enforcer.CheckVersionRule" /> + <requireSemanticVersioningConformance implementation="org.semver.enforcer.RequireSemanticVersioningConformance" /> </rules> </configuration> </execution> @@ -107,11 +107,11 @@ Checking a project's version against older releases </goals> <configuration> <rules> - <checkVersionRule implementation="org.semver.enforcer.CheckVersionRule"> + <requireSemanticVersioningConformance implementation="org.semver.enforcer.RequireSemanticVersioningConformance"> ... <previousVersion>1.0.0</previousVersion> ... - </checkVersionRule> + </requireSemanticVersioningConformance> </rules> </configuration> </execution> @@ -162,13 +162,13 @@ Checking a project's version against older releases </goals> <configuration> <rules> - <checkVersionRule implementation="org.semver.enforcer.CheckVersionRule"> + <requireSemanticVersioningConformance implementation="org.semver.enforcer.RequireSemanticVersioningConformance"> ... <includes> <include>org.project.MyClass</include> </includes> ... - </checkVersionRule> + </requireSemanticVersioningConformance> </rules> </configuration> </execution> @@ -217,14 +217,14 @@ Checking a project's version against older releases </goals> <configuration> <rules> - <checkVersionRule implementation="org.semver.enforcer.CheckVersionRule"> + <requireSemanticVersioningConformance implementation="org.semver.enforcer.RequireSemanticVersioningConformance"> ... <includes> <include>org.project.MyClass</include> <include>org.project.internal</include> </includes> ... - </checkVersionRule> + </requireSemanticVersioningConformance> </rules> </configuration> </execution> @@ -275,13 +275,13 @@ Checking a project's version against older releases </goals> <configuration> <rules> - <checkVersionRule implementation="org.semver.enforcer.CheckVersionRule"> + <requireSemanticVersioningConformance implementation="org.semver.enforcer.RequireSemanticVersioningConformance"> ... <excludes> <exclude>org.project.MyClass</exclude> </excludes> ... - </checkVersionRule> + </requireSemanticVersioningConformance> </rules> </configuration> </execution> diff --git a/enforcer-rule/src/site/apt/index.apt b/enforcer-rule/src/site/apt/index.apt index 9a22674..2887116 100644 --- a/enforcer-rule/src/site/apt/index.apt +++ b/enforcer-rule/src/site/apt/index.apt @@ -23,15 +23,10 @@ Semantic Versioning Enforcer Rule * Rules Overview - The Semantic Versioning Enforcer Rule has the following rule. + The Semantic Versioning Enforcer Rule has the following rules. - * <<<checkVersionRule>>> checks a project version number against an older release. + * {{{./examples/semantic-versioning-conformance.html}requireSemanticVersioningConformance}} checks a project version number against an older release. -* Examples - - To provide you with better understanding of some usages of Semantic Versioning Enforcer Rule, - you can take a look into the following example: - - * {{{./examples/checking-version.html}Checking a project's version against an older release}} + * {{{./examples/backward-compatibility.html}requireBackwardCompatibility}} checks a project artifact against an older release. [] diff --git a/enforcer-rule/src/site/apt/usage.apt.vm b/enforcer-rule/src/site/apt/usage.apt.vm index 9a21ac0..fc9c196 100644 --- a/enforcer-rule/src/site/apt/usage.apt.vm +++ b/enforcer-rule/src/site/apt/usage.apt.vm @@ -22,6 +22,65 @@ Usage * Basic Usage +** 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: + +--- +<project> + ... + <build> + ... + <plugins> + ... + <plugin> + <artifactId>maven-enforcer-plugin</artifactId> + <version>1.0-beta-1</version> + ... + <dependencies> + ... + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${project.version}</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. + + Some more detailed {{{./examples/backward-compatibility.html}examples}} of the <<<requireBacwardCompatibility>>> rule. + + ** Checking a project's version In order to check your project's version, you must add the enforcer rule as a dependency to @@ -58,7 +117,7 @@ Usage </goals> <configuration> <rules> - <checkVersionRule implementation="org.semver.enforcer.CheckVersionRule" /> + <requireSemanticVersioningConformance implementation="org.semver.enforcer.RequireSemanticVersioningConformance" /> </rules> </configuration> </execution> @@ -74,6 +133,6 @@ Usage </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. + Once you have configured your project, maven-enforcer will be able to throw a build error if current version follows semantic versioning principles. - Some more detailed {{{./examples/checking-version.html}examples}} of the <<<checkVersionRule>>> rule. + Some more detailed {{{./examples/semantic-versioning-conformance.html}examples}} of the <<<requireSemanticVersioningConformance>>> rule. @@ -7,7 +7,7 @@ <version>0.9.4-SNAPSHOT</version> <packaging>pom</packaging> - <name>Semantic Versioning Parent</name> + <name>Semantic Versioning</name> <inceptionYear>2010</inceptionYear> <url>http://github.com/jeluard/semantic-versioning</url> |