Skip to content

Commit ab3742b

Browse files
authored
Auto rewrite (#2477)
* Format code * Add rewrite profile * Rewrite improvements * Automatically review PRs with OpenRewrite recipe runs
1 parent 8b8c4cf commit ab3742b

File tree

31 files changed

+631
-373
lines changed

31 files changed

+631
-373
lines changed

.github/workflows/comment-pr.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Description: This workflow is triggered when the `receive-pr` workflow completes to post suggestions on the PR.
2+
# Since this pull request has write permissions on the target repo, we should **NOT** execute any untrusted code.
3+
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
4+
---
5+
name: comment-pr
6+
7+
on:
8+
workflow_run:
9+
workflows: ["receive-pr"]
10+
types:
11+
- completed
12+
13+
jobs:
14+
post-suggestions:
15+
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#running-a-workflow-based-on-the-conclusion-of-another-workflow
16+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
17+
runs-on: ubuntu-latest
18+
env:
19+
# https://docs.github.com/en/actions/reference/authentication-in-a-workflow#permissions-for-the-github_token
20+
ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21+
timeout-minutes: 10
22+
steps:
23+
- uses: actions/checkout@v4
24+
with:
25+
ref: ${{github.event.workflow_run.head_branch}}
26+
repository: ${{github.event.workflow_run.head_repository.full_name}}
27+
28+
# Download the patch
29+
- uses: actions/download-artifact@v4
30+
with:
31+
name: patch
32+
github-token: ${{ secrets.GITHUB_TOKEN }}
33+
run-id: ${{ github.event.workflow_run.id }}
34+
- name: Apply patch
35+
run: |
36+
git apply git-diff.patch --allow-empty
37+
rm git-diff.patch
38+
39+
# Download the PR number
40+
- uses: actions/download-artifact@v4
41+
with:
42+
name: pr_number
43+
github-token: ${{ secrets.GITHUB_TOKEN }}
44+
run-id: ${{ github.event.workflow_run.id }}
45+
- name: Read pr_number.txt
46+
run: |
47+
PR_NUMBER=$(cat pr_number.txt)
48+
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV
49+
rm pr_number.txt
50+
51+
# Post suggestions as a comment on the PR
52+
- uses: googleapis/code-suggester@v4
53+
with:
54+
command: review
55+
pull_number: ${{ env.PR_NUMBER }}
56+
git_dir: '.'

.github/workflows/receive-pr.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Description: This workflow runs OpenRewrite recipes against opened pull request and upload the patch.
2+
# Since this pull request receives untrusted code, we should **NOT** have any secrets in the environment.
3+
# https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
4+
---
5+
name: receive-pr
6+
7+
on:
8+
pull_request:
9+
types: [opened, synchronize]
10+
branches:
11+
- main
12+
13+
concurrency:
14+
group: '${{ github.workflow }} @ ${{ github.ref }}'
15+
cancel-in-progress: true
16+
17+
jobs:
18+
upload-patch:
19+
runs-on: ubuntu-latest
20+
timeout-minutes: 10
21+
steps:
22+
- uses: actions/checkout@v4
23+
with:
24+
ref: ${{github.event.pull_request.head.ref}}
25+
repository: ${{github.event.pull_request.head.repo.full_name}}
26+
- uses: actions/setup-java@v4
27+
with:
28+
java-version: '21'
29+
distribution: 'temurin'
30+
cache: 'maven'
31+
32+
# Capture the PR number
33+
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow
34+
- name: Create pr_number.txt
35+
run: echo "${{ github.event.number }}" > pr_number.txt
36+
- uses: actions/upload-artifact@v4
37+
with:
38+
name: pr_number
39+
path: pr_number.txt
40+
- name: Remove pr_number.txt
41+
run: rm -f pr_number.txt
42+
43+
# Execute recipes
44+
- name: Apply OpenRewrite recipes
45+
run: mvn --activate-profiles openrewrite org.openrewrite.maven:rewrite-maven-plugin:run
46+
47+
# Capture the diff
48+
- name: Create patch
49+
run: |
50+
git diff | tee git-diff.patch
51+
- uses: actions/upload-artifact@v4
52+
with:
53+
name: patch
54+
path: git-diff.patch

core/src/main/java/feign/Response.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,9 @@ public int status() {
157157
}
158158

159159
/**
160-
* Nullable and not set when using http/2
161-
* See <a href="https://github.com/http2/http2-spec/issues/202">...</a>
162-
* See <a href="https://github.com/http2/http2-spec/issues/202">...</a>
160+
* Nullable and not set when using http/2 See
161+
* <a href="https://github.com/http2/http2-spec/issues/202">...</a> See
162+
* <a href="https://github.com/http2/http2-spec/issues/202">...</a>
163163
*/
164164
public String reason() {
165165
return reason;
@@ -196,9 +196,11 @@ public ProtocolVersion protocolVersion() {
196196
}
197197

198198
/**
199-
* Returns a charset object based on the requests content type. Defaults to UTF-8
200-
* See <a href="https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.3">rfc7231 - Accept-Charset</a>
201-
* See <a href="https://datatracker.ietf.org/doc/html/rfc7231#section-3.1.1.1">rfc7231 - Media Type</a>
199+
* Returns a charset object based on the requests content type. Defaults to UTF-8 See
200+
* <a href="https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.3">rfc7231 -
201+
* Accept-Charset</a> See
202+
* <a href="https://datatracker.ietf.org/doc/html/rfc7231#section-3.1.1.1">rfc7231 - Media
203+
* Type</a>
202204
*/
203205
public Charset charset() {
204206

core/src/main/java/feign/RetryableException.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ public class RetryableException extends FeignException {
3030
private final HttpMethod httpMethod;
3131

3232
/**
33-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
34-
* If you don't want to retry, set null.
33+
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header. If you
34+
* don't want to retry, set null.
3535
*/
3636
public RetryableException(int status, String message, HttpMethod httpMethod, Throwable cause,
3737
Long retryAfter, Request request) {
@@ -49,8 +49,8 @@ public RetryableException(int status, String message, HttpMethod httpMethod, Thr
4949
}
5050

5151
/**
52-
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header.
53-
* If you don't want to retry, set null.
52+
* @param retryAfter usually corresponds to the {@link feign.Util#RETRY_AFTER} header. If you
53+
* don't want to retry, set null.
5454
*/
5555
public RetryableException(int status, String message, HttpMethod httpMethod, Long retryAfter,
5656
Request request) {

core/src/test/java/feign/BaseBuilderTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 The Feign Authors
2+
* Copyright 2012-2024 The Feign Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -41,10 +41,10 @@ private void test(BaseBuilder<?, ?> builder, int expectedFieldsCount)
4141
for (Field field : fields) {
4242
field.setAccessible(true);
4343
Object mockedValue = field.get(enriched);
44-
if (mockedValue instanceof List) {
45-
assertThat((List) mockedValue).withFailMessage("Enriched list missing contents %s", field)
44+
if (mockedValue instanceof List<?> list) {
45+
assertThat(list).withFailMessage("Enriched list missing contents %s", field)
4646
.isNotEmpty();
47-
mockedValue = ((List<Object>) mockedValue).get(0);
47+
mockedValue = list.getFirst();
4848
}
4949
assertThat(Mockito.mockingDetails(mockedValue)
5050
.isMock()).as("Field was not enriched " + field).isTrue();

core/src/test/java/feign/ClientTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@ void testConvertAndSendWithContentLength() throws IOException {
8383
Map<String, List<String>> requestProperties = urlConnection.getRequestProperties();
8484
String requestProperty = urlConnection.getRequestProperty(Util.CONTENT_LENGTH);
8585
/*
86-
* By default, "Content-Length" will not be added because this key is in the
87-
* restrictedHeaderSet of HttpURLConnection.
88-
* Unless set system property "sun.net.http.allowRestrictedHeaders" to "true"
86+
* By default, "Content-Length" will not be added because this key is in the restrictedHeaderSet
87+
* of HttpURLConnection. Unless set system property "sun.net.http.allowRestrictedHeaders" to
88+
* "true"
8989
*/
9090
assertNull(requestProperties.get(Util.CONTENT_LENGTH));
9191
}

core/src/test/java/feign/DefaultContractInheritanceTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 The Feign Authors
2+
* Copyright 2012-2024 The Feign Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -46,9 +46,9 @@ void simpleParameterizedBaseApi() throws Exception {
4646

4747
assertThat(md).hasSize(1);
4848

49-
assertThat(md.get(0).configKey()).isEqualTo("SimpleParameterizedApi#get(String)");
50-
assertThat(md.get(0).returnType()).isEqualTo(String.class);
51-
assertThat(md.get(0).template()).hasHeaders(entry("Foo", asList("Bar")));
49+
assertThat(md.getFirst().configKey()).isEqualTo("SimpleParameterizedApi#get(String)");
50+
assertThat(md.getFirst().returnType()).isEqualTo(String.class);
51+
assertThat(md.getFirst().template()).hasHeaders(entry("Foo", asList("Bar")));
5252
}
5353

5454
@Test

core/src/test/java/feign/DefaultContractTest.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 The Feign Authors
2+
* Copyright 2012-2024 The Feign Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -659,14 +659,14 @@ void parameterizedHeaderExpandApi() throws Exception {
659659

660660
assertThat(md).hasSize(1);
661661

662-
assertThat(md.get(0).configKey())
662+
assertThat(md.getFirst().configKey())
663663
.isEqualTo("ParameterizedHeaderExpandApi#getZone(String,String)");
664-
assertThat(md.get(0).returnType()).isEqualTo(String.class);
665-
assertThat(md.get(0).template()).hasHeaders(entry("Authorization", asList("{authHdr}")),
664+
assertThat(md.getFirst().returnType()).isEqualTo(String.class);
665+
assertThat(md.getFirst().template()).hasHeaders(entry("Authorization", asList("{authHdr}")),
666666
entry("Accept", asList("application/json")));
667667
// Ensure that the authHdr expansion was properly detected and did not create a
668668
// formParam
669-
assertThat(md.get(0).formParams()).isEmpty();
669+
assertThat(md.getFirst().formParams()).isEmpty();
670670
}
671671

672672
@Test
@@ -676,14 +676,15 @@ void parameterizedHeaderNotStartingWithCurlyBraceExpandApi() throws Exception {
676676

677677
assertThat(md).hasSize(1);
678678

679-
assertThat(md.get(0).configKey())
679+
assertThat(md.getFirst().configKey())
680680
.isEqualTo("ParameterizedHeaderNotStartingWithCurlyBraceExpandApi#getZone(String,String)");
681-
assertThat(md.get(0).returnType()).isEqualTo(String.class);
682-
assertThat(md.get(0).template()).hasHeaders(entry("Authorization", asList("Bearer {authHdr}")),
681+
assertThat(md.getFirst().returnType()).isEqualTo(String.class);
682+
assertThat(md.getFirst().template()).hasHeaders(
683+
entry("Authorization", asList("Bearer {authHdr}")),
683684
entry("Accept", asList("application/json")));
684685
// Ensure that the authHdr expansion was properly detected and did not create a
685686
// formParam
686-
assertThat(md.get(0).formParams()).isEmpty();
687+
assertThat(md.getFirst().formParams()).isEmpty();
687688
}
688689

689690
@Headers("Authorization: Bearer {authHdr}")
@@ -771,7 +772,7 @@ void staticMethodsOnInterfaceIgnored() throws Exception {
771772
final List<MethodMetadata> mds =
772773
contract.parseAndValidateMetadata(StaticMethodOnInterface.class);
773774
assertThat(mds).hasSize(1);
774-
final MethodMetadata md = mds.get(0);
775+
final MethodMetadata md = mds.getFirst();
775776
assertThat(md.configKey()).isEqualTo("StaticMethodOnInterface#get(String)");
776777
}
777778

@@ -789,7 +790,7 @@ void defaultMethodsOnInterfaceIgnored() throws Exception {
789790
final List<MethodMetadata> mds =
790791
contract.parseAndValidateMetadata(DefaultMethodOnInterface.class);
791792
assertThat(mds).hasSize(1);
792-
final MethodMetadata md = mds.get(0);
793+
final MethodMetadata md = mds.getFirst();
793794
assertThat(md.configKey()).isEqualTo("DefaultMethodOnInterface#get(String)");
794795
}
795796

@@ -802,8 +803,9 @@ interface SubstringQuery {
802803
void paramIsASubstringOfAQuery() throws Exception {
803804
final List<MethodMetadata> mds = contract.parseAndValidateMetadata(SubstringQuery.class);
804805

805-
assertThat(mds.get(0).template().queries()).containsExactly(entry("q", asList("body:{body}")));
806-
assertThat(mds.get(0).formParams()).isEmpty(); // Prevent issue 424
806+
assertThat(mds.getFirst().template().queries())
807+
.containsExactly(entry("q", asList("body:{body}")));
808+
assertThat(mds.getFirst().formParams()).isEmpty(); // Prevent issue 424
807809
}
808810

809811
@Test

core/src/test/java/feign/FeignExceptionTest.java

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 The Feign Authors
2+
* Copyright 2012-2024 The Feign Authors
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
55
* in compliance with the License. You may obtain a copy of the License at
@@ -119,18 +119,27 @@ void canGetResponseHeadersFromException() {
119119

120120
@Test
121121
void lengthOfBodyExceptionTest() {
122-
String bigResponse = "I love a storm in early May\n"
123-
+ "When springtime’s boisterous, firstborn thunder\n"
124-
+ "Over the sky will gaily wander\n" + "And growl and roar as though in play.\n" + "\n"
125-
+ "A peal, another — gleeful, cheering…\n" + "Rain, raindust… On the trees, behold!-\n"
126-
+ "The drops hang, each a long pearl earring;\n"
127-
+ "Bright sunshine paints the thin threads gold.\n"
128-
+ "\n" + "A stream downhill goes rushing reckless,\n"
129-
+ "And in the woods the birds rejoice.\n"
130-
+ "Din. Clamour. Noise. All nature echoes\n" + "The thunder’s youthful, merry voice.\n"
131-
+ "\n"
132-
+ "You’ll say: ‘Tis laughing, carefree Hebe —\n" + "She fed her father’s eagle, and\n"
133-
+ "The Storm Cup brimming with a seething\n" + "And bubbling wine dropped from her hand";
122+
String bigResponse = """
123+
I love a storm in early May
124+
When springtime’s boisterous, firstborn thunder
125+
Over the sky will gaily wander
126+
And growl and roar as though in play.
127+
128+
A peal, another — gleeful, cheering…
129+
Rain, raindust… On the trees, behold!-
130+
The drops hang, each a long pearl earring;
131+
Bright sunshine paints the thin threads gold.
132+
133+
A stream downhill goes rushing reckless,
134+
And in the woods the birds rejoice.
135+
Din. Clamour. Noise. All nature echoes
136+
The thunder’s youthful, merry voice.
137+
138+
You’ll say: ‘Tis laughing, carefree Hebe —
139+
She fed her father’s eagle, and
140+
The Storm Cup brimming with a seething
141+
And bubbling wine dropped from her hand\
142+
""";
134143

135144
Request request = Request.create(Request.HttpMethod.GET, "/home", Collections.emptyMap(),
136145
"data".getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8, null);

core/src/test/java/feign/LoggerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ void expectMessages(List<String> expectedMessages) {
407407

408408
@Override
409409
protected void log(String configKey, String format, Object... args) {
410-
messages.add(methodTag(configKey) + String.format(format, args));
410+
messages.add(methodTag(configKey) + format.formatted(args));
411411
}
412412

413413
// @Override

0 commit comments

Comments
 (0)