From bc6a459fd2b5af36bae19c960fe93bf2088e9547 Mon Sep 17 00:00:00 2001 From: Paul Cioanca Date: Mon, 1 Jun 2026 18:53:57 +0300 Subject: [PATCH] feat(upgrades): prevent upgrades for hibernated projects (#46109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? * Prevents hibernated projects from undergoing database version upgrades ## Summary by CodeRabbit * **New Features** * Added support for hibernating projects in upgrade warnings. Users will now see a clear message indicating their project is hibernating and will resume on the next supported request. * **Chores** * Extended log drain configuration to support additional destination types. [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/46109?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) --------- Co-authored-by: Kevin Grüneberg --- .../Infrastructure/UpgradeWarnings.tsx | 8 + packages/api-types/types/api.d.ts | 199 +++++++++++++++++- packages/common/telemetry-constants.ts | 2 - 3 files changed, 206 insertions(+), 3 deletions(-) diff --git a/apps/studio/components/interfaces/Settings/Infrastructure/UpgradeWarnings.tsx b/apps/studio/components/interfaces/Settings/Infrastructure/UpgradeWarnings.tsx index ba02bf5116f..a38bb8efd84 100644 --- a/apps/studio/components/interfaces/Settings/Infrastructure/UpgradeWarnings.tsx +++ b/apps/studio/components/interfaces/Settings/Infrastructure/UpgradeWarnings.tsx @@ -46,6 +46,10 @@ const getValidationErrorTitle = (error: ProjectUpgradeEligibilityValidationError return `${error.schema_name}.${error.obj_name}` case 'active_replication_slot': return error.slot_name + case 'project_hibernating': + return 'Project is hibernating' + case 'x86_architecture': + return 'Project is running on x86 architecture' } } @@ -67,6 +71,10 @@ const getValidationErrorDescription = (error: ProjectUpgradeEligibilityValidatio return `Move the ${error.obj_type} to your own schema` case 'active_replication_slot': return 'Drop the active replication slot' + case 'project_hibernating': + return 'The project is currently hibernating and will wake on next supported request' + case 'x86_architecture': + return 'The project is running on x86 architecture and cannot be upgraded' } } diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api.d.ts index 07d186d944d..362b857dd5b 100644 --- a/packages/api-types/types/api.d.ts +++ b/packages/api-types/types/api.d.ts @@ -1205,6 +1205,27 @@ export interface paths { patch?: never trace?: never } + '/v1/projects/{ref}/database/backups/schedule': { + parameters: { + query?: never + header?: never + path?: never + cookie?: never + } + /** Gets the backup schedule for a project */ + get: operations['v1-get-backup-schedule'] + put?: never + post?: never + delete?: never + options?: never + head?: never + /** + * Updates the backup schedule time for a project + * @description Sets the time at which the daily backup runs. The change takes effect on the next backup window that includes the new time. If the new time has already passed for today, the first backup at the new time will occur the following day. It can only be updated 3 times per 24 hours. + */ + patch: operations['v1-update-backup-schedule'] + trace?: never + } '/v1/projects/{ref}/database/backups/undo': { parameters: { query?: never @@ -2503,7 +2524,11 @@ export interface components { project_ref: string /** Format: date-time */ review_requested_at?: string - /** @enum {string} */ + /** + * @deprecated + * @description This field is deprecated. List action runs to get branch status instead. + * @enum {string} + */ status: | 'CREATING_PROJECT' | 'RUNNING_MIGRATIONS' @@ -3748,6 +3773,14 @@ export interface components { /** @enum {string} */ type: 'active_replication_slot' } + | { + /** @enum {string} */ + type: 'x86_architecture' + } + | { + /** @enum {string} */ + type: 'project_hibernating' + } )[] warnings: { /** @enum {string} */ @@ -4690,6 +4723,19 @@ export interface components { release_channel?: 'internal' | 'alpha' | 'beta' | 'ga' | 'withdrawn' | 'preview' target_version: string } + V1BackupScheduleResponse: { + /** + * @description Time of day to schedule daily backups, in UTC. Format: HH:MM:SS. + * @example 04:00:00 + */ + schedule_for: string + /** + * Format: date-time + * @description Timestamp of when the backup schedule was last updated. + * @example 2026-05-04T14:40:44+00:00 + */ + updated_at: string + } V1BackupsResponse: { backups: { id: number @@ -4945,6 +4991,7 @@ export interface components { | 'ipv4' | 'pitr.available_variants' | 'log_drains' + | 'audit_log_drains' | 'branching_limit' | 'branching_persistent' | 'auth.mfa_phone' @@ -4962,6 +5009,7 @@ export interface components { | 'auth.custom_oauth.max_providers' | 'backup.retention_days' | 'backup.restore_to_new_project' + | 'backup.schedule' | 'function.max_count' | 'function.size_limit_mb' | 'realtime.max_concurrent_users' @@ -5298,6 +5346,16 @@ export interface components { V1UndoBody: { name: string } + /** @example { + * "schedule_for": "04:00:00" + * } */ + V1UpdateBackupScheduleBody: { + /** + * @description Time of day to schedule daily backups, in UTC. Format: HH:MM:SS. + * @example 04:00:00 + */ + schedule_for: string + } /** @example { * "name": "Hello World", * "body": "Deno.serve(() => new Response('Hello again!'))", @@ -9827,6 +9885,145 @@ export interface operations { } } } + 'v1-get-backup-schedule': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody?: never + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V1BackupScheduleResponse'] + } + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Feature requires a higher plan */ + 402: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Project or backup schedule not found */ + 404: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to retrieve backup schedule */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } + 'v1-update-backup-schedule': { + parameters: { + query?: never + header?: never + path: { + /** @description Project ref */ + ref: string + } + cookie?: never + } + requestBody: { + content: { + 'application/json': components['schemas']['V1UpdateBackupScheduleBody'] + } + } + responses: { + 200: { + headers: { + [name: string]: unknown + } + content: { + 'application/json': components['schemas']['V1BackupScheduleResponse'] + } + } + /** @description Invalid schedule_for format */ + 400: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Unauthorized */ + 401: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Feature requires a higher plan */ + 402: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Forbidden action */ + 403: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Project or backup schedule not found */ + 404: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Rate limit exceeded */ + 429: { + headers: { + [name: string]: unknown + } + content?: never + } + /** @description Failed to update backup schedule */ + 500: { + headers: { + [name: string]: unknown + } + content?: never + } + } + } 'v1-undo': { parameters: { query?: never diff --git a/packages/common/telemetry-constants.ts b/packages/common/telemetry-constants.ts index 42cccb7f23a..4899cfce013 100644 --- a/packages/common/telemetry-constants.ts +++ b/packages/common/telemetry-constants.ts @@ -2450,7 +2450,6 @@ export interface LogDrainSaveButtonClickedEvent { | 'clickhouse' | 'webhook' | 'datadog' - | 'elastic' | 'loki' | 'sentry' | 's3' @@ -2481,7 +2480,6 @@ export interface LogDrainRemovedEvent { | 'clickhouse' | 'webhook' | 'datadog' - | 'elastic' | 'loki' | 'sentry' | 's3'