Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c795127
ci(lint): adopt strict golangci-lint config + cross-platform CI gate
lexfrei May 10, 2026
349da55
fix(commands): reset GlobalArgs.Endpoints to empty between files
lexfrei May 10, 2026
16fc515
refactor(commands): consolidate rotate-ca endpoint normalisation
lexfrei May 10, 2026
6107ece
fix(init): use os.IsNotExist for stat-before-write branch
lexfrei May 10, 2026
cd29111
test(init): pin gitignore report verb against ambiguous stat errors
lexfrei May 10, 2026
f3ce867
style(main): use initSubcommandName constant
lexfrei May 10, 2026
587edae
refactor(charts): wrap embedded WalkDir errors with file path
lexfrei May 10, 2026
0f565e7
test(helm): pin Lines() empty-content guard
lexfrei May 10, 2026
84757c2
refactor(engine): drop unused ctx parameter from FullConfigProcess
lexfrei May 10, 2026
33b01ea
refactor(charts): wrap AvailablePresets ReadDir error
lexfrei May 10, 2026
e4b4837
fix(test,engine): self-contained captureStderr; surface enc.Close errors
lexfrei May 10, 2026
363f7a8
test(engine): pin yaml encode/close error wrapping
lexfrei May 10, 2026
af628e6
test(commands): pin captureStderr per-call restore semantics
lexfrei May 10, 2026
42974c8
fix(main): replace panic on bad applyOptions.timeout with wrapped error
lexfrei May 10, 2026
f0cdd6e
docs(secureperm): explain unsafe.Sizeof→uint32 conversion safety
lexfrei May 10, 2026
4fd0713
refactor(commands): finish cockroachdb/errors migration in stragglers
lexfrei May 10, 2026
ac577a4
docs(engine): correct extractResourceData doc comment
lexfrei May 10, 2026
fa97b28
build: mark pkg/generated as linguist-generated
lexfrei May 10, 2026
4c24050
docs(main): per-line doc comments on completion-related const block
lexfrei May 10, 2026
37e11e4
fix(main): parse applyOptions.timeout in default-string path too
lexfrei May 10, 2026
43b8ab3
test(commands): close write-end of pipe in captureStderr defer
lexfrei May 10, 2026
3960231
test(engine): assert 2-space indent in encodeYAMLNodeIndented happy path
lexfrei May 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
* text=auto eol=lf

# Go source must keep LF endings; gofmt rejects CRLF.
*.go text eol=lf

# Go module / sum / config files.
go.mod text eol=lf
go.sum text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
*.sh text eol=lf

# Binaries
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary

# pkg/generated re-exports the embedded chart map produced by `go
# embed`; the file is mechanical glue, not hand-edited. Marking it
# generated keeps it out of GitHub language stats and collapses it
# in PR diffs by default.
pkg/generated/** linguist-generated
24 changes: 24 additions & 0 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ jobs:
- name: Run tests
run: go test ./...

lint:
# Run golangci-lint on the same OS matrix as test:. The Windows
# runner is essential — secureperm_windows.go is build-tagged
# (//go:build windows) and never gets evaluated on a Linux/macOS
# host. Without a Windows lint pass, build-tagged files diverge
# from the rest of the tree silently.
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: stable
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v7
with:
version: v2.12.2
args: --timeout=5m

dco:
runs-on: ubuntu-latest
steps:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
talm
dist/
.claude/
151 changes: 151 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
version: "2"

linters:
default: all
disable:
- depguard
- exhaustruct
- gochecknoinits
- wsl
- lll
- errchkjson
- ireturn
- gocheckcompilerdirectives
# noinlineerr: this codebase wholesale uses 'if err := X(); err != nil' inline form
# — 219+ occurrences across packages. Converting to plain-assignment style would
# produce a noisy diff with zero correctness benefit AND create variable-scope leaks
# in many places where err is locally scoped to the check.
- noinlineerr
# gomodguard: deprecated in v2.12+ in favour of gomodguard_v2; we don't use
# either (no allow/blocklists configured), so disable to silence the warning.
- gomodguard
settings:
dupl:
threshold: 100
goconst:
min-len: 2
min-occurrences: 2
gocritic:
disabled-checks:
- dupImport
- unnamedResult
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
funlen:
lines: 60
statements: 60
gomoddirectives:
# The cozystack fork of Talos carries a downstream-only patch
# (siderolabs/talos#12652, --skip-verify) that upstream declined.
# Until that flag lands upstream, the replace directive is the
# only way to consume the fork — it is not generic dependency
# rewriting and must stay.
replace-allow-list:
- github.com/siderolabs/talos
- github.com/siderolabs/talos/pkg/machinery
gocyclo:
min-complexity: 15
cyclop:
max-complexity: 15
mnd:
ignored-numbers:
- "10"
- "100"
- "1000"
- "2"
- "60"
- "60.0"
- "64"
- "500"
nolintlint:
require-explanation: true
require-specific: true
allow-unused: false
varnamelen:
max-distance: 5
min-name-length: 3
check-receiver: false
check-return: false
ignore-type-assert-ok: false
ignore-map-index-ok: false
ignore-chan-recv-ok: false
ignore-decls:
- wg sync.WaitGroup
- wg *sync.WaitGroup
- mu sync.Mutex
- ok bool
ignore-names:
- i
- w
- r
- b
- c
- m
- n
- tt
- rw
exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
paths:
- third_party$
- builtin$
- generated\.go$
- pkg/generated/
- \.claude/
rules:
- linters:
- funlen
- dupl
- gocognit
- gocyclo
- cyclop
- errcheck
- testableexamples
- testpackage
- forcetypeassert
- gocritic
- nlreturn
- wsl_v5
- varnamelen
- unparam
- modernize
- gosec
- testifylint
- perfsprint
- paralleltest
- maintidx
# goconst on _test.go: tests intentionally repeat literals
# (IPs, CIDRs, MAC addresses, YAML keys) inside backtick raw
# strings that are EXPECTED template outputs, alongside Go
# string literals used as assertion values. Substituting the
# Go literal into a const desynchronises it from the
# backtick fixture, breaking the test silently. Empirically
# observed during the strict-lint adoption pass: every
# blanket goconst substitution in pkg/engine/contract_*.go
# broke at least one TestRender* case. Sub-agent attempts
# failed for the same reason. Disable goconst on test files.
- goconst
path: _test\.go

formatters:
enable:
- gofmt
- gofumpt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- generated\.go$
- pkg/generated/
- \.claude/
68 changes: 38 additions & 30 deletions charts/charts.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import (
"path"
"regexp"
"strings"

"github.com/cockroachdb/errors"
)

const presetGenericName = "generic"

//go:embed all:cozystack all:generic all:talm
var embeddedCharts embed.FS

Expand All @@ -16,83 +20,87 @@ var embeddedCharts embed.FS
func PresetFiles() (map[string]string, error) {
filesMap := make(map[string]string)
regex := regexp.MustCompile(`(name|version): \S+`)
err := fs.WalkDir(embeddedCharts, ".", func(filePath string, d fs.DirEntry, err error) error {

err := fs.WalkDir(embeddedCharts, ".", func(filePath string, entry fs.DirEntry, err error) error {
if err != nil {
return err
// WalkDir surfaces a plain *fs.PathError on failure;
// wrap with the offending path so a downstream caller
// reading just the error message can locate the bad file
// without re-running with extra logging.
return errors.Wrapf(err, "walking embedded charts at %q", filePath)
}
if d.IsDir() {

if entry.IsDir() {
return nil
}

// Skip talm subdirectories in preset charts (cozystack/charts/talm, generic/charts/talm)
// but include files from the main talm chart (talm/templates/_helpers.tpl, etc.)
if strings.HasPrefix(filePath, "cozystack/charts/talm/") ||
strings.HasPrefix(filePath, "generic/charts/talm/") {
if strings.HasPrefix(filePath, "cozystack/charts/talm/") ||
strings.HasPrefix(filePath, "generic/charts/talm/") {
return nil
}

// Read file content
data, err := embeddedCharts.ReadFile(filePath)
if err != nil {
return err
return errors.Wrapf(err, "reading embedded chart file %q", filePath)
}

content := string(data)

// For Chart.yaml files, replace name and version with %s
if path.Base(filePath) == "Chart.yaml" {
content = regex.ReplaceAllString(content, "$1: %s")
}

// Use the file path as-is (relative to charts directory)
filesMap[filePath] = content

return nil
})

if err != nil {
return nil, err
return nil, errors.Wrap(err, "walking embedded charts")
}

return filesMap, nil
}

// AvailablePresets returns a list of available preset chart names.
// The "generic" preset is always first if it exists.
// The presetGenericName preset is always first if it exists.
func AvailablePresets() ([]string, error) {
var presets []string
var hasGeneric bool

var (
presets []string
hasGeneric bool
)

entries, err := embeddedCharts.ReadDir(".")
if err != nil {
return nil, err
return nil, errors.Wrap(err, "reading embedded charts root")
}

for _, entry := range entries {
if !entry.IsDir() {
continue
}

name := entry.Name()
// Skip talm as it's a library chart, not a preset
if name == "talm" {
continue
}
if name == "generic" {

if name == presetGenericName {
hasGeneric = true
} else {
presets = append(presets, name)
}
}

// Put generic first if it exists
if hasGeneric {
presets = append([]string{"generic"}, presets...)
presets = append([]string{presetGenericName}, presets...)
}

return presets, nil
}

Loading
Loading