Versions Transformation
Extension: revapi.versions
This is a generic transformation of differences based on the changes of the version between the old and new archives.
It can be useful for automatically allowing certain kinds of changes based on the version difference (e.g. allow breaking changes in a new major version).
By default, it assumes semantic versioning of the archives but can be reconfigured to support different versioning policies.
The extension is disabled by default and has to be explicitly configured to be switched on.
The documentation of the now deprecated revapi.semver.ignore transformation, which served a similar purpose in the past, is
here.
|
Sample Configuration
The following is the default configuration of the extension:
{
"enabled": false, (1)
"semantic0": true, (2)
"versionIncreaseAllows": { (3)
"major": {
"severity": "BREAKING"
},
"minor": {
"severity": "NON_BREAKING"
},
"patch": {
"severity": "EQUIVALENT"
}
},
"onAllowed": { (4)
"attachments": {
"breaksVersioningRules": "false"
}
},
"onDisallowed": { (5)
"criticality": "error",
"attachments": {
"breaksVersioningRules": "true"
}
},
"passThroughDifference": [] (6)
}
1 | The extension is disabled by default. |
2 | semantic0 tells the extension to honor the special rules for 0.y.z versions in semantic versioning.
See below for a more detailed discussion of the attribute. |
3 | versionIncreaseAllows specifies the rules for allowed changes in different version increase situations.
x.y.z.suffix versioning is required for this to work.
By default, an increase in the major version allows breaking changes, an increase in minor version allows non-breaking changes and a patch version only allows equivalent API changes. |
4 | onAllowed specifies the modifications to be performed on differences that are deemed allowed by the version increase rules.
By default, a "marker" attachment noting that the versioning rules have been broken is set to false . |
5 | onDisallowed specifies the modifications to be performed on differences that are deemed disallowed by the version increase rules.
By default, the criticality of the difference is set to error and "marker" attachment noting that the versioning rules have been broken is set to true . |
6 | One can define a set of difference codes that are not going to be touched by this transformation and will be let through as is. This is useful when you want certain kinds of differences to never be allowed. By default, this list is empty. |
To use this default configuration, all you need to do is to specifically enable the extension:
{
"extension": "revapi.versions",
"configuration": {
"enabled": true
}
}
or in XML:
<revapi.versions>
<enabled>true</enabled>
</revapi.versions>
Properties
enabled
-
Defaults to
false
. When set totrue
, the extension is enabled and checks for the versioning rules. semantic0
-
The semantic versioning specifies that if the major version is
0
, any kind of change can happen at any time because the API is not considered stable. If set totrue
(which is the default), this attribute makes the extension honor this behavior (i.e. any difference is allowed on any kind of version increase). versionIncreaseAllows
-
Within this attribute, one can specify the rules to allow differences for different kinds of version increases.
major
-
Specifies the rules for allowing differences when a major version increases. This can either directly contain the following configuration options or be a list thereof. If more than 1 rule is specified, a difference matches if at least 1 of the rules is satisfied.
regex
-
Defaults to
false
. When set totrue
, textual properties are considered regular expressions instead of clear text. severity
-
The maximum severity of a difference to be allowed. One of
NONE
,EQUIVALENT
,NON_BREAKING
,POTENTIALLY_BREAKING
,BREAKING
. Cannot be matched as a regular expression. criticality
-
The maximum criticality of a difference to be allowed. This is one of criticalities configured in the pipeline configuration. This cannot be matched using a regular expression.
classification
-
This is a map of classifications that a difference needs to maximally have to be allowed. The keys are one of
BINARY
,SOURCE
,SEMANTIC
,OTHER
(i.e. one of compatibility types) and the values are the severities:EQUIVALENT
,NON_BREAKING
,POTENTIALLY_BREAKING
orBREAKING
. code
-
The code (i.e. the identifier) of the difference that should be allowed.
justification
-
The text of the justification that should make the difference be allowed. If
regex
is true, this is understood to be a regular expression, otherwise an exact match is used. attachments
-
The map of attachments that the difference needs to have in order to be allowed. The keys always need to match exactly, the values are interpreted either exactly or as a regular expression depending on the value of the
regex
property. inArchives
-
A list of archives in which this rule applies. These are either exact matches or regular expressions depending on the value of the
regex
attribute. The values are compared with the "base names" of the archives - i.e. the name without a version.
minor
-
This attribute specifies the allowed changes in a minor version increase. The options are the same as with the major version increase.
patch
-
This attribute specifies the allowed changes in a patch version increase. The options are the same as with the major version increase.
suffix
-
This attribute specifies the allowed changes when only a suffix. The options are the same as with the major version increase + the
old
andnew
attributes described below.old
-
The suffix of the old version, e.g.
Beta
. Ifregex
attribute is true, this is considered a regular expression. new
-
The suffix of the new version, e.g.
Final
. Ifregex
attribute is true, this is considered a regular expression.
onAllowed
-
This configuration describes how to modify the differences that we found to conform to the versioning rules and are therefore allowed.
remove
-
Defaults to
false
. Iftrue
, the difference is removed from the analysis results. classification
-
This is a map of classifications (same in the format with the classification specification in the version increase configuration). These classifications will be added to the difference classification (overwriting the pre-existing classifications, if any).
justification
-
This either the exact text of the justification that should be added to the difference, or an object with
prepend
and/orappend
keys using which you can prepend or append some text to pre-existing justification. description
-
This either the exact text of the description that should be added to the difference, or an object with
prepend
and/orappend
keys using which you can prepend or append some text to pre-existing description. criticality
-
The criticality that should be set on the difference.
attachments
-
The map of attachments that should be added to the difference, potentially overwriting any pre-existing ones.
onDisallowed
-
This has the same configuration properties as
onAllowed
but describes the modifications to be made on the disallowed differences. passThroughDifferences
-
This is a list of difference codes that should be ignored by this extension and be passed on to the next stages as is.
Examples
Don’t allow any changes between a beta, and a final version
Let’s assume that we mark the beta versions with the beta
suffix and final versions are without any suffix whatsoever. We want to make sure that there are no API changes at all between the beta and the final version.
<revapi.versions>
<versionIncreaseAllows>
<suffix>
<regex>true</regex>
<old>[bB]eta</old>
<severity>NONE</severity>
</suffix>
</versionIncreaseAllows>
</revapi.versions>
Allow adding method to the interfaces, but no other breaking changes in non-major releases
Let’s assume that the interfaces in our library are not meant for implementation but merely for providing a public interface to the private implementations. Therefore, our policy is that we don’t consider adding methods to interfaces as a breaking change.
<revapi.versions>
<versionIncreaseAllows>
<minor>
<item>
<code>java.method.addedToInterface</code>
</item>
<item>
<severity>NON_BREAKING</severity>
</item>
</minor>
<patch>
<item>
<code>java.method.addedToInterface</code>
</item>
<item>
<severity>EQUIVALENT</severity>
</item>
</patch>
</versionIncreaseAllows>
</revapi.versions>
Allow changes that are marked as ok by other rules
Using the transformation blocks, one can configure the order in which the differences are processed by different extensions. We can take advantage of that and using more powerful transformations, like Differences Transformation, to pick and choose which changes are ok.
In this example we have a special revapi.differences
instance called manually-vetted
that is meant to capture differences that the maintainer manually examined and deemed ok for the next release.
These differences don’t conform to "the normal" set of rules otherwise required.
In Maven, one can configure the transform blocks like this:
<plugin>
<groupId>org.revapi</groupId>
<artifactId>revapi-maven-plugin</artifactId>
<version>0.15.0</version>
<configuration>
<pipelineConfiguration>
<transformBlocks>
<block>
<item>manually-vetted</item>
<item>revapi.versions</item>
</block>
</transformBlocks>
</pipelineConfiguration>
</configuration>
</plugin>
With the transform block in place, we can configure the manually vetted differences and versions extensions. Notice the multiple rules for each version increase - a difference is considered OK if at least 1 of the rules is satisfied.
<plugin>
<groupId>org.revapi</groupId>
<artifactId>revapi-maven-plugin</artifactId>
<version>0.15.0</version>
<configuration>
<analysisConfiguration>
<revapi.differences id="manually-vetted">
<attachments>
<vetted>ok</vetted>
</attachments>
<differences>
… any difference matches configured using the Differences Transformation…
</differences>
</revapi.differences>
<revapi.versions>
<versionIncreaseAllows>
<major>
<item>
<severity>BREAKING</severity>
</item>
<item>
<attachments>
<vetted>ok</vetted>
</attachments>
</item>
</major>
<minor>
<item>
<severity>NON_BREAKING</severity>
</item>
<item>
<attachments>
<vetted>ok</vetted>
</attachments>
</item>
</minor>
<patch>
<item>
<severity>EQUIVALENT</severity>
</item>
<item>
<attachments>
<vetted>ok</vetted>
</attachments>
</item>
</patch>
</versionIncreaseAllows>
</revapi.versions>
</analysisConfiguration>
</configuration>
</plugin>