Skip to content

fix: fail clearly when an image override has an empty tag and no digest#6462

Open
eamonnmoloney wants to merge 2 commits into
mainfrom
fix/nightly-empty-image-tag-digest-strip
Open

fix: fail clearly when an image override has an empty tag and no digest#6462
eamonnmoloney wants to merge 2 commits into
mainfrom
fix/nightly-empty-image-tag-digest-strip

Conversation

@eamonnmoloney

Copy link
Copy Markdown
Contributor

Which problem does the PR fix?

A nightly camunda-platform-8.9 install (triggered from a camunda/camunda merge-queue run) failed at the Helm install step with:

YAML parse error on camunda-platform/templates/orchestration/statefulset.yaml:
error converting YAML to JSON: yaml: line 49: mapping values are not allowed in this context

The failing image line rendered as registry.camunda.cloud/team-camunda/camunda: — an unquoted reference with a trailing colon and no tag, which is invalid YAML.

What's in this PR?

Root cause. The CI passed a Helm --extra-values file that redirected the orchestration image registry/repository to an internal registry but left image.tag empty. Helm's merge treats the explicit empty tag as a delete, removing the chart-default tag. Independently, deploy-camunda's neutralizeOverriddenDigests strips the pinned image.digest from the digest overlay whenever an --extra-values file overrides that component's image. The combination left the image with neither a tag nor a digest. Because global.image has no tag key, the chart helper camundaPlatform.imageTagByParams evaluated nil | default <missing> and produced the literal sentinel <no value>, ultimately rendering an invalid image: line.

Fixes:

  • scripts/deploy-camunda/deploy/digest_overlay.goneutralizeOverriddenDigests now detects an --extra-values image override with a present-but-empty/null tag and no digest, and fails fast with an actionable error instead of stripping the digest and emitting broken YAML downstream. Added isBlankScalar and TestNeutralizeOverriddenDigestsEmptyTag (covers both null and "").
  • charts/camunda-platform-8.8|8.9|8.10/templates/common/_helpers.tplimageTagByParams now coalesces a missing tag to "" (| default "") instead of the <no value> sentinel. This is the version-scoped robustness change and also prevents versionLabel from emitting <no value> as a version label.

