diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ed0311e24..8e75b66f3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -18,7 +18,7 @@ updates: - dependency-name: "javax.servlet:javax.servlet-api" # Newer versions require code changes # N/A - # Maintain dependencies for GitHub actions +# Maintain dependencies for GitHub actions - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java index 9c4ddcb90..d32a1104e 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java @@ -227,7 +227,9 @@ public static void migrateJobs() throws IOException { } } } - gitLabConfig.save(); + if (gitLabConfig != null) { + gitLabConfig.save(); + } oldConfig.jobsMigrated = true; oldConfig.save(); } diff --git a/src/main/java/com/dabsquared/gitlabjenkins/gitlab/api/impl/V4GitLabClientBuilder.java b/src/main/java/com/dabsquared/gitlabjenkins/gitlab/api/impl/V4GitLabClientBuilder.java index c6a5f0bd3..a15ccd6ad 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/gitlab/api/impl/V4GitLabClientBuilder.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/gitlab/api/impl/V4GitLabClientBuilder.java @@ -1,9 +1,19 @@ package com.dabsquared.gitlabjenkins.gitlab.api.impl; +import static com.dabsquared.gitlabjenkins.webhook.ActionResolver.getSecretToken; + import com.dabsquared.gitlabjenkins.gitlab.api.GitLabClientBuilder; import hudson.Extension; +import hudson.ProxyConfiguration; +import java.net.InetSocketAddress; +import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.URL; +import java.util.Map; +import jenkins.model.Jenkins; import org.gitlab4j.api.GitLabApi; import org.gitlab4j.api.GitLabApi.ApiVersion; +import org.gitlab4j.api.ProxyClientConfig; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -11,7 +21,9 @@ @Restricted(NoExternalUse.class) public final class V4GitLabClientBuilder extends GitLabClientBuilder { + ProxyConfiguration httpProxyConfig = Jenkins.getActiveInstance().proxy; private static final int ORDINAL = 1; + private transient GitLabApi client; public V4GitLabClientBuilder() { super("V4", ORDINAL); @@ -20,9 +32,30 @@ public V4GitLabClientBuilder() { @Override public GitLabApi buildClient( String url, String token, boolean ignoreCertificateErrors, int connectionTimeout, int readTimeout) { - GitLabApi client = new GitLabApi(ApiVersion.V4, url, token); + if (httpProxyConfig != null) { + Proxy proxy = httpProxyConfig.createProxy(getHost(url)); + InetSocketAddress address = (InetSocketAddress) proxy.address(); + String proxyHost = address.getHostString(); + int proxyPort = address.getPort(); + String proxyUri = "http://" + proxyHost + ":" + proxyPort; + if (httpProxyConfig.getUserName() != null && httpProxyConfig.getPassword() != null) { + Map clientConfig = ProxyClientConfig.createProxyClientConfig( + proxyUri, httpProxyConfig.getUserName(), httpProxyConfig.getPassword()); + client = new GitLabApi(ApiVersion.V4, url, token, getSecretToken(), clientConfig); + } + } else { + client = new GitLabApi(ApiVersion.V4, url, token, getSecretToken()); + } client.setIgnoreCertificateErrors(ignoreCertificateErrors); client.setRequestTimeout(connectionTimeout, readTimeout); return client; } + + private String getHost(String url) { + try { + return new URL(url).getHost(); + } catch (MalformedURLException e) { + return null; + } + } } diff --git a/src/main/java/com/dabsquared/gitlabjenkins/webhook/ActionResolver.java b/src/main/java/com/dabsquared/gitlabjenkins/webhook/ActionResolver.java index ec06c397e..1089a824d 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/webhook/ActionResolver.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/webhook/ActionResolver.java @@ -37,7 +37,11 @@ public class ActionResolver { private static final Pattern COMMIT_STATUS_PATTERN = Pattern.compile("^(refs/[^/]+/)?(commits|builds)/(?[0-9a-fA-F]+)(?/status.json)?$"); - public WebHookAction resolve(final String projectName, StaplerRequest request, StaplerResponse response) { + WebHookManager webHookManager = new WebHookManager(); + SystemHookManager systemHookManager = new SystemHookManager(); + static String secretToken; + + public void resolve(final String projectName, StaplerRequest request, StaplerResponse response) { Iterator restOfPathParts = Arrays.stream(request.getRestOfPath().split("/")) .filter(s -> !s.isEmpty()) .iterator(); @@ -50,23 +54,22 @@ public WebHookAction resolve(final String projectName, StaplerRequest request, S restOfPath.add(restOfPathParts.next()); } resolveAction(project, restOfPath.toString(), request, response); - return null; } private void resolveAction(Item project, String restOfPath, StaplerRequest request, StaplerResponse response) { String method = request.getMethod(); try { - WebHookManager webHookManager = new WebHookManager(); webHookManager.addListener(new GitLabHookResolver(project, request, response)); webHookManager.handleEvent(request); + setSecretToken(webHookManager.getSecretToken()); throw HttpResponses.ok(); } catch (GitLabApiException e) { LOGGER.log(Level.FINE, "WebHook was not supported for this project {0}", project.getName()); } try { - SystemHookManager systemHookManager = new SystemHookManager(); systemHookManager.addListener(new GitLabHookResolver(project, request, response)); systemHookManager.handleEvent(request); + setSecretToken(systemHookManager.getSecretToken()); throw HttpResponses.ok(); } catch (GitLabApiException e) { LOGGER.log(Level.FINE, "SystemHook was not supported for this project {0}", project.getName()); @@ -140,6 +143,14 @@ public Item invoke() { }); } + private static void setSecretToken(String token) { + secretToken = token; + } + + public static String getSecretToken() { + return secretToken; + } + static class NoopAction implements WebHookAction { public void execute(StaplerResponse response) {} } diff --git a/src/test/java/com/dabsquared/gitlabjenkins/connection/GitLabConnectionConfigTest.java b/src/test/java/com/dabsquared/gitlabjenkins/connection/GitLabConnectionConfigTest.java index 6f1c96d38..76a57e66b 100644 --- a/src/test/java/com/dabsquared/gitlabjenkins/connection/GitLabConnectionConfigTest.java +++ b/src/test/java/com/dabsquared/gitlabjenkins/connection/GitLabConnectionConfigTest.java @@ -2,6 +2,7 @@ import static com.dabsquared.gitlabjenkins.connection.Messages.connection_error; import static com.dabsquared.gitlabjenkins.connection.Messages.connection_success; +import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertNotNull; @@ -16,6 +17,7 @@ import com.cloudbees.plugins.credentials.domains.Domain; import com.dabsquared.gitlabjenkins.connection.GitLabConnection.DescriptorImpl; import com.dabsquared.gitlabjenkins.gitlab.api.impl.V4GitLabClientBuilder; +import hudson.ProxyConfiguration; import hudson.model.Item; import hudson.security.GlobalMatrixAuthorizationStrategy; import hudson.util.FormValidation; @@ -87,21 +89,23 @@ public void doCheckConnection_forbidden() { String expected = connection_error("Forbidden"); assertThat(doCheckConnection("V4", Response.Status.FORBIDDEN), is(expected)); } - // TODO: Adapt proxy tests during proxy implementation - // @Test - // public void doCheckConnection_proxy() { - // jenkins.getInstance().proxy = new ProxyConfiguration("0.0.0.0", 80); - // GitLabConnection.DescriptorImpl descriptor = - // (DescriptorImpl) jenkins.jenkins.getDescriptorOrDie(GitLabConnection.class); - // FormValidation result = descriptor.doTestConnection(gitLabUrl, API_TOKEN_ID, "V4", false, 10, 10); - // assertThat(result.getMessage(), containsString("Connection refused")); - // } - // - // @Test - // public void doCheckConnection_noProxy() { - // jenkins.getInstance().proxy = new ProxyConfiguration("0.0.0.0", 80, "", "", "localhost"); - // assertThat(doCheckConnection("V4", Response.Status.OK), is(connection_success())); - // } + + @Test + public void doCheckConnection_proxy() { + jenkins.getInstance().proxy = new ProxyConfiguration("0.0.0.0", 80); + GitLabConnection.DescriptorImpl descriptor = + (DescriptorImpl) jenkins.jenkins.getDescriptorOrDie(GitLabConnection.class); + FormValidation result = descriptor.doTestConnection(gitLabUrl, API_TOKEN_ID, "V4", true, 60, 60); + // TODO: Should be "connection refused" instead of "connection timeout" + assertThat( + result.getMessage(), containsString("Client error: java.net.SocketTimeoutException: Read timed out")); + } + + @Test + public void doCheckConnection_noProxy() { + jenkins.getInstance().proxy = new ProxyConfiguration("0.0.0.0", 80, "", "", "localhost"); + assertThat(doCheckConnection("V4", Response.Status.OK), is(connection_success())); + } private String doCheckConnection(String clientBuilderId, Response.Status status) { HttpRequest request = diff --git a/src/test/java/com/dabsquared/gitlabjenkins/trigger/handler/merge/MergeRequestHookTriggerHandlerImplTest.java b/src/test/java/com/dabsquared/gitlabjenkins/trigger/handler/merge/MergeRequestHookTriggerHandlerImplTest.java index f7daf47f0..84e611fb7 100644 --- a/src/test/java/com/dabsquared/gitlabjenkins/trigger/handler/merge/MergeRequestHookTriggerHandlerImplTest.java +++ b/src/test/java/com/dabsquared/gitlabjenkins/trigger/handler/merge/MergeRequestHookTriggerHandlerImplTest.java @@ -136,6 +136,7 @@ public void mergeRequest_build_when_reopened() throws Exception { @Test public void mergeRequest_build_when_opened_with_approved_action_enabled() throws Exception { + MergeRequestHookTriggerHandler mergeRequestHookTriggerHandler = withConfig() .setTriggerOnApprovedMergeRequest(true) .setTriggerOpenMergeRequest(TriggerOpenMergeRequest.source) @@ -208,6 +209,7 @@ public void mergeRequest_build_when_closed_with_actions_enabled() throws Excepti .setTriggerOnClosedMergeRequest(true) .setTriggerOnApprovedMergeRequest(true) .build(); + final AtomicReference buildHolder = new AtomicReference<>(); OneShotEvent buildTriggered = doHandle(mergeRequestHookTriggerHandler, MergeRequestState.CLOSED, ActionType.CLOSED, buildHolder); diff --git a/src/test/java/com/dabsquared/gitlabjenkins/trigger/handler/push/PushHookTriggerHandlerImplTest.java b/src/test/java/com/dabsquared/gitlabjenkins/trigger/handler/push/PushHookTriggerHandlerImplTest.java index fb007c7b9..17f774033 100644 --- a/src/test/java/com/dabsquared/gitlabjenkins/trigger/handler/push/PushHookTriggerHandlerImplTest.java +++ b/src/test/java/com/dabsquared/gitlabjenkins/trigger/handler/push/PushHookTriggerHandlerImplTest.java @@ -203,6 +203,5 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen assertThat(buildTriggered.isSignaled(), is(false)); // TODO: Should be 2, but fails assertThat(buildCount.intValue(), is(1)); - // jenkins.assertBuildStatusSuccess(jenkins.waitForCompletion(buildHolder.get())); } } diff --git a/src/test/java/com/dabsquared/gitlabjenkins/webhook/build/PushBuildActionTest.java b/src/test/java/com/dabsquared/gitlabjenkins/webhook/build/PushBuildActionTest.java index 4ebec8f85..1c653361d 100644 --- a/src/test/java/com/dabsquared/gitlabjenkins/webhook/build/PushBuildActionTest.java +++ b/src/test/java/com/dabsquared/gitlabjenkins/webhook/build/PushBuildActionTest.java @@ -181,20 +181,15 @@ public void invalidToken() throws IOException { verify(trigger, never()).onPost(any(PushEvent.class)); } - // TODO : Will be fixed in later milestone PRs - // @Test - // public void scmSourceOnUpdateExecuted() { - // GitSCMSource source = new GitSCMSource("http://test"); - // SCMSourceOwner item = mock(SCMSourceOwner.class); - // ACL acl = mock(ACL.class); - // when(item.getSCMSources()).thenReturn(Collections.singletonList(source)); - // when(item.getACL()).thenReturn(acl); - // Assert.assertThrows( - // HttpResponses.HttpResponseException.class, - // () -> new PushBuildAction(item, getJson("PushEvent.json"), null).execute(response)); - // item.onSCMSourceUpdated(source); - // verify(item).onSCMSourceUpdated(isA(GitSCMSource.class)); - // } + @Test + public void scmSourceOnUpdateExecuted() { + GitSCMSource source = new GitSCMSource("http://test"); + SCMSourceOwner item = mock(SCMSourceOwner.class); + when(item.getSCMSources()).thenReturn(Collections.singletonList(source)); + exception.expect(NullPointerException.class); + new PushBuildAction(item, pushEvent, null).execute(response); + verify(item).onSCMSourceUpdated(isA(GitSCMSource.class)); + } @Test public void scmSourceOnUpdateNotExecuted() {