Skip to content

Commit bfa6ef1

Browse files
BEE-72087: Replace rest-assured with Java HttpClient to fix Java 25 PCT failures
rest-assured:5.3.2 transitively pulls in groovy:4.0.11 which introduces asmResolving=true as the default class resolution strategy. When tests run on Java 25, GroovyClassLoader compiles WorkflowScript at major version 69 at runtime. ASM 9.5 (in groovy:4.0.11) supports up to version 64, causing: IllegalArgumentException: Unsupported class file major version 69 rest-assured was only used in GitHubWebHookFullTest for plain HTTP request/response assertions. Replace it with java.net.http.HttpClient (built-in since Java 11) to eliminate the transitive groovy:4.0.11 dependency entirely. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 8e3b016 commit bfa6ef1

2 files changed

Lines changed: 79 additions & 105 deletions

File tree

pom.xml

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,7 @@
128128

129129
<!--TEST DEPS-->
130130

131-
<!-- 4.5.3 used by rest-assured -->
132-
<dependency>
133-
<groupId>org.jenkins-ci.plugins</groupId>
134-
<artifactId>apache-httpcomponents-client-4-api</artifactId>
135-
<scope>test</scope>
136-
</dependency>
137-
138-
<dependency>
131+
<dependency>
139132
<groupId>org.mockito</groupId>
140133
<artifactId>mockito-core</artifactId>
141134
<scope>test</scope>
@@ -190,12 +183,6 @@
190183
<scope>test</scope>
191184
</dependency>
192185

193-
<dependency>
194-
<groupId>io.rest-assured</groupId>
195-
<artifactId>rest-assured</artifactId>
196-
<version>5.3.2</version>
197-
<scope>test</scope>
198-
</dependency>
199186

200187
</dependencies>
201188

Lines changed: 78 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
package com.cloudbees.jenkins;
22

33
import com.google.common.base.Charsets;
4-
import com.google.common.net.HttpHeaders;
5-
import io.restassured.builder.RequestSpecBuilder;
6-
import io.restassured.http.Header;
7-
import io.restassured.specification.RequestSpecification;
84
import jakarta.inject.Inject;
95
import org.apache.commons.io.IOUtils;
106
import org.jenkinsci.plugins.github.config.GitHubPluginConfig;
@@ -18,158 +14,153 @@
1814

1915
import java.io.File;
2016
import java.io.IOException;
17+
import java.net.URI;
18+
import java.net.http.HttpClient;
19+
import java.net.http.HttpRequest;
20+
import java.net.http.HttpResponse;
2121

22-
import static io.restassured.RestAssured.given;
23-
import static io.restassured.config.EncoderConfig.encoderConfig;
24-
import static io.restassured.config.RestAssuredConfig.newConfig;
2522
import static jakarta.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
2623
import static jakarta.servlet.http.HttpServletResponse.SC_METHOD_NOT_ALLOWED;
2724
import static jakarta.servlet.http.HttpServletResponse.SC_OK;
2825
import static java.lang.String.format;
2926
import static org.apache.commons.lang3.ClassUtils.PACKAGE_SEPARATOR;
27+
import static org.hamcrest.MatcherAssert.assertThat;
3028
import static org.hamcrest.Matchers.containsString;
29+
import static org.hamcrest.Matchers.is;
3130
import static org.hamcrest.Matchers.notNullValue;
3231
import static org.jenkinsci.plugins.github.test.HookSecretHelper.removeSecretIn;
3332
import static org.jenkinsci.plugins.github.test.HookSecretHelper.storeSecretIn;
34-
import static org.jenkinsci.plugins.github.webhook.RequirePostWithGHHookPayload.Processor.*;
33+
import static org.jenkinsci.plugins.github.webhook.RequirePostWithGHHookPayload.Processor.SHA256_PREFIX;
34+
import static org.jenkinsci.plugins.github.webhook.RequirePostWithGHHookPayload.Processor.SIGNATURE_HEADER;
35+
import static org.jenkinsci.plugins.github.webhook.RequirePostWithGHHookPayload.Processor.SIGNATURE_HEADER_SHA256;
3536

3637
/**
3738
* @author lanwen (Merkushev Kirill)
3839
*/
3940
@WithJenkins
4041
public class GitHubWebHookFullTest {
4142

42-
// GitHub doesn't send the charset per docs, so re-use the exact content-type from the handler
4343
public static final String APPLICATION_JSON = GHEventPayload.PayloadHandler.APPLICATION_JSON;
4444
public static final String FORM = GHEventPayload.PayloadHandler.FORM_URLENCODED;
4545

46-
public static final Header JSON_CONTENT_TYPE = new Header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON);
47-
public static final Header FORM_CONTENT_TYPE = new Header(HttpHeaders.CONTENT_TYPE, FORM);
48-
public static final String NOT_NULL_VALUE = "nonnull";
49-
50-
private RequestSpecification spec;
51-
5246
@Inject
5347
private GitHubPluginConfig config;
5448

