Skip to content

Conversation

@riderx
Copy link
Member

@riderx riderx commented Jan 15, 2026

Summary (AI generated)

Replaced the weak per-device failure notification system with a smarter daily aggregate fail ratio check. Now sends one email per app per day when install failures exceed 30%, instead of one email per device followed by a week-long silence.

Motivation (AI generated)

The old system sent one email on first device failure, then ignored all subsequent failures for a week—a poor signal. The new system uses daily aggregate statistics from the daily_version table to calculate real fail ratios and alert only when the situation is actually critical (30%+ failure rate).

Business Impact (AI generated)

Improves app reliability monitoring by catching genuine issues faster. App owners now get daily insights into failure trends instead of sporadic one-off alerts. Minimum 10 installs prevents noise from small-volume apps.

Test Plan (AI generated)

  • Verify migration runs without errors
  • Confirm cron job runs daily at 08:00 UTC
  • Test email sent when daily fail ratio ≥ 30% and installs ≥ 10
  • Test email NOT sent when below threshold or installs < 10
  • Verify daily_fail_ratio email preference controls delivery
  • Test that old device_error notification is no longer triggered

Generated with AI

Summary by CodeRabbit

  • New Features

    • Daily fail-ratio email summaries for apps, scheduled to run daily at 08:00 UTC.
    • New email preference to enable/disable daily fail-ratio notifications.
    • Cron-driven generation of per-app install/fail totals and automated email enqueueing.
  • Changes

    • Per-device failure notifications removed; failures are now reported via daily summary emails.
    • Endpoint extended to accept and relay aggregated report data for the daily summary.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Per-device immediate failure notifications were removed; a daily aggregation pipeline now computes per-app fail ratios and enqueues daily_fail_ratio emails via a new DB cron function. An HTTP handler was added to accept/process emitted daily_fail_ratio payloads and respect user email preferences.

Changes

Cohort / File(s) Summary
Stats plugin
supabase/functions/_backend/plugins/stats.ts
Removed the call to sendNotifToOrgMembers in the failure path; still records a 'fail' stat and logs the failure.
Cron email handler
supabase/functions/_backend/triggers/cron_email.ts
Added handleDailyFailRatio and a new POST branch for daily_fail_ratio; accepts totalInstalls, totalFails, failPercentage, reportDate; validates appId, checks daily_fail_ratio preference, emits metadata and tracks app:daily_fail_ratio.
Email preferences
supabase/functions/_backend/utils/org_email_notifications.ts
Expanded EmailPreferenceKey to include 'daily_fail_ratio' and added daily_fail_ratio?: boolean to EmailPreferences.
DB migration & cron task
supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
Adds public.process_daily_fail_ratio_email() to aggregate yesterday's installs/fails, filter by thresholds, enqueue daily_fail_ratio email jobs via pgmq; sets ownership/permissions and schedules a daily cron task at 08:00 UTC (with upsert-on-conflict).

Sequence Diagram(s)

sequenceDiagram
    participant Device as Device / Runtime
    participant Stats as Stats Plugin
    participant Cron as Cron Scheduler
    participant DB as Postgres (daily_version, apps)
    participant Proc as process_daily_fail_ratio_email()
    participant Queue as Email Queue (pgmq)
    participant CronHandler as cron_email HTTP handler
    participant User as Org Member

    Note over Device,Stats: OLD (immediate notification)
    Device->>Stats: record 'fail' stat
    Stats->>User: send immediate per-device notification (removed)

    Note over Cron,User: NEW (aggregated daily flow)
    Cron->>DB: trigger process_daily_fail_ratio_email() at 08:00 UTC
    DB->>Proc: aggregate installs & fails per app (yesterday)
    Proc->>Proc: filter by min installs & fail% threshold
    Proc->>Queue: enqueue `daily_fail_ratio` jobs (payload with totals, failPercentage, reportDate)
    Queue->>CronHandler: POST job payload to `cron_email` endpoint
    CronHandler->>CronHandler: check `daily_fail_ratio` email preference
    CronHandler->>User: deliver email (if pref enabled) / track event `app:daily_fail_ratio`
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped through logs at break of day,

Removed the pings that ran astray;
Now numbers gather, calm and clear,
A daily note that we will hear;
Cron hums softly, emails fly — a tidy tale from tail to sky.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: replacing per-device failure notifications with daily fail ratio emails.
Description check ✅ Passed The PR description provides clear motivation, business impact, and a detailed test plan covering all key scenarios and thresholds.

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

✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 580ae30 and 2f672dc.

📒 Files selected for processing (4)
  • supabase/functions/_backend/plugins/stats.ts
  • supabase/functions/_backend/triggers/cron_email.ts
  • supabase/functions/_backend/utils/org_email_notifications.ts
  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
