Repository: supabase/cli
Pull request #1213 (2023-06-15 06:56:34)

fix: validate version number for migration repair
## What kind of change does this PR introduce?

Bug fix https://github.com/supabase/cli/issues/1209

## What is the new behavior?

- users must supply a version number as per [migration example](https://github.com/supabase/cli/blob/main/docs/supabase/migration/repair.md#supabase-migration-repair)

## Additional context

Add any other context or screenshots.


coveralls: ## Pull Request Test Coverage Report for [Build 5275735175](https://coveralls.io/builds/60750035)

* **1** of **3**   **(33.33%)**  changed or added relevant lines in **1** file are covered.
* **10** unchanged lines in **2** files lost coverage.
* Overall coverage decreased (**-0.1%**) to **61.316%**

---

|  Changes Missing Coverage | Covered Lines | Changed/Added Lines | % |
| :-----|--------------|--------|---: |
| [internal/migration/repair/repair.go](https://coveralls.io/builds/60750035/source?filename=internal%2Fmigration%2Frepair%2Frepair.go#L36) | 1 | 3 | 33.33%
<!-- | **Total:** | **1** | **3** | **33.33%** | -->

|  Files with Coverage Reduction | New Missed Lines | % |
| :-----|--------------|--: |
| [internal/debug/postgres.go](https://coveralls.io/builds/60750035/source?filename=internal%2Fdebug%2Fpostgres.go#L139) | 3 | 66.67% |
| [internal/gen/keys/keys.go](https://coveralls.io/builds/60750035/source?filename=internal%2Fgen%2Fkeys%2Fkeys.go#L94) | 7 | 7.94% |
<!-- | **Total:** | **10** |  | -->

|  Totals | [![Coverage Status](https://coveralls.io/builds/60750035/badge)](https://coveralls.io/builds/60750035) |
| :-- | --: |
| Change from base [Build 5275429462](https://coveralls.io/builds/60749470): |  -0.1% |
| Covered Lines: | 4633 |
| Relevant Lines: | 7556 |

---
##### 💛  - [Coveralls](https://coveralls.io)


Patch:
diff --git a/internal/db/start/start.go b/internal/db/start/start.go
index 967ecff0..74610ccf 100644
--- a/internal/db/start/start.go
+++ b/internal/db/start/start.go
@@ -81,8 +81,11 @@ func StartDatabase(ctx context.Context, fsys afero.Fs, w io.Writer, options ...f
 	hostConfig := WithSyslogConfig(container.HostConfig{
 		PortBindings:  nat.PortMap{"5432/tcp": []nat.PortBinding{{HostPort: hostPort}}},
 		RestartPolicy: container.RestartPolicy{Name: "always"},
-		Binds:         []string{utils.DbId + ":/var/lib/postgresql/data"},
-		ExtraHosts:    []string{"host.docker.internal:host-gateway"},
+		Binds: []string{
+			utils.DbId + ":/var/lib/postgresql/data",
+			utils.ConfigId + ":/etc/postgresql-custom",
+		},
+		ExtraHosts: []string{"host.docker.internal:host-gateway"},
 	})
 	if utils.Config.Db.MajorVersion <= 14 {
 		config.Entrypoint = nil
diff --git a/internal/migration/repair/repair.go b/internal/migration/repair/repair.go
index b2d5bdb3..8ea21b91 100644
--- a/internal/migration/repair/repair.go
+++ b/internal/migration/repair/repair.go
@@ -2,10 +2,12 @@ package repair
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"io"
 	"os"
 	"path/filepath"
+	"strconv"
 
 	"github.com/jackc/pgconn"
 	"github.com/jackc/pgtype"
@@ -30,6 +32,9 @@ const (
 )
 
 func Run(ctx context.Context, config pgconn.Config, version, status string, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
+	if _, err := strconv.Atoi(version); err != nil {
+		return errors.New("invalid version number")
+	}
 	conn, err := utils.ConnectRemotePostgres(ctx, config, options...)
 	if err != nil {
 		return err
diff --git a/internal/stop/stop.go b/internal/stop/stop.go
index b97c9c69..01905739 100644
--- a/internal/stop/stop.go
+++ b/internal/stop/stop.go
@@ -52,10 +52,12 @@ func stop(ctx context.Context, backup bool) error {
 	// Remove named volumes
 	if backup {
 		fmt.Fprintln(os.Stderr, "Postgres database saved to volume:", utils.DbId)
+		fmt.Fprintln(os.Stderr, "Postgres config saved to volume:", utils.ConfigId)
 		fmt.Fprintln(os.Stderr, "Storage directory saved to volume:", utils.StorageId)
+		fmt.Fprintln(os.Stderr, "Functions cache saved to volume:", utils.DenoRelayId)
 	} else {
 		// TODO: label named volumes to use VolumesPrune for branch support
-		volumes := []string{utils.DbId, utils.StorageId}
+		volumes := []string{utils.ConfigId, utils.DbId, utils.StorageId, utils.DenoRelayId}
 		utils.WaitAll(volumes, func(name string) {
 			if err := utils.Docker.VolumeRemove(ctx, name, true); err != nil {
 				fmt.Fprintln(os.Stderr, "failed to remove volume:", name, err)
diff --git a/internal/utils/config.go b/internal/utils/config.go
index 8be6892b..f52d26b3 100644
--- a/internal/utils/config.go
+++ b/internal/utils/config.go
@@ -21,6 +21,7 @@ var (
 	DbImage    string
 	NetId      string
 	DbId       string
+	ConfigId   string
 	KongId     string
 	GotrueId   string
 	InbucketId string
@@ -206,6 +207,7 @@ func LoadConfigFS(fsys afero.Fs) error {
 		} else {
 			NetId = "supabase_network_" + Config.ProjectId
 			DbId = "supabase_db_" + Config.ProjectId
+			ConfigId = "supabase_config_" + Config.ProjectId
 			KongId = "supabase_kong_" + Config.ProjectId
 			GotrueId = "supabase_auth_" + Config.ProjectId
 			InbucketId = "supabase_inbucket_" + Config.ProjectId


Test patch:
diff --git a/internal/db/start/start_test.go b/internal/db/start/start_test.go
index 49e52055..d0bd0367 100644
--- a/internal/db/start/start_test.go
+++ b/internal/db/start/start_test.go
@@ -86,6 +86,7 @@ func TestStartDatabase(t *testing.T) {
 		utils.DbImage = utils.Pg15Image
 		utils.Config.Db.MajorVersion = 15
 		utils.DbId = "supabase_db_test"
+		utils.ConfigId = "supabase_config_test"
 		utils.Config.Db.Port = 5432
 		// Setup in-memory fs
 		fsys := afero.NewMemMapFs()
diff --git a/internal/stop/stop_test.go b/internal/stop/stop_test.go
index 3c65f026..1ad1e828 100644
--- a/internal/stop/stop_test.go
+++ b/internal/stop/stop_test.go
@@ -100,7 +100,9 @@ func TestStopServices(t *testing.T) {
 
 	t.Run("removes data volumes", func(t *testing.T) {
 		utils.DbId = "test-db"
+		utils.ConfigId = "test-config"
 		utils.StorageId = "test-storage"
+		utils.DenoRelayId = "test-functions"
 		// Setup mock docker
 		require.NoError(t, apitest.MockDocker(utils.Docker))
 		defer gock.OffAll()
@@ -112,12 +114,18 @@ func TestStopServices(t *testing.T) {
 			Post("/v" + utils.Docker.ClientVersion() + "/containers/prune").
 			Reply(http.StatusOK).
 			JSON(types.ContainersPruneReport{})
+		gock.New(utils.Docker.DaemonHost()).
+			Delete("/v" + utils.Docker.ClientVersion() + "/volumes/" + utils.ConfigId).
+			Reply(http.StatusOK)
 		gock.New(utils.Docker.DaemonHost()).
 			Delete("/v" + utils.Docker.ClientVersion() + "/volumes/" + utils.DbId).
 			Reply(http.StatusOK)
 		gock.New(utils.Docker.DaemonHost()).
 			Delete("/v" + utils.Docker.ClientVersion() + "/volumes/" + utils.StorageId).
 			Reply(http.StatusNotFound)
+		gock.New(utils.Docker.DaemonHost()).
+			Delete("/v" + utils.Docker.ClientVersion() + "/volumes/" + utils.DenoRelayId).
+			Reply(http.StatusNotFound)
 		gock.New(utils.Docker.DaemonHost()).
 			Post("/v" + utils.Docker.ClientVersion() + "/networks/prune").
 			Reply(http.StatusOK).