Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support passing --env-file flag to functions deploy command. #2995

Closed
wants to merge 2 commits into from
Closed
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
5 changes: 3 additions & 2 deletions cmd/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ var (
noVerifyJWT = new(bool)
useLegacyBundle bool
importMapPath string
envFilePath string

functionsDeployCmd = &cobra.Command{
Use: "deploy [Function name]",
Expand All @@ -65,7 +66,7 @@ var (
if !cmd.Flags().Changed("no-verify-jwt") {
noVerifyJWT = nil
}
return deploy.Run(cmd.Context(), args, flags.ProjectRef, noVerifyJWT, importMapPath, afero.NewOsFs())
return deploy.Run(cmd.Context(), args, flags.ProjectRef, noVerifyJWT, importMapPath, envFilePath, afero.NewOsFs())
},
}

Expand All @@ -82,7 +83,6 @@ var (
},
}

envFilePath string
inspectBrk bool
inspectMode = utils.EnumFlag{
Allowed: []string{
Expand Down Expand Up @@ -127,6 +127,7 @@ func init() {
functionsDeployCmd.Flags().StringVar(&flags.ProjectRef, "project-ref", "", "Project ref of the Supabase project.")
functionsDeployCmd.Flags().BoolVar(&useLegacyBundle, "legacy-bundle", false, "Use legacy bundling mechanism.")
functionsDeployCmd.Flags().StringVar(&importMapPath, "import-map", "", "Path to import map file.")
functionsDeployCmd.Flags().StringVar(&envFilePath, "env-file", "", "Path to an env file.")
cobra.CheckErr(functionsDeployCmd.Flags().MarkHidden("legacy-bundle"))
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.")
Expand Down
3 changes: 2 additions & 1 deletion examples/functions-deploy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

"github.com/supabase/cli/pkg/api"
"github.com/supabase/cli/pkg/config"
"github.com/supabase/cli/pkg/function"

Check failure on line 13 in examples/functions-deploy/main.go

View workflow job for this annotation

GitHub Actions / Lint

could not import github.com/supabase/cli/pkg/function (-: # github.com/supabase/cli/pkg/function
)

func main() {
Expand All @@ -29,7 +29,8 @@
Entrypoint: "supabase/functions/my-slug/index.ts",
ImportMap: "supabase/functions/import_map.json",
}}
return functionClient.UpsertFunctions(ctx, fc)
envFilePath := ""
return functionClient.UpsertFunctions(ctx, fc, envFilePath)
}

func newAPIClient(token string) api.ClientWithResponses {
Expand Down
18 changes: 16 additions & 2 deletions internal/functions/deploy/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"github.com/spf13/afero"
"github.com/spf13/viper"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/pkg/function"

Check failure on line 17 in internal/functions/deploy/bundle.go

View workflow job for this annotation

GitHub Actions / Lint

could not import github.com/supabase/cli/pkg/function (-: # github.com/supabase/cli/pkg/function
)

type dockerBundler struct {
Expand All @@ -25,7 +25,21 @@
return &dockerBundler{fsys: fsys}
}

func (b *dockerBundler) Bundle(ctx context.Context, entrypoint string, importMap string, output io.Writer) error {
func (b *dockerBundler) Bundle(ctx context.Context, entrypoint string, importMap string, envFilePath string, output io.Writer) error {
// read env file
if envFilePath == "" {
if f, err := b.fsys.Stat(utils.FallbackEnvFilePath); err == nil && !f.IsDir() {
envFilePath = utils.FallbackEnvFilePath
}
} else if !filepath.IsAbs(envFilePath) {
envFilePath = filepath.Join(utils.CurrentDirAbs, envFilePath)
}
// 2. Parse user defined env
env, err := function.ParseEnvFile(envFilePath, b.fsys)
if err != nil {
return err
}

// Create temp directory to store generated eszip
slug := filepath.Base(filepath.Dir(entrypoint))
fmt.Fprintln(os.Stderr, "Bundling Function:", utils.Bold(slug))
Expand Down Expand Up @@ -62,7 +76,7 @@
ctx,
container.Config{
Image: utils.Config.EdgeRuntime.Image,
Env: []string{},
Env: env,
Cmd: cmd,
WorkingDir: utils.ToDockerPath(cwd),
},
Expand Down
2 changes: 1 addition & 1 deletion internal/functions/deploy/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestDockerBundle(t *testing.T) {
apitest.MockDockerStart(utils.Docker, imageUrl, containerId)
require.NoError(t, apitest.MockDockerLogsExitCode(utils.Docker, containerId, 1))
// Run test
err = NewDockerBundler(fsys).Bundle(context.Background(), "", "", &body)
err = NewDockerBundler(fsys).Bundle(context.Background(), "", "", "", &body)
// Check error
assert.ErrorContains(t, err, "error running container: exit 1")
assert.Empty(t, apitest.ListUnmatchedRequests())
Expand Down
4 changes: 2 additions & 2 deletions internal/functions/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/supabase/cli/pkg/function"
)

func Run(ctx context.Context, slugs []string, projectRef string, noVerifyJWT *bool, importMapPath string, fsys afero.Fs) error {
func Run(ctx context.Context, slugs []string, projectRef string, noVerifyJWT *bool, importMapPath string, envFilePath string, fsys afero.Fs) error {
// Load function config and project id
if err := utils.LoadConfigFS(fsys); err != nil {
return err
Expand All @@ -38,7 +38,7 @@ func Run(ctx context.Context, slugs []string, projectRef string, noVerifyJWT *bo
return err
}
api := function.NewEdgeRuntimeAPI(projectRef, *utils.GetSupabase(), NewDockerBundler(fsys))
if err := api.UpsertFunctions(ctx, functionConfig); err != nil {
if err := api.UpsertFunctions(ctx, functionConfig, envFilePath); err != nil {
return err
}
fmt.Printf("Deployed Functions on project %s: %s\n", utils.Aqua(projectRef), strings.Join(slugs, ", "))
Expand Down
14 changes: 7 additions & 7 deletions internal/functions/deploy/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func TestDeployCommand(t *testing.T) {
}
// Run test
noVerifyJWT := true
err = Run(context.Background(), functions, project, &noVerifyJWT, "", fsys)
err = Run(context.Background(), functions, project, &noVerifyJWT, "", "", fsys)
// Check error
assert.NoError(t, err)
assert.Empty(t, apitest.ListUnmatchedRequests())
Expand Down Expand Up @@ -116,7 +116,7 @@ import_map = "./import_map.json"
outputDir := filepath.Join(utils.TempDir, fmt.Sprintf(".output_%s", slug))
require.NoError(t, afero.WriteFile(fsys, filepath.Join(outputDir, "output.eszip"), []byte(""), 0644))
// Run test
err = Run(context.Background(), nil, project, nil, "", fsys)
err = Run(context.Background(), nil, project, nil, "", "", fsys)
// Check error
assert.NoError(t, err)
assert.Empty(t, apitest.ListUnmatchedRequests())
Expand Down Expand Up @@ -168,7 +168,7 @@ import_map = "./import_map.json"
outputDir := filepath.Join(utils.TempDir, ".output_enabled-func")
require.NoError(t, afero.WriteFile(fsys, filepath.Join(outputDir, "output.eszip"), []byte(""), 0644))
// Run test
err = Run(context.Background(), nil, project, nil, "", fsys)
err = Run(context.Background(), nil, project, nil, "", "", fsys)
// Check error
assert.NoError(t, err)
assert.Empty(t, apitest.ListUnmatchedRequests())
Expand All @@ -179,7 +179,7 @@ import_map = "./import_map.json"
fsys := afero.NewMemMapFs()
require.NoError(t, utils.WriteConfig(fsys, false))
// Run test
err := Run(context.Background(), []string{"_invalid"}, "", nil, "", fsys)
err := Run(context.Background(), []string{"_invalid"}, "", nil, "", "", fsys)
// Check error
assert.ErrorContains(t, err, "Invalid Function name.")
})
Expand All @@ -189,7 +189,7 @@ import_map = "./import_map.json"
fsys := afero.NewMemMapFs()
require.NoError(t, utils.WriteConfig(fsys, false))
// Run test
err := Run(context.Background(), nil, "", nil, "", fsys)
err := Run(context.Background(), nil, "", nil, "", "", fsys)
// Check error
assert.ErrorContains(t, err, "No Functions specified or found in supabase/functions")
})
Expand Down Expand Up @@ -234,7 +234,7 @@ verify_jwt = false
outputDir := filepath.Join(utils.TempDir, fmt.Sprintf(".output_%s", slug))
require.NoError(t, afero.WriteFile(fsys, filepath.Join(outputDir, "output.eszip"), []byte(""), 0644))
// Run test
assert.NoError(t, Run(context.Background(), []string{slug}, project, nil, "", fsys))
assert.NoError(t, Run(context.Background(), []string{slug}, project, nil, "", "", fsys))
// Validate api
assert.Empty(t, apitest.ListUnmatchedRequests())
})
Expand Down Expand Up @@ -280,7 +280,7 @@ verify_jwt = false
require.NoError(t, afero.WriteFile(fsys, filepath.Join(outputDir, "output.eszip"), []byte(""), 0644))
// Run test
noVerifyJwt := false
assert.NoError(t, Run(context.Background(), []string{slug}, project, &noVerifyJwt, "", fsys))
assert.NoError(t, Run(context.Background(), []string{slug}, project, &noVerifyJwt, "", "", fsys))
// Validate api
assert.Empty(t, apitest.ListUnmatchedRequests())
})
Expand Down
23 changes: 2 additions & 21 deletions internal/functions/serve/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
"github.com/spf13/afero"
"github.com/spf13/viper"
"github.com/supabase/cli/internal/functions/deploy"
"github.com/supabase/cli/internal/secrets/set"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/pkg/function"

