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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ These workspaces should generally follow this structure:
- Standard scripts: `test`, `types:check`
- Standard devDependencies: `@tsconfig/bun`, `@types/bun`, `typescript`

Generic linting (`oxlint`), formatting (`oxfmt`), and unused-code analysis (`knip`) are repo-wide, not per-package: the tools are root devDependencies configured by `.oxlintrc.json`, `.oxfmtrc.json`, and `knip.json` at the repo root (knip's config maps each workspace under its `workspaces` key). Effect-specific linting covers `packages/stack` and all files under `apps/cli/src/commands/experimental/stack` through `.oxlintrc.effect.json`; run it with the root `lint:effect:check` or `lint:effect:fix` scripts. The root `check:all`/`fix:all` scripts are the sole repo-wide quality entrypoints and use Turbo to orchestrate the root-owned generic `lint:*`/`fmt:*`/`knip:*` scripts and package `types:check` targets; `fix:all` runs the Effect lint fix after those generic fixes complete. Package-local work can run `pnpm types:check` and the package's test scripts; `pnpm exec oxlint`, `pnpm exec oxfmt`, and `pnpm exec knip-bun` from the repo root also work directly.
Generic linting (`oxlint`), formatting (`oxfmt`), and unused-code analysis (`knip`) are repo-wide, not per-package: the tools are root devDependencies configured by `.oxlintrc.json`, `.oxfmtrc.json`, and `knip.json` at the repo root (knip's config maps each workspace under its `workspaces` key). Effect-specific linting covers `packages/stack`, all files under `apps/cli/src/commands/experimental/stack`, and the shared `apps/cli/src/command-internal/experimental-feature.ts` helper through `.oxlintrc.effect.json`; run it with the root `lint:effect:check` or `lint:effect:fix` scripts. The root `check:all`/`fix:all` scripts are the sole repo-wide quality entrypoints and use Turbo to orchestrate the root-owned generic `lint:*`/`fmt:*`/`knip:*` scripts and package `types:check` targets; `fix:all` runs the Effect lint fix after those generic fixes complete. Package-local work can run `pnpm types:check` and the package's test scripts; `pnpm exec oxlint`, `pnpm exec oxfmt`, and `pnpm exec knip-bun` from the repo root also work directly.

Expected exceptions:

Expand Down
1 change: 1 addition & 0 deletions apps/cli-go/pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ type (
S3Region string `toml:"s3_region" json:"s3_region"`
S3AccessKey string `toml:"s3_access_key" json:"s3_access_key"`
S3SecretKey string `toml:"s3_secret_key" json:"s3_secret_key"`
Stack bool `toml:"-" json:"stack"`
Webhooks *webhooks `toml:"webhooks" json:"webhooks"`
PgDelta *PgDeltaConfig `toml:"pgdelta" json:"pgdelta"`
Inspect inspect `toml:"inspect" json:"inspect"`
Expand Down
88 changes: 82 additions & 6 deletions apps/cli-go/pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,70 @@ instances = 3

assert.NoError(t, config.Load("", fsys))
})

for _, tt := range []struct {
name string
configData string
projectID string
want bool
}{
{
name: "base true",
configData: "[experimental]\nstack = true\n",
want: true,
},
{
name: "base false",
configData: "[experimental]\nstack = false\n",
want: false,
},
{
name: "remote true",
configData: "[remotes.prod]\nproject_id = \"abcdefghijklmnopqrst\"\n[remotes.prod.experimental]\nstack = true\n",
projectID: "abcdefghijklmnopqrst",
want: true,
},
{
name: "remote false",
configData: "[remotes.prod]\nproject_id = \"abcdefghijklmnopqrst\"\n[remotes.prod.experimental]\nstack = false\n",
projectID: "abcdefghijklmnopqrst",
want: false,
},
} {
t.Run("accepts experimental stack "+tt.name, func(t *testing.T) {
t.Setenv("SUPABASE_EXPERIMENTAL_STACK", "")
config := NewConfig()
config.ProjectId = tt.projectID
fsys := fs.MapFS{
"supabase/config.toml": &fs.MapFile{Data: []byte(tt.configData)},
}

require.NoError(t, config.Load("", fsys))
assert.Equal(t, tt.want, config.Experimental.Stack)
})
}

t.Run("does not emit experimental stack", func(t *testing.T) {
config := NewConfig()
config.Experimental.Stack = true

encodedToml, err := ToTomlBytes(config.Experimental)
require.NoError(t, err)
var encoded map[string]any
_, err = toml.Decode(string(encodedToml), &encoded)
require.NoError(t, err)
assert.NotContains(t, encoded, "stack")

var buf bytes.Buffer
require.NoError(t, config.Eject(&buf))
var rendered map[string]any
_, err = toml.Decode(buf.String(), &rendered)
require.NoError(t, err)
experimental, ok := rendered["experimental"].(map[string]any)
if assert.True(t, ok) {
assert.NotContains(t, experimental, "stack")
}
})
}

