fix: update PVC configuration for worker and webhook pods to prevent …#285
fix: update PVC configuration for worker and webhook pods to prevent …#285chris2k20 wants to merge 1 commit into8gears:mainfrom
Conversation
…RWO multi-attach issues Stopped worker/webhook from auto-mounting the main PVC and added component-specific claims so RWO volumes no longer hit multi-attach errors. -_helpers.tpl: pvc helper now takes an explicit persistence context/claim so each component mounts its own volume. -deployment.yaml, deployment.worker.yaml, deployment.webhook.yaml: pass component persistence configs; worker/webhook use suffix-specific claim names and default to their own emptyDir unless configured otherwise. - pvc.worker.yaml, pvc.webhook.yaml: create dedicated PVCs when worker/webhook persistence is enabled with dynamic provisioning. - values.yaml, README.md: note that worker/webhook storage is separate by default and how to point existingClaim at the main PVC if you really want to share it. - Chart.yaml: bump chart version to 2.0.2 with an artifacthub change note about the PVC fix.
WalkthroughThis PR addresses a Multi-Attach error on RWO PVCs in multi-node clusters by enabling separate persistence volumes for worker and webhook components instead of sharing the main PVC. Each component now has configurable, isolated storage. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~15 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @charts/n8n/templates/_helpers.tpl:
- Around line 65-76: Add a hard validation in the helper that fails template
rendering when persistence is enabled but no valid volume source is configured:
in charts/n8n/templates/_helpers.tpl, check .persistence.enabled and then if
.persistence.existingClaim is empty and .persistence.type is neither "dynamic"
nor "emptyDir" call Helm's fail with a clear error message referencing n8n.pvc
and the expected fields (e.g. require either existingClaim or type:
dynamic/emptyDir); place this guard before the existing volume selection logic
that uses $persistence, $claimName, .persistence.existingClaim and
.persistence.type so an invalid combination stops rendering with a helpful
message.
In @charts/n8n/templates/pvc.webhook.yaml:
- Around line 1-30: The annotations loop in the PersistentVolumeClaim template
uses {{ $key }}: {{ $value }} which can render non-string types and cause K8s
errors; update the annotations block (the loop over
.Values.webhook.persistence.annotations in pvc.webhook.yaml that lives alongside
the include "n8n.fullname" usage) to emit quoted string values, e.g. produce {{
$key }}: {{ $value | quote }}, ensuring annotation values are always strings
(mirror the same fix applied to the worker PVC template).
In @charts/n8n/templates/pvc.worker.yaml:
- Around line 1-30: The metadata annotations block in the PVC template can emit
non-string YAML; update the annotations range in the PersistentVolumeClaim
template so each annotation value is rendered as a string (e.g., pipe the value
through Helm's quote function) instead of printing raw {{ $value }}; target the
annotations loop that currently uses {{- range $key, $value := . }} and change
the value rendering to use a string-quoting helper (e.g., {{ $value | quote }})
so Kubernetes receives map[string]string values.
🧹 Nitpick comments (2)
README.md (1)
397-400: Docs look good; consider adding the default main PVC name to reduce guesswork.Right now users are told “point
existingClaimto the main PVC name”, but not what that name usually is (it varies withfullnameOverride, but you can still mention the default pattern).Also applies to: 585-588
charts/n8n/Chart.yaml (1)
3-4: ArtifactHub note: consider explicitly calling out the behavior change + how to keep sharing the main PVC.This will help users who upgrade and then wonder why worker/webhook no longer see the main data unless they set
existingClaim.Possible wording tweak
artifacthub.io/changes: | - kind: fixed - description: "Workers and webhooks now use their own PVC configuration instead of always mounting the main PVC, preventing RWO multi-attach issues" + description: "Workers and webhooks no longer mount the main PVC by default (prevents RWO multi-attach). To share storage, set worker/webhook.persistence.existingClaim to the main PVC."Also applies to: 37-38
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
README.mdcharts/n8n/Chart.yamlcharts/n8n/templates/_helpers.tplcharts/n8n/templates/deployment.webhook.yamlcharts/n8n/templates/deployment.worker.yamlcharts/n8n/templates/deployment.yamlcharts/n8n/templates/pvc.webhook.yamlcharts/n8n/templates/pvc.worker.yamlcharts/n8n/values.yaml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-02T08:05:39.372Z
Learnt from: tsch157
Repo: 8gears/n8n-helm-chart PR: 239
File: charts/n8n/Chart.yaml:3-4
Timestamp: 2025-09-02T08:05:39.372Z
Learning: n8n 1.110.0 is a pre-release version and should not be used in production deployments. Always verify if a version is stable before recommending upgrades in the n8n Helm chart.
Applied to files:
charts/n8n/Chart.yaml
🪛 YAMLlint (1.37.1)
charts/n8n/templates/pvc.webhook.yaml
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
charts/n8n/templates/pvc.worker.yaml
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
🔇 Additional comments (6)
charts/n8n/values.yaml (1)
296-299: Docs addition is clear and aligns with the PVC multi-attach fix.Also applies to: 484-487
charts/n8n/templates/deployment.yaml (1)
123-125: Alln8n.pvcinclude call sites have been properly migrated to the new calling convention.Verification confirms that all three call sites (deployment.yaml:124, deployment.webhook.yaml:143, and deployment.worker.yaml:139) use the new dict-based signature with
"root"and"persistence"parameters. No old-style calls remain.charts/n8n/templates/deployment.webhook.yaml (1)
141-146: Verifyn8n.pvcinclude output indentation & dict contract (root/persistence/claimName).Line 143 now passes a dict; please ensure the helper is updated accordingly and emits correctly-indented YAML when embedded under
- name: data(otherwise rendered manifests can break). Also confirm the computed claim name matchespvc.webhook.yaml(<fullname>-webhook).charts/n8n/templates/pvc.worker.yaml (1)
1-1: YAMLlint “syntax error at Line 1” likely due to linting raw Helm templates—verify pipeline config.Because the file starts with
{{- ... }}, yamllint will fail if it’s run directly on templates. If this is real in CI, consider ignoringcharts/**/templates/**in yamllint or lintinghelm templateoutput instead.charts/n8n/templates/pvc.webhook.yaml (1)
1-1: YAMLlint “syntax error at Line 1” likely due to linting raw Helm templates—verify pipeline config.charts/n8n/templates/deployment.worker.yaml (1)
137-142: Verifyn8n.pvcinclude output indentation & claimName alignment with worker PVC.Line 139 now passes
persistence: .Values.worker.persistenceandclaimName: <fullname>-worker; confirm the helper selectsemptyDirwhen worker persistence is disabled (to match the always-present volumeMount) and that dynamic provisioning aligns withpvc.worker.yaml.
| {{- $persistence := .persistence -}} | ||
| {{- $root := .root -}} | ||
| {{- $claimName := default (include "n8n.fullname" $root) .claimName -}} | ||
| {{- if or (not $persistence.enabled) (eq $persistence.type "emptyDir") -}} | ||
| emptyDir: {} | ||
| {{- else if and .Values.main.persistence.enabled .Values.main.persistence.existingClaim -}} | ||
| {{- else if and $persistence.enabled $persistence.existingClaim -}} | ||
| persistentVolumeClaim: | ||
| claimName: {{ .Values.main.persistence.existingClaim }} | ||
| {{- else if and .Values.main.persistence.enabled (eq .Values.main.persistence.type "dynamic") -}} | ||
| claimName: {{ $persistence.existingClaim }} | ||
| {{- else if and $persistence.enabled (eq $persistence.type "dynamic") -}} | ||
| persistentVolumeClaim: | ||
| claimName: {{ include "n8n.fullname" . }} | ||
| claimName: {{ $claimName }} | ||
| {{- end }} |
There was a problem hiding this comment.
Add hard validation in n8n.pvc to avoid rendering an invalid volumes entry on misconfiguration.
Right now, enabled: true + missing existingClaim + non-dynamic type will render no volume source (only name: in the caller), which becomes an invalid PodSpec at apply time.
Proposed fix (fail fast with clear errors)
{{/* PVC existing, emptyDir, Dynamic */}}
{{- define "n8n.pvc" -}}
-{{- $persistence := .persistence -}}
-{{- $root := .root -}}
+{{- $persistence := required "n8n.pvc: missing required key .persistence" .persistence -}}
+{{- $root := required "n8n.pvc: missing required key .root" .root -}}
{{- $claimName := default (include "n8n.fullname" $root) .claimName -}}
{{- if or (not $persistence.enabled) (eq $persistence.type "emptyDir") -}}
emptyDir: {}
{{- else if and $persistence.enabled $persistence.existingClaim -}}
persistentVolumeClaim:
claimName: {{ $persistence.existingClaim }}
{{- else if and $persistence.enabled (eq $persistence.type "dynamic") -}}
persistentVolumeClaim:
claimName: {{ $claimName }}
+{{- else -}}
+{{- fail (printf "persistence.enabled=true but no volume source matched (type=%v, existingClaim=%v). Set persistence.type=dynamic or set persistence.existingClaim." $persistence.type $persistence.existingClaim) -}}
{{- end }}
{{- end }}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {{- $persistence := .persistence -}} | |
| {{- $root := .root -}} | |
| {{- $claimName := default (include "n8n.fullname" $root) .claimName -}} | |
| {{- if or (not $persistence.enabled) (eq $persistence.type "emptyDir") -}} | |
| emptyDir: {} | |
| {{- else if and .Values.main.persistence.enabled .Values.main.persistence.existingClaim -}} | |
| {{- else if and $persistence.enabled $persistence.existingClaim -}} | |
| persistentVolumeClaim: | |
| claimName: {{ .Values.main.persistence.existingClaim }} | |
| {{- else if and .Values.main.persistence.enabled (eq .Values.main.persistence.type "dynamic") -}} | |
| claimName: {{ $persistence.existingClaim }} | |
| {{- else if and $persistence.enabled (eq $persistence.type "dynamic") -}} | |
| persistentVolumeClaim: | |
| claimName: {{ include "n8n.fullname" . }} | |
| claimName: {{ $claimName }} | |
| {{- end }} | |
| {{/* PVC existing, emptyDir, Dynamic */}} | |
| {{- define "n8n.pvc" -}} | |
| {{- $persistence := required "n8n.pvc: missing required key .persistence" .persistence -}} | |
| {{- $root := required "n8n.pvc: missing required key .root" .root -}} | |
| {{- $claimName := default (include "n8n.fullname" $root) .claimName -}} | |
| {{- if or (not $persistence.enabled) (eq $persistence.type "emptyDir") -}} | |
| emptyDir: {} | |
| {{- else if and $persistence.enabled $persistence.existingClaim -}} | |
| persistentVolumeClaim: | |
| claimName: {{ $persistence.existingClaim }} | |
| {{- else if and $persistence.enabled (eq $persistence.type "dynamic") -}} | |
| persistentVolumeClaim: | |
| claimName: {{ $claimName }} | |
| {{- else -}} | |
| {{- fail (printf "persistence.enabled=true but no volume source matched (type=%v, existingClaim=%v). Set persistence.type=dynamic or set persistence.existingClaim." $persistence.type $persistence.existingClaim) -}} | |
| {{- end }} | |
| {{- end }} |
🤖 Prompt for AI Agents
In @charts/n8n/templates/_helpers.tpl around lines 65 - 76, Add a hard
validation in the helper that fails template rendering when persistence is
enabled but no valid volume source is configured: in
charts/n8n/templates/_helpers.tpl, check .persistence.enabled and then if
.persistence.existingClaim is empty and .persistence.type is neither "dynamic"
nor "emptyDir" call Helm's fail with a clear error message referencing n8n.pvc
and the expected fields (e.g. require either existingClaim or type:
dynamic/emptyDir); place this guard before the existing volume selection logic
that uses $persistence, $claimName, .persistence.existingClaim and
.persistence.type so an invalid combination stops rendering with a helpful
message.
| {{- if and .Values.webhook.enabled .Values.webhook.persistence.enabled (not .Values.webhook.persistence.existingClaim) (eq .Values.webhook.persistence.type "dynamic") }} | ||
| apiVersion: v1 | ||
| kind: PersistentVolumeClaim | ||
| metadata: | ||
| name: {{ include "n8n.fullname" . }}-webhook | ||
| namespace: {{ .Release.Namespace }} | ||
| {{- with .Values.webhook.persistence.annotations }} | ||
| annotations: | ||
| {{- range $key, $value := . }} | ||
| {{ $key }}: {{ $value }} | ||
| {{- end }} | ||
| {{- end }} | ||
| labels: | ||
| {{- include "n8n.labels" . | nindent 4 }} | ||
| spec: | ||
| accessModes: | ||
| {{- range .Values.webhook.persistence.accessModes }} | ||
| - {{ . | quote }} | ||
| {{- end }} | ||
| resources: | ||
| requests: | ||
| storage: {{ .Values.webhook.persistence.size }} | ||
| {{- if .Values.webhook.persistence.storageClass }} | ||
| {{- if eq "-" .Values.webhook.persistence.storageClass }} | ||
| storageClassName: "" | ||
| {{- else }} | ||
| storageClassName: {{ .Values.webhook.persistence.storageClass }} | ||
| {{- end }} | ||
| {{- end }} | ||
| {{- end }} |
There was a problem hiding this comment.
Quote annotation values to avoid K8s type errors (annotations are string-only).
Lines 7-12 have the same string-only annotations risk as the worker PVC template.
Proposed fix
{{- with .Values.webhook.persistence.annotations }}
annotations:
{{- range $key, $value := . }}
- {{ $key }}: {{ $value }}
+ {{ $key }}: {{ $value | toString | quote }}
{{- end }}
{{- end }}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {{- if and .Values.webhook.enabled .Values.webhook.persistence.enabled (not .Values.webhook.persistence.existingClaim) (eq .Values.webhook.persistence.type "dynamic") }} | |
| apiVersion: v1 | |
| kind: PersistentVolumeClaim | |
| metadata: | |
| name: {{ include "n8n.fullname" . }}-webhook | |
| namespace: {{ .Release.Namespace }} | |
| {{- with .Values.webhook.persistence.annotations }} | |
| annotations: | |
| {{- range $key, $value := . }} | |
| {{ $key }}: {{ $value }} | |
| {{- end }} | |
| {{- end }} | |
| labels: | |
| {{- include "n8n.labels" . | nindent 4 }} | |
| spec: | |
| accessModes: | |
| {{- range .Values.webhook.persistence.accessModes }} | |
| - {{ . | quote }} | |
| {{- end }} | |
| resources: | |
| requests: | |
| storage: {{ .Values.webhook.persistence.size }} | |
| {{- if .Values.webhook.persistence.storageClass }} | |
| {{- if eq "-" .Values.webhook.persistence.storageClass }} | |
| storageClassName: "" | |
| {{- else }} | |
| storageClassName: {{ .Values.webhook.persistence.storageClass }} | |
| {{- end }} | |
| {{- end }} | |
| {{- end }} | |
| {{- if and .Values.webhook.enabled .Values.webhook.persistence.enabled (not .Values.webhook.persistence.existingClaim) (eq .Values.webhook.persistence.type "dynamic") }} | |
| apiVersion: v1 | |
| kind: PersistentVolumeClaim | |
| metadata: | |
| name: {{ include "n8n.fullname" . }}-webhook | |
| namespace: {{ .Release.Namespace }} | |
| {{- with .Values.webhook.persistence.annotations }} | |
| annotations: | |
| {{- range $key, $value := . }} | |
| {{ $key }}: {{ $value | toString | quote }} | |
| {{- end }} | |
| {{- end }} | |
| labels: | |
| {{- include "n8n.labels" . | nindent 4 }} | |
| spec: | |
| accessModes: | |
| {{- range .Values.webhook.persistence.accessModes }} | |
| - {{ . | quote }} | |
| {{- end }} | |
| resources: | |
| requests: | |
| storage: {{ .Values.webhook.persistence.size }} | |
| {{- if .Values.webhook.persistence.storageClass }} | |
| {{- if eq "-" .Values.webhook.persistence.storageClass }} | |
| storageClassName: "" | |
| {{- else }} | |
| storageClassName: {{ .Values.webhook.persistence.storageClass }} | |
| {{- end }} | |
| {{- end }} | |
| {{- end }} |
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
🤖 Prompt for AI Agents
In @charts/n8n/templates/pvc.webhook.yaml around lines 1 - 30, The annotations
loop in the PersistentVolumeClaim template uses {{ $key }}: {{ $value }} which
can render non-string types and cause K8s errors; update the annotations block
(the loop over .Values.webhook.persistence.annotations in pvc.webhook.yaml that
lives alongside the include "n8n.fullname" usage) to emit quoted string values,
e.g. produce {{ $key }}: {{ $value | quote }}, ensuring annotation values are
always strings (mirror the same fix applied to the worker PVC template).
| {{- if and .Values.worker.enabled .Values.worker.persistence.enabled (not .Values.worker.persistence.existingClaim) (eq .Values.worker.persistence.type "dynamic") }} | ||
| apiVersion: v1 | ||
| kind: PersistentVolumeClaim | ||
| metadata: | ||
| name: {{ include "n8n.fullname" . }}-worker | ||
| namespace: {{ .Release.Namespace }} | ||
| {{- with .Values.worker.persistence.annotations }} | ||
| annotations: | ||
| {{- range $key, $value := . }} | ||
| {{ $key }}: {{ $value }} | ||
| {{- end }} | ||
| {{- end }} | ||
| labels: | ||
| {{- include "n8n.labels" . | nindent 4 }} | ||
| spec: | ||
| accessModes: | ||
| {{- range .Values.worker.persistence.accessModes }} | ||
| - {{ . | quote }} | ||
| {{- end }} | ||
| resources: | ||
| requests: | ||
| storage: {{ .Values.worker.persistence.size }} | ||
| {{- if .Values.worker.persistence.storageClass }} | ||
| {{- if eq "-" .Values.worker.persistence.storageClass }} | ||
| storageClassName: "" | ||
| {{- else }} | ||
| storageClassName: {{ .Values.worker.persistence.storageClass }} | ||
| {{- end }} | ||
| {{- end }} | ||
| {{- end }} |
There was a problem hiding this comment.
Quote annotation values to avoid K8s type errors (annotations are string-only).
Lines 7-12 render raw values; if a user supplies a non-string (e.g., true, 123) Helm will emit non-string YAML and Kubernetes can reject it (metadata.annotations is map[string]string).
Proposed fix
{{- with .Values.worker.persistence.annotations }}
annotations:
{{- range $key, $value := . }}
- {{ $key }}: {{ $value }}
+ {{ $key }}: {{ $value | toString | quote }}
{{- end }}
{{- end }}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| {{- if and .Values.worker.enabled .Values.worker.persistence.enabled (not .Values.worker.persistence.existingClaim) (eq .Values.worker.persistence.type "dynamic") }} | |
| apiVersion: v1 | |
| kind: PersistentVolumeClaim | |
| metadata: | |
| name: {{ include "n8n.fullname" . }}-worker | |
| namespace: {{ .Release.Namespace }} | |
| {{- with .Values.worker.persistence.annotations }} | |
| annotations: | |
| {{- range $key, $value := . }} | |
| {{ $key }}: {{ $value }} | |
| {{- end }} | |
| {{- end }} | |
| labels: | |
| {{- include "n8n.labels" . | nindent 4 }} | |
| spec: | |
| accessModes: | |
| {{- range .Values.worker.persistence.accessModes }} | |
| - {{ . | quote }} | |
| {{- end }} | |
| resources: | |
| requests: | |
| storage: {{ .Values.worker.persistence.size }} | |
| {{- if .Values.worker.persistence.storageClass }} | |
| {{- if eq "-" .Values.worker.persistence.storageClass }} | |
| storageClassName: "" | |
| {{- else }} | |
| storageClassName: {{ .Values.worker.persistence.storageClass }} | |
| {{- end }} | |
| {{- end }} | |
| {{- end }} | |
| {{- if and .Values.worker.enabled .Values.worker.persistence.enabled (not .Values.worker.persistence.existingClaim) (eq .Values.worker.persistence.type "dynamic") }} | |
| apiVersion: v1 | |
| kind: PersistentVolumeClaim | |
| metadata: | |
| name: {{ include "n8n.fullname" . }}-worker | |
| namespace: {{ .Release.Namespace }} | |
| {{- with .Values.worker.persistence.annotations }} | |
| annotations: | |
| {{- range $key, $value := . }} | |
| {{ $key }}: {{ $value | toString | quote }} | |
| {{- end }} | |
| {{- end }} | |
| labels: | |
| {{- include "n8n.labels" . | nindent 4 }} | |
| spec: | |
| accessModes: | |
| {{- range .Values.worker.persistence.accessModes }} | |
| - {{ . | quote }} | |
| {{- end }} | |
| resources: | |
| requests: | |
| storage: {{ .Values.worker.persistence.size }} | |
| {{- if .Values.worker.persistence.storageClass }} | |
| {{- if eq "-" .Values.worker.persistence.storageClass }} | |
| storageClassName: "" | |
| {{- else }} | |
| storageClassName: {{ .Values.worker.persistence.storageClass }} | |
| {{- end }} | |
| {{- end }} | |
| {{- end }} |
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 1-1: syntax error: expected the node content, but found '-'
(syntax)
🤖 Prompt for AI Agents
In @charts/n8n/templates/pvc.worker.yaml around lines 1 - 30, The metadata
annotations block in the PVC template can emit non-string YAML; update the
annotations range in the PersistentVolumeClaim template so each annotation value
is rendered as a string (e.g., pipe the value through Helm's quote function)
instead of printing raw {{ $value }}; target the annotations loop that currently
uses {{- range $key, $value := . }} and change the value rendering to use a
string-quoting helper (e.g., {{ $value | quote }}) so Kubernetes receives
map[string]string values.
…RWO multi-attach issues
Stopped worker/webhook from auto-mounting the main PVC and added component-specific claims so RWO volumes no longer hit multi-attach errors.
-_helpers.tpl: pvc helper now takes an explicit persistence context/claim so each component mounts its own volume.
-deployment.yaml, deployment.worker.yaml, deployment.webhook.yaml: pass component persistence configs; worker/webhook use suffix-specific claim names and default to their own emptyDir unless configured otherwise.
What this PR does / why we need it
Fixes RWO multi-attach errors by stopping worker/webhook from auto-mounting the main PVC and giving each component its own persistence wiring/claims.
Adds component-specific PVC templates and updates mounts to use per-component claims (or an explicitly provided existingClaim).
Documents the new defaults and bumps the chart to 2.0.2 with an ArtifactHub entry describing the fix.
Which issue this PR fixes
Which issue this PR fixes
fixes #280
Special notes for your reviewer
Checklist
Please place an 'x' in all applicable fields and remove unrelated items.
Version and Documentation
Chart.yamlfollowing semantic versioningChart.yamlif applicableartifacthub.io/changessection updated inChart.yaml(see ArtifactHub annotation reference)README.mdTesting and Validation
ah lintlocally without errorsct lint --chart-dirs charts/n8n --charts charts/n8n --validate-maintainers=false/examplesdirectorySummary by CodeRabbit
Bug Fixes
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.