Skip to content
Open
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
24 changes: 24 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: 2
updates:
# Keep GitHub Actions pinned to immutable commit SHAs up-to-date.
# Dependabot opens a PR whenever a newer SHA is available for a pinned action.
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "dependencies"

# Keep Python runtime dependencies up-to-date within the bounded ranges
# declared in requirements.txt / pyproject.toml.
# Dependabot opens a PR for each package that has a new version available.
# After merging, regenerate requirements-lock.txt by running the
# "Update dependency lock file" workflow (or locally with pip-compile).
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "dependencies"
16 changes: 11 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,15 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Install runtime + test dependencies
# Only what the tests actually exercise. `pywebview` from
# requirements.txt is the desktop-launcher dep and pulls GTK / Qt
# system packages on Linux — out of scope for the unittest suite.
# Install from the pinned lock file for deterministic dependency
# resolution (closes #47). pytest is added on top — it is not in
# requirements-lock.txt because it is a dev-only dep. pywebview is
# the desktop-launcher dep and pulls GTK / Qt system libraries on
# Linux — intentionally excluded from the CI unittest matrix.
run: |
python -m pip install --upgrade pip
python -m pip install 'flask>=3.0' 'fpdf2>=2.7' 'pytest>=8'
python -m pip install -r requirements-lock.txt
python -m pip install 'pytest>=8,<9'

- name: Run unittest suite
run: python -m unittest discover tests -v
Expand Down Expand Up @@ -78,9 +81,12 @@ jobs:
python-version: "3.12"

- name: Install runtime deps + mypy
# Install from the pinned lock file for deterministic resolution,
# then add mypy (dev-only; not in requirements-lock.txt).
run: |
python -m pip install --upgrade pip
python -m pip install 'flask>=3.0' 'fpdf2>=2.7' 'mypy>=1.10'
python -m pip install -r requirements-lock.txt
python -m pip install 'mypy>=1.10,<2'

- name: Run mypy
# No `continue-on-error` — mypy now exits zero on this repo (closes #29),
Expand Down
62 changes: 62 additions & 0 deletions .github/workflows/update-lock.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Update dependency lock file

on:
# Run every Monday at 08:00 UTC — picks up upstream patch / security
# releases that land within the bounded ranges in requirements.txt.
schedule:
- cron: "0 8 * * 1"
# Allow manual trigger from the Actions tab for ad-hoc refreshes.
workflow_dispatch:

permissions:
contents: write
pull-requests: write

jobs:
update-lock:
name: Regenerate requirements-lock.txt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4

- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: "3.12"

- name: Install pip-tools
run: python -m pip install pip-tools

- name: Regenerate lock file
run: |
pip-compile requirements.txt \
--output-file requirements-lock.txt \
--no-header \
--annotation-style=line \
--allow-unsafe \
--upgrade

- name: Restore header comment
# pip-compile --no-header omits the auto-generated header line but
# we maintain our own documentation header; restore it if missing.
run: |
HEADER='# Pinned lock file — generated by pip-compile (pip-tools).\n# Install: pip install -r requirements-lock.txt\n# Update: pip-compile requirements.txt --output-file requirements-lock.txt --no-header --annotation-style=line --allow-unsafe\n# Run periodically (e.g. via the "Update dependency lock file" CI workflow) to pick up\n# upstream patch / security releases within the bounded ranges in requirements.txt.'
if ! head -1 requirements-lock.txt | grep -q "^#"; then
printf '%s\n' "$HEADER" | cat - requirements-lock.txt > /tmp/lock.tmp
mv /tmp/lock.tmp requirements-lock.txt
fi

- name: Open PR if lock file changed
uses: peter-evans/create-pull-request@22a9089034f40e5a961c8808d113e2c98fb63676 # v7
with:
commit-message: "chore: update requirements-lock.txt"
branch: "chore/update-lock-file"
delete-branch: true
title: "chore: update dependency lock file"
body: |
Automated weekly refresh of `requirements-lock.txt`.

Generated by `pip-compile --upgrade` from the bounded specifiers
in `requirements.txt`. Review the diff to confirm no unexpected
major-version jumps before merging.
labels: dependencies
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ requires-python = ">=3.10"
dependencies = [
"flask>=3.0,<4",
"fpdf2>=2.7,<3",
# Security floor: fpdf2 allows Pillow>=8.3.2, so 9.x can still be resolved.
# CVE-2024-28219 (buffer overflow) fixed in Pillow 10.3.0 — https://nvd.nist.gov/vuln/detail/CVE-2024-28219
"pillow>=10.3.0",
# Security floor: fpdf2 allows Pillow>=8.3.2 (no upper cap); pin 12.x to avoid
# known high-severity CVEs in Pillow 10.x (e.g. CVE-2024-28219 and later advisories).
"pillow>=12.2.0,<13",
]

[project.optional-dependencies]
Expand Down
17 changes: 17 additions & 0 deletions requirements-lock.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Pinned lock file — generated by pip-compile (pip-tools).
# Install: pip install -r requirements-lock.txt
# Update: pip-compile requirements.txt --output-file requirements-lock.txt --no-header --annotation-style=line --allow-unsafe
# Run periodically (e.g. via the "Update dependency lock file" CI workflow) to pick up
# upstream patch / security releases within the bounded ranges in requirements.txt.
blinker==1.9.0 # via flask
click==8.4.0 # via flask
colorama==0.4.6 # via click
defusedxml==0.7.1 # via fpdf2
flask==3.1.3 # via -r requirements.txt
fonttools==4.63.0 # via fpdf2
fpdf2==2.8.7 # via -r requirements.txt
itsdangerous==2.2.0 # via flask
jinja2==3.1.6 # via flask
markupsafe==3.0.3 # via flask, jinja2, werkzeug
pillow==12.2.0 # via -r requirements.txt, fpdf2
werkzeug==3.1.8 # via flask
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
# pip install -e ".[desktop]" (+ pywebview for the GUI launcher)
flask>=3.0,<4
fpdf2>=2.7,<3
pillow>=10.3.0
pillow>=12.2.0,<13
# pywebview is desktop-only — install with: pip install -e ".[desktop]"
Loading