From a4c464d4330ef23be48827074af73334ee385e2e Mon Sep 17 00:00:00 2001 From: aryansharma9917 Date: Sat, 14 Feb 2026 17:02:12 +0530 Subject: [PATCH 1/4] Add automatic namespace provisioning before deployment --- pkg/deploy/deploy.go | 14 +++++++-- pkg/deploy/namespace.go | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 pkg/deploy/namespace.go diff --git a/pkg/deploy/deploy.go b/pkg/deploy/deploy.go index c08910c..3802bea 100644 --- a/pkg/deploy/deploy.go +++ b/pkg/deploy/deploy.go @@ -9,14 +9,22 @@ func Run(envName string, dryRun bool) error { return err } - //////////////////////////////////////////////////// - // PREFLIGHT FIRST - //////////////////////////////////////////////////// + //////////////////////////////////// + // PREFLIGHT + //////////////////////////////////// if err := Preflight(environment); err != nil { return err } + //////////////////////////////////// + // ENSURE NAMESPACE + //////////////////////////////////// + + if err := EnsureNamespace(environment); err != nil { + return err + } + command, _, err := BuildCommand(environment) if err != nil { return err diff --git a/pkg/deploy/namespace.go b/pkg/deploy/namespace.go new file mode 100644 index 0000000..9f93ca0 --- /dev/null +++ b/pkg/deploy/namespace.go @@ -0,0 +1,65 @@ +package deploy + +import ( + "fmt" + "os/exec" + + "github.com/aryansharma9917/codewise-cli/pkg/env" +) + +func namespaceExists(namespace string, context string) bool { + + args := []string{"get", "ns", namespace} + + if context != "" { + args = append(args, "--context", context) + } + + cmd := exec.Command("kubectl", args...) + + if err := cmd.Run(); err != nil { + return false + } + + return true +} + +func createNamespace(namespace string, context string) error { + + args := []string{"create", "ns", namespace} + + if context != "" { + args = append(args, "--context", context) + } + + cmd := exec.Command("kubectl", args...) + + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("failed to create namespace: %s", string(output)) + } + + return nil +} + +func EnsureNamespace(environment *env.Env) error { + + ns := environment.K8s.Namespace + ctx := environment.K8s.Context + + fmt.Printf("Checking namespace \"%s\"...\n", ns) + + if namespaceExists(ns, ctx) { + fmt.Println("Namespace exists") + return nil + } + + fmt.Println("Namespace not found. Creating namespace...") + + if err := createNamespace(ns, ctx); err != nil { + return err + } + + fmt.Println("Namespace created") + return nil +} From c990e0379fe3e0701cd5ca1dd69485defad6ad8f Mon Sep 17 00:00:00 2001 From: aryansharma9917 Date: Sat, 14 Feb 2026 17:07:08 +0530 Subject: [PATCH 2/4] Add deployment rollout monitoring after release --- pkg/deploy/deploy.go | 18 +++++++++++++++- pkg/deploy/rollout.go | 49 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 pkg/deploy/rollout.go diff --git a/pkg/deploy/deploy.go b/pkg/deploy/deploy.go index 3802bea..d4fc39c 100644 --- a/pkg/deploy/deploy.go +++ b/pkg/deploy/deploy.go @@ -36,5 +36,21 @@ func Run(envName string, dryRun bool) error { fmt.Println("Starting deployment...") - return executor.Run(command.Name, command.Args...) + if err := executor.Run(command.Name, command.Args...); err != nil { + return err + } + + //////////////////////////////////// + // SKIP ROLLOUT FOR DRY RUN + //////////////////////////////////// + + if dryRun { + return nil + } + + //////////////////////////////////// + // MONITOR ROLLOUT + //////////////////////////////////// + + return MonitorRollout(environment) } diff --git a/pkg/deploy/rollout.go b/pkg/deploy/rollout.go new file mode 100644 index 0000000..5a2ae57 --- /dev/null +++ b/pkg/deploy/rollout.go @@ -0,0 +1,49 @@ +package deploy + +import ( + "fmt" + "os/exec" + "time" + + "github.com/aryansharma9917/codewise-cli/pkg/env" +) + +func MonitorRollout(environment *env.Env) error { + + release := environment.Helm.Release + namespace := environment.K8s.Namespace + context := environment.K8s.Context + + fmt.Println("Waiting for deployment rollout...") + + // We assume Helm creates a Deployment with the release name. + // This is standard Helm behavior unless overridden. + + args := []string{ + "rollout", + "status", + "deployment/" + release, + "-n", + namespace, + } + + if context != "" { + args = append(args, "--context", context) + } + + cmd := exec.Command("kubectl", args...) + + // Stream output live + cmd.Stdout = nil + cmd.Stderr = nil + + err := cmd.Run() + if err != nil { + return fmt.Errorf("deployment failed to roll out") + } + + time.Sleep(1 * time.Second) + + fmt.Println("Deployment successfully rolled out.") + return nil +} From 5abf37b66eb1787550da392afdd6f596d27613ea Mon Sep 17 00:00:00 2001 From: aryansharma9917 Date: Sat, 14 Feb 2026 17:10:38 +0530 Subject: [PATCH 3/4] Improve rollout monitoring by discovering deployments dynamically --- pkg/deploy/rollout.go | 75 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/pkg/deploy/rollout.go b/pkg/deploy/rollout.go index 5a2ae57..0c3b3bf 100644 --- a/pkg/deploy/rollout.go +++ b/pkg/deploy/rollout.go @@ -3,28 +3,54 @@ package deploy import ( "fmt" "os/exec" + "strings" "time" "github.com/aryansharma9917/codewise-cli/pkg/env" ) -func MonitorRollout(environment *env.Env) error { +func getDeployments(namespace string, context string) ([]string, error) { - release := environment.Helm.Release - namespace := environment.K8s.Namespace - context := environment.K8s.Context + args := []string{ + "get", + "deployments", + "-n", + namespace, + "-o", + "name", + } - fmt.Println("Waiting for deployment rollout...") + if context != "" { + args = append(args, "--context", context) + } + + cmd := exec.Command("kubectl", args...) + out, err := cmd.Output() + if err != nil { + return nil, fmt.Errorf("failed to list deployments") + } + + lines := strings.Split(strings.TrimSpace(string(out)), "\n") - // We assume Helm creates a Deployment with the release name. - // This is standard Helm behavior unless overridden. + var deployments []string + for _, line := range lines { + if strings.TrimSpace(line) != "" { + deployments = append(deployments, line) + } + } + + return deployments, nil +} + +func waitForDeployment(deployment string, namespace string, context string) error { args := []string{ "rollout", "status", - "deployment/" + release, + deployment, "-n", namespace, + "--timeout=120s", } if context != "" { @@ -32,18 +58,39 @@ func MonitorRollout(environment *env.Env) error { } cmd := exec.Command("kubectl", args...) - - // Stream output live cmd.Stdout = nil cmd.Stderr = nil - err := cmd.Run() + return cmd.Run() +} + +func MonitorRollout(environment *env.Env) error { + + ns := environment.K8s.Namespace + ctx := environment.K8s.Context + + fmt.Println("Waiting for deployment rollout...") + + deployments, err := getDeployments(ns, ctx) if err != nil { - return fmt.Errorf("deployment failed to roll out") + return err + } + + if len(deployments) == 0 { + fmt.Println("No deployments found. Skipping rollout monitoring.") + return nil } - time.Sleep(1 * time.Second) + for _, deploy := range deployments { + fmt.Printf("Monitoring %s...\n", deploy) + + if err := waitForDeployment(deploy, ns, ctx); err != nil { + return fmt.Errorf("deployment %s failed to roll out", deploy) + } + + time.Sleep(500 * time.Millisecond) + } - fmt.Println("Deployment successfully rolled out.") + fmt.Println("All deployments successfully rolled out.") return nil } From 2d0c936ee3a52e92c75fbcb2af39881d641bb6c3 Mon Sep 17 00:00:00 2001 From: aryansharma9917 Date: Sat, 14 Feb 2026 17:13:52 +0530 Subject: [PATCH 4/4] Add deployment template to Helm chart for workload rollout --- helm/chart/templates/deployment.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/helm/chart/templates/deployment.yaml b/helm/chart/templates/deployment.yaml index 20cebec..03b19c0 100644 --- a/helm/chart/templates/deployment.yaml +++ b/helm/chart/templates/deployment.yaml @@ -2,18 +2,24 @@ apiVersion: apps/v1 kind: Deployment metadata: name: {{ .Release.Name }} - namespace: {{ .Values.namespace }} + labels: + app: {{ .Release.Name }} + spec: replicas: 1 + selector: matchLabels: app: {{ .Release.Name }} + template: metadata: labels: app: {{ .Release.Name }} + spec: containers: - name: app - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - imagePullPolicy: {{ .Values.image.pullPolicy }} + image: nginx:latest + ports: + - containerPort: 80