🧰 Additional context used
📓 Path-based instructions (9)
supabase/functions/_backend/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

supabase/functions/_backend/**/*.{ts,js}: Backend code must be placed in supabase/functions/_backend/ as shared code deployed to Cloudflare Workers (API/Plugin/Files workers), Supabase Edge Functions, and other platforms
Use createHono from utils/hono.ts for all Hono framework application initialization and routing
All database operations must use getPgClient() or getDrizzleClient() from utils/pg.ts for PostgreSQL access during active migration to Cloudflare D1
All Hono endpoint handlers must accept Context<MiddlewareKeyVariables> and use c.get('requestId'), c.get('apikey'), and c.get('auth') for request context
Use structured logging with cloudlog({ requestId: c.get('requestId'), message: '...' }) for all backend logging
Use middlewareAPISecret for internal API endpoints and middlewareKey for external API keys; validate against owner_org in the apikeys table
Check c.get('auth')?.authType to determine authentication type ('apikey' vs 'jwt') in backend endpoints
Use Drizzle ORM query patterns with schema from postgress_schema.ts for all database operations; use aliasV2() for self-joins or multiple table references

Files:

  • supabase/functions/_backend/utils/org_email_notifications.ts
  • supabase/functions/_backend/triggers/cron_email.ts
  • supabase/functions/_backend/plugins/stats.ts
