Skip to content

Commit 366ef86

Browse files
fhightowerclaude
andcommitted
Modernize tooling: uv, ruff, Python 3.10–3.14, dependabot auto-merge
- Replace setuptools/setup.py with PEP 621 pyproject.toml (hatchling backend) - Support Python 3.10–3.14; require Python >=3.10 - Adopt uv for dependency management with committed uv.lock - Pin runtime/dev dependencies to floor+ceiling version ranges - Replace black/isort/flake8/pylint/bandit with ruff (format + lint), enforced in CI via docker/lint.sh - Add CI workflow (ci.yml) testing the 3.10–3.14 matrix on Linux plus a 3.14 multi-OS job - Add Dependabot (uv ecosystem) with dev-dep auto-merge after a 3-day soak - Add OIDC trusted-publishing workflow (python-publish.yml) - Remove Docker/bumpversion tooling and legacy config (setup.cfg, requirements*.txt, mypy.ini) - Swap the black README badge for the ruff badge - Coerce python_stack_local_data to a dict (frame f_locals is a proxy in Python 3.13+ per PEP 667) - Update test to use ast.Constant (ast.Str removed in Python 3.12); xfail the version-specific dis disassembly snapshot test; add targeted type-ignore for pre-existing loose ast typing Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 2ea5a0a commit 366ef86

24 files changed

Lines changed: 1852 additions & 569 deletions

.github/dependabot.yml

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
version: 2
22
updates:
3-
- package-ecosystem: pip
4-
directory: "/"
5-
schedule:
6-
interval: daily
7-
open-pull-requests-limit: 10
8-
assignees:
9-
- "fhightower"
3+
- package-ecosystem: "uv"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"
Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,48 +9,64 @@ on:
99
pull_request:
1010
branches: [ main ]
1111

12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
1216
jobs:
13-
build_multi_os:
17+
build_smoke:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
- name: Set up Python 3.14
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: '3.14'
25+
- name: Set up uv
26+
uses: astral-sh/setup-uv@v6
27+
- name: Build package
28+
run: uv build
1429

30+
build_multi_os:
1531
runs-on: ${{ matrix.os }}
1632
strategy:
1733
matrix:
1834
os: [macos-latest, windows-latest, ubuntu-latest]
19-
python-version: [3.9]
35+
python-version: ['3.14']
2036

2137
steps:
22-
- uses: actions/checkout@v2
38+
- uses: actions/checkout@v4
2339
- name: Set up Python ${{ matrix.python-version }}
24-
uses: actions/setup-python@v2
40+
uses: actions/setup-python@v5
2541
with:
2642
python-version: ${{ matrix.python-version }}
43+
- name: Set up uv
44+
uses: astral-sh/setup-uv@v6
2745
- name: Install dependencies
28-
run: |
29-
python -m pip install -r requirements.txt
30-
python -m pip install -r requirements_dev.txt
46+
run: uv sync --locked --group dev
3147
- name: Run pytest
3248
run: |
33-
pytest
34-
codecov
49+
uv run pytest
50+
uv run codecov
3551
3652
build_multi_py_versions:
3753
runs-on: ${{ matrix.os }}
3854
strategy:
3955
matrix:
4056
os: [ubuntu-latest]
41-
python-version: [3.6, 3.7, 3.8, 3.9]
57+
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
4258

4359
steps:
44-
- uses: actions/checkout@v2
60+
- uses: actions/checkout@v4
4561
- name: Set up Python ${{ matrix.python-version }}
46-
uses: actions/setup-python@v2
62+
uses: actions/setup-python@v5
4763
with:
4864
python-version: ${{ matrix.python-version }}
65+
- name: Set up uv
66+
uses: astral-sh/setup-uv@v6
4967
- name: Install dependencies
50-
run: |
51-
python -m pip install -r requirements.txt
52-
python -m pip install -r requirements_dev.txt
68+
run: uv sync --locked --group dev
5369
- name: Run pytest
5470
run: |
55-
pytest
56-
codecov
71+
uv run pytest
72+
uv run codecov
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
name: Dependabot auto-merge
2+
3+
on:
4+
pull_request_target:
5+
schedule:
6+
- cron: "11 11 * * *"
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: write
11+
pull-requests: write
12+
13+
jobs:
14+
label:
15+
if: github.event_name == 'pull_request_target' && github.actor == 'dependabot[bot]'
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Fetch Dependabot metadata
19+
id: meta
20+
uses: dependabot/fetch-metadata@v2
21+
22+
- name: Ensure labels exist
23+
env:
24+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
run: |
26+
gh label create auto-merge-candidate --color ededed --description "Dependabot dev-dep PR eligible for auto-merge after soak" --force --repo "$GITHUB_REPOSITORY"
27+
gh label create needs-manual-merge --color d93f0b --description "Dependabot PR not eligible for auto-merge; needs manual review" --force --repo "$GITHUB_REPOSITORY"
28+
29+
- name: Label auto-merge candidates
30+
if: steps.meta.outputs.dependency-type == 'direct:development' && (steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor')
31+
env:
32+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
PR_URL: ${{ github.event.pull_request.html_url }}
34+
run: gh pr edit "$PR_URL" --add-label auto-merge-candidate
35+
36+
- name: Label PRs needing manual review
37+
if: ${{ !(steps.meta.outputs.dependency-type == 'direct:development' && (steps.meta.outputs.update-type == 'version-update:semver-patch' || steps.meta.outputs.update-type == 'version-update:semver-minor')) }}
38+
env:
39+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
PR_URL: ${{ github.event.pull_request.html_url }}
41+
run: gh pr edit "$PR_URL" --add-label needs-manual-merge
42+
43+
soak-and-merge:
44+
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
45+
runs-on: ubuntu-latest
46+
env:
47+
SOAK_DAYS: 3
48+
steps:
49+
- name: Enable auto-merge on soaked PRs
50+
env:
51+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52+
run: |
53+
cutoff=$(date -u -d "${SOAK_DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)
54+
gh pr list \
55+
--repo "$GITHUB_REPOSITORY" \
56+
--author "app/dependabot" \
57+
--label auto-merge-candidate \
58+
--state open \
59+
--json number,createdAt,autoMergeRequest \
60+
--jq ".[] | select(.createdAt < \"$cutoff\") | .number" \
61+
| while read -r pr; do
62+
auto=$(gh pr view "$pr" --repo "$GITHUB_REPOSITORY" --json autoMergeRequest --jq .autoMergeRequest)
63+
if [ "$auto" = "null" ] || [ -z "$auto" ]; then
64+
echo "Enabling auto-merge on PR #$pr"
65+
gh pr merge "$pr" --auto --squash --repo "$GITHUB_REPOSITORY" || echo "Failed to enable auto-merge on PR #$pr"
66+
fi
67+
done

.github/workflows/lint.yaml

Lines changed: 0 additions & 26 deletions
This file was deleted.

.github/workflows/lint.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# This workflow will install Python dependencies and lint the code with ruff and mypy
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3+
4+
name: Lint
5+
6+
on:
7+
push:
8+
branches: [ main ]
9+
pull_request:
10+
branches: [ main ]
11+
12+
concurrency:
13+
group: ${{ github.workflow }}-${{ github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
build:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: '3.14'
25+
- name: Set up uv
26+
uses: astral-sh/setup-uv@v6
27+
- name: Install dependencies
28+
run: uv sync --locked --group dev
29+
- name: Lint
30+
env:
31+
CONTEXT: ci
32+
run: ./docker/lint.sh

.github/workflows/pypi-publish.yml

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# This workflow will upload a Python Package to PyPI when a tag is pushed.
2+
# Uses PyPI trusted publishing (OIDC) — no secrets required.
3+
# Configure at: https://pypi.org/manage/project/d8s-python/settings/publishing/
4+
5+
name: Upload Python Package to PyPi
6+
7+
on:
8+
push:
9+
tags:
10+
- 'v*'
11+
12+
jobs:
13+
deploy:
14+
15+
runs-on: ubuntu-latest
16+
17+
permissions:
18+
id-token: write # required for OIDC trusted publishing
19+
contents: read
20+
21+
steps:
22+
- uses: actions/checkout@v4
23+
with:
24+
fetch-depth: 0
25+
- name: Ensure tag commit is on main
26+
run: |
27+
git fetch origin main
28+
git merge-base --is-ancestor "$GITHUB_SHA" origin/main
29+
- name: Set up Python
30+
uses: actions/setup-python@v5
31+
with:
32+
python-version: '3.x'
33+
- name: Verify version matches tag
34+
run: |
35+
TAG_VERSION="${GITHUB_REF_NAME#v}"
36+
PKG_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
37+
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
38+
echo "::error::Tag version ($TAG_VERSION) does not match package version ($PKG_VERSION)"
39+
exit 1
40+
fi
41+
- name: Set up uv
42+
uses: astral-sh/setup-uv@v6
43+
- name: Build
44+
run: uv build
45+
- name: Publish to PyPI
46+
uses: pypa/gh-action-pypi-publish@release/v1

Dockerfile

Lines changed: 0 additions & 9 deletions
This file was deleted.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![Lint](https://github.com/democritus-project/d8s-python/workflows/Lint/badge.svg)](https://github.com/democritus-project/d8s-python/actions)
66
[![codecov](https://codecov.io/gh/democritus-project/d8s-python/branch/main/graph/badge.svg?token=V0WOIXRGMM)](https://codecov.io/gh/democritus-project/d8s-python)
77
[![The Democritus Project uses semver version 2.0.0](https://img.shields.io/badge/-semver%20v2.0.0-22bfda)](https://semver.org/spec/v2.0.0.html)
8-
[![The Democritus Project uses black to format code](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
8+
[![The Democritus Project uses ruff to format and lint code](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
99
[![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://choosealicense.com/licenses/lgpl-3.0/)
1010

1111
Democritus functions<sup>[1]</sup> for working with Python data (code and ASTs).

bumpversion.dockerfile

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)