Skip to content
This repository was archived by the owner on Oct 2, 2025. It is now read-only.

Commit 7de326a

Browse files
fix(retrofit2): fix google cloud build notification agent for missing Retrofit2SyncCall.execute call (#1500) (#1502)
* test(retrofit2): add a test to demonstrate the issue of missing Retrofit2SyncCall.execute call in GoogleCloudBuildNotificationAgent * fix(retrofit2): fix the issue of missing Retrofit2SyncCall.execute call in GoogleCloudBuildNotificationAgent (cherry picked from commit dde4a9c) Co-authored-by: Kiran Godishala <[email protected]>
1 parent 4c0e295 commit 7de326a

File tree

4 files changed

+120
-9
lines changed

4 files changed

+120
-9
lines changed

echo-notifications/echo-notifications.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ dependencies {
4343
testImplementation "org.springframework:spring-test"
4444
testImplementation "com.squareup.retrofit2:retrofit-mock"
4545
testImplementation "com.github.tomakehurst:wiremock-jre8"
46+
testImplementation "com.github.tomakehurst:wiremock-jre8-standalone"
4647
testImplementation "org.assertj:assertj-core"
4748
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
4849
}

echo-notifications/src/main/java/com/netflix/spinnaker/echo/notification/GoogleCloudBuildNotificationAgent.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.netflix.spinnaker.echo.model.pubsub.MessageDescription;
2222
import com.netflix.spinnaker.echo.services.IgorService;
2323
import com.netflix.spinnaker.kork.core.RetrySupport;
24+
import com.netflix.spinnaker.kork.retrofit.Retrofit2SyncCall;
2425
import com.netflix.spinnaker.security.AuthenticatedRequest;
2526
import lombok.RequiredArgsConstructor;
2627
import lombok.extern.slf4j.Slf4j;
@@ -50,13 +51,14 @@ public void processEvent(Event event) {
5051
() ->
5152
AuthenticatedRequest.allowAnonymous(
5253
() ->
53-
igorService.updateBuildStatus(
54-
messageDescription.getSubscriptionName(),
55-
messageDescription.getMessageAttributes().get("buildId"),
56-
messageDescription.getMessageAttributes().get("status"),
57-
RequestBody.create(
58-
messageDescription.getMessagePayload(),
59-
MediaType.parse("application/json")))),
54+
Retrofit2SyncCall.execute(
55+
igorService.updateBuildStatus(
56+
messageDescription.getSubscriptionName(),
57+
messageDescription.getMessageAttributes().get("buildId"),
58+
messageDescription.getMessageAttributes().get("status"),
59+
RequestBody.create(
60+
messageDescription.getMessagePayload(),
61+
MediaType.parse("application/json"))))),
6062
5,
6163
2000,
6264
false);

echo-notifications/src/test/groovy/com/netflix/spinnaker/echo/notification/GoogleCloudBuildNotificationSpec.groovy

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.netflix.spinnaker.echo.model.pubsub.MessageDescription
2424
import com.netflix.spinnaker.echo.services.IgorService
2525
import com.netflix.spinnaker.kork.core.RetrySupport
2626
import okhttp3.RequestBody
27+
import retrofit2.mock.Calls
2728
import spock.lang.Specification
2829
import spock.lang.Subject
2930

@@ -61,7 +62,7 @@ class GoogleCloudBuildNotificationSpec extends Specification {
6162
notificationAgent.processEvent(event)
6263

6364
then:
64-
1 * igorService.updateBuildStatus(ACCOUNT_NAME, BUILD_ID, BUILD_STATUS, { it -> itToString(it) == PAYLOAD })
65+
1 * igorService.updateBuildStatus(ACCOUNT_NAME, BUILD_ID, BUILD_STATUS, { it -> itToString(it) == PAYLOAD }) >> Calls.response(null)
6566
0 * igorService._
6667
}
6768

