This guide outlines the development workflow and requirements for contributing to OpenMapView.
All contributions must meet the following requirements before being merged:
All Kotlin code must follow the project's formatting rules enforced by Spotless with ktlint 1.3.1.
Before committing, run:
./gradlew spotlessApplyThis automatically formats all code according to the project's style rules:
- 4 spaces indentation
- No trailing whitespace
- Files end with newline
- Consistent ktlint formatting
To check formatting without applying changes:
./gradlew spotlessCheckThe CI pipeline will fail if code is not properly formatted.
All .kt files must include the MIT license header at the top:
/*
* Copyright (c) 2025 Alexander Farber
* SPDX-License-Identifier: MIT
*
* This file is part of the OpenMapView project (https://github.com/afarber/OpenMapView)
*/Running ./gradlew spotlessApply automatically adds this header to any files missing it.
Why copyright headers matter: Including copyright headers on all source files helps avoid potential legal issues and keeps this library clean to use for both personal and commercial applications. The MIT license identifier makes licensing terms explicit and unambiguous.
The CI pipeline includes a copyright check that will fail if any .kt files are missing the required header.
All code must pass Detekt static analysis checks. Detekt analyzes code for:
- Code complexity and potential bugs
- Naming conventions
- Performance issues
- Code smells
Run static analysis:
./gradlew detektThe CI pipeline will fail if Detekt finds any issues. View the HTML report at:
openmapview/build/reports/detekt/detekt.html
The Detekt report is also published at https://afarber.github.io/OpenMapView/detekt/
Before adding new dependencies to OpenMapView, verify the following:
-
License Compatibility: Only add dependencies with permissive licenses
- Preferred: Apache 2.0, MIT, BSD
- Prohibited: GPL, AGPL (would affect library users)
- Consult before adding: LGPL, EPL, MPL
-
Verify License: Run the license report to check all dependencies
./gradlew generateLicenseReport
View the report at:
openmapview/build/reports/licenses/licenses.html -
Minimal Footprint: Keep dependencies minimal
- OpenMapView currently has only 5 runtime dependencies
- New dependencies must provide essential functionality
- Avoid bloat - see ARCHITECTURE.md for philosophy
-
Auto-Publishing: License reports automatically publish to the documentation site
- URL: https://afarber.github.io/OpenMapView/licenses/
- Updated on every docs deployment
- No manual maintenance needed
Current Dependencies (all Apache 2.0 or MIT):
- androidx.core:core-ktx
- androidx.lifecycle:lifecycle-runtime-ktx
- androidx.compose.ui:ui-graphics
- io.ktor:ktor-client-android
- com.jakewharton:disklrucache
Git hooks can automatically check formatting and copyright headers before commits, preventing CI failures.
From the repository root, run:
./scripts/setup-git-hooks.shThis installs a pre-commit hook that automatically:
- Checks code formatting with
./scripts/check-format.sh - Checks copyright headers with
./scripts/check-copyright.sh - Runs Detekt static analysis with
./scripts/check-detekt.sh - Blocks the commit if any issues are found
When committing changes, the hook runs:
Running pre-commit checks...
1. Checking code formatting...
Code formatting: OK
2. Checking copyright headers...
Copyright headers: OK
3. Running Detekt static analysis...
Static analysis: OK
All pre-commit checks passed!
If issues are found, the commit is blocked and instructions are displayed.
Note: Git hooks are local and not tracked in the repository. Each developer must run the setup script after cloning.
All new features and bug fixes should include unit tests. See Unit Testing Guide for detailed information on writing tests with Robolectric.
Run unit tests:
./gradlew :openmapview:testThe project enforces a minimum test coverage of 20% for all code. Coverage is measured using JaCoCo.
Generate coverage report:
./gradlew :openmapview:jacocoTestReportView the HTML coverage report at:
openmapview/build/reports/jacoco/jacocoTestReport/html/index.html
Check coverage meets minimum threshold:
./scripts/check-coverage.shThe CI pipeline will fail if coverage drops below the minimum threshold. Focus on testing:
- Core business logic
- Public API methods
- Edge cases and error handling
Coverage excludes:
- Generated code (R.class, BuildConfig)
- Test files
- Android framework classes
For features requiring real Android framework APIs or rendering, add instrumentation tests.
Run instrumentation tests (requires emulator or device):
./gradlew :openmapview:connectedAndroidTest- Fork the repository
- Create a feature branch from
main - Make changes following the code quality requirements
- Run
./gradlew spotlessApplybefore committing - Ensure all tests pass locally
- Push changes and create a pull request
- CI must pass (formatting, tests, builds)
- Address any review feedback
The CI pipeline runs automatically on all pull requests and includes:
- Format Check - Verifies Spotless formatting
- Copyright Check - Verifies MIT license headers
- Static Analysis - Runs Detekt code analysis
- Unit Tests - Runs all JVM unit tests
- Test Coverage - Ensures minimum 20% code coverage
- Build Library - Builds the OpenMapView AAR
- Build Examples - Builds all example applications
All checks must pass before merging.
# Format code
./gradlew spotlessApply
# Check formatting
./gradlew spotlessCheck
# Run static analysis
./gradlew detekt
# Run unit tests
./gradlew :openmapview:test
# Generate coverage report
./gradlew :openmapview:jacocoTestReport
# Check coverage threshold
./scripts/check-coverage.sh
# Build library
./gradlew :openmapview:assembleRelease
# Build all examples
./gradlew assembleDebug
# Run instrumentation tests
./gradlew :openmapview:connectedAndroidTestFor questions about contributing, open an issue on GitHub: https://github.com/afarber/OpenMapView/issues