• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / cli / 18926015369

30 Oct 2025 12:29AM UTC coverage: 54.718% (-0.01%) from 54.728%
18926015369

Pull #4372

github

web-flow
Merge 8c4304595 into 891a5df91
Pull Request #4372: fix: toggle `DENO_NO_PACKAGE_JSON` conditionally

11 of 16 new or added lines in 2 files covered. (68.75%)

5 existing lines in 1 file now uncovered.

6396 of 11689 relevant lines covered (54.72%)

6.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.48
/internal/functions/deploy/bundle.go
1
package deploy
2

3
import (
4
        "context"
5
        "fmt"
6
        "io"
7
        "os"
8
        "path/filepath"
9
        "strings"
10

11
        "github.com/docker/docker/api/types/container"
12
        "github.com/docker/docker/api/types/network"
13
        "github.com/go-errors/errors"
14
        "github.com/spf13/afero"
15
        "github.com/spf13/viper"
16
        "github.com/supabase/cli/internal/utils"
17
        "github.com/supabase/cli/pkg/function"
18
)
19

20
type dockerBundler struct {
21
        fsys afero.Fs
22
}
23

24
func NewDockerBundler(fsys afero.Fs) function.EszipBundler {
7✔
25
        return &dockerBundler{fsys: fsys}
7✔
26
}
7✔
27

28
func (b *dockerBundler) Bundle(ctx context.Context, slug, entrypoint, importMap string, staticFiles []string, usePackageJson bool, output io.Writer) (function.FunctionDeployMetadata, error) {
8✔
29
        meta := function.NewMetadata(slug, entrypoint, importMap, staticFiles)
8✔
30
        fmt.Fprintln(os.Stderr, "Bundling Function:", utils.Bold(slug))
8✔
31
        cwd, err := os.Getwd()
8✔
32
        if err != nil {
8✔
33
                return meta, errors.Errorf("failed to get working directory: %w", err)
×
34
        }
×
35
        // BitBucket pipelines require docker bind mounts to be world writable
36
        hostOutputDir := filepath.Join(utils.TempDir, fmt.Sprintf(".output_%s", slug))
8✔
37
        if err := b.fsys.MkdirAll(hostOutputDir, 0777); err != nil {
9✔
38
                return meta, errors.Errorf("failed to mkdir: %w", err)
1✔
39
        }
1✔
40
        defer func() {
14✔
41
                if err := b.fsys.RemoveAll(hostOutputDir); err != nil {
7✔
42
                        fmt.Fprintln(os.Stderr, err)
×
43
                }
×
44
        }()
45
        // Create bind mounts
46
        binds, err := GetBindMounts(cwd, utils.FunctionsDir, hostOutputDir, entrypoint, importMap, b.fsys)
7✔
47
        if err != nil {
7✔
48
                return meta, err
×
49
        }
×
50
        hostOutputPath := filepath.Join(hostOutputDir, "output.eszip")
7✔
51
        // Create exec command
7✔
52
        cmd := []string{"bundle", "--entrypoint", utils.ToDockerPath(entrypoint), "--output", utils.ToDockerPath(hostOutputPath)}
7✔
53
        if len(importMap) > 0 {
9✔
54
                cmd = append(cmd, "--import-map", utils.ToDockerPath(importMap))
2✔
55
        }
2✔
56
        for _, sf := range staticFiles {
8✔
57
                cmd = append(cmd, "--static", utils.ToDockerPath(sf))
1✔
58
        }
1✔
59
        if viper.GetBool("DEBUG") {
7✔
60
                cmd = append(cmd, "--verbose")
×
61
        }
×
62
        cmd = append(cmd, function.BundleFlags...)
7✔
63

7✔
64
        env := []string{}
7✔
65
        denoNoPackageJsonValue := "1"
7✔
66
        if usePackageJson {
7✔
NEW
67
                denoNoPackageJsonValue = "0"
×
NEW
68
        }
×
69
        if custom_registry := os.Getenv("NPM_CONFIG_REGISTRY"); custom_registry != "" {
7✔
70
                env = append(env, "NPM_CONFIG_REGISTRY="+custom_registry)
×
71
        }
×
72
        if deno_no_package_json := os.Getenv("DENO_NO_PACKAGE_JSON"); deno_no_package_json != "" {
7✔
NEW
73
                env = append(env, "DENO_NO_PACKAGE_JSON="+deno_no_package_json)
×
74
        } else {
7✔
75
                env = append(env, "DENO_NO_PACKAGE_JSON="+denoNoPackageJsonValue)
7✔
76
        }
7✔
77
        // Run bundle
78
        if err := utils.DockerRunOnceWithConfig(
7✔
79
                ctx,
7✔
80
                container.Config{
7✔
81
                        Image:      utils.Config.EdgeRuntime.Image,
7✔
82
                        Env:        env,
7✔
83
                        Cmd:        cmd,
7✔
84
                        WorkingDir: utils.ToDockerPath(cwd),
7✔
85
                },
7✔
86
                container.HostConfig{
7✔
87
                        Binds: binds,
7✔
88
                },
7✔
89
                network.NetworkingConfig{},
7✔
90
                "",
7✔
91
                os.Stdout,
7✔
92
                os.Stderr,
7✔
93
        ); err != nil {
8✔
94
                return meta, err
1✔
95
        }
1✔
96
        // Read and compress
97
        eszipBytes, err := b.fsys.Open(hostOutputPath)
6✔
98
        if err != nil {
6✔
99
                return meta, errors.Errorf("failed to open eszip: %w", err)
×
100
        }
×
101
        defer eszipBytes.Close()
6✔
102
        return meta, function.Compress(eszipBytes, output)
6✔
103
}
104

