Skip to content

Comments

feat: add incident detection automation#86

Merged
waltergalvao merged 4 commits intomainfrom
feat/incident-detection
Feb 21, 2026
Merged

feat: add incident detection automation#86
waltergalvao merged 4 commits intomainfrom
feat/incident-detection

Conversation

@waltergalvao
Copy link
Contributor

@waltergalvao waltergalvao commented Feb 21, 2026

Greptile Summary

This PR adds a new automation type for incident detection that automatically tracks production incidents from rollbacks, hotfixes, and reverts. The implementation includes:

  • Database migration and schema updates to add INCIDENT_DETECTION automation type
  • Backend type definitions that now correctly match frontend structure with revert, hotfix, and rollback settings
  • Frontend settings page with form validation for regex patterns used in hotfix detection
  • Shared regex validation utility extracted to validation.provider.ts

The previous type mismatch issues between frontend and backend have been resolved - the backend now uses the flat structure with prTitleRegEx, branchRegEx, and prLabelRegEx fields that match the frontend form.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation is well-structured with proper type definitions, validation, and all previously identified issues have been resolved. The backend and frontend types now align correctly, and the regex validation is properly implemented.
  • No files require special attention

Important Files Changed

Filename Overview
apps/api/src/app/automations/services/automation.types.ts Defines IncidentDetectionSettings interface matching frontend structure with revert, hotfix, and rollback configuration
apps/web/src/app/automations/settings/incident-detection/types.ts Defines Zod schema with regex validation for hotfix detection patterns
apps/web/src/app/automations/settings/incident-detection/page.tsx Implements settings page with form handling, properly loading and saving incident detection configuration
apps/web/src/app/automations/settings/incident-detection/components/form-incident-detection-settings/form-incident-detection-settings.tsx Form component with switches for revert/rollback/hotfix detection and regex input fields for hotfix patterns
apps/web/src/providers/validation.provider.ts Refactored regex validation helper from pr-title-check to shared provider

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User Opens Incident Detection Settings] --> B[AutomationIncidentDetectionPage]
    B --> C[Load Automation Settings]
    C --> D[Initialize Form with Defaults]
    D --> E{Settings Loaded?}
    E -->|Yes| F[Populate Form with Saved Values]
    E -->|No| G[Use Default Values]
    F --> H[FormIncidentDetectionSettings Component]
    G --> H
    H --> I[Display Settings Sections]
    I --> J[Revert Detection Toggle]
    I --> K[Rollback Detection Toggle]
    I --> L[Hotfix Detection Toggle]
    L --> M{Hotfix Enabled?}
    M -->|Yes| N[Show Regex Input Fields]
    N --> O[prTitleRegEx validation]
    N --> P[branchRegEx validation]
    N --> Q[prLabelRegEx validation]
    O --> R[validateRegEx function]
    P --> R
    Q --> R
    M -->|No| S[Hide Regex Fields]
    J --> T[User Clicks Update]
    K --> T
    L --> T
    S --> T
    T --> U[Form Validation via Zod]
    U --> V{Valid?}
    V -->|Yes| W[Send Settings to Backend]
    V -->|No| X[Show Validation Errors]
    W --> Y[IncidentDetectionSettings Saved]
    Y --> Z[Automation Can Detect Incidents]
Loading

Last reviewed commit: 75d84a6

@dev-sweetr-dev dev-sweetr-dev bot added the large Large PR - Consider splitting up into smaller PRs to reduce risk and review time label Feb 21, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 21, 2026

Walkthrough

Adds a new INCIDENT_DETECTION automation type across DB, Prisma, backend types, GraphQL enums, and frontend UI (form, page, routing, and card/layout updates) to support incident-detection settings (revert, rollback, hotfix with regex fields).

Changes

Cohort / File(s) Summary
Database & Prisma
apps/api/prisma/migrations/20260221000000_add_incident_detection_automation_type/migration.sql, apps/api/prisma/schema.prisma
Adds INCIDENT_DETECTION to the PostgreSQL AutomationType enum and Prisma schema.
Backend types & resolvers
apps/api/src/app/automations/resolvers/automations.schema.ts, apps/api/src/app/automations/services/automation.types.ts
Adds AutomationType.INCIDENT_DETECTION, new AutomationIncidentDetection and IncidentDetectionSettings types; updates mappings/unions to include the new automation type.
GraphQL enums
packages/graphql-types/api.ts, packages/graphql-types/frontend/graphql.ts
Adds INCIDENT_DETECTION to the exported AutomationType enums.
Frontend settings types & form
apps/web/src/app/automations/settings/incident-detection/types.ts, apps/web/src/app/automations/settings/incident-detection/components/form-incident-detection-settings/form-incident-detection-settings.tsx, apps/web/src/app/automations/settings/incident-detection/components/form-incident-detection-settings/index.ts
Adds Zod schema FormIncidentDetection, exported type, and a new FormIncidentDetectionSettings React component with toggles for enabled/revert/rollback/hotfix and regex fields.
Page & routing
apps/web/src/app/automations/settings/incident-detection/page.tsx, apps/web/src/routes.tsx
Adds AutomationIncidentDetectionPage and registers route /automations/incident-detection.
Automation cards & config
apps/web/src/app/automations/use-automation-cards.tsx
Introduces INCIDENT_DETECTION card (replacing top-level PR_TITLE_CHECK), reorders/duplicates PR_TITLE_CHECK later, and updates some automation colors/content.
UI layout tweaks
apps/web/src/app/automations/components/card-automation/card-automation.tsx, apps/web/src/app/automations/settings/components/header-automation/header-automation.tsx
Adjusts Card layout spacing/matching and makes ImageDemo render conditional on demoUrl.
Misc imports
apps/web/src/app/automations/settings/pr-title-check/types.ts
Updates import path for validateRegEx to the centralized provider.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~28 minutes

Suggested labels

huge

Suggested reviewers

  • sweetrdev
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'feat: add incident detection automation' clearly and concisely describes the main change—adding a new incident detection automation feature across the codebase.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description comprehensively explains the incident detection automation feature, including database schema updates, backend type definitions, frontend settings page, and resolved type alignment issues.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/incident-detection

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 and usage tips.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 14 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/web/src/app/automations/settings/incident-detection/page.tsx">

<violation number="1" location="apps/web/src/app/automations/settings/incident-detection/page.tsx:82">
P2: Avoid calling `form.validate()` during render to derive `isFormValid`. It sets `form.errors` each time, which triggers extra renders and shows validation errors before the user submits. Use `form.isValid()` (no error state mutation) or move validation to submit.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

}, [automationSettings]);

// eslint-disable-next-line react-hooks/exhaustive-deps
const isFormValid = useMemo(() => !form.validate().hasErrors, [form.values]);
Copy link

@cubic-dev-ai cubic-dev-ai bot Feb 21, 2026

Choose a reason for hiding this comment

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

P2: Avoid calling form.validate() during render to derive isFormValid. It sets form.errors each time, which triggers extra renders and shows validation errors before the user submits. Use form.isValid() (no error state mutation) or move validation to submit.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/web/src/app/automations/settings/incident-detection/page.tsx, line 82:

<comment>Avoid calling `form.validate()` during render to derive `isFormValid`. It sets `form.errors` each time, which triggers extra renders and shows validation errors before the user submits. Use `form.isValid()` (no error state mutation) or move validation to submit.</comment>

