Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,20 @@ jobs:
with:
fetch-depth: 0

- name: Ensure upgrade YAMLs changed
- name: Ensure old operator version was bumped
run: |
CHANGED=$(git diff --name-only \
CHANGED=$(git diff \
${{ github.event.pull_request.base.sha }} \
${{ github.event.pull_request.head.sha }} \
| grep -E "systemtests/src/test/resources/upgrade/(YamlUpgrade.yaml)" || true)
-- systemtests/src/main/java/com/github/streamshub/systemtests/Environment.java \
| grep -E "^[+-].*OLD_CONSOLE_OPERATOR_VERSION" || true)

if [ -z "$CHANGED" ]; then
echo "❌[ERROR]: YamlUpgrade.yaml was not modified in this PR, exiting the flow."
echo "❌[ERROR]: OLD_CONSOLE_OPERATOR_VERSION in Environment.java was not modified in this PR, exiting the flow."
exit 1
fi

echo "✔️ Upgrade YAML change detected: $CHANGED"
echo "✔️ OLD_CONSOLE_OPERATOR_VERSION change detected: $CHANGED"

- name: Retrieve Project Metadata
uses: smallrye/project-metadata-action@62527b4a896343d4c0c6b2a61eff07f6b59fcbd8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.function.Predicate;

import org.apache.logging.log4j.Logger;

