private GetResponse get(String appUrl, AccessToken token, String endPoint, boolean withLog) throws IOException {
validateEndPoint(endPoint);
-
try (okhttp3.Response response = client.newCall(newGetRequest(appUrl, token, endPoint)).execute()) {
int responseCode = response.code();
if (responseCode != HTTP_OK) {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.alm.client.github;
+
+import java.util.Optional;
+
+import static org.apache.commons.lang.StringUtils.substringBetween;
+
+
+public final class SonarQubeIssueKeyFormatter {
+ static final String SONAR_ISSUE_KEY_PREFIX = "<!--SONAR_ISSUE_KEY:";
+ static final String SONAR_ISSUE_KEY_SUFFIX = "-->";
+
+ private SonarQubeIssueKeyFormatter() {
+ }
+
+ public static String serialize(String key) {
+ return SONAR_ISSUE_KEY_PREFIX + key + SONAR_ISSUE_KEY_SUFFIX;
+ }
+
+ public static Optional<String> deserialize(String messageText) {
+ return Optional.ofNullable(substringBetween(messageText, SONAR_ISSUE_KEY_PREFIX, SONAR_ISSUE_KEY_SUFFIX));
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.alm.client.github;
+
+import java.util.Optional;
+import org.apache.commons.lang.RandomStringUtils;
+import org.junit.Test;
+
+import static java.lang.String.join;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.alm.client.github.SonarQubeIssueKeyFormatter.SONAR_ISSUE_KEY_PREFIX;
+import static org.sonar.alm.client.github.SonarQubeIssueKeyFormatter.SONAR_ISSUE_KEY_SUFFIX;
+
+public class SonarQubeIssueKeyFormatterTest {
+
+ @Test
+ public void should_serializeIssueKey() {
+ String issueKey = RandomStringUtils.randomAlphanumeric(20);
+
+ String serialized = SonarQubeIssueKeyFormatter.serialize(issueKey);
+
+ String expectedSerializedKey = join("", SONAR_ISSUE_KEY_PREFIX, issueKey, SONAR_ISSUE_KEY_SUFFIX);
+ assertThat(serialized).isEqualTo(expectedSerializedKey);
+ }
+
+ @Test
+ public void should_deserializeIssueKey() {
+ String issueKey = RandomStringUtils.randomAlphanumeric(20);
+ String message = join("", SONAR_ISSUE_KEY_PREFIX, issueKey, SONAR_ISSUE_KEY_SUFFIX, "a message");
+
+ Optional<String> deserialized = SonarQubeIssueKeyFormatter.deserialize(message);
+
+ assertThat(deserialized).hasValue(issueKey);
+ }
+
+ @Test
+ public void should_notDeserializeIssueKey_when_messageHasWrongFormat() {
+ String issueKey = RandomStringUtils.randomAlphanumeric(20);
+ String messageWithoutSuffix = join("", SONAR_ISSUE_KEY_PREFIX, issueKey, "a message");
+ String messageWithoutPrefix = join("", issueKey, SONAR_ISSUE_KEY_SUFFIX, "a message");
+ String messageWithPrefixSuffixReversed = join("", SONAR_ISSUE_KEY_SUFFIX, issueKey, SONAR_ISSUE_KEY_PREFIX, "a message");
+ String messageWithNoPrefixSuffix = join("", issueKey, "a message");
+
+ assertThat(SonarQubeIssueKeyFormatter.deserialize(messageWithoutSuffix)).isEmpty();
+ assertThat(SonarQubeIssueKeyFormatter.deserialize(messageWithoutPrefix)).isEmpty();
+ assertThat(SonarQubeIssueKeyFormatter.deserialize(messageWithPrefixSuffixReversed)).isEmpty();
+ assertThat(SonarQubeIssueKeyFormatter.deserialize(messageWithNoPrefixSuffix)).isEmpty();
+ }
+}
public static final int DEFAULT_CONNECT_TIMEOUT_MILLISECONDS = 30_000;
public static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = 60_000;
+ private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
/**
* Base URL with trailing slash, for instance "https://localhost/sonarqube/".
RequestBody body;
Map<String, PostRequest.Part> parts = postRequest.getParts();
- if (parts.isEmpty()) {
+ if (postRequest.hasBody()) {
+ body = RequestBody.create(JSON, postRequest.getBody());
+ } else if (parts.isEmpty()) {
// parameters are defined in the body (application/x-www-form-urlencoded)
FormBody.Builder formBody = new FormBody.Builder();
postRequest.getParameters().getKeys()
*/
public class PostRequest extends BaseRequest<PostRequest> {
+ private String body;
private final Map<String, Part> parts = new LinkedHashMap<>();
public PostRequest(String path) {
return Method.POST;
}
+ public PostRequest setBody(String body) {
+ this.body = body;
+ return this;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public boolean hasBody() {
+ return this.body != null;
+ }
+
public PostRequest setPart(String name, Part part) {
this.parts.put(name, part);
return this;
AlmIntegrations.SearchBitbucketcloudReposWsResponse.parser());
}
+ /**
+ * This is part of the internal API.
+ * This is a POST request.
+ *
+ * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/alm_integrations/webhook_github">Further information about this action online (including a response example)</a>
+ * @since 9.7
+ */
+ public void sendGitubCodeScanningAlertWebhookPayload(SendGithubCodeScanningAlertWebhookPayloadRequest request) {
+ call(
+ new PostRequest(path("webhook_github"))
+ .setHeader("X-GitHub-Event", request.getGithubEventHeader())
+ .setHeader("X-Hub-Signature", request.getGithubSignatureHeader())
+ .setHeader("X-Hub-Signature-256", request.getGithubSignature256Header())
+ .setBody(request.getPayload())
+ .setMediaType(MediaTypes.JSON)
+ ).content();
+ }
+
/**
* This is part of the internal API.
* This is a POST request.
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonarqube.ws.client.almintegrations;
+
+import javax.annotation.Generated;
+
+/**
+ * This is part of the internal API.
+ * This is a POST request.
+ * @see <a href="https://next.sonarqube.com/sonarqube/web_api/api/alm_integrations/webhook_github">Further information about this action online (including a response example)</a>
+ * @since 9.7
+ */
+@Generated("sonar-ws-generator")
+public class SendGithubCodeScanningAlertWebhookPayloadRequest {
+ private String payload;
+ private String githubEventHeader;
+ private String githubSignatureHeader;
+ private String githubSignature256Header;
+
+ /**
+ * This is a mandatory parameter.
+ */
+ public SendGithubCodeScanningAlertWebhookPayloadRequest setPayload(String payload) {
+ this.payload = payload;
+ return this;
+ }
+
+ public String getPayload() {
+ return payload;
+ }
+
+ /**
+ * This is a mandatory parameter.
+ */
+ public SendGithubCodeScanningAlertWebhookPayloadRequest setGithubEventHeader(String header) {
+ this.githubEventHeader = header;
+ return this;
+ }
+
+ public String getGithubEventHeader() {
+ return githubEventHeader;
+ }
+
+ /**
+ * This is a mandatory parameter.
+ */
+ public SendGithubCodeScanningAlertWebhookPayloadRequest setGithubSignatureHeader(String header) {
+ this.githubSignatureHeader = header;
+ return this;
+ }
+
+ public String getGithubSignatureHeader() {
+ return this.githubSignatureHeader;
+ }
+
+ /**
+ * This is a mandatory parameter.
+ */
+ public SendGithubCodeScanningAlertWebhookPayloadRequest setGithubSignature256Header(String header) {
+ this.githubSignature256Header = header;
+ return this;
+ }
+
+ public String getGithubSignature256Header() {
+ return githubSignature256Header;
+ }
+}
assertThat(recordedRequest.getHeader("X-Bar")).isEqualTo("barz");
}
+ @Test
+ public void setBody_shouldAddCorrectlyBodyPayloadToPostRequest_whenComposingAndSendingPostRequest() throws Exception {
+ answerHelloWorld();
+
+ String xGithubEventHeader = "code_scanning_alert";
+ String xHubSignatureHeader = "x-hub-signature";
+ String xHubSignature256Header = "x-hub-signature-256";
+ String bodyRaw = "{\"state\":\"open\"}";
+
+ PostRequest request = new PostRequest("api/alm_integrations/webhook_github")
+ .setHeader("X-GitHub-Event", xGithubEventHeader)
+ .setHeader("X-Hub-Signature", xHubSignatureHeader)
+ .setHeader("X-Hub-Signature-256", xHubSignature256Header)
+ .setBody(bodyRaw)
+ .setMediaType(MediaTypes.JSON);
+
+ underTest = HttpConnector.newBuilder().url(serverUrl).build();
+ underTest.call(request);
+
+ RecordedRequest recordedRequest = server.takeRequest();
+ assertThat(recordedRequest.getHeader("X-GitHub-Event")).isEqualTo(xGithubEventHeader);
+ assertThat(recordedRequest.getHeader("X-Hub-Signature")).isEqualTo(xHubSignatureHeader);
+ assertThat(recordedRequest.getHeader("X-Hub-Signature-256")).isEqualTo(xHubSignature256Header);
+ assertThat(recordedRequest.getBody().readUtf8()).isEqualTo(bodyRaw);
+ }
+
@Test
public void upload_file() throws Exception {
answerHelloWorld();
assertThat(part.getMediaType()).isEqualTo(MediaTypes.JSON);
assertThat(part.getFile()).isSameAs(reportFile);
}
+
+ @Test
+ public void setBody_shouldCorrectlyAddRawBodyToPostRequest() throws IOException {
+ String bodyRaw = "{\"state\":\"open\"}";
+ PostRequest request = new PostRequest("api/alm_integrations/webhook_github");
+ request.setBody(bodyRaw);
+
+ assertThat(request.getBody()).isEqualTo(bodyRaw);
+ assertThat(request.hasBody()).isTrue();
+ }
}