diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..1e987a0 --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,28 @@ +name: Go + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: '^1.20' + + - name: Install dependencies + run: go mod tidy + + - name: Run tests for delete command + run: go test ./internal/delete* -v \ No newline at end of file diff --git a/cmd/boneless/main.go b/cmd/boneless/main.go index 2c794ac..ecfccf9 100644 --- a/cmd/boneless/main.go +++ b/cmd/boneless/main.go @@ -20,6 +20,7 @@ Targets: migrate Run migrations for an app create-app Create a new app based on a template build-app Build an app using Weaver and SQLC + delete-app Delete an app created run Run the project using Weaver Parameters: @@ -37,6 +38,7 @@ Examples: boneless migrate my-app up boneless create-app my-app boneless build-app my-app + boneless delete-app my-app boneless run ` @@ -51,6 +53,7 @@ const ( cmdMigrate = "migrate" cmdCreateApp = "create-app" cmdBuildApp = "build-app" + cmdDeleteApp = "delete-app" cmdRun = "run" DefaultComponentName = "app" @@ -83,6 +86,8 @@ func main() { internal.Build(flag.Arg(1), internal.KindComponent, "") internal.SqlcGenerate(flag.Arg(1)) internal.WeaverGenerate() + case cmdDeleteApp: + internal.DeleteApp(flag.Arg(1)) case cmdBuild: internal.SqlcGenerate() internal.WeaverGenerate() diff --git a/internal/delete.go b/internal/delete.go new file mode 100644 index 0000000..56bd623 --- /dev/null +++ b/internal/delete.go @@ -0,0 +1,54 @@ +package internal + +import ( + "fmt" + "os" +) + +func DeleteApp(appName string) { + if isValid := isAppNameValid(appName); !isValid { + return + } + + appFolderPath := getAppFolderPath(appName) + if exists := folderExists(appFolderPath); !exists { + return + } + + // Delete the app folder + if err := os.RemoveAll(appFolderPath); err != nil { + panic("Error deleting app folder: " + err.Error()) + } + + fmt.Printf("App deleted successfully: %s\n", appName) +} + +func isAppNameValid(appName string) bool { + if appName == "app" { + fmt.Println("You can't delete the app folder: it's the example component") + return false + } + + if appName == "bff" { + fmt.Println("You can't delete the bff folder: it's required to run the application") + return false + } + + return true +} + +func folderExists(pathToDelete string) bool { + if _, err := os.Stat(pathToDelete); err != nil { + if os.IsNotExist(err) { + fmt.Println("App folder not found") + return false + } + + panic("Error checking app folder: " + err.Error()) + } + return true +} + +func getAppFolderPath(appName string) string { + return fmt.Sprintf("internal/%s", appName) +} diff --git a/internal/delete_test.go b/internal/delete_test.go new file mode 100644 index 0000000..9622a8d --- /dev/null +++ b/internal/delete_test.go @@ -0,0 +1,83 @@ +package internal + +import ( + "bytes" + "io" + "os" + "path/filepath" + "testing" +) + +func TestDeleteApp(t *testing.T) { + tmpDir := t.TempDir() + appName := "test-app" + appFolderPath := filepath.Join(tmpDir, "internal", appName) + + t.Log("tmpDir: ", tmpDir) + + // Create a temporary app folder + if err := os.MkdirAll(appFolderPath, 0755); err != nil { + t.Fatalf("Failed to create app folder: %v", err) + } + + // Change the working directory to the temporary directory + if err := os.Chdir(tmpDir); err != nil { + t.Fatalf("Failed to change directory: %v", err) + } + + // Call DeleteApp + DeleteApp(appName) + + // Verify the app folder has been deleted + if _, err := os.Stat(appFolderPath); !os.IsNotExist(err) { + t.Fatalf("App folder was not deleted") + } +} + +func TestDeleteApp_NotFound(t *testing.T) { + tmpDir := t.TempDir() + appName := "test-app" + + // Change the working directory to the temporary directory + if err := os.Chdir(tmpDir); err != nil { + t.Fatalf("Failed to change directory: %v", err) + } + + // Save the current stdout + originalStdout := os.Stdout + + // Create a buffer to capture the output + r, w, _ := os.Pipe() + os.Stdout = w + + DeleteApp(appName) + + // Restore the original stdout and close the writer + w.Close() + os.Stdout = originalStdout + + // Read the captured output + var buf bytes.Buffer + io.Copy(&buf, r) + + if buf.String() != "App folder not found\n" { + t.Fatalf("Unexpected output: %s", buf.String()) + } +} + +func TestDeleteApp_ErrorDeleting(t *testing.T) { + tmpDir := t.TempDir() + + // Change the working directory to the temporary directory + if err := os.Chdir(tmpDir); err != nil { + t.Fatalf("Failed to change directory: %v", err) + } + + // Call DeleteApp and expect a panic + defer func() { + if r := recover(); r == nil { + t.Fatalf("Expected panic but did not occur") + } + }() + DeleteApp("\x00") +}