Check failure on line 21 in internal/functions/serve/serve.go

View workflow job for this annotation

GitHub Actions / Lint

could not import github.com/supabase/cli/pkg/function (-: # github.com/supabase/cli/pkg/function
)

type InspectMode string
Expand Down Expand Up @@ -105,7 +105,7 @@
envFilePath = filepath.Join(utils.CurrentDirAbs, envFilePath)
}
// 2. Parse user defined env
env, err := parseEnvFile(envFilePath, fsys)
env, err := function.ParseEnvFile(envFilePath, fsys)
if err != nil {
return err
}
Expand Down Expand Up @@ -187,25 +187,6 @@
return err
}

func parseEnvFile(envFilePath string, fsys afero.Fs) ([]string, error) {
env := []string{}
if len(envFilePath) == 0 {
return env, nil
}
envMap, err := set.ParseEnvFile(envFilePath, fsys)
if err != nil {
return env, err
}
for name, value := range envMap {
if strings.HasPrefix(name, "SUPABASE_") {
fmt.Fprintln(os.Stderr, "Env name cannot start with SUPABASE_, skipping: "+name)
continue
}
env = append(env, name+"="+value)
}
return env, nil
}

func populatePerFunctionConfigs(cwd, importMapPath string, noVerifyJWT *bool, fsys afero.Fs) ([]string, string, error) {
slugs, err := deploy.GetFunctionSlugs(fsys)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/function/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type EdgeRuntimeAPI struct {
}

type EszipBundler interface {
Bundle(ctx context.Context, entrypoint string, importMap string, output io.Writer) error
Bundle(ctx context.Context, entrypoint string, importMap string, envFilePath string, output io.Writer) error
}

func NewEdgeRuntimeAPI(project string, client api.ClientWithResponses, bundler EszipBundler) EdgeRuntimeAPI {
Expand Down
4 changes: 2 additions & 2 deletions pkg/function/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const (
maxRetries = 3
)

func (s *EdgeRuntimeAPI) UpsertFunctions(ctx context.Context, functionConfig config.FunctionConfig, filter ...func(string) bool) error {
func (s *EdgeRuntimeAPI) UpsertFunctions(ctx context.Context, functionConfig config.FunctionConfig, envFilePath string, filter ...func(string) bool) error {
var result []api.FunctionResponse
if resp, err := s.client.V1ListAllFunctionsWithResponse(ctx, s.project); err != nil {
return errors.Errorf("failed to list functions: %w", err)
Expand All @@ -45,7 +45,7 @@ func (s *EdgeRuntimeAPI) UpsertFunctions(ctx context.Context, functionConfig con
}
}
var body bytes.Buffer
if err := s.eszip.Bundle(ctx, function.Entrypoint, function.ImportMap, &body); err != nil {
if err := s.eszip.Bundle(ctx, function.Entrypoint, function.ImportMap, envFilePath, &body); err != nil {
return err
}
// Update if function already exists
Expand Down
10 changes: 5 additions & 5 deletions pkg/function/batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
type MockBundler struct {
}

func (b *MockBundler) Bundle(ctx context.Context, entrypoint string, importMap string, output io.Writer) error {
func (b *MockBundler) Bundle(ctx context.Context, entrypoint string, importMap string, envFilePath string, output io.Writer) error {
return nil
}

Expand All @@ -38,7 +38,7 @@ func TestUpsertFunctions(t *testing.T) {
Get("/v1/projects/" + mockProject + "/functions").
ReplyError(errors.New("network error"))
// Run test
err := client.UpsertFunctions(context.Background(), nil)
err := client.UpsertFunctions(context.Background(), nil, "")
// Check error
assert.ErrorContains(t, err, "network error")
})
Expand All @@ -50,7 +50,7 @@ func TestUpsertFunctions(t *testing.T) {
Get("/v1/projects/" + mockProject + "/functions").
Reply(http.StatusServiceUnavailable)
// Run test
err := client.UpsertFunctions(context.Background(), nil)
err := client.UpsertFunctions(context.Background(), nil, "")
// Check error
assert.ErrorContains(t, err, "unexpected status 503:")
})
Expand All @@ -75,7 +75,7 @@ func TestUpsertFunctions(t *testing.T) {
// Run test
err := client.UpsertFunctions(context.Background(), config.FunctionConfig{
"test": {},
})
}, "")
// Check error
assert.NoError(t, err)
})
Expand All @@ -100,7 +100,7 @@ func TestUpsertFunctions(t *testing.T) {
// Run test
err := client.UpsertFunctions(context.Background(), config.FunctionConfig{
"test": {},
})
}, "")
// Check error
assert.NoError(t, err)
})
Expand Down
19 changes: 18 additions & 1 deletion pkg/function/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

