Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: lint

on:
push:
branches: [main]
pull_request:
workflow_dispatch:

jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"

# Pinned deliberately: an unpinned ruff picks up new rules on release and
# turns a green branch red without anything in this repo changing.
- run: pip install ruff==0.16.2

- run: ruff check .
44 changes: 44 additions & 0 deletions ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Shared ruff standard for offworldlabs Python repos.
# Keep in sync across repos; see offworldlabs/ops for the canonical copy.

line-length = 120
target-version = "py311"

[lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"B", # flake8-bugbear
"UP", # pyupgrade
"S", # flake8-bandit (security)
"SIM", # flake8-simplify
]
ignore = [
"E501", # line too long — handled by formatter
"E402", # module-level import not at top — env setup before imports is intentional
"S101", # assert in tests is fine
"S104", # binding to 0.0.0.0 is intentional (Docker)
"S105", # hardcoded password false positives on dev defaults
"S106", # hardcoded password false positives
"S110", # try-except-pass is used intentionally
"S112", # try-except-continue is intentional in iteration
"S310", # URL open audit — URLs are constructed internally
"S311", # pseudo-random is fine for non-crypto uses
"S501", # requests without verify — internal calls
"S603", # subprocess calls are in controlled scripts
"S607", # partial executable path is fine for scripts
"B008", # function call in default arg — Depends() is FastAPI pattern
"B905", # zip strict — not needed everywhere
"SIM102", # nested if — readability preference
"SIM105", # contextlib.suppress — try/except is more explicit
"SIM108", # ternary operator — readability preference
"SIM117", # combine with statements — readability preference
"UP017", # datetime.UTC — cosmetic, timezone.utc is fine
"UP028", # yield from — explicit loop is clearer
]

[lint.per-file-ignores]
"tests/*" = ["S", "B"]
"scripts/*" = ["S", "E"]
Loading