Skip to content

Commit d55695f

Browse files
authored
adding pre commit hook (#1206)
Signed-off-by: Paige Patton <prubenda@redhat.com>
1 parent 71bd34b commit d55695f

File tree

2 files changed

+117
-0
lines changed

2 files changed

+117
-0
lines changed

.pre-commit-config.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
repos:
2+
- repo: local
3+
hooks:
4+
- id: check-license-header
5+
name: Check Apache 2.0 license header
6+
language: python
7+
entry: python scripts/check_license.py
8+
types: [python]
9+
exclude: ^tests/|/test_|CI/

scripts/check_license.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#!/usr/bin/env python3
2+
"""
3+
License header linter for krkn source files.
4+
5+
Checks that all non-test Python source files contain the Apache 2.0 license header.
6+
Test files (in tests/ or named test_*.py) are excluded.
7+
8+
Usage:
9+
# Check only (exit 1 if any files are missing the header)
10+
python scripts/check_license.py
11+
12+
# Auto-fix: prepend header to files that are missing it
13+
python scripts/check_license.py --fix
14+
15+
# Check specific files (e.g. from pre-commit)
16+
python scripts/check_license.py path/to/file.py [...]
17+
"""
18+
19+
import argparse
20+
import sys
21+
from pathlib import Path
22+
23+
LICENSE_HEADER = """\
24+
# Copyright 2025 The Krkn Authors
25+
#
26+
# Licensed under the Apache License, Version 2.0 (the "License");
27+
# you may not use this file except in compliance with the License.
28+
# You may obtain a copy of the License at
29+
#
30+
# http://www.apache.org/licenses/LICENSE-2.0
31+
#
32+
# Unless required by applicable law or agreed to in writing, software
33+
# distributed under the License is distributed on an "AS IS" BASIS,
34+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35+
# See the License for the specific language governing permissions and
36+
# limitations under the License."""
37+
38+
# Check for the copyright line only — allows year/author variation
39+
LICENSE_MARKER = "# Copyright 2025 The Krkn Authors"
40+
41+
REPO_ROOT = Path(__file__).parent.parent
42+
43+
44+
def is_test_file(path: Path) -> bool:
45+
parts = path.parts
46+
return "tests" in parts or path.name.startswith("test_")
47+
48+
49+
def collect_source_files() -> list[Path]:
50+
return [
51+
p
52+
for p in REPO_ROOT.rglob("*.py")
53+
if not is_test_file(p)
54+
and not any(part.startswith(".") or part in ("venv", "venv3111", "build", "dist", "__pycache__") for part in p.parts)
55+
]
56+
57+
58+
def has_license(path: Path) -> bool:
59+
try:
60+
content = path.read_text(encoding="utf-8")
61+
return LICENSE_MARKER in content
62+
except (OSError, UnicodeDecodeError):
63+
return True # skip unreadable files silently
64+
65+
66+
def add_license(path: Path) -> None:
67+
content = path.read_text(encoding="utf-8")
68+
# Preserve shebang on the first line if present
69+
if content.startswith("#!"):
70+
shebang, rest = content.split("\n", 1)
71+
path.write_text(f"{shebang}\n{LICENSE_HEADER}\n{rest}", encoding="utf-8")
72+
else:
73+
path.write_text(f"{LICENSE_HEADER}\n{content}", encoding="utf-8")
74+
75+
76+
def main() -> int:
77+
parser = argparse.ArgumentParser(description="Check/add Apache 2.0 license headers")
78+
parser.add_argument("files", nargs="*", help="Files to check (defaults to all source files)")
79+
parser.add_argument("--fix", action="store_true", help="Prepend license header to files missing it")
80+
args = parser.parse_args()
81+
82+
if args.files:
83+
paths = [Path(f) for f in args.files if not is_test_file(Path(f)) and f.endswith(".py")]
84+
else:
85+
paths = collect_source_files()
86+
87+
missing = [p for p in paths if not has_license(p)]
88+
89+
if not missing:
90+
print("All files have the license header.")
91+
return 0
92+
93+
if args.fix:
94+
for p in missing:
95+
add_license(p)
96+
print(f" fixed: {p.relative_to(REPO_ROOT)}")
97+
print(f"\nAdded license header to {len(missing)} file(s).")
98+
return 0
99+
100+
print("Missing license header in the following files:")
101+
for p in missing:
102+
print(f" {p.relative_to(REPO_ROOT)}")
103+
print(f"\nRun with --fix to add the header automatically.")
104+
return 1
105+
106+
107+
if __name__ == "__main__":
108+
sys.exit(main())

0 commit comments

Comments
 (0)