Latest stable dependencies, mcp 2.x, and the gate
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (push) Waiting to run
Tests / test (3.10) (push) Waiting to run
Tests / test (3.11) (push) Waiting to run
Tests / test (3.12) (push) Waiting to run

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Krzysztof Rudnicki 2026-08-28 17:29:14 +02:00
parent 6b92d87174
commit 9e0f75a5a0
9 changed files with 2726 additions and 48 deletions

View File

@ -0,0 +1,62 @@
name: dependency freshness
# Every dependency on its ecosystem's newest STABLE release, enforced on push
# as well as at commit time. The local pre-commit hook only sees the manifests
# in a commit and can be skipped entirely by a fresh clone that never ran
# `pre-commit install`; this runs `--all` over the whole repo.
#
# `--strict` is CI-only. Offline the gate degrades to its cached answer and
# passes, because `--no-verify` is banned locally and a hook that hard-failed
# on a flaky connection would leave no way to commit. A runner is always
# online, so here an undeterminable answer is a real failure.
#
# Expect this to go red for reasons this repo's commit did not cause: an
# upstream release overnight is enough. That is the chosen behaviour -- the
# alternative is a gate that only notices staleness when someone remembers to
# look.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
jobs:
dependency-freshness:
name: dependencies on newest stable
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# The gate lives in the shared utils repo so every repo resolves the
# same "latest stable" the same way. Checking it out beats vendoring a
# copy, which is exactly how a gate and its survey start disagreeing.
- name: Check out the shared gate
uses: actions/checkout@v4
with:
repository: kuhyx/utils
path: .utils
# "3.x", never a pinned minor: the Python target IS the interpreter the
# gate runs under (registries/toolchain.python_installed), so a runner
# held a release behind this machine reports a repo's `requires-python`
# as excluding "latest" while the same check passes locally. flax-docs-mcp
# hit exactly that -- `>=3.14` green here, red on a 3.13 runner.
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.x"
- name: Install the gate's two runtime dependencies
run: python -m pip install --upgrade pyyaml packaging
- name: Cache registry lookups
uses: actions/cache@v4
with:
path: ~/.cache/dep-freshness
key: dep-freshness-${{ hashFiles('**/pubspec.yaml', '**/pyproject.toml',
'**/requirements*.txt', '**/package.json', '**/Cargo.toml', '**/go.mod') }}
restore-keys: dep-freshness-
- name: Every dependency is on newest stable
run: bash .utils/scripts/check_dependency_freshness.sh --all --strict

View File

@ -11,6 +11,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Hooks here delegate to the shared gates in kuhyx/utils. Without this
# checkout they exit 1 with "shared gate not found at
# /home/runner/utils/..." -- green locally, red on every runner.
- name: Check out the shared gates
uses: actions/checkout@v4
with:
repository: kuhyx/utils
path: .utils
- name: Point the delegates at that checkout
run: echo "UTILS_ROOT=$GITHUB_WORKSPACE/.utils" >> "$GITHUB_ENV"
- uses: actions/setup-python@v5
with:
python-version: "3.12"

View File

@ -123,7 +123,12 @@ repos:
- --rcfile=pyproject.toml
- --fail-under=8.0
- --jobs=4
# pylint resolves imports in its OWN isolated env, so anything the
# package imports has to be listed here or it reports import-error and
# drags the score under --fail-under. `mcp` is a real runtime import
# (steam_backlog_enforcer._mcp_server).
additional_dependencies:
- mcp==2.1.1
- pytest
- requests
@ -179,7 +184,9 @@ repos:
hooks:
- id: codespell
args:
- --skip=*.json,*.lock,.git,__pycache__,.venv
# pnpm-lock.yaml is integrity hashes, not prose: `vEw` in a
# sha512 read as a misspelling of "view".
- --skip=*.json,*.lock,*-lock.yaml,.git,__pycache__,.venv,node_modules
- --ignore-words-list=als,ans,ect,nd,som,sur,te,nam,numer,lew,sie,wil,postion,clen,ther,folow,derrive,ony,tje,noe,theses,crate,doubleclick,wile,tabel,pary,blok,bloc,proces,serwer,parametr,adres,hart,dout,metod,tekst,synonim,grup,mosty,lokal,skalar,milion,nowe,tre,hel,alph
# ===========================================================================
@ -202,3 +209,25 @@ repos:
entry: scripts/check_md_naming.sh
language: system
files: \.(md|markdown)$
# Every dependency on its ecosystem's newest STABLE release, exact-pinned
# so the question is mechanically answerable at all.
#
# `files:` is what keeps this cheap: a commit touching only source makes
# ZERO network requests, and manifest commits mostly hit a 6h disk cache.
#
# Runs WITHOUT --strict on purpose. Offline it degrades to the cached
# answer and passes with a loud banner; `--no-verify` is banned here, so
# a hook that hard-failed on a flaky connection would leave no way to
# commit at all. CI, always online, is the strict authority.
- id: dependency-freshness
name: dependencies on newest stable
entry: scripts/check_dependency_freshness.sh
language: system
pass_filenames: true
files: >-
(pubspec\.(yaml|lock)|pyproject\.toml|requirements.*\.txt|uv\.lock
|package\.json|package-lock\.json|pnpm-lock\.yaml
|Cargo\.(toml|lock)|go\.(mod|sum)
|\.fvmrc|\.nvmrc|\.python-version
|\.github/workflows/.*\.ya?ml)$

View File

