Skip to content

feat: add opt-in gitops mode for deterministic rendering (plane-enterprise + plane-ce)#244

Open
sfasching wants to merge 1 commit into
makeplane:masterfrom
sfasching:gitops-deterministic-rendering
Open

feat: add opt-in gitops mode for deterministic rendering (plane-enterprise + plane-ce)#244
sfasching wants to merge 1 commit into
makeplane:masterfrom
sfasching:gitops-deterministic-rendering

Conversation

@sfasching

@sfasching sfasching commented Jun 15, 2026

Copy link
Copy Markdown

Summary

Adds an opt-in gitops.enabled flag (default false) to both plane-enterprise and plane-ce, so the charts render deterministically for declarative GitOps tools (Argo CD, Flux) — without changing anything for existing helm install / helm upgrade users.

  • gitops.enabled: false (default): renders byte-for-byte identical to today.
  • gitops.enabled: true: omits the per-render timestamp: {{ now | quote }} pod annotation, and keys migration Job names to .Values.planeVersion (instead of a wall-clock timestamp in plane-enterprise / .Release.Revision in plane-ce).

Why

Several workload templates inject timestamp: {{ now | quote }} into spec.template.metadata.annotations, and the migration Jobs derive metadata.name from a per-render value. Under a GitOps reconciler this is fatal:

  1. Never reaches Synced; rolls every pod on every reconcile — each Deployment's pod template differs on each render.
  2. Fails the migration Job with field is immutable — Argo CD tries to patch the existing Job, but Job.spec.template is immutable.

Reported in #158 (closed "intentional; couldn't reproduce the migrator breakage") and #206 (the exact immutable-Job failure), then worked around in #207 by making the plane-enterprise Job name timestamp-unique — which avoids the immutable error but runs the migration on every sync and orphans a Job each time. This fixes the root cause while preserving the intended default.

Design — non-breaking, opt-in

now forces a rollout on every helm upgrade — reasonable for imperative users, so it stays the default; only opted-in GitOps users change behavior:

gitops.enabled: false (default) gitops.enabled: true
pod timestamp annotation unchanged omitted
migration Job name suffix unchanged (now / .Release.Revision) planeVersion
rollout on every upgrade yes (unchanged) only on real spec change

Version-keyed Job names are deterministic per release, re-run cleanly on a version bump (new name → new Job; Argo CD prunes the old one), and never hit the immutable-Job patch. The charts already ship reloader.stakater.com/auto on some workloads — the deterministic, config-driven rollout mechanism — so GitOps users don't lose config-change rollouts by dropping the now annotation.

Proof it doesn't change the default

helm template with default values is identical to the current chart (modulo the now values that already differ between any two renders), for both charts:

plane-enterprise:  diff(norm(upstream), norm(this-branch defaults))  ->  empty
plane-ce:          diff(norm(upstream), norm(this-branch defaults))  ->  empty

With gitops.enabled=true, repeated renders are identical and contain no now:

                  timestamp annotations      migrate Job name
plane-enterprise  default 10 -> gitops 0     ...-migrate-20260614-... -> ...-migrate-v2-6-2
plane-ce          default  8 -> gitops 0     ...-migrate-1            -> ...-migrate-v1-2-0

Scope

charts/plane-enterprise and charts/plane-ce — the timestamp annotation in their workload templates, version-keyed migration Job names, and the gitops.enabled values flag. No default-behavior change in either chart.

Relates to #158, #206, #207.

Summary by CodeRabbit

  • New Features

    • Added a gitops configuration option to support deterministic Helm rendering across Plane charts.
  • Configuration

    • New gitops block (default: disabled). When enabled, per-workload timestamp pod annotation values are omitted, and migration job naming switches to a version-based scheme (instead of timestamp/revision-based naming) for more repeatable deployments.

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds a gitops.enabled flag (default false) to both plane-ce and plane-enterprise charts. When enabled, pod template timestamp annotations are omitted, and migrator/minio Job names switch to normalized planeVersion-based names.

Changes

GitOps Deterministic Rendering

