Files
Andrei Kvapil a887125ee5 build(apps): keep the version default out of the tag refresh
Both generators wrote the newest line as the default, so a run made to
pick up a patch tag also moved every release that never set a version
onto another major line. The default now stays where it is while it is
still supported, and a line that leaves the supported set is reported
instead of quietly leaving the enum.

FoundationDB takes the patch from the operator chart rather than from
the newest tag in the registry: the operator only carries the client
library of that build, and the generator now reproduces the committed
map exactly.

Assisted-by: LLM
Signed-off-by: Andrei Kvapil <kvapss@gmail.com>
2026-10-23 19:14:15 +05:00

187 lines
6.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FOUNDATIONDB_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
VALUES_FILE="${FOUNDATIONDB_DIR}/values.yaml"
VERSIONS_FILE="${FOUNDATIONDB_DIR}/files/versions.yaml"
OPERATOR_VALUES_FILE="${FOUNDATIONDB_DIR}/../../system/foundationdb-operator/charts/fdb-operator/values.yaml"
# Check if skopeo is installed
if ! command -v skopeo &> /dev/null; then
echo "Error: skopeo is not installed. Please install skopeo and try again." >&2
exit 1
fi
# Check if jq is installed
if ! command -v jq &> /dev/null; then
echo "Error: jq is not installed. Please install jq and try again." >&2
exit 1
fi
# Check if yq is installed
if ! command -v yq &> /dev/null; then
echo "Error: yq is not installed. Please install yq and try again." >&2
exit 1
fi
# The operator talks to a cluster through the client library of the cluster's
# major.minor, and it only carries the ones its chart lists as init containers,
# so those are the versions a cluster can run.
echo "Reading supported major.minor versions from $OPERATOR_VALUES_FILE..."
SUPPORTED_VERSIONS=$(yq -r '.initContainers | keys | .[]' "$OPERATOR_VALUES_FILE" | sort -V | xargs)
if [ -z "$SUPPORTED_VERSIONS" ]; then
echo "Error: Could not read supported versions from the operator chart" >&2
exit 1
fi
echo "Supported major.minor versions: $SUPPORTED_VERSIONS"
# imageType split runs foundationdb + foundationdb-kubernetes-sidecar (tagged
# <version>-1), unified runs fdb-kubernetes-monitor, so a version is usable
# only when all three are published.
echo "Fetching available image tags from registry..."
SERVER_TAGS=$(skopeo list-tags docker://docker.io/foundationdb/foundationdb | jq -r '.Tags[]')
SIDECAR_TAGS=$(skopeo list-tags docker://docker.io/foundationdb/foundationdb-kubernetes-sidecar | jq -r '.Tags[]')
MONITOR_TAGS=$(skopeo list-tags docker://docker.io/foundationdb/fdb-kubernetes-monitor | jq -r '.Tags[]')
if [ -z "$SERVER_TAGS" ] || [ -z "$SIDECAR_TAGS" ] || [ -z "$MONITOR_TAGS" ]; then
echo "Error: Could not fetch available image tags" >&2
exit 1
fi
# Build versions map: major.minor version -> the patch the operator carries.
# The patch comes from the operator chart rather than from the newest tag in
# the registry: the operator talks to the cluster through the client library of
# that exact build, and a server ahead of it is a combination nobody ships.
declare -A VERSION_MAP
MAJOR_VERSIONS=()
for major_version in $SUPPORTED_VERSIONS; do
tag=$(yq -r ".initContainers.\"${major_version}\".image.tag" "$OPERATOR_VALUES_FILE")
if [ -z "$tag" ] || [ "$tag" = "null" ]; then
echo "Warning: The operator chart carries no image tag for ${major_version}, skipping..." >&2
continue
fi
if echo "$SERVER_TAGS" | grep -qx "$tag" \
&& echo "$SIDECAR_TAGS" | grep -qx "${tag}-1" \
&& echo "$MONITOR_TAGS" | grep -qx "$tag"; then
VERSION_MAP["v${major_version}"]="${tag}"
MAJOR_VERSIONS+=("v${major_version}")
echo "Found version: v${major_version} -> ${tag}"
else
echo "Warning: No complete set of images published for ${tag}, skipping ${major_version}..." >&2
fi
done
if [ ${#MAJOR_VERSIONS[@]} -eq 0 ]; then
echo "Error: No matching versions found" >&2
exit 1
fi
# Sort major versions in descending order (newest first)
IFS=$'\n' MAJOR_VERSIONS=($(printf '%s\n' "${MAJOR_VERSIONS[@]}" | sort -V -r))
unset IFS
echo "Major versions to add: ${MAJOR_VERSIONS[*]}"
# Keep the default where it is. It decides what every release that never set a
# version runs, so moving it is an upgrade decision of its own rather than
# something a refresh of the tags carries along.
CURRENT_DEFAULT=$(awk '/^version: / { gsub(/"/, "", $2); print $2; exit }' "$VALUES_FILE")
DEFAULT_VERSION="${MAJOR_VERSIONS[0]}"
for major_ver in "${MAJOR_VERSIONS[@]}"; do
if [ "$major_ver" = "$CURRENT_DEFAULT" ]; then
DEFAULT_VERSION="$CURRENT_DEFAULT"
break
fi
done
if [ "$DEFAULT_VERSION" != "$CURRENT_DEFAULT" ]; then
echo "WARNING: the current default ${CURRENT_DEFAULT:-<none>} is no longer available, so the default becomes ${DEFAULT_VERSION}; every release that never set a version moves with it" >&2
fi
# A line that disappears upstream leaves the enum, and the versionMap helper
# then fails the render of every release still on it.
PREVIOUS_VERSIONS=$(awk '
/^## @enum \{string\} Version$/ { in_enum = 1; next }
in_enum && /^## @value / { print $3; next }
in_enum { in_enum = 0 }
' "$VALUES_FILE")
for old_ver in $PREVIOUS_VERSIONS; do
case " ${MAJOR_VERSIONS[*]} " in
*" $old_ver "*) ;;
*) echo "WARNING: $old_ver has left the supported set; a release still on it will fail to render" >&2 ;;
esac
done
# Create/update versions.yaml file
echo "Updating $VERSIONS_FILE..."
{
for major_ver in "${MAJOR_VERSIONS[@]}"; do
echo "\"${major_ver}\": \"${VERSION_MAP[$major_ver]}\""
done
} > "$VERSIONS_FILE"
echo "Successfully updated $VERSIONS_FILE"
# Update values.yaml - enum with major.minor versions only
TEMP_FILE=$(mktemp)
trap "rm -f $TEMP_FILE" EXIT
# Build new version section
NEW_VERSION_SECTION="## @enum {string} Version"
for major_ver in "${MAJOR_VERSIONS[@]}"; do
NEW_VERSION_SECTION="${NEW_VERSION_SECTION}
## @value $major_ver"
done
NEW_VERSION_SECTION="${NEW_VERSION_SECTION}
## @param {Version} version - FoundationDB major.minor version to deploy
version: ${DEFAULT_VERSION}"
# Check if version section already exists
if grep -q "^## @enum {string} Version" "$VALUES_FILE"; then
# Version section exists, update it using awk
echo "Updating existing version section in $VALUES_FILE..."
# Use awk to replace the section from "## @enum {string} Version" to "version: " (inclusive)
# Delete the old section and insert the new one
awk -v new_section="$NEW_VERSION_SECTION" '
/^## @enum {string} Version/ {
in_section = 1
print new_section
next
}
in_section && /^version: / {
in_section = 0
next
}
in_section {
next
}
{ print }
' "$VALUES_FILE" > "$TEMP_FILE.tmp"
mv "$TEMP_FILE.tmp" "$VALUES_FILE"
else
# Version section doesn't exist, insert it before the cluster configuration
echo "Inserting new version section in $VALUES_FILE..."
awk -v new_section="$NEW_VERSION_SECTION" '
/^## @typedef {struct} ClusterProcessCounts/ {
print new_section
print ""
}
{ print }
' "$VALUES_FILE" > "$TEMP_FILE.tmp"
mv "$TEMP_FILE.tmp" "$VALUES_FILE"
fi
echo "Successfully updated $VALUES_FILE (default ${DEFAULT_VERSION}) with major.minor versions: ${MAJOR_VERSIONS[*]}"