Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion deploy/pipeline/mw-pipeline-v0.1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ spec:
type: string
- name: JVM_BUILD_SERVICE_REQPROCESSOR_IMAGE
type: string
- name: NOTIFICATION_CONTEXT
type: string
default: ""
workspaces:
- name: source
description: Workspace containing the source code
Expand Down Expand Up @@ -101,7 +104,7 @@ spec:
resolver: http
params:
- name: url
value: https://raw.githubusercontent.com/redhat-appstudio/jvm-build-service/refs/heads/main/deploy/tasks/pre-build.yaml
value: https://raw.githubusercontent.com/rnc/jvm-build-service/refs/heads/BR3/deploy/tasks/pre-build.yaml
workspaces:
- name: source
workspace: source
Expand Down Expand Up @@ -161,3 +164,39 @@ spec:
params:
- name: url
value: https://raw.githubusercontent.com/redhat-appstudio/jvm-build-service/refs/heads/main/deploy/tasks/maven-deployment.yaml

finally:
- name: notification
displayName: "Notify PNC driver"
params:
- name: ACCESS_TOKEN
value: $(params.ACCESS_TOKEN)
- name: JVM_BUILD_SERVICE_REQPROCESSOR_IMAGE
value: $(params.JVM_BUILD_SERVICE_REQPROCESSOR_IMAGE)
- name: NOTIFICATION_CONTEXT
value: $(params.NOTIFICATION_CONTEXT)
- name: STATUS
value: $(tasks.status)
taskSpec:
params:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you miss param BULID_ID?

- name: ACCESS_TOKEN
description: Access token for OAuth.
type: string
default: ""
- name: JVM_BUILD_SERVICE_REQPROCESSOR_IMAGE
description: Name of the processor image. Useful to override for development.
type: string
- name: NOTIFICATION_CONTEXT
description: Notification context
type: string
- name: STATUS
description: Aggregate tasks status
type: string
steps:
- name: notification
image: $(params.JVM_BUILD_SERVICE_REQPROCESSOR_IMAGE)
args:
- notify
- --context=$(params.NOTIFICATION_CONTEXT)
- --status=$(params.STATUS)
- --build-id=$(params.BUILD_ID)
4 changes: 3 additions & 1 deletion deploy/tasks/pre-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,11 @@ spec:
- name: create-pre-build-image
image: quay.io/redhat-appstudio/build-trusted-artifacts:latest@sha256:52f1391e6f1c472fd10bb838f64fae2ed3320c636f536014978a5ddbdfc6b3af
script: |
set -x
echo "IMAGE is $(params.IMAGE_URL)"
cat $HOME/.docker/config.json || true
echo "Creating pre-build-image archive"
create-archive --store $(params.IMAGE_URL) $(results.PRE_BUILD_IMAGE_DIGEST.path)=$(workspaces.source.path)/source
env:
- name: IMAGE_URL
value: $(params.IMAGE_URL)

18 changes: 18 additions & 0 deletions java-components/build-request-processor/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@
<artifactId>quarkus-maven-resolver</artifactId>
</dependency>

<dependency>
<groupId>org.jboss.pnc</groupId>
<artifactId>pnc-api</artifactId>
<version>3.0.0</version>
</dependency>

<dependency>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-core</artifactId>
Expand Down Expand Up @@ -102,6 +108,13 @@
<artifactId>pom-manipulation-common</artifactId>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
Expand All @@ -122,6 +135,11 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.redhat.hacbs.container.deploy.CopyArtifactsCommand;
import com.redhat.hacbs.container.deploy.DeployCommand;
import com.redhat.hacbs.container.deploy.DeployPreBuildSourceCommand;
import com.redhat.hacbs.container.notification.NotifyCommand;
import com.redhat.hacbs.container.verifier.VerifyBuiltArtifactsCommand;

import io.quarkus.picocli.runtime.annotations.TopCommand;
Expand All @@ -27,6 +28,7 @@
LookupBuildInfoCommand.class,
LookupScmLocationCommand.class,
DeployCommand.class,
NotifyCommand.class,
MavenPrepareCommand.class,
SBTPrepareCommand.class,
VerifyBuiltArtifactsCommand.class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,6 @@ private String getContainerFile() {
""";
}

Log.warnf("### containerFile is\n%s", containerFile);

return containerFile;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.redhat.hacbs.container.notification;

import static org.apache.commons.lang3.StringUtils.isEmpty;

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Optional;

import jakarta.inject.Inject;

import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.pnc.api.dto.Request;

import com.fasterxml.jackson.databind.ObjectMapper;

import io.quarkus.logging.Log;
import picocli.CommandLine;

@CommandLine.Command(name = "notify")
public class NotifyCommand implements Runnable {

@CommandLine.Option(names = "--build-id", required = true)
String buildId;

@CommandLine.Option(names = "--status", required = true)
String status;

@CommandLine.Option(names = "--context", required = true)
String context;

@CommandLine.Option(names = "--request-timeout")
int requestTimeout = 15;

// TODO: do we need this...
@ConfigProperty(name = "access.token")
Optional<String> accessToken;

@Inject
ObjectMapper objectMapper;

public void run() {
try {

if (isEmpty(context)) {
Log.infof("No callback configured ; unable to notify.");
return;
}

Request callback = objectMapper.readValue(context, Request.class );

Log.infof("Notification for build %s with status %s and callback %s", buildId, status, callback);
PipelineNotification notification = PipelineNotification.builder().buildId(buildId).status(status).completionCallback((Request) callback.getAttachment()).build();
String body = objectMapper.writeValueAsString(notification);

HttpRequest.Builder builder = HttpRequest.newBuilder()
.uri(callback.getUri())
.method(callback.getMethod().name(), HttpRequest.BodyPublishers.ofString(body))
.timeout(Duration.ofSeconds(requestTimeout));
callback.getHeaders().forEach(h -> builder.header(h.getName(), h.getValue()));


HttpRequest request = builder.build();
// TODO: Retry? Send async? Some useful mutiny examples from quarkus in https://gist.github.com/cescoffier/e9abce907a1c3d05d70bea3dae6dc3d5
HttpResponse<String> response;
try (HttpClient httpClient = HttpClient.newHttpClient()) {
response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
}
Log.infof("Response %s", response);

} catch (Exception e) {
Log.error("Notification failed", e);
throw new RuntimeException(e);

Check warning on line 74 in java-components/build-request-processor/src/main/java/com/redhat/hacbs/container/notification/NotifyCommand.java

View check run for this annotation

Codecov / codecov/patch

java-components/build-request-processor/src/main/java/com/redhat/hacbs/container/notification/NotifyCommand.java#L72-L74

Added lines #L72 - L74 were not covered by tests
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.redhat.hacbs.container.notification;

import org.jboss.pnc.api.dto.Request;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import lombok.Builder;

// TODO: This is a direct copy of the same class in konflux-build-driver. Both need moved to pnc-api to
// avoid clashes and duplication. For instance, we can't depend upon konflux-build-driver as that
// then leads to oidc client issues.
@Builder(builderClassName = "Builder")
@JsonIgnoreProperties(ignoreUnknown = true)
public record PipelineNotification(
String status,
String buildId,
Request completionCallback) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.redhat.hacbs.container.notification;

import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.logging.LogRecord;

import javax.ws.rs.core.MediaType;

import org.jboss.pnc.api.constants.HttpHeaders;
import org.jboss.pnc.api.dto.Request;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.WireMockServer;

import io.quarkus.test.LogCollectingTestResource;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.common.ResourceArg;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
@QuarkusTestResource(value = LogCollectingTestResource.class, restrictToAnnotatedClass = true, initArgs = @ResourceArg(name = LogCollectingTestResource.LEVEL, value = "FINE"))
@QuarkusTestResource(WireMockExtensions.class)
public class NotificationTest {

private WireMockServer wireMockServer;

@BeforeEach
public void clearLogs() {
LogCollectingTestResource.current().clear();
}

@Test
public void testNoNotify() {
NotifyCommand notifyCommand = new NotifyCommand();
notifyCommand.status = "Succeeded";
notifyCommand.buildId = "1234";
notifyCommand.run();
List<LogRecord> logRecords = LogCollectingTestResource.current().getRecords();
assertTrue(logRecords.stream()
.anyMatch(r -> LogCollectingTestResource.format(r).contains("No callback configured ; unable to notify")));
}

@Test
public void testNotify() throws IOException, URISyntaxException {

Request request = Request.builder()
.method(Request.Method.PUT)
.header(new Request.Header(HttpHeaders.CONTENT_TYPE_STRING, MediaType.APPLICATION_JSON))
.attachment(null)
.uri(new URI(wireMockServer.baseUrl() + "/internal/completed"))
.build();

System.err.println("### wiremock uri: " + wireMockServer.baseUrl());
// {"method":"PUT","uri":"http://localhost:8081/internal/completed","headers":[{"name":"Content-Type","value":"application/json"}],"attachment":null}

NotifyCommand notifyCommand = new NotifyCommand();
notifyCommand.status = "Succeeded";
notifyCommand.buildId = "1234";
notifyCommand.objectMapper = new ObjectMapper();
notifyCommand.context = notifyCommand.objectMapper.writeValueAsString(request);
notifyCommand.run();

List<LogRecord> logRecords = LogCollectingTestResource.current().getRecords();
assertTrue(logRecords.stream()
.anyMatch(r -> LogCollectingTestResource.format(r).contains("Response (PUT http://localhost:8080/internal/completed) 200")));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.redhat.hacbs.container.notification;

import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
import static com.github.tomakehurst.wiremock.client.WireMock.put;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;

import java.util.Map;

import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.common.ConsoleNotifier;

import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

public class WireMockExtensions implements QuarkusTestResourceLifecycleManager {
private WireMockServer wireMockServer;

@Override
public Map<String, String> start() {
wireMockServer = new WireMockServer(wireMockConfig().notifier(new ConsoleNotifier(true)));
wireMockServer.start();

wireMockServer.stubFor(
put(urlEqualTo("/internal/completed"))
.withRequestBody(
equalToJson("{\"status\":\"Succeeded\",\"buildId\":\"1234\",\"completionCallback\":null}"))
.willReturn(aResponse()
.withStatus(200)));

return Map.of("quarkus.rest-client.wiremockextensions.url", wireMockServer.baseUrl());
}

@Override
public void stop() {
if (wireMockServer != null) {
wireMockServer.stop();
}
}

@Override
public void inject(TestInjector testInjector) {
testInjector.injectIntoFields(wireMockServer, new TestInjector.MatchesType(WireMockServer.class));
}
}
Loading