Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion cmd/db_schema_declarative.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ var (
// If the user has passed the --experimental flag and pg-delta is not enabled, enable it
// so in the rest of the code we can know that we're running pg-delta logic.
if viper.GetBool("EXPERIMENTAL") && !utils.IsPgDeltaEnabled() {
utils.Config.Experimental.PgDelta = &config.PgDeltaConfig{Enabled: true}
if utils.Config.Experimental.PgDelta == nil {
utils.Config.Experimental.PgDelta = &config.PgDeltaConfig{Enabled: true}
} else {
// We preserve the version set into `.temp/pgdelta-version` by just enabling pg-delta.
utils.Config.Experimental.PgDelta.Enabled = true
}
}
if !utils.IsPgDeltaEnabled() {
utils.CmdSuggestion = fmt.Sprintf("Either pass %s or add %s with %s to %s",
Expand Down
10 changes: 7 additions & 3 deletions internal/db/diff/pgdelta.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/jackc/pgx/v4"
"github.com/supabase/cli/internal/gen/types"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/pkg/config"
)

//go:embed templates/pgdelta.ts
Expand Down Expand Up @@ -104,7 +105,8 @@ func DiffPgDeltaRef(ctx context.Context, sourceRef, targetRef string, schema []s
binds = append(binds, cwd+":/workspace")
}
var stdout, stderr bytes.Buffer
if err := utils.RunEdgeRuntimeScript(ctx, env, pgDeltaScript, binds, "error diffing schema", &stdout, &stderr); err != nil {
script := config.InterpolatePgDeltaScript(config.Config(&utils.Config), pgDeltaScript)
if err := utils.RunEdgeRuntimeScript(ctx, env, script, binds, "error diffing schema", &stdout, &stderr); err != nil {
return "", err
}
return stdout.String(), nil
Expand Down Expand Up @@ -143,7 +145,8 @@ func DeclarativeExportPgDeltaRef(ctx context.Context, sourceRef, targetRef strin
binds = append(binds, cwd+":/workspace")
}
var stdout, stderr bytes.Buffer
if err := utils.RunEdgeRuntimeScript(ctx, env, pgDeltaDeclarativeExportScript, binds, "error exporting declarative schema", &stdout, &stderr); err != nil {
script := config.InterpolatePgDeltaScript(config.Config(&utils.Config), pgDeltaDeclarativeExportScript)
if err := utils.RunEdgeRuntimeScript(ctx, env, script, binds, "error exporting declarative schema", &stdout, &stderr); err != nil {
return DeclarativeOutput{}, err
}
if stdout.Len() == 0 {
Expand Down Expand Up @@ -179,7 +182,8 @@ func ExportCatalogPgDelta(ctx context.Context, targetRef, role string, options .
binds = append(binds, cwd+":/workspace")
}
var stdout, stderr bytes.Buffer
if err := utils.RunEdgeRuntimeScript(ctx, env, pgDeltaCatalogExportScript, binds, "error exporting pg-delta catalog", &stdout, &stderr); err != nil {
script := config.InterpolatePgDeltaScript(config.Config(&utils.Config), pgDeltaCatalogExportScript)
if err := utils.RunEdgeRuntimeScript(ctx, env, script, binds, "error exporting pg-delta catalog", &stdout, &stderr); err != nil {
return "", err
}
snapshot := strings.TrimSpace(stdout.String())
Expand Down
4 changes: 3 additions & 1 deletion internal/db/pgcache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/spf13/viper"
"github.com/supabase/cli/internal/gen/types"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/pkg/config"
"github.com/supabase/cli/pkg/migration"
)

Expand Down Expand Up @@ -253,7 +254,8 @@ func exportCatalog(ctx context.Context, targetRef string, options ...func(*pgx.C
}
binds := []string{utils.EdgeRuntimeId + ":/root/.cache/deno:rw"}
var stdout, stderr bytes.Buffer
if err := utils.RunEdgeRuntimeScript(ctx, env, pgDeltaCatalogExportTS, binds, "error exporting pg-delta catalog", &stdout, &stderr); err != nil {
script := config.InterpolatePgDeltaScript(config.Config(&utils.Config), pgDeltaCatalogExportTS)
if err := utils.RunEdgeRuntimeScript(ctx, env, script, binds, "error exporting pg-delta catalog", &stdout, &stderr); err != nil {
return "", err
}
snapshot := strings.TrimSpace(stdout.String())
Expand Down
4 changes: 3 additions & 1 deletion internal/pgdelta/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/spf13/afero"
"github.com/spf13/viper"
"github.com/supabase/cli/internal/utils"
pkgconfig "github.com/supabase/cli/pkg/config"
)

//go:embed templates/pgdelta_declarative_apply.ts
Expand Down Expand Up @@ -321,7 +322,8 @@ func ApplyDeclarative(ctx context.Context, config pgconn.Config, fsys afero.Fs)

fmt.Fprintln(os.Stderr, "Applying declarative schemas via pg-delta...")
var stdout, stderr bytes.Buffer
if err := utils.RunEdgeRuntimeScript(ctx, env, pgDeltaDeclarativeApplyScript, binds, "error running pg-delta script", &stdout, &stderr); err != nil {
script := pkgconfig.InterpolatePgDeltaScript(pkgconfig.Config(&utils.Config), pgDeltaDeclarativeApplyScript)
if err := utils.RunEdgeRuntimeScript(ctx, env, script, binds, "error running pg-delta script", &stdout, &stderr); err != nil {
return err
}

Expand Down
1 change: 1 addition & 0 deletions internal/utils/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ var (
PgmetaVersionPath = filepath.Join(TempDir, "pgmeta-version")
PoolerVersionPath = filepath.Join(TempDir, "pooler-version")
RealtimeVersionPath = filepath.Join(TempDir, "realtime-version")
PgDeltaVersionPath = filepath.Join(TempDir, "pgdelta-version")
CliVersionPath = filepath.Join(TempDir, "cli-latest")
CurrBranchPath = filepath.Join(SupabaseDirPath, ".branches", "_current_branch")
// DeclarativeDir is the canonical location for pg-delta declarative schema
Expand Down
12 changes: 12 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ type (
Enabled bool `toml:"enabled" json:"enabled"`
DeclarativeSchemaPath string `toml:"declarative_schema_path" json:"declarative_schema_path"`
FormatOptions string `toml:"format_options" json:"format_options"`
// NpmVersion is set from .temp/pgdelta-version during Load (not from TOML).
NpmVersion string `toml:"-" json:"-"`
}

inspect struct {
Expand Down Expand Up @@ -690,6 +692,16 @@ func (c *config) Load(path string, fsys fs.FS, overrides ...ConfigEditor) error
if version, err := fs.ReadFile(fsys, builder.LogflareVersionPath); err == nil && len(version) > 0 {
c.Analytics.Image = replaceImageTag(Images.Logflare, string(version))
}
v := DefaultPgDeltaNpmVersion
if version, err := fs.ReadFile(fsys, builder.PgDeltaVersionPath); err == nil {
if trimmed := strings.TrimSpace(string(version)); len(trimmed) > 0 {
v = trimmed
}
}
if c.Experimental.PgDelta == nil {
c.Experimental.PgDelta = &PgDeltaConfig{}
}
c.Experimental.PgDelta.NpmVersion = v
// TODO: replace derived config resolution with viper decode hooks
if err := c.resolve(builder, fsys); err != nil {
return err
Expand Down
51 changes: 51 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,57 @@ format_options = "not-json"
})
}

func TestPgDeltaNpmVersionPinning(t *testing.T) {
t.Run("defaults when pgdelta-version file missing", func(t *testing.T) {
c := NewConfig()
require.NoError(t, c.Load("", fs.MapFS{}))
require.NotNil(t, c.Experimental.PgDelta)
assert.Equal(t, DefaultPgDeltaNpmVersion, c.Experimental.PgDelta.NpmVersion)
assert.Equal(t, DefaultPgDeltaNpmVersion, EffectivePgDeltaNpmVersion(Config(&c)))
})

t.Run("EffectivePgDeltaNpmVersion nil config uses default", func(t *testing.T) {
assert.Equal(t, DefaultPgDeltaNpmVersion, EffectivePgDeltaNpmVersion(nil))
})

t.Run("reads trimmed version from supabase/.temp/pgdelta-version", func(t *testing.T) {
c := NewConfig()
fsys := fs.MapFS{
"supabase/config.toml": &fs.MapFile{Data: []byte(`
[experimental.pgdelta]
enabled = true
`)},
"supabase/.temp/pgdelta-version": &fs.MapFile{Data: []byte(" 9.9.9-test \n")},
}
require.NoError(t, c.Load("", fsys))
require.NotNil(t, c.Experimental.PgDelta)
assert.Equal(t, "9.9.9-test", c.Experimental.PgDelta.NpmVersion)
assert.Equal(t, "9.9.9-test", EffectivePgDeltaNpmVersion(Config(&c)))
})

t.Run("whitespace-only pgdelta-version keeps default", func(t *testing.T) {
c := NewConfig()
fsys := fs.MapFS{
"supabase/config.toml": &fs.MapFile{Data: []byte(`
[experimental.pgdelta]
enabled = true
`)},
"supabase/.temp/pgdelta-version": &fs.MapFile{Data: []byte(" \n")},
}
require.NoError(t, c.Load("", fsys))
require.NotNil(t, c.Experimental.PgDelta)
assert.Equal(t, DefaultPgDeltaNpmVersion, c.Experimental.PgDelta.NpmVersion)
})

t.Run("InterpolatePgDeltaScript substitutes placeholder", func(t *testing.T) {
c := NewConfig()
require.NoError(t, c.Load("", fs.MapFS{}))
// Embedded TS pins use this semver literal before InterpolatePgDeltaScript runs.
got := InterpolatePgDeltaScript(Config(&c), `from "npm:@supabase/pg-delta@1.0.0-alpha.20";`)
assert.Equal(t, `from "npm:@supabase/pg-delta@`+DefaultPgDeltaNpmVersion+`";`, got)
})
}

func TestRemoteOverride(t *testing.T) {
t.Run("load staging override", func(t *testing.T) {
config := NewConfig()
Expand Down
28 changes: 28 additions & 0 deletions pkg/config/pgdelta_version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package config

import "strings"

// DefaultPgDeltaNpmVersion is the npm dist-tag/version used for @supabase/pg-delta
// when supabase/.temp/pgdelta-version is absent or empty.
const DefaultPgDeltaNpmVersion = "1.0.0-alpha.22"

const pgDeltaNpmVersionPlaceholder = "1.0.0-alpha.20"

// EffectivePgDeltaNpmVersion returns the pg-delta npm version from loaded config,
// or DefaultPgDeltaNpmVersion when unset (e.g. before Load or empty field).
func EffectivePgDeltaNpmVersion(c Config) string {
if c == nil {
return DefaultPgDeltaNpmVersion
}
if c.Experimental.PgDelta != nil {
if v := strings.TrimSpace(c.Experimental.PgDelta.NpmVersion); v != "" {
return v
}
}
return DefaultPgDeltaNpmVersion
}

// InterpolatePgDeltaScript substitutes pg delta npm version placeholders in embedded TS.
func InterpolatePgDeltaScript(c Config, script string) string {
return strings.ReplaceAll(script, pgDeltaNpmVersionPlaceholder, EffectivePgDeltaNpmVersion(c))
}
2 changes: 2 additions & 0 deletions pkg/config/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type pathBuilder struct {
RealtimeVersionPath string
EdgeRuntimeVersionPath string
LogflareVersionPath string
PgDeltaVersionPath string
CliVersionPath string
CurrBranchPath string
SchemasDir string
Expand Down Expand Up @@ -64,6 +65,7 @@ func NewPathBuilder(configPath string) pathBuilder {
PoolerVersionPath: filepath.Join(base, ".temp", "pooler-version"),
RealtimeVersionPath: filepath.Join(base, ".temp", "realtime-version"),
LogflareVersionPath: filepath.Join(base, ".temp", "logflare-version"),
PgDeltaVersionPath: filepath.Join(base, ".temp", "pgdelta-version"),
CliVersionPath: filepath.Join(base, ".temp", "cli-latest"),
CurrBranchPath: filepath.Join(base, ".branches", "_current_branch"),
SchemasDir: filepath.Join(base, "schemas"),
Expand Down
Loading