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/24 12:32:06 UTC
[sling-org-apache-sling-committer-cli] 37/44: SLING-8337 - Create
sub-command to manage the Jira update when promoting a release
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 7deca18cc89a9f6b1c7eff019ce87c04c0d441cc
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Tue Apr 23 16:14:37 2019 +0300
SLING-8337 - Create sub-command to manage the Jira update when promoting
a release
Move the VersionClient to be an HTTP-based test in preparation for
testing commands that change state.
---
pom.xml | 9 +--
.../sling/cli/impl/ComponentContextHelper.java | 47 ++++++++++++
.../sling/cli/impl/http/HttpClientFactory.java | 17 ++++-
.../apache/sling/cli/impl/jira/VersionClient.java | 28 ++++---
.../org/apache/sling/cli/impl/jira/MockJira.java | 86 ++++++++++++++++++++++
.../sling/cli/impl/jira/VersionClientTest.java | 50 +++----------
6 files changed, 182 insertions(+), 55 deletions(-)
diff --git a/pom.xml b/pom.xml
index 6fa560a..bf1224a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -164,6 +164,10 @@
<artifactId>osgi.core</artifactId>
</dependency>
<dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>osgi.cmpn</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.feature.launcher</artifactId>
<version>0.8.0</version>
@@ -231,10 +235,5 @@
<version>1.3.0</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>osgi.cmpn</artifactId>
- <scope>test</scope>
- </dependency>
</dependencies>
</project>
diff --git a/src/main/java/org/apache/sling/cli/impl/ComponentContextHelper.java b/src/main/java/org/apache/sling/cli/impl/ComponentContextHelper.java
new file mode 100644
index 0000000..b996e88
--- /dev/null
+++ b/src/main/java/org/apache/sling/cli/impl/ComponentContextHelper.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+import org.osgi.service.component.ComponentContext;
+
+public class ComponentContextHelper {
+
+ public static ComponentContextHelper wrap(ComponentContext wrapped) {
+
+ return new ComponentContextHelper(wrapped);
+ }
+
+ private final ComponentContext wrapped;
+
+ public ComponentContextHelper(ComponentContext wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ public String getProperty(String name, String fallback) {
+ Object prop = wrapped.getProperties().get(name);
+ if ( prop != null) {
+ return prop.toString();
+ }
+
+ return fallback;
+ }
+
+ public int getProperty(String name, int fallback) {
+
+ return Integer.parseInt(getProperty(name, String.valueOf(fallback)));
+ }
+}
diff --git a/src/main/java/org/apache/sling/cli/impl/http/HttpClientFactory.java b/src/main/java/org/apache/sling/cli/impl/http/HttpClientFactory.java
index 7975145..f881594 100644
--- a/src/main/java/org/apache/sling/cli/impl/http/HttpClientFactory.java
+++ b/src/main/java/org/apache/sling/cli/impl/http/HttpClientFactory.java
@@ -21,16 +21,31 @@ import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
+import org.apache.sling.cli.impl.ComponentContextHelper;
import org.apache.sling.cli.impl.Credentials;
import org.apache.sling.cli.impl.CredentialsService;
+import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@Component(service = HttpClientFactory.class)
public class HttpClientFactory {
+ private static final String DEFAULT_JIRA_HOST = "jira.apache.org";
+ private static final int DEFAULT_JIRA_PORT = 443;
+
@Reference
private CredentialsService credentialsService;
+
+ private String jiraHost;
+ private int jiraPort;
+
+ protected void activate(ComponentContext ctx) {
+
+ ComponentContextHelper helper = ComponentContextHelper.wrap(ctx);
+ jiraHost = helper.getProperty("jira.host", DEFAULT_JIRA_HOST);
+ jiraPort = helper.getProperty("jira.port", DEFAULT_JIRA_PORT);
+ }
public CloseableHttpClient newClient() {
@@ -42,7 +57,7 @@ public class HttpClientFactory {
new UsernamePasswordCredentials(asf.getUsername(), asf.getPassword()));
credentialsProvider.setCredentials(new AuthScope("reporter.apache.org", 443),
new UsernamePasswordCredentials(asf.getUsername(), asf.getPassword()));
- credentialsProvider.setCredentials(new AuthScope("jira.apache.org", 443),
+ credentialsProvider.setCredentials(new AuthScope(jiraHost, jiraPort),
new UsernamePasswordCredentials(jira.getUsername(), jira.getPassword()));
return HttpClients.custom()
diff --git a/src/main/java/org/apache/sling/cli/impl/jira/VersionClient.java b/src/main/java/org/apache/sling/cli/impl/jira/VersionClient.java
index 77e6881..0c11c3c 100644
--- a/src/main/java/org/apache/sling/cli/impl/jira/VersionClient.java
+++ b/src/main/java/org/apache/sling/cli/impl/jira/VersionClient.java
@@ -32,8 +32,10 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
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.release.Release;
+import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@@ -47,11 +49,17 @@ import com.google.gson.stream.JsonWriter;
@Component(service = VersionClient.class)
public class VersionClient {
- private static final String JIRA_URL_PREFIX = "https://issues.apache.org/jira/rest/api/2/";
+ private static final String DEFAULT_JIRA_URL_PREFIX = "https://issues.apache.org/jira/rest/api/2/";
private static final String CONTENT_TYPE_JSON = "application/json";
@Reference
private HttpClientFactory httpClientFactory;
+ private String jiraUrlPrefix;
+
+ protected void activate(ComponentContext ctx) {
+ ComponentContextHelper helper = ComponentContextHelper.wrap(ctx);
+ jiraUrlPrefix = helper.getProperty("jira.url.prefix", DEFAULT_JIRA_URL_PREFIX);
+ }
/**
* Finds a Jira version which matches the specified release
@@ -98,12 +106,8 @@ public class VersionClient {
try (CloseableHttpClient client = httpClientFactory.newClient()) {
Optional<Version> opt = findVersion (
- v -> {
- Release releaseFromVersion = Release.fromString(v.getName()).get(0);
- return
- releaseFromVersion.getComponent().equals(release.getComponent())
- && new org.osgi.framework.Version(releaseFromVersion.getVersion()).compareTo(new org.osgi.framework.Version(release.getVersion())) > 0;
- },client);
+ v -> isFollowingVersion(Release.fromString(v.getName()).get(0), release)
+ ,client);
if ( !opt.isPresent() )
return null;
version = opt.get();
@@ -115,6 +119,12 @@ public class VersionClient {
return version;
}
+ private boolean isFollowingVersion(Release base, Release candidate) {
+ return base.getComponent().equals(candidate.getComponent())
+ && new org.osgi.framework.Version(base.getVersion())
+ .compareTo(new org.osgi.framework.Version(candidate.getVersion())) > 0;
+ }
+
public void create(String versionName) throws IOException {
StringWriter w = new StringWriter();
try ( JsonWriter jw = new Gson().newJsonWriter(w) ) {
@@ -124,7 +134,7 @@ public class VersionClient {
jw.endObject();
}
- HttpPost post = new HttpPost(JIRA_URL_PREFIX + "version");
+ HttpPost post = new HttpPost(jiraUrlPrefix + "version");
post.addHeader("Content-Type", CONTENT_TYPE_JSON);
post.addHeader("Accept", CONTENT_TYPE_JSON);
post.setEntity(new StringEntity(w.toString()));
@@ -190,7 +200,7 @@ public class VersionClient {
}
private HttpGet newGet(String suffix) {
- HttpGet get = new HttpGet(JIRA_URL_PREFIX + suffix);
+ HttpGet get = new HttpGet(jiraUrlPrefix + suffix);
get.addHeader("Accept", CONTENT_TYPE_JSON);
return get;
}
diff --git a/src/test/java/org/apache/sling/cli/impl/jira/MockJira.java b/src/test/java/org/apache/sling/cli/impl/jira/MockJira.java
new file mode 100644
index 0000000..903f8b0
--- /dev/null
+++ b/src/test/java/org/apache/sling/cli/impl/jira/MockJira.java
@@ -0,0 +1,86 @@
+/*
+ * 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.jira;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.rules.ExternalResource;
+
+import com.sun.net.httpserver.HttpServer;
+
+public class MockJira extends ExternalResource {
+
+ private static final Pattern VERSION_RELATED_ISSUES = Pattern.compile("^/jira/rest/api/2/version/(\\d+)/relatedIssueCounts$");
+
+ public static void main(String[] args) throws Throwable {
+
+ MockJira mj = new MockJira();
+ mj.before();
+ System.out.println(mj.getBoundPort());
+ }
+
+ private HttpServer server;
+
+ @Override
+ protected void before() throws Throwable {
+ server = HttpServer.create(new InetSocketAddress("localhost", 0), 0);
+ server.createContext("/", httpExchange -> {
+
+ if ( httpExchange.getRequestURI().getPath().equals("/jira/rest/api/2/project/SLING/versions") ) {
+ httpExchange.sendResponseHeaders(200, 0);
+ try ( InputStream in = getClass().getResourceAsStream("/jira/versions.json");
+ OutputStream out = httpExchange.getResponseBody() ) {
+ IOUtils.copy(in, out);
+ }
+ } else {
+ Matcher matcher = VERSION_RELATED_ISSUES.matcher(httpExchange.getRequestURI().getPath());
+ if ( matcher.matches() ) {
+ int version = Integer.parseInt(matcher.group(1));
+ InputStream in = getClass().getResourceAsStream("/jira/relatedIssueCounts/" + version + ".json");
+ if ( in == null ) {
+ httpExchange.sendResponseHeaders(404, -1);
+ } else {
+ httpExchange.sendResponseHeaders(200, 0);
+ try ( OutputStream out = httpExchange.getResponseBody() ) {
+ IOUtils.copy(in, out);
+ }
+ }
+ } else {
+ httpExchange.sendResponseHeaders(400, -1);
+ }
+ }
+ });
+
+ server.start();
+ }
+
+ @Override
+ protected void after() {
+
+ server.stop(0);
+ }
+
+ public int getBoundPort() {
+
+ return server.getAddress().getPort();
+ }
+}
diff --git a/src/test/java/org/apache/sling/cli/impl/jira/VersionClientTest.java b/src/test/java/org/apache/sling/cli/impl/jira/VersionClientTest.java
index 0cac72d..0d67dee 100644
--- a/src/test/java/org/apache/sling/cli/impl/jira/VersionClientTest.java
+++ b/src/test/java/org/apache/sling/cli/impl/jira/VersionClientTest.java
@@ -21,15 +21,9 @@ import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
-import java.util.function.Function;
-import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.sling.cli.impl.CredentialsService;
import org.apache.sling.cli.impl.http.HttpClientFactory;
import org.apache.sling.cli.impl.release.Release;
@@ -42,10 +36,10 @@ public class VersionClientTest {
private static final Map<String, String> SYSTEM_PROPS = new HashMap<>();
static {
- SYSTEM_PROPS.put("asf.username", "user");
- SYSTEM_PROPS.put("asf.password", "password");
- SYSTEM_PROPS.put("jira.username", "user");
- SYSTEM_PROPS.put("jira.password", "password");
+ SYSTEM_PROPS.put("asf.username", "asf-user");
+ SYSTEM_PROPS.put("asf.password", "asf-password");
+ SYSTEM_PROPS.put("jira.username", "jira-user");
+ SYSTEM_PROPS.put("jira.password", "jira-password");
}
@Rule
@@ -54,17 +48,17 @@ public class VersionClientTest {
@Rule
public final SystemPropertiesRule sysProps = new SystemPropertiesRule(SYSTEM_PROPS);
+ @Rule
+ public final MockJira mockJira = new MockJira();
+
private VersionClient versionClient;
@Before
public void prepareDependencies() throws ReflectiveOperationException {
- context.registerInjectActivateService(new CredentialsService());
- context.registerInjectActivateService(new HttpClientFactory());
- versionClient = new StubVersionClient();
- Field factoryField = VersionClient.class.getDeclaredField("httpClientFactory");
- factoryField.setAccessible(true);
- factoryField.set(versionClient, context.getService(HttpClientFactory.class));
+ context.registerInjectActivateService(new CredentialsService());
+ context.registerInjectActivateService(new HttpClientFactory(), "jira.host", "localhost", "jira.port", mockJira.getBoundPort());
+ versionClient = context.registerInjectActivateService(new VersionClient(), "jira.url.prefix", "http://localhost:" + mockJira.getBoundPort() + "/jira/rest/api/2/");
}
@Test
@@ -98,28 +92,4 @@ public class VersionClientTest {
assertThat("successor", successor, nullValue());
}
-
- private static final class StubVersionClient extends VersionClient {
- @Override
- protected <T> T doWithJiraVersions(CloseableHttpClient client, Function<InputStreamReader, T> parserCallback)
- throws IOException {
-
- try ( InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/jira/versions.json")) ) {
- return parserCallback.apply(reader);
- }
- }
-
- @Override
- protected <T> T doWithRelatedIssueCounts(CloseableHttpClient client, Version version,
- Function<InputStreamReader, T> parserCallback) throws IOException {
-
- InputStream stream = getClass().getResourceAsStream("/jira/relatedIssueCounts/" + version.getId()+".json");
- if ( stream == null )
- throw new IllegalArgumentException("No related issues count for version " + version.getId() + " (" + version.getName() + ")");
-
- try ( InputStreamReader reader = new InputStreamReader(stream) ) {
- return parserCallback.apply(reader);
- }
- }
- }
}