Compare commits

..
Author SHA1 Message Date
renovate-bot 11e2f34d0e chore(deps): update module github.com/charmbracelet/bubbletea to v2
renovate/artifacts Artifact file update failure
continuous-integration/drone/push Build is failing
2026-09-08 17:03:42 +00:00
12 changed files with 38 additions and 131 deletions
+2 -2
View File
@@ -6,7 +6,7 @@ require (
coopcloud.tech/tagcmp v0.0.0-20260515102403-c26951b55977
git.coopcloud.tech/toolshed/godotenv v1.5.2-0.20250103171850-4d0ca41daa5c
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/charmbracelet/bubbletea v1.3.10
github.com/charmbracelet/bubbletea/v2 v2.0.9
github.com/charmbracelet/lipgloss v1.1.0
github.com/charmbracelet/log v1.0.0
github.com/distribution/reference v0.6.0
@@ -20,7 +20,7 @@ require (
github.com/moby/term v0.5.2
github.com/pkg/errors v0.9.1
github.com/schollz/progressbar/v3 v3.19.1
golang.org/x/term v0.46.0
golang.org/x/term v0.45.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools/v3 v3.5.2
)
+2 -2
View File
@@ -1143,8 +1143,8 @@ golang.org/x/sys v0.48.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.46.0 h1:3+OXuTbaKDgwk8jTi3aSLHRlmWqHEUDUtxnbFigO4YE=
golang.org/x/term v0.46.0/go.mod h1:+K02xbkittuwc0Am4abfA3Fc+XRGXkvBXNO88NCXPoc=
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+9 -51
View File
@@ -10,58 +10,16 @@ import (
composetypes "github.com/docker/cli/cli/compose/types"
)
// setLabel writes a label to both the service object and the task template of
// every service of the stack.
//
// The task template labels end up on the containers themselves and are therefore
// visible to container-level tooling (cAdvisor, log shippers, docker events),
// which cannot read service labels at all.
//
// The service object is written as well because it is free: changing
// Spec.Labels updates the service without recreating any task and because
// `docker service ls --filter label=...` matches service labels only.
func setLabel(compose *composetypes.Config, key string, value string) {
for i := range compose.Services {
if compose.Services[i].Deploy.Labels == nil {
compose.Services[i].Deploy.Labels = composetypes.Labels{}
}
if compose.Services[i].Labels == nil {
compose.Services[i].Labels = composetypes.Labels{}
}
compose.Services[i].Deploy.Labels[key] = value
compose.Services[i].Labels[key] = value
}
}
// setAppLabel writes a label to the service object of the app service only.
func setAppLabel(compose *composetypes.Config, key string, value string) {
for i := range compose.Services {
if compose.Services[i].Name != "app" {
continue
}
if compose.Services[i].Deploy.Labels == nil {
compose.Services[i].Deploy.Labels = composetypes.Labels{}
}
compose.Services[i].Deploy.Labels[key] = value
}
}
// SetRecipeLabel adds two distinct labels to signal which recipe is connected
// to the deployed app:
// - 'coop-cloud.${STACK_NAME}.recipe=${RECIPE}' on the app service object,
// unchanged, as read back by GetLabel
// - 'coop-cloud.recipe=${RECIPE}' on every service of the stack, so that
// tooling can attribute any container to a recipe without knowing the
// stack name up front
// SetRecipeLabel adds the label 'coop-cloud.${STACK_NAME}.recipe=${RECIPE}' to the app container
// to signal which recipe is connected to the deployed app
func SetRecipeLabel(compose *composetypes.Config, stackName string, recipe string) {
log.Debug(i18n.G("set recipe labels 'coop-cloud.%s.recipe' and 'coop-cloud.recipe' to %s for %s", stackName, recipe, stackName))
setAppLabel(compose, fmt.Sprintf("coop-cloud.%s.recipe", stackName), recipe)
setLabel(compose, "coop-cloud.recipe", recipe)
for _, service := range compose.Services {
if service.Name == "app" {
log.Debug(i18n.G("set recipe label 'coop-cloud.%s.recipe' to %s for %s", stackName, recipe, stackName))
labelKey := fmt.Sprintf("coop-cloud.%s.recipe", stackName)
service.Deploy.Labels[labelKey] = recipe
}
}
}
// SetChaosLabel adds the label 'coop-cloud.${STACK_NAME}.chaos=true/false' to the app container
-41
View File
@@ -8,7 +8,6 @@ import (
testPkg "coopcloud.tech/abra/pkg/test"
stack "coopcloud.tech/abra/pkg/upstream/stack"
composetypes "github.com/docker/cli/cli/compose/types"
"github.com/stretchr/testify/assert"
)
@@ -62,43 +61,3 @@ func TestGetTimeoutFromLabel(t *testing.T) {
assert.Equal(t, timeout, test.expectedTimeout)
}
}
func TestSetRecipeLabel(t *testing.T) {
// the app service brings labels along on both levels, the db service
// has none at all, so the pre-existing and the nil map case are covered
compose := &composetypes.Config{
Services: []composetypes.ServiceConfig{
{
Name: "app",
Labels: composetypes.Labels{"example.container.label": "keep me"},
Deploy: composetypes.DeployConfig{
Labels: composetypes.Labels{"coop-cloud.backupbot.enabled": "true"},
},
},
{Name: "db"},
},
}
appPkg.SetRecipeLabel(compose, "test_example_com", "test-recipe")
services := make(map[string]composetypes.ServiceConfig)
for _, service := range compose.Services {
services[service.Name] = service
}
// the stack scoped label stays on the app service object only
assert.Equal(t, "test-recipe",
services["app"].Deploy.Labels["coop-cloud.test_example_com.recipe"])
assert.NotContains(t, services["db"].Deploy.Labels,
"coop-cloud.test_example_com.recipe")
// the static label reaches every container of the stack
for name, service := range services {
assert.Equal(t, "test-recipe", service.Labels["coop-cloud.recipe"], name)
assert.Equal(t, "test-recipe", service.Deploy.Labels["coop-cloud.recipe"], name)
}
// labels the recipe brought along are left alone
assert.Equal(t, "keep me", services["app"].Labels["example.container.label"])
assert.Equal(t, "true", services["app"].Deploy.Labels["coop-cloud.backupbot.enabled"])
}
+9 -9
View File
@@ -3047,7 +3047,7 @@ msgstr ""
msgid "generated secrets %s shown again, please take note of them %s"
msgstr ""
#: ./pkg/app/compose.go:105
#: ./pkg/app/compose.go:63
#, c-format
msgid "get label '%s'"
msgstr ""
@@ -3695,7 +3695,7 @@ msgstr ""
msgid "no %s exists, skipping reading gitignore paths"
msgstr ""
#: ./pkg/app/compose.go:111
#: ./pkg/app/compose.go:69
#, c-format
msgid "no %s label found for %s"
msgstr ""
@@ -4746,24 +4746,24 @@ msgstr ""
msgid "set 'main' as the default branch"
msgstr ""
#: ./pkg/app/compose.go:72
#: ./pkg/app/compose.go:30
#, c-format
msgid "set label 'coop-cloud.%s.chaos' to %v for %s"
msgstr ""
#: ./pkg/app/compose.go:83
#: ./pkg/app/compose.go:41
#, c-format
msgid "set label 'coop-cloud.%s.chaos-version' to %v for %s"
msgstr ""
#: ./pkg/app/compose.go:93
#: ./pkg/app/compose.go:51
#, c-format
msgid "set label 'coop-cloud.%s.version' to %v for %s"
msgstr ""
#: ./pkg/app/compose.go:61
#: ./pkg/app/compose.go:18
#, c-format
msgid "set recipe labels 'coop-cloud.%s.recipe' and 'coop-cloud.recipe' to %s for %s"
msgid "set recipe label 'coop-cloud.%s.recipe' to %s for %s"
msgstr ""
#: ./pkg/git/init.go:60
@@ -5064,7 +5064,7 @@ msgstr ""
msgid "timed out on undeploy (timeout=%v sec)"
msgstr ""
#: ./pkg/app/compose.go:122
#: ./pkg/app/compose.go:80
#, c-format
msgid "timeout label: %s"
msgstr ""
@@ -5172,7 +5172,7 @@ msgstr ""
msgid "unable to continue, input required for initial version"
msgstr ""
#: ./pkg/app/compose.go:127
#: ./pkg/app/compose.go:85
#, c-format
msgid "unable to convert timeout label %s to int: %s"
msgstr ""
+1 -1
View File
@@ -3,7 +3,7 @@ version: "3.8"
services:
app:
image: nginx:1.31.6
image: nginx:1.31.5
secrets:
- test_pass_one
- test_pass_two
+1 -1
View File
@@ -3,7 +3,7 @@ version: "3.8"
services:
app:
image: nginx:1.31.6
image: nginx:1.31.5
networks:
- proxy
deploy:
+3 -3
View File
@@ -3,16 +3,16 @@ kind: pipeline
name: coopcloud.tech/tagcmp
steps:
- name: gofmt
image: golang:1.27
image: golang:1.26
commands:
- test -z "$(gofmt -l .)"
- name: go build
image: golang:1.27
image: golang:1.26
commands:
- go build -v .
- name: go test
image: golang:1.27
image: golang:1.26
commands:
- go test . -cover
+1 -1
View File
@@ -1,4 +1,4 @@
FROM golang:1.27@sha256:512690a5660563b57d37ecc31129e7f136e831db2aed24a1dbeb8ad7380dc0fa
FROM golang:1.25@sha256:31c1e53dfc1cc2d269deec9c83f58729fa3c53dc9a576f6426109d1e319e9e9a
ENV GOOS=linux
ENV GOARCH=arm
+1 -1
View File
@@ -1,4 +1,4 @@
FROM golang:1.27@sha256:512690a5660563b57d37ecc31129e7f136e831db2aed24a1dbeb8ad7380dc0fa
FROM golang:1.25@sha256:31c1e53dfc1cc2d269deec9c83f58729fa3c53dc9a576f6426109d1e319e9e9a
ENV GOOS=linux
ENV GOARCH=arm64
+7 -17
View File
@@ -106,9 +106,6 @@ type Terminal struct {
// a read. It aliases into inBuf.
remainder []byte
inBuf [256]byte
// readErr is an error returned by a read that also returned data. It is
// reported after all of that data has been processed.
readErr error
// History records and retrieves lines of input read by [ReadLine] which
// a user can retrieve and navigate using the up and down arrow keys.
@@ -791,11 +788,7 @@ func (t *Terminal) ReadPassword(prompt string) (line string, err error) {
return
}
// ReadLine returns a line of input from the terminal, excluding the
// trailing newline. It may return partial data along with an error.
// An [io.EOF] error indicates the end of the stream. For other errors,
// such as [ErrPasteIndicator] in bracketed paste mode, a subsequent
// call may return more data.
// ReadLine returns a line of input from the terminal.
func (t *Terminal) ReadLine() (line string, err error) {
t.lock.Lock()
defer t.lock.Unlock()
@@ -870,24 +863,21 @@ func (t *Terminal) readLine() (line string, err error) {
}
return
}
if t.readErr != nil {
err = t.readErr
t.readErr = nil
return
}
// t.remainder is a slice at the beginning of t.inBuf
// containing a partial key sequence
readBuf := t.inBuf[len(t.remainder):]
var n int
t.lock.Unlock()
n, readErr := t.c.Read(readBuf)
n, err = t.c.Read(readBuf)
t.lock.Lock()
t.remainder = t.inBuf[:n+len(t.remainder)]
if readErr != nil {
t.readErr = readErr
if err != nil {
return
}
t.remainder = t.inBuf[:n+len(t.remainder)]
}
}
Generated Vendored
+2 -2
View File
@@ -704,8 +704,8 @@ golang.org/x/sys/plan9
golang.org/x/sys/unix
golang.org/x/sys/windows
golang.org/x/sys/windows/registry
# golang.org/x/term v0.46.0
## explicit; go 1.26.0
# golang.org/x/term v0.45.0
## explicit; go 1.25.0
golang.org/x/term
# golang.org/x/text v0.39.0
## explicit; go 1.25.0