5549
private JenkinsRule jenkins;
50+
private HttpClient httpClient;
5651

5752
@BeforeEach
5853
void before(JenkinsRule rule) throws Throwable {
5954
jenkins = rule;
6055
jenkins.getInstance().getInjector().injectMembers(this);
61-
62-
spec = new RequestSpecBuilder()
63-
.setConfig(newConfig()
64-
.encoderConfig(encoderConfig()
65-
.defaultContentCharset(Charsets.UTF_8.name())
66-
// GitHub doesn't add charsets, so don't test with them
67-
.appendDefaultContentCharsetToContentTypeIfUndefined(false)))
68-
.build();
56+
httpClient = HttpClient.newHttpClient();
6957
}
7058

7159
@Test
7260
void shouldParseJsonWebHookFromGH() throws Exception {
7361
removeSecretIn(config);
74-
given().spec(spec)
75-
.header(eventHeader(GHEvent.PUSH))
76-
.header(JSON_CONTENT_TYPE)
77-
.body(classpath("payloads/push.json"))
78-
.log().all()
79-
.expect().log().all().statusCode(SC_OK).request().post(getPath());
62+
HttpResponse<String> response = httpClient.send(
63+
HttpRequest.newBuilder(URI.create(getPath()))
64+
.POST(HttpRequest.BodyPublishers.ofString(classpath("payloads/push.json")))
65+
.header("Content-Type", APPLICATION_JSON)
66+
.header(GHEventHeader.PayloadHandler.EVENT_HEADER, GHEvent.PUSH.name().toLowerCase())
67+
.build(),
68+
HttpResponse.BodyHandlers.ofString());
69+
assertThat("status", response.statusCode(), is(SC_OK));
8070
}
8171

82-
8372
@Test
8473
void shouldParseJsonWebHookFromGHWithSignHeader() throws Exception {
8574
String hash = "355e155fc3d10c4e5f2c6086a01281d2e947d932";
8675
String hash256 = "85e61999573c7023720a12375e1e55d18a0870e1ef880736f6ffc9273d0519e3";
8776
String secret = "123";
8877

8978
storeSecretIn(config, secret);
90-
given().spec(spec)
91-
.header(eventHeader(GHEvent.PUSH))
92-
.header(JSON_CONTENT_TYPE)
93-
.header(SIGNATURE_HEADER, format("sha1=%s", hash))
94-
.header(SIGNATURE_HEADER_SHA256, format("%s%s", SHA256_PREFIX, hash256))
95-
.body(classpath(String.format("payloads/ping_hash_%s_secret_%s.json", hash, secret)))
96-
.log().all()
97-
.expect().log().all().statusCode(SC_OK).request().post(getPath());
79+
HttpResponse<String> response = httpClient.send(
80+
HttpRequest.newBuilder(URI.create(getPath()))
81+
.POST(HttpRequest.BodyPublishers.ofString(
82+
classpath(format("payloads/ping_hash_%s_secret_%s.json", hash, secret))))
83+
.header("Content-Type", APPLICATION_JSON)
84+
.header(GHEventHeader.PayloadHandler.EVENT_HEADER, GHEvent.PUSH.name().toLowerCase())
85+
.header(SIGNATURE_HEADER, format("sha1=%s", hash))
86+
.header(SIGNATURE_HEADER_SHA256, format("%s%s", SHA256_PREFIX, hash256))
87+
.build(),
88+
HttpResponse.BodyHandlers.ofString());
89+
assertThat("status", response.statusCode(), is(SC_OK));
9890
}
9991

10092
@Test
10193
void shouldParseFormWebHookOrServiceHookFromGH() throws Exception {
102-
given().spec(spec)
103-
.header(eventHeader(GHEvent.PUSH))
104-
.header(FORM_CONTENT_TYPE)
105-
.formParam("payload", classpath("payloads/push.json"))
106-
.log().all()
107-
.expect().log().all().statusCode(SC_OK).request().post(getPath());
94+
String encoded = "payload=" + java.net.URLEncoder.encode(classpath("payloads/push.json"), "UTF-8");
95+
HttpResponse<String> response = httpClient.send(
96+
HttpRequest.newBuilder(URI.create(getPath()))
97+
.POST(HttpRequest.BodyPublishers.ofString(encoded))
98+
.header("Content-Type", FORM)
99+
.header(GHEventHeader.PayloadHandler.EVENT_HEADER, GHEvent.PUSH.name().toLowerCase())
100+
.build(),
101+
HttpResponse.BodyHandlers.ofString());
102+
assertThat("status", response.statusCode(), is(SC_OK));
108103
}
109104

