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