Răsfoiți Sursa

Merge branch 'feature/codeowners' into 'master'

add initial CODEOWNERS file

Closes IDF-308

See merge request espressif/esp-idf!9928
Ivan Grokhotkov 5 ani în urmă
părinte
comite
390a90ff7f
4 a modificat fișierele cu 249 adăugiri și 0 ștergeri
  1. 107 0
      .gitlab/CODEOWNERS
  2. 5 0
      tools/ci/config/pre_check.yml
  3. 1 0
      tools/ci/executable-list.txt
  4. 136 0
      tools/codeowners.py

+ 107 - 0
.gitlab/CODEOWNERS

@@ -0,0 +1,107 @@
+* @esp-idf-codeowners/other
+
+components/app_trace                @esp-idf-codeowners/tools
+components/app_update               @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
+components/asio                     @esp-idf-codeowners/network
+components/bootloader*/**           @esp-idf-codeowners/system @esp-idf-codeowners/security
+components/bt                       @esp-idf-codeowners/bluetooth
+components/cbor                     @esp-idf-codeowners/app-utilities
+components/coap                     @esp-idf-codeowners/app-utilities
+components/console                  @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
+components/cxx                      @esp-idf-codeowners/system
+components/driver                   @esp-idf-codeowners/peripherals
+components/efuse                    @esp-idf-codeowners/system
+components/esp32*                   @esp-idf-codeowners/system
+components/esp_adc_cal              @esp-idf-codeowners/peripherals
+components/esp_common               @esp-idf-codeowners/system
+components/esp_eth                  @esp-idf-codeowners/network
+components/esp_event                @esp-idf-codeowners/system
+components/esp_gdbstub              @esp-idf-codeowners/tools
+components/esp_hid                  @esp-idf-codeowners/bluetooth
+components/esp_http_client          @esp-idf-codeowners/app-utilities
+components/esp_http_server          @esp-idf-codeowners/app-utilities
+components/esp_https_ota            @esp-idf-codeowners/app-utilities
+components/esp_https_server         @esp-idf-codeowners/app-utilities
+components/esp_ipc                  @esp-idf-codeowners/system
+components/esp_local_ctrl           @esp-idf-codeowners/app-utilities
+components/esp_netif                @esp-idf-codeowners/network
+components/esp_ringbuf              @esp-idf-codeowners/system
+components/esp_rom                  @esp-idf-codeowners/system
+components/esp_serial_slave_link    @esp-idf-codeowners/peripherals
+components/esp_system               @esp-idf-codeowners/system
+components/esp_timer                @esp-idf-codeowners/system
+components/esp-tls                  @esp-idf-codeowners/app-utilities
+components/esp_websocket_client     @esp-idf-codeowners/network
+components/esp_wifi                 @esp-idf-codeowners/wifi
+components/espcoredump              @esp-idf-codeowners/tools
+components/esptool_py               @esp-idf-codeowners/tools
+components/expat                    @esp-idf-codeowners/app-utilities
+components/fatfs                    @esp-idf-codeowners/storage
+components/freemodbus               @esp-idf-codeowners/peripherals
+components/freertos                 @esp-idf-codeowners/system
+components/heap                     @esp-idf-codeowners/system
+components/idf_test                 @esp-idf-codeowners/ci
+components/jsmn                     @esp-idf-codeowners/app-utilities
+components/json                     @esp-idf-codeowners/app-utilities
+components/libsodium                @esp-idf-codeowners/security
+components/log                      @esp-idf-codeowners/system
+components/lwip                     @esp-idf-codeowners/lwip
+components/mbedtls                  @esp-idf-codeowners/app-utilities @esp-idf-codeowners/security
+components/mdns                     @esp-idf-codeowners/network
+components/mqtt                     @esp-idf-codeowners/network
+components/newlib                   @esp-idf-codeowners/system @esp-idf-codeowners/tools
+components/nghttp                   @esp-idf-codeowners/app-utilities
+components/nvs_flash                @esp-idf-codeowners/storage
+components/openssl                  @esp-idf-codeowners/network
+components/partition_table          @esp-idf-codeowners/system
+components/perfmon                  @esp-idf-codeowners/tools
+components/protobuf-c               @esp-idf-codeowners/app-utilities
+components/protocomm                @esp-idf-codeowners/app-utilities
+components/pthread                  @esp-idf-codeowners/system
+components/sdmmc                    @esp-idf-codeowners/storage
+components/soc                      @esp-idf-codeowners/peripherals
+components/spi_flash                @esp-idf-codeowners/peripherals
+components/spiffs                   @esp-idf-codeowners/storage
+components/tcp_transport            @esp-idf-codeowners/network
+components/tcpip_adapter            @esp-idf-codeowners/network
+components/tinyusb                  @esp-idf-codeowners/peripherals
+components/ulp                      @esp-idf-codeowners/system
+components/unity                    @esp-idf-codeowners/ci
+components/vfs                      @esp-idf-codeowners/storage
+components/wear_levelling           @esp-idf-codeowners/storage
+components/wifi_provisioning        @esp-idf-codeowners/app-utilities
+components/wpa_supplicant           @esp-idf-codeowners/wifi
+components/xtensa                   @esp-idf-codeowners/system
+
+docs    @esp-idf-codeowners/docs
+
+examples/**/*.py            @esp-idf-codeowners/ci @esp-idf-codeowners/tools
+
+examples/bluetooth          @esp-idf-codeowners/bluetooth
+examples/build_system       @esp-idf-codeowners/build-config
+examples/common_components  @esp-idf-codeowners/system
+examples/cxx                @esp-idf-codeowners/system
+examples/ethernet           @esp-idf-codeowners/network
+examples/get-started        @esp-idf-codeowners/system
+examples/mesh               @esp-idf-codeowners/wifi
+examples/peripherals        @esp-idf-codeowners/peripherals
+examples/protocols          @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
+examples/provisioning       @esp-idf-codeowners/app-utilities
+examples/security           @esp-idf-codeowners/security
+examples/storage            @esp-idf-codeowners/storage
+examples/system             @esp-idf-codeowners/system
+examples/wifi               @esp-idf-codeowners/wifi
+
+make    @esp-idf-codeowners/build-config
+
+tools                       @esp-idf-codeowners/tools
+tools/*_apps.py             @esp-idf-codeowners/ci
+tools/ble                   @esp-idf-codeowners/app-utilities
+tools/catch                 @esp-idf-codeowners/ci
+tools/ci                    @esp-idf-codeowners/ci
+tools/cmake                 @esp-idf-codeowners/build-config
+tools/esp_prov              @esp-idf-codeowners/app-utilities
+tools/find_build_apps       @esp-idf-codeowners/ci
+tools/kconfig*              @esp-idf-codeowners/build-config
+tools/ldgen                 @esp-idf-codeowners/build-config
+tools/mass_mfg              @esp-idf-codeowners/app-utilities

+ 5 - 0
tools/ci/config/pre_check.yml

@@ -202,3 +202,8 @@ clang_tidy_check_all:
   variables:
     BOT_NEEDS_TRIGGER_BY_NAME: 1
     BOT_LABEL_STATIC_ANALYSIS_ALL: 1
+
+check_codeowners:
+  extends: .check_job_template
+  script:
+    - tools/codeowners.py ci-check

+ 1 - 0
tools/ci/executable-list.txt

@@ -63,6 +63,7 @@ tools/ci/test_build_system_cmake.sh
 tools/ci/test_configure_ci_environment.sh
 tools/cmake/convert_to_cmake.py
 tools/cmake/run_cmake_lint.sh
+tools/codeowners.py
 tools/docker/entrypoint.sh
 tools/docker/hooks/build
 tools/esp_app_trace/logtrace_proc.py

+ 136 - 0
tools/codeowners.py

@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+#
+# Utility script for ESP-IDF developers to work with the CODEOWNERS file.
+#
+# Copyright 2020 Espressif Systems (Shanghai) PTE LTD
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse
+from collections import defaultdict
+import os
+import subprocess
+import sys
+
+CODEOWNERS_PATH = os.path.join(os.path.dirname(__file__), "..", ".gitlab", "CODEOWNERS")
+CODEOWNER_GROUP_PREFIX = "@esp-idf-codeowners/"
+
+
+def action_identify(args):
+    best_match = []
+    with open(CODEOWNERS_PATH) as f:
+        for line in f:
+            line = line.strip()
+            if not line or line.startswith("#"):
+                continue
+            tokens = line.split()
+            path_pattern = tokens[0]
+            owners = tokens[1:]
+            files = files_by_pattern(path_pattern)
+            if args.path in files:
+                best_match = owners
+    for owner in best_match:
+        print(owner)
+
+
+def files_by_pattern(pattern=None):
+    args = ["git", "ls-files"]
+    if pattern:
+        args.append(pattern)
+    idf_root = os.path.join(os.path.dirname(__file__), "..")
+    return subprocess.check_output(args, cwd=idf_root).decode("utf-8").split()
+
+
+def action_ci_check(args):
+    errors = []
+
+    def add_error(msg):
+        errors.append("Error at CODEOWNERS:{}: {}".format(line_no, msg))
+
+    files_by_owner = defaultdict(int)
+    prev_path_pattern = ""
+    with open(CODEOWNERS_PATH) as f:
+        for line_no, line in enumerate(f, start=1):
+            # Skip empty lines and comments
+            line = line.strip()
+            if not line or line.startswith("#"):
+                continue
+
+            # Each line has a form of "<path> <owners>+"
+            tokens = line.split()
+            path_pattern = tokens[0]
+            owners = tokens[1:]
+            if not owners:
+                add_error("no owners specified for {}".format(path_pattern))
+
+            # Check that the file is sorted by path patterns
+            path_pattern_for_cmp = path_pattern.replace("-", "_")  # ignore difference between _ and - for ordering
+            if path_pattern_for_cmp < prev_path_pattern:
+                add_error("file is not sorted: {} < {}".format(path_pattern_for_cmp, prev_path_pattern))
+            prev_path_pattern = path_pattern_for_cmp
+
+            # Check that the pattern matches at least one file
+            files = files_by_pattern(path_pattern)
+            if not files:
+                add_error("no files matched by pattern {}".format(path_pattern))
+
+            # Count the number of files per owner
+            for o in owners:
+                # Sanity-check the owner group name
+                if not o.startswith(CODEOWNER_GROUP_PREFIX):
+                    add_error("owner {} doesn't start with {}".format(o, CODEOWNER_GROUP_PREFIX))
+                files_by_owner[o] += len(files)
+
+    owners_sorted = sorted([(owner, cnt) for owner, cnt in files_by_owner.items()], key=lambda p: p[0])
+    print("File count per owner (not including submodules):")
+    for owner, cnt in owners_sorted:
+        print("{}: {} files".format(owner, cnt))
+
+    if not errors:
+        print("No errors found.")
+    else:
+        print("Errors found!")
+        for e in errors:
+            print(e)
+        raise SystemExit(1)
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        sys.argv[0], description="Internal helper script for working with the CODEOWNERS file."
+    )
+    subparsers = parser.add_subparsers(dest="action")
+    identify = subparsers.add_parser(
+        "identify",
+        help="Lists the owners of the specified path within IDF."
+        "This command doesn't support files inside submodules, or files not added to git repository.",
+    )
+    identify.add_argument("path", help="Path of the file relative to the root of the repository")
+    subparsers.add_parser(
+        "ci-check",
+        help="Check CODEOWNERS file: every line should match at least one file, sanity-check group names, "
+        "check that the file is sorted by paths",
+    )
+    args = parser.parse_args()
+
+    if args.action is None:
+        parser.print_help()
+        parser.exit(1)
+
+    action_func_name = "action_" + args.action.replace("-", "_")
+    action_func = globals()[action_func_name]
+    action_func(args)
+
+
+if __name__ == "__main__":
+    main()