From a09dcd4a11c9ca421c7778e747bd189fc7ac67bd Mon Sep 17 00:00:00 2001 From: Quan Cheng Date: Sat, 28 Mar 2026 17:20:01 +0800 Subject: [PATCH] issuefix: add Ruff quality gates for local and CI checks --- .github/workflows/pytest.yml | 91 ++++++++++++++++++++++++++++++++++++ .pre-commit-config.yaml | 7 +++ pyproject.toml | 16 ++++++- 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 08608366..d7c36496 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -8,6 +8,97 @@ on: workflow_dispatch: # Allows manual triggering from GitHub UI jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Python 3.12 + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - uses: actions/cache@v3 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-lint-${{ hashFiles('**/pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-pip-lint- + + - name: Collect changed Python files + id: changed-python + shell: bash + run: | + set -euo pipefail + + if [ "${{ github.event_name }}" = "pull_request" ]; then + base_ref="${{ github.event.pull_request.base.ref }}" + git fetch --no-tags --prune --depth=1 origin "$base_ref" + merge_base="$(git merge-base "origin/$base_ref" "${{ github.sha }}")" + diff_from="$merge_base" + elif [ "${{ github.event_name }}" = "push" ]; then + before_sha="${{ github.event.before }}" + if [ -n "$before_sha" ] && [ "$before_sha" != "0000000000000000000000000000000000000000" ]; then + diff_from="$before_sha" + else + if git rev-parse --verify "${{ github.sha }}^" >/dev/null 2>&1; then + diff_from="$(git rev-parse "${{ github.sha }}^")" + else + diff_from="$(git hash-object -t tree /dev/null)" + fi + fi + else + echo "No PR/push diff context for ${GITHUB_EVENT_NAME}; skipping lint." + echo "has_python=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + mapfile -t files < <(git diff --name-only --diff-filter=ACMR "$diff_from" "${{ github.sha }}" -- '*.py') + + if [ "${#files[@]}" -eq 0 ]; then + echo "No changed Python files detected; skipping lint." + echo "has_python=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + echo "Changed Python files:" + printf ' - %s\n' "${files[@]}" + + { + echo "has_python=true" + echo "files<> "$GITHUB_OUTPUT" + + - name: Install lint dependencies + if: steps.changed-python.outputs.has_python == 'true' + run: | + python -m pip install --upgrade pip + pip install ruff + + - name: Run Ruff check + if: steps.changed-python.outputs.has_python == 'true' + shell: bash + env: + PYTHON_FILES: ${{ steps.changed-python.outputs.files }} + run: | + mapfile -t files <<< "$PYTHON_FILES" + ruff check "${files[@]}" + + - name: Run Ruff format check + if: steps.changed-python.outputs.has_python == 'true' + shell: bash + env: + PYTHON_FILES: ${{ steps.changed-python.outputs.files }} + run: | + mapfile -t files <<< "$PYTHON_FILES" + ruff format --check "${files[@]}" + # ----------------------------------------------------------------------- # Fast client tests — lightweight base install only (no gRPC/crypto/MCP) # Runs ONM unit tests + workspace backend tests diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..99499e55 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.6.9 + hooks: + - id: ruff-check + args: [--fix] + - id: ruff-format diff --git a/pyproject.toml b/pyproject.toml index 910c9919..864a809c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -93,8 +93,7 @@ dev = [ "pytest-xdist>=3.3.0", # Parallel test execution # Code quality - "black>=23.7.0", - "flake8>=6.0.0", + "ruff>=0.6.0", "mypy>=1.5.0", "pre-commit>=3.3.0", "coverage>=7.3.0", @@ -191,3 +190,16 @@ exclude_lines = [ "class .*\\bProtocol\\):", "@(abc\\.)?abstractmethod", ] + +[tool.ruff] +line-length = 120 +src = ["src", "tests"] + +[tool.ruff.lint] +select = ["E4", "E7", "E9", "F", "I"] + +[tool.ruff.lint.isort] +known-first-party = ["openagents"] + +[tool.ruff.format] +quote-style = "double"