@ -4,14 +4,14 @@ version = "1.0.0"
description = "Enforce your Steam backlog: one game at a time, tracked with HowLongToBeat data"
requires-python = ">=3.10"
dependencies = [
"requests>=2.0",
"howlongtobeatpy>=1.0",
"requests==2.34.2",
"howlongtobeatpy==1.0.23",
# Directly imported by the package (aiohttp: _hltb_* async lookups;
# websockets: library_hider). aiohttp was previously satisfied only
# transitively via howlongtobeatpy and websockets was undeclared — both
# are declared here so a clean install imports the package.
"aiohttp>=3.0",
"websockets>=11.0",
"aiohttp==3.14.3",
"websockets==17.1",
]
# Optional extras. The `mcp` group is ONLY needed by the MCP server
@ -20,7 +20,7 @@ dependencies = [
# dependency so the systemd/CLI system-python path stays dependency-light and
# never has to import the MCP SDK.
[project.optional-dependencies]
mcp = ["mcp>=1.9,<2"]
mcp = ["mcp==2.1.1"]
# Explicit package discovery. Without this, setuptools' flat-layout
# auto-discovery aborts because the repo root holds two top-level dirs

View File

@ -1,22 +1,22 @@
# Steam Backlog Enforcer — runtime + development dependencies
# Install with: pip install -r requirements.txt
aiohttp>=3.9
bandit>=1.7.0
codespell>=2.2.0
coverage>=7.4.0
howlongtobeatpy>=1.0
mcp>=1.9,<2
mypy>=1.8.0
pre-commit>=3.6.0
pylint>=3.0.0
pytest>=8.0.0
pytest-cov>=4.1.0
pytest-randomly>=3.15.0
pytest-sugar>=1.0.0
pytest-timeout>=2.2.0
pytest-xdist>=3.5.0
requests>=2.0
ruff>=0.8.0
types-requests>=2.31.0
websockets>=12.0
aiohttp==3.14.3
bandit==1.9.4
codespell==2.4.3
coverage==7.15.4
howlongtobeatpy==1.0.23
mcp==2.1.1
mypy==2.3.1
pre-commit==4.6.2
pylint==4.0.7
pytest==9.1.1
pytest-cov==7.1.0
pytest-randomly==4.1.0
pytest-sugar==1.1.1
pytest-timeout==2.4.0
pytest-xdist==3.8.0
requests==2.34.2
ruff==0.16.5
types-requests==2.33.0.20260712
websockets==17.1

View File

@ -0,0 +1,34 @@
#!/bin/bash
# ============================================================================
# Fail if any dependency in the commit is behind its ecosystem's newest stable.
#
# Thin delegate to the shared gate in ~/utils, which owns the registry
# adapters, the pre-release rules and the allowlist semantics. Copying that
# logic here is what lets one repo's idea of "current" drift from every other
# repo's -- so this script only locates the shared checker and forwards its
# arguments.
#
# Usage:
# scripts/check_dependency_freshness.sh <file> [<file> ...] # pre-commit
# scripts/check_dependency_freshness.sh --all --strict # CI
#
# Exit: 0 current | 1 behind | 2 allowlist wrong | 3 undeterminable (offline)
# ============================================================================
set -euo pipefail
readonly SHARED_GATE="${UTILS_ROOT:-$HOME/utils}/scripts/check_dependency_freshness.sh"
main() {
if [[ ! -x "$SHARED_GATE" ]]; then
echo "Error: shared dependency-freshness gate not found at $SHARED_GATE" >&2
echo " Clone github.com/kuhyx/utils to ~/utils, or set" >&2
echo " UTILS_ROOT to where it lives." >&2
exit 1
fi
exec bash "$SHARED_GATE" "$@"
}
main "$@"

View File

@ -29,7 +29,7 @@ import logging
import sys
from typing import TYPE_CHECKING
from mcp.server.fastmcp import FastMCP
from mcp.server import MCPServer
from steam_backlog_enforcer.config import load_snapshot
@ -45,7 +45,7 @@ logging.basicConfig(
)
logger = logging.getLogger(__name__)
mcp = FastMCP("steam-backlog-enforcer")
mcp = MCPServer("steam-backlog-enforcer")
_DEFAULT_LIST_LIMIT = 50

View File

@ -13,28 +13,28 @@
"coverage": "vitest run --coverage"
},
"dependencies": {
"react": "^19.2.6",
"react-dom": "^19.2.6"
"react": "19.2.8",
"react-dom": "19.2.8"
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/node": "^24.12.3",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^6.0.1",
"@vitest/coverage-v8": "^4.1.7",
"eslint": "^10.3.0",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.2",
"globals": "^17.6.0",
"jsdom": "^29.1.1",
"typescript": "~6.0.2",
"typescript-eslint": "^8.59.2",
"vite": "^8.0.12",
"vitest": "^4.1.7"
"@eslint/js": "10.0.1",
"@testing-library/dom": "10.4.1",
"@testing-library/jest-dom": "7.0.1",
"@testing-library/react": "16.3.2",
"@testing-library/user-event": "14.6.6",
"@types/node": "26.4.0",
"@types/react": "19.2.18",
"@types/react-dom": "19.2.5",
"@vitejs/plugin-react": "6.1.0",
"@vitest/coverage-v8": "4.1.11",
"eslint": "10.9.1",
"eslint-plugin-react-hooks": "7.1.1",
"eslint-plugin-react-refresh": "0.5.5",
"globals": "17.11.0",
"jsdom": "30.0.1",
"typescript": "6.0.3",
"typescript-eslint": "8.68.0",
"vite": "8.2.2",
"vitest": "4.1.11"
}
}

2542
web/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff