Effective label
Every update carries two labels. The case behind it: a chart vendor that raises the major on every release. By the declared label every one of them is a major and waits for approval. The application inside and the values you set are often the same as before.
- Declared comes from the version strings, always:
major,minor,patch,digest,pin,pinDigest,rollback. That is whatmatchUpdateTypesreads. - Effective comes from an analyzer that looked at what actually changed:
unknownas long as no rule asked, otherwisepatch,minor,majororbreaking-values.
The safety rule
An automerge decision takes the stricter of the two labels. An analyzer may only loosen a decision where a rule says its word is to be trusted: trustEffective: true. Without that, an automerge a matchEffective rule switched on stays off; the request is opened anyway, and its evidence table says why. An analyzer can never make an update stricter than the rules already made it, and it never lets a rule fire by being absent: unknown is not a value matchEffective matches.
Asking for it
"packageRules": [
{ "matchDatasources": ["docker"], "matchPackageNames": ["registry-1.docker.io/bitnamicharts/**"],
"versioning": "semver", "analyze": true },
{ "matchDatasources": ["docker"], "matchUpdateTypes": ["major"],
"matchEffective": ["patch", "minor"], "trustEffective": true,
"automerge": true, "dependencyDashboardApproval": false }
]
The first rule marks the dependencies (analyze is off by default, because the analyzer fetches both versions). The second reads the label: a declared major whose effective label is patch or minor opens without approval and merges on its own. A breaking-values matches neither; the major stays whatever the other rules make of it.
The Helm chart analyzer
Applies to helm dependencies (a chart repository's index.yaml names the archive per version) and to docker dependencies whose tag is a chart – that is how OCI registries carry charts: the manifest's config is application/vnd.cncf.helm.config.v1+json, the layer is the archive. A docker tag that is an image is none of the analyzer's business and stays unknown.
It reads Chart.yaml and values.yaml of both versions:
| Compared | Verdict |
|---|---|
appVersion | the application's own movement: major, minor, patch, unchanged; not stated or not comparable leave the label unknown |
values.yaml keys, flattened to paths | a key the new chart no longer has is a value you may have set that now does nothing: breaking-values, the strictest label, whatever appVersion did; new keys are counted |
kubeVersion | a changed constraint, as evidence |
dependencies | each subchart's movement, as evidence |
Measured against Docker Hub's bitnamicharts/redis, 20.13.4 → 28.1.0: appVersion 7.4.3 → 8.10.1 (major), two values keys removed (sentinel.externalAccess.service.loadBalancerIP …) → breaking-values, automerge off. The same chart from 20.13.4 to a 21.0.0 where application and values stand still reads patch.
What the merge request shows
Below the update table, per analysed update:
**registry-1.docker.io/bitnamicharts/redis**: declared major, effective breaking-values (helm-chart)
| Compared | From | To | Finding |
|--------------|---------|----------|-------------------------------------------|
| appVersion | `7.4.3` | `8.10.1` | major |
| values | — | — | 2 keys removed, 19 added: sentinel.… |
| dependencies | `2.x.x` | `2.41.0` | common |
And, where a rule switched automerge on without trustEffective, one more line: which rule it was and what it would allow.
helm template with your own values as a plugin, with a diff of the rendered manifests; a docker-image analyzer over OCI labels and attestations. The interface is classify.Analyzer; an analyzer is a package under analyzer/ and one line in wire.
Next
Tasks and plugins
Lock refreshes and post-upgrade commands: what runs, in what scope, with what environment.