feat(upgrades): prevent upgrades for hibernated projects (#46109)

## 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


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## 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_stack_entry_start -->

[![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)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Kevin Grüneberg <k.grueneberg1994@gmail.com>
This commit is contained in:
Paul CioancaandKevin Grüneberg authored and GitHub committed 2026-06-01 18:53:57 +03:00
1 parent cd16e85d86
commit bc6a459fd2
3 files changed
+206 -3

No files matched your search

@@ -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'
}
}
+198 -1
View File
@@ -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
-2
View File
@@ -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'