ci: run the freesailarr install-test for real instead of skipping it

freesailarr was excluded from the install-test because gluetun never becomes
healthy without a real Wireguard key and no app container behind its kill
switch can become Ready. The green "Install-test freesailarr pass" was a
25-second SKIP on the most complex chart in the repo - a signal that proved
nothing.

With a CI-only Mullvad key in 1Password the reason is gone:

- ci/run-install-test.sh learns a general rule: ci/<chart>/fixtures.env.yaml is
  rendered with envsubst before it is applied, restricted to the variable names
  a chart declares in REQUIRED_ENV. A missing or empty declared variable fails
  the run loudly and names the variable - it never skips the chart.
- The install-test job loads the key from 1Password Connect for freesailarr
  only, following the pattern publish-helm-chart.yml documents: values via
  steps.<id>.outputs.*, mapped into the step's own env, quoted, with ":?"
  guards that name the missing op:// field before a cluster is created.
- Fixtures for freesailarr: three media claims, the gluetun secret template
  with variable names only, firewallOutboundSubnets so the kill switch does not
  block cluster DNS, and INSTALL_TIMEOUT=900 for nine containers.

freesailarr/Chart.yaml goes 3.0.0+up1.0.0 -> 3.0.1+up1.0.0. That bump is
deliberately empty of content: the install-test matrix follows changed chart
directories, and without it this PR could not run the test it adds.
This commit is contained in:
jklein committed 2026-08-26 14:30:42 +02:00
1 parent 5280554329
commit 69a280399c
9 files changed
+215 -7

No files matched your search

+45 -1
View File
@@ -9,7 +9,8 @@
# ci/common/ fixtures applied for every chart (OnePasswordItem stub CRD)
# ci/<chart>/test-values.yaml values for the CI install (required)
# ci/<chart>/fixtures.yaml dummy secrets / throwaway infra / static PVs (optional)
# ci/<chart>/settings.env optional overrides, e.g. INSTALL_TIMEOUT=600
# ci/<chart>/fixtures.env.yaml fixtures with ${VARS} filled in from the environment (optional)
# ci/<chart>/settings.env optional overrides, e.g. INSTALL_TIMEOUT=600, REQUIRED_ENV=...
# ci/excluded-charts.txt charts that cannot run in CI, with reasons
set -euo pipefail
@@ -20,8 +21,11 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CI_DIR="$ROOT/ci"
# Per-chart override via ci/<chart>/settings.env (INSTALL_TIMEOUT in seconds).
# REQUIRED_ENV is a space-separated list of environment variables the chart's
# fixtures need; see the check below.
INSTALL_TIMEOUT=300
FIXTURE_JOB_TIMEOUT=600
REQUIRED_ENV=""
if [ -f "$CI_DIR/$CHART/settings.env" ]; then
# shellcheck disable=SC1090
source "$CI_DIR/$CHART/settings.env"
@@ -47,6 +51,32 @@ if [ ! -f "$CI_DIR/$CHART/test-values.yaml" ]; then
exit 1
fi
# --- Required environment for ci/<chart>/fixtures.env.yaml ------------------
# A chart whose fixtures need a value that must never be committed (freesailarr
# needs a real Wireguard key, or gluetun's kill switch keeps every app container
# from becoming Ready) declares the variable NAMES in settings.env:
#
# REQUIRED_ENV="FREESAILARR_WG_KEY FREESAILARR_WG_ADDRESSES"
#
# The values come from the environment - in CI from 1Password Connect, see the
# install-test job in .github/workflows/validate-charts.yml.
#
# A missing or empty value is a hard error on purpose. Skipping the chart
# instead would restore exactly the green-but-meaningless signal this mechanism
# exists to remove, and an empty key produces a gluetun without a handshake,
# which reads as a broken chart rather than as a missing secret. The one
# legitimate case of absent secrets - a pull request from a fork - belongs in an
# "if" on the workflow job, not in this script.
# Only the variable name is ever printed, never the value.
for VAR in $REQUIRED_ENV; do
if [ -z "${!VAR:-}" ]; then
echo "ERROR: required environment variable '$VAR' is unset or empty." >&2
echo "ci/$CHART/settings.env declares REQUIRED_ENV=\"$REQUIRED_ENV\"; ci/$CHART/fixtures.env.yaml" >&2
echo "cannot be rendered without it, and the install-test does not skip charts over missing values." >&2
exit 1
fi
done
# --- Failure diagnostics ----------------------------------------------------
diagnose() {
echo "=================== INSTALL-TEST FAILED: DIAGNOSTICS ==================="
@@ -72,6 +102,20 @@ kubectl apply -f "$CI_DIR/common/"
if [ -f "$CI_DIR/$CHART/fixtures.yaml" ]; then
kubectl apply -f "$CI_DIR/$CHART/fixtures.yaml"
fi
# Fixtures with values that must not be committed are rendered first: the
# checked-in fixtures.env.yaml holds ${VARIABLE} placeholders and nothing else.
# envsubst is restricted to the names from REQUIRED_ENV (its SHELL-FORMAT
# argument), so a variable that is not declared there is never substituted, no
# unrelated "$..." in the manifest is touched, and no other variable of the
# runner environment can end up in the cluster. The rendered document is piped
# straight into kubectl and never printed - kubectl reports object names only.
if [ -f "$CI_DIR/$CHART/fixtures.env.yaml" ]; then
SHELL_FORMAT=""
for VAR in $REQUIRED_ENV; do
SHELL_FORMAT="$SHELL_FORMAT\${$VAR}"
done
envsubst "$SHELL_FORMAT" < "$CI_DIR/$CHART/fixtures.env.yaml" | kubectl apply -f -
fi
echo "::endgroup::"
# --- 2. Wait for fixture jobs (node setup, data seeding) and infra ----------