Skip to content
Open
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
3 changes: 3 additions & 0 deletions api/overlay.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ actions:
- target: $.components.schemas.DiskRequestBody.properties.attributes.discriminator
description: Replaces discriminated union with concrete type
remove: true
- target: $.components.schemas.JitStateResponse.discriminator
description: Replaces discriminated union with concrete type
remove: true
- target: $.paths.*.*.parameters[?(@.name=='branch_id_or_ref')]
update:
schema:
Expand Down
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
3 changes: 3 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ func Execute() {
if err != nil {
fmt.Fprintln(utils.GetDebugLogger(), err)
}
if hint := utils.SuggestClaudePlugin(); hint != "" {
fmt.Fprintln(os.Stderr, hint)
}
if semver.Compare(version, "v"+utils.Version) > 0 {
fmt.Fprintln(os.Stderr, suggestUpgrade(version))
}
Expand Down
2 changes: 2 additions & 0 deletions docs/supabase/start.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ All service containers are started by default. You can exclude those not needed
> It is recommended to have at least 7GB of RAM to start all services.

Health checks are automatically added to verify the started containers. Use `--ignore-health-check` flag to ignore these errors.

> If the CLI is running inside a dev container with the Docker socket bind-mounted, set the `SUPABASE_SERVICES_HOSTNAME` environment variable to the hostname reachable from inside that container, such as `host.docker.internal`.
26 changes: 20 additions & 6 deletions internal/db/diff/pgdelta.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import (
_ "embed"
"encoding/json"
"os"
"path/filepath"
"strings"

"github.com/go-errors/errors"
"github.com/jackc/pgconn"
"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 @@ -47,12 +49,14 @@ func isPostgresURL(ref string) bool {

// containerRef translates a host-relative catalog file path into the absolute
// path where it appears inside the edge runtime container (CWD mounted at
// /workspace). Postgres URLs and empty strings pass through unchanged.
// /workspace). Postgres URLs and empty strings pass through unchanged. Path
// separators are normalised to forward slashes so Windows paths (with `\`)
// resolve correctly inside the Linux container.
func containerRef(ref string) string {
if ref == "" || isPostgresURL(ref) {
return ref
}
return "/workspace/" + ref
return "/workspace/" + filepath.ToSlash(ref)
}

// pgDeltaFormatOptions returns the experimental.pgdelta.format_options config for
Expand Down Expand Up @@ -101,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 @@ -140,9 +145,13 @@ 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 {
return DeclarativeOutput{}, errors.Errorf("error exporting declarative schema: edge-runtime script produced no output:\n%s", stderr.String())
}
var result DeclarativeOutput
if err := json.Unmarshal(stdout.Bytes(), &result); err != nil {
return DeclarativeOutput{}, errors.Errorf("failed to parse declarative export output: %w", err)
Expand Down Expand Up @@ -173,8 +182,13 @@ 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
}
return strings.TrimSpace(stdout.String()), nil
snapshot := strings.TrimSpace(stdout.String())
if len(snapshot) == 0 {
return "", errors.Errorf("error exporting pg-delta catalog: edge-runtime script produced no output:\n%s", stderr.String())
}
return snapshot, nil
}
34 changes: 34 additions & 0 deletions internal/db/diff/pgdelta_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package diff

import (
"runtime"
"testing"

"github.com/stretchr/testify/assert"
)

func TestContainerRef(t *testing.T) {
t.Run("passes empty string through", func(t *testing.T) {
assert.Equal(t, "", containerRef(""))
})

t.Run("passes postgres URLs through", func(t *testing.T) {
assert.Equal(t, "postgresql://user@host:5432/db", containerRef("postgresql://user@host:5432/db"))
assert.Equal(t, "postgres://user@host:5432/db", containerRef("postgres://user@host:5432/db"))
})

t.Run("normalises Windows path separators", func(t *testing.T) {
if runtime.GOOS != "windows" {
t.Skip("path separator behaviour is Windows-only")
}
// On Windows, filepath.Join produces backslashes which the Linux
// container cannot read; containerRef must convert them.
ref := `supabase\.temp\pgdelta\catalog-baseline-17.6.1.106.json`
assert.Equal(t, "/workspace/supabase/.temp/pgdelta/catalog-baseline-17.6.1.106.json", containerRef(ref))
})

t.Run("leaves unix paths untouched", func(t *testing.T) {
ref := "supabase/.temp/pgdelta/catalog-baseline-17.6.1.106.json"
assert.Equal(t, "/workspace/supabase/.temp/pgdelta/catalog-baseline-17.6.1.106.json", containerRef(ref))
})
}
11 changes: 9 additions & 2 deletions internal/db/pgcache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import (
"strings"
"time"

"github.com/go-errors/errors"
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
"github.com/spf13/afero"
"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 @@ -252,8 +254,13 @@ 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
}
return strings.TrimSpace(stdout.String()), nil
snapshot := strings.TrimSpace(stdout.String())
if len(snapshot) == 0 {
return "", errors.Errorf("error exporting pg-delta catalog: edge-runtime script produced no output:\n%s", stderr.String())
}
return snapshot, nil
}
2 changes: 1 addition & 1 deletion internal/db/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ func initAuthJob(host string) utils.DockerJob {
return utils.DockerJob{
Image: utils.Config.Auth.Image,
Env: []string{
"API_EXTERNAL_URL=" + utils.Config.Api.ExternalUrl,
"API_EXTERNAL_URL=" + utils.Config.AuthExternalURL(),
"GOTRUE_LOG_LEVEL=error",
"GOTRUE_DB_DRIVER=postgres",
fmt.Sprintf("GOTRUE_DB_DATABASE_URL=postgresql://supabase_auth_admin:%s@%s:5432/postgres", utils.Config.Db.Password, host),
Expand Down
10 changes: 10 additions & 0 deletions internal/functions/serve/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,16 @@ EOF
container.HostConfig{
Binds: binds,
PortBindings: portBindings,
Resources: container.Resources{
// Raise nofile to accommodate FD usage from many concurrent Deno isolates (see #5151).
Ulimits: []*container.Ulimit{
{
Name: "nofile",
Soft: 65536,
Hard: 65536,
},
},
},
},
network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
Expand Down
6 changes: 6 additions & 0 deletions internal/login/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ func Run(ctx context.Context, stdout io.Writer, params RunParams) error {
}
handleTelemetryAfterLogin(ctx, params)
fmt.Println(loggedInMsg)
if hint := utils.SuggestClaudePlugin(); hint != "" {
fmt.Fprintln(os.Stderr, hint)
}
return nil
}

Expand Down Expand Up @@ -223,6 +226,9 @@ func Run(ctx context.Context, stdout io.Writer, params RunParams) error {

fmt.Fprintf(stdout, "Token %s created successfully.\n\n", utils.Bold(params.TokenName))
fmt.Fprintln(stdout, loggedInMsg)
if hint := utils.SuggestClaudePlugin(); hint != "" {
fmt.Fprintln(os.Stderr, hint)
}

return nil
}
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
Loading
Loading