forked from toolshed/abra
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			app-new-fi
			...
			improve-li
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 7c9f3caacb | 
| @ -183,7 +183,7 @@ does not).`, | |||||||
| 		if err := internal.RunCmdRemote( | 		if err := internal.RunCmdRemote( | ||||||
| 			cl, | 			cl, | ||||||
| 			app, | 			app, | ||||||
| 			disableTTY, | 			requestTTY, | ||||||
| 			app.Recipe.AbraShPath, | 			app.Recipe.AbraShPath, | ||||||
| 			targetServiceName, cmdName, parsedCmdArgs, remoteUser); err != nil { | 			targetServiceName, cmdName, parsedCmdArgs, remoteUser); err != nil { | ||||||
| 			log.Fatal(err) | 			log.Fatal(err) | ||||||
| @ -238,7 +238,7 @@ func parseCmdArgs(args []string, isLocal bool) (bool, string) { | |||||||
| var ( | var ( | ||||||
| 	local      bool | 	local      bool | ||||||
| 	remoteUser string | 	remoteUser string | ||||||
| 	disableTTY bool | 	requestTTY bool | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| @ -259,11 +259,11 @@ func init() { | |||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	AppCmdCommand.Flags().BoolVarP( | 	AppCmdCommand.Flags().BoolVarP( | ||||||
| 		&disableTTY, | 		&requestTTY, | ||||||
| 		"tty", | 		"tty", | ||||||
| 		"T", | 		"T", | ||||||
| 		false, | 		false, | ||||||
| 		"disable remote TTY", | 		"request remote TTY", | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	AppCmdCommand.Flags().BoolVarP( | 	AppCmdCommand.Flags().BoolVarP( | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ var AppCpCommand = &cobra.Command{ | |||||||
|   abra app cp 1312.net myfile.txt app:/ |   abra app cp 1312.net myfile.txt app:/ | ||||||
|  |  | ||||||
|   # copy that file back to your current working directory locally |   # copy that file back to your current working directory locally | ||||||
|   abra app cp 1312.net app:/myfile.txt ./`, |   abra app cp 1312.net app:/myfile.txt`, | ||||||
| 	Args: cobra.ExactArgs(3), | 	Args: cobra.ExactArgs(3), | ||||||
| 	ValidArgsFunction: func( | 	ValidArgsFunction: func( | ||||||
| 		cmd *cobra.Command, | 		cmd *cobra.Command, | ||||||
|  | |||||||
| @ -142,14 +142,10 @@ Use "--status/-S" flag to query all servers for the live deployment status.`, | |||||||
| 					appStats.AutoUpdate = autoUpdate | 					appStats.AutoUpdate = autoUpdate | ||||||
|  |  | ||||||
| 					var newUpdates []string | 					var newUpdates []string | ||||||
| 					if version != "unknown" && chaosVersion == "unknown" { | 					if version != "unknown" { | ||||||
| 						if err := app.Recipe.EnsureExists(); err != nil { |  | ||||||
| 							log.Fatalf("unable to clone %s: %s", app.Name, err) |  | ||||||
| 						} |  | ||||||
|  |  | ||||||
| 						updates, err := app.Recipe.Tags() | 						updates, err := app.Recipe.Tags() | ||||||
| 						if err != nil { | 						if err != nil { | ||||||
| 							log.Fatalf("unable to retrieve tags for %s: %s", app.Name, err) | 							log.Fatal(err) | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
| 						parsedVersion, err := tagcmp.Parse(version) | 						parsedVersion, err := tagcmp.Parse(version) | ||||||
|  | |||||||
| @ -109,15 +109,6 @@ var AppNewCommand = &cobra.Command{ | |||||||
| 				if err := recipe.EnsureLatest(); err != nil { | 				if err := recipe.EnsureLatest(); err != nil { | ||||||
| 					log.Fatal(err) | 					log.Fatal(err) | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				if recipeVersion == "" { |  | ||||||
| 					head, err := recipe.Head() |  | ||||||
| 					if err != nil { |  | ||||||
| 						log.Fatalf("failed to retrieve latest commit for %s: %s", recipe.Name, err) |  | ||||||
| 					} |  | ||||||
|  |  | ||||||
| 					recipeVersion = formatter.SmallSHA(head.String()) |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -302,12 +293,6 @@ func ensureServerFlag() error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if len(servers) == 1 { |  | ||||||
| 		newAppServer = servers[0] |  | ||||||
| 		log.Infof("single server detected, choosing %s automatically", newAppServer) |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if newAppServer == "" && !internal.NoInput { | 	if newAppServer == "" && !internal.NoInput { | ||||||
| 		prompt := &survey.Select{ | 		prompt := &survey.Select{ | ||||||
| 			Message: "Select app server:", | 			Message: "Select app server:", | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ package app | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strings" |  | ||||||
|  |  | ||||||
| 	"coopcloud.tech/abra/cli/internal" | 	"coopcloud.tech/abra/cli/internal" | ||||||
| 	"coopcloud.tech/abra/pkg/app" | 	"coopcloud.tech/abra/pkg/app" | ||||||
| @ -214,7 +213,9 @@ beforehand. See "abra app backup" for more.`, | |||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if upgradeReleaseNotes == "" { | 		if upgradeReleaseNotes != "" && chosenUpgrade != "" { | ||||||
|  | 			fmt.Print(upgradeReleaseNotes) | ||||||
|  | 		} else { | ||||||
| 			upgradeWarnMessages = append( | 			upgradeWarnMessages = append( | ||||||
| 				upgradeWarnMessages, | 				upgradeWarnMessages, | ||||||
| 				fmt.Sprintf("no release notes available for %s", chosenUpgrade), | 				fmt.Sprintf("no release notes available for %s", chosenUpgrade), | ||||||
| @ -336,11 +337,6 @@ func getReleaseNotes( | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if note != "" { | 			if note != "" { | ||||||
| 				// NOTE(d1): trim any final newline on the end of the note itself before |  | ||||||
| 				//           we manually handle newlines (for multiple release notes and |  | ||||||
| 				//           ensuring space between the warning messages) |  | ||||||
| 				note = strings.TrimSuffix(note, "\n") |  | ||||||
|  |  | ||||||
| 				*upgradeReleaseNotes += fmt.Sprintf("%s\n", note) | 				*upgradeReleaseNotes += fmt.Sprintf("%s\n", note) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -24,7 +24,7 @@ import ( | |||||||
| func RunCmdRemote( | func RunCmdRemote( | ||||||
| 	cl *dockerClient.Client, | 	cl *dockerClient.Client, | ||||||
| 	app appPkg.App, | 	app appPkg.App, | ||||||
| 	disableTTY bool, | 	requestTTY bool, | ||||||
| 	abraSh, serviceName, cmdName, cmdArgs, remoteUser string) error { | 	abraSh, serviceName, cmdName, cmdArgs, remoteUser string) error { | ||||||
| 	filters := filters.NewArgs() | 	filters := filters.NewArgs() | ||||||
| 	filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), serviceName)) | 	filters.Add("name", fmt.Sprintf("^%s_%s", app.StackName(), serviceName)) | ||||||
| @ -84,10 +84,8 @@ func RunCmdRemote( | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	execCreateOpts.Cmd = cmd | 	execCreateOpts.Cmd = cmd | ||||||
|  | 	execCreateOpts.Tty = requestTTY | ||||||
| 	execCreateOpts.Tty = true | 	if !requestTTY { | ||||||
| 	if disableTTY { |  | ||||||
| 		execCreateOpts.Tty = false |  | ||||||
| 		log.Debugf("not requesting a remote TTY") | 		log.Debugf("not requesting a remote TTY") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
| @ -46,7 +46,7 @@ func DeployOverview( | |||||||
| 	app appPkg.App, | 	app appPkg.App, | ||||||
| 	deployedVersion string, | 	deployedVersion string, | ||||||
| 	toDeployVersion string, | 	toDeployVersion string, | ||||||
| 	releaseNotes string, | 	info string, | ||||||
| 	warnMessages []string, | 	warnMessages []string, | ||||||
| ) error { | ) error { | ||||||
| 	deployConfig := "compose.yml" | 	deployConfig := "compose.yml" | ||||||
| @ -85,8 +85,8 @@ func DeployOverview( | |||||||
|  |  | ||||||
| 	fmt.Println(overview) | 	fmt.Println(overview) | ||||||
|  |  | ||||||
| 	if releaseNotes != "" { | 	if info != "" { | ||||||
| 		fmt.Print(releaseNotes) | 		fmt.Println(info) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, msg := range warnMessages { | 	for _, msg := range warnMessages { | ||||||
|  | |||||||
| @ -32,12 +32,12 @@ func ValidateRecipe(args []string, cmdName string) recipe.Recipe { | |||||||
|  |  | ||||||
| 		localRecipes, err := recipe.GetRecipesLocal() | 		localRecipes, err := recipe.GetRecipesLocal() | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			log.Debugf("can't read local recipes: %s", err) | 			log.Fatal(err) | ||||||
| 		} else { | 		} | ||||||
| 			for _, recipeLocal := range localRecipes { |  | ||||||
| 				if _, ok := knownRecipes[recipeLocal]; !ok { | 		for _, recipeLocal := range localRecipes { | ||||||
| 					knownRecipes[recipeLocal] = true | 			if _, ok := knownRecipes[recipeLocal]; !ok { | ||||||
| 				} | 				knownRecipes[recipeLocal] = true | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,15 +1,11 @@ | |||||||
| package recipe | package recipe | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"os" |  | ||||||
|  |  | ||||||
| 	"coopcloud.tech/abra/cli/internal" | 	"coopcloud.tech/abra/cli/internal" | ||||||
| 	"coopcloud.tech/abra/pkg/autocomplete" | 	"coopcloud.tech/abra/pkg/autocomplete" | ||||||
| 	"coopcloud.tech/abra/pkg/formatter" | 	"coopcloud.tech/abra/pkg/formatter" | ||||||
| 	"coopcloud.tech/abra/pkg/log" | 	"coopcloud.tech/abra/pkg/log" | ||||||
| 	"coopcloud.tech/abra/pkg/recipe" | 	"coopcloud.tech/abra/pkg/recipe" | ||||||
| 	"github.com/go-git/go-git/v5" |  | ||||||
| 	gitCfg "github.com/go-git/go-git/v5/config" |  | ||||||
| 	"github.com/spf13/cobra" | 	"github.com/spf13/cobra" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @ -17,16 +13,7 @@ var RecipeFetchCommand = &cobra.Command{ | |||||||
| 	Use:     "fetch [recipe | --all] [flags]", | 	Use:     "fetch [recipe | --all] [flags]", | ||||||
| 	Aliases: []string{"f"}, | 	Aliases: []string{"f"}, | ||||||
| 	Short:   "Clone recipe(s) locally", | 	Short:   "Clone recipe(s) locally", | ||||||
| 	Long:    `Using "--force/-f" Git syncs an existing recipe. It does not erase unstaged changes.`, |  | ||||||
| 	Args:    cobra.RangeArgs(0, 1), | 	Args:    cobra.RangeArgs(0, 1), | ||||||
| 	Example: `  # fetch from recipe catalogue |  | ||||||
|   abra recipe fetch gitea |  | ||||||
|  |  | ||||||
|   # fetch from remote recipe |  | ||||||
|   abra recipe fetch git.foo.org/recipes/myrecipe |  | ||||||
|  |  | ||||||
|   # fetch with ssh remote for hacking |  | ||||||
|   abra recipe fetch gitea --ssh`, |  | ||||||
| 	ValidArgsFunction: func( | 	ValidArgsFunction: func( | ||||||
| 		cmd *cobra.Command, | 		cmd *cobra.Command, | ||||||
| 		args []string, | 		args []string, | ||||||
| @ -49,39 +36,10 @@ var RecipeFetchCommand = &cobra.Command{ | |||||||
|  |  | ||||||
| 		ensureCtx := internal.GetEnsureContext() | 		ensureCtx := internal.GetEnsureContext() | ||||||
| 		if recipeName != "" { | 		if recipeName != "" { | ||||||
| 			r := recipe.Get(recipeName) | 			r := internal.ValidateRecipe(args, cmd.Name()) | ||||||
| 			if _, err := os.Stat(r.Dir); !os.IsNotExist(err) { | 			if err := r.Ensure(ensureCtx); err != nil { | ||||||
| 				if !force { | 				log.Fatal(err) | ||||||
| 					log.Warnf("%s is already fetched", r.Name) |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			r = internal.ValidateRecipe(args, cmd.Name()) |  | ||||||
|  |  | ||||||
| 			if sshRemote { |  | ||||||
| 				if r.SSHURL == "" { |  | ||||||
| 					log.Warnf("unable to discover SSH remote for %s", r.Name) |  | ||||||
| 					return |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				repo, err := git.PlainOpen(r.Dir) |  | ||||||
| 				if err != nil { |  | ||||||
| 					log.Fatalf("unable to open %s: %s", r.Dir, err) |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if err = repo.DeleteRemote("origin"); err != nil { |  | ||||||
| 					log.Fatalf("unable to remove default remote in %s: %s", r.Dir, err) |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if _, err := repo.CreateRemote(&gitCfg.RemoteConfig{ |  | ||||||
| 					Name: "origin", |  | ||||||
| 					URLs: []string{r.SSHURL}, |  | ||||||
| 				}); err != nil { |  | ||||||
| 					log.Fatalf("unable to set SSH remote in %s: %s", r.Dir, err) |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			return | 			return | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @ -103,8 +61,6 @@ var RecipeFetchCommand = &cobra.Command{ | |||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	fetchAllRecipes bool | 	fetchAllRecipes bool | ||||||
| 	sshRemote       bool |  | ||||||
| 	force           bool |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| @ -115,20 +71,4 @@ func init() { | |||||||
| 		false, | 		false, | ||||||
| 		"fetch all recipes", | 		"fetch all recipes", | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	RecipeFetchCommand.Flags().BoolVarP( |  | ||||||
| 		&sshRemote, |  | ||||||
| 		"ssh", |  | ||||||
| 		"s", |  | ||||||
| 		false, |  | ||||||
| 		"automatically set ssh remote", |  | ||||||
| 	) |  | ||||||
|  |  | ||||||
| 	RecipeFetchCommand.Flags().BoolVarP( |  | ||||||
| 		&force, |  | ||||||
| 		"force", |  | ||||||
| 		"f", |  | ||||||
| 		false, |  | ||||||
| 		"force re-fetch", |  | ||||||
| 	) |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							| @ -19,6 +19,7 @@ require ( | |||||||
| 	github.com/google/go-cmp v0.7.0 | 	github.com/google/go-cmp v0.7.0 | ||||||
| 	github.com/moby/sys/signal v0.7.1 | 	github.com/moby/sys/signal v0.7.1 | ||||||
| 	github.com/moby/term v0.5.2 | 	github.com/moby/term v0.5.2 | ||||||
|  | 	github.com/muesli/reflow v0.3.0 | ||||||
| 	github.com/pkg/errors v0.9.1 | 	github.com/pkg/errors v0.9.1 | ||||||
| 	github.com/schollz/progressbar/v3 v3.18.0 | 	github.com/schollz/progressbar/v3 v3.18.0 | ||||||
| 	golang.org/x/term v0.30.0 | 	golang.org/x/term v0.30.0 | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							| @ -634,6 +634,7 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D | |||||||
| github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= | github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= | ||||||
| github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= | github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= | ||||||
| github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= | github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= | ||||||
|  | github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= | ||||||
| github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= | github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= | ||||||
| github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= | github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= | ||||||
| github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= | github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= | ||||||
| @ -693,6 +694,8 @@ github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D | |||||||
| github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= | github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= | ||||||
| github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= | github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= | ||||||
| github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= | github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= | ||||||
|  | github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= | ||||||
|  | github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= | ||||||
| github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= | github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= | ||||||
| github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= | github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= | ||||||
| github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= | ||||||
| @ -810,6 +813,7 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 | |||||||
| github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= | github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= | ||||||
| github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= | ||||||
| github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= | ||||||
|  | github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= | ||||||
| github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= | ||||||
| github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= | github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= | ||||||
| github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= | github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= | ||||||
|  | |||||||
| @ -1,10 +1,7 @@ | |||||||
| package git | package git | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/signal" |  | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"coopcloud.tech/abra/pkg/log" | 	"coopcloud.tech/abra/pkg/log" | ||||||
| @ -25,81 +22,46 @@ func gitCloneIgnoreErr(err error) bool { | |||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| // Clone runs a git clone which accounts for different default branches. This | // Clone runs a git clone which accounts for different default branches. | ||||||
| // function respects Ctrl+C (SIGINT) calls from the user, cancelling the |  | ||||||
| // context and deleting the (typically) half-baked clone of the repository. |  | ||||||
| // This avoids broken state for future clone / recipe ops. |  | ||||||
| func Clone(dir, url string) error { | func Clone(dir, url string) error { | ||||||
| 	ctx := context.Background() | 	if _, err := os.Stat(dir); os.IsNotExist(err) { | ||||||
| 	ctx, cancelCtx := context.WithCancel(ctx) | 		log.Debugf("git clone: %s", dir, url) | ||||||
|  |  | ||||||
| 	sigIntCh := make(chan os.Signal, 1) | 		_, err := git.PlainClone(dir, false, &git.CloneOptions{ | ||||||
| 	signal.Notify(sigIntCh, os.Interrupt) | 			URL:           url, | ||||||
| 	defer func() { | 			Tags:          git.AllTags, | ||||||
| 		signal.Stop(sigIntCh) | 			ReferenceName: plumbing.ReferenceName("refs/heads/main"), | ||||||
| 		cancelCtx() | 			SingleBranch:  true, | ||||||
| 	}() | 		}) | ||||||
|  |  | ||||||
| 	errCh := make(chan error) | 		if err != nil && gitCloneIgnoreErr(err) { | ||||||
|  | 			log.Debugf("git clone: %s cloned successfully", dir) | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 	go func() { | 		if err != nil { | ||||||
| 		if _, err := os.Stat(dir); os.IsNotExist(err) { | 			log.Debug("git clone: main branch failed, attempting master branch") | ||||||
| 			log.Debugf("git clone: %s", url) |  | ||||||
|  |  | ||||||
| 			_, err := git.PlainCloneContext(ctx, dir, false, &git.CloneOptions{ | 			_, err := git.PlainClone(dir, false, &git.CloneOptions{ | ||||||
| 				URL:           url, | 				URL:           url, | ||||||
| 				Tags:          git.AllTags, | 				Tags:          git.AllTags, | ||||||
| 				ReferenceName: plumbing.ReferenceName("refs/heads/main"), | 				ReferenceName: plumbing.ReferenceName("refs/heads/master"), | ||||||
| 				SingleBranch:  true, | 				SingleBranch:  true, | ||||||
| 			}) | 			}) | ||||||
|  |  | ||||||
| 			if err != nil && gitCloneIgnoreErr(err) { | 			if err != nil && gitCloneIgnoreErr(err) { | ||||||
| 				log.Debugf("git clone: %s cloned successfully", dir) | 				log.Debugf("git clone: %s cloned successfully", dir) | ||||||
| 				errCh <- nil | 				return nil | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			if err := ctx.Err(); err != nil { |  | ||||||
| 				errCh <- fmt.Errorf("git clone %s: cancelled due to interrupt", dir) |  | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				log.Debug("git clone: main branch failed, attempting master branch") | 				return err | ||||||
|  |  | ||||||
| 				_, err := git.PlainCloneContext(ctx, dir, false, &git.CloneOptions{ |  | ||||||
| 					URL:           url, |  | ||||||
| 					Tags:          git.AllTags, |  | ||||||
| 					ReferenceName: plumbing.ReferenceName("refs/heads/master"), |  | ||||||
| 					SingleBranch:  true, |  | ||||||
| 				}) |  | ||||||
|  |  | ||||||
| 				if err != nil && gitCloneIgnoreErr(err) { |  | ||||||
| 					log.Debugf("git clone: %s cloned successfully", dir) |  | ||||||
| 					errCh <- nil |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if err != nil { |  | ||||||
| 					errCh <- err |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			log.Debugf("git clone: %s cloned successfully", dir) |  | ||||||
| 		} else { |  | ||||||
| 			log.Debugf("git clone: %s already exists", dir) |  | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		errCh <- nil | 		log.Debugf("git clone: %s cloned successfully", dir) | ||||||
| 	}() | 	} else { | ||||||
|  | 		log.Debugf("git clone: %s already exists", dir) | ||||||
| 	select { |  | ||||||
| 	case <-sigIntCh: |  | ||||||
| 		cancelCtx() |  | ||||||
| 		fmt.Println() // NOTE(d1): newline after ^C |  | ||||||
| 		if err := os.RemoveAll(dir); err != nil { |  | ||||||
| 			return fmt.Errorf("unable to clean up git clone of %s: %s", dir, err) |  | ||||||
| 		} |  | ||||||
| 		return fmt.Errorf("git clone %s: cancelled due to interrupt", dir) |  | ||||||
| 	case err := <-errCh: |  | ||||||
| 		return err |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
|  | |||||||
| @ -1,48 +0,0 @@ | |||||||
| package git |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
| 	"path" |  | ||||||
| 	"syscall" |  | ||||||
| 	"testing" |  | ||||||
|  |  | ||||||
| 	"coopcloud.tech/abra/pkg/config" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| func TestClone(t *testing.T) { |  | ||||||
| 	dir := path.Join(config.RECIPES_DIR, "gitea") |  | ||||||
| 	os.RemoveAll(dir) |  | ||||||
|  |  | ||||||
| 	gitURL := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, "gitea") |  | ||||||
| 	if err := Clone(dir, gitURL); err != nil { |  | ||||||
| 		t.Fatalf("unable to git clone gitea: %s", err) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) { |  | ||||||
| 		t.Fatal("gitea repo was not cloned successfully") |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func TestCancelGitClone(t *testing.T) { |  | ||||||
| 	dir := path.Join(config.RECIPES_DIR, "gitea") |  | ||||||
| 	os.RemoveAll(dir) |  | ||||||
|  |  | ||||||
| 	go func() { |  | ||||||
| 		p, err := os.FindProcess(os.Getpid()) |  | ||||||
| 		if err != nil { |  | ||||||
| 			t.Fatalf("unable to find current process: %s", err) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		p.Signal(syscall.SIGINT) |  | ||||||
| 	}() |  | ||||||
|  |  | ||||||
| 	gitURL := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, "gitea") |  | ||||||
| 	if err := Clone(dir, gitURL); err == nil { |  | ||||||
| 		t.Fatal("cloning should have been interrupted") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if _, err := os.Stat(dir); err != nil && !os.IsNotExist(err) { |  | ||||||
| 		t.Fatal("recipe repo was not deleted") |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @ -1,8 +1,8 @@ | |||||||
| #!/usr/bin/env bash | #!/usr/bin/env bash | ||||||
|  |  | ||||||
| ABRA_VERSION="0.10.0-beta" | ABRA_VERSION="0.9.0-beta" | ||||||
| ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$ABRA_VERSION" | ABRA_RELEASE_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$ABRA_VERSION" | ||||||
| RC_VERSION="0.10.0-beta" | RC_VERSION="0.10.0-rc2-beta" | ||||||
| RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$RC_VERSION" | RC_VERSION_URL="https://git.coopcloud.tech/api/v1/repos/toolshed/abra/releases/tags/$RC_VERSION" | ||||||
|  |  | ||||||
| for arg in "$@"; do | for arg in "$@"; do | ||||||
|  | |||||||
| @ -401,6 +401,8 @@ teardown(){ | |||||||
|  |  | ||||||
| # bats test_tags=slow | # bats test_tags=slow | ||||||
| @test "ignore env version on new deploy" { | @test "ignore env version on new deploy" { | ||||||
|  |   tagHash=$(_get_tag_hash "0.1.0+1.20.0") | ||||||
|  |  | ||||||
|   run $ABRA app deploy "$TEST_APP_DOMAIN" "0.1.0+1.20.0" \ |   run $ABRA app deploy "$TEST_APP_DOMAIN" "0.1.0+1.20.0" \ | ||||||
|     --no-input --no-converge-checks |     --no-input --no-converge-checks | ||||||
|   assert_success |   assert_success | ||||||
|  | |||||||
| @ -8,7 +8,6 @@ setup_file(){ | |||||||
| } | } | ||||||
|  |  | ||||||
| teardown_file(){ | teardown_file(){ | ||||||
|   _undeploy_app |  | ||||||
|   _rm_app |   _rm_app | ||||||
|   _rm_server |   _rm_server | ||||||
| } | } | ||||||
| @ -19,7 +18,6 @@ setup(){ | |||||||
| } | } | ||||||
|  |  | ||||||
| teardown(){ | teardown(){ | ||||||
|   _reset_recipe |  | ||||||
|   _undeploy_app |   _undeploy_app | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -89,10 +87,6 @@ teardown(){ | |||||||
|   assert_success |   assert_success | ||||||
|   refute_output --partial "$TEST_RECIPE" |   refute_output --partial "$TEST_RECIPE" | ||||||
|   assert_output --partial "foo-recipe" |   assert_output --partial "foo-recipe" | ||||||
|  |  | ||||||
|   run rm -rf "$ABRA_DIR/servers/foo.com" |  | ||||||
|   assert_success |  | ||||||
|   assert_not_exists "$ABRA_DIR/servers/foo.com" |  | ||||||
| } | } | ||||||
|  |  | ||||||
| @test "output is machine readable" { | @test "output is machine readable" { | ||||||
| @ -104,36 +98,3 @@ teardown(){ | |||||||
|  |  | ||||||
|   assert_output --partial "$expectedOutput" |   assert_output --partial "$expectedOutput" | ||||||
| } | } | ||||||
|  |  | ||||||
| # bats test_tags=slow |  | ||||||
| @test "list with status fetches recipe" { |  | ||||||
|   _deploy_app |  | ||||||
|  |  | ||||||
|   run $ABRA app ls --status |  | ||||||
|   assert_success |  | ||||||
|  |  | ||||||
|   run rm -rf "$ABRA_DIR/recipes/$TEST_RECIPE" |  | ||||||
|   assert_success |  | ||||||
|  |  | ||||||
|   run $ABRA app ls --status |  | ||||||
|   assert_success |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # bats test_tags=slow |  | ||||||
| @test "list with chaos version" { |  | ||||||
|   run bash -c "echo foo >> $ABRA_DIR/recipes/$TEST_RECIPE/foo" |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/$TEST_RECIPE/foo" |  | ||||||
|  |  | ||||||
|   run $ABRA app deploy "$TEST_APP_DOMAIN" \ |  | ||||||
|     --no-input --no-converge-checks --chaos |  | ||||||
|   assert_success |  | ||||||
|  |  | ||||||
|   run $ABRA app ls --status |  | ||||||
|   assert_success |  | ||||||
|   assert_output --partial "+U" |  | ||||||
|  |  | ||||||
|   run rm -rf "$ABRA_DIR/servers/foo.com" |  | ||||||
|   assert_success |  | ||||||
|   assert_not_exists "$ABRA_DIR/servers/foo.com" |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -250,10 +250,3 @@ teardown(){ | |||||||
|     "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" |     "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" | ||||||
|   assert_success |   assert_success | ||||||
| } | } | ||||||
|  |  | ||||||
| @test "automatically select single server" { |  | ||||||
|   # NOTE(d1): no --no-input required, single server available |  | ||||||
|   run $ABRA app new "$TEST_RECIPE" --domain "$TEST_APP_DOMAIN" |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$TEST_APP_DOMAIN.env" |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -25,3 +25,13 @@ teardown(){ | |||||||
|   run "$HOME/.local/bin/abra" -v |   run "$HOME/.local/bin/abra" -v | ||||||
|   assert_output --partial 'beta' |   assert_output --partial 'beta' | ||||||
| } | } | ||||||
|  |  | ||||||
|  | # bats test_tags=slow | ||||||
|  | @test "install release candidate from script" { | ||||||
|  |   run bash -c 'curl https://install.abra.coopcloud.tech | bash -s -- --rc' | ||||||
|  |   assert_success | ||||||
|  |  | ||||||
|  |   assert_exists "$HOME/.local/bin/abra" | ||||||
|  |   run "$HOME/.local/bin/abra" -v | ||||||
|  |   assert_output --partial '-rc' | ||||||
|  | } | ||||||
|  | |||||||
| @ -5,16 +5,6 @@ setup() { | |||||||
|   _common_setup |   _common_setup | ||||||
| } | } | ||||||
|  |  | ||||||
| teardown(){ |  | ||||||
|   run rm -rf "$ABRA_DIR/recipes/matrix-synapse" |  | ||||||
|   assert_success |  | ||||||
|   assert_not_exists "$ABRA_DIR/recipes/$TEST_RECIPE" |  | ||||||
|  |  | ||||||
|   run rm -rf "$ABRA_DIR/recipes/git_coopcloud_tech_coop-cloud_matrix-synapse" |  | ||||||
|   assert_success |  | ||||||
|   assert_not_exists "$ABRA_DIR/recipes/git_coopcloud_tech_coop-cloud_matrix-synapse" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| # bats test_tags=slow | # bats test_tags=slow | ||||||
| @test "recipe fetch all" { | @test "recipe fetch all" { | ||||||
|   run rm -rf "$ABRA_DIR/recipes/matrix-synapse" |   run rm -rf "$ABRA_DIR/recipes/matrix-synapse" | ||||||
| @ -45,81 +35,3 @@ teardown(){ | |||||||
|   run $ABRA recipe fetch matrix-synapse --all |   run $ABRA recipe fetch matrix-synapse --all | ||||||
|   assert_failure |   assert_failure | ||||||
| } | } | ||||||
|  |  | ||||||
| @test "do not refetch without --force" { |  | ||||||
|   run $ABRA recipe fetch matrix-synapse |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse" |  | ||||||
|  |  | ||||||
|   run $ABRA recipe fetch matrix-synapse |  | ||||||
|   assert_output --partial "already fetched" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @test "refetch with --force" { |  | ||||||
|   run $ABRA recipe fetch matrix-synapse |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse" |  | ||||||
|  |  | ||||||
|   run $ABRA recipe fetch matrix-synapse --force |  | ||||||
|   assert_success |  | ||||||
|   refute_output --partial "already fetched" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @test "refetch with --force does not erase unstaged changes" { |  | ||||||
|   run $ABRA recipe fetch matrix-synapse |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse" |  | ||||||
|  |  | ||||||
|   run bash -c "echo foo >> $ABRA_DIR/recipes/matrix-synapse/foo" |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse/foo" |  | ||||||
|  |  | ||||||
|   run $ABRA recipe fetch matrix-synapse --force |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse" |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse/foo" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @test "fetch with --ssh" { |  | ||||||
|   run $ABRA recipe fetch matrix-synapse --ssh |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse" |  | ||||||
|  |  | ||||||
|   run git -C "$ABRA_DIR/recipes/matrix-synapse" remote -v |  | ||||||
|   assert_success |  | ||||||
|   assert_output --partial "ssh://" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @test "re-fetch with --ssh/--force" { |  | ||||||
|   run $ABRA recipe fetch matrix-synapse |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse" |  | ||||||
|  |  | ||||||
|   run git -C "$ABRA_DIR/recipes/matrix-synapse" remote -v |  | ||||||
|   assert_success |  | ||||||
|   assert_output --partial "https://" |  | ||||||
|  |  | ||||||
|   run $ABRA recipe fetch matrix-synapse --ssh --force |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/matrix-synapse" |  | ||||||
|  |  | ||||||
|   run git -C "$ABRA_DIR/recipes/matrix-synapse" remote -v |  | ||||||
|   assert_success |  | ||||||
|   assert_output --partial "ssh://" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @test "fetch remote recipe" { |  | ||||||
|   run $ABRA recipe fetch git.coopcloud.tech/coop-cloud/matrix-synapse |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/git_coopcloud_tech_coop-cloud_matrix-synapse" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| @test "remote recipe do not refetch without --force" { |  | ||||||
|   run $ABRA recipe fetch git.coopcloud.tech/coop-cloud/matrix-synapse |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/git_coopcloud_tech_coop-cloud_matrix-synapse" |  | ||||||
|  |  | ||||||
|   run $ABRA recipe fetch git.coopcloud.tech/coop-cloud/matrix-synapse |  | ||||||
|   assert_success |  | ||||||
|   assert_output --partial "already fetched" |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -68,27 +68,3 @@ teardown(){ | |||||||
|   assert_output --partial 'fooUser' |   assert_output --partial 'fooUser' | ||||||
|   assert_output --partial 'foo@example.com' |   assert_output --partial 'foo@example.com' | ||||||
| } | } | ||||||
|  |  | ||||||
| # bats test_tags=slow |  | ||||||
| @test "recipe new, app new, no releases, latest commit" { |  | ||||||
|   recipeName="foobar" |  | ||||||
|  |  | ||||||
|   run $ABRA recipe new "$recipeName" |  | ||||||
|   assert_success |  | ||||||
|   assert_exists "$ABRA_DIR/recipes/$recipeName" |  | ||||||
|  |  | ||||||
|   currentHash=$(git -C "$ABRA_DIR/recipes/$recipeName" show -s --format="%H") |  | ||||||
|   domain="$recipeName.$TEST_APP_SERVER"  |  | ||||||
|  |  | ||||||
|   run $ABRA app new "$recipeName" \ |  | ||||||
|     --no-input \ |  | ||||||
|     --server "$TEST_SERVER" \ |  | ||||||
|     --domain "$domain" |  | ||||||
|   assert_success |  | ||||||
|   assert_output --partial "version: ${currentHash:0:8}" |  | ||||||
|   assert_exists "$ABRA_DIR/servers/$TEST_SERVER/$domain.env" |  | ||||||
|  |  | ||||||
|   run grep -q "TYPE=$recipeName:${currentHash:0:8}" \ |  | ||||||
|     "$ABRA_DIR/servers/$TEST_SERVER/$domain.env" |  | ||||||
|   assert_success |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -26,3 +26,14 @@ teardown(){ | |||||||
|   run "$HOME/.local/bin/abra" -v |   run "$HOME/.local/bin/abra" -v | ||||||
|   assert_output --partial 'beta' |   assert_output --partial 'beta' | ||||||
| } | } | ||||||
|  |  | ||||||
|  | # bats test_tags=slow | ||||||
|  | @test "abra upgrade release candidate" { | ||||||
|  |   run $ABRA upgrade --rc | ||||||
|  |   assert_success | ||||||
|  |   assert_output --partial 'Public interest infrastructure' | ||||||
|  |  | ||||||
|  |   assert_exists "$HOME/.local/bin/abra" | ||||||
|  |   run "$HOME/.local/bin/abra" -v | ||||||
|  |   assert_output --partial '-rc' | ||||||
|  | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user