CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-quarkus--quarkus-devservices-deployment

Quarkus deployment module that provides automatic configuration and orchestration of development services using Docker Compose

Pending
Overview
Eval results
Files

devservices-processing.mddocs/

DevServices Processing

Core build step processing that orchestrates the DevServices lifecycle, provides shared networking, and configures console commands for development-time service management.

Capabilities

DevServicesProcessor

Main build step processor that integrates DevServices with the Quarkus build pipeline, handles networking setup, and configures development-time tooling.

/**
 * Main DevServices processor providing build steps for service orchestration
 */
public class DevServicesProcessor {
    
    /**
     * Provides shared network ID for DevServices containers
     * @param devServicesLauncherConfig Optional launcher configuration
     * @param composeProjectBuildItem Optional compose project information
     * @return Network ID build item
     */
    @BuildStep
    public DevServicesNetworkIdBuildItem networkId(
        Optional<DevServicesLauncherConfigResultBuildItem> devServicesLauncherConfig,
        Optional<DevServicesComposeProjectBuildItem> composeProjectBuildItem);
    
    /**
     * Main configuration build step that sets up DevServices descriptions and console commands
     * @param dockerStatusBuildItem Docker availability status
     * @param commandBuildItemBuildProducer Producer for console commands
     * @param footerLogProducer Producer for Dev UI log streams
     * @param launchModeBuildItem Current launch mode
     * @param devServicesLauncherConfig Optional launcher configuration
     * @param devServicesResults List of all DevServices results
     * @return List of service descriptions
     */
    @BuildStep(onlyIf = { IsDevelopment.class })
    public List<DevServiceDescriptionBuildItem> config(
        DockerStatusBuildItem dockerStatusBuildItem,
        BuildProducer<ConsoleCommandBuildItem> commandBuildItemBuildProducer,
        BuildProducer<FooterLogBuildItem> footerLogProducer,
        LaunchModeBuildItem launchModeBuildItem,
        Optional<DevServicesLauncherConfigResultBuildItem> devServicesLauncherConfig,
        List<DevServicesResultBuildItem> devServicesResults);
    
    /**
     * Formats service information for console display
     * @param builder StringBuilder to append formatted information
     * @param devService Service description to format
     * @param withStatus Whether to include status information
     */
    public static void printDevService(
        StringBuilder builder, 
        DevServiceDescriptionBuildItem devService, 
        boolean withStatus);
}

Usage Examples:

// Custom build step that uses DevServices network
@BuildStep
public void configureCustomService(
    DevServicesNetworkIdBuildItem networkId,
    BuildProducer<DevServicesResultBuildItem> devServicesProducer) {
    
    if (networkId.getNetworkId() != null) {
        // Use shared network for custom service
        String customServiceId = startCustomService(networkId.getNetworkId());
        devServicesProducer.produce(new DevServicesResultBuildItem(
            "Custom Service",
            "Custom development service",
            customServiceId,
            Map.of("custom.service.url", "http://localhost:8080")
        ));
    }
}

// Accessing service descriptions in build steps
@BuildStep
public void processServiceDescriptions(List<DevServiceDescriptionBuildItem> services) {
    for (DevServiceDescriptionBuildItem service : services) {
        if (service.hasContainerInfo()) {
            String containerId = service.getContainerInfo().id();
            Map<String, String> config = service.getConfigs();
            // Process service information
        }
    }
}

ComposeDevServicesProcessor

Specialized processor for Docker Compose DevServices integration that handles compose file discovery, service startup, and lifecycle management.

/**
 * Processor for Docker Compose DevServices integration
 */
@BuildSteps(onlyIfNot = IsNormal.class, onlyIf = DevServicesConfig.Enabled.class)
public class ComposeDevServicesProcessor {
    
    /**
     * Registers the COMPOSE feature
     * @return Feature build item
     */
    @BuildStep
    FeatureBuildItem feature();
    
    /**
     * Sets up file watching for compose files
     * @param composeBuildTimeConfig Compose configuration
     * @param producer Producer for watched file items
     */
    @BuildStep
    public void watchComposeFiles(
        ComposeBuildTimeConfig composeBuildTimeConfig,
        BuildProducer<HotDeploymentWatchedFileBuildItem> producer);
    
    /**
     * Main configuration and lifecycle management for Compose services
     * @param buildExecutor Executor for build operations
     * @param composeBuildTimeConfig Compose configuration
     * @param appInfo Application information
     * @param launchMode Current launch mode
     * @param consoleInstalledBuildItem Optional console installation status
     * @param closeBuildItem Shutdown handler
     * @param loggingSetupBuildItem Logging configuration
     * @param devServicesConfig DevServices configuration
     * @param dockerStatusBuildItem Docker status
     * @return Compose project build item
     * @throws IOException If file operations fail
     */
    @BuildStep
    public DevServicesComposeProjectBuildItem config(
        Executor buildExecutor,
        ComposeBuildTimeConfig composeBuildTimeConfig,
        ApplicationInfoBuildItem appInfo,
        LaunchModeBuildItem launchMode,
        Optional<ConsoleInstalledBuildItem> consoleInstalledBuildItem,
        CuratedApplicationShutdownBuildItem closeBuildItem,
        LoggingSetupBuildItem loggingSetupBuildItem,
        DevServicesConfig devServicesConfig,
        DockerStatusBuildItem dockerStatusBuildItem) throws IOException;
    
    /**
     * Converts compose project to DevServices result
     * @param composeBuildItem Compose project information
     * @return DevServices result or null if no project
     */
    @BuildStep
    public DevServicesResultBuildItem toDevServicesResult(
        DevServicesComposeProjectBuildItem composeBuildItem);
    
    /**
     * Checks if a file is a compose file based on naming pattern
     * @param p Path to check
     * @return true if file matches compose naming pattern
     */
    static boolean isComposeFile(Path p);
    
    /**
     * Gets the project root directory
     * @return Path to project root
     */
    static Path getProjectRoot();
    
    /**
     * Converts list of file paths to File objects
     * @param l List of file path strings
     * @return List of File objects
     */
    static List<File> filesFromConfigList(List<String> l);
    
    /**
     * Automatically discovers compose files in project root
     * @return List of discovered compose files
     * @throws RuntimeException If directory reading fails
     */
    static List<File> collectComposeFilesFromProjectRoot() throws RuntimeException;
}

Usage Examples:

// Custom processor that integrates with compose services
@BuildStep
public void integrateWithCompose(
    DevServicesComposeProjectBuildItem composeProject,
    BuildProducer<MyCustomBuildItem> producer) {
    
    if (composeProject.getProject() != null) {
        Map<String, List<RunningContainer>> services = composeProject.getComposeServices();
        String networkId = composeProject.getDefaultNetworkId();
        
        // Integrate with running compose services
        for (Map.Entry<String, List<RunningContainer>> entry : services.entrySet()) {
            String serviceName = entry.getKey();
            List<RunningContainer> containers = entry.getValue();
            
            producer.produce(new MyCustomBuildItem(serviceName, containers, networkId));
        }
    }
}

// Checking if files are compose files
List<Path> potentialComposeFiles = List.of(
    Paths.get("docker-compose.yml"),
    Paths.get("compose-dev-services.yml"),
    Paths.get("regular-file.txt")
);

List<Path> composeFiles = potentialComposeFiles.stream()
    .filter(ComposeDevServicesProcessor::isComposeFile)
    .collect(Collectors.toList());
// Result: [docker-compose.yml, compose-dev-services.yml]

Configuration Constants

// Compose file pattern matching
static final Pattern COMPOSE_FILE = Pattern.compile("(^docker-compose|^compose)(-dev(-)?service).*.(yml|yaml)");

// Project naming prefix
static final String PROJECT_PREFIX = "quarkus-devservices";

Configuration Options

DevServices can be configured through application properties:

# Global DevServices configuration
quarkus.devservices.enabled=true
quarkus.devservices.timeout=PT2M

# Compose-specific configuration
quarkus.compose.enabled=true
quarkus.compose.files=docker-compose.yml,docker-compose.override.yml
quarkus.compose.profiles=development,testing
quarkus.compose.project-name=my-devservices
quarkus.compose.start-services=true
quarkus.compose.stop-services=true
quarkus.compose.follow-logs=false
quarkus.compose.env.POSTGRES_PASSWORD=secret
quarkus.compose.env.REDIS_PASSWORD=redis-secret

# Service-specific wait configuration via labels
quarkus.compose.wait-for.logs=Server started
quarkus.compose.wait-for.ports.timeout=PT30S
quarkus.compose.wait-for.healthcheck=true

# Port configuration mapping
quarkus.compose.config.port.5432=DATABASE_URL
quarkus.compose.config.port.6379=REDIS_URL

The configuration is managed through build-time configuration classes that process these properties during the build phase.

Install with Tessl CLI

npx tessl i tessl/maven-io-quarkus--quarkus-devservices-deployment

docs

compose-files.md

compose-project.md

console-commands.md

devservices-processing.md

index.md

tile.json