From 5304c8ee01d5cdb4339b81315e3406afa009372d Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Thu, 23 Apr 2026 09:42:35 +0200 Subject: [PATCH] core(deploy): DeploymentStrategy enum with safe wire conversion Typed enum (BLUE_GREEN, ROLLING) with fromWire/toWire kebab-case translation. fromWire falls back to BLUE_GREEN for unknown or null input so the executor dispatch site never null-checks and no misconfigured container-config can throw at runtime. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../core/runtime/DeploymentStrategy.java | 31 +++++++++++++++++ .../core/runtime/DeploymentStrategyTest.java | 34 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 cameleer-server-core/src/main/java/com/cameleer/server/core/runtime/DeploymentStrategy.java create mode 100644 cameleer-server-core/src/test/java/com/cameleer/server/core/runtime/DeploymentStrategyTest.java diff --git a/cameleer-server-core/src/main/java/com/cameleer/server/core/runtime/DeploymentStrategy.java b/cameleer-server-core/src/main/java/com/cameleer/server/core/runtime/DeploymentStrategy.java new file mode 100644 index 00000000..8e6ad11d --- /dev/null +++ b/cameleer-server-core/src/main/java/com/cameleer/server/core/runtime/DeploymentStrategy.java @@ -0,0 +1,31 @@ +package com.cameleer.server.core.runtime; + +/** + * Supported deployment strategies. Persisted as a kebab-case string on + * ApplicationConfig / ResolvedContainerConfig; {@link #fromWire(String)} is + * the only conversion entry point and falls back to {@link #BLUE_GREEN} for + * unknown or null input so the executor never has to null-check. + */ +public enum DeploymentStrategy { + BLUE_GREEN("blue-green"), + ROLLING("rolling"); + + private final String wire; + + DeploymentStrategy(String wire) { + this.wire = wire; + } + + public String toWire() { + return wire; + } + + public static DeploymentStrategy fromWire(String value) { + if (value == null) return BLUE_GREEN; + String normalized = value.trim().toLowerCase(); + for (DeploymentStrategy s : values()) { + if (s.wire.equals(normalized)) return s; + } + return BLUE_GREEN; + } +} diff --git a/cameleer-server-core/src/test/java/com/cameleer/server/core/runtime/DeploymentStrategyTest.java b/cameleer-server-core/src/test/java/com/cameleer/server/core/runtime/DeploymentStrategyTest.java new file mode 100644 index 00000000..7cfcfc74 --- /dev/null +++ b/cameleer-server-core/src/test/java/com/cameleer/server/core/runtime/DeploymentStrategyTest.java @@ -0,0 +1,34 @@ +package com.cameleer.server.core.runtime; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class DeploymentStrategyTest { + + @Test + void fromWire_knownValues() { + assertThat(DeploymentStrategy.fromWire("blue-green")).isEqualTo(DeploymentStrategy.BLUE_GREEN); + assertThat(DeploymentStrategy.fromWire("rolling")).isEqualTo(DeploymentStrategy.ROLLING); + } + + @Test + void fromWire_caseInsensitiveAndTrims() { + assertThat(DeploymentStrategy.fromWire("BLUE-GREEN")).isEqualTo(DeploymentStrategy.BLUE_GREEN); + assertThat(DeploymentStrategy.fromWire(" Rolling ")).isEqualTo(DeploymentStrategy.ROLLING); + } + + @Test + void fromWire_unknownOrNullFallsBackToBlueGreen() { + assertThat(DeploymentStrategy.fromWire(null)).isEqualTo(DeploymentStrategy.BLUE_GREEN); + assertThat(DeploymentStrategy.fromWire("")).isEqualTo(DeploymentStrategy.BLUE_GREEN); + assertThat(DeploymentStrategy.fromWire("canary")).isEqualTo(DeploymentStrategy.BLUE_GREEN); + } + + @Test + void toWire_roundTrips() { + for (DeploymentStrategy s : DeploymentStrategy.values()) { + assertThat(DeploymentStrategy.fromWire(s.toWire())).isEqualTo(s); + } + } +}