LocalDeployPreflight.java
package com.cloudforgeci.api.deploy;
import com.cloudforge.core.config.DeploymentConfig;
import com.cloudforge.core.interfaces.ApplicationSpec;
import com.cloudforge.core.local.DeploymentTarget;
import com.cloudforge.core.local.LocalStackCapabilitySnapshot;
import com.cloudforge.core.local.PreflightMessages;
import com.cloudforge.core.local.PreflightMode;
import com.cloudforge.core.local.PreflightResult;
import com.cloudforgeci.localstack.LocalStackCapabilityProbe;
import com.cloudforgeci.localstack.LocalStackDeployPreflight;
import com.cloudforgeci.localstack.LocalStackDeployer;
import com.cloudforgeci.ministack.MiniStackDeployPreflight;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
/**
* Runs target-specific deploy preflight before local emulator pipelines execute.
*/
public final class LocalDeployPreflight {
private LocalDeployPreflight() {
}
public static PreflightOutcome run(DeploymentRequest request) throws IOException {
DeployMode mode = request.mode();
if (mode != DeployMode.DEPLOY && mode != DeployMode.DRY_RUN) {
return PreflightOutcome.skipped();
}
PreflightMode preflightMode = modeFor(request.target());
if (preflightMode == PreflightMode.OFF) {
return PreflightOutcome.skipped();
}
DeploymentConfig config = request.config();
ApplicationSpec spec = config.applicationSpec;
Path canonical = request.canonicalTemplate();
String stackName = config.stackName;
PreflightResult result = switch (request.target()) {
case MINISTACK -> MiniStackDeployPreflight.validate(
config,
spec,
canonical,
java.net.URI.create(com.cloudforgeci.ministack.MiniStackDeployer.resolveEndpoint()),
stackName);
case LOCALSTACK -> {
LocalStackCapabilitySnapshot snapshot =
LocalStackCapabilityProbe.probe(LocalStackDeployer.resolveEndpoint());
yield LocalStackDeployPreflight.validateForDeployment(
config, spec, canonical, snapshot, stackName);
}
case AWS -> PreflightResult.allowed(request.target());
};
return new PreflightOutcome(result, preflightMode, true);
}
public static PreflightMode modeFor(DeploymentTarget target) {
return switch (target) {
case MINISTACK -> PreflightMode.fromEnv("MINISTACK_PREFLIGHT", PreflightMode.ENFORCE);
case LOCALSTACK -> {
if (Boolean.parseBoolean(System.getenv().getOrDefault(
"CFC_LOCALSTACK_SKIP_PREFLIGHT", "false"))) {
yield PreflightMode.OFF;
}
yield PreflightMode.fromEnv("LOCALSTACK_PREFLIGHT", PreflightMode.ENFORCE);
}
case AWS -> PreflightMode.OFF;
};
}
public record PreflightOutcome(PreflightResult result, PreflightMode mode, boolean ran) {
public PreflightOutcome(PreflightResult result, PreflightMode mode) {
this(result, mode, true);
}
public static PreflightOutcome skipped() {
return new PreflightOutcome(null, PreflightMode.OFF, false);
}
public List<String> warningMessages() {
if (result == null) {
return List.of();
}
List<String> messages = new ArrayList<>();
for (var warning : result.warnings()) {
messages.add("[" + warning.ruleId() + "] " + warning.message());
}
return messages;
}
public void throwIfBlocked() throws IOException {
if (!ran || result == null) {
return;
}
result.throwIfBlocked(mode);
}
public String formattedWarnings() {
return result == null ? "" : PreflightMessages.formatWarnings(result);
}
}
}