Layer / File(s) Summary
gitops values contract
charts/plane-ce/values.yaml, charts/plane-enterprise/values.yaml
Adds a new gitops: { enabled: false } block with comments describing the rendering behavior it controls.
Deterministic Job naming and annotation guards
charts/plane-ce/templates/workloads/migrator.job.yaml, charts/plane-ce/templates/workloads/minio.stateful.yaml, charts/plane-enterprise/templates/workloads/migrator.job.yaml, charts/plane-enterprise/templates/workloads/minio.stateful.yaml, charts/plane-enterprise/templates/workloads/pi-migrator.job.yaml
When gitops.enabled is true, Job names derive from normalized planeVersion values instead of timestamps or Release.Revision, and timestamp annotations are suppressed on those Jobs.
Deployment and StatefulSet timestamp annotation guards
charts/plane-ce/templates/workloads/*.deployment.yaml, charts/plane-enterprise/templates/workloads/*.deployment.yaml, charts/plane-enterprise/templates/workloads/monitor.stateful.yaml
Wraps the timestamp: {{ now | quote }} annotation in gitops conditionals across workload pod templates in both charts.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: mguptahub

Poem

🐇 Hop hop, the charts now render clear,
GitOps mode trims timestamps near.
Jobs find names in planeVersion light,
Deployments hush their clocks at night.
Deterministic hops feel just right.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: an opt-in GitOps mode for deterministic rendering across both charts.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sfasching

Copy link
Copy Markdown
Author

bump - what's the word on this? I would really like to get plane added to my gitops flow, but the helm chart as it stands today is gitops hostle.

…prise + plane-ce)

Adds a gitops.enabled flag (default false) to both charts. When false they render
byte-for-byte as today. When true, the per-render timestamp pod annotation is
omitted and migration Job names are keyed to planeVersion (instead of a wall-clock
timestamp in plane-enterprise / .Release.Revision in plane-ce), so Argo CD/Flux get
a deterministic render: no perpetual drift and no immutable-Job patch errors.

Relates to makeplane#158, makeplane#206, makeplane#207.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sfasching sfasching force-pushed the gitops-deterministic-rendering branch from 218525e to 3f350da Compare July 9, 2026 04:37

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/plane-ce/templates/workloads/migrator.job.yaml`:
- Line 6: The migrator Job name sanitization only handles dots, pluses, and
casing, so `planeVersion` values with other invalid DNS-1123 characters can
still render an invalid name. Update the name generation in the migrator job
template to normalize all remaining non-[a-z0-9-] characters or otherwise
restrict `planeVersion` to a safe format, using the existing
`planeVersion`/`.Release.Name` branch as the place to fix it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3c179468-b9c0-482d-aaae-f9ef5e945af9

📥 Commits

Reviewing files that changed from the base of the PR and between 218525e and 3f350da.

📒 Files selected for processing (31)
  • charts/plane-ce/templates/workloads/admin.deployment.yaml
  • charts/plane-ce/templates/workloads/api.deployment.yaml
  • charts/plane-ce/templates/workloads/beat-worker.deployment.yaml
  • charts/plane-ce/templates/workloads/live.deployment.yaml
  • charts/plane-ce/templates/workloads/migrator.job.yaml
  • charts/plane-ce/templates/workloads/minio.stateful.yaml
  • charts/plane-ce/templates/workloads/space.deployment.yaml
  • charts/plane-ce/templates/workloads/web.deployment.yaml
  • charts/plane-ce/templates/workloads/worker.deployment.yaml
  • charts/plane-ce/values.yaml
  • charts/plane-enterprise/templates/workloads/admin.deployment.yaml
  • charts/plane-enterprise/templates/workloads/api.deployment.yaml
  • charts/plane-enterprise/templates/workloads/automation-consumer.deployment.yaml
  • charts/plane-enterprise/templates/workloads/beat-worker.deployment.yaml
  • charts/plane-enterprise/templates/workloads/email.deployment.yaml
  • charts/plane-enterprise/templates/workloads/iframely.deployment.yaml
  • charts/plane-enterprise/templates/workloads/live.deployment.yaml
  • charts/plane-enterprise/templates/workloads/migrator.job.yaml
  • charts/plane-enterprise/templates/workloads/minio.stateful.yaml
  • charts/plane-enterprise/templates/workloads/monitor.stateful.yaml
  • charts/plane-enterprise/templates/workloads/outbox-poller.deployment.yaml
  • charts/plane-enterprise/templates/workloads/pi-api.deployment.yaml
  • charts/plane-enterprise/templates/workloads/pi-beat.deployment.yaml
  • charts/plane-enterprise/templates/workloads/pi-migrator.job.yaml
  • charts/plane-enterprise/templates/workloads/pi-worker.deployment.yaml
  • charts/plane-enterprise/templates/workloads/runner.deployment.yaml
  • charts/plane-enterprise/templates/workloads/silo.deployment.yaml
  • charts/plane-enterprise/templates/workloads/space.deployment.yaml
  • charts/plane-enterprise/templates/workloads/web.deployment.yaml
  • charts/plane-enterprise/templates/workloads/worker.deployment.yaml
  • charts/plane-enterprise/values.yaml
✅ Files skipped from review due to trivial changes (2)
  • charts/plane-ce/templates/workloads/web.deployment.yaml
  • charts/plane-enterprise/templates/workloads/pi-api.deployment.yaml
🚧 Files skipped from review as they are similar to previous changes (21)
  • charts/plane-enterprise/templates/workloads/pi-worker.deployment.yaml
  • charts/plane-enterprise/templates/workloads/worker.deployment.yaml
  • charts/plane-ce/templates/workloads/api.deployment.yaml
  • charts/plane-enterprise/templates/workloads/outbox-poller.deployment.yaml
  • charts/plane-enterprise/templates/workloads/runner.deployment.yaml
  • charts/plane-ce/templates/workloads/worker.deployment.yaml
  • charts/plane-ce/templates/workloads/space.deployment.yaml
  • charts/plane-enterprise/templates/workloads/pi-migrator.job.yaml
  • charts/plane-enterprise/templates/workloads/monitor.stateful.yaml
  • charts/plane-enterprise/templates/workloads/pi-beat.deployment.yaml
  • charts/plane-ce/templates/workloads/live.deployment.yaml
  • charts/plane-enterprise/templates/workloads/iframely.deployment.yaml
  • charts/plane-ce/values.yaml
  • charts/plane-ce/templates/workloads/minio.stateful.yaml
  • charts/plane-ce/templates/workloads/admin.deployment.yaml
  • charts/plane-ce/templates/workloads/beat-worker.deployment.yaml
  • charts/plane-enterprise/templates/workloads/beat-worker.deployment.yaml
  • charts/plane-enterprise/templates/workloads/automation-consumer.deployment.yaml
  • charts/plane-enterprise/templates/workloads/silo.deployment.yaml
  • charts/plane-enterprise/templates/workloads/email.deployment.yaml
  • charts/plane-enterprise/values.yaml

metadata:
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}-api-migrate-{{ .Release.Revision }}
name: {{ .Release.Name }}-api-migrate-{{ if $.Values.gitops.enabled }}{{ .Values.planeVersion | replace "." "-" | replace "+" "-" | lower }}{{ else }}{{ .Release.Revision }}{{ end }}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Broaden planeVersion sanitization for the Job name. replace "." "-" | replace "+" "-" | lower still leaves other DNS-1123-invalid characters, so an underscore or space in planeVersion would make the rendered Job name invalid. Normalize the remaining non [a-z0-9-] characters or constrain the accepted version format.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 6-6: syntax error: expected , but found ''

(syntax)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@charts/plane-ce/templates/workloads/migrator.job.yaml` at line 6, The
migrator Job name sanitization only handles dots, pluses, and casing, so
`planeVersion` values with other invalid DNS-1123 characters can still render an
invalid name. Update the name generation in the migrator job template to
normalize all remaining non-[a-z0-9-] characters or otherwise restrict
`planeVersion` to a safe format, using the existing
`planeVersion`/`.Release.Name` branch as the place to fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant