1#!/usr/bin/env python3 2 3# 4# Copyright 2025, The Android Open Source Project 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17# 18 19"""Script that enforces Relnote: any file path in the commit contains module substring""" 20 21import argparse 22import os.path 23import re 24import sys 25 26ERROR_RELNOTE_REQUIRED = """ 27RELNOTE: is required for commits that contain changes in {} 28 29Please add a RELNOTE to the commit or RELNOTE: N/A if a release note is not applicable to the 30commit. 31 32A RELNOTE is required for all commits that changes the release artifacts. 33 34A RELNOTE can be N/A for commit messages that only effects tooling, documentation, directory 35structure, etc., but not the release artifacts. 36""" 37 38def main(args=None): 39 parser = argparse.ArgumentParser( 40 prog="requirerelnote", 41 description="Check if RELNOTE is required") 42 parser.add_argument('--file', nargs='*') 43 parser.add_argument('--module') 44 parser.add_argument('--commit') 45 46 args = parser.parse_args() 47 48 source_files = [f for f in args.file 49 if (not "buildSrc/" in f and 50 "/src/main/" in f or 51 "/src/commonMain/" in f or 52 "/src/androidMain/" in f)] 53 module_files = [f for f in source_files 54 if (args.module in f)] 55 56 if not module_files: 57 sys.exit(0) 58 59 """Following copied (with minor edits) from hooks.py:check_commit_msg_relnote_for_current_txt""" 60 """Check if the commit contain the 'Relnote:' stanza.""" 61 field = 'Relnote' 62 regex = fr'^{field}: .+$' 63 check_re = re.compile(regex, re.IGNORECASE) 64 65 found = [] 66 for line in args.commit.splitlines(): 67 if check_re.match(line): 68 found.append(line) 69 70 if not found: 71 print(ERROR_RELNOTE_REQUIRED.format(args.module)) 72 sys.exit(1) 73 74 sys.exit(0) 75 76if __name__ == '__main__': 77 main()