Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions go/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,23 @@ package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/soda-data-inc/soda-cli/internal/output"
)

var defaultSodaYml = `# soda.yml — project configuration
# Docs: https://github.com/sodadata/soda-cli

# datasource: my_datasource
# type: postgres
# host: localhost
# port: "5432"
# database: my_db
`

var initCmd = &cobra.Command{
Use: "init",
Short: "Scaffold soda.yml and project structure",
Expand All @@ -17,9 +28,24 @@ var initCmd = &cobra.Command{
fmt.Println("Scaffolding soda project structure...")
fmt.Println()
}

// Create soda.yml if it doesn't already exist
if _, err := os.Stat("soda.yml"); err == nil {
return fmt.Errorf("soda.yml already exists in this directory")
}
if err := os.WriteFile("soda.yml", []byte(defaultSodaYml), 0644); err != nil {
return fmt.Errorf("failed to create soda.yml: %w", err)
}
fmt.Println(" Created soda.yml")
fmt.Println(" Created contracts/")
fmt.Println(" Created configs/")

// Create contracts/ and configs/ directories
for _, dir := range []string{"contracts", "configs"} {
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create %s/: %w", dir, err)
}
fmt.Printf(" Created %s/\n", dir)
}

fmt.Println()
output.PrintSuccess("Project initialized. Edit soda.yml to configure your datasources.", GCtx)
return nil
Expand Down
28 changes: 28 additions & 0 deletions go/tests/integration/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,34 @@ func run(t *testing.T, args ...string) Result {
}
}

// runInDir executes sodacli with the given args in the specified directory.
func runInDir(t *testing.T, dir string, args ...string) Result {
t.Helper()
bin := ensureBinary(t)

cmd := exec.Command(bin, args...)
cmd.Dir = dir
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr

err := cmd.Run()
exitCode := 0
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
exitCode = exitErr.ExitCode()
} else {
t.Fatalf("failed to run command: %v", err)
}
}

return Result{
Stdout: stdout.String(),
Stderr: stderr.String(),
ExitCode: exitCode,
}
}

// Output returns combined stdout+stderr for simple checks.
func (r Result) Output() string {
return r.Stdout + r.Stderr
Expand Down
49 changes: 49 additions & 0 deletions go/tests/integration/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//go:build integration

package integration

import (
"os"
"path/filepath"
"testing"
)

func TestInit(t *testing.T) {
t.Run("creates_files_and_dirs", func(t *testing.T) {
dir := t.TempDir()
r := runInDir(t, dir, "init", "--no-interactive")
assertExitCode(t, r, 0)
assertOutputContains(t, r, "Created soda.yml")
assertOutputContains(t, r, "Created contracts/")
assertOutputContains(t, r, "Created configs/")

// Verify soda.yml was actually created
info, err := os.Stat(filepath.Join(dir, "soda.yml"))
if err != nil {
t.Fatalf("soda.yml not created: %v", err)
}
if info.Size() == 0 {
t.Error("soda.yml is empty")
}

// Verify directories were created
for _, d := range []string{"contracts", "configs"} {
info, err := os.Stat(filepath.Join(dir, d))
if err != nil {
t.Fatalf("%s/ not created: %v", d, err)
}
if !info.IsDir() {
t.Errorf("%s is not a directory", d)
}
}
})

t.Run("fails_if_soda_yml_exists", func(t *testing.T) {
dir := t.TempDir()
os.WriteFile(filepath.Join(dir, "soda.yml"), []byte("existing"), 0644)

r := runInDir(t, dir, "init", "--no-interactive")
assertExitCode(t, r, 1)
assertOutputContains(t, r, "already exists")
})
}