@@ -74,7 +75,7 @@ class GoogleCloudBuildNotificationSpec extends Specification {
7475

7576
then:
7677
2 * igorService.updateBuildStatus(ACCOUNT_NAME, BUILD_ID, BUILD_STATUS, { it -> itToString(it) == PAYLOAD }) >>
77-
{ throw new RuntimeException() } >> { }
78+
{ throw new RuntimeException() } >> { Calls.response(null) }
7879
0 * igorService._
7980
}
8081

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2025 OpsMx, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.netflix.spinnaker.echo.notification;
18+
19+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
20+
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
21+
import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor;
22+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
23+
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
24+
25+
import com.fasterxml.jackson.core.JsonProcessingException;
26+
import com.fasterxml.jackson.databind.ObjectMapper;
27+
import com.github.tomakehurst.wiremock.client.WireMock;
28+
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
29+
import com.netflix.spinnaker.echo.api.events.Event;
30+
import com.netflix.spinnaker.echo.api.events.Metadata;
31+
import com.netflix.spinnaker.echo.model.pubsub.MessageDescription;
32+
import com.netflix.spinnaker.echo.services.IgorService;
33+
import com.netflix.spinnaker.echo.util.RetrofitUtils;
34+
import com.netflix.spinnaker.kork.core.RetrySupport;
35+
import com.netflix.spinnaker.kork.retrofit.ErrorHandlingExecutorCallAdapterFactory;
36+
import java.util.HashMap;
37+
import java.util.Map;
38+
import okhttp3.OkHttpClient;
39+
import org.junit.jupiter.api.BeforeAll;
40+
import org.junit.jupiter.api.Test;
41+
import org.junit.jupiter.api.extension.RegisterExtension;
42+
import retrofit2.Retrofit;
43+
import retrofit2.converter.jackson.JacksonConverterFactory;
44+
45+
public class GoogleCloudBuildNotificationAgentTest {
46+
public static final String ACCOUNT = "my-account";
47+
public static final String BUILD_ID = "1a9ea355-eb3d-4148-b81b-875d07ea118b";
48+
public static final String BUILD_STATUS = "QUEUED";
49+
50+
@RegisterExtension
51+
static final WireMockExtension wmIgor =
52+
WireMockExtension.newInstance().options(wireMockConfig().dynamicPort()).build();
53+
54+
static GoogleCloudBuildNotificationAgent notificationAgent;
55+
static ObjectMapper mapper = new ObjectMapper();
56+
57+
@BeforeAll
58+
public static void setup() {
59+
// Create IgorService
60+
IgorService igorService =
61+
new Retrofit.Builder()
62+
.baseUrl(RetrofitUtils.getBaseUrl(wmIgor.baseUrl()))
63+
.client(new OkHttpClient())
64+
.addCallAdapterFactory(ErrorHandlingExecutorCallAdapterFactory.getInstance())
65+
.addConverterFactory(JacksonConverterFactory.create())
66+
.build()
67+
.create(IgorService.class);
68+
69+
notificationAgent = new GoogleCloudBuildNotificationAgent(igorService, new RetrySupport());
70+
}
71+
72+
@Test
73+
public void testGoogleCloudBuildNotificationAgent() throws JsonProcessingException {
74+
String updateBuildStatusUrl = "/gcb/builds/" + ACCOUNT + "/" + BUILD_ID;
75+
76+
wmIgor.stubFor(
77+
WireMock.put(urlPathEqualTo(updateBuildStatusUrl))
78+
.withQueryParam("status", equalTo(BUILD_STATUS))
79+
.willReturn(aResponse().withStatus(200).withBody("[]")));
80+
81+
notificationAgent.processEvent(createEvent());
82+
83+
wmIgor.verify(
84+
1,
85+
putRequestedFor(urlPathEqualTo(updateBuildStatusUrl))
86+
.withQueryParam("status", equalTo(BUILD_STATUS)));
87+
}
88+
89+
private Event createEvent() throws JsonProcessingException {
90+
MessageDescription messageDescription =
91+
MessageDescription.builder()
92+
.subscriptionName(ACCOUNT)
93+
.messagePayload(mapper.writeValueAsString(Map.of("key", "value")))
94+
.messageAttributes(Map.of("buildId", BUILD_ID, "status", BUILD_STATUS))
95+
.build();
96+
Map<String, Object> content = new HashMap<>();
97+
content.put("messageDescription", messageDescription);
98+
99+
Metadata details = new Metadata();
100+
details.setType("googleCloudBuild");
101+
102+
Event event = new Event();
103+
event.setContent(content);
104+
event.setDetails(details);
105+
return event;
106+
}
107+
}

0 commit comments

Comments
 (0)