mirror of
https://github.com/helmfile/helmfile.git
synced 2026-09-30 14:01:46 +02:00
Toolchain and CI:
- Bump go directive from 1.26.8 to 1.27.1 (go.mod)
- Use golang:1.27-alpine builder images in all Dockerfiles
- Bump golangci-lint to v2.13.2 (first release with go1.27 support)
- Add CI gate: `go fix -diff` fails when outdated Go patterns are
detected (locally: `make check-modernize`)
Note: darwin binaries now require macOS 13 or later.
Lint fixes required by golangci-lint v2.13.2:
- goconst: ignore tests (all 436 findings were test-only; goconst
got stricter since v2.12 and this option was added for it)
- openai.go: keep deprecated MaxTokens deliberately with a nolint
rationale (max_tokens is the only form universally supported by
OpenAI-compatible backends like One-API, LiteLLM, Ollama shim)
- state.go: drop always-nil flags param from appendChartVersionFlags
(renamed to chartVersionFlags, unparam)
Modernization (go fix ./..., 62 files):
- interface{} -> any, maps.Copy, strings.SplitSeq, range-over-int,
builtin min/max, slices.Contains/ContainsFunc/Sort, WaitGroup.Go,
reflect.Type.Fields(), new(expr)
- exit_error.go: strings.Builder + fmt.Fprintf instead of string
concatenation and WriteString(fmt.Sprintf(...)) (QF1012)
- chart_dependency.go: strings.CutLast for OCI dependency helpers
Signed-off-by: yxxhero <aiopsclub@163.com>
Co-authored-by: Claude <noreply@anthropic.com>
5.1 KiB
5.1 KiB
AGENTS.md
Build and Test Commands
Essential Setup
# Check Go version (requires 1.27.1+)
go version
# Check Helm dependency (required at runtime)
helm version # Must show version 3.x
# Install gci tool for import formatting
go install github.com/daixiang0/gci@latest
Build Commands
# Standard build
make build
# Direct build
go build -o helmfile .
# Cross-platform builds
make cross
# Build test tools (required for integration tests)
make build-test-tools
Linting and Formatting
# Run go vet (always available)
make check
# Format code with gci
make fmt
# Run golangci-lint
golangci-lint run
# Detect outdated Go patterns (fails if `go fix` would rewrite anything;
# enforced in CI)
make check-modernize
Testing Commands
# Run all unit tests
make test
# Run specific test package
go test -v ./pkg/app/...
# Run single test function
go test -v ./pkg/app/... -run TestSpecificFunction
# Run tests with coverage
go test -v ./pkg/... -coverprofile cover.out -race -p=1
go tool cover -func cover.out
# Run integration tests (requires Kubernetes cluster)
make integration
Code Style Guidelines
Imports
Import ordering (enforced by gci):
- Standard library (stdlib)
- Default (third-party)
- Local (github.com/helmfile/helmfile prefix)
Always use aliases for common stdlib packages to avoid conflicts:
import (
goContext "context" // Alias to avoid naming conflicts
goruntime "runtime"
"fmt"
"os"
"github.com/helmfile/helmfile/pkg/app"
)
Formatting
- Use
go fmtfor standard formatting - Use
gcifor import organization:gci write --skip-generated -s standard -s default -s 'prefix(github.com/helmfile/helmfile)' . - Run
make fmtbefore committing (requires gci installation)
Types
- Exported types use PascalCase:
type App struct - Private types use PascalCase:
type helmKey struct - Interface names should describe behavior:
type Interface interface - Use
anyinstead ofinterface{}
Naming Conventions
- Exported functions/variables: PascalCase
- Private functions/variables: camelCase
- Constants: PascalCase
- Test functions: TestXxx with descriptive names
- Package names: lowercase, single word when possible
- Error variables: ErrXxx
Error Handling
- Use fmt.Errorf with %w for wrapping errors
- Check errors explicitly; never ignore
- Use custom error types in pkg/errors/ when appropriate
- Return error as last return value
if err != nil {
return fmt.Errorf("failed to parse helm version '%s': %w", version, err)
}
Testing
- Use testify/assert for assertions:
assert.Equal(t, expected, actual) - Use testify/require for critical assertions:
require.NoError(t, err) - Test files: *_test.go
- Use table-driven tests for multiple scenarios
- Run tests with -race flag:
-race -p=1 - Use test helper packages: pkg/testutil, pkg/testhelper
func TestFunctionName(t *testing.T) {
tests := []struct {
name string
input string
want string
wantErr bool
}{
{
name: "valid input",
input: "test",
want: "result",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := FunctionUnderTest(tt.input)
if (err != nil) != tt.wantErr {
t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
return
}
assert.Equal(t, tt.want, got)
})
}
}
Logging
- Use zap.SugaredLogger:
logger.Infof("message") - Logger injected via dependency injection
- Don't use fmt.Print for production logging
Comments
- Exported functions must have comments
- Comments should be complete sentences with capital first letter
- Use // for single-line comments
- Use /* */ for package documentation
Linting Configuration (from .golangci.yaml)
Key enabled linters:
- errcheck: Check unhandled errors
- staticcheck: Advanced static analysis
- revive: Fast linter
- govet: Go vet checks
- ineffassign: Detect ineffectual assignments
- misspell: Spell checking
- unused: Detect unused code
Important thresholds:
- Max function length: 280 lines
- Max statements per function: 140
- Max cognitive complexity: 110
- Max naked return lines: 50
- Line length: 120 characters
Structure
- Package main: Entry point only (main.go)
- cmd/: CLI commands using cobra
- pkg/: Core library code organized by domain
- test/: Integration and E2E tests
- Use dependency injection for testability
- Prefer composition over inheritance
Critical Rules
- Always handle errors
- Run
make checkbefore committing - Run
golangci-lint runand fix all issues - Write tests for new pkg/ functionality
- Update docs/ for user-facing changes
- Follow declarative design principles (desired state in config, operational via flags)
Common Issues
- First build downloads 200+ packages (2-3 minutes)
- Integration tests require Kubernetes cluster (minikube/kind)
- Make fmt requires gci installation
- Use -p=1 for tests to avoid race conditions
- Always initialize Helm plugins with
helmfile initafter installation