"github.com/andybalholm/brotli"
"github.com/go-errors/errors"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/utils"
)

type nativeBundler struct {
Expand All @@ -28,7 +30,21 @@
// Use a package private variable to allow testing without gosec complaining about G204
var edgeRuntimeBin = "edge-runtime"

func (b *nativeBundler) Bundle(ctx context.Context, entrypoint string, importMap string, output io.Writer) error {
func (b *nativeBundler) Bundle(ctx context.Context, entrypoint string, importMap string, envFilePath string, output io.Writer) error {
// read env file
if envFilePath == "" {
if f, err := fs.Stat(b.fsys, utils.FallbackEnvFilePath); err == nil && !f.IsDir() {
envFilePath = utils.FallbackEnvFilePath
}
} else if !filepath.IsAbs(envFilePath) {
envFilePath = filepath.Join(utils.CurrentDirAbs, envFilePath)
}
// 2. Parse user defined env
env, err := ParseEnvFile(envFilePath, afero.FromIOFS{b.fsys})

Check failure on line 43 in pkg/function/bundle.go

View workflow job for this annotation

GitHub Actions / Start

undefined: ParseEnvFile

Check failure on line 43 in pkg/function/bundle.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: ParseEnvFile) (typecheck)

Check failure on line 43 in pkg/function/bundle.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: ParseEnvFile) (typecheck)

Check failure on line 43 in pkg/function/bundle.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: ParseEnvFile) (typecheck)

Check failure on line 43 in pkg/function/bundle.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: ParseEnvFile (typecheck)

Check failure on line 43 in pkg/function/bundle.go

View workflow job for this annotation

GitHub Actions / Test

undefined: ParseEnvFile

Check failure on line 43 in pkg/function/bundle.go

View workflow job for this annotation

GitHub Actions / Test

undefined: ParseEnvFile
if err != nil {
return err
}

slug := filepath.Base(filepath.Dir(entrypoint))
outputPath := filepath.Join(b.tempDir, slug+".eszip")
// TODO: make edge runtime write to stdout
Expand All @@ -39,6 +55,7 @@
cmd := exec.CommandContext(ctx, edgeRuntimeBin, args...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
cmd.Env = env
if err := cmd.Run(); err != nil {
return errors.Errorf("failed to bundle function: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/function/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestBundleFunction(t *testing.T) {
// Setup mock bundler
bundler := nativeBundler{fsys: fsys}
// Run test
err := bundler.Bundle(context.Background(), "hello/index.ts", "", &body)
err := bundler.Bundle(context.Background(), "hello/index.ts", "", "", &body)
// Check error
assert.NoError(t, err)
assert.Equal(t, compressedEszipMagicID+";", body.String())
Expand Down
Loading