You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2019/04/23 11:48:09 UTC
[sling-org-apache-sling-committer-cli] 04/36: SLING-8311 -
Investigate creating a Sling CLI tool for development task automation
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch feature/SLING-8337
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-committer-cli.git
commit d5e841e05e0b1f3e8f1e1c224ab634f2ef254168
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Tue Mar 19 15:16:23 2019 +0100
SLING-8311 - Investigate creating a Sling CLI tool for development task automation
Implement command for listing active releases.
---
README.md | 8 +-
.../cli/impl/nexus/StagingRepositoryFinder.java | 37 ++++++--
.../apache/sling/cli/impl/release/ListCommand.java | 49 ++++++++++
.../cli/impl/release/PrepareVoteEmailCommand.java | 15 +--
.../sling/cli/impl/release/ReleaseVersion.java} | 41 +++++++--
.../sling/cli/impl/release/TallyVotesCommand.java | 9 +-
.../cli/impl/release/UpdateLocalSiteCommand.java | 102 +++++++++++++++++++++
...ailCommandTest.java => ReleaseVersionTest.java} | 11 ++-
8 files changed, 234 insertions(+), 38 deletions(-)
diff --git a/README.md b/README.md
index eabf20c..45336b1 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,10 @@ This invocation produces a list of available subcommands.
## Commands
+Listing active releases
+
+ docker run --env-file=./docker-env apache/sling-cli release list
+
Generating a release vote email
docker run --env-file=./docker-env apache/sling-cli release prepare-email $STAGING_REPOSITORY_ID
@@ -27,7 +31,7 @@ Generating a release vote email
Generating a release vote result email
docker run --env-file=./docker-env apache/sling-cli release tally-votes $STAGING_REPOSITORY_ID
-
+
## Assumptions
This tool assumes that the name of the staging repository matches the one of the version in Jira. For instance, the
@@ -35,4 +39,4 @@ staging repositories are usually named _Apache Sling Foo 1.2.0_. It is then expe
named _Foo 1.2.0_. Otherwise the link between the staging repository and the Jira release can not be found.
It is allowed for staging repository names to have an _RC_ suffix, which may include a number, so that _RC_, _RC1_, _RC25_ are
-all valid suffixes.
\ No newline at end of file
+all valid suffixes.
diff --git a/src/main/java/org/apache/sling/cli/impl/nexus/StagingRepositoryFinder.java b/src/main/java/org/apache/sling/cli/impl/nexus/StagingRepositoryFinder.java
index 3ef7992..21b30ff 100644
--- a/src/main/java/org/apache/sling/cli/impl/nexus/StagingRepositoryFinder.java
+++ b/src/main/java/org/apache/sling/cli/impl/nexus/StagingRepositoryFinder.java
@@ -19,6 +19,9 @@ package org.apache.sling.cli.impl.nexus;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
@@ -43,6 +46,8 @@ import com.google.gson.Gson;
)
@Designate(ocd = StagingRepositoryFinder.Config.class)
public class StagingRepositoryFinder {
+
+ private static final String REPOSITORY_PREFIX = "orgapachesling-";
@ObjectClassDefinition
static @interface Config {
@@ -61,8 +66,30 @@ public class StagingRepositoryFinder {
credentialsProvider.setCredentials(new AuthScope("repository.apache.org", 443),
new UsernamePasswordCredentials(cfg.username(), cfg.password()));
}
+
+ public List<StagingRepository> list() throws IOException {
+ return this. <List<StagingRepository>> withStagingRepositories( reader -> {
+ Gson gson = new Gson();
+ return gson.fromJson(reader, StagingRepositories.class).getData().stream()
+ .filter( r -> r.getType() == Status.closed)
+ .filter( r -> r.getRepositoryId().startsWith(REPOSITORY_PREFIX) )
+ .collect(Collectors.toList());
+ });
+ }
public StagingRepository find(int stagingRepositoryId) throws IOException {
+ return this.<StagingRepository> withStagingRepositories( reader -> {
+ Gson gson = new Gson();
+ return gson.fromJson(reader, StagingRepositories.class).getData().stream()
+ .filter( r -> r.getType() == Status.closed)
+ .filter( r -> r.getRepositoryId().startsWith(REPOSITORY_PREFIX) )
+ .filter( r -> r.getRepositoryId().endsWith("-" + stagingRepositoryId))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException("No repository found with id " + stagingRepositoryId));
+ });
+ }
+
+ private <T> T withStagingRepositories(Function<InputStreamReader, T> function) throws IOException {
try ( CloseableHttpClient client = HttpClients.custom()
.setDefaultCredentialsProvider(credentialsProvider)
.build() ) {
@@ -73,14 +100,10 @@ public class StagingRepositoryFinder {
InputStreamReader reader = new InputStreamReader(content)) {
if ( response.getStatusLine().getStatusCode() != 200 )
throw new IOException("Status line : " + response.getStatusLine());
- Gson gson = new Gson();
- return gson.fromJson(reader, StagingRepositories.class).getData().stream()
- .filter( r -> r.getType() == Status.closed)
- .filter( r -> r.getRepositoryId().endsWith("-" + stagingRepositoryId))
- .findFirst()
- .orElseThrow(() -> new IllegalArgumentException("No repository found with id " + stagingRepositoryId));
+
+ return function.apply(reader);
}
}
- }
+ }
}
}
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
new file mode 100644
index 0000000..1d35e29
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/release/ListCommand.java
@@ -0,0 +1,49 @@
+/*
+ * 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.sling.cli.impl.release;
+
+import java.io.IOException;
+
+import org.apache.sling.cli.impl.Command;
+import org.apache.sling.cli.impl.nexus.StagingRepositoryFinder;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = Command.class, property = {
+ Command.PROPERTY_NAME_COMMAND + "=release",
+ Command.PROPERTY_NAME_SUBCOMMAND + "=list",
+ Command.PROPERTY_NAME_SUMMARY + "=Lists all open releases" })
+public class ListCommand implements Command {
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Reference
+ private StagingRepositoryFinder repoFinder;
+
+ @Override
+ public void execute(String target) {
+ try {
+ repoFinder.list().stream()
+ .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 eff3a3f..5b8df75 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
@@ -36,7 +36,7 @@ public class PrepareVoteEmailCommand implements Command {
// TODO - replace with file template
private static final String EMAIL_TEMPLATE ="To: \"Sling Developers List\" <de...@sling.apache.org>\n" +
- "Subject: [VOTE] Release Apache Sling ##RELEASE_NAME##\n" +
+ "Subject: [VOTE] Release ##RELEASE_NAME##\n" +
"\n" +
"Hi,\n" +
"\n" +
@@ -73,11 +73,11 @@ public class PrepareVoteEmailCommand implements Command {
try {
int repoId = Integer.parseInt(target);
StagingRepository repo = repoFinder.find(repoId);
- String cleanVersion = getCleanVersion(repo.getDescription());
- Version version = versionFinder.find(cleanVersion);
+ ReleaseVersion releaseVersion = ReleaseVersion.fromRepositoryDescription(repo.getDescription());
+ Version version = versionFinder.find(releaseVersion.getName());
String emailContents = EMAIL_TEMPLATE
- .replace("##RELEASE_NAME##", cleanVersion)
+ .replace("##RELEASE_NAME##", releaseVersion.getFullName())
.replace("##RELEASE_ID##", String.valueOf(repoId))
.replace("##VERSION_ID##", String.valueOf(version.getId()))
.replace("##FIXED_ISSUES_COUNT##", String.valueOf(version.getIssuesFixedCount()));
@@ -88,11 +88,4 @@ public class PrepareVoteEmailCommand implements Command {
logger.warn("Failed executing command", e);
}
}
-
- static String getCleanVersion(String repoDescription) {
- return repoDescription
- .replace("Apache Sling ", "") // Apache Sling prefix
- .replaceAll(" RC[0-9]*$", ""); // 'release candidate' suffix
- }
-
}
diff --git a/src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java b/src/main/java/org/apache/sling/cli/impl/release/ReleaseVersion.java
similarity index 50%
copy from src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java
copy to src/main/java/org/apache/sling/cli/impl/release/ReleaseVersion.java
index 8dd81aa..b629e19 100644
--- a/src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java
+++ b/src/main/java/org/apache/sling/cli/impl/release/ReleaseVersion.java
@@ -16,16 +16,39 @@
*/
package org.apache.sling.cli.impl.release;
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-public class PrepareVoteEmailCommandTest {
+public final class ReleaseVersion {
+
+ public static ReleaseVersion fromRepositoryDescription(String repositoryDescription) {
+
+ ReleaseVersion rel = new ReleaseVersion();
+
+ rel.fullName = repositoryDescription
+ .replaceAll(" RC[0-9]*$", ""); // 'release candidate' suffix
+ rel.name = rel.fullName
+ .replace("Apache Sling ", ""); // Apache Sling prefix
+ rel.version = rel.fullName.substring(rel.fullName.lastIndexOf(' ') + 1);
+
+ return rel;
+ }
+
+ private String fullName;
+ private String name;
+ private String version;
- @Test
- public void cleanVersion() {
+ private ReleaseVersion() {
- assertEquals("Resource Merger 1.3.10",
- PrepareVoteEmailCommand.getCleanVersion("Apache Sling Resource Merger 1.3.10 RC1"));
}
+
+ public String getFullName() {
+ return fullName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
}
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 8e34d87..f15f60b 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
@@ -42,7 +42,7 @@ public class TallyVotesCommand implements Command {
private static final String EMAIL_TEMPLATE ="\n" +
"\n" +
"To: \"Sling Developers List\" <de...@sling.apache.org>\n" +
- "Subject: [RESULT] [VOTE] Release Apache Sling ##RELEASE_NAME##\n" +
+ "Subject: [RESULT] [VOTE] Release ##RELEASE_NAME##\n" +
"\n" +
"Hi,\n" +
"\n" +
@@ -65,9 +65,8 @@ public class TallyVotesCommand implements Command {
try {
StagingRepository repository = repoFinder.find(Integer.parseInt(target));
- // TODO - release name cleanup does not belong here
- String releaseName = repository.getDescription().replaceFirst(" RC[0-9]+", "");
- EmailThread voteThread = voteThreadFinder.findVoteThread(releaseName);
+ ReleaseVersion releaseVersion = ReleaseVersion.fromRepositoryDescription(repository.getDescription());
+ EmailThread voteThread = voteThreadFinder.findVoteThread(releaseVersion.getFullName());
// TODO - validate which voters are binding and list them separately in the email
String bindingVoters = voteThread.getEmails().stream()
@@ -76,7 +75,7 @@ public class TallyVotesCommand implements Command {
.collect(Collectors.joining(", "));
String email = EMAIL_TEMPLATE
- .replace("##RELEASE_NAME##", releaseName)
+ .replace("##RELEASE_NAME##", releaseVersion.getFullName())
.replace("##BINDING_VOTERS##", bindingVoters);
logger.info(email);
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
new file mode 100644
index 0000000..483613e
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/release/UpdateLocalSiteCommand.java
@@ -0,0 +1,102 @@
+/*
+ * 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.sling.cli.impl.release;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Locale;
+
+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.StagingRepositoryFinder;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.ResetCommand.ResetType;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(service = Command.class, property = {
+ Command.PROPERTY_NAME_COMMAND+"=release",
+ Command.PROPERTY_NAME_SUBCOMMAND+"=update-local-site",
+ Command.PROPERTY_NAME_SUMMARY+"=Updates the Sling website with the new release information, based on a local checkout"
+})
+public class UpdateLocalSiteCommand implements Command {
+
+ public static void main(String[] args) {
+ System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("MMMM uuuu", Locale.ENGLISH)));
+ }
+
+ private static final String GIT_CHECKOUT = "/tmp/sling-site";
+
+ @Reference
+ private StagingRepositoryFinder repoFinder;
+
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Override
+ public void execute(String target) {
+
+
+ try {
+ ensureRepo();
+ try ( Git git = Git.open(new File(GIT_CHECKOUT)) ) {
+
+ StagingRepository repository = repoFinder.find(Integer.parseInt(target));
+ ReleaseVersion releaseVersion = ReleaseVersion.fromRepositoryDescription(repository.getDescription());
+
+ JBakeContentUpdater updater = new JBakeContentUpdater();
+
+ Path templatePath = Paths.get(GIT_CHECKOUT, "src", "main", "jbake", "templates", "downloads.tpl");
+ Path releasesPath = Paths.get(GIT_CHECKOUT, "src", "main", "jbake", "content", "releases.md");
+ updater.updateDownloads(templatePath, releaseVersion.getName(), releaseVersion.getVersion());
+ updater.updateReleases(releasesPath, releaseVersion.getName(), releaseVersion.getVersion(), LocalDateTime.now());
+
+ git.diff()
+ .setOutputStream(System.out)
+ .call();
+ }
+ } catch (GitAPIException | IOException e) {
+ logger.warn("Failed executing command", e);
+ }
+
+ }
+
+ private void ensureRepo() throws GitAPIException, IOException {
+
+ if ( !Paths.get(GIT_CHECKOUT).toFile().exists() ) {
+ Git.cloneRepository()
+ .setURI("https://github.com/apache/sling-site.git")
+ .setProgressMonitor(new TextProgressMonitor())
+ .setDirectory(new File(GIT_CHECKOUT))
+ .call();
+ } else {
+ try ( Git git = Git.open(new File(GIT_CHECKOUT)) ) {
+ git.reset()
+ .setMode(ResetType.HARD)
+ .call();
+ }
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java b/src/test/java/org/apache/sling/cli/impl/release/ReleaseVersionTest.java
similarity index 70%
rename from src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java
rename to src/test/java/org/apache/sling/cli/impl/release/ReleaseVersionTest.java
index 8dd81aa..90ed3e5 100644
--- a/src/test/java/org/apache/sling/cli/impl/release/PrepareVoteEmailCommandTest.java
+++ b/src/test/java/org/apache/sling/cli/impl/release/ReleaseVersionTest.java
@@ -20,12 +20,15 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test;
-public class PrepareVoteEmailCommandTest {
+public class ReleaseVersionTest {
@Test
- public void cleanVersion() {
+ public void fromRepositoryDescription() {
- assertEquals("Resource Merger 1.3.10",
- PrepareVoteEmailCommand.getCleanVersion("Apache Sling Resource Merger 1.3.10 RC1"));
+ ReleaseVersion rel = ReleaseVersion.fromRepositoryDescription("Apache Sling Resource Merger 1.3.10 RC1");
+
+ assertEquals("Resource Merger 1.3.10", rel.getName());
+ assertEquals("Apache Sling Resource Merger 1.3.10", rel.getFullName());
+ assertEquals("1.3.10", rel.getVersion());
}
}