java springboot

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”, “”); }}