This is an automated email from the ASF dual-hosted git repository. hgruszecki pushed a commit to branch prek in repository https://gitbox.apache.org/repos/asf/iggy.git
commit 202e5d783e544c3b4c10cdf01bc20d8bc0ea8558 Author: Hubert Gruszecki <[email protected]> AuthorDate: Thu Nov 20 13:23:20 2025 +0100 feat(repo): introduce pre-commit hooks and refactor CI scripts Adds .pre-commit-config.yaml with prek-based hooks and extracts inline bash from GitHub Actions workflows into reusable scripts with --check/--fix modes. --- .github/workflows/_common.yml | 253 ++++-------------------------- .github/workflows/dependabot-licenses.yml | 2 +- .markdownlint.yml | 24 +++ .pre-commit-config.yaml | 120 ++++++++++++++ CONTRIBUTING.md | 34 ++++ foreign/cpp/.pre-commit-config.yaml | 107 ------------- justfile | 8 +- scripts/ci/license-headers.sh | 136 ++++++++++++++++ scripts/ci/licenses-list.sh | 100 ++++++++++++ scripts/ci/markdownlint.sh | 63 ++++++++ scripts/ci/shellcheck.sh | 111 +++++++++++++ scripts/{ => ci}/sync-rust-version.sh | 4 +- scripts/ci/trailing-newline.sh | 188 ++++++++++++++++++++++ scripts/ci/trailing-whitespace.sh | 187 ++++++++++++++++++++++ scripts/copy-latest-from-master.sh | 4 +- scripts/licenses-list.sh | 110 ------------- 16 files changed, 1000 insertions(+), 451 deletions(-) diff --git a/.github/workflows/_common.yml b/.github/workflows/_common.yml index f4de395e3..1595affc2 100644 --- a/.github/workflows/_common.yml +++ b/.github/workflows/_common.yml @@ -39,18 +39,7 @@ jobs: - uses: actions/checkout@v4 - name: Check Rust versions are synchronized - run: | - # Use the sync-rust-version.sh script in check mode - if ! bash scripts/sync-rust-version.sh --check; then - echo "" - echo "โ Rust versions are not synchronized!" - echo "" - echo "To fix this issue, run:" - echo " ./scripts/sync-rust-version.sh --fix" - echo "" - echo "This script will automatically update all Dockerfiles to match rust-toolchain.toml" - exit 1 - fi + run: ./scripts/ci/sync-rust-version.sh --check pr-title: name: Check PR Title @@ -121,36 +110,7 @@ jobs: - uses: actions/checkout@v4 - name: Check Apache license headers - run: | - echo "๐ Checking license headers..." - - # Pull the addlicense image - docker pull ghcr.io/google/addlicense:latest - - # Run the check - if docker run --rm -v ${{ github.workspace }}:/src -w /src \ - ghcr.io/google/addlicense:latest \ - -check -f ASF_LICENSE.txt . > missing_files.txt 2>&1; then - echo "โ All files have proper license headers" - else - file_count=$(wc -l < missing_files.txt) - echo "โ Found $file_count files missing license headers:" - echo "" - cat missing_files.txt | sed 's/^/ โข /' - echo "" - echo "๐ก Run 'addlicense -f ASF_LICENSE.txt .' to fix automatically" - - # Add to summary - echo "## โ License Headers Missing" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "The following files are missing Apache license headers:" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - cat missing_files.txt >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - echo 'Please call `just licenses-fix` to fix automatically.' >> $GITHUB_STEP_SUMMARY - - exit 1 - fi + run: ./scripts/ci/license-headers.sh --check license-list: name: Check licenses list @@ -163,9 +123,12 @@ jobs: - name: Setup Rust toolchain uses: ./.github/actions/utils/setup-rust-with-cache with: - enabled: "false" # Don't need cache for just checking licenses + enabled: "false" # Don't need cache for just checking licenses - - run: scripts/licenses-list.sh --check + - name: Install cargo-license + run: cargo install cargo-license + + - run: ./scripts/ci/licenses-list.sh --check markdown: name: Markdown lint @@ -178,37 +141,13 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '23' + node-version: "23" - name: Install markdownlint-cli run: npm install -g markdownlint-cli - name: Run markdownlint - run: | - echo "๐ Checking markdown files..." - - # Create config if it doesn't exist - if [ ! -f ".markdownlint.yml" ]; then - cat > .markdownlint.yml << 'EOF' - # Markdown lint configuration - default: true - MD013: - line_length: 120 - tables: false - MD033: - allowed_elements: [details, summary, img] - MD041: false # First line in file should be a top level heading - EOF - fi - - # Run the linter - if markdownlint '**/*.md' --ignore-path .gitignore; then - echo "โ All markdown files are properly formatted" - else - echo "โ Markdown linting failed" - echo "๐ก Run 'markdownlint **/*.md --fix' to auto-fix issues" - exit 1 - fi + run: ./scripts/ci/markdownlint.sh --check shellcheck: name: Shell scripts lint @@ -221,26 +160,12 @@ jobs: - name: Install shellcheck run: | - sudo apt-get update --yes && sudo apt-get install --yes shellcheck + SHELLCHECK_VERSION="0.11.0" + wget -qO- "https://github.com/koalaman/shellcheck/releases/download/v${SHELLCHECK_VERSION}/shellcheck-v${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | tar -xJv + sudo cp "shellcheck-v${SHELLCHECK_VERSION}/shellcheck" /usr/local/bin/ - name: Check shell scripts - run: | - echo "๐ Checking shell scripts..." - - # Find all shell scripts excluding certain directories - if find . -type f -name "*.sh" \ - -not -path "./target/*" \ - -not -path "./node_modules/*" \ - -not -path "./.git/*" \ - -not -path "./foreign/node/node_modules/*" \ - -not -path "./foreign/python/.venv/*" \ - -exec shellcheck -S warning {} +; then - echo "โ All shell scripts passed shellcheck" - else - echo "โ Shellcheck found issues in shell scripts" - echo "๐ก Fix the issues reported above" - exit 1 - fi + run: ./scripts/ci/shellcheck.sh --check trailing-whitespace: name: Check trailing whitespace @@ -251,76 +176,10 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Need full history to get diff + fetch-depth: 0 # Need full history to get diff - name: Check for trailing whitespace in changed files - run: | - echo "๐ Checking for trailing whitespace in changed files..." - - # Get list of changed files in PR - if [ "${{ github.event_name }}" = "pull_request" ]; then - git fetch --no-tags --depth=1 origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }} || true - BASE_SHA="${{ github.event.pull_request.base.sha }}" - CHANGED_FILES=$(git diff --name-only --diff-filter=ACM "$BASE_SHA"...HEAD || true) - else - CHANGED_FILES=$(git diff --name-only --diff-filter=ACM HEAD~1) - fi - - if [ -z "$CHANGED_FILES" ]; then - echo "No files changed to check" - exit 0 - fi - - echo "Files to check:" - echo "$CHANGED_FILES" | sed 's/^/ โข /' - echo "" - - # Check each changed file for trailing whitespace - FILES_WITH_TRAILING="" - for file in $CHANGED_FILES; do - # Skip if file doesn't exist (might be deleted) - if [ ! -f "$file" ]; then - continue - fi - - # Skip binary files - if file "$file" | grep -qE "binary|data|executable|compressed"; then - continue - fi - - # Check for trailing whitespace - if grep -q '[[:space:]]$' "$file" 2>/dev/null; then - FILES_WITH_TRAILING="$FILES_WITH_TRAILING $file" - fi - done - - if [ -z "$FILES_WITH_TRAILING" ]; then - echo "โ No trailing whitespace found in changed files" - else - echo "โ Found trailing whitespace in the following changed files:" - echo "" - for file in $FILES_WITH_TRAILING; do - echo " โข $file" - # Show lines with trailing whitespace (limit to first 5 occurrences per file) - grep -n '[[:space:]]$' "$file" | head -5 | while IFS=: read -r line_num content; do - # Show the line with visible whitespace markers - visible_content=$(echo "$content" | sed 's/ /ยท/g; s/\t/โ/g') - echo " Line $line_num: '${visible_content}'" - done - TOTAL_LINES=$(grep -c '[[:space:]]$' "$file") - if [ "$TOTAL_LINES" -gt 5 ]; then - echo " ... and $((TOTAL_LINES - 5)) more lines" - fi - echo "" - done - - echo "๐ก To fix trailing whitespace in these files:" - echo " โข VSCode: Enable 'files.trimTrailingWhitespace' setting" - echo " โข Fix specific file: sed -i 's/[[:space:]]*$//' <filename>" - echo " โข Fix all changed files:" - echo " for f in$FILES_WITH_TRAILING; do sed -i 's/[[:space:]]*$//' \$f; done" - exit 1 - fi + run: ./scripts/ci/trailing-whitespace.sh --check --ci trailing-newline: name: Check trailing newline @@ -331,80 +190,24 @@ jobs: - name: Checkout code uses: actions/checkout@v4 with: - fetch-depth: 0 # Need full history to get diff + fetch-depth: 0 # Need full history to get diff - name: Check for trailing newline in changed text files - run: | - echo "๐ Checking for trailing newline in changed text files..." - - # Get list of changed files in PR - if [ "${{ github.event_name }}" = "pull_request" ]; then - git fetch --no-tags --depth=1 origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }} || true - BASE_SHA="${{ github.event.pull_request.base.sha }}" - CHANGED_FILES=$(git diff --name-only --diff-filter=ACM "$BASE_SHA"...HEAD || true) - else - CHANGED_FILES=$(git diff --name-only --diff-filter=ACM HEAD~1) - fi - - if [ -z "$CHANGED_FILES" ]; then - echo "No files changed to check" - exit 0 - fi - - echo "Files to check:" - echo "$CHANGED_FILES" | sed 's/^/ โข /' - echo "" - - # Check each changed file for missing trailing newline - FILES_WITHOUT_NEWLINE="" - for file in $CHANGED_FILES; do - # Skip if file doesn't exist (might be deleted) - if [ ! -f "$file" ]; then - continue - fi - - # Skip binary files - if file "$file" | grep -qE "binary|data|executable|compressed"; then - continue - fi - - # Skip empty files - if [ ! -s "$file" ]; then - continue - fi - - # Check if file ends with a newline - # Use tail to get last byte and od to check if it's a newline (0x0a) - if [ -n "$(tail -c 1 "$file" | od -An -tx1 | grep -v '0a')" ]; then - FILES_WITHOUT_NEWLINE="$FILES_WITHOUT_NEWLINE $file" - fi - done - - if [ -z "$FILES_WITHOUT_NEWLINE" ]; then - echo "โ All changed text files have trailing newlines" - else - echo "โ Found text files without trailing newline:" - echo "" - for file in $FILES_WITHOUT_NEWLINE; do - echo " โข $file" - # Show last few characters of the file for context - echo -n " Last characters: '" - tail -c 20 "$file" | tr '\n' 'โต' | sed 's/\t/โ/g' - echo "'" - echo "" - done - - echo "๐ก To add trailing newlines to these files:" - echo " โข VSCode: Enable 'files.insertFinalNewline' setting" - echo " โข Fix specific file: echo >> <filename>" - echo " โข Fix all files:" - echo " for f in$FILES_WITHOUT_NEWLINE; do [ -n \"\$(tail -c 1 \"\$f\")\" ] && echo >> \"\$f\"; done" - exit 1 - fi + run: ./scripts/ci/trailing-newline.sh --check --ci summary: name: Common checks summary - needs: [rust-versions, pr-title, license-headers, license-list, markdown, shellcheck, trailing-whitespace, trailing-newline] + needs: + [ + rust-versions, + pr-title, + license-headers, + license-list, + markdown, + shellcheck, + trailing-whitespace, + trailing-newline, + ] if: always() runs-on: ubuntu-latest env: diff --git a/.github/workflows/dependabot-licenses.yml b/.github/workflows/dependabot-licenses.yml index d58f91aeb..8b433feb4 100644 --- a/.github/workflows/dependabot-licenses.yml +++ b/.github/workflows/dependabot-licenses.yml @@ -50,7 +50,7 @@ jobs: run: cargo install cargo-license - name: Update DEPENDENCIES.md - run: ./scripts/licenses-list.sh --update + run: ./scripts/ci/licenses-list.sh --update - name: Commit changes run: | diff --git a/.markdownlint.yml b/.markdownlint.yml new file mode 100644 index 000000000..88d9d9b03 --- /dev/null +++ b/.markdownlint.yml @@ -0,0 +1,24 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +default: true +MD013: + line_length: 120 + tables: false +MD033: + allowed_elements: [details, summary, img] +MD041: false # First line in file should be a top level heading diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..e0919768b --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,120 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +default_stages: [pre-commit] +default_install_hook_types: [pre-commit, pre-push] + +repos: + # Standard pre-commit hooks + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: check-yaml + - id: mixed-line-ending + + # CI scripts + - repo: local + hooks: + - id: markdownlint + name: markdownlint + entry: ./scripts/ci/markdownlint.sh + args: ["--fix", "--staged"] + language: system + types: [markdown] + pass_filenames: false + + - id: shellcheck + name: shellcheck + entry: ./scripts/ci/shellcheck.sh + args: ["--fix", "--staged"] + language: system + types: [shell] + pass_filenames: false + + - id: license-headers + name: license headers + entry: ./scripts/ci/license-headers.sh + args: ["--fix"] + language: system + pass_filenames: false + + - id: licenses-list + name: licenses list + entry: ./scripts/ci/licenses-list.sh + args: ["--fix"] + language: system + files: ^Cargo\.lock$ + pass_filenames: false + + - id: rust-version-sync + name: rust version sync + entry: ./scripts/ci/sync-rust-version.sh + args: ["--fix"] + language: system + files: ^rust-toolchain\.toml$ + pass_filenames: false + + - id: trailing-whitespace + name: trailing whitespace + entry: ./scripts/ci/trailing-whitespace.sh + args: ["--fix", "--staged"] + language: system + types: [text] + pass_filenames: false + + - id: trailing-newline + name: trailing newline + entry: ./scripts/ci/trailing-newline.sh + args: ["--fix", "--staged"] + language: system + types: [text] + pass_filenames: false + + # Rust + - repo: local + hooks: + - id: cargo-fmt + name: cargo fmt + entry: cargo fmt --all + language: system + types: [rust] + pass_filenames: false + + - id: cargo-clippy + name: cargo clippy + entry: cargo clippy + args: + [ + "--all-features", + "--all-targets", + "--manifest-path", + "Cargo.toml", + "--", + "-D", + "warnings", + ] + language: system + types: [rust] + pass_filenames: false + stages: [pre-push] + + # TODO(hubcio): add fast checks, linters, formatters for other languages + # - python (maturin, pytest, ruff, black) + # - java + # - go + # - csharp + # - js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31696169a..8964a23e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -72,6 +72,40 @@ $ cargo version cargo 1.86.0 (adf9b6ad1 2025-02-28) ``` +### Pre-commit Hooks (Recommended) + +Iggy uses [prek](https://github.com/9999years/prek) for pre-commit hooks to ensure code quality before commits. Setting up hooks is optional but strongly recommended to catch issues early. + +#### Setup + +```shell +cargo install prek +prek install +``` + +This will install git hooks that automatically run on `pre-commit` and `pre-push` events. + +#### Manual hook execution + +You can manually run specific hooks: + +```shell +# Run all pre-commit hooks +prek run + +# Run specific hook +prek run cargo-fmt +prek run cargo-clippy +``` + +#### Skip hooks (when necessary) + +If you need to skip hooks for a specific commit: + +```shell +git commit --no-verify -m "your message" +``` + ## How to build See [Quick Start](https://github.com/apache/iggy?tab=readme-ov-file#quick-start) diff --git a/foreign/cpp/.pre-commit-config.yaml b/foreign/cpp/.pre-commit-config.yaml deleted file mode 100644 index e3a87f017..000000000 --- a/foreign/cpp/.pre-commit-config.yaml +++ /dev/null @@ -1,107 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. ---- -repos: - - repo: https://github.com/adrienverge/yamllint.git - rev: v1.21.0 - hooks: - - id: yamllint - args: [--format, parsable, --strict] - - repo: https://github.com/cmake-lint/cmake-lint - rev: 1.4.2 - hooks: - - id: cmakelint - args: [--filter, -linelength] - - repo: https://github.com/cpplint/cpplint - rev: 1.6.1 - hooks: - - id: cpplint - - repo: https://github.com/gitleaks/gitleaks - rev: v8.16.1 - hooks: - - id: gitleaks - - repo: https://github.com/hadolint/hadolint - rev: v2.12.0 - hooks: - - id: hadolint - args: [--config, .github/linters/.hadolint.yaml] - - repo: https://github.com/igorshubovych/markdownlint-cli - rev: v0.39.0 - hooks: - - id: markdownlint - args: [--config, .github/linters/.markdown-lint.yml] - - repo: https://github.com/jumanjihouse/pre-commit-hook-yamlfmt - rev: 0.2.3 - hooks: - - id: yamlfmt - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 - hooks: - - id: check-added-large-files - - id: check-json - - id: check-merge-conflict - - id: check-yaml - - id: end-of-file-fixer - - id: trailing-whitespace - - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v18.1.0 - hooks: - - id: clang-format - - repo: https://github.com/scop/pre-commit-shfmt - rev: v3.8.0-1 - hooks: - - id: shfmt - - repo: local - hooks: - - id: cppcheck - name: cppcheck - entry: cppcheck --enable=style,performance,warning --inline-suppr --std=c++20 -x c++ - language: system - files: \.(cc|h)$ - pass_filenames: true - always_run: false - - id: flawfinder - name: flawfinder - entry: flawfinder --quiet -S -D --error-level=1 - language: system - files: \.(cc|h)$ - pass_filenames: true - always_run: false - - id: lizard - name: Check code cyclomatic complexity - entry: lizard -C 15 -i 0 -w -l c,cc,cpp,h,hpp - language: system - pass_filenames: true - always_run: false - - id: build - name: Build - entry: cmake --build build - language: system - pass_filenames: false - always_run: true - - id: run-unit-tests - name: Run Unit Tests - entry: ./build/tests/Debug/iggy_cpp_test - language: system - pass_filenames: false - always_run: true - - id: e2e-tests - name: Run E2E Tests - entry: ./build/tests/Debug/iggy_e2e_test - language: system - pass_filenames: false - always_run: true diff --git a/justfile b/justfile index 7b7a14b9e..578d0e4dd 100644 --- a/justfile +++ b/justfile @@ -67,16 +67,16 @@ profile-io-client: ./scripts/profile.sh iggy-bench io licenses-fix: - docker run --rm -v $(pwd):/src -w /src ghcr.io/google/addlicense:latest -f ASF_LICENSE.txt . + ./scripts/ci/license-headers.sh --fix licenses-check: - docker run --rm -v $(pwd):/src -w /src ghcr.io/google/addlicense:latest -check -f ASF_LICENSE.txt . + ./scripts/ci/license-headers.sh --check licenses-list-check: - ./scripts/licenses-list.sh --check + ./scripts/ci/licenses-list.sh --check licenses-list-fix: - ./scripts/licenses-list.sh --update + ./scripts/ci/licenses-list.sh --fix markdownlint: markdownlint '**/*.md' --ignore-path .gitignore diff --git a/scripts/ci/license-headers.sh b/scripts/ci/license-headers.sh new file mode 100755 index 000000000..7a002d5b8 --- /dev/null +++ b/scripts/ci/license-headers.sh @@ -0,0 +1,136 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +set -euo pipefail + +# Parse arguments +MODE="check" +if [ $# -gt 0 ]; then + case "$1" in + --check) + MODE="check" + ;; + --fix) + MODE="fix" + ;; + *) + echo "Usage: $0 [--check|--fix]" + echo " --check Check files for Apache license headers (default)" + echo " --fix Add Apache license headers to files missing them" + exit 1 + ;; + esac +fi + +# Check if docker is available +if ! command -v docker &> /dev/null; then + echo "โ docker command not found" + echo "๐ก Install Docker to run license header checks" + exit 1 +fi + +# Get the repository root +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$REPO_ROOT" + +# Check if ASF_LICENSE.txt exists +if [ ! -f "ASF_LICENSE.txt" ]; then + echo "โ ASF_LICENSE.txt not found in repository root" + exit 1 +fi + +# Pull the addlicense image +echo "Pulling addlicense Docker image..." +docker pull ghcr.io/google/addlicense:latest >/dev/null 2>&1 + +# Common patterns to ignore (build artifacts, dependencies, IDE files) +IGNORE_PATTERNS=( + "**/target/**" + "target/**" + "**/node_modules/**" + "node_modules/**" + "**/.venv/**" + ".venv/**" + "**/venv/**" + "venv/**" + "**/dist/**" + "dist/**" + "**/build/**" + "build/**" + "**/.idea/**" + ".idea/**" + "**/.vscode/**" + ".vscode/**" + "**/.gradle/**" + ".gradle/**" + "**/bin/**" + "**/obj/**" + "**/local_data*/**" + "**/performance_results*/**" +) + +# Build ignore flags for addlicense +IGNORE_FLAGS=() +for pattern in "${IGNORE_PATTERNS[@]}"; do + IGNORE_FLAGS+=("-ignore" "$pattern") +done + +if [ "$MODE" = "fix" ]; then + echo "๐ง Adding license headers to files..." + + # Run addlicense without -check to fix files + docker run --rm -v "$REPO_ROOT:/src" -w /src \ + ghcr.io/google/addlicense:latest \ + -f ASF_LICENSE.txt "${IGNORE_FLAGS[@]}" . + + echo "โ License headers have been added to files" +else + echo "๐ Checking license headers..." + + # Run the check and capture output + TEMP_FILE=$(mktemp) + trap 'rm -f "$TEMP_FILE"' EXIT + + if docker run --rm -v "$REPO_ROOT:/src" -w /src \ + ghcr.io/google/addlicense:latest \ + -check -f ASF_LICENSE.txt "${IGNORE_FLAGS[@]}" . > "$TEMP_FILE" 2>&1; then + echo "โ All files have proper license headers" + else + file_count=$(wc -l < "$TEMP_FILE") + echo "โ Found $file_count files missing license headers:" + echo "" + cat "$TEMP_FILE" | sed 's/^/ โข /' + echo "" + echo "๐ก Run '$0 --fix' to add license headers automatically" + + # Add to GitHub Actions summary if running in CI + if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then + { + echo "## โ License Headers Missing" + echo "" + echo "The following files are missing Apache license headers:" + echo '```' + cat "$TEMP_FILE" + echo '```' + echo "Please run \`./scripts/ci/license-headers.sh --fix\` to fix automatically." + } >> "$GITHUB_STEP_SUMMARY" + fi + + exit 1 + fi +fi diff --git a/scripts/ci/licenses-list.sh b/scripts/ci/licenses-list.sh new file mode 100755 index 000000000..2372ff3b3 --- /dev/null +++ b/scripts/ci/licenses-list.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash + +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +set -euo pipefail + +# Default mode +MODE="check" + +# Parse arguments +if [ $# -gt 0 ]; then + case "$1" in + --check) + MODE="check" + ;; + --update|--fix) + MODE="update" + ;; + *) + echo "Usage: $0 [--check|--update|--fix]" + echo " --check Check if DEPENDENCIES.md is up to date (default)" + echo " --update Update DEPENDENCIES.md with current dependencies" + echo " --fix Alias for --update" + exit 1 + ;; + esac +fi + +# Check if cargo-license is installed +if ! command -v cargo-license &>/dev/null; then + echo "โ cargo-license command not found" + echo "๐ก Install it using: cargo install cargo-license" + exit 1 +fi + +# Check if DEPENDENCIES.md exists +if [ ! -f "DEPENDENCIES.md" ] && [ "$MODE" = "check" ]; then + echo "โ DEPENDENCIES.md does not exist" + echo "๐ก Run '$0 --fix' to create it" + exit 1 +fi + +# Generate current dependencies +TEMP_FILE=$(mktemp) +trap 'rm -f "$TEMP_FILE"' EXIT + +echo "Generating current dependencies list..." +cargo license --color never --do-not-bundle --all-features >"$TEMP_FILE" + +# Update mode +if [ "$MODE" = "update" ]; then + echo "๐ง Updating DEPENDENCIES.md..." + { + echo "# Dependencies" + echo "" + cat "$TEMP_FILE" + } >DEPENDENCIES.md + echo "โ DEPENDENCIES.md has been updated" + exit 0 +fi + +# Check mode +if [ "$MODE" = "check" ]; then + echo "๐ Checking if DEPENDENCIES.md is up to date..." + # Create expected format for comparison + EXPECTED_FILE=$(mktemp) + trap 'rm -f "$TEMP_FILE" "$EXPECTED_FILE"' EXIT + { + echo "# Dependencies" + echo "" + cat "$TEMP_FILE" + } >"$EXPECTED_FILE" + + if ! diff -q "$EXPECTED_FILE" DEPENDENCIES.md >/dev/null; then + echo "โ DEPENDENCIES.md is out of date" + echo "" + echo "Diff:" + diff -u DEPENDENCIES.md "$EXPECTED_FILE" || true + echo "" + echo "๐ก Run '$0 --fix' to update it" + exit 1 + else + echo "โ DEPENDENCIES.md is up to date" + fi +fi diff --git a/scripts/ci/markdownlint.sh b/scripts/ci/markdownlint.sh new file mode 100755 index 000000000..61ba62467 --- /dev/null +++ b/scripts/ci/markdownlint.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +set -euo pipefail + +# Parse arguments +MODE="check" +if [ $# -gt 0 ]; then + case "$1" in + --check) + MODE="check" + ;; + --fix) + MODE="fix" + ;; + *) + echo "Usage: $0 [--check|--fix]" + echo " --check Check markdown files for issues (default)" + echo " --fix Automatically fix markdown issues" + exit 1 + ;; + esac +fi + +# Check if markdownlint is installed +if ! command -v markdownlint &> /dev/null; then + echo "โ markdownlint command not found" + echo "๐ก Install it using: npm install -g markdownlint-cli" + exit 1 +fi + +# Files to ignore (in addition to .gitignore) +IGNORE_FILES="CLAUDE.md" + +if [ "$MODE" = "fix" ]; then + echo "๐ง Fixing markdown files..." + markdownlint '**/*.md' --ignore-path .gitignore --ignore "$IGNORE_FILES" --fix + echo "โ Markdown files have been fixed" +else + echo "๐ Checking markdown files..." + if markdownlint '**/*.md' --ignore-path .gitignore --ignore "$IGNORE_FILES"; then + echo "โ All markdown files are properly formatted" + else + echo "โ Markdown linting failed" + echo "๐ก Run '$0 --fix' to auto-fix issues" + exit 1 + fi +fi diff --git a/scripts/ci/shellcheck.sh b/scripts/ci/shellcheck.sh new file mode 100755 index 000000000..e4b1e0f32 --- /dev/null +++ b/scripts/ci/shellcheck.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +set -euo pipefail + +# Parse arguments +MODE="check" +if [ $# -gt 0 ]; then + case "$1" in + --check) + MODE="check" + ;; + --fix) + MODE="fix" + ;; + *) + echo "Usage: $0 [--check|--fix]" + echo " --check Check shell scripts for issues (default)" + echo " --fix Show detailed suggestions for fixes" + exit 1 + ;; + esac +fi + +# Check if shellcheck is installed +if ! command -v shellcheck &> /dev/null; then + echo "โ shellcheck command not found" + echo "๐ก Install it using:" + echo " โข Ubuntu/Debian: sudo apt-get install shellcheck" + echo " โข macOS: brew install shellcheck" + echo " โข Or visit: https://www.shellcheck.net/" + exit 1 +fi + +echo "shellcheck version: $(shellcheck --version)" + +# Get repository root +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +cd "$REPO_ROOT" + +# Directories to exclude +EXCLUDE_PATHS=( + "./target/*" + "./node_modules/*" + "./.git/*" + "./foreign/node/node_modules/*" + "./foreign/python/.venv/*" + "./.venv/*" + "./venv/*" + "./build/*" + "./dist/*" +) + +# Build find exclusion arguments +FIND_EXCLUDE_ARGS=() +for path in "${EXCLUDE_PATHS[@]}"; do + FIND_EXCLUDE_ARGS+=("-not" "-path" "$path") +done + +if [ "$MODE" = "fix" ]; then + echo "๐ง Running shellcheck with detailed suggestions..." + echo "" + echo "Note: shellcheck does not support automatic fixing." + echo "Please review the suggestions below and fix issues manually." + echo "" + + # Run with detailed format + FAILED=0 + while IFS= read -r -d '' script; do + echo "Checking: $script" + if ! shellcheck -f gcc "$script"; then + FAILED=1 + fi + echo "" + done < <(find . -type f -name "*.sh" "${FIND_EXCLUDE_ARGS[@]}" -print0) + + if [ $FAILED -eq 1 ]; then + echo "โ Found issues in shell scripts" + echo "๐ก Fix the issues reported above manually" + exit 1 + else + echo "โ All shell scripts passed shellcheck" + fi +else + echo "๐ Checking shell scripts..." + + # Run shellcheck on all shell scripts (checks all severities: error, warning, info, style) + if find . -type f -name "*.sh" "${FIND_EXCLUDE_ARGS[@]}" -exec shellcheck {} +; then + echo "โ All shell scripts passed shellcheck" + else + echo "" + echo "โ Shellcheck found issues in shell scripts" + echo "๐ก Run '$0 --fix' to see detailed suggestions" + exit 1 + fi +fi diff --git a/scripts/sync-rust-version.sh b/scripts/ci/sync-rust-version.sh similarity index 97% rename from scripts/sync-rust-version.sh rename to scripts/ci/sync-rust-version.sh index ccaa8012f..45b056f7f 100755 --- a/scripts/sync-rust-version.sh +++ b/scripts/ci/sync-rust-version.sh @@ -64,8 +64,8 @@ if [ -z "$MODE" ]; then exit 1 fi -# Get the repository root (parent of scripts directory) -REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +# Get the repository root (two levels up from scripts/ci/) +REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" cd "$REPO_ROOT" # Extract Rust version from rust-toolchain.toml diff --git a/scripts/ci/trailing-newline.sh b/scripts/ci/trailing-newline.sh new file mode 100755 index 000000000..bbab2e564 --- /dev/null +++ b/scripts/ci/trailing-newline.sh @@ -0,0 +1,188 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +set -euo pipefail + +# Default values +MODE="check" +FILE_MODE="staged" +FILES=() + +# Parse arguments +while [[ $# -gt 0 ]]; do + case "$1" in + --check) + MODE="check" + shift + ;; + --fix) + MODE="fix" + shift + ;; + --staged) + FILE_MODE="staged" + shift + ;; + --ci) + FILE_MODE="ci" + shift + ;; + --all) + FILE_MODE="all" + shift + ;; + --help|-h) + echo "Usage: $0 [--check|--fix] [--staged|--ci|--all] [files...]" + echo "" + echo "Modes:" + echo " --check Check for missing trailing newlines (default)" + echo " --fix Add trailing newlines to files" + echo "" + echo "File selection:" + echo " --staged Check staged files (default, for git hooks)" + echo " --ci Check files changed in PR (for CI)" + echo " --all Check all tracked files" + echo " [files] Check specific files" + exit 0 + ;; + -*) + echo "Unknown option: $1" + echo "Use --help for usage information" + exit 1 + ;; + *) + # Treat as file argument + FILES+=("$1") + shift + ;; + esac +done + +# Get files to check based on mode +get_files() { + case "$FILE_MODE" in + staged) + # Get staged files for git hooks + git diff --cached --name-only --diff-filter=ACM + ;; + ci) + # Get files changed in PR for CI + if [ -n "${GITHUB_BASE_REF:-}" ]; then + # GitHub Actions PR context + git fetch --no-tags --depth=1 origin "${GITHUB_BASE_REF}:${GITHUB_BASE_REF}" 2>/dev/null || true + git diff --name-only --diff-filter=ACM "${GITHUB_BASE_REF}...HEAD" + elif [ -n "${CI:-}" ]; then + # Generic CI - compare with HEAD~1 + git diff --name-only --diff-filter=ACM HEAD~1 + else + # Fallback to staged files + git diff --cached --name-only --diff-filter=ACM + fi + ;; + all) + # Get all tracked files + git ls-files + ;; + esac +} + +# If files were provided as arguments, use them +if [ ${#FILES[@]} -gt 0 ]; then + CHANGED_FILES=("${FILES[@]}") +else + # Get files based on mode + CHANGED_FILES=() + while IFS= read -r file; do + CHANGED_FILES+=("$file") + done < <(get_files) +fi + +# Exit early if no files to check +if [ ${#CHANGED_FILES[@]} -eq 0 ]; then + echo "No files to check" + exit 0 +fi + +echo "Checking ${#CHANGED_FILES[@]} file(s) for trailing newlines..." + +# Track files with issues +FILES_WITHOUT_NEWLINE=() + +# Check each file +for file in "${CHANGED_FILES[@]}"; do + # Skip if file doesn't exist (might be deleted) + if [ ! -f "$file" ]; then + continue + fi + + # Skip binary files + if file "$file" | grep -qE "binary|data|executable|compressed"; then + continue + fi + + # Skip empty files + if [ ! -s "$file" ]; then + continue + fi + + # Check if file ends with a newline + # Use tail to get last byte and od to check if it's a newline (0x0a) + if ! tail -c 1 "$file" | od -An -tx1 | grep -q '0a'; then + FILES_WITHOUT_NEWLINE+=("$file") + fi +done + +# Fix mode +if [ "$MODE" = "fix" ]; then + if [ ${#FILES_WITHOUT_NEWLINE[@]} -eq 0 ]; then + echo "โ All files have trailing newlines" + exit 0 + fi + + echo "๐ง Adding trailing newlines to ${#FILES_WITHOUT_NEWLINE[@]} file(s)..." + for file in "${FILES_WITHOUT_NEWLINE[@]}"; do + # Add newline if file doesn't end with one + if [ -n "$(tail -c 1 "$file")" ]; then + echo >> "$file" + echo " Fixed: $file" + fi + done + echo "โ Trailing newlines added to ${#FILES_WITHOUT_NEWLINE[@]} file(s)" + exit 0 +fi + +# Check mode +if [ ${#FILES_WITHOUT_NEWLINE[@]} -eq 0 ]; then + echo "โ All text files have trailing newlines" + exit 0 +fi + +echo "โ Found ${#FILES_WITHOUT_NEWLINE[@]} file(s) without trailing newline:" +echo "" + +for file in "${FILES_WITHOUT_NEWLINE[@]}"; do + echo " โข $file" + # Show last few characters of the file for context + echo -n " Last characters: '" + tail -c 20 "$file" | tr '\n' 'โต' | sed 's/\t/โ/g' + echo "'" + echo "" +done + +echo "๐ก Run '$0 --fix' to add trailing newlines automatically" +exit 1 diff --git a/scripts/ci/trailing-whitespace.sh b/scripts/ci/trailing-whitespace.sh new file mode 100755 index 000000000..b2e066021 --- /dev/null +++ b/scripts/ci/trailing-whitespace.sh @@ -0,0 +1,187 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +set -euo pipefail + +# Default values +MODE="check" +FILE_MODE="staged" +FILES=() + +# Parse arguments +while [[ $# -gt 0 ]]; do + case "$1" in + --check) + MODE="check" + shift + ;; + --fix) + MODE="fix" + shift + ;; + --staged) + FILE_MODE="staged" + shift + ;; + --ci) + FILE_MODE="ci" + shift + ;; + --all) + FILE_MODE="all" + shift + ;; + --help|-h) + echo "Usage: $0 [--check|--fix] [--staged|--ci|--all] [files...]" + echo "" + echo "Modes:" + echo " --check Check for trailing whitespace (default)" + echo " --fix Remove trailing whitespace" + echo "" + echo "File selection:" + echo " --staged Check staged files (default, for git hooks)" + echo " --ci Check files changed in PR (for CI)" + echo " --all Check all tracked files" + echo " [files] Check specific files" + exit 0 + ;; + -*) + echo "Unknown option: $1" + echo "Use --help for usage information" + exit 1 + ;; + *) + # Treat as file argument + FILES+=("$1") + shift + ;; + esac +done + +# Get files to check based on mode +get_files() { + case "$FILE_MODE" in + staged) + # Get staged files for git hooks + git diff --cached --name-only --diff-filter=ACM + ;; + ci) + # Get files changed in PR for CI + if [ -n "${GITHUB_BASE_REF:-}" ]; then + # GitHub Actions PR context + git fetch --no-tags --depth=1 origin "${GITHUB_BASE_REF}:${GITHUB_BASE_REF}" 2>/dev/null || true + git diff --name-only --diff-filter=ACM "${GITHUB_BASE_REF}...HEAD" + elif [ -n "${CI:-}" ]; then + # Generic CI - compare with HEAD~1 + git diff --name-only --diff-filter=ACM HEAD~1 + else + # Fallback to staged files + git diff --cached --name-only --diff-filter=ACM + fi + ;; + all) + # Get all tracked files + git ls-files + ;; + esac +} + +# If files were provided as arguments, use them +if [ ${#FILES[@]} -gt 0 ]; then + CHANGED_FILES=("${FILES[@]}") +else + # Get files based on mode + CHANGED_FILES=() + while IFS= read -r file; do + CHANGED_FILES+=("$file") + done < <(get_files) +fi + +# Exit early if no files to check +if [ ${#CHANGED_FILES[@]} -eq 0 ]; then + echo "No files to check" + exit 0 +fi + +echo "Checking ${#CHANGED_FILES[@]} file(s) for trailing whitespace..." + +# Track files with issues +FILES_WITH_TRAILING=() + +# Check each file +for file in "${CHANGED_FILES[@]}"; do + # Skip if file doesn't exist (might be deleted) + if [ ! -f "$file" ]; then + continue + fi + + # Skip binary files + if file "$file" | grep -qE "binary|data|executable|compressed"; then + continue + fi + + # Check for trailing whitespace + if grep -q '[[:space:]]$' "$file" 2>/dev/null; then + FILES_WITH_TRAILING+=("$file") + fi +done + +# Fix mode +if [ "$MODE" = "fix" ]; then + if [ ${#FILES_WITH_TRAILING[@]} -eq 0 ]; then + echo "โ No trailing whitespace found" + exit 0 + fi + + echo "๐ง Removing trailing whitespace from ${#FILES_WITH_TRAILING[@]} file(s)..." + for file in "${FILES_WITH_TRAILING[@]}"; do + # Remove trailing whitespace (in-place) + sed -i 's/[[:space:]]*$//' "$file" + echo " Fixed: $file" + done + echo "โ Trailing whitespace removed from ${#FILES_WITH_TRAILING[@]} file(s)" + exit 0 +fi + +# Check mode +if [ ${#FILES_WITH_TRAILING[@]} -eq 0 ]; then + echo "โ No trailing whitespace found" + exit 0 +fi + +echo "โ Found trailing whitespace in ${#FILES_WITH_TRAILING[@]} file(s):" +echo "" + +for file in "${FILES_WITH_TRAILING[@]}"; do + echo " โข $file" + # Show lines with trailing whitespace (limit to first 3 occurrences per file) + grep -n '[[:space:]]$' "$file" | head -3 | while IFS=: read -r line_num content; do + # Show the line with visible whitespace markers + visible_content=$(echo "$content" | sed 's/ /ยท/g; s/\t/โ/g') + echo " Line $line_num: '${visible_content}'" + done + + TOTAL_LINES=$(grep -c '[[:space:]]$' "$file") + if [ "$TOTAL_LINES" -gt 3 ]; then + echo " ... and $((TOTAL_LINES - 3)) more lines" + fi + echo "" +done + +echo "๐ก Run '$0 --fix' to remove trailing whitespace automatically" +exit 1 diff --git a/scripts/copy-latest-from-master.sh b/scripts/copy-latest-from-master.sh index a6c2fa6c9..35665cf58 100755 --- a/scripts/copy-latest-from-master.sh +++ b/scripts/copy-latest-from-master.sh @@ -107,7 +107,7 @@ case "$COMMAND" in # Iterate through all saved files find "$TMP_SAVED" -type f | while read -r saved_file; do # Get relative path by removing the tmp prefix - rel_path="${saved_file#$TMP_SAVED/}" + rel_path="${saved_file#"$TMP_SAVED"/}" dest_dir=$(dirname "$rel_path") # Create destination directory if it doesn't exist @@ -136,4 +136,4 @@ case "$COMMAND" in echo "Valid commands: save, apply" exit 1 ;; -esac \ No newline at end of file +esac diff --git a/scripts/licenses-list.sh b/scripts/licenses-list.sh deleted file mode 100755 index 8739383d9..000000000 --- a/scripts/licenses-list.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -# This script is used to generate Cross.toml file for user which executes -# this script. This is needed since Cross.toml build.dockerfile.build-args -# section requires statically defined Docker build arguments and parameters -# like current UID or GID must be entered (cannot be generated or fetched -# during cross execution time). - -set -euo pipefail - -# Default mode -MODE="help" - -# Parse arguments -while [[ $# -gt 0 ]]; do - case "$1" in - --update) - MODE="update" - shift - ;; - --check) - MODE="check" - shift - ;; - *) - echo "Unknown option: $1" - MODE="help" - shift - ;; - esac -done - -# Display usage if no valid arguments provided -if [ "$MODE" = "help" ]; then - echo "Usage: $0 [OPTIONS]" - echo "Options:" - echo " --check Check if DEPENDENCIES.md is up to date" - echo " --update Update DEPENDENCIES.md with current dependencies" - exit 0 -fi - -# Check if cargo-license is installed -if ! command -v cargo-license &>/dev/null; then - echo "Installing cargo-license..." - cargo install cargo-license -fi - -# Check if DEPENDENCIES.md exists -if [ ! -f "DEPENDENCIES.md" ] && [ "$MODE" = "check" ]; then - echo "Error: DEPENDENCIES.md does not exist." - exit 1 -fi - -# Generate current dependencies -TEMP_FILE=$(mktemp) -trap 'rm -f "$TEMP_FILE"' EXIT - -echo "Generating current dependencies list..." -cargo license --color never --do-not-bundle --all-features >"$TEMP_FILE" - -# Update mode -if [ "$MODE" = "update" ]; then - echo "Updating DEPENDENCIES.md..." - { - echo "# Dependencies" - echo "" - cat "$TEMP_FILE" - } >DEPENDENCIES.md - echo "DEPENDENCIES.md has been updated." - exit 0 -fi - -# Check mode -if [ "$MODE" = "check" ]; then - echo "Checking if DEPENDENCIES.md is up to date..." - # Create expected format for comparison - EXPECTED_FILE=$(mktemp) - trap 'rm -f "$TEMP_FILE" "$EXPECTED_FILE"' EXIT - { - echo "# Dependencies" - echo "" - cat "$TEMP_FILE" - } >"$EXPECTED_FILE" - - if ! diff -q "$EXPECTED_FILE" DEPENDENCIES.md >/dev/null; then - echo "Error: DEPENDENCIES.md is out of date. Please run '$0 --update' to update it." - echo "Diff:" - diff -u DEPENDENCIES.md "$EXPECTED_FILE" - exit 1 - else - echo "DEPENDENCIES.md is up to date." - fi -fi
