Skip to content

Commit

Permalink
Block dbt deploys from within Astro project (#1676)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremybeard authored and kushalmalani committed Jul 18, 2024
1 parent 57f2ee2 commit b5b1d79
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 1 deletion.
11 changes: 10 additions & 1 deletion cmd/cloud/dbt.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,17 @@ func deployDbt(cmd *cobra.Command, args []string) error {
dbtProjectPath = config.WorkingPath
}

// check that the dbt project path is not within an Astro project
withinAstroProject, err := config.IsWithinProjectDir(dbtProjectPath)
if err != nil {
return fmt.Errorf("failed to verify dbt project path is not within an Astro project: %w", err)
}
if withinAstroProject {
return fmt.Errorf("dbt project is within an Astro project. Use 'astro deploy' to deploy your Astro project")
}

// check that there is a valid dbt project at the dbt project path
err := validateDbtProjectExists(dbtProjectPath)
err = validateDbtProjectExists(dbtProjectPath)
if err != nil {
return err
}
Expand Down
11 changes: 11 additions & 0 deletions cmd/cloud/dbt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
astroplatformcore "github.com/astronomer/astro-cli/astro-client-platform-core"
astroplatformcore_mocks "github.com/astronomer/astro-cli/astro-client-platform-core/mocks"
cloud "github.com/astronomer/astro-cli/cloud/deploy"
"github.com/astronomer/astro-cli/config"
testUtil "github.com/astronomer/astro-cli/pkg/testing"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -125,6 +126,16 @@ func (s *DbtSuite) TestDbtDeploy_CustomMountPath() {
s.mockPlatformCoreClient.AssertExpectations(s.T())
}

func (s *DbtSuite) TestDbtDeploy_WithinAstroProject() {
projectDir, cleanup, err := config.CreateTempProject()
assert.NoError(s.T(), err)
defer cleanup()

err = testExecCmd(newDbtDeployCmd(), "test-deployment-id", "--project-path", projectDir)
assert.Error(s.T(), err)
assert.Contains(s.T(), err.Error(), "dbt project is within an Astro project")
}

func (s *DbtSuite) TestDbtDelete_PickDeployment() {
s.createDbtProjectFile("dbt_project.yml")
defer os.Remove("dbt_project.yml")
Expand Down
21 changes: 21 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/astronomer/astro-cli/pkg/fileutil"
"github.com/spf13/afero"
Expand Down Expand Up @@ -230,6 +231,26 @@ func IsProjectDir(path string) (bool, error) {
return fileutil.Exists(configFile, nil)
}

// IsWithinProjectDir returns true if the path is at or within an Astro project directory
func IsWithinProjectDir(path string) (bool, error) {
pathAbs, err := filepath.Abs(filepath.Clean(path))
if err != nil {
return false, err
}
pathComponents := strings.Split(pathAbs, string(os.PathSeparator))
for i := range pathComponents {
componentAbs := strings.Join(pathComponents[:i+1], string(os.PathSeparator))
isProjectDir, err := IsProjectDir(componentAbs)
if err != nil {
return false, err
}
if isProjectDir {
return true, nil
}
}
return false, nil
}

// saveConfig will save the config to a file
func saveConfig(v *viper.Viper, file string) error {
err := v.WriteConfigAs(file)
Expand Down
28 changes: 28 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,34 @@ func (s *Suite) TestIsProjectDir() {
}
}

func (s *Suite) TestIsWithinProjectDir() {
projectDir, cleanupProjectDir, err := CreateTempProject()
s.NoError(err)
defer cleanupProjectDir()

anotherDir, err := os.MkdirTemp("", "")
s.NoError(err)

tests := []struct {
name string
in string
out bool
}{
{"not in", anotherDir, false},
{"at", projectDir, true},
{"just in", filepath.Join(projectDir, "test"), true},
{"deep in", filepath.Join(projectDir, "test", "test", "test"), true},
{"root", string(os.PathSeparator), false},
}
for _, tt := range tests {
s.Run(tt.name, func() {
got, err := IsWithinProjectDir(tt.in)
s.NoError(err)
s.Equal(got, tt.out)
})
}
}

func (s *Suite) TestInitHomeDefaultCase() {
fs := afero.NewMemMapFs()
initHome(fs)
Expand Down
27 changes: 27 additions & 0 deletions config/config_test_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package config

import (
"io/fs"
"os"
"path/filepath"
)

func CreateTempProject() (dir string, cleanup func(), err error) {
projectDir, err := os.MkdirTemp("", "")
if err != nil {
return "", nil, err
}
astroDirPerms := 0o755
err = os.Mkdir(filepath.Join(projectDir, ".astro"), fs.FileMode(astroDirPerms))
if err != nil {
return "", nil, err
}
configFile, err := os.Create(filepath.Join(projectDir, ConfigDir, ConfigFileNameWithExt))
if err != nil {
return "", nil, err
}
return projectDir, func() {
configFile.Close()
os.RemoveAll(projectDir)
}, nil
}

0 comments on commit b5b1d79

Please sign in to comment.