Skip to content

Commit

Permalink
chore: reuse services command for version check
Browse files Browse the repository at this point in the history
  • Loading branch information
sweatybridge committed Dec 7, 2024
1 parent 6f87ea3 commit 6d51d7b
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 54 deletions.
3 changes: 1 addition & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/spf13/afero"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/supabase/cli/internal/services"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/flags"
"golang.org/x/mod/semver"
Expand Down Expand Up @@ -250,7 +249,7 @@ func GetRootCmd() *cobra.Command {
}

func addSentryScope(scope *sentry.Scope) {
serviceImages := services.GetServiceImages()
serviceImages := utils.Config.GetServiceImages()
imageToVersion := make(map[string]interface{}, len(serviceImages))
for _, image := range serviceImages {
parts := strings.Split(image, ":")
Expand Down
73 changes: 45 additions & 28 deletions internal/services/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package services

import (
"context"
"errors"
"fmt"
"os"
"strings"
"sync"

Expand All @@ -13,50 +15,56 @@ import (
"github.com/supabase/cli/internal/utils/tenant"
)

var suggestLinkCommand = fmt.Sprintf("Run %s to sync your local image versions with the linked project.", utils.Aqua("supabase link"))

func Run(ctx context.Context, fsys afero.Fs) error {
_ = utils.LoadConfigFS(fsys)
serviceImages := GetServiceImages()

var linked map[string]string
if projectRef, err := flags.LoadProjectRef(fsys); err == nil {
linked = GetRemoteImages(ctx, projectRef)
if _, err := flags.LoadProjectRef(fsys); err != nil && !errors.Is(err, utils.ErrNotLinked) {
fmt.Fprintln(os.Stderr, err)
}
if err := utils.Config.Load("", utils.NewRootFS(fsys)); err != nil && !errors.Is(err, os.ErrNotExist) {
fmt.Fprintln(os.Stderr, err)
}

serviceImages := CheckVersions(ctx, fsys)
table := `|SERVICE IMAGE|LOCAL|LINKED|
|-|-|-|
`
for _, image := range serviceImages {
parts := strings.Split(image, ":")
version, ok := linked[image]
if !ok {
version = "-"
} else if parts[1] != version && image != utils.Config.Db.Image {
utils.CmdSuggestion = suggestLinkCommand
remote := image.Remote
if len(remote) == 0 {
remote = "-"
}
table += fmt.Sprintf("|`%s`|`%s`|`%s`|\n", parts[0], parts[1], version)
table += fmt.Sprintf("|`%s`|`%s`|`%s`|\n", image.Name, image.Local, remote)
}

return list.RenderTable(table)
}

func GetServiceImages() []string {
return []string{
utils.Config.Db.Image,
utils.Config.Auth.Image,
utils.Config.Api.Image,
utils.Config.Realtime.Image,
utils.Config.Storage.Image,
utils.Config.EdgeRuntime.Image,
utils.Config.Studio.Image,
utils.Config.Studio.PgmetaImage,
utils.Config.Analytics.Image,
utils.Config.Db.Pooler.Image,
type imageVersion struct {
Name string `json:"name"`
Local string `json:"local"`
Remote string `json:"remote"`
}

func CheckVersions(ctx context.Context, fsys afero.Fs) []imageVersion {
var remote map[string]string
if _, err := utils.LoadAccessTokenFS(fsys); err == nil && len(flags.ProjectRef) > 0 {
remote = listRemoteImages(ctx, flags.ProjectRef)
}
var result []imageVersion
for _, image := range utils.Config.GetServiceImages() {
parts := strings.Split(image, ":")
v := imageVersion{Name: parts[0], Local: parts[1]}
if v.Remote = remote[image]; v.Remote == v.Local {
delete(remote, image)
}
result = append(result, v)
}
if len(remote) > 0 {
fmt.Fprintln(os.Stderr, suggestUpdateCmd(remote))
}
return result
}

func GetRemoteImages(ctx context.Context, projectRef string) map[string]string {
func listRemoteImages(ctx context.Context, projectRef string) map[string]string {
linked := make(map[string]string, 4)
var wg sync.WaitGroup
wg.Add(1)
Expand Down Expand Up @@ -94,3 +102,12 @@ func GetRemoteImages(ctx context.Context, projectRef string) map[string]string {
wg.Wait()
return linked
}

func suggestUpdateCmd(serviceImages map[string]string) string {
cmd := fmt.Sprintln(utils.Yellow("WARNING:"), "You are running different service versions locally than your linked project:")
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
}
26 changes: 2 additions & 24 deletions internal/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,10 @@ import (
"golang.org/x/mod/semver"
)

func suggestUpdateCmd(serviceImages map[string]string) string {
cmd := fmt.Sprintln(utils.Yellow("WARNING:"), "You are running different service versions locally than your linked project:")
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.
{
_, _ = flags.LoadProjectRef(fsys)
if err := utils.LoadConfigFS(fsys); err != nil {
return err
}
Expand All @@ -56,21 +48,7 @@ func Run(ctx context.Context, fsys afero.Fs, excludedContainers []string, ignore
} else if !errors.Is(err, utils.ErrNotRunning) {
return err
}
if _, err := utils.LoadAccessTokenFS(fsys); err == nil {
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))
}
}
}
_ = services.CheckVersions(ctx, fsys)
}

if err := utils.RunProgram(ctx, func(p utils.Program, ctx context.Context) error {
Expand Down
15 changes: 15 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,21 @@ func (a *auth) ResolveJWKS(ctx context.Context) (string, error) {
return string(jwksEncoded), nil
}

func (c *baseConfig) GetServiceImages() []string {
return []string{
c.Db.Image,
c.Auth.Image,
c.Api.Image,
c.Realtime.Image,
c.Storage.Image,
c.EdgeRuntime.Image,
c.Studio.Image,
c.Studio.PgmetaImage,
c.Analytics.Image,
c.Db.Pooler.Image,
}
}

// Retrieve the final base config to use taking into account the remotes override
func (c *config) GetRemoteByProjectRef(projectRef string) (baseConfig, error) {
var result []string
Expand Down

0 comments on commit 6d51d7b

Please sign in to comment.