Expand Down Expand Up @@ -41,6 +43,11 @@ public class Environment {
// YAML bundle
public static final String CONSOLE_OPERATOR_BUNDLE_URL = ENVS.getOrDefault("CONSOLE_OPERATOR_BUNDLE_URL", "");

public static final String OLD_CONSOLE_OPERATOR_VERSION = ENVS.getOrDefault("OLD_CONSOLE_OPERATOR_VERSION", "0.13.0");
public static final String OLD_CONSOLE_OPERATOR_CRDS_URL = ENVS.getOrDefault("OLD_CONSOLE_OPERATOR_CRDS_URL",
"https://github.com/streamshub/console/releases/download/" + OLD_CONSOLE_OPERATOR_VERSION + "/streamshub-console-operator.yaml");
public static final String NEW_CONSOLE_OPERATOR_CRDS_URL = ENVS.getOrDefault("NEW_CONSOLE_OPERATOR_CRDS_URL", "");

// OLM
public static final String CONSOLE_OLM_CATALOG_SOURCE_NAME = ENVS.getOrDefault("CONSOLE_OLM_CATALOG_SOURCE_NAME", "streamshub-console-catalog");
public static final String CONSOLE_OLM_PACKAGE_NAME = ENVS.getOrDefault("CONSOLE_OLM_PACKAGE_NAME", "streamshub-console-operator");
Expand Down Expand Up @@ -113,6 +120,19 @@ public static boolean isOlmInstall() {
return CONSOLE_INSTALL_TYPE.equals(InstallType.Olm);
}

/**
* Resolves the Console Operator version under test: {@link #CONSOLE_OPERATOR_VERSION} if set,
* otherwise the {@code operator.version} system property (populated by the Maven build with
* the current {@code project.version} — see systemtests/pom.xml). Empty if neither is set.
* Not lowercased: must match the case used in the Quarkus-generated Kubernetes manifest's
* {@code app.kubernetes.io/version} label.
*/
public static String getConsoleOperatorVersion() {
return Optional.of(CONSOLE_OPERATOR_VERSION)
.filter(Predicate.not(String::isBlank))
.orElseGet(() -> System.getProperty("operator.version", ""));
}

public static boolean isTestClientsPullSecretPresent() {
return !Environment.TEST_CLIENTS_PULL_SECRET.isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
Expand Down Expand Up @@ -121,10 +120,7 @@ public void delete() {
public OlmVersionModificationData getUpgradeData() {
maybeCreateCatalogSource();

String newVersion = Optional.of(Environment.CONSOLE_OPERATOR_VERSION)
.filter(Predicate.not(String::isBlank))
.orElseGet(() -> System.getProperty("operator.version", "")
.toLowerCase(Locale.ROOT));
String newVersion = Environment.getConsoleOperatorVersion();

String[] newVersionElements = newVersion.split("[.-]");
var newChannelSemVer = Version.of(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
package com.github.streamshub.systemtests.upgrade;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.github.streamshub.systemtests.Environment;
import com.github.streamshub.systemtests.exceptions.SetupException;
import com.github.streamshub.systemtests.utils.FileUtils;

public class VersionModificationDataLoader {
public enum InstallType {
YAML
}

private static final Logger LOGGER = LogManager.getLogger(VersionModificationDataLoader.class);
private static final String UPGRADE_FILE_PATH = System.getProperty("user.dir") + "/src/test/resources/upgrade/";
private static final String YAML_UPGRADE_FILE = UPGRADE_FILE_PATH + "YamlUpgrade.yaml";

// Output produced by a normal build in .github/workflows/release.yml, which joins the same two files into release operator YAML bundle.
private static final String OPERATOR_KUBERNETES_DIR = System.getProperty("user.dir") + "/../operator/target/kubernetes/";
private static final Path OPERATOR_CRD_FILE = Paths.get(OPERATOR_KUBERNETES_DIR, "consoles.console.streamshub.github.com-v1.yml");
private static final Path OPERATOR_RESOURCES_FILE = Paths.get(OPERATOR_KUBERNETES_DIR, "kubernetes.yml");

private static final Pattern VERSION_LABEL_PATTERN = Pattern.compile("app\\.kubernetes\\.io/version:\\s*\"?([\\w.-]+)\"?");

private YamlVersionModificationData yamlUpgradeData;

Expand All @@ -28,16 +39,59 @@ public VersionModificationDataLoader(InstallType upgradeType) {
}

private void loadYamlUpgradeData() {
LOGGER.info("Loading Yaml upgrade data from file {}", YAML_UPGRADE_FILE);
String oldOperatorVersion = Environment.OLD_CONSOLE_OPERATOR_VERSION;
String oldOperatorCrdsUrl = Environment.OLD_CONSOLE_OPERATOR_CRDS_URL;
String newOperatorVersion = Environment.getConsoleOperatorVersion();
String newOperatorCrdsUrl = resolveNewOperatorCrdsUrl(newOperatorVersion);

this.yamlUpgradeData = new YamlVersionModificationData(oldOperatorVersion, newOperatorVersion, oldOperatorCrdsUrl, newOperatorCrdsUrl);
LOGGER.info("Loaded Yaml upgrade data: operator version {} -> {}", oldOperatorVersion, newOperatorVersion);
}

static String resolveNewOperatorCrdsUrl(String newOperatorVersion) {
if (Environment.NEW_CONSOLE_OPERATOR_CRDS_URL != null && !Environment.NEW_CONSOLE_OPERATOR_CRDS_URL.isBlank()) {
LOGGER.info("Using NEW_CONSOLE_OPERATOR_CRDS_URL override: {}", Environment.NEW_CONSOLE_OPERATOR_CRDS_URL);
return Environment.NEW_CONSOLE_OPERATOR_CRDS_URL;
}

String mergedPath = mergeLocalOperatorBundle(newOperatorVersion);
LOGGER.info("NEW_CONSOLE_OPERATOR_CRDS_URL not set, using locally merged operator manifest: {}", mergedPath);
return mergedPath;
}

private static String mergeLocalOperatorBundle(String newOperatorVersion) {
if (Files.notExists(OPERATOR_CRD_FILE) || Files.notExists(OPERATOR_RESOURCES_FILE)) {
throw new SetupException(String.format("Local Console Operator build output not found at '%s' and '%s. " +
"Build the operator module first before running tests.", OPERATOR_CRD_FILE, OPERATOR_RESOURCES_FILE));
}

String actualVersion;
Path mergedBundle;
try {
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
this.yamlUpgradeData = mapper.readValue(new File(YAML_UPGRADE_FILE), YamlVersionModificationData.class);
LOGGER.info("Loaded Yaml upgrade data: operator version {} -> {}",
yamlUpgradeData.getOldOperatorVersion(), yamlUpgradeData.getNewOperatorVersion());
actualVersion = extractOperatorVersionLabel(Files.readString(OPERATOR_RESOURCES_FILE));
mergedBundle = FileUtils.mergeYamlFiles(List.of(OPERATOR_CRD_FILE, OPERATOR_RESOURCES_FILE));
} catch (IOException e) {
LOGGER.error("Failed to parse Yaml upgrade data from file {}: {}", YAML_UPGRADE_FILE, e.getMessage());
throw new RuntimeException(e);
throw new SetupException("Failed to read/merge local Console Operator build output", e);
}

if (!newOperatorVersion.equals(actualVersion)) {
throw new SetupException(String.format("Local Console Operator build output at '%s' has version '%s' " +
"but the expected new operator version is '%s'. Rebuild the operator module for the expected version.",
OPERATOR_RESOURCES_FILE, actualVersion, newOperatorVersion));
}

return mergedBundle.toAbsolutePath().toString();
}

/**
* Extracts the value of the first {@code app.kubernetes.io/version} label found in the given YAML
*/
static String extractOperatorVersionLabel(String yamlContent) {
Matcher matcher = VERSION_LABEL_PATTERN.matcher(yamlContent);
if (!matcher.find()) {
throw new SetupException("Could not find an 'app.kubernetes.io/version' label in the locally built Console Operator YAML bundle");
}
return matcher.group(1);
}

public YamlVersionModificationData getYamlUpgradeData() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
package com.github.streamshub.systemtests.upgrade;

public class YamlVersionModificationData {
private String oldOperatorVersion;
private String newOperatorVersion;
private String oldOperatorCrdsUrl;
private String newOperatorCrdsUrl;
private final String oldOperatorVersion;
private final String newOperatorVersion;
private final String oldOperatorCrdsUrl;
private final String newOperatorCrdsUrl;

public YamlVersionModificationData(String oldOperatorVersion, String newOperatorVersion, String oldOperatorCrdsUrl, String newOperatorCrdsUrl) {
this.oldOperatorVersion = oldOperatorVersion;
this.newOperatorVersion = newOperatorVersion;
this.oldOperatorCrdsUrl = oldOperatorCrdsUrl;
this.newOperatorCrdsUrl = newOperatorCrdsUrl;
}

public String getOldOperatorVersion() {
return oldOperatorVersion;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@

public static FileInputStream getYamlFileFromURL(String url) throws IOException {
LOGGER.info("Fetching resources from {}", url);
File yamlFile = Files.createTempFile("tempfile", ".yaml", getDefaultPosixFilePermissions()).toFile();

Check failure on line 88 in systemtests/src/main/java/com/github/streamshub/systemtests/utils/FileUtils.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Define a constant instead of duplicating this literal ".yaml" 3 times.

See more on https://sonarcloud.io/project/issues?id=streamshub_console&issues=AZ-Ux11zRo9R-gan1lJ0&open=AZ-Ux11zRo9R-gan1lJ0&pullRequest=2796
copyURLToFile(
URI.create(url).toURL(),
yamlFile,
Expand Down Expand Up @@ -182,5 +182,29 @@

return new ByteArrayInputStream(combined.toByteArray());
}

/**
* Concatenates the given files' raw contents, in order, into a single new temporary file —
* equivalent to {@code cat file1 file2 > merged}. Unlike {@link #loadYamlsFromPath(Path)}, this
* does not insert `---` separators between files, since the inputs (e.g. generated Kubernetes
* manifests) already contain their own document separators where needed.
*
* @param files ordered list of files to concatenate
* @return path to the merged temporary file
* @throws IOException if a file cannot be read or the temp file cannot be written
*/
public static Path mergeYamlFiles(List<Path> files) throws IOException {
File mergedFile = Files.createTempFile("merged-operator-bundle", ".yaml", getDefaultPosixFilePermissions()).toFile();
mergedFile.deleteOnExit();

try (var out = Files.newOutputStream(mergedFile.toPath())) {
for (Path file : files) {
Files.copy(file, out);
}
}

LOGGER.debug("Merged {} files into temporary file: {}", files.size(), mergedFile.getAbsolutePath());
return mergedFile.toPath();
}
}

Loading
Loading