func TestRemoteOverride(t *testing.T) {
Expand All @@ -317,8 +381,12 @@ func TestRemoteOverride(t *testing.T) {
config.ProjectId = "bvikqvbczudanvggcord"
// Setup in-memory fs
fsys := fs.MapFS{
"supabase/config.toml": &fs.MapFile{Data: testInitConfigEmbed},
"supabase/templates/invite.html": &fs.MapFile{},
"supabase/config.toml": &fs.MapFile{Data: testInitConfigEmbed},
"supabase/templates/invite.html": &fs.MapFile{},
"supabase/templates/password_changed_notification.html": &fs.MapFile{},
"certs/my-cert.pem": &fs.MapFile{},
"certs/my-key.pem": &fs.MapFile{},
"supabase/signing_keys.json": &fs.MapFile{Data: []byte("[]")},
}
// Run test
t.Setenv("SUPABASE_AUTH_SITE_URL", "http://preview.com")
Expand All @@ -335,8 +403,12 @@ func TestRemoteOverride(t *testing.T) {
config.ProjectId = "vpefcjyosynxeiebfscx"
// Setup in-memory fs
fsys := fs.MapFS{
"supabase/config.toml": &fs.MapFile{Data: testInitConfigEmbed},
"supabase/templates/invite.html": &fs.MapFile{},
"supabase/config.toml": &fs.MapFile{Data: testInitConfigEmbed},
"supabase/templates/invite.html": &fs.MapFile{},
"supabase/templates/password_changed_notification.html": &fs.MapFile{},
"certs/my-cert.pem": &fs.MapFile{},
"certs/my-key.pem": &fs.MapFile{},
"supabase/signing_keys.json": &fs.MapFile{Data: []byte("[]")},
}
// Run test
t.Setenv("SUPABASE_AUTH_SITE_URL", "http://preview.com")
Expand All @@ -353,8 +425,12 @@ func TestRemoteOverride(t *testing.T) {
config := NewConfig()
// Setup in-memory fs
fsys := fs.MapFS{
"supabase/config.toml": &fs.MapFile{Data: testInitConfigEmbed},
"supabase/templates/invite.html": &fs.MapFile{},
"supabase/config.toml": &fs.MapFile{Data: testInitConfigEmbed},
"supabase/templates/invite.html": &fs.MapFile{},
"supabase/templates/password_changed_notification.html": &fs.MapFile{},
"certs/my-cert.pem": &fs.MapFile{},
"certs/my-key.pem": &fs.MapFile{},
"supabase/signing_keys.json": &fs.MapFile{Data: []byte("[]")},
}
// Run test
t.Setenv("TWILIO_AUTH_TOKEN", "token")
Expand Down
16 changes: 8 additions & 8 deletions apps/cli-go/pkg/config/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,10 @@ func TestNetworkRestrictionsDiff(t *testing.T) {
remoteConfig.Config.DbAllowedCidrsV6 = &[]string{"fd00::/8"}
diff, err := local.DiffWithRemote(remoteConfig)
assert.NoError(t, err)
assert.Contains(t, string(diff), "-db_allowed_cidrs = [\"10.0.0.0/8\"]")
assert.Contains(t, string(diff), "+db_allowed_cidrs = [\"192.168.1.0/24\"]")
assert.Contains(t, string(diff), "-db_allowed_cidrs_v6 = [\"2001:db8::/32\"]")
assert.Contains(t, string(diff), "+db_allowed_cidrs_v6 = [\"fd00::/8\"]")
assert.Contains(t, string(diff), "-allowed_cidrs = [\"10.0.0.0/8\"]")
assert.Contains(t, string(diff), "+allowed_cidrs = [\"192.168.1.0/24\"]")
assert.Contains(t, string(diff), "-allowed_cidrs_v6 = [\"fd00::/8\"]")
assert.Contains(t, string(diff), "+allowed_cidrs_v6 = [\"2001:db8::/32\"]")
})

t.Run("no differences", func(t *testing.T) {
Expand Down Expand Up @@ -273,9 +273,9 @@ func TestNetworkRestrictionsDiff(t *testing.T) {
remoteConfig.Config.DbAllowedCidrsV6 = &[]string{"::/0"}
diff, err := local.DiffWithRemote(remoteConfig)
assert.NoError(t, err)
assert.Contains(t, string(diff), "-db_allowed_cidrs = [\"0.0.0.0/0\"]")
assert.Contains(t, string(diff), "+db_allowed_cidrs = []")
assert.Contains(t, string(diff), "-db_allowed_cidrs_v6 = [\"::/0\"]")
assert.Contains(t, string(diff), "+db_allowed_cidrs_v6 = []")
assert.Contains(t, string(diff), "-allowed_cidrs = [\"0.0.0.0/0\"]")
assert.Contains(t, string(diff), "+allowed_cidrs = []")
assert.Contains(t, string(diff), "-allowed_cidrs_v6 = [\"::/0\"]")
assert.Contains(t, string(diff), "+allowed_cidrs_v6 = []")
})
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -23,7 +23,7 @@
@@ -28,7 +28,7 @@
web3 = 0

[captcha]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -23,9 +23,9 @@
@@ -28,9 +28,9 @@
web3 = 0

[captcha]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -47,13 +47,13 @@
@@ -49,13 +49,13 @@
inactivity_timeout = "0s"

[email]
Expand All @@ -22,7 +22,7 @@ diff remote[auth] local[auth]
[email.template]
[email.template.confirmation]
content_path = ""
@@ -69,25 +69,25 @@
@@ -71,25 +71,25 @@
content_path = ""
[email.notification]
[email.notification.email_changed]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -47,62 +47,74 @@
@@ -49,62 +49,74 @@
inactivity_timeout = "0s"

[email]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -84,7 +84,7 @@
@@ -89,7 +89,7 @@

[external]
[external.apple]
Expand All @@ -10,9 +10,9 @@ diff remote[auth] local[auth]
client_id = "test-client-1,test-client-2"
secret = "hash:ce62bb9bcced294fd4afe668f8ab3b50a89cf433093c526fffa3d0e46bf55252"
url = ""
@@ -91,9 +91,9 @@
redirect_uri = ""
@@ -97,9 +97,9 @@
skip_nonce_check = false
email_optional = false
[external.azure]
-enabled = false
-client_id = ""
Expand All @@ -23,9 +23,9 @@ diff remote[auth] local[auth]
url = ""
redirect_uri = ""
skip_nonce_check = false
@@ -140,7 +140,7 @@
redirect_uri = ""
@@ -153,7 +153,7 @@
skip_nonce_check = false
email_optional = false
[external.google]
-enabled = true
+enabled = false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -24,23 +24,23 @@
@@ -29,23 +29,23 @@

[hook]
[hook.mfa_verification_attempt]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -24,25 +24,25 @@
@@ -29,25 +29,25 @@

[hook]
[hook.mfa_verification_attempt]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -25,16 +25,16 @@
@@ -30,16 +30,16 @@
[hook]

[mfa]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -14,12 +14,12 @@
@@ -19,12 +19,12 @@
service_role_key = ""

[rate_limit]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -53,7 +53,7 @@
@@ -58,7 +58,7 @@
otp_expiry = 0

[sms]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -53,12 +53,12 @@
@@ -58,12 +58,12 @@
otp_expiry = 0

[sms]
Expand All @@ -19,7 +19,7 @@ diff remote[auth] local[auth]
account_sid = ""
message_service_sid = ""
auth_token = ""
@@ -81,8 +81,6 @@
@@ -86,8 +86,6 @@
api_key = ""
api_secret = ""
[sms.test_otp]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
diff remote[auth] local[auth]
--- remote[auth]
+++ local[auth]
@@ -53,12 +53,12 @@
@@ -58,12 +58,12 @@
otp_expiry = 0

[sms]
Expand All @@ -19,7 +19,7 @@ diff remote[auth] local[auth]
account_sid = ""
message_service_sid = ""
auth_token = ""
@@ -68,9 +68,9 @@
@@ -73,9 +73,9 @@
message_service_sid = ""
auth_token = ""
[sms.messagebird]
Expand All @@ -32,7 +32,7 @@ diff remote[auth] local[auth]
[sms.textlocal]
enabled = false
sender = ""
@@ -81,6 +81,7 @@
@@ -86,6 +86,7 @@
api_key = ""
api_secret = ""
[sms.test_otp]
Expand Down
12 changes: 5 additions & 7 deletions apps/cli-go/pkg/config/updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ func TestUpdateAuthConfig(t *testing.T) {
Get("/v1/projects/test-project/config/auth").
Reply(http.StatusOK).
JSON(v1API.AuthConfigResponseOutput{
SiteUrl: nullable.NewNullableWithValue("http://localhost:3000"),
SiteUrl: nullable.NewNullableWithValue("http://localhost:3000"),
SmtpAdminEmail: nullable.NewNullableWithValue(openapi_types.Email("abc@example.com")),
})
gock.New(server).
Patch("/v1/projects/test-project/config/auth").
Expand All @@ -224,7 +225,9 @@ func TestUpdateAuthConfig(t *testing.T) {
gock.New(server).
Get("/v1/projects/test-project/config/auth").
Reply(http.StatusOK).
JSON(v1API.AuthConfigResponseOutput{})
JSON(v1API.AuthConfigResponseOutput{
SmtpAdminEmail: nullable.NewNullableWithValue(openapi_types.Email("abc@example.com")),
})
// Run test
err := updater.UpdateAuthConfig(context.Background(), "test-project", auth{
Enabled: true,
Expand Down Expand Up @@ -331,11 +334,6 @@ func TestUpdateRemoteConfig(t *testing.T) {
JSON(v1API.PostgresConfigResponseOutput{
MaxConnections: cast.Ptr(cast.UintToInt(100)),
})
// Network config
gock.New(server).
Get("/v1/projects/test-project/network-restrictions").
Reply(http.StatusOK).
JSON(v1API.V1GetNetworkRestrictionsResponse{})
// Auth config
gock.New(server).
Get("/v1/projects/test-project/config/auth").
Expand Down
Loading
Loading