From bb8710d43004ee96bbe4ea5051ae1c815d519ab6 Mon Sep 17 00:00:00 2001 From: Qiao Han Date: Tue, 22 Oct 2024 18:04:33 +0800 Subject: [PATCH 1/2] fix: ignore project not found error on linking --- internal/link/link.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/link/link.go b/internal/link/link.go index 8a75a8d3de..e3878eadb9 100644 --- a/internal/link/link.go +++ b/internal/link/link.go @@ -3,6 +3,7 @@ package link import ( "context" "fmt" + "net/http" "os" "strconv" "strings" @@ -243,7 +244,12 @@ func checkRemoteProjectStatus(ctx context.Context, projectRef string) error { if err != nil { return errors.Errorf("failed to retrieve remote project status: %w", err) } - if resp.JSON200 == nil { + switch resp.StatusCode() { + case http.StatusNotFound: + // Ignore not found error to support linking branch projects + return nil + case http.StatusOK: + default: return errors.New("Unexpected error retrieving remote project status: " + string(resp.Body)) } From 8abc7ebf92f98dc5704b4af4fc96289358e010b5 Mon Sep 17 00:00:00 2001 From: Qiao Han Date: Tue, 22 Oct 2024 18:31:37 +0800 Subject: [PATCH 2/2] chore: update unit tests --- internal/link/link.go | 8 +++++--- internal/link/link_test.go | 28 +++++++++++++++++++++++----- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/internal/link/link.go b/internal/link/link.go index e3878eadb9..04e5c565b1 100644 --- a/internal/link/link.go +++ b/internal/link/link.go @@ -239,6 +239,8 @@ func updatePoolerConfig(config api.SupavisorConfigResponse) { } } +var errProjectPaused = errors.New("project is paused") + func checkRemoteProjectStatus(ctx context.Context, projectRef string) error { resp, err := utils.GetSupabase().V1GetProjectWithResponse(ctx, projectRef) if err != nil { @@ -249,6 +251,7 @@ func checkRemoteProjectStatus(ctx context.Context, projectRef string) error { // Ignore not found error to support linking branch projects return nil case http.StatusOK: + // resp.JSON200 is not nil, proceed default: return errors.New("Unexpected error retrieving remote project status: " + string(resp.Body)) } @@ -256,12 +259,11 @@ func checkRemoteProjectStatus(ctx context.Context, projectRef string) error { switch resp.JSON200.Status { case api.V1ProjectResponseStatusINACTIVE: utils.CmdSuggestion = fmt.Sprintf("An admin must unpause it from the Supabase dashboard at %s", utils.Aqua(fmt.Sprintf("%s/project/%s", utils.GetSupabaseDashboardURL(), projectRef))) - return errors.New("project is paused") + return errors.New(errProjectPaused) case api.V1ProjectResponseStatusACTIVEHEALTHY: // Project is in the desired state, do nothing - return nil default: - fmt.Fprintf(os.Stderr, "%s: Project status is %s instead of Active Healthy. Some operations might fail.\n", utils.Yellow("Warning"), resp.JSON200.Status) + fmt.Fprintf(os.Stderr, "%s: Project status is %s instead of Active Healthy. Some operations might fail.\n", utils.Yellow("WARNING"), resp.JSON200.Status) } return nil diff --git a/internal/link/link_test.go b/internal/link/link_test.go index f39388bfd9..c8a867f6b0 100644 --- a/internal/link/link_test.go +++ b/internal/link/link_test.go @@ -3,6 +3,7 @@ package link import ( "context" "errors" + "net/http" "testing" "github.com/h2non/gock" @@ -209,20 +210,37 @@ func TestLinkCommand(t *testing.T) { assert.NoError(t, err) assert.False(t, exists) }) +} + +func TestStatusCheck(t *testing.T) { + project := "test-project" + + t.Run("ignores project not found", func(t *testing.T) { + // Flush pending mocks after test execution + defer gock.OffAll() + // Mock project status + gock.New(utils.DefaultApiHost). + Get("/v1/projects/" + project). + Reply(http.StatusNotFound) + // Run test + err := checkRemoteProjectStatus(context.Background(), project) + // Check error + assert.NoError(t, err) + assert.Empty(t, apitest.ListUnmatchedRequests()) + }) + t.Run("throws error on project inactive", func(t *testing.T) { - // Setup in-memory fs - fsys := afero.NewReadOnlyFs(afero.NewMemMapFs()) // Flush pending mocks after test execution defer gock.OffAll() // Mock project status gock.New(utils.DefaultApiHost). Get("/v1/projects/" + project). - Reply(200). + Reply(http.StatusOK). JSON(api.V1ProjectResponse{Status: api.V1ProjectResponseStatusINACTIVE}) // Run test - err := Run(context.Background(), project, fsys) + err := checkRemoteProjectStatus(context.Background(), project) // Check error - assert.ErrorContains(t, err, "project is paused") + assert.ErrorIs(t, err, errProjectPaused) assert.Empty(t, apitest.ListUnmatchedRequests()) }) }