Merge pull request #170 from jk-cluster/ci/freesailarr-install-test
ci: freesailarr wirklich installieren statt überspringen (Wireguard-Zugang aus 1Password)
This commit is contained in:
9 files changed
+235
-8
No files matched your search
@@ -149,13 +149,61 @@ jobs:
|
||||
uses: actions/checkout@v7
|
||||
- name: "Install Helm"
|
||||
uses: azure/setup-helm@v5
|
||||
# freesailarr is the one chart whose install-test needs credentials:
|
||||
# without a real Wireguard key gluetun never completes a handshake, and
|
||||
# behind its kill switch not a single app container becomes Ready. The key
|
||||
# comes from 1Password Connect like the registry credentials in
|
||||
# publish-helm-chart.yml, and it is a CI-ONLY Mullvad key: Mullvad ties an
|
||||
# address to a key and sends the tunnel to the endpoint it saw last, so
|
||||
# reusing the production key would let every PR run pull the tunnel out
|
||||
# from under the running stack - with the symptom in the cluster and the
|
||||
# cause in a pull request. Loaded only for this chart; no other chart run
|
||||
# touches the VPN key.
|
||||
- name: "Configure OP-Connect"
|
||||
if: matrix.chart == 'freesailarr'
|
||||
uses: 1password/load-secrets-action/configure@v5
|
||||
with:
|
||||
connect-host: https://op-connect.jk-dev.de
|
||||
- name: "Load freesailarr VPN credentials"
|
||||
id: load-freesailarr-vpn
|
||||
if: matrix.chart == 'freesailarr'
|
||||
uses: 1password/load-secrets-action@v5
|
||||
env:
|
||||
OP_CONNECT_TOKEN: ${{ secrets.OP_CONNECT_TOKEN }}
|
||||
FREESAILARR_WG_KEY: op://GitHub-Actions/freesailarr-mullvad-test-config/credential
|
||||
FREESAILARR_WG_ADDRESSES: op://GitHub-Actions/freesailarr-mullvad-test-config/ip-address
|
||||
# The same trap publish-helm-chart.yml documents at length: v5 of
|
||||
# load-secrets-action does NOT export the loaded values as environment
|
||||
# variables for later steps, only its step outputs carry them, and the
|
||||
# loading step logs "Populating variable" and stays green either way. So
|
||||
# the values are mapped into each step's own env block via
|
||||
# steps.<id>.outputs.* and read as quoted shell variables. The ":?" guards
|
||||
# run before the cluster is even created and name the op:// field that is
|
||||
# missing - an empty key would otherwise reach gluetun and look like a
|
||||
# broken chart instead of a missing secret. They print the variable name,
|
||||
# never its value.
|
||||
- name: "Verify the VPN credentials arrived"
|
||||
if: matrix.chart == 'freesailarr'
|
||||
env:
|
||||
FREESAILARR_WG_KEY: ${{ steps.load-freesailarr-vpn.outputs.FREESAILARR_WG_KEY }}
|
||||
FREESAILARR_WG_ADDRESSES: ${{ steps.load-freesailarr-vpn.outputs.FREESAILARR_WG_ADDRESSES }}
|
||||
run: |-
|
||||
: "${FREESAILARR_WG_KEY:?empty - check op://GitHub-Actions/freesailarr-mullvad-test-config/credential}"
|
||||
: "${FREESAILARR_WG_ADDRESSES:?empty - check op://GitHub-Actions/freesailarr-mullvad-test-config/ip-address}"
|
||||
echo "Both VPN values arrived non-empty."
|
||||
- name: "Install k3d"
|
||||
run: curl -sSfL https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | TAG="$K3D_VERSION" bash
|
||||
- name: "Create k3d cluster"
|
||||
run: k3d cluster create install-test --image "$K3S_IMAGE" --wait --timeout 180s
|
||||
# Excluded charts (see ci/excluded-charts.txt) are skipped inside the
|
||||
# script with their documented reason.
|
||||
# script with their documented reason. The variables below are empty for
|
||||
# every other chart and are read only by the chart that declares them in
|
||||
# ci/<chart>/settings.env (REQUIRED_ENV); the script fails loudly if a
|
||||
# declared one is missing, it never skips over it.
|
||||
- name: "Install chart and wait for readiness"
|
||||
env:
|
||||
FREESAILARR_WG_KEY: ${{ steps.load-freesailarr-vpn.outputs.FREESAILARR_WG_KEY }}
|
||||
FREESAILARR_WG_ADDRESSES: ${{ steps.load-freesailarr-vpn.outputs.FREESAILARR_WG_ADDRESSES }}
|
||||
run: ci/run-install-test.sh "${{ matrix.chart }}"
|
||||
- name: "Delete k3d cluster"
|
||||
if: always()
|
||||
|
||||
@@ -40,7 +40,7 @@ Collection of some self-made helm-charts. Each top-level directory is a standalo
|
||||
- `publish-<chart>.yml` — one thin workflow per chart; triggers on pushes to `main` touching `<chart>/**` (or manually) and calls the reusable workflow below. **A push to a chart directory on `main` publishes that chart**, so the chart version must be bumped in the same change.
|
||||
- `publish-helm-chart.yml` — reusable workflow: `helm package`, then `helm push` to the private JK-Registry. Registry credentials come from 1Password Connect (`OP_CONNECT_TOKEN` secret, items under `op://GitHub-Actions/`). The loaded values are read via **`steps.<id>.outputs.*`**, mapped into each step's own `env:` block and used as quoted shell variables — never interpolated into the command line. `load-secrets-action` **v5 no longer exports them as environment variables** for later steps the way v4 did, so after the v5 bump every `${{ env.JK_CR_* }}` reference resolved to an empty string while the loading step still logged `Populating variable` and stayed green. Each value is additionally guarded with `:?`, because an empty one used to collapse into a missing argument rather than an error: `-u` consumed the following `--password-stdin`, helm fell back to an interactive prompt and the job died with `inappropriate ioctl for device` — a terminal error for what was really an unset variable.
|
||||
- `change-app-version.yml` — manually dispatched app-version bump; the chart must be listed in its `chart-name` choice list.
|
||||
- `validate-charts.yml` — PR pipeline: detects which charts a PR touches and, for exactly those, runs `helm lint --strict`, `helm package`, and a chart-version bump check (`template-chart` is exempt from the version check). PRs without chart changes skip the build matrix. After the build stage, an **install-test** job (same changed-charts matrix) installs each changed chart into an ephemeral [k3d](https://k3d.io) cluster on the runner and requires every workload to become Ready — see below.
|
||||
- `validate-charts.yml` — PR pipeline: detects which charts a PR touches and, for exactly those, runs `helm lint --strict`, `helm package`, and a chart-version bump check (`template-chart` is exempt from the version check). PRs without chart changes skip the build matrix. After the build stage, an **install-test** job (same changed-charts matrix) installs each changed chart into an ephemeral [k3d](https://k3d.io) cluster on the runner and requires every workload to become Ready — see below. Both matrices follow the changed chart directories, so a PR that only changes the harness under `ci/` exercises nothing by itself; the Trivy scan has a fixed-sample fallback for that case, the install-test has none — bump the affected chart's patch version to pull it into the matrix.
|
||||
|
||||
### Install-test (PR pipeline stage 2)
|
||||
|
||||
@@ -51,9 +51,12 @@ Fixtures live at the **repo root** under `ci/` (deliberately *not* inside the ch
|
||||
- `ci/common/` — fixtures applied for every chart (schema-less stub CRD for `OnePasswordItem`)
|
||||
- `ci/<chart>/test-values.yaml` — values for the CI install (required for every installable chart)
|
||||
- `ci/<chart>/fixtures.yaml` — dummy secrets with in-cluster connection data, throwaway infrastructure (postgres/redis/dex), static hostPath PVs/StorageClasses where the chart pins a storage class or needs RWX, and seed jobs (e.g. `synapse generate`)
|
||||
- `ci/<chart>/settings.env` — optional overrides (e.g. `INSTALL_TIMEOUT` for slow starters)
|
||||
- `ci/<chart>/fixtures.env.yaml` — fixtures that need a value which must not be committed. The file holds `${VARIABLE}` placeholders and nothing else; `ci/run-install-test.sh` renders it with `envsubst` and pipes the result straight into `kubectl` (never printed). Substitution is restricted to the names from `REQUIRED_ENV`, so an undeclared variable is never filled in and no unrelated `$…` in the manifest is touched
|
||||
- `ci/<chart>/settings.env` — optional overrides: `INSTALL_TIMEOUT` for slow starters, and `REQUIRED_ENV="VAR_A VAR_B"` to declare the variables `fixtures.env.yaml` needs. **A missing or empty declared variable fails the install-test loudly, naming the variable — it never skips the chart.** Skipping would restore exactly the green-but-meaningless signal this mechanism exists to remove; the one legitimate case of absent secrets, a PR from a fork, belongs in an `if` on the workflow job rather than in the script
|
||||
- `ci/excluded-charts.txt` — charts that cannot run in CI, each with a justification. Currently: `satisfactory` (multi-GB image + 10GB+ Steam download), `template-chart` (scaffold with placeholder image)
|
||||
|
||||
`freesailarr` is the only chart using `fixtures.env.yaml` today: gluetun needs a real Wireguard key, or it never completes a handshake and no app container behind its kill switch becomes Ready. The install-test job loads the key from 1Password Connect for that chart only, using the same pattern as `publish-helm-chart.yml` — `steps.<id>.outputs.*` into the step's own `env:`, quoted, with `:?` guards that name the missing `op://` field before the cluster is even created. The key in that item is a **CI-only Mullvad key**, deliberately not the production one: Mullvad ties an address to a key and routes the tunnel to the endpoint it saw last, so a shared key would make every PR run pull the tunnel out from under the running stack — with the symptom in the cluster and the cause in a pull request.
|
||||
|
||||
Fixture images avoid Docker Hub where possible (`public.ecr.aws`/`ghcr.io`) to dodge runner rate limits. The job **blocks the PR** on failure — the stabilization phase of #22 ended when Renovate started automerging patch/minor updates, since a chart that no longer starts must not reach `main` and publish unattended. When adding a new chart, add its `ci/<chart>/` fixtures (or an entry in `ci/excluded-charts.txt`) — the install-test fails if both are missing. The script also runs locally against any existing cluster: `k3d cluster create t && ci/run-install-test.sh <chart> && k3d cluster delete t`.
|
||||
|
||||
## Dependency updates (Renovate)
|
||||
@@ -251,5 +254,5 @@ Reference implementation: `template-chart/values.schema.json` and `template-char
|
||||
- `icon:` is mandatory in every `Chart.yaml`. **Documented exception — freesailarr, the only chart without one**: the rule everywhere else is "the icon is this chart's one upstream's logo", and a chart bundling nine independently versioned projects has no such upstream — picking one of the nine would imply a "main app" the stack deliberately does not have. That is the whole criterion, and it applies to no other chart in the repo: a single-upstream chart without an icon is a missing icon, not an exception. The omission costs an INFO line in `helm lint --strict` (`icon is recommended`), which still exits 0.
|
||||
- `helm lint --strict` must pass without findings.
|
||||
- `NOTES.txt` for every chart is planned (#43); seven charts ship one so far (`apache-tika`, `cyberchef`, `freesailarr`, `gotenberg`, `homeassistant`, `patchmon`, `rss-bridge`).
|
||||
- CI: every installable chart has fixtures under `ci/<chart>/` (`test-values.yaml`, optionally `fixtures.yaml`/`settings.env`) or a justified entry in `ci/excluded-charts.txt` — the install-test fails if both are missing.
|
||||
- CI: every installable chart has fixtures under `ci/<chart>/` (`test-values.yaml`, optionally `fixtures.yaml`/`fixtures.env.yaml`/`settings.env`) or a justified entry in `ci/excluded-charts.txt` — the install-test fails if both are missing.
|
||||
- Charts have no dependencies (`charts/` directories are empty).
|
||||
@@ -1,5 +1,4 @@
|
||||
# Charts excluded from the PR install-test, one per line: <chart> <reason>.
|
||||
# ci/run-install-test.sh skips these with the given reason.
|
||||
freesailarr gluetun never becomes healthy without a real Wireguard key and VPN connectivity, and every app container sits behind its firewall - the pod cannot become Ready on a CI runner
|
||||
satisfactory the game-server image is multiple GB and Steam downloads 10GB+ game files on first start - impractical on a CI runner
|
||||
template-chart scaffold with placeholder image "ghcr.io/ORG/IMAGE:xxx", never published
|
||||
@@ -0,0 +1,22 @@
|
||||
# The gluetun credentials Secret the 1Password operator materializes on the
|
||||
# real cluster - here as a template with variable NAMES only. This file must
|
||||
# never contain a value; ci/run-install-test.sh renders it with envsubst,
|
||||
# restricted to the names declared in ci/freesailarr/settings.env
|
||||
# (REQUIRED_ENV), and pipes the result straight into kubectl.
|
||||
#
|
||||
# The values come from a 1Password item holding a CI-only Mullvad key, loaded in
|
||||
# the install-test job of .github/workflows/validate-charts.yml. A CI-only key
|
||||
# on purpose: Mullvad ties an address to a key and sends the tunnel to the
|
||||
# endpoint it saw last, so a shared key would let every pull request pull the
|
||||
# tunnel out from under the running stack.
|
||||
#
|
||||
# Name and keys follow the chart: <release>-<chart>-gluetun-secret with the
|
||||
# fields the StatefulSet reads via secretKeyRef. Release name is ci.
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: ci-freesailarr-gluetun-secret
|
||||
type: Opaque
|
||||
stringData:
|
||||
wireguard-private-key: "${FREESAILARR_WG_KEY}"
|
||||
wireguard-addresses: "${FREESAILARR_WG_ADDRESSES}"
|
||||
@@ -0,0 +1,43 @@
|
||||
# Fixtures for the freesailarr install-test: the three media claims the chart
|
||||
# mounts but never creates (media.*.existingClaim). The config volumes come from
|
||||
# the StatefulSet's own volumeClaimTemplates and need nothing here.
|
||||
#
|
||||
# Default StorageClass (k3d's local-path), so the claims stay Pending until the
|
||||
# pod is scheduled - WaitForFirstConsumer, which is exactly what the chart sees
|
||||
# on a real cluster. local-path creates its directories mode 0777, so the claim
|
||||
# roots are writable for PUID/PGID 1000 without a chown job.
|
||||
#
|
||||
# The gluetun credentials Secret is NOT here: it carries values that must not be
|
||||
# committed and lives in fixtures.env.yaml.
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: ci-freesailarr-downloads
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: ci-freesailarr-movies
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: ci-freesailarr-tv
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi
|
||||
@@ -0,0 +1,10 @@
|
||||
# Nine containers in one pod, several GB of images to pull, and the app
|
||||
# containers only start once gluetun has completed its Wireguard handshake -
|
||||
# each of them then runs its own startup probe (150s budget, 300s for seerr's
|
||||
# first-boot migrations). The default of 300s is not enough for that.
|
||||
INSTALL_TIMEOUT=900
|
||||
|
||||
# The gluetun credentials for ci/freesailarr/fixtures.env.yaml. Missing or empty
|
||||
# values fail the install-test loudly instead of skipping it - see
|
||||
# ci/run-install-test.sh.
|
||||
REQUIRED_ENV="FREESAILARR_WG_KEY FREESAILARR_WG_ADDRESSES"
|
||||
@@ -0,0 +1,39 @@
|
||||
# freesailarr: the whole stack in one pod - gluetun plus eight app containers
|
||||
# that share its network namespace and sit behind its kill switch. Nothing here
|
||||
# is a shortcut around that: the install-test brings up a real Wireguard tunnel
|
||||
# with a CI-only Mullvad key (see ci/freesailarr/fixtures.env.yaml), because a
|
||||
# gluetun without a handshake keeps every app container from becoming Ready.
|
||||
#
|
||||
# Release name is ci, so the chart looks for the gluetun credentials in the
|
||||
# Secret ci-freesailarr-gluetun-secret, which the fixtures create. The chart's
|
||||
# own OnePasswordItem CR applies against the stub CRD and stays unreconciled -
|
||||
# there is no 1Password operator in the CI cluster.
|
||||
secrets:
|
||||
# Required by the chart. Only the CR's itemPath, never resolved in CI.
|
||||
gluetunSecretRef: op://ci/freesailarr-gluetun
|
||||
|
||||
media:
|
||||
# The three media claims are pre-created in fixtures.yaml (one claim per
|
||||
# category, no subPath - the shared-claim layout is a values question, not a
|
||||
# startup question). local-path hands out its directories mode 0777, so the
|
||||
# claim roots are writable for PUID/PGID as the chart requires.
|
||||
downloads:
|
||||
existingClaim: ci-freesailarr-downloads
|
||||
movies:
|
||||
existingClaim: ci-freesailarr-movies
|
||||
tv:
|
||||
existingClaim: ci-freesailarr-tv
|
||||
|
||||
gluetun:
|
||||
vpn:
|
||||
# Without this the kill switch drops cluster-internal egress as well, and
|
||||
# the very first DNS lookup against cluster DNS fails. k3s defaults:
|
||||
# 10.42.0.0/16 pods, 10.43.0.0/16 services.
|
||||
firewallOutboundSubnets: "10.42.0.0/16,10.43.0.0/16"
|
||||
|
||||
ingress:
|
||||
# Shared-domain mode with a placeholder host: the Ingress objects only have to
|
||||
# be accepted by the API server. There is no ingress-nginx and no cert-manager
|
||||
# in the CI cluster, and the install-test checks readiness, not routing.
|
||||
host: freesailarr.example.com
|
||||
clusterIssuer: ci
|
||||
+65
-2
@@ -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,7 +51,52 @@ 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 ----------------------------------------------------
|
||||
# The diagnostics echo application output, and an app may well print a value it
|
||||
# was given: gluetun logs its Wireguard address on startup. So everything the
|
||||
# failure path prints runs through a filter that replaces the values of the
|
||||
# declared REQUIRED_ENV variables with the variable name. GitHub masks them as
|
||||
# well, but that is the platform's promise rather than this harness's - and the
|
||||
# script runs locally too, where nothing masks anything.
|
||||
redact_secrets() {
|
||||
if [ -z "$REQUIRED_ENV" ]; then
|
||||
cat
|
||||
return
|
||||
fi
|
||||
local SED_ARGS=()
|
||||
local VAR
|
||||
for VAR in $REQUIRED_ENV; do
|
||||
SED_ARGS+=(-e "s|${!VAR}|<redacted:$VAR>|g")
|
||||
done
|
||||
sed "${SED_ARGS[@]}"
|
||||
}
|
||||
|
||||
diagnose() {
|
||||
echo "=================== INSTALL-TEST FAILED: DIAGNOSTICS ==================="
|
||||
echo "--- pods ---"
|
||||
@@ -64,7 +113,7 @@ diagnose() {
|
||||
done
|
||||
echo "========================================================================"
|
||||
}
|
||||
trap 'RC=$?; if [ $RC -ne 0 ]; then diagnose; fi; exit $RC' EXIT
|
||||
trap 'RC=$?; if [ $RC -ne 0 ]; then diagnose | redact_secrets; fi; exit $RC' EXIT
|
||||
|
||||
# --- 1. Apply fixtures ------------------------------------------------------
|
||||
echo "::group::Apply fixtures"
|
||||
@@ -72,6 +121,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 before they are
|
||||
# applied: the checked-in fixtures.env.yaml holds ${VARIABLE} placeholders only.
|
||||
# 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 ----------
|
||||
|
||||
@@ -8,7 +8,7 @@ description: A Helm chart to deploy a Wireguard-tunneled media automation stack
|
||||
|
||||
type: application
|
||||
|
||||
version: 3.0.0+up1.0.0
|
||||
version: 3.0.1+up1.0.0
|
||||
# The chart's own version marker, freely chosen and tied to no upstream. The
|
||||
# stack bundles nine independently versioned projects, so there is no single
|
||||
# "app version" to track here.
|
||||
|
||||
Reference in new issue
Block a user