Contributions to QFieldCloud are welcome! This guide covers the process for submitting changes.
Before You Start
1. Communicate Your Ideas
Before investing time in a PR, discuss your proposal with the QFieldCloud team:
- Create an issue: Open a GitHub issue detailing your suggestion
- Wait for feedback: The development team will review and provide guidance
- Clarify details: Engage in discussion to refine the approach
Not every idea will be accepted. Discussing first saves you time and effort on PRs that wouldn’t be merged.
2. Check Existing Issues
Search for existing issues or discussions related to your idea:
Development Workflow
1. Fork and Clone
Fork the repository and clone with submodules:
git clone --recurse-submodules [email protected]:YOUR_USERNAME/QFieldCloud.git
cd QFieldCloud
2. Create a Branch
Create a feature branch from master:
git checkout master
git pull origin master
git checkout -b feature/my-feature-name
Branch naming conventions:
feature/description - New features
fix/description - Bug fixes
refactor/description - Code refactoring
docs/description - Documentation changes
test/description - Test improvements
3. Make Changes
Develop your changes following the code style guidelines.
4. Commit Changes
Write clear, concise commit messages:
git add .
git commit -m "Add support for custom QGIS project thumbnails"
Commit message guidelines:
- Use imperative mood (“Add” not “Added”)
- First line: concise summary (50 chars or less)
- Reference issue numbers: “Fix #123: Handle null project descriptions”
- Explain why, not just what
5. Push and Create PR
Push your branch and create a pull request:
git push origin feature/my-feature-name
Then go to GitHub and click “Create Pull Request”.
Pull Request Guidelines
PR Title and Description
Title: Clear and descriptive
Add custom thumbnail support for QGIS projects
Description: Include:
- Summary: What does this PR do?
- Issue reference:
Closes #123 or Related to #456
- Changes: List of main changes
- Screenshots: Before/after (for UI changes)
- Testing: How to test the changes
Example:
## Summary
Adds support for custom project thumbnails uploaded by users.
## Changes
- Add `thumbnail` field to Project model
- Create API endpoint for thumbnail upload
- Add thumbnail display in project list
## Screenshots
[Before]
[After]
## Testing
1. Create a project
2. Upload a thumbnail via `/api/v1/projects/{id}/thumbnail`
3. Verify thumbnail appears in project list
Closes #123
PR Checklist
Before submitting:
Draft PRs
If your PR is not ready for review, mark it as a draft PR.
Draft PRs should:
- Be checkable without breaking the stack
- Have the specific feature testable (even if incomplete)
PR Review Process
- Automated checks: CI runs tests and linters
- Code review: Team members review your code
- Feedback: Address review comments
- Approval: Once approved, your PR will be merged
Code Style
QFieldCloud uses automated tools to enforce code style.
Pre-commit Hooks
Install pre-commit hooks to automatically check code before commits:
pip install pre-commit
pre-commit install
Now hooks run automatically on git commit.
Pre-commit Configuration
See .pre-commit-config.yaml for the full configuration. Key hooks:
Ruff is used for both linting and formatting Python code:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.13.0
hooks:
# Linter
- id: ruff
args: [ --fix ]
# Formatter
- id: ruff-format
Run manually:
# Lint and auto-fix
pre-commit run ruff --all-files
# Format code
pre-commit run ruff-format --all-files
2. Flake8 (Additional Linting)
- repo: https://github.com/pycqa/flake8
rev: '7.3.0'
hooks:
- id: flake8
additional_dependencies: [flake8-clean-block, flake8-if-expr]
3. mypy (Type Checking)
Static type checking with mypy:
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.18.1
hooks:
- id: mypy
additional_dependencies: [types-*, django-stubs, ...]
Run manually:
mypy -p docker-app -p docker-qgis
4. django-upgrade
Automatically upgrades Django code to 4.2 standards:
- repo: https://github.com/adamchainz/django-upgrade
rev: '1.28.0'
hooks:
- id: django-upgrade
args: [--target-version, '4.2']
5. Standard Hooks
Basic code quality checks:
check-ast: Validate Python syntax
check-yaml: Validate YAML files
check-json: Validate JSON files
check-merge-conflict: Detect merge conflicts
end-of-file-fixer: Ensure files end with newline
trailing-whitespace: Remove trailing whitespace
mixed-line-ending: Enforce LF line endings
Run All Pre-commit Hooks
Manually run all hooks:
pre-commit run --all-files
Code Style Guidelines
Python
- PEP 8: Follow Python style guide
- Line length: 88 characters (Black default, used by Ruff)
- Imports: Group into stdlib, third-party, and local
- Docstrings: Use for public methods and classes
- Type hints: Add where beneficial
Example:
from typing import Optional
from django.db import models
from rest_framework import serializers
from qfieldcloud.core.models import Project
class ProjectSerializer(serializers.ModelSerializer):
"""Serializer for Project model."""
owner_username: str = serializers.CharField(source="owner.username", read_only=True)
class Meta:
model = Project
fields = ["id", "name", "description", "owner_username"]
def validate_name(self, value: str) -> str:
"""Validate project name."""
if len(value) < 3:
raise serializers.ValidationError("Name must be at least 3 characters")
return value
Django
- Use Django 4.2 features (enforced by
django-upgrade)
- Avoid deprecated patterns
- Use ORM instead of raw SQL where possible
- Follow Django naming conventions
Templates
- Use Django template language best practices
- Escape user input (auto-escape is on)
- Keep logic minimal in templates
Testing Requirements
Write Tests
All new features and bug fixes should include tests.
Example test:
from django.test import TestCase
from qfieldcloud.core.models import Project, User
class ProjectThumbnailTestCase(TestCase):
def setUp(self):
self.user = User.objects.create_user(username="test")
self.project = Project.objects.create(name="Test", owner=self.user)
def test_upload_thumbnail(self):
"""Test uploading a project thumbnail."""
# Test implementation
pass
Run Tests
Ensure all tests pass before submitting:
docker compose run app python manage.py test --keepdb
Check Coverage
Maintain or improve test coverage:
docker compose exec app coverage run manage.py test --keepdb
docker compose exec app coverage report
Documentation
Update Documentation
If your changes affect:
- API: Update API documentation or docstrings
- Setup: Update README.md or setup docs
- Features: Update user-facing documentation
Docstrings
Use clear docstrings for public APIs:
def upload_thumbnail(project_id: int, thumbnail_file) -> bool:
"""
Upload a custom thumbnail for a project.
Args:
project_id: ID of the project
thumbnail_file: Image file object
Returns:
True if upload successful, False otherwise
Raises:
Project.DoesNotExist: If project not found
ValidationError: If file is invalid
"""
# Implementation
Branching Strategy
Main Branches
master: Main development branch
- Feature branches: Created from
master
Branch Protection
master is protected:
- Cannot push directly
- PRs required
- CI checks must pass
- Code review required
Merge Strategy
PRs are typically merged using:
- Squash and merge: For feature branches (clean history)
- Merge commit: For important multi-commit PRs
Common Scenarios
Updating Your Branch
Keep your branch up-to-date with master:
git checkout master
git pull origin master
git checkout feature/my-feature
git rebase master
If there are conflicts, resolve them and continue:
Fixing Failed CI
If CI fails:
- Check the error in the GitHub Actions logs
- Fix the issue locally
- Commit and push:
git add .
git commit -m "Fix linting errors"
git push origin feature/my-feature
- Make the requested changes
- Commit with a clear message
- Push to update the PR
- Reply to comments to notify reviewers
Resources
Getting Help
- GitHub Issues: For bugs and feature requests
- Pull Requests: For code review questions
- Email: [email protected] for funding features
Thank You!
Your contributions make QFieldCloud better for everyone. Thank you for taking the time to contribute!