diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 16598a700..000000000 --- a/.flake8 +++ /dev/null @@ -1,3 +0,0 @@ -[flake8] -max-line-length = 99 -ignore = E731,E203 diff --git a/.github/workflows/python-check.yaml b/.github/workflows/python-check.yaml new file mode 100644 index 000000000..f8fecd2f1 --- /dev/null +++ b/.github/workflows/python-check.yaml @@ -0,0 +1,127 @@ +name: Python Check +run-name: "${{ github.actor }} checking Python code" + +permissions: + contents: read + pull-requests: read + +on: + pull_request: + branches: [ main, develop ] + workflow_dispatch: + +jobs: + pre-check: + runs-on: ubuntu-latest + outputs: + is_act: ${{ steps.detect_act.outputs.is_act }} + steps: + - name: Detect act environment + id: detect_act + uses: Framework-R-D/phlex/.github/actions/detect-act-env@main + + detect-changes: + needs: pre-check + if: github.event_name != 'workflow_dispatch' && needs.pre-check.outputs.is_act != 'true' + runs-on: ubuntu-latest + permissions: + contents: read + packages: read + outputs: + has_changes: ${{ steps.filter.outputs.matched }} + steps: + - name: Checkout code + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + fetch-depth: 0 + path: phlex-src + + - name: Detect Python changes + id: filter + uses: Framework-R-D/phlex/.github/actions/detect-relevant-changes@main + with: + repo-path: phlex-src + base-ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before }} + head-ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} + file-type: python + + - name: Report detection outcome + run: | + if [ "${{ steps.filter.outputs.matched }}" != "true" ]; then + echo "::notice::No python check relevant changes detected; job will be skipped." + else + echo "::group::Python check relevant files" + printf '%s\n' "${{ steps.filter.outputs.matched_files }}" + echo "::endgroup::" + fi + + python-check: + needs: [pre-check, detect-changes] + if: > + github.event_name == 'workflow_dispatch' || + needs.pre-check.outputs.is_act == 'true' || + (needs.detect-changes.result == 'success' && needs.detect-changes.outputs.has_changes == 'true') + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + path: phlex-src + + - name: Set up Python + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: '3.x' + + - name: Install Python dependencies + run: | + pip install ruff mypy + + - name: Run ruff and mypy checks + working-directory: phlex-src + env: + FORCE_COLOR: 1 # `ruff`/`colored` crate + run: | + failed=0 + + echo "➡️ Checking Python code with ruff..." + echo "::group::Running ruff check" + if ! ruff check; then + failed=1 + echo "::endgroup::" + echo "::error:: Ruff check failed." + else + echo "::endgroup::" + echo "✅ Ruff check passed." + fi + + echo "➡️ Checking Python code with mypy..." + echo "::group::Running mypy" + if ! mypy --color-output .; then + failed=1 + echo "::endgroup::" + echo "::error:: MyPy check failed." + else + echo "::endgroup::" + echo "✅ MyPy check passed." + fi + + exit $failed + + python-check-skipped: + needs: [pre-check, detect-changes] + if: > + github.event_name != 'workflow_dispatch' && + needs.pre-check.outputs.is_act != 'true' && + needs.detect-changes.result == 'success' && + needs.detect-changes.outputs.has_changes != 'true' + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: No relevant Python changes detected + run: echo "No Python relevant changes detected; check skipped." diff --git a/.github/workflows/python-fix.yaml b/.github/workflows/python-fix.yaml new file mode 100644 index 000000000..d7f1e6ff1 --- /dev/null +++ b/.github/workflows/python-fix.yaml @@ -0,0 +1,73 @@ +name: Python Fix +run-name: "${{ github.actor }} fixing Python code" + +on: + issue_comment: + types: + - created + +permissions: + pull-requests: write + contents: write + +jobs: + apply_fixes: + runs-on: ubuntu-latest + name: Apply fixes + if: | + github.event.issue.pull_request && + (github.event.comment.author_association == 'COLLABORATOR' || github.event.comment.author_association == 'OWNER') && + startsWith(github.event.comment.body, '@phlexbot python-fix') + steps: + - name: Get PR Info + id: get_pr + uses: Framework-R-D/phlex/.github/actions/get-pr-info@main + + - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + with: + path: phlex-src + ref: ${{ steps.get_pr.outputs.ref }} + repository: ${{ steps.get_pr.outputs.repo }} + token: ${{ secrets.WORKFLOW_PAT }} + + - name: Set up Python + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 + with: + python-version: '3.x' + + - name: Install Python dependencies + run: | + pip install ruff + + - name: Run ruff format and fix + working-directory: phlex-src + env: + FORCE_COLOR: 1 + run: | + echo "Fixing Python format with ruff" + ruff format . || true + echo "Fixing Python linter issues with ruff" + ruff check --fix . || true + + - uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 + id: add_and_commit + with: + token: ${{ secrets.WORKFLOW_PAT }} + cwd: phlex-src + author_name: "github-actions[bot]" + author_email: "41898282+github-actions[bot]@users.noreply.github.com" + message: 'Committing Python linting fixes' + + - name: Formatting changes committed and pushed + if: ${{ steps.add_and_commit.outputs.committed == 'true' && steps.add_and_commit.outputs.pushed == 'true'}} + uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1 + with: + message: | + Python linting fixes pushed (commit ${{ steps.add_and_commit.outputs.commit_sha }}) + + - name: No formatting changes to make + if: ${{ steps.add_and_commit.outputs.committed == 'false' }} + uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b # v3.0.1 + with: + message: | + No Python linting fixes to make diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..9357828e5 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,34 @@ +[tool.mypy] +ignore_missing_imports = true +no_implicit_optional = true +plugins = [ +] +show_error_codes = true +warn_unreachable = true +disable_error_code = "annotation-unchecked" + +[tool.ruff] +target-version = "py310" +line-length = 99 + +[tool.ruff.lint] +select = [ + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "D", # pydocstyle + "E", # pycodestyle errors + "F", # pyflakes + "I", # isort + "W", # pycodestyle warnings +] +ignore = [] +extend-ignore = [ + "E731", # do not assign a lambda expression, use a def + "E203", # whitespace before ':' +] + +[tool.ruff.lint.pydocstyle] +convention = "google" + +[tool.ruff.format] +quote-style = "double"