Two documentation gaps, both about a reader drawing the wrong conclusion.
The install-test section said nothing about what an exclusion looks like in a PR's check list. It now says that an excluded chart gets no job at all rather than a green tick, that the detect job names it with its documented reason in the summary, that the mandatory justification is what makes a line an exclusion in the first place, and why the per-chart "if" that would produce a visible Skipped is not available (#231).
Section 3 of the style guidelines lists the charts that deviate from "the main image tag comes from appVersion" so that nobody mistakes a deviation for a mistake and tidies it away. minecraft-server has been the only chart with an overridable tag since #158 and was missing from that list: the line says that image.tagOverride exists, why (only the newest Java line is maintained, so the line becomes a decision at rollout time instead of a property of the chart), and that the chart checks the pairing of effective tag and minecraft.version itself and fails the render on a mismatch (#232).
A chart in ci/excluded-charts.txt got an install-test job that ran the script, printed SKIP and exited 0. GitHub knows only the exit code, so the check list showed "Install-test satisfactory OK" for a chart whose image was never pulled - indistinguishable from one that really came up in the cluster (#231). detect-changed-charts now removes those charts before the matrix is built, so no job exists for them and nothing claims they passed.
An absence says nothing by itself, so the detect job writes every excluded chart of the PR with its documented justification into the job summary. A "Skipped" would only say "not run"; the reason is the question a review actually asks.
The list is not parsed in YAML. The workflow calls ci/run-install-test.sh --list-excluded, the one parser, and compares whole strings with jq, so a chart name is never read as a pattern. The script's own exclusion branch now goes through the same excluded_reason() helper instead of a grep that used the chart name as a regex; it stays for local runs, where the CI filter does not apply.
Not viable, and recorded at the matrix as a comment: deciding per chart in an "if" on the install-test job, which would give a visible Skipped entry instead of an absent one. GitHub rejects it - jobs.<id>.if is evaluated before the matrix is expanded, so the matrix context does not exist there ("context \"matrix\" is not allowed here. available contexts are \"github\", \"inputs\", \"needs\", \"vars\"."). Run 33650724109 on the closed PR #233 ended in failure with zero jobs created.
Two consumers read ci/excluded-charts.txt: this script and the install-test matrix in validate-charts.yml, which has to drop excluded charts before the matrix is built (#231). Two parsers would be two chances to select different charts, and the disagreement would be silent in either direction. So the script grows a --list-excluded mode and the workflow will call it instead of re-implementing the parsing.
A line carrying only a chart name and no justification is deliberately not an exclusion: the README requires the reason, and a bare name would drop a chart out of CI with nothing to review. The reason lookup matches the name exactly instead of as a regex, so a chart name is never read as a pattern.
The workflow side is not part of this commit.
Only the newest Java line is maintained from now on. Publishing the chart once
per line out of one directory is what made the lines drift apart (#158): a
change reached whichever line happened to lie in the directory. java8 and java17
stay published as frozen artifacts at 4.0.0, java21 at 4.1.0, and none of them
gets another chart change.
Running an older JVM is now a decision at rollout time instead of a chart
version: image.tagOverride replaces the tag that otherwise comes from
appVersion. It is not called image.tag because it decouples the running image
from the chart version, and it is deliberately outside Renovate's reach -
renovate.json5 keeps tracking appVersion only.
The pairing of tag and minecraft.version is now checked at render time and fails
with both values named, the line each one belongs to, and where the tag came
from. Until now nothing checked it: a mismatch installed silently and only the
container failed afterwards. The boundaries are Mojang's, swept over all 102
releases of the piston-meta manifest (javaVersion.majorVersion): up to 1.16.5
Java 8, 1.17-1.17.1 Java 16, 1.18-1.20.4 Java 17, 1.20.5-1.21.11 Java 21, 26.1
and later Java 25. The 1.17 line was the one gap the chart's own notes did not
cover.
Two cases pass unchecked on purpose, documented in values.yaml and NOTES.txt: a
tag without a recognizable java<N> part, and a minecraft.version that is not a
plain numeric x[.y[.z]]. A guard that rejects what it does not understand gets
worked around instead of respected.
Major, because an installation that already runs a mismatched pair stops
rendering. It does not run today either - it now fails earlier and visibly.
game.seasonalEvents was handed to the container unchanged, into the image's
DISABLESEASONALEVENTS. Its default true therefore wrote
DISABLESEASONALEVENTS=true: the seasonal events were OFF in every install
this chart has ever produced, while values.schema.json described the very
same key as "true means events are enabled" (#215).
Of the two ways out, this is the loud one. Inverting the template under the
old key would have flipped the behaviour of every existing release in
silence - the same class of mistake that created the issue. Renaming the key
cannot be missed: game.seasonalEvents no longer exists, additionalProperties
is false on the game block, and a values file that still carries it fails
schema validation on upgrade instead of quietly meaning the opposite.
The new key is positive (enableSeasonalEvents) to avoid a double negative,
so the chart negates it on the way into the env var. Go's "not" cannot do
that: it reads every non-empty string as true, and the schema deliberately
accepts the string form of booleans, so "false" would have flipped the wrong
way. The helper compares explicitly and fails on anything that is neither
true nor false rather than filing it under "off".
The default is enableSeasonalEvents: false, which renders the
DISABLESEASONALEVENTS this chart has always rendered. At chart defaults the
6.1.0 and 7.0.0 manifests are identical, so upgrading alone moves no server;
switching the events on is now a deliberate act with a key that means it.
Separate finding from the same issue, fixed here because it lives in the
block being touched: "--set game=null" - or a leftover "game:" whose
sub-keys were deleted - aborted the render with a nil pointer at
.Values.game.maxPlayers. The game block never got the null-safe treatment of
#99 that probes, security contexts and resources have. It now falls back to
the documented defaults, and the schema accepts the null accordingly. The
same gap remains in the dev and server blocks; it is reported, not fixed
here.
Major bump: a values key is removed, and the schema rejects it.
The chart told operators that adding a duplicate env name to an installed
release makes the next upgrade fail in the API server, quoting "The order in
patch list ... doesn't match $setElementOrder list". Measured against helm
3.19.0 and Kubernetes 1.35, it does not fail: the upgrade succeeds, helm prints
"Release has been upgraded", and Kubernetes merges the env list by name, so the
duplicate pair collapses to the chart's own entry and the operator's override is
discarded without a word. At install time the same values behave differently -
both entries reach the pod, the later one wins, and the API server says so with
"hides previous definition of ..., which may be dropped when using apply".
The advice that followed from the old claim survives - such a switch only takes
at install time - but the stated reason was wrong in the dangerous direction. A
reader who expects a loud failure treats a green upgrade as proof the override
took effect, and green is exactly what a silently dropped override looks like.
The text now names the real failure mode and tells the reader to read the value
back off the Deployment. README carries the same correction, because every chart
in this repo offers the same additive env block.
Also records what the earlier measurement left open. With the database scaled
back up the pod returns to Ready on its own after about five seconds, restart
count still 0, so leaving the liveness group untouched costs no manual recovery.
And the limit of that signal belongs next to it: the db indicator validates a
connection, not the schema, so a database that came back empty still put the pod
back to Ready with /actuator/health at 200.
MANAGEMENT_ENDPOINT_HEALTH_GROUP_READINESS_INCLUDE=readinessState,db puts the datasource into Spring Boot's readiness group, which shipped with readinessState alone: a total database outage left the pod 1/1 Ready while every request failed. Naming the members replaces the default, so readinessState is repeated. The liveness group stays untouched on purpose, because an outage has to keep traffic away rather than add a crash loop to it.
MANAGEMENT_HEALTH_MAIL_ENABLED=false removes the mail indicator, which pinned the aggregate /actuator/health at 503 for the whole life of a healthy release, because the chart's mail wiring points at localhost:1025 where nothing listens. values.yaml and NOTES.txt document what that costs and when it has to be switched back on.