From d0b49d76ca5cd2a58a442f8d1fc570ec89d788fa Mon Sep 17 00:00:00 2001
From: lijianguo <lijianguo1991@outlook.com>
Date: Wed, 27 Nov 2024 18:20:59 +0800
Subject: [PATCH 1/2] chore(workflow-cli): build create hint if has large
 change

---
 cmd/builds.go         | 32 ++++++++++++++++++--
 cmd/builds_test.go    | 68 +++++++++++++++++++++++--------------------
 cmd/cmd.go            |  2 +-
 parser/builds.go      |  5 +++-
 parser/builds_test.go |  2 +-
 5 files changed, 73 insertions(+), 36 deletions(-)

diff --git a/cmd/builds.go b/cmd/builds.go
index 1530081d..193e9d5f 100644
--- a/cmd/builds.go
+++ b/cmd/builds.go
@@ -1,10 +1,12 @@
 package cmd
 
 import (
+	"fmt"
 	"os"
 
 	yaml "gopkg.in/yaml.v3"
 
+	drycc "github.com/drycc/controller-sdk-go"
 	"github.com/drycc/controller-sdk-go/builds"
 )
 
@@ -54,7 +56,7 @@ func (d *DryccCmd) BuildsInfo(appID string, version int) error {
 }
 
 // BuildsCreate creates a build for an app.
