fix: unstaged changes handling

See toolshed/organising#651
This commit is contained in:
2024-12-31 11:19:03 +01:00
parent bfed51a69c
commit 5975be6870
26 changed files with 622 additions and 56 deletions

View File

@ -206,10 +206,15 @@ Please note, "upgrade"/"rollback" do not support chaos operations.`,
log.Fatal(err)
}
toDeployChaosVersionLabel := toDeployChaosVersion
if app.Recipe.Dirty {
toDeployChaosVersionLabel = fmt.Sprintf("%s%s", toDeployChaosVersion, config.DIRTY_DEFAULT)
}
appPkg.ExposeAllEnv(stackName, compose, app.Env)
appPkg.SetRecipeLabel(compose, stackName, app.Recipe.Name)
appPkg.SetChaosLabel(compose, stackName, internal.Chaos)
appPkg.SetChaosVersionLabel(compose, stackName, toDeployChaosVersion)
appPkg.SetChaosVersionLabel(compose, stackName, toDeployChaosVersionLabel)
appPkg.SetUpdateLabel(compose, stackName, app.Env)
envVars, err := appPkg.CheckEnv(app)
@ -275,7 +280,6 @@ Please note, "upgrade"/"rollback" do not support chaos operations.`,
if toDeployChaosVersion != config.CHAOS_DEFAULT {
app.Recipe.Version = toDeployChaosVersion
}
log.Debugf("choosing %s as version to save to env file", app.Recipe.Version)
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
log.Fatalf("writing new recipe version in env file: %s", err)
}

139
cli/app/labels.go Normal file
View File

@ -0,0 +1,139 @@
package app
import (
"context"
"fmt"
"sort"
"coopcloud.tech/abra/cli/internal"
"coopcloud.tech/abra/pkg/autocomplete"
"coopcloud.tech/abra/pkg/client"
"coopcloud.tech/abra/pkg/formatter"
"coopcloud.tech/abra/pkg/log"
"coopcloud.tech/abra/pkg/upstream/convert"
composetypes "github.com/docker/cli/cli/compose/types"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters"
dockerClient "github.com/docker/docker/client"
"github.com/spf13/cobra"
)
var AppLabelsCommand = &cobra.Command{
Use: "labels <app> [flags]",
Aliases: []string{"lb"},
Short: "Show deployment labels",
Long: "Both local recipe and live deployment labels are shown.",
Example: " abra app labels 1312.net",
Args: cobra.ExactArgs(1),
ValidArgsFunction: func(
cmd *cobra.Command,
args []string,
toComplete string) ([]string, cobra.ShellCompDirective) {
return autocomplete.AppNameComplete()
},
Run: func(cmd *cobra.Command, args []string) {
app := internal.ValidateApp(args)
if err := app.Recipe.Ensure(internal.Chaos, internal.Offline); err != nil {
log.Fatal(err)
}
cl, err := client.New(app.Server)
if err != nil {
log.Fatal(err)
}
remoteLabels, err := getLabels(cl, app.StackName())
if err != nil {
log.Fatal(err)
}
rows := [][]string{
{"DEPLOYED LABELS", "---"},
}
remoteLabelKeys := make([]string, 0, len(remoteLabels))
for k := range remoteLabels {
remoteLabelKeys = append(remoteLabelKeys, k)
}
sort.Strings(remoteLabelKeys)
for _, k := range remoteLabelKeys {
rows = append(rows, []string{
k,
remoteLabels[k],
})
}
if len(remoteLabelKeys) == 0 {
rows = append(rows, []string{"unknown"})
}
rows = append(rows, []string{"RECIPE LABELS", "---"})
config, err := app.Recipe.GetComposeConfig(app.Env)
if err != nil {
log.Fatal(err)
}
var localLabelKeys []string
var appServiceConfig composetypes.ServiceConfig
for _, service := range config.Services {
if service.Name == "app" {
appServiceConfig = service
for k := range service.Deploy.Labels {
localLabelKeys = append(localLabelKeys, k)
}
}
}
sort.Strings(localLabelKeys)
for _, k := range localLabelKeys {
rows = append(rows, []string{
k,
appServiceConfig.Deploy.Labels[k],
})
}
overview := formatter.CreateOverview("LABELS OVERVIEW", rows)
fmt.Println(overview)
},
}
// getLabels reads docker labels from running services in the format of "coop-cloud.${STACK_NAME}.${LABEL}".
func getLabels(cl *dockerClient.Client, stackName string) (map[string]string, error) {
labels := make(map[string]string)
filter := filters.NewArgs()
filter.Add("label", fmt.Sprintf("%s=%s", convert.LabelNamespace, stackName))
services, err := cl.ServiceList(context.Background(), types.ServiceListOptions{Filters: filter})
if err != nil {
return labels, err
}
for _, service := range services {
if service.Spec.Name != fmt.Sprintf("%s_app", stackName) {
continue
}
for k, v := range service.Spec.Labels {
labels[k] = v
}
}
return labels, nil
}
func init() {
AppLabelsCommand.Flags().BoolVarP(
&internal.Chaos,
"chaos",
"C",
false,
"ignore uncommitted recipes changes",
)
}

