diff --git a/internal/services/services.go b/internal/services/services.go index 1feeff3c4..46d399c43 100644 --- a/internal/services/services.go +++ b/internal/services/services.go @@ -5,14 +5,13 @@ import ( "fmt" "os" "strings" - "sync" "github.com/go-errors/errors" "github.com/spf13/afero" - "github.com/spf13/viper" "github.com/supabase/cli/internal/utils" "github.com/supabase/cli/internal/utils/flags" "github.com/supabase/cli/internal/utils/tenant" + "github.com/supabase/cli/pkg/queue" ) func Run(ctx context.Context, fsys afero.Fs) error { @@ -77,39 +76,53 @@ func CheckVersions(ctx context.Context, fsys afero.Fs) []imageVersion { } func listRemoteImages(ctx context.Context, projectRef string) map[string]string { - linked := make(map[string]string, 4) - var wg sync.WaitGroup - wg.Add(1) - go func() { - defer wg.Done() - if version, err := tenant.GetDatabaseVersion(ctx, projectRef); err == nil { - linked[utils.Config.Db.Image] = version - } - }() + linked := map[string]string{} keys, err := tenant.GetApiKeys(ctx, projectRef) if err != nil { - wg.Wait() return linked } + jq := queue.NewJobQueue(5) api := tenant.NewTenantAPI(ctx, projectRef, keys.ServiceRole) - wg.Add(2) - go func() { - defer wg.Done() - if version, err := api.GetGotrueVersion(ctx); err == nil { - linked[utils.Config.Auth.Image] = version - } else if viper.GetBool("DEBUG") { - fmt.Fprintln(os.Stderr, err) - } - }() - go func() { - defer wg.Done() - if version, err := api.GetPostgrestVersion(ctx); err == nil { - linked[utils.Config.Api.Image] = version - } else if viper.GetBool("DEBUG") { - fmt.Fprintln(os.Stderr, err) + jobs := []func() error{ + func() error { + version, err := tenant.GetDatabaseVersion(ctx, projectRef) + if err == nil { + linked[utils.Config.Db.Image] = version + } + return nil + }, + func() error { + version, err := api.GetGotrueVersion(ctx) + if err == nil { + linked[utils.Config.Auth.Image] = version + } + return nil + }, + func() error { + version, err := api.GetPostgrestVersion(ctx) + if err == nil { + linked[utils.Config.Api.Image] = version + } + return nil + }, + func() error { + version, err := api.GetStorageVersion(ctx) + if err == nil { + linked[utils.Config.Storage.Image] = version + } + return err + }, + } + // Ignore non-fatal errors linking services + logger := utils.GetDebugLogger() + for _, job := range jobs { + if err := jq.Put(job); err != nil { + fmt.Fprintln(logger, err) } - }() - wg.Wait() + } + if err := jq.Collect(); err != nil { + fmt.Fprintln(logger, err) + } return linked } diff --git a/internal/utils/tenant/database.go b/internal/utils/tenant/database.go index 1ae1ee6a7..ababf74af 100644 --- a/internal/utils/tenant/database.go +++ b/internal/utils/tenant/database.go @@ -10,17 +10,15 @@ import ( var errDatabaseVersion = errors.New("Database version not found.") func GetDatabaseVersion(ctx context.Context, projectRef string) (string, error) { - resp, err := utils.GetSupabase().V1ListAllProjectsWithResponse(ctx) + resp, err := utils.GetSupabase().V1GetProjectWithResponse(ctx, projectRef) if err != nil { - return "", errors.Errorf("failed to retrieve projects: %w", err) + return "", errors.Errorf("failed to retrieve project: %w", err) } if resp.JSON200 == nil { - return "", errors.New("Unexpected error retrieving projects: " + string(resp.Body)) + return "", errors.Errorf("unexpected retrieve project status %d: %s", resp.StatusCode(), string(resp.Body)) } - for _, project := range *resp.JSON200 { - if project.Id == projectRef && len(project.Database.Version) > 0 { - return project.Database.Version, nil - } + if len(resp.JSON200.Database.Version) > 0 { + return resp.JSON200.Database.Version, nil } return "", errors.New(errDatabaseVersion) } diff --git a/internal/utils/tenant/database_test.go b/internal/utils/tenant/database_test.go index d80ac5cba..5a042cd74 100644 --- a/internal/utils/tenant/database_test.go +++ b/internal/utils/tenant/database_test.go @@ -22,9 +22,9 @@ func TestGetDatabaseVersion(t *testing.T) { mockPostgres := api.V1ProjectWithDatabaseResponse{Id: projectRef} mockPostgres.Database.Version = "14.1.0.99" gock.New(utils.DefaultApiHost). - Get("/v1/projects"). + Get("/v1/projects/" + projectRef). Reply(http.StatusOK). - JSON([]api.V1ProjectWithDatabaseResponse{mockPostgres}) + JSON(mockPostgres) version, err := GetDatabaseVersion(context.Background(), projectRef) @@ -39,16 +39,13 @@ func TestGetDatabaseVersion(t *testing.T) { defer gock.OffAll() projectRef := apitest.RandomProjectRef() - mockPostgres := api.V1ProjectWithDatabaseResponse{Id: "different-project"} - mockPostgres.Database.Version = "14.1.0.99" gock.New(utils.DefaultApiHost). - Get("/v1/projects"). - Reply(http.StatusOK). - JSON([]api.V1ProjectWithDatabaseResponse{mockPostgres}) + Get("/v1/projects/" + projectRef). + Reply(http.StatusNotFound) version, err := GetDatabaseVersion(context.Background(), projectRef) - assert.ErrorIs(t, err, errDatabaseVersion) + assert.ErrorContains(t, err, "unexpected retrieve project status 404:") assert.Empty(t, version) assert.Empty(t, apitest.ListUnmatchedRequests()) }) @@ -60,11 +57,9 @@ func TestGetDatabaseVersion(t *testing.T) { defer gock.OffAll() projectRef := apitest.RandomProjectRef() gock.New(utils.DefaultApiHost). - Get("/v1/projects"). + Get("/v1/projects/" + projectRef). Reply(http.StatusOK). - JSON([]api.V1ProjectWithDatabaseResponse{{ - Id: projectRef, - }}) + JSON(api.V1ProjectWithDatabaseResponse{Id: projectRef}) version, err := GetDatabaseVersion(context.Background(), projectRef) diff --git a/pkg/config/config.go b/pkg/config/config.go index ee899f4ac..3096f4d55 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -629,7 +629,7 @@ func (c *config) Load(path string, fsys fs.FS, overrides ...ConfigEditor) error } if version, err := fs.ReadFile(fsys, builder.StorageVersionPath); err == nil && len(version) > 0 { // Only replace image if local storage version is newer - if i := strings.IndexByte(Images.Storage, ':'); semver.Compare(string(version), Images.Storage[i+1:]) > 0 { + if i := strings.IndexByte(Images.Storage, ':'); semver.Compare(strings.TrimSpace(string(version)), Images.Storage[i+1:]) > 0 { c.Storage.Image = replaceImageTag(Images.Storage, string(version)) } }