You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2019/09/16 15:05:13 UTC

[sling-org-apache-sling-committer-cli] branch master updated: SLING-8707 - Try to map a staging Nexus repository to a JIRA release by inspecting the POM files

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

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-committer-cli.git


The following commit(s) were added to refs/heads/master by this push:
     new c2f4f94  SLING-8707 - Try to map a staging Nexus repository to a JIRA release by inspecting the POM files
c2f4f94 is described below

commit c2f4f947a50eac2642b85791e8e3590ac982466c
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Sep 16 17:05:01 2019 +0200

    SLING-8707 - Try to map a staging Nexus repository to a JIRA release by inspecting the POM files
    
    * staged pom files are read in order to extract the JIRA releases corresponding to the staging
    repository; it is assumed that a JIRA release obeys the following syntax:
    '${project.name} ${project.version}', where 'Apache Sling' is optional
---
 .../org/apache/sling/cli/impl/nexus/Artifact.java  |  6 ++++
 .../sling/cli/impl/nexus/RepositoryService.java    | 40 ++++++++++++++++++++++
 .../cli/impl/release/CreateJiraVersionCommand.java |  6 ++--
 .../apache/sling/cli/impl/release/ListCommand.java |  4 +--
 .../cli/impl/release/PrepareVoteEmailCommand.java  |  6 ++--
 .../sling/cli/impl/release/TallyVotesCommand.java  |  8 ++---
 .../cli/impl/release/UpdateLocalSiteCommand.java   | 10 +++---
 .../cli/impl/release/UpdateReporterCommand.java    | 11 +++---
 .../cli/impl/nexus/RepositoryServiceTest.java      | 10 ++++++
 .../impl/release/PrepareVoteEmailCommandTest.java  |  4 ++-
 .../cli/impl/release/TallyVotesCommandTest.java    |  3 ++
 .../impl/release/UpdateReporterCommandTest.java    | 14 +++++---
 12 files changed, 95 insertions(+), 27 deletions(-)

diff --git a/src/main/java/org/apache/sling/cli/impl/nexus/Artifact.java b/src/main/java/org/apache/sling/cli/impl/nexus/Artifact.java
index 7656301..24b45b3 100644
--- a/src/main/java/org/apache/sling/cli/impl/nexus/Artifact.java
+++ b/src/main/java/org/apache/sling/cli/impl/nexus/Artifact.java
@@ -118,4 +118,10 @@ public class Artifact {
         }
         return false;
     }
+
+    @Override
+    public String toString() {
+        return String.format("Artifact {groupId=%s; artifactId=%s; version=%s; classifier=%s; type=%s}", groupId, artifactId, version,
+                classifier, type);
+    }
 }
diff --git a/src/main/java/org/apache/sling/cli/impl/nexus/RepositoryService.java b/src/main/java/org/apache/sling/cli/impl/nexus/RepositoryService.java
index 249ac5f..fec188a 100644
--- a/src/main/java/org/apache/sling/cli/impl/nexus/RepositoryService.java
+++ b/src/main/java/org/apache/sling/cli/impl/nexus/RepositoryService.java
@@ -31,6 +31,14 @@ import java.util.function.Consumer;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
 import org.apache.commons.io.IOUtils;
 import org.apache.http.HttpHeaders;
 import org.apache.http.client.methods.CloseableHttpResponse;
@@ -39,6 +47,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.sling.cli.impl.ComponentContextHelper;
 import org.apache.sling.cli.impl.http.HttpClientFactory;
 import org.apache.sling.cli.impl.nexus.StagingRepository.Status;
+import org.apache.sling.cli.impl.release.Release;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
@@ -46,6 +55,8 @@ import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
 
 import com.google.gson.Gson;
 import com.google.gson.JsonArray;
@@ -63,6 +74,8 @@ public class RepositoryService {
 
     private Map<String, LocalRepository> repositories = new HashMap<>();
     private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
+    private final XPathFactory xPathFactory = XPathFactory.newInstance();
+    private final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
 
     @Reference
     private HttpClientFactory httpClientFactory;
@@ -204,6 +217,33 @@ public class RepositoryService {
         }
     }
 
+    public Set<Release> getReleases(StagingRepository stagingRepository) throws IOException {
+        Set<Release> releases = new HashSet<>();
+        getArtifacts(stagingRepository).stream().filter(artifact -> "pom".equals(artifact.getType())).forEach(pom -> {
+            try {
+                XPath xPath = xPathFactory.newXPath();
+                processArtifactStream(pom, stream -> {
+                    try {
+                        DocumentBuilder builder = builderFactory.newDocumentBuilder();
+                        Document xmlDocument = builder.parse(stream);
+                        String name = (String) xPath.compile("/project/name/text()").evaluate(xmlDocument, XPathConstants.STRING);
+                        String version = (String) xPath.compile("/project/version/text()").evaluate(xmlDocument, XPathConstants.STRING);
+                        try {
+                            releases.addAll(Release.fromString(name + " " + version));
+                        } catch (IllegalArgumentException e) {
+                            LOGGER.error(String.format("Unable to determine a valid release from '%s %s'", name, version), e);
+                        }
+                    } catch (ParserConfigurationException | SAXException | XPathExpressionException | IOException e) {
+                        LOGGER.error(String.format("Unable to process artifact %s.", pom), e);
+                    }
+                });
+            } catch (IOException e) {
+                LOGGER.error(String.format("Unable to process artifact %s.", pom), e);
+            }
+        });
+        return Set.copyOf(releases);
+    }
+
     private void downloadFileFromRepository(@NotNull StagingRepository repository, @NotNull CloseableHttpClient client,
                                             @NotNull Path artifactFolderPath, @NotNull String relativeFilePath) throws IOException {
         String fileName = relativeFilePath.substring(relativeFilePath.lastIndexOf('/') + 1);
diff --git a/src/main/java/org/apache/sling/cli/impl/release/CreateJiraVersionCommand.java b/src/main/java/org/apache/sling/cli/impl/release/CreateJiraVersionCommand.java
index 09f9f8d..063e4ab 100644
--- a/src/main/java/org/apache/sling/cli/impl/release/CreateJiraVersionCommand.java
+++ b/src/main/java/org/apache/sling/cli/impl/release/CreateJiraVersionCommand.java
@@ -56,7 +56,7 @@ public class CreateJiraVersionCommand implements Command {
     private Integer repositoryId;
 
     @Reference
-    private RepositoryService repoFinder;
+    private RepositoryService repositoryService;
     
     @Reference
     private VersionClient versionClient;
@@ -69,8 +69,8 @@ public class CreateJiraVersionCommand implements Command {
     @Override
     public void run() {
         try {
-            StagingRepository repo = repoFinder.find(repositoryId);
-            for (Release release : Release.fromString(repo.getDescription()) ) {
+            StagingRepository repo = repositoryService.find(repositoryId);
+            for (Release release : repositoryService.getReleases(repo)) {
                 Version version = versionClient.find(release);
                 logger.info("Found {}.", version);
                 Version successorVersion = versionClient.findSuccessorVersion(release);
diff --git a/src/main/java/org/apache/sling/cli/impl/release/ListCommand.java b/src/main/java/org/apache/sling/cli/impl/release/ListCommand.java
index 56a1297..0b48265 100644
--- a/src/main/java/org/apache/sling/cli/impl/release/ListCommand.java
+++ b/src/main/java/org/apache/sling/cli/impl/release/ListCommand.java
@@ -42,12 +42,12 @@ public class ListCommand implements Command {
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
     @Reference
-    private RepositoryService repoFinder;
+    private RepositoryService repositoryService;
 
     @Override
     public void run() {
         try {
-            repoFinder.list().forEach( r -> logger.info("{}\t{}", r.getRepositoryId(), r.getDescription()));
+            repositoryService.list().forEach( r -> logger.info("{}\t{}", r.getRepositoryId(), r.getDescription()));
         } catch (IOException e) {
             logger.warn("Failed executing command", e);
         }
diff --git a/src/main/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommand.java b/src/main/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommand.java
index 076026c..4ade9ca 100644
--- a/src/main/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommand.java
+++ b/src/main/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommand.java
@@ -67,7 +67,7 @@ public class PrepareVoteEmailCommand implements Command {
     private MembersFinder membersFinder;
 
     @Reference
-    private RepositoryService repoFinder;
+    private RepositoryService repositoryService;
 
     @Reference
     private VersionClient versionClient;
@@ -110,8 +110,8 @@ public class PrepareVoteEmailCommand implements Command {
             if (commandLine.isUsageHelpRequested()) {
                 commandLine.usage(commandLine.getOut());
             } else {
-                StagingRepository repo = repoFinder.find(repositoryId);
-                List<Release> releases = Release.fromString(repo.getDescription());
+                StagingRepository repo = repositoryService.find(repositoryId);
+                Set<Release> releases = repositoryService.getReleases(repo);
                 List<Version> versions = releases.stream()
                         .map(r -> versionClient.find(r))
                         .collect(Collectors.toList());
diff --git a/src/main/java/org/apache/sling/cli/impl/release/TallyVotesCommand.java b/src/main/java/org/apache/sling/cli/impl/release/TallyVotesCommand.java
index 1e1d024..25f43cb 100644
--- a/src/main/java/org/apache/sling/cli/impl/release/TallyVotesCommand.java
+++ b/src/main/java/org/apache/sling/cli/impl/release/TallyVotesCommand.java
@@ -36,8 +36,8 @@ import org.apache.sling.cli.impl.UserInput;
 import org.apache.sling.cli.impl.mail.Email;
 import org.apache.sling.cli.impl.mail.Mailer;
 import org.apache.sling.cli.impl.mail.VoteThreadFinder;
-import org.apache.sling.cli.impl.nexus.StagingRepository;
 import org.apache.sling.cli.impl.nexus.RepositoryService;
+import org.apache.sling.cli.impl.nexus.StagingRepository;
 import org.apache.sling.cli.impl.people.Member;
 import org.apache.sling.cli.impl.people.MembersFinder;
 import org.osgi.service.component.annotations.Component;
@@ -65,7 +65,7 @@ public class TallyVotesCommand implements Command {
     private MembersFinder membersFinder;
 
     @Reference
-    private RepositoryService repoFinder;
+    private RepositoryService repositoryService;
 
     @Reference
     private VoteThreadFinder voteThreadFinder;
@@ -98,8 +98,8 @@ public class TallyVotesCommand implements Command {
     @Override
     public void run() {
         try {
-            StagingRepository repository = repoFinder.find(repositoryId);
-            List<Release> releases = Release.fromString(repository.getDescription());
+            StagingRepository repository = repositoryService.find(repositoryId);
+            Set<Release> releases = repositoryService.getReleases(repository);
             String releaseName = releases.stream().map(Release::getName).collect(Collectors.joining(", "));
             String releaseFullName = releases.stream().map(Release::getFullName).collect(Collectors.joining(", "));
             Set<String> bindingVoters = new LinkedHashSet<>();
diff --git a/src/main/java/org/apache/sling/cli/impl/release/UpdateLocalSiteCommand.java b/src/main/java/org/apache/sling/cli/impl/release/UpdateLocalSiteCommand.java
index 9f919d6..d21ea02 100644
--- a/src/main/java/org/apache/sling/cli/impl/release/UpdateLocalSiteCommand.java
+++ b/src/main/java/org/apache/sling/cli/impl/release/UpdateLocalSiteCommand.java
@@ -21,12 +21,12 @@ import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.time.LocalDateTime;
-import java.util.List;
+import java.util.Set;
 
 import org.apache.sling.cli.impl.Command;
 import org.apache.sling.cli.impl.jbake.JBakeContentUpdater;
-import org.apache.sling.cli.impl.nexus.StagingRepository;
 import org.apache.sling.cli.impl.nexus.RepositoryService;
+import org.apache.sling.cli.impl.nexus.StagingRepository;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.ResetCommand.ResetType;
 import org.eclipse.jgit.api.errors.GitAPIException;
@@ -54,7 +54,7 @@ public class UpdateLocalSiteCommand implements Command {
     private static final String GIT_CHECKOUT = "/tmp/sling-site";
 
     @Reference
-    private RepositoryService repoFinder;
+    private RepositoryService repositoryService;
     
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
@@ -67,8 +67,8 @@ public class UpdateLocalSiteCommand implements Command {
             ensureRepo();
             try ( Git git = Git.open(new File(GIT_CHECKOUT)) ) {
                 
-                StagingRepository repository = repoFinder.find(repositoryId);
-                List<Release> releases = Release.fromString(repository.getDescription());
+                StagingRepository repository = repositoryService.find(repositoryId);
+                Set<Release> releases = repositoryService.getReleases(repository);
                 
                 JBakeContentUpdater updater = new JBakeContentUpdater();
         
diff --git a/src/main/java/org/apache/sling/cli/impl/release/UpdateReporterCommand.java b/src/main/java/org/apache/sling/cli/impl/release/UpdateReporterCommand.java
index 137d662..027eba9 100644
--- a/src/main/java/org/apache/sling/cli/impl/release/UpdateReporterCommand.java
+++ b/src/main/java/org/apache/sling/cli/impl/release/UpdateReporterCommand.java
@@ -24,6 +24,7 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.http.NameValuePair;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
@@ -35,8 +36,8 @@ import org.apache.sling.cli.impl.Command;
 import org.apache.sling.cli.impl.InputOption;
 import org.apache.sling.cli.impl.UserInput;
 import org.apache.sling.cli.impl.http.HttpClientFactory;
-import org.apache.sling.cli.impl.nexus.StagingRepository;
 import org.apache.sling.cli.impl.nexus.RepositoryService;
+import org.apache.sling.cli.impl.nexus.StagingRepository;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 import org.slf4j.Logger;
@@ -63,7 +64,7 @@ public class UpdateReporterCommand implements Command {
     private static final Logger LOGGER = LoggerFactory.getLogger(UpdateReporterCommand.class);
 
     @Reference
-    private RepositoryService repoFinder;
+    private RepositoryService repositoryService;
 
     @Reference
     private HttpClientFactory httpClientFactory;
@@ -77,8 +78,8 @@ public class UpdateReporterCommand implements Command {
     @Override
     public void run() {
         try {
-            StagingRepository repository = repoFinder.find(repositoryId);
-            List<Release> releases = Release.fromString(repository.getDescription());
+            StagingRepository repository = repositoryService.find(repositoryId);
+            Set<Release> releases = repositoryService.getReleases(repository);
             String releaseReleases = releases.size() > 1 ? "releases" : "release";
             switch (reusableCLIOptions.executionMode) {
                 case DRY_RUN:
@@ -111,7 +112,7 @@ public class UpdateReporterCommand implements Command {
 
     }
 
-    private void updateReporter(List<Release> releases) throws IOException {
+    private void updateReporter(Set<Release> releases) throws IOException {
         try (CloseableHttpClient client = httpClientFactory.newClient()) {
             for (Release release : releases) {
                 HttpPost post = new HttpPost("https://reporter.apache.org/addrelease.py");
diff --git a/src/test/java/org/apache/sling/cli/impl/nexus/RepositoryServiceTest.java b/src/test/java/org/apache/sling/cli/impl/nexus/RepositoryServiceTest.java
index abba1a0..6f7cdea 100644
--- a/src/test/java/org/apache/sling/cli/impl/nexus/RepositoryServiceTest.java
+++ b/src/test/java/org/apache/sling/cli/impl/nexus/RepositoryServiceTest.java
@@ -36,6 +36,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.sling.cli.impl.CredentialsService;
 import org.apache.sling.cli.impl.http.HttpClientFactory;
 import org.apache.sling.cli.impl.jira.SystemPropertiesRule;
+import org.apache.sling.cli.impl.release.Release;
 import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
 import org.junit.Before;
 import org.junit.Rule;
@@ -150,6 +151,15 @@ public class RepositoryServiceTest {
         }
     }
 
+    @Test
+    public void testReleaseLookup() throws IOException {
+        StagingRepository stagingRepository = getStagingRepository();
+        Set<Release> releases = repositoryService.getReleases(stagingRepository);
+        assertEquals(1, releases.size());
+        Release release = releases.iterator().next();
+        assertEquals("Sling Adapter Annotations 1.0.0", release.getFullName());
+    }
+
 
     private StagingRepository getStagingRepository() {
         StagingRepository stagingRepository = new StagingRepository();
diff --git a/src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java b/src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java
index ea146fd..226f0f1 100644
--- a/src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java
+++ b/src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java
@@ -21,6 +21,7 @@ package org.apache.sling.cli.impl.release;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.apache.sling.cli.impl.Command;
 import org.apache.sling.cli.impl.DateProvider;
@@ -118,7 +119,8 @@ public class PrepareVoteEmailCommandTest {
         when(version.getName()).thenReturn("CLI Test 1.0.0");
         when(version.getId()).thenReturn(1);
         when(version.getIssuesFixedCount()).thenReturn(42);
-        Release release = Release.fromString("CLI Test 1.0.0").get(0);
+        Release release = Release.fromString("Apache Sling CLI Test 1.0.0").get(0);
+        when(repositoryService.getReleases(stagingRepository)).thenReturn(Set.of(release));
         List<Issue> fixedIssues = new ArrayList<>();
         for (int i = 0; i < 42; i++) {
             fixedIssues.add(mock(Issue.class));
diff --git a/src/test/java/org/apache/sling/cli/impl/release/TallyVotesCommandTest.java b/src/test/java/org/apache/sling/cli/impl/release/TallyVotesCommandTest.java
index c1c9444..f9ff9a4 100644
--- a/src/test/java/org/apache/sling/cli/impl/release/TallyVotesCommandTest.java
+++ b/src/test/java/org/apache/sling/cli/impl/release/TallyVotesCommandTest.java
@@ -223,6 +223,9 @@ public class TallyVotesCommandTest {
         when(stagingRepository.getDescription()).thenReturn("Apache Sling CLI Test 1.0.0");
         RepositoryService repositoryService = mock(RepositoryService.class);
         when(repositoryService.find(123)).thenReturn(stagingRepository);
+        Release release = Release.fromString("Apache Sling CLI Test 1.0.0").get(0);
+        when(repositoryService.getReleases(stagingRepository)).thenReturn(Set.of(release));
+
 
         VoteThreadFinder voteThreadFinder = mock(VoteThreadFinder.class);
         when(voteThreadFinder.findVoteThread("CLI Test 1.0.0")).thenReturn(thread);
diff --git a/src/test/java/org/apache/sling/cli/impl/release/UpdateReporterCommandTest.java b/src/test/java/org/apache/sling/cli/impl/release/UpdateReporterCommandTest.java
index 55f50d2..8a11450 100644
--- a/src/test/java/org/apache/sling/cli/impl/release/UpdateReporterCommandTest.java
+++ b/src/test/java/org/apache/sling/cli/impl/release/UpdateReporterCommandTest.java
@@ -19,6 +19,10 @@
 package org.apache.sling.cli.impl.release;
 
 import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 import org.apache.http.StatusLine;
 import org.apache.http.client.methods.CloseableHttpResponse;
@@ -64,20 +68,22 @@ public class UpdateReporterCommandTest {
     private CloseableHttpClient client;
 
     @Rule
-    public final OsgiContext osgiContext = new OsgiContext();
+    public OsgiContext osgiContext = new OsgiContext();
 
     @Before
     public void before() throws IOException {
-        RepositoryService repositoryFinder = mock(RepositoryService.class);
+        RepositoryService repositoryService = mock(RepositoryService.class);
         StagingRepository stagingRepository = mock(StagingRepository.class);
         when(stagingRepository.getDescription()).thenReturn("Apache Sling CLI 1, Apache Sling CLI 2");
-        when(repositoryFinder.find(42)).thenReturn(stagingRepository);
+        when(repositoryService.find(42)).thenReturn(stagingRepository);
+        List<Release> releases = Release.fromString("Apache Sling CLI 1, Apache Sling CLI 2");
+        when(repositoryService.getReleases(stagingRepository)).thenReturn(new HashSet<>(releases));
 
         HttpClientFactory httpClientFactory = mock(HttpClientFactory.class);
         client = mock(CloseableHttpClient.class);
         when(httpClientFactory.newClient()).thenReturn(client);
 
-        osgiContext.registerService(repositoryFinder);
+        osgiContext.registerService(repositoryService);
         osgiContext.registerService(httpClientFactory);
     }