-func (d *DryccCmd) BuildsCreate(appID, image, stack, procfile string, dryccfile string) error {
+func (d *DryccCmd) BuildsCreate(appID, image, stack, procfile, dryccfile, confirm string) error {
 	s, appID, err := load(d.ConfigFile, appID)
 
 	if err != nil {
@@ -84,7 +86,11 @@ func (d *DryccCmd) BuildsCreate(appID, image, stack, procfile string, dryccfile
 			return err
 		}
 	}
-
+	// check procfileMap dryccfileMap stack is exist
+	err = buildConfirmAction(s.Client, appID, procfileMap, dryccfileMap, confirm)
+	if err != nil {
+		return err
+	}
 	d.Print("Creating build... ")
 	quit := progress(d.WOut)
 	_, err = builds.New(s.Client, appID, image, stack, procfileMap, dryccfileMap)
@@ -108,3 +114,25 @@ func parseDryccfile(dryccfile []byte) (map[string]interface{}, error) {
 	dryccfileMap := make(map[string]interface{})
 	return dryccfileMap, yaml.Unmarshal(dryccfile, &dryccfileMap)
 }
+
+func buildConfirmAction(c *drycc.Client, appID string, procfileMap map[string]string,
+	dryccfileMap map[string]interface{}, confirm string) error {
+
+	build, _ := builds.Get(c, appID, 0)
+
+	if ((len(build.Procfile) != 0 && len(procfileMap) == 0) || (len(build.Dryccfile) != 0 && len(dryccfileMap) == 0)) && (confirm == "" || confirm != "yes") {
+		// hint
+		fmt.Printf(` !    WARNING: Potentially Build Create Action
+ !    The Procfile or drycc.yaml is empty, not last time
+ !    To proceed, type "yes" !
+
+> `)
+
+		fmt.Scanln(&confirm)
+		if confirm != "yes" {
+			return fmt.Errorf("cancel the build create action")
+		}
+		return nil
+	}
+	return nil
+}
diff --git a/cmd/builds_test.go b/cmd/builds_test.go
index 28ffffdc..cf9e01f9 100644
--- a/cmd/builds_test.go
+++ b/cmd/builds_test.go
@@ -84,28 +84,32 @@ func TestBuildsCreate(t *testing.T) {
 
 	server.Mux.HandleFunc("/v2/apps/enterprise/build/", func(w http.ResponseWriter, r *http.Request) {
 		testutil.SetHeaders(w)
-		testutil.AssertBody(t, api.CreateBuildRequest{
-			Image: "ncc/1701:A",
-			Stack: "container",
-		}, r)
-		w.WriteHeader(http.StatusCreated)
-		fmt.Fprintf(w, "{}")
+		if r.Method == "POST" {
+			testutil.AssertBody(t, api.CreateBuildRequest{
+				Image: "ncc/1701:A",
+				Stack: "container",
+			}, r)
+			w.WriteHeader(http.StatusCreated)
+			fmt.Fprintf(w, "{}")
+		}
 	})
 
-	err = cmdr.BuildsCreate("enterprise", "ncc/1701:A", "container", "", "")
+	err = cmdr.BuildsCreate("enterprise", "ncc/1701:A", "container", "", "", "yes")
 	assert.NoError(t, err)
 	assert.Equal(t, testutil.StripProgress(b.String()), "Creating build... done\n", "output")
 
 	server.Mux.HandleFunc("/v2/apps/bradbury/build/", func(w http.ResponseWriter, r *http.Request) {
 		testutil.SetHeaders(w)
-		testutil.AssertBody(t, api.CreateBuildRequest{
-			Image: "nx/72307:latest",
-			Stack: "container",
-			Procfile: map[string]string{
-				"web":  "./drive",
-				"warp": "./warp 8",
-			},
-		}, r)
+		if r.Method == "POST" {
+			testutil.AssertBody(t, api.CreateBuildRequest{
+				Image: "nx/72307:latest",
+				Stack: "container",
+				Procfile: map[string]string{
+					"web":  "./drive",
+					"warp": "./warp 8",
+				},
+			}, r)
+		}
 
 		w.WriteHeader(http.StatusCreated)
 		fmt.Fprintf(w, "{}")
@@ -127,28 +131,30 @@ warp: ./warp 8`
 		}
 	}()
 
-	err = cmdr.BuildsCreate("bradbury", "nx/72307:latest", "container", tmpDir+"/Procfile", "")
+	err = cmdr.BuildsCreate("bradbury", "nx/72307:latest", "container", tmpDir+"/Procfile", "", "yes")
 	assert.NoError(t, err)
 	assert.Equal(t, testutil.StripProgress(b.String()), "Creating build... done\n", "output")
 
 	server.Mux.HandleFunc("/v2/apps/franklin/build/", func(w http.ResponseWriter, r *http.Request) {
 		testutil.SetHeaders(w)
-		testutil.AssertBody(t, api.CreateBuildRequest{
-			Image: "nx/326:latest",
-			Stack: "container",
-			Procfile: map[string]string{
-				"web":  "./drive",
-				"warp": "./warp 8",
-			},
-			Dryccfile: map[string]interface{}{
-				"deploy": map[string]interface{}{
-					"web": map[string]interface{}{
-						"command": []string{"bash", "-c"},
-						"args":    []string{"bundle exec puma -C config/puma.rb"},
+		if r.Method == "POST" {
+			testutil.AssertBody(t, api.CreateBuildRequest{
+				Image: "nx/326:latest",
+				Stack: "container",
+				Procfile: map[string]string{
+					"web":  "./drive",
+					"warp": "./warp 8",
+				},
+				Dryccfile: map[string]interface{}{
+					"deploy": map[string]interface{}{
+						"web": map[string]interface{}{
+							"command": []string{"bash", "-c"},
+							"args":    []string{"bundle exec puma -C config/puma.rb"},
+						},
 					},
 				},
-			},
-		}, r)
+			}, r)
+		}
 
 		w.WriteHeader(http.StatusCreated)
 		fmt.Fprintf(w, "{}")
@@ -171,7 +177,7 @@ deploy:
 `), os.ModePerm)
 	assert.NoError(t, err)
 
-	err = cmdr.BuildsCreate("franklin", "nx/326:latest", "container", "Procfile", "drycc.yaml")
+	err = cmdr.BuildsCreate("franklin", "nx/326:latest", "container", "Procfile", "drycc.yaml", "yes")
 	assert.NoError(t, err)
 	assert.Equal(t, testutil.StripProgress(b.String()), "Creating build... done\n", "output")
 
diff --git a/cmd/cmd.go b/cmd/cmd.go
index 6f8aa834..18492b5d 100644
--- a/cmd/cmd.go
+++ b/cmd/cmd.go
@@ -35,7 +35,7 @@ type Commander interface {
 	TokensAdd(*drycc.Client, string, string, string, string, bool) (*api.AuthTokenResponse, error)
 	TokensRemove(string, string) error
 	BuildsInfo(string, int) error
-	BuildsCreate(string, string, string, string, string) error
+	BuildsCreate(string, string, string, string, string, string) error
 	CertsList(string, int) error
 	CertAdd(string, string, string, string) error
 	CertRemove(string, string) error
diff --git a/parser/builds.go b/parser/builds.go
index 2e4efb8b..30bac089 100644
--- a/parser/builds.go
+++ b/parser/builds.go
@@ -88,6 +88,8 @@ Options:
     A YAML file used to supply a Procfile to the application.
   -d --dryccfile=<dryccfile>
     A YAML file used to supply a drycc.yaml to the application.
+  --confirm=yes
+    To proceed, type "yes".
 `
 
 	args, err := docopt.ParseArgs(usage, argv, "")
@@ -99,11 +101,12 @@ Options:
 	app := safeGetString(args, "--app")
 	image := safeGetString(args, "<image>")
 	stack := safeGetString(args, "--stack")
+	confirm := safeGetString(args, "--confirm")
 	if stack == "" {
 		stack = "container"
 	}
 	procfile := safeGetValue(args, "--procfile", "Procfile")
 	dryccfile := safeGetValue(args, "--dryccfile", "drycc.yaml")
 
-	return cmdr.BuildsCreate(app, image, stack, procfile, dryccfile)
+	return cmdr.BuildsCreate(app, image, stack, procfile, dryccfile, confirm)
 }
diff --git a/parser/builds_test.go b/parser/builds_test.go
index 24b56109..c3ee1571 100644
--- a/parser/builds_test.go
+++ b/parser/builds_test.go
@@ -13,7 +13,7 @@ func (d FakeDryccCmd) BuildsInfo(string, int) error {
 	return errors.New("builds:info")
 }
 
-func (d FakeDryccCmd) BuildsCreate(string, string, string, string, string) error {
+func (d FakeDryccCmd) BuildsCreate(string, string, string, string, string, string) error {
 	return errors.New("builds:create")
 }
 

From 10bf247244e9e2103f50b73ea9a01449dc3f9b5c Mon Sep 17 00:00:00 2001
From: lijianguo <lijianguo1991@outlook.com>
Date: Thu, 28 Nov 2024 11:21:32 +0800
Subject: [PATCH 2/2] chore(ps): support previous pod logs

---
 cmd/builds.go     | 1 -
 cmd/cmd.go        | 2 +-
 cmd/ps.go         | 3 ++-
 cmd/ps_test.go    | 2 +-
 go.mod            | 2 +-
 go.sum            | 4 ++--
 parser/ps.go      | 5 ++++-
 parser/ps_test.go | 2 +-
 parser/pts.go     | 2 +-
 9 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/cmd/builds.go b/cmd/builds.go
index 193e9d5f..d0ceebb1 100644
--- a/cmd/builds.go
+++ b/cmd/builds.go
@@ -132,7 +132,6 @@ func buildConfirmAction(c *drycc.Client, appID string, procfileMap map[string]st
 		if confirm != "yes" {
 			return fmt.Errorf("cancel the build create action")
 		}
-		return nil
 	}
 	return nil
 }
diff --git a/cmd/cmd.go b/cmd/cmd.go
index 18492b5d..322ba6f4 100644
--- a/cmd/cmd.go
+++ b/cmd/cmd.go
@@ -89,7 +89,7 @@ type Commander interface {
 	PermUpdate(string, string, string) error
 	PermDelete(string, string) error
 	PsList(string, int) error
-	PsLogs(string, string, int, bool, string) error
+	PsLogs(string, string, int, bool, string, bool) error
 	PsExec(string, string, bool, bool, []string) error
 	PsDescribe(string, string) error
 	PsDelete(string, []string) error
diff --git a/cmd/ps.go b/cmd/ps.go
index 0a0c6e26..f6e1059d 100644
--- a/cmd/ps.go
+++ b/cmd/ps.go
@@ -50,7 +50,7 @@ func (d *DryccCmd) PsList(appID string, results int) error {
 }
 
 // PodLogs returns the logs from an pod.
-func (d *DryccCmd) PsLogs(appID, podID string, lines int, follow bool, container string) error {
+func (d *DryccCmd) PsLogs(appID, podID string, lines int, follow bool, container string, previous bool) error {
 	s, appID, err := load(d.ConfigFile, appID)
 
 	if err != nil {
@@ -60,6 +60,7 @@ func (d *DryccCmd) PsLogs(appID, podID string, lines int, follow bool, container
 		Lines:     lines,
 		Follow:    follow,
 		Container: container,
+		Previous:  previous,
 	}
 	conn, err := ps.Logs(s.Client, appID, podID, request)
 	if err != nil {
diff --git a/cmd/ps_test.go b/cmd/ps_test.go
index 41e11ee8..6707c904 100644
--- a/cmd/ps_test.go
+++ b/cmd/ps_test.go
@@ -121,7 +121,7 @@ func TestPsLogs(t *testing.T) {
 			conn.WriteClose(100)
 		}),
 	)
-	err = cmdr.PsLogs("foo", "foo-web-111", 300, true, "runner")
+	err = cmdr.PsLogs("foo", "foo-web-111", 300, true, "runner", false)
 	assert.NoError(t, err)
 }
 
diff --git a/go.mod b/go.mod
index 622a2c2b..8282a1ce 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.23
 require (
 	github.com/containerd/console v1.0.4
 	github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
-	github.com/drycc/controller-sdk-go v0.0.0-20241122013249-f1d6fea5bf81
+	github.com/drycc/controller-sdk-go v0.0.0-20241128052705-94f8d2dcc087
 	github.com/drycc/pkg v0.0.0-20241028091700-8caca001c932
 	github.com/minio/selfupdate v0.6.0
 	github.com/olekukonko/tablewriter v0.0.5
diff --git a/go.sum b/go.sum
index 1479e783..23def561 100644
--- a/go.sum
+++ b/go.sum
@@ -9,8 +9,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 h1:bWDMxwH3px2JBh6AyO7hdCn/PkvCZXii8TGj7sbtEbQ=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/drycc/controller-sdk-go v0.0.0-20241122013249-f1d6fea5bf81 h1:y809MASIviVNxzUxP1CDU2EaB5AruRNAiFKjOMCx+0s=
-github.com/drycc/controller-sdk-go v0.0.0-20241122013249-f1d6fea5bf81/go.mod h1:F9ViuoVcZ/OG1WnfZBYH6j4v6mb5B+RW9FLaCopADoo=
+github.com/drycc/controller-sdk-go v0.0.0-20241128052705-94f8d2dcc087 h1:cbniB2KxxeV72y/7KILVorTTxlzCF41xtBysDT1FjJg=
+github.com/drycc/controller-sdk-go v0.0.0-20241128052705-94f8d2dcc087/go.mod h1:F9ViuoVcZ/OG1WnfZBYH6j4v6mb5B+RW9FLaCopADoo=
 github.com/drycc/pkg v0.0.0-20241028091700-8caca001c932 h1:tUfkfjmFmlm9n0dYp1NoHcFK6+APD/wHZ2We6CKXDSI=
 github.com/drycc/pkg v0.0.0-20241028091700-8caca001c932/go.mod h1:upGcZF/RCEqidGjSnWHh/txRC1I4GPsRGvF8/+bDfwU=
 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
diff --git a/parser/ps.go b/parser/ps.go
index 481ea182..f1f7318c 100644
--- a/parser/ps.go
+++ b/parser/ps.go
@@ -86,6 +86,8 @@ Options:
     specify if the logs should be streamed.
   -c --container=<container>
     print the logs of this container.
+  --previous
+    print the logs for the previous instance of the container in a pod if it exists.
 `
 
 	args, err := docopt.ParseArgs(usage, argv, "")
@@ -104,8 +106,9 @@ Options:
 	follow := safeGetBool(args, "--follow")
 	podID := safeGetString(args, "<pod>")
 	container := safeGetString(args, "--container")
+	previous := args["--previous"].(bool)
 
-	return cmdr.PsLogs(app, podID, lines, follow, container)
+	return cmdr.PsLogs(app, podID, lines, follow, container, previous)
 }
 
 func psExec(argv []string, cmdr cmd.Commander) error {
diff --git a/parser/ps_test.go b/parser/ps_test.go
index a5a0e700..0fcffea0 100644
--- a/parser/ps_test.go
+++ b/parser/ps_test.go
@@ -16,7 +16,7 @@ func (d FakeDryccCmd) PsList(string, int) error {
 	return errors.New("ps:list")
 }
 
-func (d FakeDryccCmd) PsLogs(string, string, int, bool, string) error {
+func (d FakeDryccCmd) PsLogs(string, string, int, bool, string, bool) error {
 	return errors.New("ps:logs")
 }
 
diff --git a/parser/pts.go b/parser/pts.go
index 4b79acbc..27b6811e 100644
--- a/parser/pts.go
+++ b/parser/pts.go
@@ -167,5 +167,5 @@ Options:
 	}
 
 	apps := safeGetString(args, "--app")
-	return cmdr.PtsScale(apps, args["<ptype>"].([]string))
+	return cmdr.PtsClean(apps, args["<ptype>"].([]string))
 }
