Thank you for your interest in contributing to Blobber! This document provides guidelines and instructions for contributing.
- Code of Conduct
- Getting Started
- Development Workflow
- Code Style
- Commit Guidelines
- Testing
- Pull Request Process
- Documentation
- Getting Help
We are committed to providing a welcoming and inclusive environment. Please be respectful and constructive in all interactions. Harassment, discrimination, or abusive behavior will not be tolerated.
- Go 1.24+ - Installation guide
- Docker - Required for integration tests
- just - Command runner (installation)
- golangci-lint - Go linter (installation)
Alternatively, use Nix for a reproducible development environment:
nix develop-
Fork the repository on GitHub
-
Clone your fork:
git clone https://github.com/YOUR_USERNAME/blobber.git cd blobber -
Add the upstream remote:
git remote add upstream https://github.com/meigma/blobber.git
-
Verify your setup:
just ci
Create a feature branch from master:
git checkout master
git pull upstream master
git checkout -b feat/your-feature-nameUse descriptive branch names with prefixes like feat/, fix/, docs/, or refactor/.
Use just to run common development tasks:
| Command | Description |
|---|---|
just |
Show all available commands |
just build |
Build all packages |
just build-cli |
Build CLI binary to bin/blobber |
just test |
Run unit tests |
just test-v |
Run tests with verbose output |
just test-cover |
Run tests with coverage report |
just test-integration |
Run integration tests (requires Docker) |
just lint |
Run golangci-lint |
just lint-fix |
Run linter with auto-fix |
just fmt |
Format code |
just ci |
Run all CI checks locally |
Start a local OCI registry for manual testing:
just registry-start # Start registry at localhost:5050
just registry-stop # Stop registry
just registry-rm # Remove registry containerCode must be formatted with gofmt and goimports:
just fmtImports must be organized in groups:
- Standard library
- External packages
- Local packages (
github.com/meigma/blobber)
All code must pass golangci-lint with no errors:
just lintThe linter enforces:
- Error handling - All errors must be explicitly handled
- Security - No common security vulnerabilities (gosec)
- Complexity - Cyclomatic complexity <= 15, cognitive complexity <= 20
- Code quality - Various best practices via revive, gocritic, etc.
Use just lint-fix to auto-fix some issues.
- Keep functions focused and concise
- Use meaningful variable and function names
- Add godoc comments for exported functions and types
- Handle errors explicitly; avoid ignoring them
- Use
context.Contextfor cancellation and timeouts
This project uses Conventional Commits for automated versioning and changelog generation.
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
| Type | Version Bump | Example |
|---|---|---|
fix: |
Patch (0.0.x) | fix: handle nil pointer in registry client |
feat: |
Minor (0.x.0) | feat: add zstd compression support |
feat!: |
Major (x.0.0) | feat!: redesign Client API |
BREAKING CHANGE: |
Major (x.0.0) | Footer indicating breaking change |
Other types (no version bump, but tracked in changelog):
docs:- Documentation changeschore:- Maintenance taskstest:- Test additions or fixesci:- CI/CD changesrefactor:- Code refactoringstyle:- Code style changesperf:- Performance improvements
# Bug fix
git commit -m "fix: prevent panic when image manifest is nil"
# New feature
git commit -m "feat: add support for zstd compression"
# Breaking change
git commit -m "feat!: change Push signature to accept options struct"
# With scope
git commit -m "fix(cli): correct flag parsing for --no-cache"
# With body
git commit -m "feat: add blob caching
Implements local filesystem caching to avoid repeated
downloads of the same blobs. Cache location follows
XDG conventions."Run unit tests:
just testRun with verbose output:
just test-vGenerate coverage report:
just test-cover
# Opens coverage.htmlIntegration tests require Docker and test against a real OCI registry:
just test-integrationFor debugging with container logs:
just test-integration-debug- Use testify for assertions
- Place test files alongside source files (
foo_test.go) - Use table-driven tests for multiple test cases
- Tag integration tests with
//go:build integration
Example:
func TestClient_Push(t *testing.T) {
tests := []struct {
name string
input string
want string
wantErr bool
}{
// test cases...
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// test implementation
})
}
}-
Sync with upstream:
git fetch upstream git rebase upstream/master
-
Run all checks:
just ci
-
Run integration tests (if applicable):
just test-integration
-
Push your branch to your fork:
git push origin feat/your-feature-name
-
Open a Pull Request against
meigma/blobber:master -
Fill out the PR template with:
- Summary of changes
- Related issues (use
Fixes #123to auto-close) - Testing performed
- All CI checks must pass
- Code must be formatted and lint-free
- Tests must pass (including any new tests for new functionality)
- Commits must follow Conventional Commits format
- Changes should be focused and atomic
- A maintainer will review your PR
- Address feedback by pushing additional commits
- Once approved, a maintainer will merge the PR
- Add godoc comments for all exported types, functions, and methods
- Keep comments concise and focused on "why" not "what"
User-facing documentation lives in /docs (Docusaurus site):
just docs-install # Install dependencies
just docs-dev # Start dev server
just docs-build # Build for productionUpdate documentation when:
- Adding new CLI commands or flags
- Changing library API
- Adding new features
- Questions: Open a GitHub Discussion
- Bugs: Open a GitHub Issue
- Documentation: Visit blobber.meigma.dev
By contributing, you agree that your contributions will be licensed under the MIT License.