From 534f9faf7c400c8c133c9ed06a60ebf99d584b86 Mon Sep 17 00:00:00 2001 From: Chris Gwilliams <517923+encima@users.noreply.github.com> Date: Fri, 15 May 2026 12:53:24 +0200 Subject: [PATCH 1/4] clean up report table output and add rules for duplicate indexes, dead rows and repl slots --- internal/inspect/index_stats/index_stats.go | 6 ++- internal/inspect/index_stats/index_stats.sql | 11 ++++- .../inspect/index_stats/index_stats_test.go | 2 + internal/inspect/report.go | 2 + internal/inspect/templates/rules.toml | 40 ++++++++++++++++++- 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/internal/inspect/index_stats/index_stats.go b/internal/inspect/index_stats/index_stats.go index 6db47c4bfe..bdec377dca 100644 --- a/internal/inspect/index_stats/index_stats.go +++ b/internal/inspect/index_stats/index_stats.go @@ -19,6 +19,8 @@ var IndexStatsQuery string type Result struct { Name string + Table string + Columns string Size string Percent_used string Index_scans int64 @@ -41,9 +43,9 @@ func Run(ctx context.Context, config pgconn.Config, fsys afero.Fs, options ...fu return err } - table := "|Name|Size|Percent used|Index scans|Seq scans|Unused|\n|-|-|-|-|-|-|\n" + table := "|Name|Table|Columns|Size|Percent used|Index scans|Seq scans|Unused|\n|-|-|-|-|-|-|-|-|\n" for _, r := range result { - table += fmt.Sprintf("|`%s`|`%s`|`%s`|`%d`|`%d`|`%t`|\n", r.Name, r.Size, r.Percent_used, r.Index_scans, r.Seq_scans, r.Unused) + table += fmt.Sprintf("|`%s`|`%s`|`%s`|`%s`|`%s`|`%d`|`%d`|`%t`|\n", r.Name, r.Table, r.Columns, r.Size, r.Percent_used, r.Index_scans, r.Seq_scans, r.Unused) } return utils.RenderTable(table) } diff --git a/internal/inspect/index_stats/index_stats.sql b/internal/inspect/index_stats/index_stats.sql index c8d33e95dd..7547fc205b 100644 --- a/internal/inspect/index_stats/index_stats.sql +++ b/internal/inspect/index_stats/index_stats.sql @@ -1,13 +1,20 @@ --- Combined index statistics: size, usage percent, seq scans, and mark unused +-- Combined index statistics: size, usage percent, seq scans, mark unused, expose table + columns WITH idx_sizes AS ( SELECT i.indexrelid AS oid, FORMAT('%I.%I', n.nspname, c.relname) AS name, + FORMAT('%I.%I', tn.nspname, tc.relname) AS table_name, + ( + SELECT STRING_AGG(pg_get_indexdef(i.indexrelid, ord::int, false), ',' ORDER BY ord) + FROM unnest(i.indkey::int[]) WITH ORDINALITY AS k(attnum, ord) + ) AS columns, pg_relation_size(i.indexrelid) AS index_size_bytes FROM pg_stat_user_indexes ui JOIN pg_index i ON ui.indexrelid = i.indexrelid JOIN pg_class c ON ui.indexrelid = c.oid JOIN pg_namespace n ON c.relnamespace = n.oid + JOIN pg_class tc ON tc.oid = i.indrelid + JOIN pg_namespace tn ON tn.oid = tc.relnamespace WHERE NOT n.nspname LIKE ANY($1) ), idx_usage AS ( @@ -37,6 +44,8 @@ usage_pct AS ( ) SELECT s.name, + s.table_name AS "table", + s.columns, pg_size_pretty(s.index_size_bytes) AS size, COALESCE(up.percent_used, 0)::text || '%' AS percent_used, COALESCE(u.idx_scans, 0) AS index_scans, diff --git a/internal/inspect/index_stats/index_stats_test.go b/internal/inspect/index_stats/index_stats_test.go index abc3cd6543..c9edc49581 100644 --- a/internal/inspect/index_stats/index_stats_test.go +++ b/internal/inspect/index_stats/index_stats_test.go @@ -30,6 +30,8 @@ func TestIndexStatsCommand(t *testing.T) { conn.Query(IndexStatsQuery, reset.LikeEscapeSchema(utils.InternalSchemas)). Reply("SELECT 1", Result{ Name: "public.test_idx", + Table: "public.test", + Columns: "id", Size: "1GB", Percent_used: "50%", Index_scans: 5, diff --git a/internal/inspect/report.go b/internal/inspect/report.go index 162d0bb08f..1f038cdc52 100644 --- a/internal/inspect/report.go +++ b/internal/inspect/report.go @@ -117,6 +117,8 @@ func printSummary(ctx context.Context, outDir string) error { } if !match.Valid { match.String = "-" + } else if len(match.String) > 20 { + match.String = fmt.Sprintf("%d matches", strings.Count(match.String, ",")+1) } table += fmt.Sprintf("|`%s`|`%s`|`%s`|\n", r.Name, status, match.String) } diff --git a/internal/inspect/templates/rules.toml b/internal/inspect/templates/rules.toml index 2597ee720d..7d69efda63 100644 --- a/internal/inspect/templates/rules.toml +++ b/internal/inspect/templates/rules.toml @@ -19,7 +19,13 @@ pass = "✔" fail = "There is at least one unused index" [[rules]] -query = "SELECT LISTAGG(name, ',') AS match FROM `db_stats.csv` WHERE index_hit_rate < 0.94 OR table_hit_rate < 0.94" +query = "SELECT LISTAGG(i.name, ',') AS match FROM `index_stats.csv` AS i JOIN (SELECT `table`, columns FROM `index_stats.csv` GROUP BY `table`, columns HAVING COUNT(*) > 1) AS d ON i.`table` = d.`table` AND i.columns = d.columns" +name = "No duplicate indexes" +pass = "✔" +fail = "There is at least one duplicate index (same columns on the same table)" + +[[rules]] +query = "SELECT 'index: ' || index_hit_rate || ', table: ' || table_hit_rate AS match FROM `db_stats.csv` WHERE index_hit_rate < 0.94 OR table_hit_rate < 0.94" name = "Check cache hit is within acceptable bounds" pass = "✔" fail = "There is a cache hit ratio (table or index) below 94%" @@ -31,7 +37,7 @@ pass = "✔" fail = "At least one table is showing sequential scans more than 10% of total row count" [[rules]] -query = "SELECT LISTAGG(s.tbl, ',') AS match FROM `vacuum_stats.csv` s WHERE s.expect_autovacuum = 'yes' and s.rowcount > 1000;" +query = "SELECT LISTAGG(s.name, ',') AS match FROM `vacuum_stats.csv` s WHERE s.expect_autovacuum = 'yes' and s.rowcount > 1000;" name = "No large tables waiting on autovacuum" pass = "✔" fail = "At least one table is waiting on autovacuum" @@ -41,3 +47,33 @@ query = "SELECT LISTAGG(s.name, ',') AS match FROM `vacuum_stats.csv` s WHERE s. name = "No tables yet to be vacuumed" pass = "✔" fail = "At least one table has never had autovacuum or vacuum run on it" + +[[rules]] +query = "SELECT LISTAGG(s.name, ',') AS match FROM `vacuum_stats.csv` s WHERE FLOAT(REPLACE(s.rowcount, ',', '')) > 1000 AND FLOAT(REPLACE(s.dead_rowcount, ',', '')) > 0.2 * FLOAT(REPLACE(s.rowcount, ',', ''))" +name = "No tables with more than 20% dead rows" +pass = "✔" +fail = "At least one table has more than 20% dead rows" + +[[rules]] +query = "SELECT LISTAGG(slot_name, ',') AS match FROM `replication_slots.csv` WHERE active = 'f'" +name = "No inactive replication slots" +pass = "✔" +fail = "There is at least one inactive replication slot" + +[[rules]] +query = "SELECT LISTAGG(blocked_pid, ',') AS match FROM `blocking.csv`" +name = "No blocked queries" +pass = "✔" +fail = "There is at least one query blocked on another" + +[[rules]] +query = "SELECT LISTAGG(pid, ',') AS match FROM `long_running_queries.csv`" +name = "No queries running longer than 5 minutes" +pass = "✔" +fail = "At least one query has been running for more than 5 minutes" + +[[rules]] +query = "SELECT LISTAGG(name, ',') AS match FROM `bloat.csv` WHERE bloat > 4" +name = "No tables or indexes with bloat ratio above 4x" +pass = "✔" +fail = "At least one table or index is more than 4x its expected size" From 50cd8cb9f91fc062f33dd78e9dfaf0a5378f11e1 Mon Sep 17 00:00:00 2001 From: Qiao Han Date: Fri, 9 Jan 2026 03:01:53 +0800 Subject: [PATCH 2/4] feat: support ssl enforcement config --- pkg/config/db.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/config/db.go b/pkg/config/db.go index 7b0c76a163..963cfba9c7 100644 --- a/pkg/config/db.go +++ b/pkg/config/db.go @@ -92,7 +92,7 @@ type ( Seed seed `toml:"seed" json:"seed"` Settings settings `toml:"settings" json:"settings"` NetworkRestrictions networkRestrictions `toml:"network_restrictions" json:"network_restrictions"` - SslEnforcement *sslEnforcement `toml:"ssl_enforcement" json:"ssl_enforcement"` + SslEnforcement *sslEnforcement `toml:"ssl_enforcement" json:"ssl_enforcement"` Vault map[string]Secret `toml:"vault" json:"vault"` } From 22bd83fa067b9be9811943836ccdbc821a850112 Mon Sep 17 00:00:00 2001 From: Pamela Chia Date: Mon, 6 Apr 2026 23:34:24 +0900 Subject: [PATCH 3/4] chore: retrigger CI From 6923f5d816e98b958b7c618bc442c9816afce2fe Mon Sep 17 00:00:00 2001 From: Andrew Valleteau Date: Mon, 27 Apr 2026 09:13:12 +0200 Subject: [PATCH 4/4] chore: resync develop with main (#5123) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prod deploy (#5109) * fix(pg-delta): declarative-sync-no-declarative-dir-set (#5078) * feat(declarative): add tests for skipping config updates when PgDelta is enabled - These tests verify that the configuration remains unchanged when PgDelta is enabled, ensuring the declarative directory is the source of truth. - Updated the WriteDeclarativeSchemas function to reflect the new behavior regarding PgDelta configuration. * fix(declarative): DSL change due to upgrade * feat(auth): add support for configuring passkeys and webauthn (#5077) * fix: atomic parser (#5064) * fix * test --------- * fix(pg-delta): declarative apply error results (#5082) * fix(pg-delta): declarative apply error results Improve readability report for decalrative appy errors wrapping * chore: upgrade pg-delta to alpha 13 * feat(telemetry): attach org/project groups to all CLI events Only ~19% of CLI events had PostHog group properties ($group_0, $group_1) because groups were only set during `supabase link`. Commands using --project-ref without linking sent events invisible to group analytics. Add EnsureProjectGroupsCached which resolves and caches project metadata (including org ID) in linked-project.json when a project ref is available. The cache is checked before every cli_command_executed event, so the API call only happens once per unique project ref. Closes GROWTH-761 * fix: address code review feedback - Guard against log.Fatalln crash: check auth token before calling GetSupabase(), and move the API call to cmd/root.go where it belongs - Don't overwrite existing linked-project.json cache — supabase link is the authoritative source, we only fill the gap when no cache exists - Fire GroupIdentify for org and project after caching, matching the link flow so PostHog has group metadata - Restructure so telemetry package has no API dependencies (pure caching + PostHog calls), making tests reliable without gock/mocks * fix: adds etl to managed schema (#5090) * chore: sync API types from infrastructure (#5093) * chore(deps): bump the actions-major group across 1 directory with 5 updates (#5088) Bumps the actions-major group with 5 updates in the / directory: | Package | From | To | | --- | --- | --- | | [actions/create-github-app-token](https://github.com/actions/create-github-app-token) | `3.0.0` | `3.1.1` | | [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) | `8.1.0` | `8.1.1` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `7.0.0` | `7.0.1` | | [github/codeql-action](https://github.com/github/codeql-action) | `4.35.1` | `4.35.2` | | [docker/build-push-action](https://github.com/docker/build-push-action) | `7.0.0` | `7.1.0` | Updates `actions/create-github-app-token` from 3.0.0 to 3.1.1 - [Release notes](https://github.com/actions/create-github-app-token/releases) - [Commits](https://github.com/actions/create-github-app-token/compare/f8d387b68d61c58ab83c6c016672934102569859...1b10c78c7865c340bc4f6099eb2f838309f1e8c3) Updates `peter-evans/create-pull-request` from 8.1.0 to 8.1.1 - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/c0f553fe549906ede9cf27b5156039d195d2ece0...5f6978faf089d4d20b00c7766989d076bb2fc7f1) Updates `actions/upload-artifact` from 7.0.0 to 7.0.1 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/bbbca2ddaa5d8feaa63e36b76fdaad77386f024f...043fb46d1a93c77aae656e7c1c64a875d1fc6a0a) Updates `github/codeql-action` from 4.35.1 to 4.35.2 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/c10b8064de6f491fea524254123dbe5e09572f13...95e58e9a2cdfd71adc6e0353d5c52f41a045d225) Updates `docker/build-push-action` from 7.0.0 to 7.1.0 - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/d08e5c354a6adb9ed34480a06d141179aa583294...bcafcacb16a39f128d818304e6c9c0c18556b85f) --- updated-dependencies: - dependency-name: actions/create-github-app-token dependency-version: 3.1.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-major - dependency-name: peter-evans/create-pull-request dependency-version: 8.1.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-major - dependency-name: actions/upload-artifact dependency-version: 7.0.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-major - dependency-name: github/codeql-action dependency-version: 4.35.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions-major - dependency-name: docker/build-push-action dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-major ... * fix: functions download (#5096) * fix * test --------- * feat(db): strengthen RLS advisory message for stronger agent compliance * chore(deps): upgrade pg-delta to alpha.17 (#5110) Closes: #5094 * chore(deps): bump the actions-major group across 1 directory with 4 updates (#5108) Bumps the actions-major group with 4 updates in the / directory: [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata), [t1m0thyj/unlock-keyring](https://github.com/t1m0thyj/unlock-keyring), [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) and [actions/setup-node](https://github.com/actions/setup-node). Updates `dependabot/fetch-metadata` from 3.0.0 to 3.1.0 - [Release notes](https://github.com/dependabot/fetch-metadata/releases) - [Commits](https://github.com/dependabot/fetch-metadata/compare/ffa630c65fa7e0ecfa0625b5ceda64399aea1b36...25dd0e34f4fe68f24cc83900b1fe3fe149efef98) Updates `t1m0thyj/unlock-keyring` from 1.1.0 to 1.2.0 - [Release notes](https://github.com/t1m0thyj/unlock-keyring/releases) - [Commits](https://github.com/t1m0thyj/unlock-keyring/compare/728cc718a07b5e7b62c269fc89295e248b24cba7...cbcf205c879ebd86add70bab3a6abfcce59a5cae) Updates `goreleaser/goreleaser-action` from 7.0.0 to 7.1.0 - [Release notes](https://github.com/goreleaser/goreleaser-action/releases) - [Commits](https://github.com/goreleaser/goreleaser-action/compare/ec59f474b9834571250b370d4735c50f8e2d1e29...e24998b8b67b290c2fa8b7c14fcfa7de2c5c9b8c) Updates `actions/setup-node` from 6.3.0 to 6.4.0 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/53b83947a5a98c8d113130e565377fae1a50d02f...48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e) --- updated-dependencies: - dependency-name: dependabot/fetch-metadata dependency-version: 3.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-major - dependency-name: t1m0thyj/unlock-keyring dependency-version: 1.2.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-major - dependency-name: goreleaser/goreleaser-action dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-major - dependency-name: actions/setup-node dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions-major ... * fix(docker): bump the docker-minor group across 1 directory with 6 updates (#5079) * fix(docker): bump the docker-minor group across 1 directory with 6 updates Bumps the docker-minor group with 6 updates in the /pkg/config/templates directory: | Package | From | To | | --- | --- | --- | | postgrest/postgrest | `v14.8` | `v14.9` | | supabase/studio | `2026.04.08-sha-205cbe7` | `2026.04.13-sha-e95f1cc` | | supabase/edge-runtime | `v1.73.3` | `v1.73.5` | | supabase/realtime | `v2.82.0` | `v2.83.1` | | supabase/storage-api | `v1.48.28` | `v1.51.0` | | supabase/logflare | `1.37.1` | `1.38.2` | Updates `postgrest/postgrest` from v14.8 to v14.9 Updates `supabase/studio` from 2026.04.08-sha-205cbe7 to 2026.04.13-sha-e95f1cc Updates `supabase/edge-runtime` from v1.73.3 to v1.73.5 Updates `supabase/realtime` from v2.82.0 to v2.83.1 Updates `supabase/storage-api` from v1.48.28 to v1.51.0 Updates `supabase/logflare` from 1.37.1 to 1.38.2 --- updated-dependencies: - dependency-name: postgrest/postgrest dependency-version: v14.9 dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/studio dependency-version: 2026.04.13-sha-e95f1cc dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/edge-runtime dependency-version: v1.73.5 dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/realtime dependency-version: v2.83.1 dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/storage-api dependency-version: v1.51.0 dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/logflare dependency-version: 1.38.2 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker-minor ... * Downgrade postgrest version from 14.9 to 14.8 --------- * chore(workflows): enable install scripts for supabase package in Yarn (#5111) chore(workflows): enable install scripts for supabase package in Yarn Berry setup This change sets the YARN_ENABLE_SCRIPTS environment variable to true during the installation of the supabase package, allowing its postinstall script to run as required by Yarn Berry 4.14+. This adjustment ensures the necessary binary is fetched correctly. * feat: --diff-engine flag on db pull * fix(docker): bump the docker-minor group in /pkg/config/templates with 6 updates (#5113) fix(docker): bump the docker-minor group Bumps the docker-minor group in /pkg/config/templates with 6 updates: | Package | From | To | | --- | --- | --- | | postgrest/postgrest | `v14.8` | `v14.10` | | supabase/studio | `2026.04.13-sha-e95f1cc` | `2026.04.20-sha-b721a2d` | | supabase/edge-runtime | `v1.73.5` | `v1.73.13` | | supabase/realtime | `v2.83.1` | `v2.86.3` | | supabase/storage-api | `v1.51.0` | `v1.54.1` | | supabase/logflare | `1.38.2` | `1.39.1` | Updates `postgrest/postgrest` from v14.8 to v14.10 Updates `supabase/studio` from 2026.04.13-sha-e95f1cc to 2026.04.20-sha-b721a2d Updates `supabase/edge-runtime` from v1.73.5 to v1.73.13 Updates `supabase/realtime` from v2.83.1 to v2.86.3 Updates `supabase/storage-api` from v1.51.0 to v1.54.1 Updates `supabase/logflare` from 1.38.2 to 1.39.1 --- updated-dependencies: - dependency-name: postgrest/postgrest dependency-version: v14.10 dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/studio dependency-version: 2026.04.20-sha-b721a2d dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/edge-runtime dependency-version: v1.73.13 dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/realtime dependency-version: v2.86.3 dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/storage-api dependency-version: v1.54.1 dependency-type: direct:production dependency-group: docker-minor - dependency-name: supabase/logflare dependency-version: 1.39.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: docker-minor ... * feat: exposing new api keys to functions (#4946) * chore: upgrade pg-delta to alpha.20 in multiple templates * fix: remove version comparison check for storage image updates (#5118) fix: honor pinned storage version offline Remove the version comparison that only pinned storage when the local version was newer than the default. This prevented `supabase start` from using an already-downloaded image offline, since Docker would still try to pull the default newer image. Fixes CLI-1393. * fix: improve error handling and output formatting in pg-delta apply process (#5120) - Updated the `runDeclarativeSync` function to avoid wrapping SQL output with `utils.Bold`, preventing excessive whitespace in multi-line SQL. - Changed the result accumulation in `migra.ts` from string concatenation to an array for better performance and clarity. - Enhanced the `ApplyResult` struct to include `ValidationErrors` and `Diagnostics`, allowing for more detailed error reporting. - Modified the `formatApplyFailure` function to include validation errors and diagnostics in the output, improving user feedback on apply failures. - Added tests for validation error handling in `apply_test.go` to ensure robustness against various error scenarios. --------- Signed-off-by: dependabot[bot] Co-authored-by: supabase-cli-releaser[bot] <246109035+supabase-cli-releaser[bot]@users.noreply.github.com> Co-authored-by: fadymak Co-authored-by: Vaibhav <117663341+7ttp@users.noreply.github.com> Co-authored-by: Sean Oliver <882952+seanoliver@users.noreply.github.com> Co-authored-by: Han Qiao Co-authored-by: Julien Goux Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Mert YEREKAPAN Co-authored-by: Mert YEREKAPAN <33198490+myerekapan@users.noreply.github.com> Co-authored-by: Kalleby Santos <105971119+kallebysantos@users.noreply.github.com> Co-authored-by: Claude