feat(rss-bridge): Gateway-API as an alternative to the Ingress (last chart of the sweep) #124

Merged
jklein merged 4 commits from feat/rss-bridge-gateway-api into main 2026-10-13 12:25:15 +02:00
Member

rss-bridge on the Gateway API — the last chart of the sweep

22 charts carried an Ingress template, 21 an HTTPRoute template, and the difference was exactly this one. It had been held back as frozen for changes by #51 — a runner defect, not a property of the chart — and the maintainer has lifted that freeze.

Plan: the last comment on #114. Decision on the red install-test: the last comment on #51.

Read the first section before the rest. This PR was prepared for a red pipeline and the pipeline came back green, which is the one thing #51 was waiting for. The body was corrected rather than left as written.

The headline finding: this chart's install-test went GREEN

This body was written expecting a red pipeline. The pipeline came back green — all eight contexts, combined state success. That is the event #51 designated as its own signal, so it belongs at the top rather than in a footnote.

Measured from run 792, job 2623:

Changed charts: ["rss-bridge"]   ->   Install-test matrix: ["rss-bridge"]
k3d cluster created, helm install -> NAME: ci, STATUS: deployed
deployment "ci-rss-bridge-deployment" successfully rolled out
ci-rss-bridge-deployment-...   1/1   Running   0   22s
OK: chart 'rss-bridge' installed and all workloads are Ready.

Zero occurrences of Unable to open primary script or Permission denied in the job. It was not a vacuum-green: the chart was in the matrix, a cluster was built, the chart installed, the pod became Ready in 22 s with 0 restarts.

The chart is ruled out as the cause by a diff, not by an argument. The empty helm template diff in the table below was produced to justify the Minor bump — it doubles as the control case. The rendered output for the fixture values is byte-identical to origin/main, so the pod spec that succeeded is, line for line, the pod spec that had been failing for months. Nothing in this PR touches the Deployment, the probes, the security context or runAsUser. The implicated layer is therefore the runner, which is exactly where #51 had already placed the burden of proof.

What this does not establish, and why #51 stays open:

  • Nobody has identified what changed on the runner. It has since reproduced — green on two consecutive runs, on two different commits of this branch (run 792 job 2623, run 794 job 2638), so it is not a single fluke. But a green test does not explain itself, and the diagnostic programme in #51's body (docker info on the runner for userns and the dind configuration, the same image in a local k3d without remapping) is still unexecuted.
  • The standing instruction on #51 is to close it on a cause, not on a colour. I have not closed it, and Fixes #51 is deliberately absent. A fresh red would be the control case this result is missing — and a finding, not a known quirk.

The decision not to put this chart in ci/excluded-charts.txt is what made this visible at all: an excluded test would have passed the whole time and told nobody. That reasoning, and this outcome, are now a Lessons-Learned entry.

The documentation was corrected in a second commit rather than shipped as written, since claiming a red test that demonstrably passed is exactly the half-finished state this repo tries not to leave behind.

What remains unproven about the Gateway mode

  • No Gateway controller runs in CI, so no HTTPRoute of this repository has ever reached Accepted: True there. True for all 22 charts, and no PR of this sweep claims otherwise.
  • The install-test installs the Ingress mode, because that is what the fixture sets. So this chart's Gateway mode is backed by helm lint --strict, the render assertions and the schema — the same position as all 21 other charts: no better, and no longer worse.

For freesailarr the Gateway mode has since been measured in production (comment on #114, and now on its wiki page). That is evidence for the form, not for this chart.

Scope

1. One HTTPRoute with all three hostnames. Nothing differs per host: every name serves the same Service at /, measured on the live Ingress (three host rules, byte-identical path and backend). spec.hostnames is a list and its rules apply to the whole object, so one object is the answer and a second would repeat one rule. Contrast kept in the template header: homeassistant renders one route per host (paths differ per host), matrix-synapse two (different paths and backends), and the Keycloak realms of #122 would need one each (app-root differs per host).

2. httpRoute.hostnames as its own mandatory value — a third shape, and it follows from the values. Most charts fall back to ingress.domain. freesailarr and homeassistant reject a hostnames key outright, because a chart-global list could not say which of ten apps, or which host entry and therefore which set of paths, it belonged to. This chart has no ingress.domain either, but its names are unambiguous — one Service, one path — so a chart-global list says exactly one thing. What rules out reusing ingress.hosts is the other half of those entries: each carries an optional tlsSecretName, which exists only to keep three grown certificates on their existing names and which addresses nothing once TLS sits on the Gateway's listener. Reusing the list would drag a structure whose second field is meaningless into the new mode and invite somebody to set it there.

rss-bridge.tlsGroups becomes inert, and this is written down as a simplification rather than quietly translated. The helper exists only to group hosts by TLS secret name; with the certificate on the listener there is nothing to group. Both its callers sit behind ingress.enabled, so Gateway mode never invokes it. It is the most intricate part of this chart's Ingress and it has no job in the new mode.

One correction to the plan — "Folge 1" does not apply here as written. The plan expected required "At least one ingress host must be provided (ingress.hosts)" to be a demanded-but-useless value in Gateway mode. It is not: that required() sits inside rss-bridge.ingress.yaml, behind {{- if .Values.ingress.enabled }}, and Gateway mode forces ingress.enabled: false. So it is already conditional and demands nothing in this mode — the same structural fact the pilot recorded for cyberchef's clusterIssuer. No code change was needed to relax it; what this PR adds is that values.yaml and the schema now say so. The schema was also checked: it requires only whitelist, and ingress.hosts accepts null.

3. The ingress.enabled-derived-value screen came back CLEAN, and that is a measurement rather than an omission. In group 2 (freesailarr) and group 3 (ytdlp-web-player — a silent authentication bypass) this was a real defect. Measured here over the whole chart directory: outside the Ingress template the only readers of an ingress value are NOTES.txt, which knows its own mode, and the tlsGroups helper, called only from behind the switch. The Deployment, Service and ConfigMap read none. RSS-Bridge takes no base URL and no hostname in its environment, so there is nothing that could come out wrong behind a Ready pod. No published helper is needed, and the clean result is recorded in README so the screen is not re-run from scratch.

4. The annotation screen is clean too — confirmed, not assumed. Read-only kubectl against the live object, 2026-10-13: the running Ingress carries cert-manager.io/cluster-issuer, the two meta.helm.sh/* keys, objectset.rio.cattle.io/id and Rancher's generated field.cattle.io/publicEndpoints — and not one nginx.ingress.kubernetes.io annotation. So rss-bridge is the first chart of the sweep whose Gateway branch in NOTES.txt has no loss to explain, and it says so positively rather than carrying over a loss paragraph from another chart. Group 3 found an operator-set compensation on four of its six charts; here that screen came back empty.

5. #40 rides along. rss-bridge/templates/_helpers.tpl held the last occurrence in the repository of "charts in this repo deliberately have no dependencies" — verified by git grep over origin/main (exactly one hit) and now zero repo-wide. Reworded on the state README describes under "Chart dependencies": dependencies are admissible but expensive (guideline 14), and ytdlp-web-player, stalwart and paperless-ngx use subcharts. The reason the helper is duplicated is unchanged, only its content — sharing it would mean a library chart, a second artefact to publish, version and pull for about one change a year. #40's other scope item, the "nine images" note in change-app-version.yml, was already corrected by PR #48 and now reads "ten".

6. No appVersion change. 2026-09-30 is the newest date tag the registry offers; everything newer is sha-*, latest and stable. Untouched.

7. Minor: 2.1.0+up2026.09.30. Additive, defaults unchanged, and relaxing a required is not a tightening.

8. Overlay at ci/httproute/rss-bridge.yaml, so the assurance is not vacuum-green. It is the second overlay in the repository that has to supply hostnames (homeassistant's was the first, for a different reason — that chart has no hostnames key and its overlay supplies names via ingress.hosts). An overlay rather than a fixture change, and here the reason is sharper than elsewhere: the fixture's Ingress is the only thing that exercises tlsGroups, which is inert in Gateway mode, so a switched fixture would stop covering it entirely.

Measured

helm lint --strict rss-bridge 0 failures
helm template diff vs origin/main, defaults empty — 229 lines, byte-identical
Gateway mode + overlay Ingress replaced by HTTPRoute, everything else identical
ci/run-httproute-match-test.sh 58 assertions over 22 charts, 0 failed (was 56 over 21)
ci/run-httproute-match-test.sh rss-bridge 2 assertions held
ci/run-selector-match-test.sh (all) 5 selectors verified, 0 failed
ci/run-quantity-render-test.sh (all) 0 failed
helm package rss-bridge-2.1.0+up2026.09.30.tgz
live pod 2026-09-30, Ready=True, 0 restarts
live Ingress 3 hosts, 3 TLS secrets, no nginx annotation

All four guard paths were exercised rather than assumed: both modes on → abort naming both value paths; empty parentRefs → abort; empty hostnames → abort; and a null httpRoute: block → clean Ingress render, no nil pointer.

# comments were kept out of the templates — every justification is in {{/* */}}, so none of it reaches the rendered manifest. That was the trap that hit groups 1 and 2.

The install-test history, kept because a recurrence would be read against it

The brief for this PR was "merge red, and do not try to make it green". That instruction was followed to the letter — nothing was weakened: not the probes, not the budgets, not the security context, not runAsUser. The byte-identical render proves that mechanically rather than on my word.

