Skip to content

feat: add promtool check to preview - #43

Merged
HahaSula merged 6 commits into
mainfrom
feat-preview-promtool-check
Jul 6, 2026
Merged

feat: add promtool check to preview#43
HahaSula merged 6 commits into
mainfrom
feat-preview-promtool-check

Conversation

@HahaSula

@HahaSula HahaSula commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Refs #38

Adds promtool validation to the Preview flow so rendered PrometheusRule YAML is checked before it is shown to the user.

  • Parse rendered Helm YAML and collect PrometheusRule.spec.groups
  • Write extracted groups to a temporary rules file
  • Run promtool check rules from the server-side render route
  • Return check status with Preview response without blocking render output
  • Display promtool pass/fail/skipped state in the Preview modal
  • Include promtool in the runtime Docker image from a pinned Prometheus image

Behavior

  • If rendered YAML contains PrometheusRule resources, Preview runs promtool check rules
  • If promtool finds rule errors, Preview still opens and shows the rendered YAML plus the promtool error
  • If no PrometheusRule resources are rendered, the check is skipped
  • If promtool is missing while PrometheusRule resources exist, the check fails because runtime images are expected to include promtool

Validation

  • npm run lint
  • npm run build
  • npm test -- tests/integration/render-api.test.js

Notes

Full npm test still has one existing locale-sensitive failure unrelated to this change:

  • tests/unit/git-lib.test.js
  • expected English git output containing On branch
  • current environment returns Chinese output: 位於分支 master

Summary by CodeRabbit

  • New Features
    • Render previews now validate rendered PrometheusRule YAML via Promtool and show clear pass/fail/skipped status.
    • Preview displays Promtool output details when available.
  • Bug Fixes
    • Improved render API error responses with consistent JSON output.
    • Validation results are handled for cases like invalid PrometheusRule content, no rules found, or Promtool not available.
    • Chart dependency handling now uses dependency update to avoid leftover artifacts.
  • Chores
    • Updated the runtime image to include Promtool, with a configurable Prometheus version.

@rophy

rophy commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

PR Preview Bot

Preview environment torn down.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d074a11-f930-4aea-bc49-6d3f39f48008

📥 Commits

Reviewing files that changed from the base of the PR and between 237787d and cbdb4f3.

📒 Files selected for processing (1)
  • server/routes/render.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/routes/render.js

📝 Walkthrough

Walkthrough

This PR adds promtool to the runtime image, validates rendered PrometheusRule resources during render, shows the check result in the preview UI, and expands integration tests for success, failure, and missing-binary cases.

Changes

Promtool Validation Feature

Layer / File(s) Summary
Docker image: promtool binary install
Dockerfile
Adds PROMETHEUS_VERSION, a prometheus build stage, and copies promtool into the final runtime image.
Render route: rule validation logic
server/routes/render.js
Adds helpers for command execution and PrometheusRule extraction, runs promtool check rules on rendered output, and returns the check result from the render endpoint.
Preview UI: display check result
src/pages/AlertUserView.jsx
Stores preview check results and renders an Alert banner in the PrometheusRule preview modal.
Integration tests for promtool check flow
tests/integration/render-api.test.js
Adds fake helm/promtool binaries and coverage for successful, failing, and unavailable promtool checks plus helm dependency update execution.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant RenderRoute
  participant Helm
  participant Promtool

  Client->>RenderRoute: POST /api/v2/render/:chart/:deployment
  RenderRoute->>Helm: helm dependency update
  RenderRoute->>Helm: helm template
  Helm-->>RenderRoute: rendered YAML output
  RenderRoute->>RenderRoute: extractPrometheusRuleGroups(output)
  RenderRoute->>Promtool: promtool check rules (temp rules.yaml)
  Promtool-->>RenderRoute: check result (passed/errors/output)
  RenderRoute-->>Client: { ok, output, check }
Loading

Possibly related issues

Possibly related PRs

  • null-ptr-exception/ruleMgmt#27: Modifies the same POST /:chart/:deployment route in server/routes/render.js, so it overlaps at the render-handler level.

Suggested reviewers: rophy

🚥 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 clearly summarizes the main change: adding promtool checks to the preview flow.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-preview-promtool-check

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.

@HahaSula
HahaSula marked this pull request as ready for review July 1, 2026 09:54

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Dockerfile (1)

13-25: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Run the runtime image as a non-root user.

The final stage still starts as root. This PR adds more file/process activity (helm, promtool, temp files) to the request path, so any server-side compromise inherits full container privileges. Drop to USER node (or a dedicated user) after the installs/copies and fix ownership on /app as needed.

Possible hardening change
 FROM node:22-alpine
 
 RUN apk add --no-cache git helm
 
 WORKDIR /app
@@
 COPY server/ ./server/
 COPY sample/ ./sample/
 COPY index.html ./
+RUN chown -R node:node /app
+
+USER node
 
 EXPOSE 8080
 ENV PORT=8080
 CMD ["node", "server.js"]
🤖 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 `@Dockerfile` around lines 13 - 25, The final runtime stage in the Dockerfile
still runs as root; update the image to drop privileges after the package
installs and copy steps by switching to a non-root user such as node. Make sure
the /app workdir and any copied artifacts used by the app (including dist and
promtool) have the correct ownership/permissions before the USER change so the
container can run normally without root.

Source: Linters/SAST tools

🤖 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 `@server/routes/render.js`:
- Line 118: The preview path in render.js is mutating the live chart checkout
because runCommand(helm, ['dependency', 'build', templateDir], ...) writes into
req.gitopsDir. Update the Helm flow in the preview handler so it operates on a
temporary copy of the chart or uses a prebuilt dependency directory instead of
templateDir from the live repo. Keep the fix localized around the preview
command path in render.js and preserve the read-only behavior of the request.

---

Outside diff comments:
In `@Dockerfile`:
- Around line 13-25: The final runtime stage in the Dockerfile still runs as
root; update the image to drop privileges after the package installs and copy
steps by switching to a non-root user such as node. Make sure the /app workdir
and any copied artifacts used by the app (including dist and promtool) have the
correct ownership/permissions before the USER change so the container can run
normally without root.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 43780962-101b-47df-bede-7ebbe33b7768

📥 Commits

Reviewing files that changed from the base of the PR and between 0c3f166 and a8bf2d9.

📒 Files selected for processing (4)
  • Dockerfile
  • server/routes/render.js
  • src/pages/AlertUserView.jsx
  • tests/integration/render-api.test.js

Comment thread server/routes/render.js Outdated
@HahaSula
HahaSula force-pushed the feat-preview-promtool-check branch from a8bf2d9 to 1cfb92d Compare July 2, 2026 04:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
server/routes/render.js (1)

35-52: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Full recursive repo copy on every preview request.

copyGitopsDirToTemp now correctly resolves the previously-flagged issue of helm dependency build mutating the live checkout — good fix. However, it does a full recursive fs.cp of the entire req.gitopsDir (minus .git/node_modules/__pycache__) on every render/preview call, then discards it. For a gitops repo with many charts/deployments this is an expensive I/O operation on a hot, frequently-invoked path, and cost scales with total repo size rather than with the size of the specific chart being previewed.

Consider narrowing the copy to just the chart/deployment subtree actually needed (chartDir/templateDir plus any local file:// chart dependencies), or caching/reusing a synced working copy instead of a fresh full copy per request.

Also applies to: 128-150

🤖 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 `@server/routes/render.js` around lines 35 - 52, The full recursive repo copy
in copyGitopsDirToTemp is too expensive for the render/preview hot path because
it clones the entire gitops checkout on every request. Update the render flow in
server/routes/render.js to avoid fs.cp of req.gitopsDir wholesale; instead copy
only the chart/deployment subtree needed by the preview (the
chartDir/templateDir and any local file:// dependencies), or reuse a cached
synced working copy across requests. Keep copyGitopsDirToTemp focused on the
minimal needed workspace and ensure the callers still receive a valid
copiedGitopsDir.
src/pages/AlertUserView.jsx (1)

369-381: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Bound the promtool output height like the YAML preview.

The main rendered-YAML <pre> below (Line 382-388) has maxHeight: 500, overflow: 'auto', but the promtool output <pre> inside the Alert description has no height bound. Large promtool output could push the modal well beyond the viewport.

💚 Suggested fix
                     previewCheck.output
-                      ? <pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>{previewCheck.output}</pre>
+                      ? <pre style={{ margin: 0, whiteSpace: 'pre-wrap', wordBreak: 'break-word', maxHeight: 200, overflow: 'auto' }}>{previewCheck.output}</pre>
                       : null
🤖 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 `@src/pages/AlertUserView.jsx` around lines 369 - 381, The promtool output
rendered in the AlertUserView preview is unbounded and can expand the modal too
far. Update the previewCheck Alert description’s <pre> block to match the
rendered YAML preview behavior by adding a max height and scroll overflow so
large promtool output stays contained. Use the existing previewCheck conditional
render in AlertUserView and keep the same word-wrapping behavior while bounding
the display area.
🤖 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.

Nitpick comments:
In `@server/routes/render.js`:
- Around line 35-52: The full recursive repo copy in copyGitopsDirToTemp is too
expensive for the render/preview hot path because it clones the entire gitops
checkout on every request. Update the render flow in server/routes/render.js to
avoid fs.cp of req.gitopsDir wholesale; instead copy only the chart/deployment
subtree needed by the preview (the chartDir/templateDir and any local file://
dependencies), or reuse a cached synced working copy across requests. Keep
copyGitopsDirToTemp focused on the minimal needed workspace and ensure the
callers still receive a valid copiedGitopsDir.

In `@src/pages/AlertUserView.jsx`:
- Around line 369-381: The promtool output rendered in the AlertUserView preview
is unbounded and can expand the modal too far. Update the previewCheck Alert
description’s <pre> block to match the rendered YAML preview behavior by adding
a max height and scroll overflow so large promtool output stays contained. Use
the existing previewCheck conditional render in AlertUserView and keep the same
word-wrapping behavior while bounding the display area.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a447e623-aa28-4269-b9a6-2948d5d10a9c

📥 Commits

Reviewing files that changed from the base of the PR and between a8bf2d9 and 1cfb92d.

📒 Files selected for processing (4)
  • Dockerfile
  • server/routes/render.js
  • src/pages/AlertUserView.jsx
  • tests/integration/render-api.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • Dockerfile

HahaSula and others added 3 commits July 2, 2026 12:41
The full gitops copy added for CodeRabbit's mutation finding re-litigated
a decision this project already made: #29 raised the same pollution
problem, PR #30's temp-dir mirror was closed as over-engineered, and
PR #31 settled it — the gitops repo's own .gitignore keeps Chart.lock
and charts/*.tgz out of version control (doc/gitops-repo-setup.md).
Copying the whole repo per render also scaled preview latency with repo
size and was the root cause of the flaky e2e preview timeout on CI.

Switching build → update fixes a latent bug that predates this PR:
helm dependency build hard-errors on a stale on-disk Chart.lock ("lock
file out of sync") as soon as a chart version is bumped, breaking
Preview for every previously-rendered deployment. update re-resolves
each time — the lock has no pinning value for same-repo file://
dependencies — and prunes outdated .tgz files as a side effect.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@server/routes/render.js`:
- Around line 128-132: The `helm template` invocation in `render.js` can exceed
the default `execFile` buffer and fail on large charts. Update the
`runCommand(helm, templateArgs, ...)` call to pass a larger `maxBuffer` so
`stdout` can be captured reliably; if `checkPrometheusRules` can also emit large
output through `runCommand`, apply the same buffer increase there as well.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f484e4e7-f536-42b2-96f4-5265643b274a

📥 Commits

Reviewing files that changed from the base of the PR and between 1cfb92d and 237787d.

📒 Files selected for processing (3)
  • server/routes/render.js
  • src/pages/AlertUserView.jsx
  • tests/integration/render-api.test.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/AlertUserView.jsx

Comment thread server/routes/render.js
rophy
rophy previously approved these changes Jul 5, 2026

@rophy rophy 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.

Clean, well-tested PR. Promtool integration is solid — good error handling, proper temp-dir cleanup, and the fake-helm/fake-promtool test setup is well done.

execFile's default maxBuffer is 1MiB, so a large chart render or rule
set could fail with ERR_CHILD_PROCESS_STDIO_MAXBUFFER and turn Preview
into { ok: false } instead of returning output.

Addresses CodeRabbit review on #43.
@HahaSula

HahaSula commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in cbdb4f3 — raised maxBuffer to 10MiB on both the helm template and promtool check rules execFile calls.

@HahaSula
HahaSula merged commit 5ab5aee into main Jul 6, 2026
4 checks passed
HahaSula added a commit that referenced this pull request Jul 6, 2026
Bump version from 1.3.0 to 1.4.0 to trigger a new image build and
GitHub Release via CI. Since 1.3.0: deployment sync (#44), alert
overview mode with column filters (#37), promtool validation (#41,
#43), plus several fixes — enough new features to warrant a minor
bump per this project's convention (1.2.0 -> 1.3.0 similarly bumped
minor for the Gitea migration).
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.

2 participants