Repository navigation
E2E on a stacked PR tests stale committed image refs because the base-branch overlay tag is invalid #4391
Description
When a PR targets a branch other than main, its E2E run does not test current main images. It falls back to the image refs committed in the repo, and some of those are too old for the charts that use them today. The visible symptom is Grafana failing to start in "Configure Tenant and wait for applications" with failed to download plugin archive: 404 from http://grafana-dashboards.cozy-grafana-operator.svc/plugins/<id>-<ver>.zip.
There are two separate defects here. Either one alone would not produce the failure.
Base-branch overlay builds an invalid tag for a stacked PR
The Finalize job pulls the current packages tree for the PR base and overlays its image refs onto packages the PR did not rebuild. The tag is the base branch name as is, see .github/workflows/pull-requests.yaml line 648 at a759190:
if ! flux pull artifact "oci://${REGISTRY}/cozystack-packages:${BASE_REF}" \
A branch name like fix/cdi-update-keeps-local-templates has a /, which is not valid in an OCI tag, so the pull fails at parse time:
✗ 'oci://iad.ocir.io/idyksih5sir9/cozystack/cozystack-packages:fix/cdi-update-keeps-local-templates' invalid URL: could not parse reference: ...
No current-main packages tree at _out/mainpkgs — unbuilt packages keep committed refs
The job prints a warning and continues, so every unbuilt package runs its committed ref. For a stacked PR that means E2E tests the last release, not the tip of main. The overlay from the base branch came in with #3471.
Committed grafana-dashboards ref predates plugin mirroring
packages/system/grafana-operator/images/grafana-dashboards.tag on main points to grafana-dashboards:v1.6.0@sha256:cb22416b34d4385e4df58314de390920af805c03358fe00734c8fa44ba505fe9. It was last stamped in 235d38d (2026-07-22). Plugin mirroring into that image landed two days later in 606ffd5, and grafana.yaml on main now installs plugins from it. I exported the pinned image: it has the dashboards under /var/www/dashboards/ and no plugins/ directory at all. So any path that falls back to committed refs gets the 404.
Affected runs
In PR runs created 2026-09-12 to 2026-09-22 UTC, 211 reached E2E. Only two had a base other than main, and both hit this 404. None of the 207 main-based runs did. The two runs, both with base fix/kafka-hook-credentials:
- 34991666797, 2026-09-15 15:55 UTC
- 35190300009, 2026-09-17 06:32 UTC
The same failure happened earlier in run 34543762473 (2026-09-11), twice on retry.
Possible fixes
For the overlay, fall back to main when the base is neither main nor a release-* line, or sanitize the ref into a valid tag. Either way, a stacked PR would get current main images, not the last release.
For the grafana-dashboards ref, re-stamp it so the committed image includes the plugins its chart asks for.
I did not pull the cozystack-packages:main artifact myself, so I have not checked directly that its grafana-dashboards image has the plugins. The 207 clean main-based runs are the only evidence for that.
Activity
fix(ci): overlay the right line's refs for a PR on a feature branch (#…
IvanHunters commentedon Sep 25, 2026
Hit the same failure on a fresh run and captured the server side, which confirms the grafana-dashboards half directly (this issue notes the
mainartifact was not pulled to check).Run 36069518943 (PR #4471, base
test/wait-budget-guard-margin, a stacked PR). From that run'scozyreport, thegrafana-dashboardsmirror pod runs the committed pinghcr.io/cozystack/cozystack/grafana-dashboards:v1.6.0@sha256:cb22416b34d4385e4df58314de390920af805c03358fe00734c8fa44ba505fe9and is healthy the whole time (phase: Running,ready: true,restartCount: 0, darkhttpd listening). It serves every dashboard.jsonwith 200 and answers every/plugins/*.zipwith 404:So the pinned image has the dashboards and no
plugins/, exactly as reasoned here. Grafana stops on the first plugin and crashloops, andConfigure Tenant and wait for applicationstimes out.One addition for the fix scope:
606ffd5b1(the plugin mirroring) is only on the v1.7.0 line, not in v1.6.1..v1.6.3. If releases carry the committed digest through the promote/retag path rather than a rebuild, a v1.7.0 release would ship the pre-plugingrafana-dashboardsimage to production as well, not just E2E, which is the air-gapped case the mirror exists for. So re-stamping the ref closes a production risk too, not only the stacked-PR symptom.test(monitoring): scope the parity guard's comment to what it proves
lexfrei commentedon Sep 28, 2026
I checked whether the stale grafana-dashboards pin reaches a release. It doesn't, so the defect is confined to CI runs that fall back to committed refs.
The v1.7.0-alpha.1 tag still carries the pre-mirror pin in the tree (
grafana-dashboards:v1.6.0@sha256:cb22416b…). The packages artifact the release actually installs from iscozystack-packages@sha256:ea73f9c03dafa3012789087b187c40ff518ca39de05a3c9729144b712e758a5a, taken fromcozystack-operator-generic.yamlin the release assets. That artifact hasgrafana-dashboards:v1.7.0-alpha.1@sha256:41a87524e84624cd5b816f7539d30cd5ec9d73d1899b024481cd447a3381b87c, and that image does ship the plugins:The v1.6.x line is not affected either. v1.6.4 pins its own v1.6.4 image, and its
grafana.yamldoes not install plugins from the mirror at all.One more stacked-PR run with the same failure: 36059722762 (PR #4453, base
feat/kubevirt-csi-vmi-hotplug-fallback-flag). Its cozyreport shows the mirror on thev1.6.0@sha256:cb22416b…pin answeringGET /plugins/grafana-worldmap-panel-1.0.6.zipwith 404 72 times, and Grafana exits withfailed to download plugin archive: 404.