The failure being worked around was: php-fpm as uid 33 cannot read /app/index.php, the startup probe gets a 403 through its whole 150 s budget and the pod never becomes Ready. Reproduced on two different images (#51; PR #62 was merged with exactly those red contexts) while the same chart and image ran healthy in the cluster.

Only these two contexts were permitted to be red:

  • Install-test / Install-test rss-bridge
  • Validate Helm Charts / Install-test (the collective context)

In the event, neither is. All eight contexts are green and no other context went red at any point, so the "any other red context is a real defect" clause never had to be applied. ci/excluded-charts.txt is untouched, as instructed — and in hindsight that is the decision the whole result hangs on.

Wiki

Updated in the same round, wiki 1e684ca → 3fd7e65:

  • rss-bridge — routing row, per-mode prerequisites, a Gateway-mode install example, the httpRoute values table, and operating-notes sections for the mode guards, why httpRoute.hostnames is this chart's own mandatory value, the inert tlsGroups, the clean annotation screen, the clean ingress.enabled screen, and the install-test history including the green.
  • CI-CD — 58 assertions over 22 charts, two hostname-supplying overlays instead of one, and the corrected note that this chart's last green install-test is no longer a GitHub one.
  • freesailarr — the production measurements of the Gateway mode (2026-10-13), independently re-measured here, with their limits stated.
  • Lessons-Learned — three entries: where the production measurement actually stopped; a screen that finds nothing is still a result; and the red check that was kept red so it could say something, and then said it.

Fixes #114
Fixes #40

#51 stays open on purpose. Its check went green here, but one run with no identified cause is not a repair — and that issue's own instruction is to close it on a cause, not on a colour.

# `rss-bridge` on the Gateway API — the last chart of the sweep 22 charts carried an Ingress template, 21 an HTTPRoute template, and the difference was exactly this one. It had been held back as frozen for changes by #51 — a runner defect, not a property of the chart — and the maintainer has lifted that freeze. Plan: the last comment on #114. Decision on the red install-test: the last comment on #51. > **Read the first section before the rest.** This PR was prepared for a red pipeline and the pipeline came back **green**, which is the one thing #51 was waiting for. The body was corrected rather than left as written. ## The headline finding: this chart's install-test went GREEN **This body was written expecting a red pipeline. The pipeline came back green — all eight contexts, combined state `success`.** That is the event #51 designated as its own signal, so it belongs at the top rather than in a footnote. Measured from run 792, job 2623: ``` Changed charts: ["rss-bridge"] -> Install-test matrix: ["rss-bridge"] k3d cluster created, helm install -> NAME: ci, STATUS: deployed deployment "ci-rss-bridge-deployment" successfully rolled out ci-rss-bridge-deployment-... 1/1 Running 0 22s OK: chart 'rss-bridge' installed and all workloads are Ready. ``` Zero occurrences of `Unable to open primary script` or `Permission denied` in the job. **It was not a vacuum-green**: the chart was in the matrix, a cluster was built, the chart installed, the pod became Ready in 22 s with 0 restarts. **The chart is ruled out as the cause by a diff, not by an argument.** The empty `helm template` diff in the table below was produced to justify the Minor bump — it doubles as the control case. The rendered output for the fixture values is **byte-identical** to `origin/main`, so the pod spec that succeeded is, line for line, the pod spec that had been failing for months. Nothing in this PR touches the Deployment, the probes, the security context or `runAsUser`. **The implicated layer is therefore the runner**, which is exactly where #51 had already placed the burden of proof. **What this does not establish, and why #51 stays open:** - **Nobody has identified what changed on the runner.** It has since reproduced — green on two consecutive runs, on two different commits of this branch (run 792 job 2623, run 794 job 2638), so it is not a single fluke. But a green test does not explain itself, and the diagnostic programme in #51's body (`docker info` on the runner for `userns` and the dind configuration, the same image in a local k3d without remapping) is still unexecuted. - The standing instruction on #51 is to close it **on a cause, not on a colour**. I have not closed it, and `Fixes #51` is deliberately absent. A fresh red would be the control case this result is missing — and a finding, not a known quirk. The decision **not** to put this chart in `ci/excluded-charts.txt` is what made this visible at all: an excluded test would have passed the whole time and told nobody. That reasoning, and this outcome, are now a Lessons-Learned entry. The documentation was corrected in a second commit rather than shipped as written, since claiming a red test that demonstrably passed is exactly the half-finished state this repo tries not to leave behind. ## What remains unproven about the Gateway mode - **No Gateway controller runs in CI**, so no `HTTPRoute` of this repository has ever reached `Accepted: True` there. True for all 22 charts, and no PR of this sweep claims otherwise. - **The install-test installs the *Ingress* mode**, because that is what the fixture sets. So this chart's Gateway mode is backed by `helm lint --strict`, the render assertions and the schema — the same position as all 21 other charts: no better, and no longer worse. For `freesailarr` the Gateway mode has since been measured in production (comment on #114, and now on its wiki page). That is evidence for the *form*, not for this chart. ## Scope **1. One `HTTPRoute` with all three hostnames.** Nothing differs per host: every name serves the same Service at `/`, measured on the live Ingress (three host rules, byte-identical path and backend). `spec.hostnames` is a list and its rules apply to the whole object, so one object is the answer and a second would repeat one rule. Contrast kept in the template header: `homeassistant` renders one route per host (paths differ per host), `matrix-synapse` two (different paths and backends), and the Keycloak realms of #122 would need one each (`app-root` differs per host). **2. `httpRoute.hostnames` as its own mandatory value — a third shape, and it follows from the values.** Most charts fall back to `ingress.domain`. `freesailarr` and `homeassistant` reject a `hostnames` key outright, because a chart-global list could not say which of ten apps, or which host entry and therefore which set of paths, it belonged to. This chart has no `ingress.domain` either, but its names *are* unambiguous — one Service, one path — so a chart-global list says exactly one thing. What rules out reusing `ingress.hosts` is the other half of those entries: each carries an optional `tlsSecretName`, which exists only to keep three grown certificates on their existing names and which addresses nothing once TLS sits on the Gateway's listener. Reusing the list would drag a structure whose second field is meaningless into the new mode and invite somebody to set it there. **`rss-bridge.tlsGroups` becomes inert, and this is written down as a simplification rather than quietly translated.** The helper exists only to group hosts by TLS secret name; with the certificate on the listener there is nothing to group. Both its callers sit behind `ingress.enabled`, so Gateway mode never invokes it. It is the most intricate part of this chart's Ingress and it has no job in the new mode. **One correction to the plan — "Folge 1" does not apply here as written.** The plan expected `required "At least one ingress host must be provided (ingress.hosts)"` to be a demanded-but-useless value in Gateway mode. It is not: that `required()` sits *inside* `rss-bridge.ingress.yaml`, behind `{{- if .Values.ingress.enabled }}`, and Gateway mode forces `ingress.enabled: false`. So it is **already conditional** and demands nothing in this mode — the same structural fact the pilot recorded for `cyberchef`'s `clusterIssuer`. No code change was needed to relax it; what this PR adds is that `values.yaml` and the schema now *say* so. The schema was also checked: it requires only `whitelist`, and `ingress.hosts` accepts `null`. **3. The `ingress.enabled`-derived-value screen came back CLEAN**, and that is a measurement rather than an omission. In group 2 (`freesailarr`) and group 3 (`ytdlp-web-player` — a silent authentication bypass) this was a real defect. Measured here over the whole chart directory: outside the Ingress template the only readers of an ingress value are `NOTES.txt`, which knows its own mode, and the `tlsGroups` helper, called only from behind the switch. The Deployment, Service and ConfigMap read none. RSS-Bridge takes no base URL and no hostname in its environment, so there is nothing that could come out wrong behind a `Ready` pod. **No `published` helper is needed**, and the clean result is recorded in README so the screen is not re-run from scratch. **4. The annotation screen is clean too — confirmed, not assumed.** Read-only `kubectl` against the live object, 2026-10-13: the running Ingress carries `cert-manager.io/cluster-issuer`, the two `meta.helm.sh/*` keys, `objectset.rio.cattle.io/id` and Rancher's generated `field.cattle.io/publicEndpoints` — and **not one `nginx.ingress.kubernetes.io` annotation**. So `rss-bridge` is the **first chart of the sweep whose Gateway branch in `NOTES.txt` has no loss to explain**, and it says so positively rather than carrying over a loss paragraph from another chart. Group 3 found an operator-set compensation on four of its six charts; here that screen came back empty. **5. #40 rides along.** `rss-bridge/templates/_helpers.tpl` held the **last** occurrence in the repository of "charts in this repo deliberately have no dependencies" — verified by `git grep` over `origin/main` (exactly one hit) and now zero repo-wide. Reworded on the state README describes under "Chart dependencies": dependencies are admissible but expensive (guideline 14), and `ytdlp-web-player`, `stalwart` and `paperless-ngx` use subcharts. The reason the helper is duplicated is unchanged, only its content — sharing it would mean a library chart, a second artefact to publish, version and pull for about one change a year. #40's other scope item, the "nine images" note in `change-app-version.yml`, was already corrected by PR #48 and now reads "ten". **6. No `appVersion` change.** `2026-09-30` is the newest *date* tag the registry offers; everything newer is `sha-*`, `latest` and `stable`. Untouched. **7. Minor: `2.1.0+up2026.09.30`.** Additive, defaults unchanged, and relaxing a `required` is not a tightening. **8. Overlay at `ci/httproute/rss-bridge.yaml`**, so the assurance is not vacuum-green. It is the **second** overlay in the repository that has to *supply* hostnames (`homeassistant`'s was the first, for a different reason — that chart has no `hostnames` key and its overlay supplies names via `ingress.hosts`). An overlay rather than a fixture change, and here the reason is sharper than elsewhere: the fixture's Ingress is the only thing that exercises `tlsGroups`, which is inert in Gateway mode, so a switched fixture would stop covering it entirely. ## Measured | | | | --- | --- | | `helm lint --strict rss-bridge` | 0 failures | | `helm template` diff vs `origin/main`, defaults | **empty** — 229 lines, byte-identical | | Gateway mode + overlay | Ingress replaced by HTTPRoute, everything else identical | | `ci/run-httproute-match-test.sh` | **58 assertions over 22 charts**, 0 failed (was 56 over 21) | | `ci/run-httproute-match-test.sh rss-bridge` | 2 assertions held | | `ci/run-selector-match-test.sh` (all) | 5 selectors verified, 0 failed | | `ci/run-quantity-render-test.sh` (all) | 0 failed | | `helm package` | `rss-bridge-2.1.0+up2026.09.30.tgz` | | live pod | `2026-09-30`, `Ready=True`, **0 restarts** | | live Ingress | 3 hosts, 3 TLS secrets, **no nginx annotation** | All four guard paths were exercised rather than assumed: both modes on → abort naming both value paths; empty `parentRefs` → abort; empty `hostnames` → abort; and a null `httpRoute:` block → clean Ingress render, no nil pointer. `#` comments were kept out of the templates — every justification is in `{{/* */}}`, so none of it reaches the rendered manifest. That was the trap that hit groups 1 and 2. ## The install-test history, kept because a recurrence would be read against it The brief for this PR was "merge red, and do not try to make it green". That instruction was followed to the letter — **nothing was weakened**: not the probes, not the budgets, not the security context, not `runAsUser`. The byte-identical render proves that mechanically rather than on my word. The failure being worked around was: php-fpm as uid 33 cannot read `/app/index.php`, the startup probe gets a 403 through its whole 150 s budget and the pod never becomes Ready. Reproduced on two different images (#51; PR #62 was merged with exactly those red contexts) while the same chart and image ran healthy in the cluster. **Only these two contexts were permitted to be red:** - `Install-test / Install-test rss-bridge` - `Validate Helm Charts / Install-test` (the collective context) **In the event, neither is.** All eight contexts are green and no other context went red at any point, so the "any other red context is a real defect" clause never had to be applied. `ci/excluded-charts.txt` is untouched, as instructed — and in hindsight that is the decision the whole result hangs on. ## Wiki Updated in the same round, wiki `1e684ca` → `3fd7e65`: - **`rss-bridge`** — routing row, per-mode prerequisites, a Gateway-mode install example, the `httpRoute` values table, and operating-notes sections for the mode guards, why `httpRoute.hostnames` is this chart's own mandatory value, the inert `tlsGroups`, the clean annotation screen, the clean `ingress.enabled` screen, and the install-test history including the green. - **`CI-CD`** — 58 assertions over 22 charts, two hostname-supplying overlays instead of one, and the corrected note that this chart's last green install-test is no longer a GitHub one. - **`freesailarr`** — the production measurements of the Gateway mode (2026-10-13), independently re-measured here, with their limits stated. - **`Lessons-Learned`** — three entries: where the production measurement actually stopped; a screen that finds nothing is still a result; and the red check that was kept red so it could say something, and then said it. Fixes #114 Fixes #40 **`#51` stays open on purpose.** Its check went green here, but one run with no identified cause is not a repair — and that issue's own instruction is to close it on a cause, not on a colour.
jlab-bot added 1 commit 2026-10-13 11:59:24 +02:00
feat(rss-bridge): Gateway-API as an alternative to the Ingress (last chart)
Validate Helm Charts / Detect changed charts (pull_request) Successful in 4s
Validate Helm Charts / Resource quantities (pull_request) Successful in 17s
Validate Helm Charts / Selector match (pull_request) Successful in 14s
Validate Helm Charts / HTTPRoute match (pull_request) Successful in 15s
Validate Helm Charts / Build rss-bridge (pull_request) Successful in 8s
Validate Helm Charts / Trivy config rss-bridge (pull_request) Successful in 24s
Install-test / Install-test rss-bridge (pull_request) Successful in 1m10s
Validate Helm Charts / Install-test (pull_request) Successful in 1m10s
45b2d2ea4e
rss-bridge was the twenty-second and last chart of the Gateway-API sweep:
22 charts carried an Ingress template, 21 an HTTPRoute template, and the
difference was exactly this one. It had been held back as frozen by #51 -
a runner defect, not a property of the chart - and that freeze is lifted.

One HTTPRoute carrying ALL THREE hostnames, because nothing differs per
host: every name serves the same Service at "/", measured on the live
Ingress. spec.hostnames is a list, so one object is the whole answer and a
second would repeat one rule. (Unlike homeassistant, whose paths differ per
host, or matrix-synapse, whose two routes want different backends.)

httpRoute.hostnames is its own MANDATORY value, which is a third shape for
this repository and follows from the values rather than from taste. Most
charts fall back to ingress.domain; freesailarr and homeassistant reject a
hostnames key outright, because a chart-global list could not say which app
or host entry it belonged to. This chart has no ingress.domain either, but
its names are unambiguous - and the ingress.hosts list it would otherwise
reuse carries per-host tlsSecretName values that address nothing once TLS
sits on the Gateway's listener. Reusing it would drag a structure whose
other half is meaningless into the new mode.

rss-bridge.tlsGroups is therefore INERT in Gateway mode, and that is named
as a simplification rather than quietly translated: the helper exists only
to group hosts by TLS secret name, and there is nothing left to group. The
required() on ingress.hosts needed no change to become conditional - it
already sits inside the Ingress template behind ingress.enabled - so what
is new is that values.yaml and the schema now say so.

The ingress.enabled-derived-value screen that caught sure, freesailarr and
ytdlp-web-player was run here and came back CLEAN: outside the Ingress
template the only readers of an ingress value are NOTES.txt, which knows
its own mode, and tlsGroups, called only from behind the switch. The app
takes no base URL in its environment, so no "published" helper is needed.

First chart of the sweep whose Gateway branch has NO loss to explain, and
it was measured rather than assumed (read-only kubectl against the live
object): the running Ingress carries the cert-manager annotation plus Helm
and Rancher/Fleet bookkeeping, and not one nginx.ingress.kubernetes.io
annotation. The group-3 screen came back empty, so NOTES.txt says so
positively instead of copying a loss paragraph from another chart.

Also corrects the last occurrence in the repository of the outdated
sentence "charts in this repo deliberately have no dependencies"
(rss-bridge/templates/_helpers.tpl) - dependencies are admissible but
expensive since #214, and ytdlp-web-player, stalwart and paperless-ngx use
subcharts. The reason the helper is duplicated is unchanged, only its
content: sharing it would mean a library chart, a second artefact to
publish, version and pull for about one change a year.

Minor, not major: additive, defaults unchanged, and relaxing a required is
not a tightening. Proven with an EMPTY helm template diff against
origin/main for the defaults (229 lines, byte-identical); the Gateway mode
with its overlay renders the HTTPRoute in place of the Ingress and nothing
else changes. appVersion untouched - 2026-09-30 is the newest date tag the
registry has, everything newer is sha-* and latest.

ci/run-httproute-match-test.sh goes from 56 assertions over 21 charts to
58 over 22. The overlay at ci/httproute/rss-bridge.yaml has to SUPPLY
hostnames, the second in the repository that does (homeassistant's was the
first, for a different reason), because this chart has no fallback.

NOT PROVEN, and stated in the PR as well: that traffic flows. No Gateway
controller runs in CI and no HTTPRoute reaches "Accepted: True" there. For
this chart there is additionally NO successful install-test at all - it
fails on the Gitea runner in either mode (#51, reproduced on two images
while the same chart and image run healthy in the cluster). The chart is
deliberately NOT added to ci/excluded-charts.txt: an exclusion would
silence the signal, and the day the runner is fixed the test goes green by
itself. So the only red contexts expected here are
"Install-test / Install-test rss-bridge" and the collective
"Validate Helm Charts / Install-test".

Fixes #114
Fixes #40
jklein added 1 commit 2026-10-13 12:10:38 +02:00
docs(rss-bridge): the install-test went green, and the chart is ruled out as the cause
Validate Helm Charts / Detect changed charts (pull_request) Successful in 4s
Validate Helm Charts / Resource quantities (pull_request) Successful in 15s
Validate Helm Charts / Selector match (pull_request) Successful in 15s
Validate Helm Charts / HTTPRoute match (pull_request) Successful in 16s
Validate Helm Charts / Build rss-bridge (pull_request) Successful in 8s
Validate Helm Charts / Trivy config rss-bridge (pull_request) Successful in 23s
Install-test / Install-test rss-bridge (pull_request) Successful in 1m14s
Validate Helm Charts / Install-test (pull_request) Successful in 1m14s
7d365c912c
This chart's install-test had failed on the Gitea runner since the move
(#51): php-fpm as uid 33 unable to read /app/index.php, the startup probe
403ing through its whole 150s budget, the pod never Ready. The chart was
deliberately kept OUT of ci/excluded-charts.txt so that a pass would be
noticed rather than silenced.

It passed, in this PR. Measured from the run: k3d cluster up, helm install
in Ingress mode, pod 1/1 Ready in 22s with 0 restarts, no "Permission
denied" anywhere in the job, and all eight check contexts green.

The chart is ruled out as the cause by a diff rather than by an argument:
the rendered output for the fixture values is BYTE-IDENTICAL to
origin/main - proven in the previous commit to justify the Minor bump - so
the pod spec that succeeded is, line for line, the pod spec that had been
failing. The implicated layer is the runner, which is where #51 had
already placed the burden of proof. The control case arrived for free,
from evidence collected for an unrelated reason.

What this does NOT establish, and the docs say so: that it is repaired.
It is one run, nobody has identified what changed on the runner, and an
intermittent effect needs several runs per side. #51 therefore stays open
and is to be closed on a cause, not on a colour - which was the standing
instruction there before the green arrived.

Corrected accordingly, because shipping documentation that says the test
fails while it demonstrably passed is the half-finished state this repo
tries not to leave behind:

  - README: the httproute-test paragraph, guideline 4's closing passage on
    the last chart of the sweep, and the chart table row.
  - rss-bridge/templates/NOTES.txt: the Gateway branch no longer claims
    the chart has no successful install-test. What remains true, and is
    what it now says, is that the install-test installs the INGRESS mode,
    so the Gateway mode is render-only - the same position as all 21 other
    charts of the sweep rather than a worse one.
  - ci/httproute/rss-bridge.yaml: same correction, plus why the overlay
    stays load-bearing either way.

The wiki carries the same correction in the same round (rss-bridge, CI-CD)
plus a Lessons-Learned entry on the decision that produced the signal: an
excluded test is not a quiet test but a blind one, because you also lose
the moment the fault stops existing.
Author
Member

Heads-up for review: the install-test is green, and the PR body has been rewritten around that

This PR was prepared under the instruction "merge red, do not try to make it green" (#51, last comment). The instruction was followed — nothing was weakened: not the probes, not the budgets, not the security context, not runAsUser, and ci/excluded-charts.txt is untouched.

The pipeline then came back green: all eight contexts, combined state success. Install-test / Install-test rss-bridge passed in 1m10s, with the chart genuinely in the matrix, a k3d cluster built, helm install run, and the pod 1/1 Ready in 22 s with 0 restarts. Zero occurrences of Unable to open primary script or Permission denied in the job.

Why that is more than a lucky run: the empty helm template diff this PR already needed for its Minor-bump justification doubles as the control case. The rendered defaults are byte-identical to origin/main, so the pod spec that succeeded is line-for-line the one that had been failing for months. The chart is ruled out by a diff rather than by an argument, and the implicated layer is the runner — which is where #51 had already put the burden of proof.

I have not closed #51, and Fixes #51 is deliberately absent. One run, no identified cause on the runner, and that issue's own instruction is to close on a cause rather than on a colour. Reported there in full instead.

Two things changed as a result, both in the second commit (7d365c9) rather than left as written, since documentation claiming a red test that demonstrably passed is the half-finished state this repo tries to avoid:

  • README, the chart's NOTES.txt Gateway branch and the overlay comment no longer say this chart has no successful install-test. What they say instead is the part that is still true: the install-test installs the Ingress mode, so this chart's Gateway mode is render-only — the same position as all 21 other charts of the sweep, no better and no longer worse.
  • The wiki carries the same correction plus a Lessons-Learned entry on the decision that produced the signal: an excluded test is not a quiet test but a blind one, because you also lose the moment the fault stops existing.

Everything else in the scope is unchanged and is listed in the body. One correction to the approved plan worth a reviewer's eye: "Folge 1" does not apply to this chart as written — the required() on ingress.hosts already sits inside the Ingress template behind ingress.enabled, so it was conditional on the mode before this PR and demanded nothing in Gateway mode. No code change was needed to relax it; what this PR adds is that values.yaml and the schema now say so.

## Heads-up for review: the install-test is **green**, and the PR body has been rewritten around that This PR was prepared under the instruction "merge red, do not try to make it green" (#51, last comment). The instruction was followed — **nothing was weakened**: not the probes, not the budgets, not the security context, not `runAsUser`, and `ci/excluded-charts.txt` is untouched. The pipeline then came back **green**: all eight contexts, combined state `success`. `Install-test / Install-test rss-bridge` passed in 1m10s, with the chart genuinely in the matrix, a k3d cluster built, `helm install` run, and the pod `1/1 Ready` in 22 s with 0 restarts. Zero occurrences of `Unable to open primary script` or `Permission denied` in the job. **Why that is more than a lucky run:** the empty `helm template` diff this PR already needed for its Minor-bump justification doubles as the control case. The rendered defaults are **byte-identical** to `origin/main`, so the pod spec that succeeded is line-for-line the one that had been failing for months. The chart is ruled out by a diff rather than by an argument, and the implicated layer is the runner — which is where #51 had already put the burden of proof. **I have not closed #51**, and `Fixes #51` is deliberately absent. One run, no identified cause on the runner, and that issue's own instruction is to close on a cause rather than on a colour. Reported there in full instead. Two things changed as a result, both in the second commit (`7d365c9`) rather than left as written, since documentation claiming a red test that demonstrably passed is the half-finished state this repo tries to avoid: - **README**, the chart's **`NOTES.txt`** Gateway branch and the **overlay** comment no longer say this chart has no successful install-test. What they say instead is the part that is still true: the install-test installs the **Ingress** mode, so this chart's Gateway mode is render-only — the same position as all 21 other charts of the sweep, no better and no longer worse. - The **wiki** carries the same correction plus a `Lessons-Learned` entry on the decision that produced the signal: an excluded test is not a quiet test but a blind one, because you also lose the moment the fault stops existing. Everything else in the scope is unchanged and is listed in the body. One correction to the approved plan worth a reviewer's eye: **"Folge 1" does not apply to this chart as written** — the `required()` on `ingress.hosts` already sits inside the Ingress template behind `ingress.enabled`, so it was conditional on the mode before this PR and demanded nothing in Gateway mode. No code change was needed to relax it; what this PR adds is that `values.yaml` and the schema now say so.
jklein added 1 commit 2026-10-13 12:17:51 +02:00
docs(rss-bridge): the green install-test reproduced, so say "twice" rather than "one run"
Validate Helm Charts / Detect changed charts (pull_request) Successful in 7s
Validate Helm Charts / Resource quantities (pull_request) Successful in 19s
Validate Helm Charts / Selector match (pull_request) Successful in 16s
Validate Helm Charts / HTTPRoute match (pull_request) Successful in 17s
Validate Helm Charts / Build rss-bridge (pull_request) Successful in 9s
Validate Helm Charts / Trivy config rss-bridge (pull_request) Successful in 20s
Install-test / Install-test rss-bridge (pull_request) Successful in 1m8s
Validate Helm Charts / Install-test (pull_request) Successful in 1m8s
23ac537e24
The previous commit recorded the install-test going green and hedged it
with "it is one run". Pushing that commit produced a second run, on a
second commit, and it was green too - run 792 job 2623 (1m10s) and run 794
job 2638 (1m14s), both with the chart genuinely in the matrix.

So the hedge was understated in one direction and the real caution lies
elsewhere. Corrected to say what is actually true: it reproduced over two
consecutive runs, so it is not a fluke - and nobody has identified what
changed on the runner, which is the reason #51 stays open. A green test
does not explain itself, and the diagnostic programme in that issue's body
(docker info on the runner for userns and the dind configuration, the same
image in a local k3d without remapping) remains unexecuted.

"Close an issue on a cause, not on a colour" is unaffected by the count.
jklein added 1 commit 2026-10-13 12:20:54 +02:00
docs(README): the 58/22 figure is a delta, not a running total
Validate Helm Charts / Detect changed charts (pull_request) Successful in 7s
Validate Helm Charts / Resource quantities (pull_request) Successful in 15s
Validate Helm Charts / HTTPRoute match (pull_request) Successful in 18s
Validate Helm Charts / Trivy config rss-bridge (pull_request) Successful in 18s
Validate Helm Charts / Selector match (pull_request) Successful in 15s
Validate Helm Charts / Build rss-bridge (pull_request) Successful in 16s
Install-test / Install-test rss-bridge (pull_request) Successful in 1m4s
Validate Helm Charts / Install-test (pull_request) Successful in 1m4s
SonarQube Analysis / SonarQube Analysis (push) Successful in 45s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 12s
Publish RSS-Bridge Helm Chart / Publish RSS-Bridge Helm Chart (push) Successful in 12s
8896fc8d7d
Gitea #122 (one hostname per keycloak realm) is in flight concurrently and
raises keycloak's share from 4 assertions to 8. Its round was measured at
60 over 21 on a branch that does not contain rss-bridge, while the 58 over
22 here was read on a branch that does not contain the realm hostnames.

Neither total includes the other, so stating 58/22 as the figure after the
sweep would be stale in main the moment the second of the two PRs merges.
Says so now: the delta is what either round can claim, and the running
total is whatever the first run on main prints once both have landed.

Same rule, and the same wording, as the wiki's CI-CD page carries for the
two rounds.
jklein approved these changes 2026-10-13 12:25:09 +02:00
jklein merged commit 8896fc8d7d into main 2026-10-13 12:25:15 +02:00
jklein deleted branch feat/rss-bridge-gateway-api 2026-10-13 12:25:16 +02:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: jlab-cluster/helm-charts#124