View File

@ -201,8 +201,8 @@ var AppNewCommand = &cobra.Command{
log.Warnf(
"secrets are %s shown again, please save them %s",
formatter.BoldStyle.Render("NOT"),
formatter.BoldStyle.Render("NOW"),
formatter.BoldUnderlineStyle.Render("NOT"),
formatter.BoldUnderlineStyle.Render("NOW"),
)
}
@ -211,7 +211,6 @@ var AppNewCommand = &cobra.Command{
log.Fatal(err)
}
log.Debugf("choosing %s as version to save to env file", recipeVersion)
if err := app.WriteRecipeVersion(recipeVersion, false); err != nil {
log.Fatalf("writing new recipe version in env file: %s", err)
}

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"strings"
"coopcloud.tech/abra/cli/internal"
appPkg "coopcloud.tech/abra/pkg/app"
@ -24,7 +25,7 @@ import (
var AppPsCommand = &cobra.Command{
Use: "ps <app> [flags]",
Aliases: []string{"p"},
Short: "Check app status",
Short: "Check app deployment status",
Args: cobra.ExactArgs(1),
ValidArgsFunction: func(
cmd *cobra.Command,
@ -57,9 +58,11 @@ var AppPsCommand = &cobra.Command{
statuses, err := appPkg.GetAppStatuses([]appPkg.App{app}, true)
if statusMeta, ok := statuses[app.StackName()]; ok {
if isChaos, exists := statusMeta["chaos"]; exists && isChaos == "true" {
chaosVersion, err = app.Recipe.ChaosVersion()
if err != nil {
log.Fatal(err)
if cVersion, exists := statusMeta["chaosVersion"]; exists {
chaosVersion = cVersion
if strings.HasSuffix(chaosVersion, config.DIRTY_DEFAULT) {
chaosVersion = formatter.BoldDirtyDefault(chaosVersion)
}
}
}
}

View File

@ -235,7 +235,6 @@ beforehand.`,
}
app.Recipe.Version = chosenDowngrade
log.Debugf("choosing %s as version to save to env file", app.Recipe.Version)
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
log.Fatalf("writing new recipe version in env file: %s", err)
}

View File

@ -80,7 +80,6 @@ Passing "--prune/-p" does not remove those volumes.`,
}
}
log.Debugf("choosing %s as version to save to env file", deployMeta.Version)
if err := app.WriteRecipeVersion(deployMeta.Version, false); err != nil {
log.Fatalf("writing undeployed recipe version in env file: %s", err)
}

View File

@ -182,7 +182,7 @@ beforehand.`,
if err != nil {
log.Fatal(err)
}
for _, version := range versions {
for _, version := range internal.SortVersionsDesc(versions) {
parsedVersion, err := tagcmp.Parse(version)
if err != nil {
log.Fatal(err)
@ -289,7 +289,6 @@ beforehand.`,
}
app.Recipe.Version = chosenUpgrade
log.Debugf("choosing %s as version to save to env file", app.Recipe.Version)
if err := app.WriteRecipeVersion(app.Recipe.Version, false); err != nil {
log.Fatalf("writing new recipe version in env file: %s", err)
}

View File

@ -61,18 +61,22 @@ func NewVersionOverview(
domain = config.NO_DOMAIN_DEFAULT
}
upperKind := strings.ToUpper(kind)
rows := [][]string{
{"APP", domain},
{"RECIPE", app.Recipe.Name},
{"SERVER", server},
{"DEPLOYED", deployedVersion},
{"CURRENT CHAOS ", deployedChaosVersion},
{fmt.Sprintf("TO %s", strings.ToUpper(kind)), toDeployVersion},
{"CONFIG", deployConfig},
{"CURRENT DEPLOYMENT", "---"},
{"VERSION", deployedVersion},
{"CHAOS ", deployedChaosVersion},
{upperKind, "---"},
{"VERSION", toDeployVersion},
}
overview := formatter.CreateOverview(
fmt.Sprintf("%s OVERVIEW", strings.ToUpper(kind)),
fmt.Sprintf("%s OVERVIEW", upperKind),
rows,
)
@ -131,15 +135,25 @@ func DeployOverview(
domain = config.NO_DOMAIN_DEFAULT
}
deployedChaosVersion = formatter.BoldDirtyDefault(deployedChaosVersion)
if app.Recipe.Dirty {
toDeployChaosVersion = formatter.BoldDirtyDefault(toDeployChaosVersion)
}
rows := [][]string{
{"APP", domain},
{"RECIPE", app.Recipe.Name},
{"SERVER", server},
{"DEPLOYED", deployedVersion},
{"CURRENT CHAOS ", deployedChaosVersion},
{"TO DEPLOY", toDeployVersion},
{"NEW CHAOS", toDeployChaosVersion},
{"CONFIG", deployConfig},
{"CURRENT DEPLOYMENT", "---"},
{"VERSION", deployedVersion},
{"CHAOS", deployedChaosVersion},
{"NEW DEPLOYMENT", "---"},
{"VERSION", toDeployVersion},
{"CHAOS", toDeployChaosVersion},
}
overview := formatter.CreateOverview("DEPLOY OVERVIEW", rows)
@ -187,13 +201,18 @@ func UndeployOverview(
domain = config.NO_DOMAIN_DEFAULT
}
if app.Recipe.Dirty {
chaosVersion = formatter.BoldDirtyDefault(chaosVersion)
}
rows := [][]string{
{"APP", domain},
{"RECIPE", app.Recipe.Name},
{"SERVER", server},
{"CONFIG", deployConfig},
{"CURRENT DEPLOYMENT", "---"},
{"DEPLOYED", version},
{"CHAOS", chaosVersion},
{"CONFIG", deployConfig},
}
overview := formatter.CreateOverview("UNDEPLOY OVERVIEW", rows)

View File

@ -0,0 +1,17 @@
package internal
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSortVersionsDesc(t *testing.T) {
versions := SortVersionsDesc([]string{
"0.2.3+1.2.2",
"1.0.0+2.2.2",
})
assert.Equal(t, "1.0.0+2.2.2", versions[0])
assert.Equal(t, "0.2.3+1.2.2", versions[1])
}

View File

@ -187,6 +187,7 @@ func Run(version, commit string) {
app.AppUndeployCommand,
app.AppUpgradeCommand,
app.AppVolumeCommand,
app.AppLabelsCommand,
)
if err := rootCmd.Execute(); err != nil {