Skip to content

Commit e30aaac

Browse files
committed
Add copyright header check and pre-commit hook
1 parent dda7b4c commit e30aaac

8 files changed

Lines changed: 313 additions & 4 deletions

File tree

.github/workflows/_copyright.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Copyright Check
2+
3+
on:
4+
workflow_call:
5+
6+
permissions:
7+
contents: read
8+
9+
jobs:
10+
copyright:
11+
name: Check Copyright Headers
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v4
17+
18+
- name: Check for missing copyright headers
19+
run: ./scripts/check-copyright.sh

.github/workflows/_format.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,4 @@ jobs:
3535
run: chmod +x gradlew
3636

3737
- name: Run Spotless check
38-
run: ./gradlew spotlessCheck
38+
run: ./scripts/check-format.sh

.github/workflows/ci.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,22 @@ jobs:
1414
name: Check Formatting
1515
uses: ./.github/workflows/_format.yml
1616

17+
copyright:
18+
name: Check Copyright Headers
19+
uses: ./.github/workflows/_copyright.yml
20+
1721
test:
1822
name: Unit Tests
19-
needs: format
23+
needs: [format, copyright]
2024
uses: ./.github/workflows/_test.yml
2125

2226
build-library:
2327
name: Build Library
24-
needs: [format, test]
28+
needs: [format, copyright, test]
2529
uses: ./.github/workflows/_build-library.yml
2630

2731
build-examples:
2832
name: Build Examples
29-
needs: [format, test]
33+
needs: [format, copyright, test]
3034
uses: ./.github/workflows/_build-examples.yml
3135

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Demonstrates marker system with custom icons and click handling.
3838

3939
## Documentation
4040

41+
- [Contributing Guide](docs/CONTRIBUTING.md) - Code quality requirements, formatting, git hooks, and PR process
4142
- [Lifecycle Management](docs/LIFECYCLE.md) - How OpenMapView handles Android lifecycle events
4243
- [Maven Central Setup](docs/MAVEN_CENTRAL_SETUP.md) - Publishing configuration and release process
4344
- [GitHub Workflows](docs/GITHUB_WORKFLOWS.md) - CI/CD pipeline and workflow architecture

docs/CONTRIBUTING.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Contributing to OpenMapView
2+
3+
[Back to README](../README.md)
4+
5+
This guide outlines the development workflow and requirements for contributing to OpenMapView.
6+
7+
## Code Quality Requirements
8+
9+
All contributions must meet the following requirements before being merged:
10+
11+
### 1. Code Formatting
12+
13+
All Kotlin code must follow the project's formatting rules enforced by Spotless with ktlint 1.3.1.
14+
15+
**Before committing**, run:
16+
17+
```bash
18+
./gradlew spotlessApply
19+
```
20+
21+
This automatically formats all code according to the project's style rules:
22+
- 4 spaces indentation
23+
- No trailing whitespace
24+
- Files end with newline
25+
- Consistent ktlint formatting
26+
27+
**To check formatting** without applying changes:
28+
29+
```bash
30+
./gradlew spotlessCheck
31+
```
32+
33+
The CI pipeline will fail if code is not properly formatted.
34+
35+
### 2. Copyright Headers
36+
37+
All `.kt` and `.kts` files must include the MIT license header at the top:
38+
39+
```kotlin
40+
/*
41+
* Copyright (c) 2025 Alexander Farber
42+
* SPDX-License-Identifier: MIT
43+
*
44+
* This file is part of the OpenMapView project (https://github.com/afarber/OpenMapView)
45+
*/
46+
```
47+
48+
Running `./gradlew spotlessApply` automatically adds this header to any files missing it.
49+
50+
**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.
51+
52+
The CI pipeline includes a copyright check that will fail if any Kotlin files are missing the required header.
53+
54+
## Automated Git Hooks (Recommended)
55+
56+
Git hooks can automatically check formatting and copyright headers before commits, preventing CI failures.
57+
58+
### Setup Pre-commit Hook
59+
60+
From the repository root, run:
61+
62+
```bash
63+
./scripts/setup-git-hooks.sh
64+
```
65+
66+
This installs a pre-commit hook that automatically:
67+
1. Checks code formatting with `./scripts/check-format.sh`
68+
2. Checks copyright headers with `./scripts/check-copyright.sh`
69+
3. Blocks the commit if any issues are found
70+
4. Provides instructions to run `./gradlew spotlessApply` to fix issues
71+
72+
### What Happens on Commit
73+
74+
When committing changes, the hook runs:
75+
76+
```
77+
Running pre-commit checks...
78+
79+
1. Checking code formatting...
80+
Code formatting: OK
81+
2. Checking copyright headers...
82+
Copyright headers: OK
83+
84+
All pre-commit checks passed!
85+
```
86+
87+
If issues are found, the commit is blocked and instructions are displayed.
88+
89+
**Note:** Git hooks are local and not tracked in the repository. Each developer must run the setup script after cloning.
90+
91+
## Testing Requirements
92+
93+
### Unit Tests
94+
95+
All new features and bug fixes should include unit tests.
96+
97+
Run unit tests:
98+
99+
```bash
100+
./gradlew :openmapview:test
101+
```
102+
103+
### Instrumentation Tests
104+
105+
For features requiring real Android framework APIs or rendering, add instrumentation tests.
106+
107+
Run instrumentation tests (requires emulator or device):
108+
109+
```bash
110+
./gradlew :openmapview:connectedAndroidTest
111+
```
112+
113+
## Pull Request Process
114+
115+
1. Fork the repository
116+
2. Create a feature branch from `main`
117+
3. Make changes following the code quality requirements
118+
4. Run `./gradlew spotlessApply` before committing
119+
5. Ensure all tests pass locally
120+
6. Push changes and create a pull request
121+
7. CI must pass (formatting, tests, builds)
122+
8. Address any review feedback
123+
124+
## CI Pipeline
125+
126+
The CI pipeline runs automatically on all pull requests and includes:
127+
128+
1. **Format Check** - Verifies Spotless formatting
129+
2. **Copyright Check** - Verifies MIT license headers
130+
3. **Unit Tests** - Runs all JVM unit tests
131+
4. **Build Library** - Builds the OpenMapView AAR
132+
5. **Build Examples** - Builds all example applications
133+
134+
All checks must pass before merging.
135+
136+
## Build Commands
137+
138+
```bash
139+
# Format code
140+
./gradlew spotlessApply
141+
142+
# Check formatting
143+
./gradlew spotlessCheck
144+
145+
# Run unit tests
146+
./gradlew :openmapview:test
147+
148+
# Build library
149+
./gradlew :openmapview:assembleRelease
150+
151+
# Build all examples
152+
./gradlew assembleDebug
153+
154+
# Run instrumentation tests
155+
./gradlew :openmapview:connectedAndroidTest
156+
```
157+
158+
## Questions or Issues?
159+
160+
For questions about contributing, open an issue on GitHub: https://github.com/afarber/OpenMapView/issues
161+

