elharo commented on issue #91:
URL: 
https://github.com/apache/maven-artifact-plugin/issues/91#issuecomment-5846872300

   ## Proposed feature: verifying artifact checksums
   
   This is a draft of the user-facing description for the new goal, to be 
turned into documentation once the goal exists. Feedback on the design choices 
(in particular the two questions at the end) is welcome.
   
   ### The problem
   
   Every ASF release publishes checksum files next to the artifacts: `.sha1` 
and `.md5` for everything in the repository, and additionally `.sha512` for the 
source release archive.
   
   To confirm that the file on your disk is the file that was actually 
published, you have to compute a digest of your local copy and compare it with 
the published value. Doing that by eye is unpleasant and error-prone:
   
   - a single transposed character in a 128 character hex string is very hard 
to spot,
   - it is easy to skip an artifact, because there is no list telling you what 
should have been checked,
   - the repetition is tedious, since a release of a multi-module project has 
one artifact per module plus sources, javadoc, the BOM and the source release 
archive.
   
   The plugin already knows how to compute digests of build output: 
`artifact:buildinfo` records a `sha512` for every file it describes, and 
`artifact:describe-build-output` prints a `sha256` next to each file. What is 
missing is the comparison against a value that was published somewhere else, 
which is exactly the step a release manager performs by hand today.
   
   ### The goal
   
   A goal that computes the digest of the artifacts your build has produced, 
compares it with the expected value that you supply, and fails the build if 
they differ.
   
   It is a verification tool: it does not publish or generate anything. You 
tell it what the published checksum is supposed to be, and it tells you whether 
your local file agrees with it.
   
   ### Usage
   
   #### Verifying the main artifact
   
   The simplest case is the one in the original report: the main artifact of 
the project, that is the jar for `jar` packaging and the POM for `pom` 
packaging.
   
   ```
   $ mvn clean verify artifact:verify-checksum -Dsha512=1a2b3c4d5e6f7890...
   ```
   
   If the computed digest equals the supplied value, the goal reports a match 
and the build continues. If it differs, the build fails and both values are 
printed so that the difference can be seen.
   
   #### Verifying a particular attached artifact
   
   Most release artifacts are attached artifacts, identified by a classifier 
and an extension, and are named that way in the published file name. Use the 
same pair in brackets after the algorithm name:
   
   ```
   $ mvn clean verify artifact:verify-checksum 
"-Dsha512[source-release:zip]=4d5e6f708192a3b4..."
   ```
   
   - the part before the brackets is the digest algorithm,
   - the part in brackets is `<classifier>:<extension>`,
   - the main artifact, which has no classifier, is the short form with no 
brackets at all.
   
   To verify the POM of a `jar` project, which has no classifier either, leave 
the classifier empty:
   
   ```
   $ mvn clean verify artifact:verify-checksum "-Dsha512[:pom]=7c8d9e0f1a2b..."
   ```
   
   > **Quote the property.** The square brackets are glob characters in most 
shells. Unquoted, the argument may be expanded away or, in shells that fail on 
unmatched globs, abort the command. Always write 
`-D"sha512[source-release:zip]=..."`.
   
   #### Verifying several artifacts at once
   
   Repeat the property, once per artifact, in a single invocation. This is the 
shape of a full release verification, for `maven-artifact-plugin` 3.7.0:
   
   ```
   $ mvn clean deploy artifact:verify-checksum \
       -Dsha512=1a2b3c4d5e6f7890... \
       "-Dsha512[:pom]=7c8d9e0f1a2b..." \
       "-Dsha512[sources:jar]=9f0a1b2c3d4e..." \
       "-Dsha512[javadoc:jar]=5a6b7c8d9e0f..." \
       "-Dsha512[source-release:zip]=4d5e6f708192..." \
       "-Dsha512[cyclonedx:xml]=1b2c3d4e5f60..." \
       "-Dsha512[cyclonedx:json]=7e8f9a0b1c2d..."
   ```
   
   Every artifact named must be present in the build and every digest must 
match, otherwise the build fails.
   
   #### Publishing a repeatable configuration
   
   Long command lines are easy to mistype and awkward to keep. The expected 
values can be declared in the POM instead, which also makes them reviewable and 
repeatable, and lets the check run as part of the build:
   
   ```xml
   <build>
     <plugins>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-artifact-plugin</artifactId>
         <version>3.7.1-SNAPSHOT</version>
         <configuration>
           <checksums>
             <checksum>
               <algorithm>sha512</algorithm>
               <expected>1a2b3c4d5e6f7890...</expected>
             </checksum>
             <checksum>
               <algorithm>sha512</algorithm>
               <classifier>source-release</classifier>
               <extension>zip</extension>
               <expected>4d5e6f708192a3b4...</expected>
             </checksum>
             <checksum>
               <algorithm>sha1</algorithm>
               <expected>2b3c4d5e6f708192...</expected>
             </checksum>
           </checksums>
         </configuration>
       </plugin>
     </plugins>
   </build>
   ```
   
   An entry without `classifier` and `extension` refers to the main artifact. 
An entry without `algorithm` defaults to `sha512`, which is the algorithm the 
ASF dist area publishes.
   
   Values given on the command line are combined with the ones in the POM, so a 
CI job can verify the artifacts the POM covers and add a few more for a 
specific run.
   
   #### Running the check as part of the build
   
   The goal is not bound to a lifecycle phase by default and is meant to be 