<file context>
@@ -0,0 +1,141 @@
+  }, [automationSettings]);
+
+  // eslint-disable-next-line react-hooks/exhaustive-deps
+  const isFormValid = useMemo(() => !form.validate().hasErrors, [form.values]);
+
+  const handleSave: FormEventHandler = async (event) => {
</file context>
Fix with Cubic

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
apps/web/src/app/automations/components/card-automation/card-automation.tsx (1)

48-48: Consider extracting the mih magic number to a named constant.

191 lacks semantic context. A named constant would clarify intent and prevent future drift if the value changes.

♻️ Suggested refactor
+const CARD_CONTENT_MIN_HEIGHT = 191;

 ...

-<Stack gap="md" h="100%" mih={191} justify="space-between">
+<Stack gap="md" h="100%" mih={CARD_CONTENT_MIN_HEIGHT} justify="space-between">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/automations/components/card-automation/card-automation.tsx`
at line 48, The literal 191 used as the Stack prop mih is a magic number;
extract it to a named constant (e.g., AUTOMATION_CARD_MIN_HEIGHT or
CARD_MIN_HEIGHT) near the top of the file or a shared constants module, replace
the inline 191 in the Stack component (Stack gap="md" h="100%" mih={191} ...)
with the constant (mih={AUTOMATION_CARD_MIN_HEIGHT}), and add a brief comment
explaining the constant’s purpose to give semantic context and make future
changes easier.
apps/api/prisma/migrations/20260221000000_add_incident_detection_automation_type/migration.sql (2)

1-2: Consider splitting this migration into a separate PR per project convention.

Based on learnings, this project handles Prisma schema migrations in dedicated PRs, separate from feature implementation. The current PR bundles the migration with the full frontend/backend feature code.

Based on learnings: "In this project, updates to the Prisma schema that require a migration are handled in separate PRs."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/api/prisma/migrations/20260221000000_add_incident_detection_automation_type/migration.sql`
around lines 1 - 2, This migration adds a new enum value via ALTER TYPE
"AutomationType" ADD VALUE 'INCIDENT_DETECTION' in migration.sql; move this
database change into its own PR per project convention by extracting the
migration file (the new migration that contains ALTER TYPE "AutomationType" ADD
VALUE 'INCIDENT_DETECTION') into a separate branch/PR that only contains the
Prisma schema change and generated migration, then rebase the feature branch to
remove that migration so the feature PR contains only application code changes.

2-2: Add IF NOT EXISTS for idempotency.

Without it, retrying the migration after a partial failure (where the ADD VALUE already committed) will throw ERROR: enum label already exists.

♻️ Suggested fix
-ALTER TYPE "AutomationType" ADD VALUE 'INCIDENT_DETECTION';
+ALTER TYPE "AutomationType" ADD VALUE IF NOT EXISTS 'INCIDENT_DETECTION';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/api/prisma/migrations/20260221000000_add_incident_detection_automation_type/migration.sql`
at line 2, Update the enum-add statement to be idempotent: change the ALTER TYPE
"AutomationType" ADD VALUE 'INCIDENT_DETECTION' statement to use IF NOT EXISTS
so the migration won't fail if that label already exists; locate the migration
SQL containing the ALTER TYPE "AutomationType" ADD VALUE 'INCIDENT_DETECTION'
and modify it to include IF NOT EXISTS in the ADD VALUE clause.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api/src/app/automations/services/automation.types.ts`:
- Around line 66-90: The IncidentDetection settings type doesn't match the
frontend contract: update IncidentDetectionSettings (and any usage like
AutomationIncidentDetection) to include a top-level rollback property (matching
frontend `settings.rollback`) and flatten `hotfix` to the fields the frontend
sends (enabled, prTitleRegEx, branchRegEx, prLabelRegEx), or alternatively add a
mapping step where settings payloads are transformed from the frontend shape to
the existing backend shape before persisting/using them; adjust the type
definitions (IncidentDetectionSettings) and any service/handler that
reads/writes these settings to ensure the shape aligns or is converted.

---

Nitpick comments:
In
`@apps/api/prisma/migrations/20260221000000_add_incident_detection_automation_type/migration.sql`:
- Around line 1-2: This migration adds a new enum value via ALTER TYPE
"AutomationType" ADD VALUE 'INCIDENT_DETECTION' in migration.sql; move this
database change into its own PR per project convention by extracting the
migration file (the new migration that contains ALTER TYPE "AutomationType" ADD
VALUE 'INCIDENT_DETECTION') into a separate branch/PR that only contains the
Prisma schema change and generated migration, then rebase the feature branch to
remove that migration so the feature PR contains only application code changes.
- Line 2: Update the enum-add statement to be idempotent: change the ALTER TYPE
"AutomationType" ADD VALUE 'INCIDENT_DETECTION' statement to use IF NOT EXISTS
so the migration won't fail if that label already exists; locate the migration
SQL containing the ALTER TYPE "AutomationType" ADD VALUE 'INCIDENT_DETECTION'
and modify it to include IF NOT EXISTS in the ADD VALUE clause.

In `@apps/web/src/app/automations/components/card-automation/card-automation.tsx`:
- Line 48: The literal 191 used as the Stack prop mih is a magic number; extract
it to a named constant (e.g., AUTOMATION_CARD_MIN_HEIGHT or CARD_MIN_HEIGHT)
near the top of the file or a shared constants module, replace the inline 191 in
the Stack component (Stack gap="md" h="100%" mih={191} ...) with the constant
(mih={AUTOMATION_CARD_MIN_HEIGHT}), and add a brief comment explaining the
constant’s purpose to give semantic context and make future changes easier.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

14 files reviewed, 5 comments

Edit Code Review Agent Settings | Greptile

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 21, 2026
Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

14 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

16 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

coderabbitai[bot]
coderabbitai bot previously requested changes Feb 21, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/app/automations/settings/incident-detection/types.ts`:
- Around line 12-23: The three schema fields prTitleRegEx, branchRegEx, and
prLabelRegEx currently use z.string().refine(validateRegEx, ...).optional() and
therefore accept "" — update each to require a non-empty string before running
validateRegEx by inserting the same guard used elsewhere (e.g., use
stringCantBeEmpty or .min(1)) before .refine and keep .optional() after the
non-empty check; alternatively, if your form sends empty strings and you want
them treated as absent, add a z.preprocess that converts "" to undefined before
validation so empty inputs are either stripped or fail the .min(1) check as
intended.

---

Duplicate comments:
In `@apps/api/src/app/automations/services/automation.types.ts`:
- Around line 72-85: Confirm and align the frontend Zod/schema and TypeScript
types to match the backend IncidentDetectionSettings shape: ensure the frontend
type/schema (look for symbols like incidentDetectionSchema,
IncidentDetectionFormSchema or IncidentDetectionSettings type in files under
incident-detection) defines top-level revert and rollback objects that contain
only an optional enabled?: boolean and no regex fields, and a hotfix object that
contains enabled?: boolean plus prTitleRegEx?: string, branchRegEx?: string,
prLabelRegEx?: string; if mismatches are found, update the frontend types/Zod
schema to this exact structure, update any form serialization or API payload
builders to send that shape, and add or update unit/integration tests to assert
the payload matches IncidentDetectionSettings.

Comment on lines +12 to +23
prTitleRegEx: z
.string()
.refine(validateRegEx, "Invalid regular expression")
.optional(),
branchRegEx: z
.string()
.refine(validateRegEx, "Invalid regular expression")
.optional(),
prLabelRegEx: z
.string()
.refine(validateRegEx, "Invalid regular expression")
.optional(),
Copy link

@coderabbitai coderabbitai bot Feb 21, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Empty string bypasses regex intent — add a .min(1) guard for each optional regex field.

z.string().refine(validateRegEx, ...).optional() only short-circuits for undefined. When a user clears a text input, the form typically submits "", which Zod passes to validateRegEx(""). Because new RegExp("") is a valid (match-everything) regex, it returns true and the empty string reaches the backend — where it would match every PR title, branch name, or label, effectively flagging every PR as a hotfix incident.

The companion pr-title-check/types.ts prevents this via stringCantBeEmpty before the .refine(). Apply the same guard here:

🛡️ Proposed fix — require non-empty value when field is present
-      prTitleRegEx: z
-        .string()
-        .refine(validateRegEx, "Invalid regular expression")
-        .optional(),
-      branchRegEx: z
-        .string()
-        .refine(validateRegEx, "Invalid regular expression")
-        .optional(),
-      prLabelRegEx: z
-        .string()
-        .refine(validateRegEx, "Invalid regular expression")
-        .optional(),
+      prTitleRegEx: z
+        .string()
+        .min(1, "Can't be empty")
+        .refine(validateRegEx, "Invalid regular expression")
+        .optional(),
+      branchRegEx: z
+        .string()
+        .min(1, "Can't be empty")
+        .refine(validateRegEx, "Invalid regular expression")
+        .optional(),
+      prLabelRegEx: z
+        .string()
+        .min(1, "Can't be empty")
+        .refine(validateRegEx, "Invalid regular expression")
+        .optional(),

Note on form submit handling: If your form submits cleared inputs as "" rather than omitting the key, you may also need to strip/transform empty strings to undefined before validation (e.g., via z.preprocess) so that blank fields are treated as absent rather than failing the .min(1) check.

📝 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.

Suggested change
prTitleRegEx: z
.string()
.refine(validateRegEx, "Invalid regular expression")
.optional(),
branchRegEx: z
.string()
.refine(validateRegEx, "Invalid regular expression")
.optional(),
prLabelRegEx: z
.string()
.refine(validateRegEx, "Invalid regular expression")
.optional(),
prTitleRegEx: z
.string()
.min(1, "Can't be empty")
.refine(validateRegEx, "Invalid regular expression")
.optional(),
branchRegEx: z
.string()
.min(1, "Can't be empty")
.refine(validateRegEx, "Invalid regular expression")
.optional(),
prLabelRegEx: z
.string()
.min(1, "Can't be empty")
.refine(validateRegEx, "Invalid regular expression")
.optional(),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/automations/settings/incident-detection/types.ts` around
lines 12 - 23, The three schema fields prTitleRegEx, branchRegEx, and
prLabelRegEx currently use z.string().refine(validateRegEx, ...).optional() and
therefore accept "" — update each to require a non-empty string before running
validateRegEx by inserting the same guard used elsewhere (e.g., use
stringCantBeEmpty or .min(1)) before .refine and keep .optional() after the
non-empty check; alternatively, if your form sends empty strings and you want
them treated as absent, add a z.preprocess that converts "" to undefined before
validation so empty inputs are either stripped or fail the .min(1) check as
intended.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's okay to have empty strings here

Copy link

Choose a reason for hiding this comment

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

@waltergalvao, understood! I'll note that empty strings are acceptable for these regex fields in the incident detection settings.


✏️ Learnings added
Learnt from: waltergalvao
Repo: sweetr-dev/sweetr.dev PR: 86
File: apps/web/src/app/automations/settings/incident-detection/types.ts:12-23
Timestamp: 2026-02-21T06:35:31.854Z
Learning: In the incident detection settings form (`apps/web/src/app/automations/settings/incident-detection/types.ts`), empty strings are intentionally allowed for the optional regex fields (prTitleRegEx, branchRegEx, prLabelRegEx) in the hotfix configuration.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: waltergalvao
Repo: sweetr-dev/sweetr.dev PR: 33
File: apps/api/src/app/workspaces/services/workspace-settings.types.ts:5-11
Timestamp: 2024-12-01T02:31:20.571Z
Learning: You prefer using per-field validation in `zod` schemas (e.g., in `apps/api/src/app/workspaces/services/workspace-settings.types.ts`) over cross-field validation using `.refine()`, to allow displaying validation errors below each input in forms.

@waltergalvao waltergalvao merged commit 2bf1198 into main Feb 21, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

large Large PR - Consider splitting up into smaller PRs to reduce risk and review time

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants