diff --git a/.github/workflows/change-app-version.yml b/.github/workflows/change-app-version.yml index 1c1aaea..d04ce0c 100644 --- a/.github/workflows/change-app-version.yml +++ b/.github/workflows/change-app-version.yml @@ -35,7 +35,11 @@ on: - minecraft-router - minecraft-server - rss-bridge - - freesailarr + # freesailarr is deliberately absent: none of its nine images takes + # its tag from appVersion (they are all pinned in its values.yaml), + # so this workflow would rewrite appVersion and republish the chart + # without changing a single deployed image. Update its images through + # a Renovate PR, and its appVersion by hand. workflow_call: inputs: app-version: diff --git a/README.md b/README.md index 6176672..e034f85 100644 --- a/README.md +++ b/README.md @@ -66,10 +66,13 @@ What Renovate keeps current: | --- | --- | | Chart app versions (`appVersion:` in `Chart.yaml`) | One `customManagers` entry per chart, hard-coding the image repository | | Sidecar/init images in `values.yaml` (nginx, guacd, busybox, alpine) | Built-in `helm-values` manager | +| **All** images of `freesailarr`, including its main one | Built-in `helm-values` manager — the chart pins every tag in `values.yaml` and has no app-version block | | GitHub Actions | Built-in `github-actions` manager | | Tool versions pinned as workflow env vars (`TRIVY_VERSION`) | `# renovate: datasource=… depName=…` comment above the line | -Each chart renders its main image as `:{{ .Chart.AppVersion }}` — repository in the template, version in `Chart.yaml`. Renovate cannot join two files, so the mapping lives in `renovate.json5`, one block per chart. It is deliberately *not* a `# renovate:` comment inside each `Chart.yaml`: that would touch all chart directories and force a version bump plus a publish per chart for a pure comment change. Charts whose tags carry a flavour or date suffix (`apache-tika`, `minecraft-server`, `rss-bridge`, `teamspeak-server`) override `versioning` in their block; the reasoning sits next to each one. +Each chart renders its main image as `:{{ .Chart.AppVersion }}` — repository in the template, version in `Chart.yaml`. Renovate cannot join two files, so the mapping lives in `renovate.json5`, one block per chart. It is deliberately *not* a `# renovate:` comment inside each `Chart.yaml`: that would touch all chart directories and force a version bump plus a publish per chart for a pure comment change. Charts whose tags carry a flavour or date suffix (`apache-tika`, `minecraft-server`, `rss-bridge`, `teamspeak-server`) override `versioning` in their block; the reasoning sits next to each one. `freesailarr` has no block on purpose — see the images exception above; a block would either duplicate the `helm-values` updates or rewrite an `appVersion` that selects no image. + +A consequence of pinning every tag in `values.yaml`: `ci/renovate-bump-chart.sh` sees an unchanged `appVersion` and bumps the chart **patch**, so the `+up` suffix keeps naming the old marker version. That is intended for the eight app images, but it means a **gluetun** update must be paired with a hand edit of `appVersion` (and thus the suffix), otherwise the chart version stops describing what is deployed. One dependency is constrained beyond its versioning: **nginx** (the Synapse delegation sidecar) is limited to **even minors** via `allowedVersions`. nginx numbers its release branches by minor — even is stable, odd is mainline — and the chart belongs on stable. Patch updates inside the stable branch still flow through normally. The constraint tolerates a variant suffix (`1.30.4-alpine`) on purpose: docker versioning only ever offers candidates carrying the current tag's suffix, so a suffix-blind constraint would silently freeze nginx the day the sidecar moves to a slimmer base image — a switch to `1.30.4-alpine` that #84 has commissioned a check on — with no error and no warning. @@ -143,6 +146,7 @@ These guidelines are **binding for every current and future chart** in this repo ### 3. Images - The main app image tag comes from `{{ .Chart.AppVersion }}` — never hardcoded. +- **Documented exception — freesailarr**: the chart bundles nine independently versioned upstreams, so none of them is "the" app version. **No** tag comes from `appVersion`; all nine images are pinned as `.image.repository` / `.image.tag` in `values.yaml`, which is also what puts every one of them under the built-in `helm-values` manager. Its `appVersion` is a hand-maintained marker for the gluetun line and is updated together with `gluetun.image.tag`; consequently the chart has **no** block in `renovate.json5` and is **not** in the `change-app-version.yml` choice list. - Auxiliary images (sidecars, init containers, secondary workloads — e.g. the delegation nginx in matrix-synapse, guacd in patchmon, busybox init/consume images in paperless-ngx) are pinned via values instead of being hardcoded in templates, and their pinned versions are reviewed alongside every app-version update round. ### 4. Ingress diff --git a/freesailarr/Chart.yaml b/freesailarr/Chart.yaml index a2b3389..98e889c 100644 --- a/freesailarr/Chart.yaml +++ b/freesailarr/Chart.yaml @@ -6,6 +6,13 @@ icon: https://raw.githubusercontent.com/qdm12/gluetun/master/doc/logo_256.png type: application version: 1.0.0+upv3.41.1 +# Hand-maintained marker for the gluetun line this chart is built around - it +# is NOT the source of any image tag. All nine images, gluetun included, are +# pinned in values.yaml so Renovate's helm-values manager can propose them +# there; consequently this chart has no app-version block in renovate.json5 and +# nothing rewrites this field automatically. Update it by hand together with +# gluetun.image.tag, otherwise the +up suffix of version: stops describing what +# the chart deploys. appVersion: "v3.41.1" maintainers: diff --git a/freesailarr/templates/freesailarr.sfs.yaml b/freesailarr/templates/freesailarr.sfs.yaml index d2d220e..4a45414 100644 --- a/freesailarr/templates/freesailarr.sfs.yaml +++ b/freesailarr/templates/freesailarr.sfs.yaml @@ -86,7 +86,7 @@ spec: # internet only through the Wireguard tunnel (gluetun's firewall acts # as kill switch). - name: gluetun - image: "qmcgaw/gluetun:{{ .Chart.AppVersion }}" + image: "{{ .Values.gluetun.image.repository }}:{{ .Values.gluetun.image.tag }}" imagePullPolicy: IfNotPresent # An uncleanly exited gluetun (crash, OOM killer, node issue) leaves # its ip rule, routing table and tun device behind in the shared pod diff --git a/freesailarr/values.yaml b/freesailarr/values.yaml index 5507c51..a0eb083 100644 --- a/freesailarr/values.yaml +++ b/freesailarr/values.yaml @@ -4,10 +4,21 @@ # the Wireguard tunnel. # # Image pinning (documented deviation from the Chart.AppVersion standard): -# appVersion pins the gluetun image only. All other app images are pinned via -# values (.image.repository / .image.tag) because the stack combines -# nine independently versioned upstream projects; the pinned tags are reviewed -# alongside every app-version update round, like side images in other charts. +# NO image tag comes from appVersion. All nine images, gluetun included, are +# pinned here via .image.repository / .image.tag, because the stack +# combines nine independently versioned upstream projects and none of them is +# "the" one app version. +# +# That is also what puts every image under Renovate: the built-in helm-values +# manager reads image.repository/image.tag pairs out of this file and proposes +# one update per image, and ci/renovate-bump-chart.sh bumps the chart version +# along with it. A chart whose main image came from appVersion would instead +# need a hard-coded block in renovate.json5 - freesailarr deliberately has none. +# +# Chart.yaml's appVersion is therefore a hand-maintained marker for the gluetun +# line this chart is built around, not the source of any tag. Keep it in step +# with gluetun.image.tag below when you accept a gluetun update, otherwise the +# +up suffix of the chart version drifts away from what is actually deployed. # Scale the whole chart down without uninstalling it: scaleDown: true renders # every Deployment/StatefulSet with replicas: 0 (and suspends CronJobs) and @@ -113,7 +124,11 @@ ingress: annotations: {} gluetun: - # Image tag comes from Chart.AppVersion (gluetun is the chart's main app). + # Pinned here like every other image in this chart, so Renovate's helm-values + # manager proposes gluetun updates too. Docker Hub tags carry a v prefix. + image: + repository: qmcgaw/gluetun + tag: v3.41.1 vpn: serviceProvider: mullvad type: wireguard diff --git a/renovate.json5 b/renovate.json5 index 2f6d880..e400c1f 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -148,6 +148,15 @@ // mapping here leaves the charts untouched. // // When adding a chart, add a block here — see README "Creating a new chart". + // + // Exception, deliberately no block: `freesailarr`. It bundles nine + // independently versioned upstreams, so none of them is "the" app version + // and no image tag comes from appVersion — all nine are pinned as + // image.repository/image.tag in its values.yaml, where the built-in + // helm-values manager already finds them and proposes one update per + // image. Adding a block here would either duplicate those updates or + // rewrite an appVersion that selects nothing. Its appVersion is a + // hand-maintained marker; see freesailarr/Chart.yaml. { description: "apache-tika: four-part version plus flavour suffix (3.3.1.0-full); the compatibility group keeps the chart on -full.",