scripts/check-copyright.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
3+
# Check for missing MIT copyright headers in Kotlin files
4+
# Returns 0 if all files have headers, 1 if any are missing
5+
6+
MISSING_FILES=()
7+
8+
while IFS= read -r file; do
9+
if ! grep -q "SPDX-License-Identifier: MIT" "$file"; then
10+
MISSING_FILES+=("$file")
11+
fi
12+
done < <(find . -type f \( -name "*.kt" -o -name "*.kts" \) \
13+
-not -path "*/build/*" \
14+
-not -path "*/.gradle/*")
15+
16+
if [ ${#MISSING_FILES[@]} -gt 0 ]; then
17+
echo ""
18+
echo "ERROR: The following files are missing the MIT copyright header:"
19+
echo ""
20+
for file in "${MISSING_FILES[@]}"; do
21+
echo " - $file"
22+
done
23+
echo ""
24+
echo "Required header format:"
25+
echo "/*"
26+
echo " * Copyright (c) 2025 Alexander Farber"
27+
echo " * SPDX-License-Identifier: MIT"
28+
echo " *"
29+
echo " * This file is part of the OpenMapView project (https://github.com/afarber/OpenMapView)"
30+
echo " */"
31+
echo ""
32+
echo "Run './gradlew spotlessApply' to automatically add headers."
33+
echo ""
34+
exit 1
35+
fi
36+
37+
echo "All Kotlin files have proper copyright headers."
38+
exit 0

scripts/check-format.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
3+
# Check code formatting with Spotless
4+
# Returns 0 if formatting is correct, 1 if issues are found
5+
6+
echo "Checking code formatting with Spotless..."
7+
8+
./gradlew spotlessCheck
9+
10+
if [ $? -ne 0 ]; then
11+
echo ""
12+
echo "Code formatting check failed!"
13+
echo "Run './gradlew spotlessApply' to fix formatting issues."
14+
echo ""
15+
exit 1
16+
fi
17+
18+
echo "Code formatting is correct."
19+
exit 0

scripts/setup-git-hooks.sh

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/bin/bash
2+
3+
# Setup Git hooks for OpenMapView
4+
# This script installs a pre-commit hook that checks code formatting and copyright headers
5+
6+
HOOKS_DIR=".git/hooks"
7+
HOOK_FILE="$HOOKS_DIR/pre-commit"
8+
9+
# Check if .git directory exists
10+
if [ ! -d ".git" ]; then
11+
echo "Error: .git directory not found. Run this script from the repository root."
12+
exit 1
13+
fi
14+
15+
# Create hooks directory if it doesn't exist
16+
mkdir -p "$HOOKS_DIR"
17+
18+
# Create pre-commit hook
19+
cat > "$HOOK_FILE" << 'EOF'
20+
#!/bin/bash
21+
22+
echo "Running pre-commit checks..."
23+
echo ""
24+
25+
# Check code formatting
26+
echo "1. Checking code formatting..."
27+
./scripts/check-format.sh > /dev/null 2>&1
28+
29+
if [ $? -ne 0 ]; then
30+
echo ""
31+
echo "Code formatting check failed!"
32+
echo "Run './gradlew spotlessApply' to fix formatting issues."
33+
echo ""
34+
exit 1
35+
fi
36+
37+
echo " Code formatting: OK"
38+
39+
# Check copyright headers
40+
echo "2. Checking copyright headers..."
41+
./scripts/check-copyright.sh > /dev/null 2>&1
42+
43+
if [ $? -ne 0 ]; then
44+
echo ""
45+
echo "Copyright header check failed!"
46+
echo "Run './gradlew spotlessApply' to fix issues."
47+
echo ""
48+
exit 1
49+
fi
50+
51+
echo " Copyright headers: OK"
52+
echo ""
53+
echo "All pre-commit checks passed!"
54+
EOF
55+
56+
# Make hook executable
57+
chmod +x "$HOOK_FILE"
58+
59+
echo "Git hooks installed successfully!"
60+
echo ""
61+
echo "Pre-commit hook will now:"
62+
echo " - Check code formatting before each commit"
63+
echo " - Check copyright headers on all Kotlin files"
64+
echo " - Block commits if issues are found"
65+
echo " - Prompt to run './gradlew spotlessApply' to fix issues"
66+
echo ""
67+
echo "To bypass the hook (not recommended), use: git commit --no-verify"

0 commit comments

Comments
 (0)