invoked from the command line, like `artifact:compare` and 
`artifact:describe-build-output`. It can be bound to a phase once the artifacts 
it verifies exist, typically `verify` or `deploy`:
   
   ```xml
   <executions>
     <execution>
       <id>verify-checksums</id>
       <phase>verify</phase>
       <goals>
         <goal>verify-checksum</goal>
       </goals>
     </execution>
   </executions>
   ```
   
   #### Multi-module builds
   
   In a multi-module build each module has its own main artifact, and Maven 
scopes properties per project, so the goal can be run for one module at a time:
   
   ```
   $ mvn clean install
   $ mvn -pl core artifact:verify-checksum -Dsha512=1a2b3c4d5e6f7890...
   $ mvn -pl compat artifact:verify-checksum -Dsha512=3d4e5f607182...
   ```
   
   Alternatively, declare the `<checksums>` configuration in each module's own 
POM, which keeps the verification next to the module it belongs to and lets one 
command verify the whole reactor.
   
   ### Behaviour
   
   **Algorithms.** `sha1`, `sha256`, `sha512` and `md5` are supported, and the 
name is matched regardless of case. `sha1` and `md5` are weak digests, but they 
are published by the ASF for every artifact, so verifying them is still useful: 
a match confirms the file is the published one, and that is what the release 
manager is trying to establish.
   
   **Values.** The supplied value is compared after trimming surrounding 
whitespace, so it does not matter whether the value is copied from a `.sha512` 
file with its trailing newline or typed by hand. Comparison is 
case-insensitive, since hex digits are sometimes pasted in uppercase.
   
   **Mismatches.** A mismatch fails the build and reports the algorithm, the 
artifact, the expected value and the value that was actually computed, so that 
a wrong value can be spotted and re-copied without re-running anything.
   
   **Missing artifacts.** If a checksum is supplied for an artifact that the 
build did not produce, for example because the release profile was not active, 
the build fails. A verification that silently checks nothing is worse than no 
verification.
   
   **Uncovered artifacts.** Artifacts that no expected value was supplied for 
are not verified and are not an error, so the single property case above stays 
usable on a project that also produces sources and javadoc jars. A summary line 
reports how many artifacts were verified, how many mismatched and how many were 
not covered, so an incomplete run is visible in the log.
   
   **Nothing to verify.** If no expected checksum is supplied at all, either on 
the command line or in the POM, the goal reports this and does not fail, so 
that it can be safely left in a POM while the expected values are still being 
filled in.
   
   ### Example output
   
   ```
   [INFO] --- maven-artifact-plugin:3.7.1-SNAPSHOT:verify-checksum 
(default-cli) @ maven-artifact-plugin ---
   [INFO] Verifying 7 checksums of maven-artifact-plugin:3.7.0
   [INFO] sha512 matches maven-artifact-plugin-3.7.0.jar
   [INFO] sha512 matches maven-artifact-plugin-3.7.0.pom
   [INFO] sha512 matches maven-artifact-plugin-3.7.0-sources.jar
   [INFO] sha512 matches maven-artifact-plugin-3.7.0-javadoc.jar
   [INFO] sha512 matches maven-artifact-plugin-3.7.0-source-release.zip
   [INFO] sha1   matches maven-artifact-plugin-3.7.0.jar
   [INFO] md5    matches maven-artifact-plugin-3.7.0.jar
   [INFO] Checksum verification result: 7 verified, 0 mismatched, 0 missing
   ```
   
   and on a mismatch:
   
   ```
   [ERROR] sha512 mismatch for maven-artifact-plugin-3.7.0-source-release.zip
   [ERROR]   expected 
4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c
   [ERROR]   actual   
4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3d
   [ERROR] Checksum verification result: 6 verified, 1 mismatched, 0 missing
   [ERROR] Failed to execute goal 
org.apache.maven.plugins:maven-artifact-plugin:3.7.1-SNAPSHOT:verify-checksum 
(default-cli) on project maven-artifact-plugin: checksum verification failed
   ```
   
   ### Open questions
   
   Two design choices are worth settling before this is implemented.
   
   **1. How to identify the artifact on the command line.** This draft uses 
`<algorithm>[<classifier>:<extension>]`, so `sha512[source-release:zip]`, which 
is the order that matches the published file name 
`maven-artifact-plugin-3.7.0-source-release.zip` and is what the original 
report proposed. The alternatives are the opposite order, 
`sha512[zip:source-release]`, which is the order Maven itself uses in 
coordinates like `groupId:artifactId:version:type:classifier`, or the published 
file name, `sha512[maven-artifact-plugin-3.7.0-source-release.zip]`, which is 
unambiguous but verbose, especially for a multi-module project where it has to 
be repeated per module. Any of the three is implementable; the first was chosen 
because it is the shortest of the unambiguous options and matches the file the 
user has just downloaded.
   
   **2. Whether the expected values should also be readable from a file.** The 
release manager normally downloads the published `.sha512` file rather than 
copying its content out of a web page. Accepting a path to that file, or to a 
directory of checksum files, would remove the last manual step and would also 
make a multi-module release practical in one invocation, because one manifest 
can cover every module. That is a larger addition than the goal asked for here, 
so it is raised here rather than assumed.
   
   ### Related
   
   - Original report: 
[MARTIFACT-1](https://issues.apache.org/jira/browse/MARTIFACT-1)
   - Goals that already expose computed digests: `artifact:buildinfo` (records 
`sha512`) and `artifact:describe-build-output` (prints `sha256`)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to