diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4832e3..310900e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,15 +8,13 @@ jobs: lint: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 - - name: Check SPDX identifiers - run: ./scripts/lint/spdx.sh - - name: Check indentation - run: ./scripts/lint/indent.sh + - uses: actions/checkout@v3 + + - name: Check SPDX tags + run: ./scripts/lint/01-spdx-tags.sh - name: Check formatting - run: ./scripts/clang-format.sh - continue-on-error: true + run: ./scripts/lint/02-clang-format.sh tool: strategy: @@ -27,7 +25,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install dependencies run: ./scripts/deps.sh @@ -90,7 +88,7 @@ jobs: board: oryp9 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install dependencies run: ./scripts/deps.sh diff --git a/Makefile b/Makefile index 47a2ac5..a4a0a0c 100644 --- a/Makefile +++ b/Makefile @@ -69,6 +69,10 @@ include $(ARCH_DIR)/toolchain.mk # The architecture defines build targets, no more is required endif -# Target to remove build artifacts +.PHONY: clean clean: rm -rf $(obj) + +.PHONY: lint +lint: + ./scripts/lint/lint.sh diff --git a/scripts/lint/01-spdx-tags.sh b/scripts/lint/01-spdx-tags.sh new file mode 100755 index 0000000..e9136e8 --- /dev/null +++ b/scripts/lint/01-spdx-tags.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only + +# Check that all files have a SPDX license identifier +# TODO: Validate license tags against a whitelist + +LINT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) +. "$LINT_DIR/util.sh" + +echo -n "Checking for SPDX tags..." + +EXCLUDES=( + # Ignore license files + ':!:LICENSE' + ':!:**/LICENSE' + # Ignore cargo files + ':!:**/Cargo.lock' + ':!:**/Cargo.toml' + ':!:rust-toolchain.toml' + # Ignore text files + ':!:*.md' + ':!:*.txt' + # Ignore dotfiles + ':!:\.*' + ':!:**/\.*' +) + +needs_tag=() + +for file in $(git ls-files "${EXCLUDES[@]}"); do + # Only check regular files + if [[ ! -f "$file" ]]; then + continue + fi + + # SPDX must appear at head of file + if ! head "$file" | grep -q 'SPDX-License-Identifier:'; then + needs_tag+=("$file") + fi +done + +if [[ "${#needs_tag[@]}" != "0" ]]; then + failed + + for file in "${needs_tag[@]}"; do + echo "- $file" + done + + exit 1 +fi + +passed diff --git a/scripts/lint/02-clang-format.sh b/scripts/lint/02-clang-format.sh new file mode 100755 index 0000000..56902af --- /dev/null +++ b/scripts/lint/02-clang-format.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only + +# Check if any C files or headers need to be formatted. + +LINT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) +. "$LINT_DIR/util.sh" + +echo -n "Checking C style..." + +if ! command -v clang-format > /dev/null; then + skipped "clang-format not found" + exit 0 +fi + +readarray -t FILES < <(git ls-files '*.c' '*.h') + +FMT_OPTS=( + "-style=file" + "--fallback-style=none" + "--dry-run" + "--Werror" +) + +# NOTE: It is too slow to run clang-format on every file individually to report +# which ones fail. Leave it up to the user to apply formatting via `make fmt`. + +_output=$(clang-format "${FMT_OPTS[@]}" "${FILES[@]}" 2>&1) +if [[ $_output != "" ]]; then + failed + exit 1 +fi + +passed diff --git a/scripts/lint/indent.sh b/scripts/lint/indent.sh deleted file mode 100755 index 553e79f..0000000 --- a/scripts/lint/indent.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: GPL-3.0-only -# Check files do not use tabs for indentation - -git ls-files '*.[c\|h\|rs\|sh]' | xargs grep --line-number $'^\s*\t' && exit 1 -exit 0 diff --git a/scripts/lint/lint.sh b/scripts/lint/lint.sh new file mode 100755 index 0000000..d69358f --- /dev/null +++ b/scripts/lint/lint.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only + +# Run all lints. + +LINT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd) +LINTS=$(find "$LINT_DIR" -type f -name "[0-9][0-9]-*" | sort) +FAILED=0 + +for lint in $LINTS; do + $lint || FAILED=1 +done + +[[ "$FAILED" = "0" ]] || exit 1 diff --git a/scripts/lint/spdx.sh b/scripts/lint/spdx.sh deleted file mode 100755 index 3ad4c84..0000000 --- a/scripts/lint/spdx.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# SPDX-License-Identifier: GPL-3.0-only -# Check that all files have a SPDX license identifier - -set -e - -# File patterns to check -FILE_TYPES=( - '*.c' - '*.h' - '*.mk' - '*.rs' - '*.sh' - 'Makefile' -) - -ret=0 - -for ft in "${FILE_TYPES[@]}"; do - files=$(git ls-files "$ft") - for f in ${files}; do - # Skip empty files - if [[ "$(wc -l < "$f")" = "0" ]]; then - continue - fi - - # SPDX must appear at head of file - if ! head "$f" | grep -q 'SPDX-License-Identifier:'; then - echo "$f: Missing SPDX identifier" - ret=1 - fi - done -done - -exit ${ret} diff --git a/scripts/lint/util.sh b/scripts/lint/util.sh new file mode 100644 index 0000000..f29dd2a --- /dev/null +++ b/scripts/lint/util.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: GPL-3.0-only + +passed() { + echo -e "\x1B[32mPASSED\x1B[0m" +} + +skipped() { + local reason=$1 + echo -e "\x1B[33mSKIPPED\x1B[0m ($reason)" +} + +failed() { + echo -e "\x1B[31mFAILED\x1B[0m" +}