You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by sj...@apache.org on 2026/06/14 10:09:24 UTC

(tooling-atr-maven-plugin) branch main updated: Add support for creating release version in ATR by check-composing mojo

This is an automated email from the ASF dual-hosted git repository.

slawekjaranowski pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-atr-maven-plugin.git


The following commit(s) were added to refs/heads/main by this push:
     new f0a0ded  Add support for creating release version in ATR by check-composing mojo
f0a0ded is described below

commit f0a0dedc90618d04acb1e65f5b56b1e48ea0f799
Author: Slawomir Jaranowski <s....@gmail.com>
AuthorDate: Sat Jun 13 11:59:13 2026 +0200

    Add support for creating release version in ATR by check-composing mojo
    
    - Implemented `createRelease` method to allow creation of new releases via ATR.
    - Modified `CheckComposingMojo` to optionally create versions if they do not exist in ATR.
---
 .../org/apache/tooling/atr/CheckComposingMojo.java | 14 +++++
 .../org/apache/tooling/atr/client/AtrClient.java   | 32 ++++++++++-
 .../apache/tooling/atr/client/AtrClientImpl.java   | 18 +++++-
 .../tooling/atr/client/AtrClientImplTest.java      | 65 ++++++++++++++++++++++
 .../apache/tooling/atr/client/AtrClientMock.java   | 10 ++++
 5 files changed, 136 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/apache/tooling/atr/CheckComposingMojo.java b/src/main/java/org/apache/tooling/atr/CheckComposingMojo.java
index b602322..adf2e72 100644
--- a/src/main/java/org/apache/tooling/atr/CheckComposingMojo.java
+++ b/src/main/java/org/apache/tooling/atr/CheckComposingMojo.java
@@ -25,6 +25,7 @@ import java.util.List;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.LifecyclePhase;
 import org.apache.maven.plugins.annotations.Mojo;
+import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.project.MavenProject;
 import org.apache.tooling.atr.client.AtrClient;
 import org.apache.tooling.atr.client.AtrClientException;
