diff --git a/cmd/root.go b/cmd/root.go index 0c18dbc94..cc43efd47 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -223,7 +223,7 @@ func changeWorkDir(fsys afero.Fs) error { func addSentryScope(scope *sentry.Scope) { serviceImages := services.GetServiceImages() imageToVersion := make(map[string]interface{}, len(serviceImages)) - for _, image := range services.GetServiceImages() { + for _, image := range serviceImages { parts := strings.Split(image, ":") // Bypasses sentry's IP sanitization rule, ie. 15.1.0.147 if net.ParseIP(parts[1]) != nil { diff --git a/internal/services/services.go b/internal/services/services.go index 9c16aac4a..a6d451ede 100644 --- a/internal/services/services.go +++ b/internal/services/services.go @@ -19,35 +19,9 @@ func Run(ctx context.Context, fsys afero.Fs) error { _ = utils.LoadConfigFS(fsys) serviceImages := GetServiceImages() - linked := make(map[string]string) + var linked map[string]string if projectRef, err := flags.LoadProjectRef(fsys); err == nil { - var wg sync.WaitGroup - wg.Add(4) - go func() { - defer wg.Done() - if version, err := tenant.GetDatabaseVersion(ctx, projectRef); err == nil { - linked[utils.Config.Db.Image] = version - } - }() - go func() { - defer wg.Done() - if version, err := tenant.GetGotrueVersion(ctx, projectRef); err == nil { - linked[utils.Config.Auth.Image] = version - } - }() - go func() { - defer wg.Done() - if version, err := tenant.GetPostgrestVersion(ctx, projectRef); err == nil { - linked[utils.Config.Api.Image] = version - } - }() - go func() { - defer wg.Done() - if version, err := tenant.GetStorageVersion(ctx, projectRef); err == nil { - linked[utils.Config.Storage.Image] = version - } - }() - wg.Wait() + linked = GetRemoteImages(ctx, projectRef) } table := `|SERVICE IMAGE|LOCAL|LINKED| @@ -82,3 +56,36 @@ func GetServiceImages() []string { utils.ImageProxyImage, } } + +func GetRemoteImages(ctx context.Context, projectRef string) map[string]string { + const cap = 4 + linked := make(map[string]string, cap) + var wg sync.WaitGroup + wg.Add(cap) + go func() { + defer wg.Done() + if version, err := tenant.GetDatabaseVersion(ctx, projectRef); err == nil { + linked[utils.Config.Db.Image] = version + } + }() + go func() { + defer wg.Done() + if version, err := tenant.GetGotrueVersion(ctx, projectRef); err == nil { + linked[utils.Config.Auth.Image] = version + } + }() + go func() { + defer wg.Done() + if version, err := tenant.GetPostgrestVersion(ctx, projectRef); err == nil { + linked[utils.Config.Api.Image] = version + } + }() + go func() { + defer wg.Done() + if version, err := tenant.GetStorageVersion(ctx, projectRef); err == nil { + linked[utils.Config.Storage.Image] = version + } + }() + wg.Wait() + return linked +} diff --git a/internal/start/start.go b/internal/start/start.go index b4a3941c3..b4b192d18 100644 --- a/internal/start/start.go +++ b/internal/start/start.go @@ -24,10 +24,21 @@ import ( "github.com/supabase/cli/internal/db/reset" "github.com/supabase/cli/internal/db/start" "github.com/supabase/cli/internal/functions/serve" + "github.com/supabase/cli/internal/services" "github.com/supabase/cli/internal/status" "github.com/supabase/cli/internal/utils" + "github.com/supabase/cli/internal/utils/flags" ) +func suggestUpdateCmd(serviceImages map[string]string) string { + cmd := "You are running outdated service versions locally:\n" + for k, v := range serviceImages { + cmd += fmt.Sprintf("%s => %s\n", k, v) + } + cmd += fmt.Sprintf("Run %s to update them.", utils.Aqua("supabase link")) + return cmd +} + func Run(ctx context.Context, fsys afero.Fs, excludedContainers []string, ignoreHealthCheck bool) error { // Sanity checks. { @@ -41,6 +52,19 @@ func Run(ctx context.Context, fsys afero.Fs, excludedContainers []string, ignore } else if !errors.Is(err, utils.ErrNotRunning) { return err } + if ref, err := flags.LoadProjectRef(fsys); err == nil { + local := services.GetServiceImages() + remote := services.GetRemoteImages(ctx, ref) + for _, image := range local { + parts := strings.Split(image, ":") + if version, ok := remote[image]; ok && version == parts[1] { + delete(remote, image) + } + } + if len(remote) > 0 { + fmt.Fprintln(os.Stderr, suggestUpdateCmd(remote)) + } + } } if err := utils.RunProgram(ctx, func(p utils.Program, ctx context.Context) error {