You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2026/04/14 17:22:44 UTC
(maven-studies) branch maven-atr-plugin updated: add atr:check-composing goal
This is an automated email from the ASF dual-hosted git repository.
hboutemy pushed a commit to branch maven-atr-plugin
in repository https://gitbox.apache.org/repos/asf/maven-studies.git
The following commit(s) were added to refs/heads/maven-atr-plugin by this push:
new 4b189edcc add atr:check-composing goal
4b189edcc is described below
commit 4b189edcc6c59b87166cef5c9c4f12424bad0725
Author: Hervé Boutemy <hb...@apache.org>
AuthorDate: Tue Apr 14 19:22:34 2026 +0200
add atr:check-composing goal
---
src/it/apache-release-profile/pom.xml | 14 +-
.../apache/maven/plugins/atr/AbstractAtrMojo.java | 16 +-
.../org/apache/maven/plugins/atr/AtrClient.java | 212 +++++++++++++++++++++
.../maven/plugins/atr/CheckComposingMojo.java | 77 ++++++++
.../org/apache/maven/plugins/atr/UploadMojo.java | 14 +-
src/site/markdown/usage.md | 12 +-
6 files changed, 325 insertions(+), 20 deletions(-)
diff --git a/src/it/apache-release-profile/pom.xml b/src/it/apache-release-profile/pom.xml
index f72f722e3..a39a17f2a 100644
--- a/src/it/apache-release-profile/pom.xml
+++ b/src/it/apache-release-profile/pom.xml
@@ -59,16 +59,24 @@ under the License.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-atr-plugin</artifactId>
+ <configuration>
+ <dryRun>true</dryRun>
+ <project>${project.artifactId}</project>
+ <version>${project.version}</version>
+ </configuration>
<executions>
+ <execution>
+ <id>atr-check-composing</id>
+ <goals>
+ <goal>check-composing</goal>
+ </goals>
+ </execution>
<execution>
<id>upload-to-atr</id>
<goals>
<goal>upload</goal>
</goals>
<configuration>
- <dryRun>true</dryRun>
- <project>${project.artifactId}</project>
- <version>${project.version}</version>
<files>
<file>${project.build.directory}/${project.artifactId}-${project.version}-source-release.zip</file>
<file>${project.build.directory}/${project.artifactId}-${project.version}-source-release.zip.sha512</file>
diff --git a/src/main/java/org/apache/maven/plugins/atr/AbstractAtrMojo.java b/src/main/java/org/apache/maven/plugins/atr/AbstractAtrMojo.java
index d499d396c..4c08c9eba 100644
--- a/src/main/java/org/apache/maven/plugins/atr/AbstractAtrMojo.java
+++ b/src/main/java/org/apache/maven/plugins/atr/AbstractAtrMojo.java
@@ -41,6 +41,18 @@ import org.apache.maven.settings.crypto.SettingsDecryptionResult;
*/
public abstract class AbstractAtrMojo extends AbstractMojo {
+ /**
+ * The project id for ATR upload.
+ */
+ @Parameter(property = "atr.project", required = true)
+ protected String project;
+
+ /**
+ * The version for ATR upload.
+ */
+ @Parameter(property = "atr.version", required = true)
+ protected String version;
+
/**
* The ATR server URL.
*/
@@ -77,7 +89,7 @@ public abstract class AbstractAtrMojo extends AbstractMojo {
* Maven project.
*/
@Parameter(defaultValue = "${project}", readonly = true, required = true)
- protected MavenProject project;
+ protected MavenProject mavenProject;
/**
* Maven session.
@@ -148,7 +160,7 @@ public abstract class AbstractAtrMojo extends AbstractMojo {
*/
private boolean isExecutionRoot() {
File executionRootDirectory = new File(session.getExecutionRootDirectory());
- File projectBaseDir = project.getBasedir();
+ File projectBaseDir = mavenProject.getBasedir();
return executionRootDirectory.equals(projectBaseDir);
}
diff --git a/src/main/java/org/apache/maven/plugins/atr/AtrClient.java b/src/main/java/org/apache/maven/plugins/atr/AtrClient.java
index 619ea365c..5c560c611 100644
--- a/src/main/java/org/apache/maven/plugins/atr/AtrClient.java
+++ b/src/main/java/org/apache/maven/plugins/atr/AtrClient.java
@@ -102,6 +102,44 @@ public class AtrClient {
}
}
+ /**
+ * Check if a version exists in ATR and get its release information.
+ *
+ * @param project the project id
+ * @param version the version
+ * @return the release information, or null if the version does not exist
+ * @throws MojoExecutionException if the check fails
+ */
+ public ReleaseInfo checkVersion(String project, String version) throws MojoExecutionException {
+ // Ensure we have a valid JWT
+ ensureJwt();
+
+ try {
+ // Create connection
+ URL checkUrl = new URL(baseUrl, "api/release/get/" + project + "/" + version);
+ HttpURLConnection conn = (HttpURLConnection) checkUrl.openConnection();
+ conn.setRequestMethod("GET");
+ conn.setRequestProperty("Authorization", "Bearer " + jwt);
+
+ // Check response
+ int responseCode = conn.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ ReleaseGetResponse response = objectMapper.readValue(conn.getInputStream(), ReleaseGetResponse.class);
+ log.debug("Version check successful: " + objectMapper.writeValueAsString(response));
+ return response.getRelease();
+ } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
+ log.debug("Version does not exist: " + project + " " + version);
+ return null;
+ } else {
+ String errorResponse = readErrorResponse(conn.getErrorStream());
+ throw new MojoExecutionException(
+ "Failed to check version: HTTP " + responseCode + " - " + errorResponse);
+ }
+ } catch (IOException e) {
+ throw new MojoExecutionException("Failed to check version in ATR: " + project + " " + version, e);
+ }
+ }
+
/**
* Upload a file to ATR.
*
@@ -311,4 +349,178 @@ public class AtrClient {
this.releaseName = releaseName;
}
}
+
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ static class ReleaseGetResponse {
+ @JsonProperty("endpoint")
+ private String endpoint;
+
+ @JsonProperty("release")
+ private ReleaseInfo release;
+
+ public String getEndpoint() {
+ return endpoint;
+ }
+
+ public void setEndpoint(String endpoint) {
+ this.endpoint = endpoint;
+ }
+
+ public ReleaseInfo getRelease() {
+ return release;
+ }
+
+ public void setRelease(ReleaseInfo release) {
+ this.release = release;
+ }
+ }
+
+ @JsonIgnoreProperties(ignoreUnknown = true)
+ public static class ReleaseInfo {
+ // Phase constants
+ public static final String PHASE_RELEASE_CANDIDATE_DRAFT = "release_candidate_draft";
+ public static final String PHASE_RELEASE_CANDIDATE = "release_candidate";
+ public static final String PHASE_RELEASE_PREVIEW = "release_preview";
+ public static final String PHASE_RELEASE = "release";
+
+ @JsonProperty("name")
+ private String name;
+
+ @JsonProperty("phase")
+ private String phase;
+
+ @JsonProperty("project_name")
+ private String projectName;
+
+ @JsonProperty("version")
+ private String version;
+
+ @JsonProperty("created")
+ private String created;
+
+ @JsonProperty("latest_revision_number")
+ private String latestRevisionNumber;
+
+ @JsonProperty("vote_started")
+ private String voteStarted;
+
+ @JsonProperty("vote_resolved")
+ private String voteResolved;
+
+ @JsonProperty("released")
+ private String released;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getPhase() {
+ return phase;
+ }
+
+ public void setPhase(String phase) {
+ this.phase = phase;
+ }
+
+ public String getProjectName() {
+ return projectName;
+ }
+
+ public void setProjectName(String projectName) {
+ this.projectName = projectName;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getCreated() {
+ return created;
+ }
+
+ public void setCreated(String created) {
+ this.created = created;
+ }
+
+ public String getLatestRevisionNumber() {
+ return latestRevisionNumber;
+ }
+
+ public void setLatestRevisionNumber(String latestRevisionNumber) {
+ this.latestRevisionNumber = latestRevisionNumber;
+ }
+
+ public String getVoteStarted() {
+ return voteStarted;
+ }
+
+ public void setVoteStarted(String voteStarted) {
+ this.voteStarted = voteStarted;
+ }
+
+ public String getVoteResolved() {
+ return voteResolved;
+ }
+
+ public void setVoteResolved(String voteResolved) {
+ this.voteResolved = voteResolved;
+ }
+
+ public String getReleased() {
+ return released;
+ }
+
+ public void setReleased(String released) {
+ this.released = released;
+ }
+
+ /**
+ * Check if the release is being composed (not yet in vote).
+ *
+ * @return true if the release is being composed
+ */
+ public boolean isComposing() {
+ return PHASE_RELEASE_CANDIDATE_DRAFT.equals(phase);
+ }
+
+ /**
+ * Check if the release has been finalized and released.
+ *
+ * @return true if the release is in the release phase
+ */
+ public boolean isReleased() {
+ return PHASE_RELEASE.equals(phase);
+ }
+
+ /**
+ * Get a human-readable description of the phase.
+ *
+ * @return phase description
+ */
+ public String getPhaseDescription() {
+ if (phase == null) {
+ return "Unknown";
+ }
+ switch (phase) {
+ case PHASE_RELEASE_CANDIDATE_DRAFT:
+ return "Release Candidate (Draft - Being Composed)";
+ case PHASE_RELEASE_CANDIDATE:
+ return "Release Candidate (In Voting)";
+ case PHASE_RELEASE_PREVIEW:
+ return "Release Preview";
+ case PHASE_RELEASE:
+ return "Released";
+ default:
+ return phase;
+ }
+ }
+ }
}
diff --git a/src/main/java/org/apache/maven/plugins/atr/CheckComposingMojo.java b/src/main/java/org/apache/maven/plugins/atr/CheckComposingMojo.java
new file mode 100644
index 000000000..a7e043f9b
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/atr/CheckComposingMojo.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.maven.plugins.atr;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+import org.apache.maven.plugins.annotations.Mojo;
+
+/**
+ * Check if a version exists in ATR and is being composed (in draft phase).
+ *
+ * @author Maven Team
+ */
+@Mojo(name = "check-composing", defaultPhase = LifecyclePhase.INITIALIZE, threadSafe = true)
+public class CheckComposingMojo extends AbstractAtrMojo {
+
+ @Override
+ protected void atrExecute() throws MojoExecutionException, MojoFailureException {
+ if (dryRun) {
+ getLog().info("DRY RUN: Simulating ATR version check (no actual API call will be made)");
+ }
+
+ getLog().info("Checking project release in ATR: " + project + " version " + version);
+
+ if (dryRun) {
+ getLog().info("DRY RUN: Would check version at " + url + "api/release/get/" + project + "/" + version);
+ return;
+ }
+
+ AtrClient client = new AtrClient(url, getServer(), getLog());
+ AtrClient.ReleaseInfo releaseInfo = client.checkVersion(project, version);
+
+ if (releaseInfo == null) {
+ getLog().info("Version does not exist in ATR: " + project + " " + version + System.lineSeparator()
+ + " See " + url + "projects/" + project + " for more information");
+ throw new MojoFailureException("Version does not exist in ATR: " + project + " " + version);
+ }
+
+ getLog().info("Version exists in ATR:" + System.lineSeparator()
+ + " Phase: " + releaseInfo.getPhaseDescription() + System.lineSeparator()
+ + " Created: " + releaseInfo.getCreated() + System.lineSeparator()
+ + " Latest Revision: " + releaseInfo.getLatestRevisionNumber());
+
+ // Check fail conditions
+ if (releaseInfo.isComposing()) {
+ getLog().info("Version is being composed in ATR: " + project + " " + version + System.lineSeparator()
+ + " See " + url + "compose/" + project + "/" + version + " for more information");
+ } else {
+ if (releaseInfo.isReleased()) {
+ getLog().error("Version is already released: " + project + " " + version + System.lineSeparator()
+ + " See " + url + "file/" + project + "/" + version + " for more information");
+ } else {
+ getLog().error("Version is " + releaseInfo.getPhaseDescription() + ": " + project + " " + version
+ + System.lineSeparator() + " See " + url + "compose/" + project + "/" + version
+ + " for more information");
+ }
+ throw new MojoFailureException("Version is not being composed: " + project + " " + version);
+ }
+ }
+}
diff --git a/src/main/java/org/apache/maven/plugins/atr/UploadMojo.java b/src/main/java/org/apache/maven/plugins/atr/UploadMojo.java
index 3d29fa262..b2e82a36f 100644
--- a/src/main/java/org/apache/maven/plugins/atr/UploadMojo.java
+++ b/src/main/java/org/apache/maven/plugins/atr/UploadMojo.java
@@ -31,21 +31,9 @@ import org.apache.maven.plugins.annotations.Parameter;
*
* @author Maven Team
*/
-@Mojo(name = "upload", requiresProject = true, defaultPhase = LifecyclePhase.DEPLOY, threadSafe = true)
+@Mojo(name = "upload", defaultPhase = LifecyclePhase.DEPLOY, threadSafe = true)
public class UploadMojo extends AbstractAtrMojo {
- /**
- * The project id for ATR upload.
- */
- @Parameter(property = "atr.project", required = true)
- private String project;
-
- /**
- * The version for ATR upload.
- */
- @Parameter(property = "atr.version", required = true)
- private String version;
-
/**
* The files to upload to ATR.
*/
diff --git a/src/site/markdown/usage.md b/src/site/markdown/usage.md
index f40f548fa..4fbd2bf07 100644
--- a/src/site/markdown/usage.md
+++ b/src/site/markdown/usage.md
@@ -75,15 +75,23 @@ The typical use case is to integrate the ATR plugin into your `apache-release` p
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-atr-plugin</artifactId>
+ <configuration>
+ <project>${project.artifactId}</project>
+ <version>${project.version}</version>
+ </configuration>
<executions>
+ <execution>
+ <id>atr-check-composing</id>
+ <goals>
+ <goal>check-composing</goal>
+ </goals>
+ </execution>
<execution>
<id>upload-to-atr</id>
<goals>
<goal>upload</goal>
</goals>
<configuration>
- <project>${project.artifactId}</project>
- <version>${project.version}</version>
<files>
<file>${project.build.directory}/${project.artifactId}-${project.version}-source-release.zip</file>
<file>${project.build.directory}/${project.artifactId}-${project.version}-source-release.zip.sha512</file>