helmfile/AGENTS.md

197 lines
5.0 KiB
Markdown

# AGENTS.md
## Build and Test Commands
### Essential Setup
```bash
# Check Go version (requires 1.24.2+)
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
```bash
# 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
```bash
# Run go vet (always available)
make check
# Format code with gci
make fmt
# Run golangci-lint
golangci-lint run
```
### Testing Commands
```bash
# 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):
1. Standard library (stdlib)
2. Default (third-party)
3. Local (github.com/helmfile/helmfile prefix)
Always use aliases for common stdlib packages to avoid conflicts:
```go
import (
goContext "context" // Alias to avoid naming conflicts
goruntime "runtime"
"fmt"
"os"
"github.com/helmfile/helmfile/pkg/app"
)
```
### Formatting
- Use `go fmt` for standard formatting
- Use `gci` for import organization: `gci write --skip-generated -s standard -s default -s 'prefix(github.com/helmfile/helmfile)' .`
- Run `make fmt` before 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 `any` instead of `interface{}`
### 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
```go
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
```go
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
1. Always handle errors
2. Run `make check` before committing
3. Run `golangci-lint run` and fix all issues
4. Write tests for new pkg/ functionality
5. Update docs/ for user-facing changes
6. 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 init` after installation