110105
@Test
111106
void shouldParsePingFromGH() throws Exception {
112-
given().spec(spec)
113-
.header(eventHeader(GHEvent.PING))
114-
.header(JSON_CONTENT_TYPE)
115-
.body(classpath("payloads/ping.json"))
116-
.log().all()
117-
.expect().log().all()
118-
.statusCode(SC_OK)
119-
.request()
120-
.post(getPath());
107+
HttpResponse<String> response = httpClient.send(
108+
HttpRequest.newBuilder(URI.create(getPath()))
109+
.POST(HttpRequest.BodyPublishers.ofString(classpath("payloads/ping.json")))
110+
.header("Content-Type", APPLICATION_JSON)
111+
.header(GHEventHeader.PayloadHandler.EVENT_HEADER, GHEvent.PING.name().toLowerCase())
112+
.build(),
113+
HttpResponse.BodyHandlers.ofString());
114+
assertThat("status", response.statusCode(), is(SC_OK));
121115
}
122116

123117
@Test
124118
void shouldReturnErrOnEmptyPayloadAndHeader() throws Exception {
125-
given().spec(spec)
126-
.log().all()
127-
.expect().log().all()
128-
.statusCode(SC_BAD_REQUEST)
129-
.body(containsString("Hook should contain event type"))
130-
.request()
131-
.post(getPath());
119+
HttpResponse<String> response = httpClient.send(
120+
HttpRequest.newBuilder(URI.create(getPath()))
121+
.POST(HttpRequest.BodyPublishers.noBody())
122+
.build(),
123+
HttpResponse.BodyHandlers.ofString());
124+
assertThat("status", response.statusCode(), is(SC_BAD_REQUEST));
125+
assertThat("body", response.body(), containsString("Hook should contain event type"));
132126
}
133127

134128
@Test
135129
void shouldReturnErrOnEmptyPayload() throws Exception {
136-
given().spec(spec)
137-
.header(eventHeader(GHEvent.PUSH))
138-
.log().all()
139-
.expect().log().all()
140-
.statusCode(SC_BAD_REQUEST)
141-
.body(containsString("Hook should contain payload"))
142-
.request()
143-
.post(getPath());
130+
HttpResponse<String> response = httpClient.send(
131+
HttpRequest.newBuilder(URI.create(getPath()))
132+
.POST(HttpRequest.BodyPublishers.noBody())
133+
.header(GHEventHeader.PayloadHandler.EVENT_HEADER, GHEvent.PUSH.name().toLowerCase())
134+
.build(),
135+
HttpResponse.BodyHandlers.ofString());
136+
assertThat("status", response.statusCode(), is(SC_BAD_REQUEST));
137+
assertThat("body", response.body(), containsString("Hook should contain payload"));
144138
}
145139

146140
@Test
147141
void shouldReturnErrOnGetReq() throws Exception {
148-
given().spec(spec)
149-
.log().all().expect().log().all()
150-
.statusCode(SC_METHOD_NOT_ALLOWED)
151-
.request()
152-
.get(getPath());
142+
HttpResponse<String> response = httpClient.send(
143+
HttpRequest.newBuilder(URI.create(getPath()))
144+
.GET()
145+
.build(),
146+
HttpResponse.BodyHandlers.ofString());
147+
assertThat("status", response.statusCode(), is(SC_METHOD_NOT_ALLOWED));
153148
}
154149

155150
@Test
156151
void shouldProcessSelfTest() throws Exception {
157-
given().spec(spec)
158-
.header(new Header(GitHubWebHook.URL_VALIDATION_HEADER, NOT_NULL_VALUE))
159-
.log().all()
160-
.expect().log().all()
161-
.statusCode(SC_OK)
162-
.header(GitHubWebHook.X_INSTANCE_IDENTITY, notNullValue())
163-
.request()
164-
.post(getPath());
165-
}
166-
167-
public Header eventHeader(GHEvent event) {
168-
return eventHeader(event.name().toLowerCase());
152+
HttpResponse<String> response = httpClient.send(
153+
HttpRequest.newBuilder(URI.create(getPath()))
154+
.POST(HttpRequest.BodyPublishers.noBody())
155+
.header(GitHubWebHook.URL_VALIDATION_HEADER, "nonnull")
156+
.build(),
157+
HttpResponse.BodyHandlers.ofString());
158+
assertThat("status", response.statusCode(), is(SC_OK));
159+
assertThat("identity header", response.headers().firstValue(GitHubWebHook.X_INSTANCE_IDENTITY).orElse(null), notNullValue());
169160
}
170161

171-
public Header eventHeader(String event) {
172-
return new Header(GHEventHeader.PayloadHandler.EVENT_HEADER, event);
162+
private String getPath() {
163+
return jenkins.getInstance().getRootUrl() + GitHubWebHook.URLNAME.concat("/");
173164
}
174165

175166
public static String classpath(String path) {
@@ -185,8 +176,4 @@ public static String classpath(Class<?> clazz, String path) {
185176
throw new RuntimeException(format("Can't load %s for class %s", path, clazz), e);
186177
}
187178
}
188-
189-
private String getPath(){
190-
return jenkins.getInstance().getRootUrl() + GitHubWebHook.URLNAME.concat("/");
191-
}
192179
}

0 commit comments

Comments
 (0)