Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/release-management/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,9 @@ loop before posting `+1`.
previous release, no prohibited binaries, published-JVM-artefact
compliance via `tools/maven-artifact-verify` — POM licence set,
podling incubation disclaimer, companion `-sources.jar` /
`-javadoc.jar` with signatures and checksums — source-tree
`-javadoc.jar` with signatures and checksums, informational
observations (timestamp reproducibility signal, package/groupId
correspondence, companion content sanity) — source-tree
integrity, version-string consistency, and — optional per
`release-build.md § Reproducibility checks` — reproducibility: the
source artefact rebuilt from the tag with `repro-archive build` at
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,33 @@ and [Maven Central's publishing requirements](https://central.sonatype.org/publi
a companion with no `.asc` is already a finding and gets no line.
A main jar declared by a staged POM but not staged locally is an observation (`ABSENT`), not a failure:
in the common ASF workflow the jars are staged in the Nexus staging repository, which this step never reads
(read-only, and check 4 is a later PR on [#1173](https://github.com/apache/magpie/issues/1173)).
(read-only; the Nexus staging-repository check — check 4 of the issue — is the read-only `asf-nexus` adapter and
Step 6c, landing via [#1505](https://github.com/apache/magpie/pull/1505)).
Classify an `ABSENT` jar against `release-build.md § JVM artefact checks` —
when that file declares `jvm_companion_location: staged`, an absent jar is a `FAIL`.

The same tool run emits **informational observations** — checks 5–7 of [issue #1173](https://github.com/apache/magpie/issues/1173) —
which are signals for the reviewer and never change the step's verdict:

5. **Timestamp reproducibility signal** — whether every file entry of a main jar shares one timestamp (consistent with
`project.build.outputTimestamp` being set) or varies across entries. Worded as "consistent / not consistent with a
reproducible configuration", never as "reproducible" — only Step 9's rebuild-and-compare can assert that. An empty or
single-entry jar reports `insufficient-data`, never a pass.
6. **Namespace and package/groupId correspondence** — whether the declared `groupId` sits under `org.apache.*` (informational even
for ASF top-level projects: published coordinates cannot be renamed retroactively, so there is no available remedy to gate on),
and the proportion of the jar's class entries under the package path derived from the groupId plus the package roots actually
found — a proportion and a list for the reviewer to judge, never a boolean. `META-INF/` entries, `module-info.class` and
multi-release overrides are excluded as legitimate divergences. Most useful for podlings, where it surfaces whether the
`org.apache.<project>` rename has happened.
7. **Companion content sanity** — whether `-sources.jar` carries `.java` / `.scala` / `.kt` sources and no `.class` files, and
whether `-javadoc.jar` is non-empty. Placeholder companions are a Maven-Central-sanctioned pattern, reported as such and never
failed; no Javadoc-specific structure is asserted (Scala/Kotlin projects publish dokka/scaladoc output under the `-javadoc`
classifier). Classified jars (`-tests`, `-shaded`, …) are not part of the required set and are not inspected.

A jar that cannot be opened at all — truncated, corrupt central directory, undecodable entry names — yields an `unreadable`
observation in each affected section and never takes the run down: check 3 never opens a jar, so a damaged jar with a valid
signature and checksum can pass the blocking checks while the observations report that its contents could not be read.

Emit the paste-ready recipe.
Resolve every placeholder to a concrete value:
`<framework>` is the framework root (`.apache-magpie` in an adopter repository),
Expand Down Expand Up @@ -66,6 +89,7 @@ Return ONLY valid JSON with this structure:
"tool_report": "<the maven-artifact-verify JSON report verbatim>",
"pom_findings": ["<one line per POM finding>"],
"companion_findings": ["<one line per jar finding>"],
"observations": ["<one line per informational observation>"],
"paste_recipe": "<multi-line shell commands>"
}
```
Expand All @@ -74,6 +98,10 @@ Return ONLY valid JSON with this structure:
one line each naming the artefact and what is wrong;
a passing check is not a finding, and an empty list means there is nothing to report.

`observations` carries the tool's informational observations (checks 5–7), one line each naming the jar and what was observed;
an empty list means the staged set carried none. They never change `status`: a jar whose timestamps vary, whose groupId sits
outside `org.apache.*`, or whose `-sources.jar` contains `.class` files still passes every blocking check.

`status` is the tool report's `status`,
except that an `ABSENT` jar becomes `FAIL` when `release-build.md § JVM artefact checks` declares `jvm_companion_location: staged`
(the RC was expected to stage it).
Expand Down
54 changes: 47 additions & 7 deletions tools/maven-artifact-verify/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,12 @@ Verifies **locally staged JVM release-candidate artefacts** — the
`.pom` files, the main jars and their companion `-sources.jar` /
`-javadoc.jar` — the way `release-verify-rc` verifies a staged source
artefact today. Implements the blocking checks 1–3 proposed in
[apache/magpie#1173](https://github.com/apache/magpie/issues/1173);
the Nexus staging-repository check (check 4) and the informational
checks (5–7) are later PRs on that issue.
[apache/magpie#1173](https://github.com/apache/magpie/issues/1173)
and reports the issue's informational checks (5–7) as `observations`
in the same JSON report; the Nexus staging-repository check (check 4)
will be implemented by the read-only `tools/asf-nexus` adapter and
`release-verify-rc` Step 6c — pending merge as
[#1505](https://github.com/apache/magpie/pull/1505).

Until this tool exists, `release-verify-rc` handles a jar in exactly
one direction: as *contraband inside the source tree* (Step 6's
Expand Down Expand Up @@ -77,10 +80,42 @@ blocking.
the release key, which `release-verify-rc` Step 2 runs against the
main artefacts, and the Step 6b recipe extends to the companions.

The same run also reports the issue's **informational checks 5–7**
under `observations` — signals for a human reviewer that never change
the `status`:

5. **Timestamp reproducibility signal** — whether every file entry of
a main jar shares one timestamp (consistent with
`project.build.outputTimestamp` being set) or varies across
entries. Worded as "consistent / not consistent with a reproducible
configuration", never as "reproducible" — only a rebuild-and-compare
can assert that. An empty or single-entry jar reports
`insufficient-data`, never a pass. ZIP's MS-DOS entry times carry
2-second granularity and no timezone; entries are compared as raw
values within one jar and never converted to absolute times.
6. **Namespace and package/groupId correspondence** — whether the
declared `groupId` sits under `org.apache.*` (informational even
for ASF top-level projects: published coordinates cannot be renamed
retroactively, so a gate would leave the RM no remedy), and the
proportion of the jar's class entries under the package path
derived from the groupId plus the package roots actually found — a
proportion and a list, never a boolean. `META-INF/` entries,
`module-info.class` and multi-release overrides are excluded as
legitimate divergences. Most useful for podlings, where it
surfaces whether the `org.apache.<project>` rename has happened.
7. **Companion content sanity** — whether `-sources.jar` carries
`.java` / `.scala` / `.kt` sources and no `.class` files, and
whether `-javadoc.jar` is non-empty. Placeholder companions are a
Maven-Central-sanctioned pattern and are reported as such, never
failed; no Javadoc-specific structure is asserted (Scala/Kotlin
projects publish dokka/scaladoc output under the `-javadoc`
classifier).

The overall `status` is `FAIL` when any check fails, `WARN` when only
`INHERITED-UNVERIFIED` results remain, `PASS` otherwise, and `SKIP`
when the staged set contains no `.pom` and no `.jar` at all — a
non-JVM project's RC runs the tool and skips cleanly.
non-JVM project's RC runs the tool and skips cleanly. The
informational observations never change it.

## Prerequisites

Expand Down Expand Up @@ -117,9 +152,14 @@ not fail correct releases:
- `packaging=pom` modules have no jar and are exempt from check 3
(they still get checks 1 and 2).
- Placeholder companion jars are a Maven-Central-sanctioned pattern;
check 3 only verifies presence, signatures and checksums, and never
opens a jar to judge its content (that is informational check 7, a
later PR).
check 3 verifies presence, signatures and checksums only, and the
check-7 observation reports a placeholder as the sanctioned pattern
it is, never a defect. Opening a jar reads the zip central
directory only (entry names and timestamps) — no entry content is
extracted. A jar that cannot be opened at all (truncated, corrupt
central directory, undecodable entry names) yields an `unreadable`
observation in each affected section — never a failure and never a
crash.
- Classified jars (`-tests`, `-shaded`, `-linux-x86_64`, …) are
neither mains nor companions: a jar whose classifier is not
`sources`/`javadoc` and that no staged POM declares is reported in
Expand Down
Loading