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
56 changes: 56 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,17 @@ concurrency:
jobs:
lint:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# Caches the pip download/wheel cache keyed on pyproject.toml. The
# runtime has zero dependencies, but the dev extra pulls ruff, mypy,
# pytest and their graph, and 19 jobs were each fetching it fresh.
cache: pip
cache-dependency-path: pyproject.toml
- name: Install dev deps
run: |
python -m pip install --upgrade pip
Expand Down Expand Up @@ -113,11 +119,14 @@ jobs:
# registered with that label.
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: pyproject.toml
- name: Install dev deps
run: |
python -m pip install --upgrade pip
Expand Down Expand Up @@ -150,11 +159,17 @@ jobs:

integration:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# Caches the pip download/wheel cache keyed on pyproject.toml. The
# runtime has zero dependencies, but the dev extra pulls ruff, mypy,
# pytest and their graph, and 19 jobs were each fetching it fresh.
cache: pip
cache-dependency-path: pyproject.toml
- name: Install dev deps
run: |
python -m pip install --upgrade pip
Expand All @@ -172,11 +187,17 @@ jobs:

smoke:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# Caches the pip download/wheel cache keyed on pyproject.toml. The
# runtime has zero dependencies, but the dev extra pulls ruff, mypy,
# pytest and their graph, and 19 jobs were each fetching it fresh.
cache: pip
cache-dependency-path: pyproject.toml
- name: Run `da --version` (stdlib-only — no deps needed)
run: python3 da --version
- name: Run `da --help`
Expand Down Expand Up @@ -243,12 +264,18 @@ jobs:
# installer that flattens one, passes all of them. This job runs only
# what a user would actually receive.
runs-on: ubuntu-latest
timeout-minutes: 15
needs: test
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# Caches the pip download/wheel cache keyed on pyproject.toml. The
# runtime has zero dependencies, but the dev extra pulls ruff, mypy,
# pytest and their graph, and 19 jobs were each fetching it fresh.
cache: pip
cache-dependency-path: pyproject.toml

- name: Build wheel + sdist
run: |
Expand Down Expand Up @@ -336,6 +363,7 @@ jobs:
# ---------------------------------------------------------------------------
secret-scan:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
with:
Expand Down Expand Up @@ -368,6 +396,7 @@ jobs:
# approach as the gitleaks job above). --fail → exit 183 on any
# reportable finding, which gates CI.
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
with:
Expand All @@ -384,6 +413,7 @@ jobs:

codespell:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v7
- name: Install codespell
Expand Down Expand Up @@ -411,12 +441,18 @@ jobs:
# deps). da-cli itself has 0 runtime deps, so this is purely about
# the dev environment.
runs-on: ubuntu-latest
timeout-minutes: 10
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# Caches the pip download/wheel cache keyed on pyproject.toml. The
# runtime has zero dependencies, but the dev extra pulls ruff, mypy,
# pytest and their graph, and 19 jobs were each fetching it fresh.
cache: pip
cache-dependency-path: pyproject.toml
- name: Install dev deps
run: |
python -m pip install --upgrade pip
Expand All @@ -436,6 +472,7 @@ jobs:
# advisory and the corpus had drifted to 56 violations. Run it here
# so "configured" and "enforced" mean the same thing.
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v7
- name: markdownlint
Expand All @@ -449,6 +486,7 @@ jobs:
# deterministic, no network, gates every push/PR. External URLs are
# covered by link-check-external below.
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v7
- name: Install lychee
Expand All @@ -468,6 +506,7 @@ jobs:
# unrelated PRs. Exclusions and accepted status codes live in
# lychee.toml.
runs-on: ubuntu-latest
timeout-minutes: 10
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
steps:
- uses: actions/checkout@v7
Expand All @@ -487,11 +526,17 @@ jobs:
# so unlike the live jobs below it can gate every push, and it is
# what actually catches a DA response-shape change.
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# Caches the pip download/wheel cache keyed on pyproject.toml. The
# runtime has zero dependencies, but the dev extra pulls ruff, mypy,
# pytest and their graph, and 19 jobs were each fetching it fresh.
cache: pip
cache-dependency-path: pyproject.toml
- name: Install dev + integration deps
run: |
python -m pip install --upgrade pip
Expand Down Expand Up @@ -531,12 +576,18 @@ jobs:
github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
timeout-minutes: 15
needs: test # don't bother if unit tests are broken
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# Caches the pip download/wheel cache keyed on pyproject.toml. The
# runtime has zero dependencies, but the dev extra pulls ruff, mypy,
# pytest and their graph, and 19 jobs were each fetching it fresh.
cache: pip
cache-dependency-path: pyproject.toml
- name: Install dev + integration deps
run: |
python -m pip install --upgrade pip
Expand Down Expand Up @@ -571,6 +622,11 @@ jobs:
- uses: actions/setup-python@v7
with:
python-version: "3.13"
# Caches the pip download/wheel cache keyed on pyproject.toml. The
# runtime has zero dependencies, but the dev extra pulls ruff, mypy,
# pytest and their graph, and 19 jobs were each fetching it fresh.
cache: pip
cache-dependency-path: pyproject.toml
- name: Discoverability and metadata checks
run: python3 tools/check_discoverability.py

Expand Down
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ repos:
- "--warn-unreachable"
- "--warn-redundant-casts"
- "--warn-unused-ignores"
- "--check-untyped-defs"
- "--no-implicit-optional"
- "--strict-equality"
- "--disallow-untyped-calls"
- "--disallow-incomplete-defs"
- "--disable-error-code=type-arg"
- "--disable-error-code=no-any-return"
- "--disable-error-code=attr-defined"
Expand Down
9 changes: 9 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,15 @@ warn_unreachable = true
warn_redundant_casts = true
warn_unused_ignores = true
disallow_untyped_decorators = true
# All five verified to pass with zero findings before being enabled, so they
# cost nothing today and stop a regression tomorrow. They are the strict flags
# that do not require annotating every local — the ones this codebase already
# satisfies without knowing it.
check_untyped_defs = true # type-check bodies of unannotated functions
no_implicit_optional = true # `def f(x: int = None)` is an error, not Optional
strict_equality = true # `x == y` where the types cannot overlap
disallow_untyped_calls = true # calling an unannotated function from a typed one
disallow_incomplete_defs = true # a signature annotated only in part
disallow_untyped_defs = true
no_implicit_reexport = true
# Relax the rules that produce noise from JSON-shaped values
Expand Down
Loading