Thank you for your interest in contributing to the PDP Server project. This document provides guidelines and information for contributors.
- Code of Conduct
- Getting Started
- Development Setup
- Contributing Process
- Coding Standards
- Testing Guidelines
- Documentation
- Issue Reporting
- Pull Request Process
This project adheres to a code of conduct adapted from the Contributor Covenant. By participating, you are expected to uphold this code.
- Be Respectful: Treat everyone with respect and kindness
- Be Inclusive: Welcome newcomers and diverse perspectives
- Be Collaborative: Work together constructively
- Be Professional: Maintain professional communication
- Go 1.21+: Installation Guide
- Git: For version control
- Make: For build automation (optional)
- Docker: For containerized development (optional)
-
Fork the Repository
# Fork on GitHub, then clone your fork git clone https://github.com/your-username/pdp-server.git cd pdp-server
-
Add Upstream Remote
git remote add upstream https://github.com/original-org/pdp-server.git
-
Install Dependencies
go mod download
-
Build and Test
go build -o pdp-server cmd/server/main.go go test ./...
-
Copy Configuration
cp config.yaml.example config.yaml
-
Set Up Development Environment
# Create development directories mkdir -p dev-data/{blobs,db} # Set development config export PDP_DATA_DIR=./dev-data export PDP_LOG_LEVEL=debug
-
Run Development Server
go run cmd/server/main.go
VS Code:
- Go extension by Google
- Go Test Explorer
- GitLens
- REST Client
GoLand/IntelliJ:
- Go plugin
- Database Navigator
- HTTP Client
# Run with live reload (install air first: go install github.com/cosmtrek/air@latest)
air
# Format code
go fmt ./...
# Lint code (install golangci-lint first)
golangci-lint run
# Generate mocks (install mockgen first)
go generate ./...
# Run specific tests
go test ./pkg/api -v
# Run tests with coverage
go test -cover ./...- Look for issues labeled
good first issuefor beginners - Check
help wantedlabels for areas needing contribution - Discuss complex changes in issues before starting
# Sync with upstream
git fetch upstream
git checkout main
git merge upstream/main
# Create feature branch
git checkout -b feature/your-feature-name- Follow coding standards (see below)
- Write tests for new functionality
- Update documentation as needed
- Commit changes with clear messages
# Run all tests
go test ./...
# Run integration tests
./test_complete.sh
# Test specific functionality
go test ./pkg/api -run TestUploadPiece- Push your branch to your fork
- Create a pull request with clear description
- Link related issues
- Wait for review and address feedback
We follow the standard Go style guide with some project-specific conventions:
# Use gofmt for formatting
go fmt ./...
# Use goimports for import organization
goimports -w .// Good: Clear, descriptive names
func CreateProofSet(ctx context.Context, data ProofSetData) (*ProofSet, error)
type PieceService struct {
blobStore blobstore.Blobstore
piriClient service.PDPService
}
// Bad: Unclear abbreviations
func CreatePS(ctx context.Context, d PSD) (*PS, error)// Good: Wrap errors with context
func (s *PieceService) UploadPiece(ctx context.Context, data []byte) error {
if err := s.validateData(data); err != nil {
return fmt.Errorf("data validation failed: %w", err)
}
if err := s.blobStore.Put(ctx, key, bytes.NewReader(data)); err != nil {
return fmt.Errorf("failed to store piece data: %w", err)
}
return nil
}
// Bad: Swallowing errors
func (s *PieceService) UploadPiece(ctx context.Context, data []byte) error {
s.validateData(data) // Error ignored
s.blobStore.Put(ctx, key, bytes.NewReader(data)) // Error ignored
return nil
}// Good: Small, focused interfaces
type Blobstore interface {
Put(ctx context.Context, key string, data io.Reader) error
Get(ctx context.Context, key string) (io.ReadCloser, error)
Delete(ctx context.Context, key string) error
}
// Bad: Large, monolithic interfaces
type Storage interface {
PutBlob(ctx context.Context, key string, data io.Reader) error
GetBlob(ctx context.Context, key string) (io.ReadCloser, error)
DeleteBlob(ctx context.Context, key string) error
CreateDatabase() error
MigrateDatabase() error
QueryDatabase(query string) ([]map[string]interface{}, error)
// ... many more methods
}pkg/
├── api/ # HTTP API handlers and routing
├── blobstore/ # File storage abstractions
├── config/ # Configuration management
├── models/ # Database models and types
├── piece/ # Piece management business logic
├── proofset/ # Proof set management
├── service/ # External service adapters
└── watcher/ # Background services
// PieceService manages the lifecycle of data pieces for Filecoin storage.
// It handles piece preparation, upload, and CommP calculation with
// power-of-2 padding for Filecoin compatibility.
type PieceService struct {
blobStore blobstore.Blobstore
piriService service.PDPService
db *gorm.DB
}
// UploadPiece stores piece data with proper Filecoin formatting.
// The data is padded to the next power of 2 and CommP is calculated
// for blockchain registration.
//
// Parameters:
// - ctx: Request context for cancellation
// - fileContent: Raw piece data to be stored
//
// Returns:
// - PieceInfo: Metadata about the stored piece
// - error: Any error that occurred during processing
func (s *PieceService) UploadPiece(ctx context.Context, fileContent []byte) (*PieceInfo, error) {
// Implementation...
}func TestPieceService_UploadPiece(t *testing.T) {
tests := []struct {
name string
input []byte
wantSize int64
wantErr bool
errContains string
}{
{
name: "valid small file",
input: []byte("hello world"),
wantSize: 16, // Next power of 2 after 11
wantErr: false,
},
{
name: "empty file",
input: []byte{},
wantErr: true,
errContains: "empty file",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Test implementation
})
}
}- Test individual functions and methods
- Use mocks for external dependencies
- Fast execution (< 1 second per test)
func TestPadToPowerOfTwo(t *testing.T) {
testCases := []struct {
input []byte
expected int
}{
{[]byte("hello"), 8},
{[]byte("hello world"), 16},
{make([]byte, 1024), 1024},
}
for _, tc := range testCases {
result := padToPowerOfTwo(tc.input)
assert.Equal(t, tc.expected, len(result))
}
}- Test component interactions
- Use real dependencies where possible
- Test realistic scenarios
func TestPieceUploadIntegration(t *testing.T) {
// Set up real blobstore and database
tempDir := t.TempDir()
blobStore, err := blobstore.NewFileBlobstore(tempDir)
require.NoError(t, err)
db := setupTestDB(t)
service := piece.NewPieceService(blobStore, mockPiriService, db)
// Test the complete flow
testData := []byte("integration test data")
pieceInfo, err := service.UploadPiece(context.Background(), testData)
require.NoError(t, err)
assert.NotEmpty(t, pieceInfo.PieceCID)
assert.Equal(t, int64(32), pieceInfo.Size) // Next power of 2
}- Test complete workflows via HTTP API
- Use the test script:
./test_complete.sh
Use interfaces for testability:
//go:generate mockgen -source=blobstore.go -destination=mocks/mock_blobstore.go
type Blobstore interface {
Put(ctx context.Context, key string, data io.Reader) error
Get(ctx context.Context, key string) (io.ReadCloser, error)
Delete(ctx context.Context, key string) error
}When adding features, update the main README.md:
- Feature descriptions
- API endpoint changes
- Configuration options
- Usage examples
Update docs/API.md for any API changes:
- New endpoints
- Parameter changes
- Response format changes
- Error codes
Update docs/ARCHITECTURE.md for structural changes:
- New components
- Data flow changes
- Integration patterns
- Technology stack updates
Use the bug report template:
**Describe the bug**
A clear description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. See error
**Expected behavior**
What you expected to happen.
**Environment:**
- OS: [e.g. Ubuntu 20.04]
- Go version: [e.g. 1.21]
- PDP Server version: [e.g. v1.0.0]
**Additional context**
Any other context about the problem.Use the feature request template:
**Is your feature request related to a problem?**
A clear description of what the problem is.
**Describe the solution you'd like**
A clear description of what you want to happen.
**Describe alternatives you've considered**
Alternative solutions or features you've considered.
**Additional context**
Any other context about the feature request.- Code follows project style guidelines
- Self-review of the code completed
- Tests added for new functionality
- All tests pass locally
- Documentation updated as needed
- Commit messages are clear and descriptive
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that causes existing functionality to not work as expected)
- [ ] Documentation update
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] Tests added/updated- Automated Checks: CI/CD pipeline runs tests and linting
- Code Review: Maintainers review code for quality and correctness
- Testing: Additional testing by reviewers if needed
- Approval: At least one maintainer approval required
- Merge: Squash and merge or rebase merge based on complexity
- Delete your feature branch
- Update your local main branch
- Close related issues if applicable
We use a simplified Git Flow:
# Main branch: stable, production-ready code
main
# Feature branches: new features and bug fixes
feature/add-authentication
feature/improve-error-handling
bugfix/fix-memory-leak
# Release branches: prepare for releases (if needed)
release/v1.1.0Follow conventional commits:
# Format: type(scope): description
feat(api): add authentication middleware
fix(piece): resolve memory leak in upload handler
docs(readme): update installation instructions
test(api): add integration tests for proof sets
refactor(storage): extract blobstore interfaceTypes:
feat: New featurefix: Bug fixdocs: Documentation only changesstyle: Code style changes (formatting, etc.)refactor: Code change that neither fixes a bug nor adds a featuretest: Adding missing testschore: Changes to build process or auxiliary tools
- Version Bumping: Follow semantic versioning (MAJOR.MINOR.PATCH)
- Changelog: Update CHANGELOG.md with new features and fixes
- Tagging: Create git tags for releases
- Documentation: Update version-specific documentation
- GitHub Issues: Bug reports and feature requests
- GitHub Discussions: General questions and discussions
- Email: [maintainer-email] for private matters
Contributors will be recognized in:
- CONTRIBUTORS.md file
- Release notes for significant contributions
- GitHub contributor statistics
Thank you for contributing to PDP Server! 🎉