105
func GetBindMounts(cwd, hostFuncDir, hostOutputDir, hostEntrypointPath, hostImportMapPath string, fsys afero.Fs) ([]string, error) {
10✔
106
        sep := string(filepath.Separator)
10✔
107
        // Docker requires all host paths to be absolute
10✔
108
        if !filepath.IsAbs(hostFuncDir) {
20✔
109
                hostFuncDir = filepath.Join(cwd, hostFuncDir)
10✔
110
        }
10✔
111
        if !strings.HasSuffix(hostFuncDir, sep) {
20✔
112
                hostFuncDir += sep
10✔
113
        }
10✔
114
        dockerFuncDir := utils.ToDockerPath(hostFuncDir)
10✔
115
        // TODO: bind ./supabase/functions:/home/deno/functions to hide PII?
10✔
116
        binds := []string{
10✔
117
                // Reuse deno cache directory, ie. DENO_DIR, between container restarts
10✔
118
                // https://denolib.gitbook.io/guide/advanced/deno_dir-code-fetch-and-cache
10✔
119
                utils.EdgeRuntimeId + ":/root/.cache/deno:rw",
10✔
120
                hostFuncDir + ":" + dockerFuncDir + ":ro",
10✔
121
        }
10✔
122
        if len(hostOutputDir) > 0 {
17✔
123
                if !filepath.IsAbs(hostOutputDir) {
14✔
124
                        hostOutputDir = filepath.Join(cwd, hostOutputDir)
7✔
125
                }
7✔
126
                if !strings.HasSuffix(hostOutputDir, sep) {
14✔
127
                        hostOutputDir += sep
7✔
128
                }
7✔
129
                if !strings.HasPrefix(hostOutputDir, hostFuncDir) {
14✔
130
                        dockerOutputDir := utils.ToDockerPath(hostOutputDir)
7✔
131
                        binds = append(binds, hostOutputDir+":"+dockerOutputDir+":rw")
7✔
132
                }
7✔
133
        }
134
        // Imports outside of ./supabase/functions will be bound by walking the entrypoint
135
        modules, err := utils.BindHostModules(cwd, hostEntrypointPath, hostImportMapPath, fsys)
10✔
136
        if err != nil {
10✔
137
                return nil, err
×
138
        }
×
139
        // Remove any duplicate mount points
140
        for _, mod := range modules {
13✔
141
                hostPath := strings.Split(mod, ":")[0]
3✔
142
                if volName := filepath.VolumeName(mod); len(volName) > 0 {
3✔
143
                        hostPath = volName + strings.Split(strings.TrimPrefix(mod, volName), ":")[0]
×
144
                }
×
145
                if !strings.HasPrefix(hostPath, hostFuncDir) &&
3✔
146
                        (len(hostOutputDir) == 0 || !strings.HasPrefix(hostPath, hostOutputDir)) {
5✔
147
                        binds = append(binds, mod)
2✔
148
                }
2✔
149
        }
150
        return binds, nil
10✔
151
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc