Skip to content

Contributing

Thank you for your interest in contributing to coverctl! This guide will help you get started.

  • Go 1.25 or later
  • Git
  • Make (optional)
Terminal window
git clone https://github.com/felixgeelhaar/coverctl.git
cd coverctl
go build ./...
Terminal window
go test ./... -cover
Terminal window
golangci-lint run
Terminal window
git checkout -b feature/your-feature

Follow the architecture guidelines.

Practice TDD - write tests before implementation:

func TestNewFeature(t *testing.T) {
// Arrange
input := "test"
// Act
result := NewFeature(input)
// Assert
if result != expected {
t.Errorf("got %v, want %v", result, expected)
}
}
Terminal window
# Run coverctl on itself
./coverctl check

Maintain ≥80% coverage.

Use Conventional Commits:

Terminal window
git commit -m "feat: add new validation option"
git commit -m "fix: handle empty domain list"
git commit -m "docs: update CLI reference"
  • Fill out the PR template
  • Link related issues
  • Wait for CI to pass
  • Request review
  • Follow Effective Go
  • Use gofmt for formatting
  • Run golangci-lint before committing
// Exported types: PascalCase
type CoverageResult struct {}
// Unexported types: camelCase
type internalState struct {}
// Methods: verb phrases
func (s *Service) CalculateCoverage() {}
// Interfaces: -er suffix when possible
type Runner interface {}
type Parser interface {}
// Wrap errors with context
if err != nil {
return fmt.Errorf("parse config: %w", err)
}
// Use sentinel errors for expected conditions
var ErrConfigNotFound = errors.New("config not found")
func TestEvaluate(t *testing.T) {
tests := []struct {
name string
policy Policy
coverage map[string]CoverageStat
want Result
}{
{
name: "all domains pass",
policy: Policy{Default: DefaultPolicy{Min: 80}},
// ...
},
{
name: "one domain fails",
// ...
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Evaluate(tt.policy, tt.coverage)
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("got %+v, want %+v", got, tt.want)
}
})
}
}
type mockRunner struct {
runFunc func(ctx context.Context, opts RunOptions) (string, error)
}
func (m *mockRunner) Run(ctx context.Context, opts RunOptions) (string, error) {
return m.runFunc(ctx, opts)
}
  1. CI Must Pass: All tests, linting, and coverage checks
  2. Review Required: At least one maintainer approval
  3. Squash Merge: PRs are squashed to keep history clean
  4. Conventional Commits: PR title follows conventional commit format
TypeDescription
featNew feature
fixBug fix
docsDocumentation only
styleFormatting, no code change
refactorCode restructuring
testAdding tests
choreMaintenance tasks

Releases are automated via Relicta:

  1. Commits to main trigger version analysis
  2. Conventional commits determine version bump
  3. Tags are created automatically
  4. GitHub releases include binaries for all platforms

coverctl is MIT licensed. By contributing, you agree to license your contributions under the same license.