Skip to content

Commit efcbdc7

Browse files
committed
README: add a section about the enforcer config
This commit is dedicated to Tobias Pietzsch.
1 parent 0450638 commit efcbdc7

1 file changed

Lines changed: 172 additions & 0 deletions

File tree

README.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,178 @@ See these examples for guidance:
2323
* [ImageJ 1.x plugin template](https://github.com/imagej/example-legacy-plugin)
2424
* [ImageJ tutorials](https://github.com/imagej/tutorials)
2525

26+
## Enforcer rules declared in this parent
27+
28+
The `pom-scijava-base` parent POM declares several
29+
[enforcer](http://maven.apache.org/enforcer/maven-enforcer-plugin/) rules which
30+
we believe make SciJava-based projects more reproducible and more consistent:
31+
32+
* __Plugin versions.__ Out of the box, Maven does not require plugins used to
33+
declare a version. But plugin versions must be declared to ensure
34+
reproducible builds. Otherwise, the version of Maven core you use at build
35+
time will determine which plugin versions are used, and the behavior might
36+
differ between builds.
37+
38+
* __No duplicate classes.__ If two dependencies define the same class, then
39+
it introduces the possibility of serious class-loading issues. Which version
40+
of the class should be chosen? In some scenarios, classes from one part of a
41+
certain library may be loaded from dependency `foo`, but classes from a
42+
different part of that same library at a _different version_ may be loaded
43+
from dependency `bar`. When this happens, difficult-to-understand compiler
44+
errors, or even runtime errors, may occur. Best practice is to ensure that
45+
all classes come onto the classpath from exactly _one_ source.
46+
47+
* __No too-new dependencies.__ When a project is compiled for Java version X,
48+
then it may not use any dependencies which require a version newer than X.
49+
Otherwise, your project is lying about needing only version X.
50+
51+
* __No circular dependencies.__ Actually, this is a central rule of Maven. But
52+
we configure the Enforcer to explicitly check for it, just to be safe. It is
53+
always possible to avoid circular dependencies; if you feel like you need
54+
one, you should instead solve it in one of the following ways, depending on
55+
how much code is co-dependent:
56+
1. Combine the co-dependent artifacts into a single artifact.
57+
2. Introduce a third artifact to house the co-dependent code, which depends
58+
on the other two artifacts.
59+
3. If all else fails, write to the
60+
[SciJava list](http://groups.google.com/group/scijava) for help.
61+
62+
* __Reproducible builds.__ This rule means no `SNAPSHOT` dependencies, no
63+
`SNAPSHOT` parents, and no `SNAPSHOT` plugin versions. A snapshot version is
64+
not immutable, which means that code which depends on a snapshot may build
65+
today, but not build tomorrow, if the snapshot is later changed. The best way
66+
to avoid this conundrum is to _never depend on `SNAPSHOT` versions_. Snapshot
67+
are best used for testing only; they can be used transiently, but their use
68+
should never make it onto the main integration branch (i.e., `master`) of a
69+
project. See also
70+
[Using snapshot couplings during development](https://imagej.net/Architecture#Using_snapshot_couplings_during_development).
71+
72+
* __Developer roles.__ SciJava-based projects define developers and
73+
contributors with roles matching the
74+
[SciJava team roles](http://imagej.net/Team). Doing this is vital for
75+
consistency, and for communicating expectations to the community. By being
76+
careful about which developers are pledging which sorts of responsibility,
77+
the social status of each project becomes much clearer, and which social
78+
actions to take in various circumstances becomes a more tractable problem.
79+
We have [automated tooling](https://github.com/scijava/mediawiki-maven-info)
80+
which generates MediaWiki sidebar templates for all components of the
81+
[ImageJ software stack](https://imagej.net/Architecture#Definitions); this
82+
tooling requires SciJava developer roles to be present for sensible results.
83+
84+
* __Required metadata.__ Every SciJava-based project must override key pieces
85+
of metadata, including the `name`, `description`, `url`, `inceptionYear`,
86+
`organization`, `licenses`, `developers`, `contributors`, `mailingLists`,
87+
`scm`, `issueManagement` and `ciManagement` elements, as well as the
88+
`license.licenseName` and `license.copyrightOwners` properties.
89+
There are several reasons for requiring these overrides:
90+
* __Avoid inadvertent inheritance.__ The `pom-scijava-base` POM itself
91+
declares all of this metadata for itself (e.g., its `<scm>` block defines
92+
where the `pom-scijava-base` source code is managed, and this information
93+
is necessary for the tooling which cuts releases of the
94+
`pom-scijava-base` POM itself). For better and worse, when extending
95+
`pom-scijava-base`, the child POM inherits all of these elements (except
96+
for `<name>`, but that is the sole exception in the above list). If the
97+
child POM does not override each and every one of these elements, then it
98+
will inadvertently inherit the incorrect values from the
99+
`pom-scijava-base` parent. Furthermore, due to a quirk/limitation in
100+
Maven, if you specify an empty block (e.g., `<contributors />`), then the
101+
non-empty value from the ancestor will take precedence in the
102+
interpolated POM. Hence, we enforce that all of these fields are
103+
overridden with _non-empty_ values. See below for advice on how to best
104+
override specific metadata fields.
105+
* __Present the project's metadata simply and clearly.__ For humans, being
106+
able to look at a project POM and clearly see the metadata is very
107+
helpful for understanding the project. Whereas when inheritance is
108+
involved, the human must be patient enough to dig through the ancestor
109+
POMs manually looking for the information, or else knowledgeable enough
110+
to know that they should actually use `mvn help:effective-pom` and check
111+
the metadata there instead, to know the actual values.
112+
* __Make the metadata easier for tooling to consume.__ Maven-based tooling
113+
which uses the interpolated POM will be able to extract the correct
114+
inherited metadata from a POM, sure. But in many cases, it is much
115+
simpler and more natural, especially for Maven non-experts, to code
116+
tooling using shell scripts and similar approaches. In those cases, it is
117+
much easier if the tooling can simply extract the metadata from the child
118+
POM itself and be guaranteed that the values there are the correct ones,
119+
without needing to recurse into parent POMs whose contents may be less
120+
trivial to inspect.
121+
* __Make it easier to maintain license headers in the sources.__ Putting a
122+
license blurb at the top of each source file is legal best practice, but
123+
it is undeniably a hassle, which is one reason many projects do not
124+
bother. But with the `license-maven-plugin`, generating and maintaining
125+
these license headers becomes very easy—as long as the `inceptionYear`,
126+
`license.projectLicense` and `license.copyrightOwners` values are
127+
provided in the POM. At that point, you can just invoke `mvn
128+
license:update-file-header license:update-project-license` and your work
129+
is done.
130+
* __Encourage responsible metadata curation.__ As a project maintainer,
131+
_you_ are responsible for your project's metadata. Yes, it is a hassle to
132+
specify it. But regardless, you need to understand where (if anywhere)
133+
your project lives in SCM, which (if any) system is being used to
134+
automatically build it, and so on. You have legal and social obligations
135+
to clearly communicate the project license, to clearly document community
136+
expectations, to give credit where credit is due, etc.
137+
138+
The full set of Enforcer rules as of `pom-scijava-base` version 3.0.0 can be
139+
[seen here](https://github.com/scijava/pom-scijava-base/blob/pom-scijava-base-3.0.0/pom.xml#L542-L638).
140+
141+
### How to override a field with an "empty" value
142+
143+
For some projects, you may have "empty" metadata fields, and you may be unsure
144+
how best to override those values accordingly. The most common scenarios are:
145+
146+
* If your project has no contributors, write:
147+
```xml
148+
<contributors>
149+
<!--
150+
NB: Need at least one element to override the parent.
151+
See: https://issues.apache.org/jira/browse/MNG-5220
152+
-->
153+
<contributor>
154+
<name>None</name>
155+
</contributor>
156+
</contributors>
157+
```
158+
* If your project has no discussion forum or mailing list, write:
159+
```xml
160+
<mailingLists>
161+
<mailingList>
162+
<name>None</name>
163+
</mailingList>
164+
</mailingLists>
165+
```
166+
But actually, you are warmly welcome to use the
167+
[ImageJ Forum](http://forum.imagej.net/) for discussing your project,
168+
so instead it is better to write:
169+
```xml
170+
<mailingLists>
171+
<mailingList>
172+
<name>ImageJ Forum</name>
173+
<archive>http://forum.imagej.net/</archive>
174+
</mailingList>
175+
</mailingLists>
176+
```
177+
* If your project has no CI, write:
178+
```xml
179+
<ciManagement>
180+
<system>None</system>
181+
</ciManagement>
182+
```
183+
* If your project has no issue tracker, write:
184+
```xml
185+
<issueManagement>
186+
<system>None</system>
187+
</issueManagement>
188+
```
189+
* If your project does not live in SCM, then write:
190+
```xml
191+
<scm>
192+
<system>None</system>
193+
</scm>
194+
```
195+
But as an aside, in this case, we strongly encourage you to adopt an SCM;
196+
[check yourself before you wreck yourself](https://imagej.net/Distribution).
197+
26198
## Getting help with Maven
27199

28200
For more information about Maven, see:

0 commit comments

Comments
 (0)