go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/PRESUBMIT.py (about) 1 # Copyright 2017 The LUCI Authors. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 """Top-level presubmit script. 16 17 See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for 18 details on the presubmit API built into depot_tools. 19 """ 20 21 import os 22 import re 23 import sys 24 25 USE_PYTHON3 = True 26 27 # Note that the URL http://www.apache.org/licenses/LICENSE-2.0 28 # is not indented. 29 COPYRIGHT_TEMPLATE = """ 30 Copyright YEARPATTERN The LUCI Authors. 31 32 Licensed under the Apache License, Version 2.0 (the "License"); 33 you may not use this file except in compliance with the License. 34 You may obtain a copy of the License at 35 36 http://www.apache.org/licenses/LICENSE-2.0 37 38 Unless required by applicable law or agreed to in writing, software 39 distributed under the License is distributed on an "AS IS" BASIS, 40 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 41 See the License for the specific language governing permissions and 42 limitations under the License. 43 """.strip() 44 45 def header(input_api): 46 """Returns the expected license header regexp for this project.""" 47 current_year = int(input_api.time.strftime('%Y')) 48 allowed_years = (str(s) for s in reversed(range(2011, current_year + 1))) 49 years_re = '(' + '|'.join(allowed_years) + ')' 50 # The regex below should accept the following comment styles at the beginning of the line: 51 # 1) # -- Python, Bash 52 # 2) // -- Go, Javascript 53 # 3) /* -- CSS 54 # See comments on https://chromium-review.googlesource.com/c/infra/luci/luci-go/+/4202089 for details. 55 lines = [ 56 (r'[#/*]?[#/*]?[ \t]*' + re.escape(line)) if line else '.*?' 57 for line in COPYRIGHT_TEMPLATE.splitlines() 58 ] 59 lines[0] = lines[0].replace('YEARPATTERN', years_re) 60 return '\n'.join(lines) + '(?: \*/)?\n' 61 62 63 def source_file_filter(input_api): 64 """Returns filter that selects source code files only.""" 65 files_to_skip = list(input_api.DEFAULT_FILES_TO_SKIP) + [ 66 r'.+/bootstrap/.*', # third party 67 r'.+/jquery/.*', # third party 68 r'.+/pb\.discovery\.go$', 69 r'.+/pb\.discovery_test\.go$', 70 r'.+\.pb\.go$', 71 r'.+\.pb\.ts$', 72 r'.+\.pb\.validate\.go$', 73 r'.+\.pb_test\.go$', 74 r'.+_dec\.go$', 75 r'.+.mock\.go$', 76 r'.+_mux\.go$', 77 r'.+_string\.go$', 78 r'.+gae\.py$', # symlinks from outside 79 r'common/api/internal/gensupport/.*', # third party 80 r'common/goroutine/goroutine_id.go', 81 r'common/terminal/.*', # third party 82 r'server/static/bower_components/.*', # third party 83 r'server/static/upload/bower_components/.*', # third party 84 ] 85 files_to_check = list(input_api.DEFAULT_FILES_TO_CHECK) + [ 86 r'.+\.go$', 87 ] 88 return lambda x: input_api.FilterSourceFile( 89 x, files_to_check=files_to_check, files_to_skip=files_to_skip) 90 91 92 def CheckGoModTidy(input_api, output_api): 93 root = input_api.change.RepositoryRoot() 94 return input_api.RunTests([ 95 input_api.Command( 96 name='go mod tidy', 97 cmd=[ 98 input_api.python3_executable, 99 os.path.join(root, 'scripts', 'check_go_mod_tidy.py'), 100 root, 101 ], 102 kwargs={}, 103 message=output_api.PresubmitError) 104 ]) 105 106 107 def CheckGoLinterConfigs(input_api, output_api): 108 root = input_api.change.RepositoryRoot() 109 return input_api.RunTests([ 110 input_api.Command( 111 name='regen_golangci_config.py --check', 112 cmd=[ 113 input_api.python3_executable, 114 os.path.join(root, 'scripts', 'regen_golangci_config.py'), 115 '--check', 116 ], 117 kwargs={}, 118 message=output_api.PresubmitError) 119 ]) 120 121 122 def CheckGoogleapisInSync(input_api, output_api): 123 root = input_api.change.RepositoryRoot() 124 return input_api.RunTests([ 125 input_api.Command( 126 name='Assert googleapis librariy is in sync', 127 cmd=[ 128 input_api.python3_executable, 129 os.path.join(root, 'scripts', 'check_googleapis_in_sync.py'), 130 root, 131 ], 132 kwargs={}, 133 message=output_api.PresubmitError) 134 ]) 135 136 137 def CommonChecks(input_api, output_api): 138 results = [] 139 results.extend( 140 input_api.canned_checks.CheckChangeHasNoStrayWhitespace( 141 input_api, output_api, 142 source_file_filter=source_file_filter(input_api))) 143 results.extend( 144 input_api.canned_checks.CheckLicense( 145 input_api, output_api, header(input_api), 146 source_file_filter=source_file_filter(input_api))) 147 if os.environ.get('GO111MODULE') != 'off': 148 results.extend(CheckGoModTidy(input_api, output_api)) 149 results.extend(CheckGoLinterConfigs(input_api, output_api)) 150 results.extend(CheckGoogleapisInSync(input_api, output_api)) 151 return results 152 153 154 def CheckChangeOnUpload(input_api, output_api): 155 return CommonChecks(input_api, output_api) 156 157 158 def CheckChangeOnCommit(input_api, output_api): 159 results = CommonChecks(input_api, output_api) 160 results.extend(input_api.canned_checks.CheckChangeHasDescription( 161 input_api, output_api)) 162 results.extend(input_api.canned_checks.CheckDoNotSubmitInDescription( 163 input_api, output_api)) 164 results.extend(input_api.canned_checks.CheckDoNotSubmitInFiles( 165 input_api, output_api)) 166 return results