supabase/functions/**/*.{ts,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Backend ESLint must pass before commit; run bun lint:backend for backend files

Files:

  • supabase/functions/_backend/utils/org_email_notifications.ts
  • supabase/functions/_backend/triggers/cron_email.ts
  • supabase/functions/_backend/plugins/stats.ts
**/*.{vue,ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Run bun lint to lint Vue, TypeScript, and JavaScript files; use bun lint:fix to auto-fix issues

Files:

  • supabase/functions/_backend/utils/org_email_notifications.ts
  • supabase/functions/_backend/triggers/cron_email.ts
  • supabase/functions/_backend/plugins/stats.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use single quotes and no semicolons per @antfu/eslint-config rules

Files:

  • supabase/functions/_backend/utils/org_email_notifications.ts
  • supabase/functions/_backend/triggers/cron_email.ts
  • supabase/functions/_backend/plugins/stats.ts
supabase/functions/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

supabase/functions/**/*.ts: Never use the Supabase admin SDK with service key for user-facing APIs; always use client SDK with user authentication to enforce RLS policies. Admin SDK should only be used for internal operations (triggers, CRON jobs, etc.)
When admin access is unavoidable for a user-facing endpoint, sanitize all user inputs carefully to prevent PostgREST query injection

Files:

  • supabase/functions/_backend/utils/org_email_notifications.ts
  • supabase/functions/_backend/triggers/cron_email.ts
  • supabase/functions/_backend/plugins/stats.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Run bun lint or lint/format command before validating any backend or frontend task to ensure consistent formatting

Files:

  • supabase/functions/_backend/utils/org_email_notifications.ts
  • supabase/functions/_backend/triggers/cron_email.ts
  • supabase/functions/_backend/plugins/stats.ts
supabase/functions/_backend/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Place core backend logic in supabase/functions/_backend/ with plugins, private, public, triggers, and utils subdirectories

Files:

  • supabase/functions/_backend/utils/org_email_notifications.ts
  • supabase/functions/_backend/triggers/cron_email.ts
  • supabase/functions/_backend/plugins/stats.ts
supabase/migrations/**/*.sql

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Database migrations must be created with supabase migration new <feature_slug> and never modify previously committed migrations

Files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
supabase/migrations/*.sql

📄 CodeRabbit inference engine (AGENTS.md)

supabase/migrations/*.sql: Use Supabase CLI for every migration and operational task; avoid manual changes through dashboard or direct SQL
Create a single migration file per feature using supabase migration new <feature_slug> and keep editing that file until the feature ships; never edit previously committed migrations
Never edit previously committed migrations; treat new seeding in migrations as part of the current feature
Do not create new cron jobs; instead update the process_all_cron_tasks function in a new migration file to add your job if needed
Use get_identity_org_appid() for RLS policies when app_id exists on the table instead of get_identity() directly
Only use get_identity_org_allowed() as a last resort when the table genuinely has no app_id column and there is no way to join to get an app_id

Files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
🧠 Learnings (11)
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/functions/_backend/**/*.ts : Place core backend logic in supabase/functions/_backend/ with plugins, private, public, triggers, and utils subdirectories

Applied to files:

  • supabase/functions/_backend/plugins/stats.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : Use `createHono` from `utils/hono.ts` for all Hono framework application initialization and routing

Applied to files:

  • supabase/functions/_backend/plugins/stats.ts
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/**/*.{ts,js} : All Hono endpoint handlers must accept `Context<MiddlewareKeyVariables>` and use `c.get('requestId')`, `c.get('apikey')`, and `c.get('auth')` for request context

Applied to files:

  • supabase/functions/_backend/plugins/stats.ts
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/migrations/*.sql : Do not create new cron jobs; instead update the process_all_cron_tasks function in a new migration file to add your job if needed

Applied to files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/migrations/*.sql : Use Supabase CLI for every migration and operational task; avoid manual changes through dashboard or direct SQL

Applied to files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/seed.sql : Update supabase/seed.sql for new or evolved tests; keep fixtures focused on current behavior while leaving committed migrations unchanged

Applied to files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/migrations/*.sql : Never edit previously committed migrations; treat new seeding in migrations as part of the current feature

Applied to files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/migrations/**/*.sql : Database migrations must be created with `supabase migration new <feature_slug>` and never modify previously committed migrations

Applied to files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
📚 Learning: 2026-01-10T04:55:25.264Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-10T04:55:25.264Z
Learning: Applies to supabase/migrations/*.sql : Create a single migration file per feature using `supabase migration new <feature_slug>` and keep editing that file until the feature ships; never edit previously committed migrations

Applied to files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
📚 Learning: 2025-12-23T02:53:12.055Z
Learnt from: CR
Repo: Cap-go/capgo PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-23T02:53:12.055Z
Learning: Applies to supabase/functions/_backend/utils/postgress_schema.ts : Schema definitions must be placed in `utils/postgress_schema.ts` using Drizzle ORM and never edited in committed migration files

Applied to files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
📚 Learning: 2025-12-25T11:22:13.039Z
Learnt from: WcaleNieWolny
Repo: Cap-go/capgo PR: 1300
File: supabase/migrations/20251224103713_2fa_enforcement.sql:85-96
Timestamp: 2025-12-25T11:22:13.039Z
Learning: In SQL migrations under the repository (e.g., supabase/migrations), enforce that when an org has enforcing_2fa=true, all users (including super_admins) must have 2FA enabled before accessing any org functions, including check_org_members_2fa_enabled. Do not grant admin exceptions to 2FA requirements. This ensures consistent security enforcement across all org-related operations; implement this rule within relevant migrations and associated stored procedures/tests.

Applied to files:

  • supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql
🧬 Code graph analysis (1)
supabase/functions/_backend/triggers/cron_email.ts (3)
supabase/functions/_backend/utils/hono.ts (2)
  • simpleError (247-249)
  • BRES (135-135)
supabase/functions/_backend/utils/logging.ts (1)
  • cloudlog (3-15)
supabase/functions/_backend/utils/bento.ts (1)
  • trackBentoEvent (49-75)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Socket Security: Pull Request Alerts
  • GitHub Check: Socket Security: Project Report
🔇 Additional comments (8)
supabase/functions/_backend/utils/org_email_notifications.ts (1)

22-24: LGTM - new preference key follows existing patterns.

The daily_fail_ratio preference key and interface field are correctly added. Consider whether the device_error preference (lines 22/36) should be deprecated or removed in a follow-up since per-device failure notifications are being replaced by this daily aggregate approach.

Also applies to: 36-38

supabase/functions/_backend/triggers/cron_email.ts (3)

182-193: LGTM - new handler branch follows existing patterns.

The daily_fail_ratio branch correctly routes to handleDailyFailRatio and passes all required payload fields.


595-652: LGTM - handleDailyFailRatio implementation is consistent with other handlers.

The function correctly:

  • Validates appId presence
  • Checks email preference before sending
  • Builds metadata with safe defaults (?? 0, ?? '')
  • Tracks the Bento event
  • Logs completion

630-639: Potential NaN in success_percentage when failPercentage is undefined.

If failPercentage is not provided in the payload, line 638 computes 100 - undefined which results in NaN.toFixed(2) = "NaN". Consider defaulting before the subtraction:

Proposed fix
   const metadata = {
     app_id: appId,
     org_id: orgId ?? '',
     app_name: appName ?? '',
     total_installs: (totalInstalls ?? 0).toString(),
     total_fails: (totalFails ?? 0).toString(),
     fail_percentage: (failPercentage ?? 0).toString(),
     report_date: reportDate ?? '',
-    success_percentage: (100 - (failPercentage ?? 0)).toFixed(2),
+    success_percentage: ((failPercentage ?? 0) >= 0 ? 100 - (failPercentage ?? 0) : 0).toFixed(2),
   }

Actually, the current (failPercentage ?? 0) already handles the undefined case correctly. The expression 100 - (failPercentage ?? 0) will evaluate the nullish coalescing first, so this is fine.

supabase/functions/_backend/plugins/stats.ts (1)

117-129: LGTM - clean removal of per-device notification with clear documentation.

The fail stat creation and logging remain intact. The comment at lines 126-127 clearly documents that daily fail ratio emails are now handled by the cron job, which will help future maintainers understand the architecture.

supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql (3)

42-52: Email sent only to management_email, not all eligible org admins.

The SQL function only retrieves and sends to management_email. However, the TypeScript side has sendEmailToOrgMembers which sends to all admin/super_admin members who have the preference enabled. This means other org admins won't receive this notification even if they have daily_fail_ratio enabled.

If this is intentional (to reduce email volume), the implementation is fine. If all eligible admins should receive the email, consider either:

  1. Using sendEmailToOrgMembers in handleDailyFailRatio, or
  2. Querying all eligible emails in the SQL function

6-75: LGTM - well-structured SQL function with proper thresholds and security.

The function correctly:

  • Uses CTEs for readable query composition
  • Applies both minimum install threshold (10) and fail rate threshold (30%)
  • Handles division-by-zero with explicit checks
  • Queues emails via pgmq with complete payload
  • Sets appropriate ownership and permission grants

83-122: LGTM - cron task registration follows canonical pattern.

The task is registered in cron_tasks table per the coding guidelines (avoiding modification of process_all_cron_tasks). The ON CONFLICT clause handles idempotent migrations correctly.

Based on learnings, this aligns with the guidance to use cron_tasks table for task registration.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 SQLFluff (3.5.0)
supabase/migrations/20260115025158_add_daily_fail_ratio_email.sql

User Error: No dialect was specified. You must configure a dialect or specify one on the command line using --dialect after the command. Available dialects:
ansi, athena, bigquery, clickhouse, databricks, db2, doris, duckdb, exasol, flink, greenplum, hive, impala, mariadb, materialize, mysql, oracle, postgres, redshift, snowflake, soql, sparksql, sqlite, starrocks, teradata, trino, tsql, vertica


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

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8de866743a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 114 to 116
-- Every minute (at :00 seconds): Per-minute tasks
IF current_second = 0 THEN
BEGIN

Choose a reason for hiding this comment

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

P1 Badge Avoid exact-second gating in cron runner

The new process_all_cron_tasks only triggers the per-minute/hour/daily branches when current_second = 0 (see the IF current_second = 0 THEN guard). In this repo the cron runner is invoked every 10 seconds and prior migration 20260103030451_add_advisory_lock_to_cron.sql explicitly warns that pg_cron intervals are not clock‑aligned, so if the job starts at an offset (e.g., :05) this condition never becomes true and all scheduled tasks (including the new daily fail ratio email) will never run. Please restore the offset-safe check (e.g., current_second < 10) or the table-driven scheduler that handled this.

Useful? React with 👍 / 👎.

Comment on lines 96 to 101
-- Every 10 seconds: High-frequency queues (at :00, :10, :20, :30, :40, :50)
IF current_second % 10 = 0 THEN
-- Process high-frequency queues with default batch size (950)
BEGIN
PERFORM public.process_function_queue(ARRAY['on_channel_update', 'on_user_create', 'on_user_update', 'on_version_create', 'on_version_delete', 'on_version_update', 'on_app_delete', 'on_organization_create', 'on_user_delete', 'on_app_create', 'credit_usage_alerts']);
EXCEPTION WHEN OTHERS THEN

Choose a reason for hiding this comment

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

P2 Badge Keep cron_tasks table execution

This migration replaces the table-driven cron runner with a hard-coded list (process_function_queue(ARRAY['on_channel_update', ...])), so anything registered in cron_tasks will no longer execute. I checked supabase/migrations/20260112140000_cleanup_old_channel_devices.sql and 20260113160650_delete_old_deleted_versions.sql, both of which register maintenance jobs in cron_tasks with the comment that this table is the canonical scheduler. With this change those jobs stop running entirely, so stale data cleanup will silently stall. Please keep the cron_tasks loop or explicitly add those tasks to the hard-coded schedule.

Useful? React with 👍 / 👎.

riderx and others added 2 commits January 16, 2026 02:12
…ratio emails

- Removed per-device failure notifications that sent once then waited a week
- Added daily cron job (08:00 UTC) to check install fail ratios by app
- Sends email only when fail rate exceeds 30% with minimum 10 installs
- Added daily_fail_ratio email preference for user control
- One email per app per day maximum, based on aggregate daily stats

Co-Authored-By: Claude Haiku 4.5 <[email protected]>
Addresses PR review comments:
- P1: No longer modifies process_all_cron_tasks, so offset-safe checks preserved
- P2: Registers task in cron_tasks table (canonical scheduler), not hardcoded

Co-Authored-By: Claude Haiku 4.5 <[email protected]>
@riderx riderx force-pushed the riderx/install-fail-ratio-email branch from 580ae30 to 2f672dc Compare January 16, 2026 02:13
@sonarqubecloud
Copy link

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