import org.springframework.core.io.buffer.DataBuffer;import org.springframework.core.io.buffer.DataBufferUtils;import org.springframework.stereotype.Service;import org.springframework.web.reactive.function.client.WebClient;import org.springframework.web.reactive.function.client.WebClientResponseException;import reactor.core.publisher.Mono;import java.io.File;import java.io.FileOutputStream;import java.nio.channels.FileChannel;import java.nio.file.Path;@Servicepublic class GitDownloadService { private final WebClient webClient; public GitDownloadService() { this.webClient = WebClient.builder() .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024)) // 16 MB buffer .build(); } public Mono<File> downloadZip(String repoUrl, File downloadDir, String token) { return webClient.get() .uri(repoUrl) .header(“Authorization”, “token ” + token) // Use “Bearer” for OAuth tokens if needed .header(“Accept”, “application/vnd.github.v3+json”) .header(“User-Agent”, “Java-WebClient”) .retrieve() .bodyToFlux(DataBuffer.class) // Stream the file content as DataBuffer .reduce(DataBufferUtils.join()) // Combine the buffers into a single DataBuffer .flatMap(dataBuffer -> saveToFile(dataBuffer, downloadDir)) .doOnError(WebClientResponseException.class, ex -> { throw new RuntimeException(“Error downloading file: ” + ex.getStatusCode() + ” ” + ex.getResponseBodyAsString()); }) .onErrorMap(ex -> new RuntimeException(“Failed to download ZIP file”, ex)); } private Mono<File> saveToFile(DataBuffer dataBuffer, File downloadDir) { try { if (!downloadDir.exists() && !downloadDir.mkdirs()) { throw new RuntimeException(“Failed to create directory: ” + downloadDir.getAbsolutePath()); } File zipFile = new File(downloadDir, “repo.zip”); try (FileChannel channel = new FileOutputStream(zipFile).getChannel()) { channel.write(dataBuffer.asByteBuffer()); } finally { DataBufferUtils.release(dataBuffer); // Release the buffer } return Mono.just(zipFile); } catch (Exception e) { return Mono.error(new RuntimeException(“Error saving ZIP file: ” + e.getMessage(), e)); } }}
download service
import org.springframework.web.reactive.function.client.WebClient;import org.springframework.web.reactive.function.client.ExchangeStrategies;private final WebClient webClient = WebClient.builder() .exchangeStrategies(ExchangeStrategies.builder() .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(16 * 1024 * 1024)) .build()) .build();private File downloadZip(String repoUrl, File downloadDir, String token) throws IOException { byte[] zipBytes = webClient.get() .uri(repoUrl) .header(“Authorization”, “Bearer ” + token) .retrieve() .bodyToMono(byte[].class) .block(); File zipFile = new File(downloadDir, “repo.zip”); try (FileOutputStream out = new FileOutputStream(zipFile)) { out.write(zipBytes); } catch (IOException e) { throw new IOException(“Failed to download the zip file. Error: ” + e.getMessage()); } return zipFile;}
basic auth
import org.springframework.web.reactive.function.client.WebClient;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class BitbucketService {
private final WebClient webClient;
public BitbucketService() {
this.webClient = WebClient.builder().build();
}
public String fetchDataWithBasicAuth(String apiUrl, String username, String password) {
String authHeader = generateBasicAuthHeader(username, password);
return webClient.get()
.uri(apiUrl)
.header("Authorization", authHeader)
.retrieve()
.bodyToMono(String.class)
.block();
}
private String generateBasicAuthHeader(String username, String password) {
String credentials = username + ":" + password;
return "Basic " + Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8));
}
}
webclient config
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import org.apache.hc.client5.http.ssl.SSLContextBuilder;
import org.apache.hc.core5.ssl.SSLContexts;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import reactor.netty.http.client.HttpClient;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.nio.file.Path;
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient() {
try {
// Load the custom JKS keystore
Path jksPath = Path.of("/path/to/cert1.jks");
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(jksPath.toFile(), "your_jks_password".toCharArray())
.build();
// Configure HttpClient with SSLContext
HttpClient httpClient = HttpClient.create()
.secure(t -> t.sslContext(sslContext));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
} catch (Exception e) {
throw new RuntimeException("Error setting up WebClient with custom SSL", e);
}
}
}
=====
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.Files;
@Service
public class DownloadService {
private final WebClient webClient;
@Autowired
public DownloadService(WebClient webClient) {
this.webClient = webClient;
}
public Mono<File> downloadZip(String repoUrl, Path downloadDir) {
Path zipFilePath = downloadDir.resolve("repo.zip");
return webClient
.get()
.uri(repoUrl)
.retrieve()
.bodyToMono(byte[].class)
.map(bytes -> {
try (FileOutputStream out = new FileOutputStream(zipFilePath.toFile())) {
out.write(bytes);
} catch (Exception e) {
throw new RuntimeException("Failed to write zip file", e);
}
return zipFilePath.toFile();
});
}
}
=====
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import org.apache.hc.client5.http.ssl.SSLContextBuilder;
import org.apache.hc.core5.ssl.TrustSelfSignedStrategy;
import java.net.URL;
public class SSLConnectionUtil {
public void connectWithCustomSSL(String repoUrl) {
try {
// Create SSLContext allowing self-signed certificates
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(new TrustSelfSignedStrategy())
.build();
// Open a connection and set the SSL factory
URL url = new URL(repoUrl);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setSSLSocketFactory(sslContext.getSocketFactory());
// Proceed with your connection logic here
connection.connect();
// Handle the connection (read response, handle data, etc.)
// ...
} catch (Exception e) {
throw new RuntimeException("Error connecting with custom SSL", e);
}
}
}
====
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import org.apache.hc.client5.http.ssl.SSLContextBuilder;
import org.apache.hc.core5.ssl.TrustSelfSignedStrategy;
public class SSLConfigUtil {
static {
try {
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(new TrustSelfSignedStrategy()) // Allows self-signed certificates
.build();
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
} catch (Exception e) {
throw new RuntimeException("Failed to initialize SSL context", e);
}
}
}
===== resolve cert errror3
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.ssl.SSLContextBuilder;
import org.apache.hc.core5.ssl.TrustStrategy;
import org.springframework.stereotype.Service;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.KeyStore;
@Service
public class GitDownloadService {
private static final String TRUSTSTORE_PATH = "/path/to/your-keystore.jks";
private static final String TRUSTSTORE_PASSWORD = "your_password";
public void downloadZip(String repoUrl, File downloadDir) {
try {
// Load the JKS file
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (FileInputStream trustStoreStream = new FileInputStream(TRUSTSTORE_PATH)) {
trustStore.load(trustStoreStream, TRUSTSTORE_PASSWORD.toCharArray());
}
// Build SSL context with the loaded trust store
SSLContext sslContext = SSLContextBuilder
.create()
.loadTrustMaterial(trustStore, (TrustStrategy) null) // null -> trust all certificates in trust store
.build();
// Configure HttpClient with custom SSL context
try (CloseableHttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContext)
.build()) {
// Use the custom HttpClient to download the file
URL url = new URL(repoUrl);
try (var inputStream = url.openStream()) {
File zipFile = new File(downloadDir, "repo.zip");
Files.copy(inputStream, zipFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
} catch (Exception e) {
throw new RuntimeException("Error downloading zip file", e);
}
}
}
==== run gradle
package com.example.demo.service;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.io.*;
import java.net.URL;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.Enumeration;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@Service
public class GitDownloadService {
private static final String BASE_DIR = "C:/path/to/selenium";
public Mono<String> downloadAndExtract(String repoUrl, String branch) {
return Mono.fromCallable(() -> {
System.out.println("Attempting to resolve path: " + new File(BASE_DIR).getAbsolutePath());
String branchRepoUrl = String.format("%s/archive/refs/heads/%s.zip", repoUrl, branch);
File baseDir = new File(BASE_DIR);
if (!baseDir.exists() || !baseDir.isDirectory() || !baseDir.canWrite()) {
throw new IOException("Base directory is invalid or not writable: " + BASE_DIR);
}
String uniqueDirName = "extracted_repo_" + Instant.now().getEpochSecond() + "_" + (new Random().nextInt(900) + 100);
File extractDir = new File(baseDir, uniqueDirName);
extractDir.mkdirs();
File zipFilePath = downloadZip(branchRepoUrl, extractDir);
unzip(zipFilePath, extractDir);
zipFilePath.delete();
return runGradleTest(extractDir.getAbsolutePath() + "/folder1/folder2");
});
}
private File downloadZip(String repoUrl, File downloadDir) throws IOException {
URL url = new URL(repoUrl);
File zipFile = new File(downloadDir, "repo.zip");
try (InputStream in = url.openStream(); FileOutputStream out = new FileOutputStream(zipFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
return zipFile;
}
private void unzip(File zipFile, File extractTo) throws IOException {
try (ZipFile zip = new ZipFile(zipFile)) {
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File entryDestination = new File(extractTo, entry.getName());
if (entry.isDirectory()) {
entryDestination.mkdirs();
} else {
entryDestination.getParentFile().mkdirs();
try (InputStream in = zip.getInputStream(entry); OutputStream out = new FileOutputStream(entryDestination)) {
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
}
}
}
}
}
private String runGradleTest(String directoryPath) {
StringBuilder output = new StringBuilder();
try {
// Build the command to run in the specified directory
ProcessBuilder processBuilder = new ProcessBuilder("./gradlew", "clean", "test", "--info");
processBuilder.directory(new File(directoryPath)); // Set working directory to the specific path
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
}
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new RuntimeException("Gradle command execution failed with exit code: " + exitCode);
}
return "Gradle command executed successfully:\n" + output.toString();
} catch (Exception e) {
throw new RuntimeException("Error executing Gradle command", e);
}
}
}
===/
package com.example.demo.controller;import com.example.demo.service.GitDownloadService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import reactor.core.publisher.Mono;@RestController@RequestMapping(“/api/git”)public class GitDownloadController { private final GitDownloadService gitDownloadService; @Autowired public GitDownloadController(GitDownloadService gitDownloadService) { this.gitDownloadService = gitDownloadService; } @PostMapping(“/download”) public Mono<ResponseEntity<String>> downloadGitRepo( @RequestParam String repoUrl, @RequestParam String branch ) { return gitDownloadService.downloadAndExtract(repoUrl, branch) .map(extractedPath -> ResponseEntity.ok(“Repository extracted to: ” + extractedPath)) .onErrorResume(e -> Mono.just(ResponseEntity.status(500).body(“Error: ” + e.getMessage()))); }}
====== service
package com.example.demo.service;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import java.io.; import java.net.URL; import java.nio.file.;
import java.time.Instant;
import java.util.Enumeration;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@Service
public class GitDownloadService {
private static final String BASE_DIR = "/root/extracted-repos/";
public Mono<String> downloadAndExtract(String repoUrl, String branch) {
return Mono.fromCallable(() -> {
String branchRepoUrl = String.format("%s/archive/refs/heads/%s.zip", repoUrl, branch);
// Create unique directory name based on timestamp and random number
String uniqueDirName = "extracted_repo_" + Instant.now().getEpochSecond() + "_" + (new Random().nextInt(900) + 100);
Path extractDir = Paths.get(BASE_DIR, uniqueDirName);
// Ensure the directory exists
Files.createDirectories(extractDir);
// Download and save zip file
Path zipFilePath = downloadZip(branchRepoUrl, extractDir);
// Extract the downloaded zip file
unzip(zipFilePath.toFile(), extractDir.toFile());
return extractDir.toString();
});
}
private Path downloadZip(String repoUrl, Path downloadDir) throws IOException {
URL url = new URL(repoUrl);
Path zipFilePath = downloadDir.resolve("repo.zip");
try (InputStream in = url.openStream()) {
Files.copy(in, zipFilePath, StandardCopyOption.REPLACE_EXISTING);
}
return zipFilePath;
}
private void unzip(File zipFile, File extractTo) throws IOException {
try (ZipFile zip = new ZipFile(zipFile)) {
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File entryDestination = new File(extractTo, entry.getName());
if (entry.isDirectory()) {
entryDestination.mkdirs();
} else {
entryDestination.getParentFile().mkdirs();
try (InputStream in = zip.getInputStream(entry);
OutputStream out = new FileOutputStream(entryDestination)) {
in.transferTo(out);
}
}
}
} finally {
Files.deleteIfExists(zipFile.toPath()); // Optional: Clean up the zip file after extraction
}
}
}
==========
download and zip code
package com.example.demo.service;
import org.springframework.stereotype.Service;
import java.io.; import java.net.URL; import java.nio.file.;
import java.time.Instant;
import java.util.Enumeration;
import java.util.Random;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@Service
public class GitDownloadService {
private static final String BASE_DIR = "/root/extracted-repos/";
public String downloadAndExtract(String repoUrl, String branch) throws IOException {
String branchRepoUrl = String.format("%s/archive/refs/heads/%s.zip", repoUrl, branch);
// Create unique directory name based on timestamp and random number
String uniqueDirName = "extracted_repo_" + Instant.now().getEpochSecond() + "_" + (new Random().nextInt(900) + 100);
Path extractDir = Paths.get(BASE_DIR, uniqueDirName);
// Ensure the directory exists
Files.createDirectories(extractDir);
// Download and save zip file
Path zipFilePath = downloadZip(branchRepoUrl, extractDir);
// Extract the downloaded zip file
unzip(zipFilePath.toFile(), extractDir.toFile());
return extractDir.toString();
}
private Path downloadZip(String repoUrl, Path downloadDir) throws IOException {
URL url = new URL(repoUrl);
Path zipFilePath = downloadDir.resolve("repo.zip");
try (InputStream in = url.openStream()) {
Files.copy(in, zipFilePath, StandardCopyOption.REPLACE_EXISTING);
}
return zipFilePath;
}
private void unzip(File zipFile, File extractTo) throws IOException {
try (ZipFile zip = new ZipFile(zipFile)) {
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File entryDestination = new File(extractTo, entry.getName());
if (entry.isDirectory()) {
entryDestination.mkdirs();
} else {
entryDestination.getParentFile().mkdirs();
try (InputStream in = zip.getInputStream(entry);
OutputStream out = new FileOutputStream(entryDestination)) {
in.transferTo(out);
}
}
}
} finally {
Files.deleteIfExists(zipFile.toPath()); // Optional: Clean up the zip file after extraction
}
}
}
============ Utils
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
@Component
public class ShellCommandUtil {
private static final String SCRIPT_DIRECTORY = "/root/opt/selenium/";
public void createShellFile(String gitRepo, String branch, String frameworkType) {
try {
File scriptDirectory = new File(SCRIPT_DIRECTORY);
if (!scriptDirectory.exists()) {
throw new RuntimeException("Directory does not exist: " + SCRIPT_DIRECTORY);
}
File file = new File(scriptDirectory, "script.sh");
try (var writer = new FileWriter(file)) {
writer.write("echo " + gitRepo + "\n");
writer.write("echo " + branch + "\n");
writer.write("echo " + frameworkType + "\n");
}
file.setExecutable(true);
} catch (Exception e) {
throw new RuntimeException("Error creating shell file", e);
}
}
public String runShellScript() {
StringBuilder output = new StringBuilder();
try {
ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "script.sh");
processBuilder.directory(new File(SCRIPT_DIRECTORY));
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
}
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new RuntimeException("Script execution failed with exit code: " + exitCode);
}
return "Script executed successfully:\n" + output.toString();
} catch (Exception e) {
throw new RuntimeException("Error executing shell script", e);
}
}
public String runShellCommandDirectly(String gitRepo, String branch, String frameworkType) {
StringBuilder output = new StringBuilder();
try {
String command = String.format("git clone -b %s %s && cd %s && ./gradlew clean test", branch, gitRepo, frameworkType);
ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "-c", command);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
}
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new RuntimeException("Shell command execution failed with exit code: " + exitCode);
}
return "Shell command executed successfully:\n" + output.toString();
} catch (Exception e) {
throw new RuntimeException("Error executing shell command", e);
}
}
}
===== WebClientConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.tcp.TcpClient;
import java.time.Duration;
@Configuration
public class WebClientConfig {
private static final int TIMEOUT_MILLIS = 5000;
@Bean
public WebClient webClientWithTimeout() {
TcpClient tcpClient = TcpClient.create()
.responseTimeout(Duration.ofMillis(TIMEOUT_MILLIS))
.doOnConnected(conn -> conn
.addHandlerLast(new ReadTimeoutHandler(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS))
.addHandlerLast(new WriteTimeoutHandler(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)));
HttpClient httpClient = HttpClient.from(tcpClient);
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
}
========= git service
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.reactive.function.client.WebClient;import reactor.core.publisher.Mono;@Servicepublic class GitService { private final ShellCommandUtil shellCommandUtil; private final WebClient webClient; @Autowired public GitService(ShellCommandUtil shellCommandUtil, WebClient webClient) { this.shellCommandUtil = shellCommandUtil; this.webClient = webClient; } public Mono<String> createAndRunShellFileReactive(String gitRepo, String branch, String frameworkType) { return Mono.fromCallable(() -> { shellCommandUtil.createShellFile(gitRepo, branch, frameworkType); return shellCommandUtil.runShellScript(); }); } public Mono<String> runShellCommandDirectlyReactive(String gitRepo, String branch, String frameworkType) { return Mono.fromCallable(() -> shellCommandUtil.runShellCommandDirectly(gitRepo, branch, frameworkType)); } // Example for potential external HTTP request using WebClient public Mono<String> externalServiceCall() { return webClient.get() .uri(“http://some-external-service”) .retrieve() .bodyToMono(String.class) .timeout(Duration.ofSeconds(3)); }}
===== git controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping(“/api/get”)
public class GitController {
private final GitService gitService;
@Autowired
public GitController(GitService gitService) {
this.gitService = gitService;
}
// Endpoint to create and run shell script (reactive)
@PostMapping("/execute-workflow/reactive")
public Mono<ResponseEntity<String>> executeWorkflowReactive(@RequestBody GitRequest gitRequest) {
return gitService.createAndRunShellFileReactive(gitRequest.getGitRepo(), gitRequest.getBranch(), gitRequest.getFrameworkType())
.map(ResponseEntity::ok);
}
// Endpoint to run shell command directly (reactive)
@PostMapping("/execute-command/reactive")
public Mono<ResponseEntity<String>> executeCommandReactive(@RequestBody GitRequest gitRequest) {
return gitService.runShellCommandDirectlyReactive(gitRequest.getGitRepo(), gitRequest.getBranch(), gitRequest.getFrameworkType())
.map(ResponseEntity::ok);
}
}
========util config
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;@Configurationpublic class ShellCommandConfig { @Bean @Primary public ShellCommandUtil primaryShellCommandUtil() { return new ShellCommandUtil(); // Default/primary bean for shell commands } @Bean public ShellCommandUtil secondaryShellCommandUtil() { return new ShellCommandUtil(); // Another bean if needed with @Qualifier }}
==================
package com.example.demo.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
@Service
public class GitService {
private static final Logger logger = LoggerFactory.getLogger(GitService.class);
/**
* Executes the workflow by invoking the shell script for Git clone/pull and Gradle tests.
*
* @param gitUrl The Git repository URL.
* @param branch The Git branch.
* @param targetDir The target directory to clone/pull the repository.
* @return The output of the shell script execution.
*/
public String executeWorkflow(String gitUrl, String branch, String targetDir) {
try {
// Path to the shell script
String scriptPath = "./git-workflow.sh";
// Build the command to run the shell script
List<String> command = new ArrayList<>();
command.add("bash"); // Specify to use bash shell
command.add(scriptPath); // Path to the shell script
command.add(gitUrl); // Git URL
command.add(branch); // Git branch
command.add(targetDir); // Target directory
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(".")); // Set working directory (current directory)
processBuilder.redirectErrorStream(true); // Merge error and output streams
// Start the process
Process process = processBuilder.start();
// Capture the output
StringBuilder output = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
logger.info(line);
}
}
// Wait for the process to complete
int exitCode = process.waitFor();
logger.info("Shell script exited with code: " + exitCode);
if (exitCode == 0) {
return "Workflow completed successfully.\n" + output.toString();
} else {
throw new RuntimeException("Shell script failed with exit code: " + exitCode);
}
} catch (Exception e) {
throw new RuntimeException("Failed to execute workflow: " + e.getMessage(), e);
}
}
}
webclient config
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.client.reactive.ReactorClientHttpConnector;import org.springframework.web.reactive.function.client.WebClient;import reactor.netty.http.client.HttpClient;import reactor.netty.tcp.TcpClient;import java.time.Duration;@Configurationpublic class WebClientConfig { private static final int TIMEOUT_MILLIS = 5000; @Bean public WebClient webClientWithTimeout() { TcpClient tcpClient = TcpClient.create() .responseTimeout(Duration.ofMillis(TIMEOUT_MILLIS)) .doOnConnected(conn -> conn .addHandlerLast(new ReadTimeoutHandler(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)) .addHandlerLast(new WriteTimeoutHandler(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS))); HttpClient httpClient = HttpClient.from(tcpClient); return WebClient.builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) .build(); }}
gitservice
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.web.reactive.function.client.WebClient;import reactor.core.publisher.Mono;@Servicepublic class GitService { private final ShellCommandUtil shellCommandUtil; private final WebClient webClient; @Autowired public GitService(ShellCommandUtil shellCommandUtil, WebClient webClient) { this.shellCommandUtil = shellCommandUtil; this.webClient = webClient; } public Mono<String> createAndRunShellFileReactive(String gitRepo, String branch, String frameworkType) { return Mono.fromCallable(() -> { shellCommandUtil.createShellFile(gitRepo, branch, frameworkType); return shellCommandUtil.runShellScript(); }); } public Mono<String> runShellCommandDirectlyReactive(String gitRepo, String branch, String frameworkType) { return Mono.fromCallable(() -> shellCommandUtil.runShellCommandDirectly(gitRepo, branch, frameworkType)); } // Example for potential external HTTP request using WebClient public Mono<String> externalServiceCall() { return webClient.get() .uri(“http://some-external-service”) .retrieve() .bodyToMono(String.class) .timeout(Duration.ofSeconds(3)); }}
gitcontroller
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import reactor.core.publisher.Mono;@RestController@RequestMapping(“/api/get”)public class GitController { private final GitService gitService; @Autowired public GitController(GitService gitService) { this.gitService = gitService; } // Endpoint to create and run shell script (reactive) @PostMapping(“/execute-workflow/reactive”) public Mono<ResponseEntity<String>> executeWorkflowReactive(@RequestBody GitRequest gitRequest) { return gitService.createAndRunShellFileReactive(gitRequest.getGitRepo(), gitRequest.getBranch(), gitRequest.getFrameworkType()) .map(ResponseEntity::ok); } // Endpoint to run shell command directly (reactive) @PostMapping(“/execute-command/reactive”) public Mono<ResponseEntity<String>> executeCommandReactive(@RequestBody GitRequest gitRequest) { return gitService.runShellCommandDirectlyReactive(gitRequest.getGitRepo(), gitRequest.getBranch(), gitRequest.getFrameworkType()) .map(ResponseEntity::ok); }}
util config
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;@Configurationpublic class ShellCommandConfig { @Bean @Primary public ShellCommandUtil primaryShellCommandUtil() { return new ShellCommandUtil(); // Default/primary bean for shell commands } @Bean public ShellCommandUtil secondaryShellCommandUtil() { return new ShellCommandUtil(); // Another bean if needed with @Qualifier }}
!/bin/bash
Input arguments
GIT_URL=$1
BRANCH=$2
TARGET_DIR=$3
Clone or pull the repository
if [ -d “$TARGET_DIR” ]; then
echo “Directory $TARGET_DIR already exists. Pulling latest changes from $BRANCH branch…”
cd “$TARGET_DIR”
git pull origin “$BRANCH”
else
echo “Cloning $GIT_URL into $TARGET_DIR…”
git clone -b “$BRANCH” “$GIT_URL” “$TARGET_DIR”
cd “$TARGET_DIR”
fi
Run Gradle tests
echo “Running ./gradlew clean test –info…”
./gradlew clean test –info
import java.io.BufferedReader;import java.io.File;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;public class GitService { /** * Executes the shell script using Git Bash on Windows. * * @param scriptPath The full path to the shell script. * @return The output of the shell script execution. */ public String executeShellScript(String scriptPath) { try { // Specify the path to Git Bash or another Bash shell installed on Windows String bashPath = “C:\\Program Files\\Git\\bin\\bash.exe”; // Path to Git Bash // Build the command to execute the shell script List<String> command = new ArrayList<>(); command.add(bashPath); // Git Bash executable command.add(scriptPath); // Full path to the shell script ProcessBuilder processBuilder = new ProcessBuilder(command); processBuilder.directory(new File(“.”)); // Set working directory (current directory) processBuilder.redirectErrorStream(true); // Merge error and output streams // Start the process Process process = processBuilder.start(); // Capture the output StringBuilder output = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { output.append(line).append(“\n”); System.out.println(line); // Print the output to console } } // Wait for the process to complete int exitCode = process.waitFor(); System.out.println(“Shell script exited with code: ” + exitCode); if (exitCode == 0) { return “Script executed successfully.\n” + output.toString(); } else { throw new RuntimeException(“Shell script failed with exit code: ” + exitCode); } } catch (Exception e) { throw new RuntimeException(“Failed to execute shell script: ” + e.getMessage(), e); } } public static void main(String[] args) { GitService gitService = new GitService(); // Full path to the shell script String scriptPath = “C:\\path\\to\\your\\script\\abc.sh”; // Execute the shell script and print the output String result = gitService.executeShellScript(scriptPath); System.out.println(result); }}
asycn below
package com.example.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.scheduling.annotation.EnableAsync;@SpringBootApplication@EnableAsync // Enable async processingpublic class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}
package com.example.demo.service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Service
public class GitService {
@Async // Make this method asynchronous
public CompletableFuture<String> executeWorkflow(String repo, String branch, String frameworkType) {
try {
// Define the command for Git clone with the provided repo and branch
List<String> command = new ArrayList<>();
command.add("C:\\Program Files\\Git\\bin\\bash.exe"); // Path to Git Bash
command.add("-c");
command.add("git clone -b " + branch + " " + repo);
// Start the Git clone process
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(".")); // Set working directory (current directory)
processBuilder.redirectErrorStream(true); // Merge error and output streams
Process process = processBuilder.start();
StringBuilder output = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
}
// Wait for the process to complete
int exitCode = process.waitFor();
if (exitCode != 0) {
throw new RuntimeException("Git clone failed with exit code: " + exitCode);
}
// Execute the framework-specific command (e.g., Gradle build)
if ("gradle".equalsIgnoreCase(frameworkType)) {
return CompletableFuture.completedFuture(executeFrameworkCommand("./gradlew clean test --info", output));
} else {
// Other framework commands can be added here as needed
return CompletableFuture.completedFuture("Unsupported framework type: " + frameworkType);
}
} catch (Exception e) {
throw new RuntimeException("Failed to execute workflow: " + e.getMessage(), e);
}
}
private String executeFrameworkCommand(String command, StringBuilder output) throws Exception {
// Execute the framework-specific command (e.g., Gradle clean test)
ProcessBuilder frameworkBuilder = new ProcessBuilder("C:\\Program Files\\Git\\bin\\bash.exe", "-c", command);
frameworkBuilder.directory(new File("your_project_subdirectory")); // Change directory to the cloned repo
frameworkBuilder.redirectErrorStream(true);
Process frameworkProcess = frameworkBuilder.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(frameworkProcess.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
output.append(line).append("\n");
}
}
int exitCode = frameworkProcess.waitFor();
if (exitCode == 0) {
return "Workflow executed successfully.\n" + output.toString();
} else {
throw new RuntimeException("Framework command failed with exit code: " + exitCode);
}
}
}
package com.example.demo.controller;import com.example.demo.model.WorkflowRequest;import com.example.demo.service.GitService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import java.util.concurrent.CompletableFuture;@RestController@RequestMapping(“/api”)public class WorkflowController { @Autowired private GitService gitService; @PostMapping(“/execute-workflow”) public CompletableFuture<ResponseEntity<String>> executeWorkflow(@RequestBody WorkflowRequest request) { return gitService.executeWorkflow(request.getRepo(), request.getBranch(), request.getFrameworkType()) .thenApply(output -> ResponseEntity.ok(output)) .exceptionally(ex -> ResponseEntity.status(500).body(“Error: ” + ex.getMessage())); }}
curl -X POST http://localhost:8080/api/execute-workflow \ -H “Content-Type: application/json” \ -d ‘{ “repo”: “https://github.com/crewAIInc/crewAI-examples.git”, “branch”: “master”, “frameworkType”: “gradle” }’
Gitservice for Linux machine
package com.example.demo.service;import org.springframework.stereotype.Service;import reactor.core.publisher.Mono;import java.io.BufferedReader;import java.io.File;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;@Servicepublic class GitService { public Mono<String> executeWorkflow(String repo, String branch, String frameworkType) { return Mono.fromCallable(() -> { String tarballUrl = repo + “/archive/” + branch + “.tar.gz”; String repoDirName = extractRepoNameFromUrl(repo) + “-” + branch; // The extracted directory usually has the format {repoName}-{branch} // Step 1: Download the repository tarball using wget List<String> wgetCommand = new ArrayList<>(); wgetCommand.add(“bash”); wgetCommand.add(“-c”); wgetCommand.add(“wget ” + tarballUrl); ProcessBuilder wgetProcessBuilder = new ProcessBuilder(wgetCommand); wgetProcessBuilder.directory(new File(“.”)); // Set working directory (current directory) wgetProcessBuilder.redirectErrorStream(true); Process wgetProcess = wgetProcessBuilder.start(); StringBuilder output = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(wgetProcess.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { output.append(line).append(“\n”); } } int wgetExitCode = wgetProcess.waitFor(); if (wgetExitCode != 0) { throw new RuntimeException(“wget failed with exit code: ” + wgetExitCode); } // Step 2: Extract the downloaded tarball List<String> tarCommand = new ArrayList<>(); tarCommand.add(“bash”); tarCommand.add(“-c”); tarCommand.add(“tar -xvf ” + branch + “.tar.gz”); ProcessBuilder tarProcessBuilder = new ProcessBuilder(tarCommand); tarProcessBuilder.directory(new File(“.”)); // Set working directory (current directory) tarProcessBuilder.redirectErrorStream(true); Process tarProcess = tarProcessBuilder.start(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(tarProcess.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { output.append(line).append(“\n”); } } int tarExitCode = tarProcess.waitFor(); if (tarExitCode != 0) { throw new RuntimeException(“Tar extraction failed with exit code: ” + tarExitCode); } // Step 3: Execute framework-specific command (e.g., Gradle build) if (“gradle”.equalsIgnoreCase(frameworkType)) { return executeFrameworkCommand(“./gradlew clean test –info”, output, repoDirName); } else { return “Unsupported framework type: ” + frameworkType; } }); } private String executeFrameworkCommand(String command, StringBuilder output, String repoDirName) throws Exception { // Execute the framework-specific command (e.g., Gradle clean test) ProcessBuilder frameworkBuilder = new ProcessBuilder(“bash”, “-c”, command); frameworkBuilder.directory(new File(repoDirName)); // Change directory to the extracted repo frameworkBuilder.redirectErrorStream(true); Process frameworkProcess = frameworkBuilder.start(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(frameworkProcess.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { output.append(line).append(“\n”); } } int exitCode = frameworkProcess.waitFor(); if (exitCode == 0) { return “Workflow executed successfully.\n” + output.toString(); } else { throw new RuntimeException(“Framework command failed with exit code: ” + exitCode); } } private String extractRepoNameFromUrl(String repoUrl) { // Extract the repository name from the URL return repoUrl.substring(repoUrl.lastIndexOf(“/”) + 1).replace(“.git”, “”); }}