Skip to content

Latest commit

 

History

History
315 lines (232 loc) · 6.69 KB

File metadata and controls

315 lines (232 loc) · 6.69 KB

Contributing to Trash Pickup CLI

Thank you for considering contributing to this project! This document outlines the workflow for both human and AI contributors.

Table of Contents

Branch Naming

Use the following prefixes for branch names:

  • feature/ - New features (e.g., feature/add-retry-logic)
  • fix/ - Bug fixes (e.g., fix/date-formatting-bug)
  • docs/ - Documentation updates (e.g., docs/update-readme)
  • refactor/ - Code refactoring (e.g., refactor/simplify-cache)
  • test/ - Test additions or improvements (e.g., test/add-domain-tests)
  • chore/ - Maintenance tasks (e.g., chore/update-dependencies)

Commit Messages

Follow Conventional Commits format:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Types

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • test: Adding or updating tests
  • refactor: Code changes that neither fix a bug nor add a feature
  • chore: Maintenance tasks
  • perf: Performance improvements

Examples

feat(alarm): add support for custom notification sound

fix(cache): ensure atomic writes on Windows systems

docs: update cron examples in README

test(domain): add edge cases for month boundary handling

Running Tests

Run All Tests

task test

This will:

  • Run all tests with race detector
  • Generate coverage report
  • Create coverage.html for viewing

Run Specific Package Tests

go test -v ./internal/domain

View Coverage

open coverage.html
# OR
go tool cover -html=coverage.txt

Coverage Requirements

  • Overall coverage: >95%
  • Domain logic (internal/domain): 100%
  • New code must include tests

Validating AWTRIX Payloads

Before submitting changes that affect AWTRIX payloads, validate the JSON structure.

Example Status Payload

{
  "draw": [
    {"df": [0, 0, 4, 7, "#FFFF00"]},
    {"df": [5, 0, 4, 7, "#099999"]},
    {"df": [10, 0, 4, 7, "#4584D3"]},
    {"dt": [15, 1, "TOM", "#FF0000"]}
  ],
  "noScroll": true,
  "duration": 5
}

Example Alarm Payload

{
  "text": "TRASH: Bio 14-tgl., Gelbe Tonne",
  "background": "#FF0000",
  "blinkText": 500,
  "hold": true,
  "duration": 0,
  "noScroll": false
}

Validation Checklist

  • JSON is valid (use jq or online validator)
  • All colors are 6-char hex with # prefix (e.g., #FF0000)
  • Draw commands use correct syntax (df, dt)
  • Chip positions follow spacing rule (0, 5, 10, 15...)
  • Text position is at x=15
  • Text is max 4 characters and uppercase

Manual Testing

  1. Start a local MQTT broker:

    docker run -it -p 1883:1883 eclipse-mosquitto
  2. Subscribe to messages:

    mosquitto_sub -h localhost -t "test_prefix/#" -v
  3. Run the command:

    ./bin/bdg status --city-id=123 --area-id=456 \
      --mqtt-broker=tcp://localhost:1883 \
      --mqtt-prefix=test_prefix
  4. Verify the payload in mosquitto_sub output

Cache Behavior

Safety Rules

⚠️ NEVER:

  • Delete cache files programmatically
  • Modify existing cache files in place
  • Assume cache structure (always check for existence)

ALWAYS:

  • Use atomic writes (temp file + rename)
  • Handle cache misses gracefully (return nil, nil)
  • Respect the cache-first policy (never refetch if file exists)

Testing Cache Changes

When modifying cache behavior:

  1. Test with empty cache directory
  2. Test with existing cache files
  3. Test with corrupted cache files
  4. Test cache writes under disk full conditions
  5. Test cache reads with permission errors

Cache File Format

  • Location: ~/.cache/bdg/
  • Naming: YYYY-MM.json (e.g., 2025-12.json)
  • Content: Raw API response JSON (pretty-printed with 2-space indent)

Example:

{
  "year": "2025",
  "month": "12",
  "dates": [
    {
      "title": "Bio 14-tgl.",
      "trash_name": "BARNIM_BIO",
      "day": "2025-12-30",
      "description": "",
      "color": "#566322"
    }
  ]
}

Pull Request Process

  1. Fork and Branch

    git checkout -b feature/your-feature-name
  2. Make Changes

    • Write code
    • Add tests
    • Update documentation
  3. Run Quality Checks

    task test
    task lint
  4. Commit

    git add .
    git commit -m "feat: add your feature"
  5. Push and Create PR

    git push origin feature/your-feature-name
  6. PR Checklist

    • Tests pass
    • Linter passes
    • Coverage >95%
    • Documentation updated
    • CHANGELOG updated (if applicable)
    • Manual testing completed (if applicable)

Code Style

Go Style

Follow Effective Go and Go Code Review Comments.

Key points:

  • Use gofmt (automatically applied by task lint)
  • Error strings should not be capitalized or end with punctuation
  • Prefer short variable names in limited scopes
  • Document exported functions and types

Project-Specific Style

  • Domain logic: Pure functions, no I/O
  • Error handling: Wrap errors with context using fmt.Errorf("context: %w", err)
  • Time handling: Always pass time.Time as parameter, never use global time.Now()
  • Tests: Use table-driven tests with descriptive names

Linting

All code must pass golangci-lint:

task lint

Fix automatically when possible:

golangci-lint run --fix ./...

Questions?

  • Read AGENTS.md for detailed architecture and design decisions
  • Check existing issues and discussions
  • Open a new issue for clarification

Releases

Releases are automated using GoReleaser and GitHub Actions.

Creating a Release

  1. Update CHANGELOG.md with changes
  2. Commit all changes
  3. Create and push a version tag:
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
  1. GitHub Actions will automatically:
    • Run tests on all platforms
    • Build binaries for Linux, macOS, Windows
    • Create checksums
    • Generate release notes
    • Publish to GitHub Releases

Testing Releases Locally

Before creating a tag, test the release process:

# Validate GoReleaser config
task release-check

# Build snapshot (no publish)
task release

Binaries will be in dist/ directory.

License

By contributing, you agree that your contributions will be licensed under the same license as the project.