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
10 changes: 8 additions & 2 deletions cmd/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,18 +95,23 @@ var (
}

envFilePath string
serveAll bool

functionsServeCmd = &cobra.Command{
Use: "serve <Function name>",
Short: "Serve a Function locally",
Args: cobra.ExactArgs(1),
Args: cobra.RangeArgs(0, 1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx, _ := signal.NotifyContext(cmd.Context(), os.Interrupt)
// Fallback to config if user did not set the flag.
if !cmd.Flags().Changed("no-verify-jwt") {
noVerifyJWT = nil
}
return serve.Run(ctx, args[0], envFilePath, noVerifyJWT, importMapPath, afero.NewOsFs())
slug := ""
if len(args) > 1 {
slug = args[0]
}
return serve.Run(ctx, slug, envFilePath, noVerifyJWT, importMapPath, serveAll, afero.NewOsFs())
},
}
)
Expand All @@ -120,6 +125,7 @@ func init() {
functionsServeCmd.Flags().BoolVar(noVerifyJWT, "no-verify-jwt", false, "Disable JWT verification for the Function.")
functionsServeCmd.Flags().StringVar(&envFilePath, "env-file", "", "Path to an env file to be populated to the Function environment.")
functionsServeCmd.Flags().StringVar(&importMapPath, "import-map", "", "Path to import map file.")
functionsServeCmd.Flags().BoolVar(&serveAll, "all", false, "Serve all functions (caution: Experimental feature)")
functionsDownloadCmd.Flags().StringVar(&projectRef, "project-ref", "", "Project ref of the Supabase project.")
functionsCmd.AddCommand(functionsDeleteCmd)
functionsCmd.AddCommand(functionsDeployCmd)
Expand Down
2 changes: 2 additions & 0 deletions internal/db/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func DiffSchema(ctx context.Context, source, target string, schema []string, p u
utils.DifferImage,
nil,
args,
nil,
stream.Stdout(),
stream.Stderr(),
); err != nil {
Expand All @@ -95,6 +96,7 @@ func DiffSchema(ctx context.Context, source, target string, schema []string, p u
utils.DifferImage,
nil,
append([]string{"--schema", s}, args...),
nil,
stream.Stdout(),
stream.Stderr(),
); err != nil {
Expand Down
92 changes: 91 additions & 1 deletion internal/functions/serve/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ func ParseEnvFile(envFilePath string) ([]string, error) {
return env, nil
}

func Run(ctx context.Context, slug string, envFilePath string, noVerifyJWT *bool, importMapPath string, fsys afero.Fs) error {
func Run(ctx context.Context, slug string, envFilePath string, noVerifyJWT *bool, importMapPath string, serveAll bool, fsys afero.Fs) error {
if serveAll {
return runServeAll(ctx, envFilePath, noVerifyJWT, importMapPath, fsys)
}

// 1. Sanity checks.
{
if err := utils.LoadConfigFS(fsys); err != nil {
Expand Down Expand Up @@ -216,3 +220,89 @@ func Run(ctx context.Context, slug string, envFilePath string, noVerifyJWT *bool
fmt.Println("Stopped serving " + utils.Bold(localFuncDir))
return nil
}

func runServeAll(ctx context.Context, envFilePath string, noVerifyJWT *bool, importMapPath string, fsys afero.Fs) error {
// 1. Sanity checks.
{
if err := utils.LoadConfigFS(fsys); err != nil {
return err
}
if err := utils.AssertSupabaseDbIsRunning(); err != nil {
return err
}
if envFilePath != "" {
if _, err := fsys.Stat(envFilePath); err != nil {
return fmt.Errorf("Failed to read env file: %w", err)
}
}
if importMapPath != "" {
// skip
} else if f, err := fsys.Stat(utils.FallbackImportMapPath); err == nil && !f.IsDir() {
importMapPath = utils.FallbackImportMapPath
}
if importMapPath != "" {
if _, err := fsys.Stat(importMapPath); err != nil {
return fmt.Errorf("Failed to read import map: %w", err)
}
}
}

// 2. Parse user defined env
userEnv, err := ParseEnvFile(envFilePath)
if err != nil {
return err
}

// 3. Start container
{
_ = utils.Docker.ContainerRemove(ctx, utils.DenoRelayId, types.ContainerRemoveOptions{
RemoveVolumes: true,
Force: true,
})

env := []string{
"JWT_SECRET=" + utils.JWTSecret,
"SUPABASE_URL=http://" + utils.KongId + ":8000",
"SUPABASE_ANON_KEY=" + utils.AnonKey,
"SUPABASE_SERVICE_ROLE_KEY=" + utils.ServiceRoleKey,
"SUPABASE_DB_URL=postgresql://postgres:postgres@localhost:" + strconv.FormatUint(uint64(utils.Config.Db.Port), 10) + "/postgres",
}
verifyJWTEnv := "VERIFY_JWT=true"
if noVerifyJWT != nil {
verifyJWTEnv = "VERIFY_JWT=false"
}
env = append(env, verifyJWTEnv)

cwd, err := os.Getwd()
if err != nil {
return err
}

binds := []string{
filepath.Join(cwd, utils.FunctionsDir) + ":" + relayFuncDir + ":ro,z",
utils.DenoRelayId + ":/root/.cache/deno:rw,z",
}
// If a import map path is explcitly provided, mount it as a separate file
if importMapPath != "" {
binds = append(binds, filepath.Join(cwd, importMapPath)+":"+customDockerImportMapPath+":ro,z")
}

fmt.Println("Serving " + utils.Bold(utils.FunctionsDir))

if err := utils.DockerRunOnceWithStream(
ctx,
utils.EdgeRuntimeImage,
append(env, userEnv...),
[]string{"start", "--dir", relayFuncDir, "-p", "8081"},
binds,
os.Stdout,
os.Stderr,
); err != nil {
return err
}
}

fmt.Println("Stopped serving " + utils.Bold(utils.FunctionsDir))
return nil

}
2 changes: 1 addition & 1 deletion internal/functions/serve/serve_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestServeCommand(t *testing.T) {
Post("/v" + utils.Docker.ClientVersion() + "/containers").
Reply(http.StatusServiceUnavailable)
// Run test
err := Run(context.Background(), "test-func", "", nil, "", fsys)
err := Run(context.Background(), "test-func", "", nil, "", false, fsys)
// Check error
assert.ErrorContains(t, err, "request returned Service Unavailable for API route and version http://localhost/v1.41/containers/supabase_deno_relay_serve/exec")
assert.Empty(t, apitest.ListUnmatchedRequests())
Expand Down
10 changes: 7 additions & 3 deletions internal/utils/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,19 +302,23 @@ func DockerRunOnce(ctx context.Context, image string, env []string, cmd []string
stderr = os.Stderr
}
var out bytes.Buffer
err := DockerRunOnceWithStream(ctx, image, env, cmd, &out, stderr)
err := DockerRunOnceWithStream(ctx, image, env, cmd, nil, &out, stderr)
return out.String(), err
}

func DockerRunOnceWithStream(ctx context.Context, image string, env []string, cmd []string, stdout, stderr io.Writer) error {
func DockerRunOnceWithStream(ctx context.Context, image string, env, cmd, binds []string, stdout, stderr io.Writer) error {
// Cannot rely on docker's auto remove because
// 1. We must inspect exit code after container stops
// 2. Context cancellation may happen after start
container, err := DockerStart(ctx, container.Config{
Image: image,
Env: env,
Cmd: cmd,
}, container.HostConfig{}, "")
}, container.HostConfig{
Binds: binds,
// Allows containerized functions on Linux to reach host OS
ExtraHosts: []string{"host.docker.internal:host-gateway"},
}, "")
if err != nil {
return err
}
Expand Down
19 changes: 10 additions & 9 deletions internal/utils/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ const (
Pg14Image = "supabase/postgres:14.1.0.89"
Pg15Image = "supabase/postgres:15.1.0.33"
// Append to ServiceImages when adding new dependencies below
KongImage = "library/kong:2.8.1"
InbucketImage = "inbucket/inbucket:3.0.3"
PostgrestImage = "postgrest/postgrest:v10.1.1.20221215"
DifferImage = "supabase/pgadmin-schema-diff:cli-0.0.5"
MigraImage = "djrobstep/migra:3.0.1621480950"
PgmetaImage = "supabase/postgres-meta:v0.60.3"
StudioImage = "supabase/studio:20230127-6bfd87b"
DenoRelayImage = "supabase/deno-relay:v1.5.0"
ImageProxyImage = "darthsim/imgproxy:v3.8.0"
KongImage = "library/kong:2.8.1"
InbucketImage = "inbucket/inbucket:3.0.3"
PostgrestImage = "postgrest/postgrest:v10.1.1.20221215"
DifferImage = "supabase/pgadmin-schema-diff:cli-0.0.5"
MigraImage = "djrobstep/migra:3.0.1621480950"
PgmetaImage = "supabase/postgres-meta:v0.60.3"
StudioImage = "supabase/studio:20230127-6bfd87b"
DenoRelayImage = "supabase/deno-relay:v1.5.0"
ImageProxyImage = "darthsim/imgproxy:v3.8.0"
EdgeRuntimeImage = "supabase/edge-runtime:v1.0.7"
// Update initial schemas in internal/utils/templates/initial_schemas when
// updating any one of these.
GotrueImage = "supabase/gotrue:v2.40.1"
Expand Down