blob: 1b68dda566dc384fa6375fa141f14d3fcc5bd46b [file] [log] [blame]
Anthony DiGirolamofb41f922021-03-02 14:32:01 -08001#!/usr/bin/env python3
2# Copyright 2021 The Pigweed Authors
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may not
5# use this file except in compliance with the License. You may obtain a copy of
6# the License at
7#
8# https://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations under
14# the License.
15"""Example presubmit check script."""
16
17import argparse
18import logging
19import os
20from pathlib import Path
21import re
22import sys
23
24try:
25 import pw_cli.log
26except ImportError:
27 print('ERROR: Activate the environment before running presubmits!',
28 file=sys.stderr)
29 sys.exit(2)
30
31import pw_presubmit
Rob Mohr7f2e41a2021-10-21 14:09:10 -070032from pw_presubmit import (
33 build,
34 cli,
35 cpp_checks,
36 format_code,
37 git_repo,
38 inclusive_language,
39 install_hook,
40 python_checks,
41 PresubmitContext,
42)
Anthony DiGirolamofb41f922021-03-02 14:32:01 -080043
44_LOG = logging.getLogger(__name__)
45
46# Set up variables for key project paths.
47try:
48 PROJECT_ROOT = Path(os.environ['PIGWEED_EXPERIMENTAL_ROOT'])
49except KeyError:
50 print(
51 'ERROR: The presubmit checks must be run in the sample project\'s root'
52 ' directory',
53 file=sys.stderr)
54 sys.exit(2)
55
56PIGWEED_ROOT = PROJECT_ROOT / 'third_party' / 'pigweed'
57REPOS = (
58 PROJECT_ROOT,
59 PIGWEED_ROOT,
60 PROJECT_ROOT / 'third_party' / 'nanopb',
61)
62
Anthony DiGirolamofb41f922021-03-02 14:32:01 -080063# Rerun the build if files with these extensions change.
64_BUILD_EXTENSIONS = frozenset(
65 ['.rst', '.gn', '.gni', *format_code.C_FORMAT.extensions])
66
67
68#
69# Presubmit checks
70#
71def default_build(ctx: PresubmitContext):
72 """Creates a default build."""
Rob Mohr9c4c7672022-08-18 14:49:15 +000073 build.gn_gen(ctx)
Rob Mohrfa6c95f2022-08-16 23:26:11 +000074 build.ninja(ctx)
Anthony DiGirolamofb41f922021-03-02 14:32:01 -080075
76
77def check_for_git_changes(_: PresubmitContext):
78 """Checks that repositories have all changes commited."""
79 checked_repos = (PIGWEED_ROOT, *REPOS)
80 changes = [r for r in checked_repos if git_repo.has_uncommitted_changes(r)]
81 for repo in changes:
82 _LOG.error('There are uncommitted changes in the %s repo!', repo.name)
83 if changes:
84 _LOG.warning(
85 'Commit or stash pending changes before running the presubmit.')
86 raise pw_presubmit.PresubmitFailure
87
88
89# Avoid running some checks on certain paths.
90PATH_EXCLUSIONS = (
91 re.compile(r'^external/'),
92 re.compile(r'^third_party/'),
93 re.compile(r'^vendor/'),
94)
95
Anthony DiGirolamofb41f922021-03-02 14:32:01 -080096#
97# Presubmit check programs
98#
Rob Mohr7f2e41a2021-10-21 14:09:10 -070099OTHER_CHECKS = (
100 build.gn_gen_check,
101 inclusive_language.inclusive_language.with_filter(exclude=PATH_EXCLUSIONS),
102)
Rob Mohrd5e996c2021-05-24 11:51:16 -0700103
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800104QUICK = (
105 # List some presubmit checks to run
106 default_build,
107 # Use the upstream formatting checks, with custom path filters applied.
Wyatt Hepler87969a82022-07-29 00:26:00 +0000108 format_code.presubmit_checks(),
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800109)
Rob Mohrd5e996c2021-05-24 11:51:16 -0700110
Rob Mohrf831e412021-08-03 13:56:59 -0700111LINTFORMAT = (
112 # Use the upstream formatting checks, with custom path filters applied.
Wyatt Hepler87969a82022-07-29 00:26:00 +0000113 format_code.presubmit_checks(),
114 python_checks.gn_python_lint,
115 cpp_checks.pragma_once,
Rob Mohrf831e412021-08-03 13:56:59 -0700116)
117
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800118FULL = (
Wyatt Hepler87969a82022-07-29 00:26:00 +0000119 cpp_checks.pragma_once,
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800120 QUICK, # Add all checks from the 'quick' program
121 # Use the upstream Python checks, with custom path filters applied.
Wyatt Hepler87969a82022-07-29 00:26:00 +0000122 python_checks.gn_python_check,
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800123)
Rob Mohrd5e996c2021-05-24 11:51:16 -0700124
125PROGRAMS = pw_presubmit.Programs(
126 quick=QUICK,
127 full=FULL,
Rob Mohrf831e412021-08-03 13:56:59 -0700128 lintformat=LINTFORMAT,
Rob Mohrd5e996c2021-05-24 11:51:16 -0700129 other_checks=OTHER_CHECKS,
130)
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800131
132
Wyatt Hepler87969a82022-07-29 00:26:00 +0000133def run(install: bool, exclude: list, **presubmit_args) -> int:
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800134 """Process the --install argument then invoke pw_presubmit."""
135
136 # Install the presubmit Git pre-push hook, if requested.
137 if install:
Rob Mohr7f2e41a2021-10-21 14:09:10 -0700138 install_hook.install_hook(__file__, 'pre-push', ['--base', 'HEAD~'],
139 git_repo.root())
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800140 return 0
141
Wyatt Hepler87969a82022-07-29 00:26:00 +0000142 exclude.extend(PATH_EXCLUSIONS)
143 return cli.run(root=PROJECT_ROOT, exclude=exclude, **presubmit_args)
Anthony DiGirolamofb41f922021-03-02 14:32:01 -0800144
145
146def main() -> int:
147 """Run the presubmit checks for this repository."""
148 parser = argparse.ArgumentParser(description=__doc__)
149 cli.add_arguments(parser, PROGRAMS, 'quick')
150
151 # Define an option for installing a Git pre-push hook for this script.
152 parser.add_argument(
153 '--install',
154 action='store_true',
155 help='Install the presubmit as a Git pre-push hook and exit.')
156
157 return run(**vars(parser.parse_args()))
158
159
160if __name__ == '__main__':
161 pw_cli.log.install(logging.INFO)
162 sys.exit(main())