diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 000000000..2ecb9230f --- /dev/null +++ b/.codespellrc @@ -0,0 +1,3 @@ +[codespell] +ignore-regex = _ +ignore-words-list = ot, bootup, requestor, pase diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 05600d30f..4b93aa11b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,5 @@ stages: + - check_typos - cleanup - docker_build - build @@ -236,6 +237,10 @@ build_image: image: ${DOCKER_IMAGE_NAME}:chip_${CHIP_SHORT_HASH}_idf_${IDF_CHECKOUT_REF} rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "push" || $CI_COMMIT_BRANCH == "main" + needs: + - job: build_image + optional: true + - job: check_typos tags: - build # runner: `sudo mkdir -p /cache/matter_build/` @@ -278,9 +283,6 @@ build_image: build_esp_matter_examples_pytest_C6_idf_v5_1: extends: - .build_examples_template - needs: - - job: build_image - optional: true artifacts: paths: - "examples/**/build*/size.json" @@ -301,9 +303,6 @@ build_esp_matter_examples_pytest_C6_idf_v5_1: build_esp_matter_examples_pytest_H2_idf_v5_1: extends: - .build_examples_template - needs: - - job: build_image - optional: true artifacts: paths: - "examples/**/build*/size.json" @@ -341,9 +340,6 @@ build_esp_matter_examples_pytest_H2_idf_v5_1: build_esp_matter_examples_pytest_C2_idf_v5_1: extends: - .build_examples_template - needs: - - job: build_image - optional: true artifacts: paths: - "examples/**/build*/size.json" @@ -372,9 +368,6 @@ build_esp_matter_examples_pytest_C2_idf_v5_1: build_ext_plat_c6_thread_controller_examples: extends: - .build_examples_template - needs: - - job: build_image - optional: true script: - *build_external_platform_example - *build_esp32c6_thread_example @@ -384,9 +377,6 @@ build_ext_plat_c6_thread_controller_examples: build_zap_light_example: extends: - .build_examples_template - needs: - - job: build_image - optional: true script: - cd ${ESP_MATTER_PATH}/connectedhomeip/connectedhomeip - source ./scripts/activate.sh @@ -398,9 +388,6 @@ build_zap_light_example: build_esp_matter_examples: extends: - .build_examples_template - needs: - - job: build_image - optional: true artifacts: paths: - "examples/**/build*/size.json" @@ -446,9 +433,6 @@ build_nopytest_remaining_examples_manual: - if: $CI_COMMIT_BRANCH != "main" when: manual allow_failure: true - needs: - - job: build_image - optional: true artifacts: paths: - "examples/**/build*/size.json" @@ -473,9 +457,6 @@ build_esp_matter_examples_pytest_C3_idf_v4_4: extends: - .build_examples_template image: ${DOCKER_IMAGE_NAME}:chip_${CHIP_SHORT_HASH}_idf_${IDF_CHECKOUT_REF} - needs: - - job: build_image - optional: true artifacts: paths: - "examples/**/build*/size.json" @@ -590,6 +571,7 @@ build_managed_component_light: needs: - job: build_image optional: true + - job: check_typos script: - cd ${ESP_MATTER_PATH}/examples/managed_component_light - idf.py set-target esp32c3 @@ -608,6 +590,7 @@ build_esp_rainmaker_apps: needs: - job: build_image optional: true + - job: check_typos artifacts: paths: @@ -647,6 +630,8 @@ build_docs: - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_COMMIT_BRANCH == "main" || $CI_PIPELINE_SOURCE == "push" tags: - build + needs: + - job: check_typos variables: ESP_DOCS_LATEST_BRANCH_NAME: "main" artifacts: @@ -708,3 +693,18 @@ deploy_docs_production: DOCS_DEPLOY_SERVER_USER: "$DOCS_PROD_SERVER_USER" DOCS_DEPLOY_PATH: "$DOCS_PROD_PATH" DOCS_DEPLOY_URL_BASE: "https://$DOCS_PROD_SERVER/$DOCS_PROD_PATH" + +check_typos: + image: $CI_DOCKER_REGISTRY/esp-env-v6.0:1 + stage: check_typos + script: + - pip install codespell + - git fetch origin main + - | + FILES=$(git diff --name-only origin/main...HEAD) + echo "change files: $FILES" + if [ -n "$FILES" ]; then + ./tools/check_typos.sh $FILES + fi + tags: + - build diff --git a/docs/conf_common.py b/docs/conf_common.py index 4948da03d..9d74a5f69 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -62,7 +62,7 @@ versions_url = '_static/esp_sdk_matter_version.js' # Final PDF filename will contains target and version pdf_file_prefix = u'esp-matter' -# Disable index in LaTeX output, as it's not rendered correctly +# Disable index in Latex output, as it's not rendered correctly latex_elements = { 'printindex': '', 'makeindex': '', diff --git a/tools/check_typos.sh b/tools/check_typos.sh new file mode 100755 index 000000000..2c2e6aaca --- /dev/null +++ b/tools/check_typos.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# Usage: tools/check_typos.sh [source_file_or_directory] ... + +CODESPELL_SKIP_LIST=() +ERROR_FOUND=0 + +parse_codespellrc_skips() { + if [ -f .codespellrc ]; then + local skip_files + skip_files=$(grep -E "^skip\s*=" .codespellrc | cut -d '=' -f2 | tr -d ' ') + IFS=',' read -ra CODESPELL_SKIP_LIST <<< "$skip_files" + fi +} + +should_skip_file() { + local file_path="$1" + for pattern in "${CODESPELL_SKIP_LIST[@]}"; do + if [[ "$file_path" == $pattern* ]]; then + return 0 + fi + done + return 1 +} + +process_file() { + local SRC_FILE="$1" + cat "$SRC_FILE" | \ + python3 -c " +import sys, re +ignore_directive = re.compile(r\"[^\w\s]\s*codespell:ignore\b\") +def split_line(line): + if ignore_directive.search(line): + return line.rstrip() + tokens = re.findall(r\"\b[\w']+\b\", line) + result = [] + for token in tokens: + if \"'\" in token: + result.append(token) + else: + result.extend(re.findall(r\"\d+[a-zA-Z]+|[A-Z]+(?=[A-Z][a-z])|[A-Z]?[a-z]+|[A-Z]+\", token)) + return \" \".join(result) +for line in sys.stdin: + print(split_line(line)) +" | codespell --check-hidden --stdin-single-line -q 32 - 2>&1 | sed "s|^|$SRC_FILE: |" + if [ "${PIPESTATUS[2]}" -ne 0 ]; then + ERROR_FOUND=1 + fi +} + +is_valid_file() { + local file="$1" + + case "$file" in + *.c|*.h|*.cpp|*.py|*.txt|*.md|*.yml|*.ini|*.json|*.sh|*.cmake) ;; + *) return 1 ;; + esac + + if should_skip_file "$file"; then + return 1 + fi + + return 0 +} + +process_directory() { + local DIR="$1" + local file + + find "$DIR" -type f | while read -r file; do + if is_valid_file "$file"; then + process_file "$file" + fi + done +} + +main() { + local TARGETS=("$@") + + parse_codespellrc_skips + + if [ "$#" -eq 0 ]; then + TARGETS=(./components ./examples) + fi + + for TARGET in "${TARGETS[@]}"; do + if [ -f "$TARGET" ]; then + if is_valid_file "$TARGET"; then + process_file "$TARGET" + fi + elif [ -d "$TARGET" ]; then + process_directory "$TARGET" + else + echo "Warning: '$TARGET' is not a valid file or directory, skipping" + fi + done + + if [ "$ERROR_FOUND" == "1" ]; then + echo "Typos found" + exit 1 + fi +} + +main "$@"