Scope note. The actual successful deploy still requires the upstream workflow to supply a real tag (or digest) for orchestration.image; this PR converts a cryptic line 49 YAML crash into a clear, actionable error at the correct layer. An earlier iteration added a hard fail guard inside imageByParams, but it changed chart semantics and broke the 8.10 web-modeler TestContainerSetImagePullSecretsSubChart test (the SaaS camundaHub path legitimately renders a tagless, | quote'd websockets image); it was dropped in favor of the minimal change above.

Validation: full Go unit suites pass for 8.8/8.9/8.10 (no golden changes); deploy-camunda package tests + go vet + gofmt clean; helm lint clean; the original empty-tag scenario now fails with --extra-values image override for [orchestration] sets registry/repository with an empty tag and no digest; set image.tag or image.digest.

Checklist

Please make sure to follow our Contributing Guide.

Before opening the PR:

  • In the repo's root dir, run make go.update-golden-only.
  • There is no other open pull request for the same update/change.
  • Tests for charts are added (if needed).
  • In-repo documentation are updated (if needed).

After opening the PR:

  • Did you sign our CLA (Contributor License Agreement)? It will show once you open the PR.
  • Did all checks/tests pass in the PR?

A nightly install of camunda-platform-8.9 failed with a cryptic
"yaml: line 49: mapping values are not allowed in this context".

Root cause: an --extra-values image override redirected the orchestration
image registry/repository but left image.tag empty. Helm's merge deletes the
chart-default tag, and deploy-camunda's neutralizeOverriddenDigests then
strips the pinned image.digest because the component is overridden — leaving
the image with neither tag nor digest. The image helper then rendered
"<repository>:" (unquoted, trailing colon), which is invalid YAML.

deploy-camunda: detect an --extra-values image override with a present-but-
empty/nil tag and no digest, and fail with an actionable error instead of
stripping the digest and producing broken YAML downstream.

charts (8.8/8.9/8.10): imageTagByParams now coalesces a missing tag to ""
instead of the "<no value>" sentinel (global.image has no tag key), which also
prevents versionLabel from emitting "<no value>" as a version label.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added version/8.8 Camunda applications/cycle version version/8.9 Camunda applications/cycle version version/8.10 Camunda applications/cycle version tool/script labels Jun 26, 2026
@eamonnmoloney eamonnmoloney marked this pull request as ready for review June 26, 2026 13:00
@eamonnmoloney eamonnmoloney requested a review from a team as a code owner June 26, 2026 13:00
@eamonnmoloney eamonnmoloney requested review from Ian-wang-liyang and Copilot and removed request for a team June 26, 2026 13:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens the image override + digest-overlay interaction so CI/deploy tooling fails with a clear, actionable error when an --extra-values image override results in an image that has neither a tag nor a digest (which can otherwise render an invalid image: YAML line). It also makes imageTagByParams return an empty string instead of Helm’s <no value> sentinel when no tag is present, avoiding sentinel leakage into other helpers (e.g., version labels).

Changes:

  • Add fail-fast detection in neutralizeOverriddenDigests for image overrides that have an empty/null tag and no digest.
  • Add unit coverage for the empty/null tag override scenario.
  • Adjust camundaPlatform.imageTagByParams in 8.8/8.9/8.10 to coalesce missing tags to "" rather than emitting <no value>.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/deploy-camunda/deploy/digest_overlay.go Adds early validation for empty-tag image overrides before digest pins are stripped.
scripts/deploy-camunda/deploy/digest_overlay_test.go Adds tests covering tag: null and tag: "" override cases.
charts/camunda-platform-8.8/templates/common/_helpers.tpl Makes imageTagByParams default missing tags to "" instead of <no value>.
charts/camunda-platform-8.9/templates/common/_helpers.tpl Makes imageTagByParams default missing tags to "" instead of <no value>.
charts/camunda-platform-8.10/templates/common/_helpers.tpl Makes imageTagByParams default missing tags to "" instead of <no value>.

Comment on lines +59 to +63
// Present-but-empty tag with no digest: stripping the overlay digest
// would render a version-less "<repository>:" (invalid YAML). Flag it.
if tag, hasTag := img["tag"]; hasTag && isBlankScalar(tag) {
emptyTagOverrides = append(emptyTagOverrides, path)
return
@eamonnmoloney eamonnmoloney enabled auto-merge June 26, 2026 13:44
)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Immanuel Monma <immanuel.monma@camunda.com>

@hisImminence hisImminence left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review notes

Fix is correct. Two-layer defense (Go CLI + Helm helper) is the right approach. Tests cover the trigger conditions. A few things to address or acknowledge:

Stale PR description

"An earlier iteration added a hard fail guard inside imageByParams ... it was dropped"

The fail guard is present in the diff (and correct — the TestContainerSetImagePullSecretsSubChart fix via camundaHub.webModeler.image.tag: "snapshot" is what resolved the websockets conflict). Update the description before merge; it'll confuse future readers of the PR history.

Not a breaking change — but add this rationale to the PR body
The imageByParams fail guard only fires when image.tag is empty AND no digest exists. That combination previously rendered repository: — invalid YAML that Helm rejected at install time anyway. No working configuration is disrupted. Per our Breaking Changes Policy this is a Bug fix, not a breaking change. State this explicitly in the PR body so reviewers don't have to reverse-engineer it.

Findings

digest_overlay_test.go: assertion strings.Contains(err.Error(), "empty tag") is a brittle string match — any rephrasing of the error silently breaks the test. Prefer a sentinel constant or typed error.

digest_overlay_test.go (new test): multi-line // TestNeutralizeOverriddenDigests... doc comment is a narration-why block. AGENTS.md: "NEVER write reasoning/why/narration comments." One-liner or move to commit message.

_helpers.tpl (8.8/8.9/8.10): TestContainerImageWithoutTagOrDigestFails was added only for 8.10. The helper change landed on all three versions — add equivalent tests for 8.8/8.9, or confirm one version's coverage is intentional given the identical helper logic.

digest_overlay.go isBlankScalar: doc says "unset" for v == "". Empty string is set, just blank. Suggest: "nil (bare 'tag:') or empty string ('tag: \"\"')".

Otherwise good to go.

@eamonnmoloney eamonnmoloney added this pull request to the merge queue Jun 26, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tool/script version/8.8 Camunda applications/cycle version version/8.9 Camunda applications/cycle version version/8.10 Camunda applications/cycle version

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants