diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..e4580b3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,24 @@ +version: 2 +updates: + # Picks up requirements.txt and requirements-dev.txt. + - package-ecosystem: pip + directory: / + schedule: + interval: weekly + ignore: + # Deliberately unpinned and kept current on the server by a daily timer + # (deploy/update-ytdlp.sh). Its floor only moves when YouTube requires a + # newer build, which is a judgement no weekly bump can make. + - dependency-name: yt-dlp + # Capped below 1.6 by discord.py 2.7.1; see requirements.txt. + - dependency-name: PyNaCl + versions: [">=1.6"] + + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + groups: + # One PR for all action bumps rather than one per action. + actions: + patterns: ["*"] diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index edab48d..848062b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,19 +10,48 @@ on: permissions: contents: read +# A new push to a PR makes the run for the previous one pointless. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-python@v7 + with: + python-version: "3.12" + cache: pip + + - name: Install dependencies + run: pip install -r requirements-dev.txt + + - name: Lint + # Correctness rules only (see ruff.toml): an undefined name in a + # rarely-run branch otherwise surfaces as a crash in production. + run: ruff check . + + - name: Type check + # Every function must be annotated (see mypy.ini). + run: mypy + pytest: runs-on: ubuntu-latest strategy: fail-fast: false matrix: # 3.12 is what Ubuntu 24.04 ships, which is what the bot is deployed on. - python-version: ["3.11", "3.12"] + # 3.14 is the newest release, so a dependency that breaks on it shows + # up here rather than on the next OS upgrade. + python-version: ["3.12", "3.14"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-python@v5 + - uses: actions/setup-python@v7 with: python-version: ${{ matrix.python-version }} cache: pip @@ -37,18 +66,7 @@ jobs: ffmpeg -version | head -1 - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements-dev.txt - - - name: Lint - # Correctness rules only (see ruff.toml): an undefined name in a - # rarely-run branch otherwise surfaces as a crash in production. - run: ruff check . - - - name: Type check - # Every function must be annotated (see mypy.ini). - run: mypy + run: pip install -r requirements-dev.txt - name: Run tests # The suite needs no credentials, no network and no .env. diff --git a/README.md b/README.md index 0a76b9f..c218383 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ No installation required — the bot is hosted and always online. ## 🛠️ Self-hosting ### Requirements -- Python 3.11+ +- Python 3.12+ - FFmpeg on your PATH - A Discord bot token with the **Message Content** intent enabled — the only privileged intent the bot asks for @@ -131,7 +131,7 @@ filters, since a wrong filter string looks perfectly reasonable and only shows u as the wrong playback speed. Those skip automatically if FFmpeg is not installed. CI runs the lint, the type check and the tests on every push and pull request, -against Python 3.11 and 3.12. +with the tests running on Python 3.12 (what the server runs) and 3.14 (the newest). ### Deploy to a server See **[deploy/README.md](deploy/README.md)** for the full walkthrough: diff --git a/mypy.ini b/mypy.ini index 286ad0f..3560c3f 100644 --- a/mypy.ini +++ b/mypy.ini @@ -1,5 +1,5 @@ [mypy] -python_version = 3.11 +python_version = 3.12 files = main.py, config.py, cogs, services, utils # The project is a set of top-level packages rather than one installed package. explicit_package_bases = True diff --git a/ruff.toml b/ruff.toml index a40e950..8ff1a09 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,4 +1,4 @@ -target-version = "py311" +target-version = "py312" [lint] # Correctness only: undefined names, unused imports and variables, syntax