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

supabase / cli / 19880047649

03 Dec 2025 02:15AM UTC coverage: 55.457% (-0.06%) from 55.514%
19880047649

Pull #4568

github

web-flow
Merge ffcff0ec1 into c4baba6d3
Pull Request #4568: fix: include storage version in services command

4 of 39 new or added lines in 2 files covered. (10.26%)

7 existing lines in 2 files now uncovered.

6728 of 12132 relevant lines covered (55.46%)

6.21 hits per line

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

0.0
/internal/services/services.go
1
package services
2

3
import (
4
        "context"
5
        "fmt"
6
        "os"
7
        "strings"
8

9
        "github.com/go-errors/errors"
10
        "github.com/spf13/afero"
11
        "github.com/supabase/cli/internal/utils"
12
        "github.com/supabase/cli/internal/utils/flags"
13
        "github.com/supabase/cli/internal/utils/tenant"
14
        "github.com/supabase/cli/pkg/queue"
15
)
16

17
func Run(ctx context.Context, fsys afero.Fs) error {
×
18
        if err := flags.LoadProjectRef(fsys); err != nil && !errors.Is(err, utils.ErrNotLinked) {
×
19
                fmt.Fprintln(os.Stderr, err)
×
20
        }
×
21
        if err := flags.LoadConfig(fsys); err != nil {
×
22
                fmt.Fprintln(os.Stderr, err)
×
23
        }
×
24

25
        serviceImages := CheckVersions(ctx, fsys)
×
26
        switch utils.OutputFormat.Value {
×
27
        case utils.OutputPretty:
×
28
                table := `|SERVICE IMAGE|LOCAL|LINKED|
×
29
|-|-|-|
×
30
`
×
31
                for _, image := range serviceImages {
×
32
                        remote := image.Remote
×
33
                        if len(remote) == 0 {
×
34
                                remote = "-"
×
35
                        }
×
36
                        table += fmt.Sprintf("|`%s`|`%s`|`%s`|\n", image.Name, image.Local, remote)
×
37
                }
38
                return utils.RenderTable(table)
×
39
        case utils.OutputToml:
×
40
                return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, struct {
×
41
                        Services []imageVersion `toml:"services"`
×
42
                }{
×
43
                        Services: serviceImages,
×
44
                })
×
45
        case utils.OutputEnv:
×
46
                return errors.Errorf("--output env flag is not supported")
×
47
        }
48

49
        return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, serviceImages)
×
50
}
51

52
type imageVersion struct {
53
        Name   string `json:"name"`
54
        Local  string `json:"local"`
55
        Remote string `json:"remote"`
56
}
57

58
func CheckVersions(ctx context.Context, fsys afero.Fs) []imageVersion {
×
59
        var remote map[string]string
×
60
        if _, err := utils.LoadAccessTokenFS(fsys); err == nil && len(flags.ProjectRef) > 0 {
×
61
                remote = listRemoteImages(ctx, flags.ProjectRef)
×
62
        }
×
63
        var result []imageVersion
×
64
        for _, image := range utils.Config.GetServiceImages() {
×
65
                parts := strings.Split(image, ":")
×
66
                v := imageVersion{Name: parts[0], Local: parts[1]}
×
67
                if v.Remote = remote[image]; v.Remote == v.Local {
×
68
                        delete(remote, image)
×
69
                }
×
70
                result = append(result, v)
×
71
        }
72
        if len(remote) > 0 {
×
73
                fmt.Fprintln(os.Stderr, suggestUpdateCmd(remote))
×
74
        }
×
75
        return result
×
76
}
77

78
func listRemoteImages(ctx context.Context, projectRef string) map[string]string {
×
NEW
79
        linked := map[string]string{}
×
80
        keys, err := tenant.GetApiKeys(ctx, projectRef)
×
81
        if err != nil {
×
82
                return linked
×
83
        }
×
NEW
84
        jq := queue.NewJobQueue(5)
×
85
        api := tenant.NewTenantAPI(ctx, projectRef, keys.ServiceRole)
×
NEW
86
        jobs := []func() error{
×
NEW
87
                func() error {
×
NEW
88
                        version, err := tenant.GetDatabaseVersion(ctx, projectRef)
×
NEW
89
                        if err == nil {
×
NEW
90
                                linked[utils.Config.Db.Image] = version
×
NEW
91
                        }
×
NEW
92
                        return nil
×
93
                },
NEW
94
                func() error {
×
NEW
95
                        version, err := api.GetGotrueVersion(ctx)
×
NEW
96
                        if err == nil {
×
NEW
97
                                linked[utils.Config.Auth.Image] = version
×
NEW
98
                        }
×
NEW
99
                        return nil
×
100
                },
NEW
101
                func() error {
×
NEW
102
                        version, err := api.GetPostgrestVersion(ctx)
×
NEW
103
                        if err == nil {
×
NEW
104
                                linked[utils.Config.Api.Image] = version
×
NEW
105
                        }
×
NEW
106
                        return nil
×
107
                },
NEW
108
                func() error {
×
NEW
109
                        version, err := api.GetStorageVersion(ctx)
×
NEW
110
                        if err == nil {
×
NEW
111
                                linked[utils.Config.Storage.Image] = version
×
NEW
112
                        }
×
NEW
113
                        return err
×
114
                },
115
        }
116
        // Ignore non-fatal errors linking services
NEW
117
        logger := utils.GetDebugLogger()
×
NEW
118
        for _, job := range jobs {
×
NEW
119
                if err := jq.Put(job); err != nil {
×
NEW
120
                        fmt.Fprintln(logger, err)
×
UNCOV
121
                }
×
122
        }
NEW
123
        if err := jq.Collect(); err != nil {
×
NEW
124
                fmt.Fprintln(logger, err)
×
NEW
125
        }
×
UNCOV
126
        return linked
×
127
}
128

129
func suggestUpdateCmd(serviceImages map[string]string) string {
×
130
        cmd := fmt.Sprintln(utils.Yellow("WARNING:"), "You are running different service versions locally than your linked project:")
×
131
        for k, v := range serviceImages {
×
132
                cmd += fmt.Sprintf("%s => %s\n", k, v)
×
133
        }
×
134
        cmd += fmt.Sprintf("Run %s to update them.", utils.Aqua("supabase link"))
×
135
        return cmd
×
136
}
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