@@ -39,6 +40,14 @@ import org.apache.tooling.atr.client.AtrClientFactory;
 @Mojo(name = "check-composing", defaultPhase = LifecyclePhase.INITIALIZE, threadSafe = true)
 public class CheckComposingMojo extends AbstractAtrMojo {
 
+    /**
+     * If set to true, the plugin will create the version in ATR if it does not exist.
+     *
+     * @since 1.0.0-beta-1
+     */
+    @Parameter(property = "atr.createVersion", defaultValue = "false")
+    private boolean createVersion;
+
     @Inject
     CheckComposingMojo(MavenProject mavenProject, List<AtrClientFactory> atrClientFactories) {
         super(mavenProject, atrClientFactories);
@@ -60,6 +69,11 @@ public class CheckComposingMojo extends AbstractAtrMojo {
         AtrClient client = createAtrClient();
         AtrClient.ReleaseInfo releaseInfo = client.getRelease(project, version);
 
+        if (releaseInfo == null && createVersion) {
+            getLog().info("Version does not exist in ATR, creating new version: " + project + " " + version);
+            releaseInfo = client.createRelease(project, version);
+        }
+
         if (releaseInfo == null) {
             getLog().info("Version does not exist in ATR: " + project + " " + version + System.lineSeparator()
                     + "       See " + url + "projects/" + project + " for more information");
diff --git a/src/main/java/org/apache/tooling/atr/client/AtrClient.java b/src/main/java/org/apache/tooling/atr/client/AtrClient.java
index 0eca770..88ee3f9 100644
--- a/src/main/java/org/apache/tooling/atr/client/AtrClient.java
+++ b/src/main/java/org/apache/tooling/atr/client/AtrClient.java
@@ -39,6 +39,17 @@ public interface AtrClient {
      * @throws AtrClientException if the check fails
      */
     ReleaseInfo getRelease(String project, String version) throws AtrClientException;
+
+    /**
+     * Create a new release in ATR.
+     *
+     * @param project the project id
+     * @param version the version
+     * @return the release information of the newly created release
+     * @throws AtrClientException if the release creation fails
+     */
+    ReleaseInfo createRelease(String project, String version) throws AtrClientException;
+
     /**
      * Upload a file to ATR.
      *
@@ -198,7 +209,7 @@ public interface AtrClient {
     }
 
     @JsonIgnoreProperties(ignoreUnknown = true)
-    class ReleaseGetResponse {
+    class ReleaseResponse {
         @JsonProperty("endpoint")
         private String endpoint;
 
@@ -370,4 +381,23 @@ public interface AtrClient {
             }
         }
     }
+
+    @JsonIgnoreProperties(ignoreUnknown = true)
+    class ReleaseCreateRequest {
+        private final String project;
+        private final String version;
+
+        public ReleaseCreateRequest(String project, String version) {
+            this.project = project;
+            this.version = version;
+        }
+
+        public String getProject() {
+            return project;
+        }
+
+        public String getVersion() {
+            return version;
+        }
+    }
 }
diff --git a/src/main/java/org/apache/tooling/atr/client/AtrClientImpl.java b/src/main/java/org/apache/tooling/atr/client/AtrClientImpl.java
index 84cdaf6..f653d52 100644
--- a/src/main/java/org/apache/tooling/atr/client/AtrClientImpl.java
+++ b/src/main/java/org/apache/tooling/atr/client/AtrClientImpl.java
@@ -106,8 +106,8 @@ class AtrClientImpl implements AtrClient {
         ensureJwt();
 
         try {
-            ReleaseGetResponse releaseResponse =
-                    executeGet("api/release/get/" + project + "/" + version, ReleaseGetResponse.class);
+            ReleaseResponse releaseResponse =
+                    executeGet("api/release/get/" + project + "/" + version, ReleaseResponse.class);
             return releaseResponse.getRelease();
         } catch (AtrClientException e) {
             if (e.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
@@ -119,6 +119,20 @@ class AtrClientImpl implements AtrClient {
         }
     }
 
+    @Override
+    public ReleaseInfo createRelease(String project, String version) throws AtrClientException {
+        // Ensure we have a valid JWT
+        ensureJwt();
+
+        try {
+            ReleaseCreateRequest request = new ReleaseCreateRequest(project, version);
+            ReleaseResponse releaseResponse = executePost("api/release/create", request, ReleaseResponse.class);
+            return releaseResponse.getRelease();
+        } catch (IOException e) {
+            throw new AtrClientException("Failed to create release in ATR: " + project + " " + version, e);
+        }
+    }
+
     /**
      * Upload a file to ATR.
      *
diff --git a/src/test/java/org/apache/tooling/atr/client/AtrClientImplTest.java b/src/test/java/org/apache/tooling/atr/client/AtrClientImplTest.java
index e8fe6fc..f2e3df0 100644
--- a/src/test/java/org/apache/tooling/atr/client/AtrClientImplTest.java
+++ b/src/test/java/org/apache/tooling/atr/client/AtrClientImplTest.java
@@ -119,6 +119,71 @@ class AtrClientImplTest {
         assertTrue(exception.getMessage().contains("\"Internal server error\""));
     }
 
+    @Test
+    void createReleaseShouldSendCorrectPayload() throws Exception {
+        stubForJwtCreate();
+
+        stubFor(post(urlEqualTo("/api/release/create"))
+                .withHeader("Authorization", equalTo("Bearer test-jwt"))
+                .willReturn(aResponse()
+                        .withHeader("Content-Type", "application/json")
+                        .withBody("{\"release\":{"
+                                + "  \"version\":\"2.0.0\","
+                                + "  \"phase\":\"release_candidate_draft\""
+                                + "}}")));
+
+        AtrClient.ReleaseInfo release = atrClient.createRelease("my-project", "2.0.0");
+
+        assertNotNull(release);
+        assertEquals("2.0.0", release.getVersion());
+
+        // Verify the request body contains correct project and version
+        verify(
+                1,
+                postRequestedFor(urlEqualTo("/api/release/create"))
+                        .withHeader("Authorization", equalTo("Bearer test-jwt"))
+                        .withRequestBody(matchingJsonPath("$.project", equalTo("my-project")))
+                        .withRequestBody(matchingJsonPath("$.version", equalTo("2.0.0"))));
+    }
+
+    @Test
+    void createReleaseShouldUseCachedJwt() throws Exception {
+        stubForJwtCreate();
+
+        stubFor(post(urlEqualTo("/api/release/create"))
+                .withHeader("Authorization", equalTo("Bearer test-jwt"))
+                .willReturn(aResponse()
+                        .withHeader("Content-Type", "application/json")
+                        .withBody("{\"release\":{"
+                                + "  \"version\":\"1.0.0\","
+                                + "  \"phase\":\"release_candidate_draft\""
+                                + "}}")));
+
+        // First call
+        atrClient.createRelease("test-project", "1.0.0");
+
+        // Second call should reuse cached JWT
+        atrClient.createRelease("test-project", "1.0.0");
+
+        // Verify that JWT was only created once and release create was called twice
+        verify(1, postRequestedFor(urlEqualTo("/api/jwt/create")));
+        verify(2, postRequestedFor(urlEqualTo("/api/release/create")));
+    }
+
+    @Test
+    void createReleaseServerErrorShouldThrowException() {
+        stubForJwtCreate();
+
+        stubFor(post(urlEqualTo("/api/release/create"))
+                .withHeader("Authorization", equalTo("Bearer test-jwt"))
+                .willReturn(aResponse().withStatus(500).withBody("{\"error\": \"Internal server error\"}")));
+
+        AtrClientException exception =
+                assertThrows(AtrClientException.class, () -> atrClient.createRelease("test-project", "1.0.0"));
+
+        assertTrue(exception.getMessage().contains("\"Internal server error\""));
+    }
+
     @Test
     void uploadFileShouldSucceedWithoutRevisionNumber(@TempDir Path tempDir) throws Exception {
         stubForJwtCreate();
diff --git a/src/test/java/org/apache/tooling/atr/client/AtrClientMock.java b/src/test/java/org/apache/tooling/atr/client/AtrClientMock.java
index c5a175d..94c733e 100644
--- a/src/test/java/org/apache/tooling/atr/client/AtrClientMock.java
+++ b/src/test/java/org/apache/tooling/atr/client/AtrClientMock.java
@@ -56,6 +56,16 @@ class AtrClientMock implements AtrClient {
         return releaseInfo;
     }
 
+    @Override
+    public ReleaseInfo createRelease(String project, String version) throws AtrClientException {
+        logger.info("[Mock ATR client] createRelease: {}, {}", project, version);
+        ReleaseInfo releaseInfo = new ReleaseInfo();
+        releaseInfo.setProjectName(project);
+        releaseInfo.setVersion(version);
+        releaseInfo.setPhase(ReleaseInfo.PHASE_RELEASE_CANDIDATE_DRAFT);
+        return releaseInfo;
+    }
+
     @Override
     public String uploadFile(String project, String version, String path, Path file) {
         logger.info("[Mock ATR client] uploadFile: {}, {}, {}, {}", project, version, path, file);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org