From f22a7cb65a5d57d86948804bf7d4a304f0d77355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulo=20Ara=C3=BAjo?= Date: Fri, 13 Feb 2026 17:07:04 +0100 Subject: [PATCH] feat: support for db migrations --- go/porcelain/deploy.go | 16 +++++++++++-- go/porcelain/deploy_test.go | 48 +++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/go/porcelain/deploy.go b/go/porcelain/deploy.go index b1017894b..368ddb349 100644 --- a/go/porcelain/deploy.go +++ b/go/porcelain/deploy.go @@ -43,8 +43,9 @@ const ( lfsVersionString = "version https://git-lfs.github.com/spec/v1" - edgeFunctionsInternalPath = ".netlify/internal/edge-functions/" - edgeRedirectsInternalPath = ".netlify/deploy-config/" + edgeFunctionsInternalPath = ".netlify/internal/edge-functions/" + edgeRedirectsInternalPath = ".netlify/deploy-config/" + dbMigrationsInternalPath = ".netlify/internal/db/migrations/" ) var installDirs = []string{"node_modules/", "bower_components/"} @@ -89,6 +90,7 @@ type DeployOptions struct { FunctionsDir string EdgeFunctionsDir string EdgeRedirectsDir string + DbMigrationsDir string BuildDir string LargeMediaEnabled bool Environment []*models.DeployEnvironmentVariable @@ -255,6 +257,16 @@ func (n *Netlify) DoDeploy(ctx context.Context, options *DeployOptions, deploy * } } + if options.DbMigrationsDir != "" { + err = addInternalFilesToDeploy(options.DbMigrationsDir, dbMigrationsInternalPath, files, options.Observer) + if err != nil { + if options.Observer != nil { + options.Observer.OnFailedWalk() + } + return nil, err + } + } + options.files = files functions, schedules, functionsConfig, err := bundle(ctx, options.FunctionsDir, options.Observer) diff --git a/go/porcelain/deploy_test.go b/go/porcelain/deploy_test.go index 537a5efd9..a56c99d59 100644 --- a/go/porcelain/deploy_test.go +++ b/go/porcelain/deploy_test.go @@ -287,6 +287,54 @@ func TestWalk_PublishedFilesAndEdgeRedirects(t *testing.T) { assert.NotNil(t, files.Files[".netlify/deploy-config/redirects.json"]) } +func TestWalk_DbMigrations(t *testing.T) { + files := newDeployFiles() + + netlifyDir, err := ioutil.TempDir("", ".netlify") + require.Nil(t, err) + defer os.RemoveAll(netlifyDir) + + dbMigrationsDir, err := ioutil.TempDir(netlifyDir, "db-migrations-dist") + require.Nil(t, err) + defer os.RemoveAll(dbMigrationsDir) + + migrationDir := filepath.Join(dbMigrationsDir, "1700000000_create-users") + err = os.Mkdir(migrationDir, os.ModePerm) + require.Nil(t, err) + err = ioutil.WriteFile(filepath.Join(migrationDir, "migration.sql"), []byte("CREATE TABLE users (id INT);"), 0644) + require.Nil(t, err) + + err = addInternalFilesToDeploy(dbMigrationsDir, dbMigrationsInternalPath, files, mockObserver{}) + require.Nil(t, err) + + assert.NotNil(t, files.Files[".netlify/internal/db/migrations/1700000000_create-users/migration.sql"]) +} + +func TestWalk_PublishedFilesAndDbMigrations(t *testing.T) { + files := setupPublishedAssets(t) + + netlifyDir, err := ioutil.TempDir("", ".netlify") + require.Nil(t, err) + defer os.RemoveAll(netlifyDir) + + dbMigrationsDir, err := ioutil.TempDir(netlifyDir, "db-migrations-dist") + require.Nil(t, err) + defer os.RemoveAll(dbMigrationsDir) + + migrationDir := filepath.Join(dbMigrationsDir, "1700000000_create-users") + err = os.Mkdir(migrationDir, os.ModePerm) + require.Nil(t, err) + err = ioutil.WriteFile(filepath.Join(migrationDir, "migration.sql"), []byte("CREATE TABLE users (id INT);"), 0644) + require.Nil(t, err) + + err = addInternalFilesToDeploy(dbMigrationsDir, dbMigrationsInternalPath, files, mockObserver{}) + require.Nil(t, err) + + assert.NotNil(t, files.Files["assets/styles.css"]) + assert.NotNil(t, files.Files["index.html"]) + assert.NotNil(t, files.Files[".netlify/internal/db/migrations/1700000000_create-users/migration.sql"]) +} + func setupPublishedAssets(t *testing.T) *deployFiles { publishDir, err := ioutil.TempDir("", "publish") require.Nil(t, err)