Skip to content

Commit 52e202f

Browse files
committed
Control dependencies more carefully and ensure frequent updates
1 parent 65dca05 commit 52e202f

File tree

6 files changed

+121
-37
lines changed

6 files changed

+121
-37
lines changed

.pre-commit-config.yaml

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ repos:
33
- repo: meta
44
hooks:
55
- id: check-hooks-apply
6-
name: run check hooks apply
6+
name: check that hooks apply
77
description: check that all the hooks apply to the repository
88
- repo: https://github.com/pre-commit/pre-commit-hooks
99
rev: v6.0.0
@@ -30,7 +30,7 @@ repos:
3030
rev: v1.5.5
3131
hooks:
3232
- id: insert-license
33-
name: Add license for all Python files
33+
name: add a license for all Python files
3434
files: ^(atr|scripts|tests)/(.*\.py$|.*\.pyi)$
3535
args:
3636
- --comment-style
@@ -39,7 +39,7 @@ repos:
3939
- scripts/ci/LICENSE-template.txt
4040
- --fuzzy-match-generates-todo
4141
- id: insert-license
42-
name: Add license for JS and TS files
42+
name: add a license for JS and TS files
4343
files: ^atr/static/(js/src/.*\.js|ts/.*\.ts)$
4444
args:
4545
- --comment-style
@@ -51,7 +51,7 @@ repos:
5151
rev: v0.47.0
5252
hooks:
5353
- id: markdownlint
54-
name: run markdownlint
54+
name: run Markdown lints
5555
description: check Markdown files with markdownlint
5656
args: [--config=.github/linters/.markdown-lint.yml]
5757
types: [markdown]
@@ -105,7 +105,7 @@ repos:
105105
rev: v1.33.0
106106
hooks:
107107
- id: oxlint
108-
name: Oxlint JS Linter
108+
name: lint JS files with Oxlint
109109
types: [javascript]
110110
files: ^atr/static/js/src/.*\.js$
111111
args:
@@ -134,21 +134,21 @@ repos:
134134
- repo: local
135135
hooks:
136136
- id: ruff
137-
name: Ruff Linter
138-
entry: uv run ruff check --fix
137+
name: lint Python files with Ruff
138+
entry: uv run --frozen ruff check --fix
139139
language: system
140140
types: [python]
141141

142142
- id: ruff-format
143-
name: Ruff Formatter
144-
entry: uv run ruff format --force-exclude
143+
name: format Python files with Ruff
144+
entry: uv run --frozen ruff format --force-exclude
145145
language: system
146146
types: [python]
147147

148148
- id: biome-format
149149
# Install biome from https://biomejs.dev/guides/manual-installation/
150150
# Avoid using NPM to install it until #359 is resolved
151-
name: Biome JS Formatter
151+
name: format JS files with Biome
152152
entry: biome format --write --files-ignore-unknown=true --no-errors-on-unmatched --colors=off
153153
language: system
154154
types: [javascript]
@@ -157,24 +157,32 @@ repos:
157157
- id: biome-check
158158
# Install biome from https://biomejs.dev/guides/manual-installation/
159159
# Avoid using NPM to install it until #359 is resolved
160-
name: Biome JS Linter
160+
name: lint JS files with Biome
161161
entry: biome check --write --error-on-warnings --files-ignore-unknown=true --no-errors-on-unmatched --colors=off
162162
language: system
163163
types: [javascript]
164164
files: ^atr/static/js/src/.*\.js$
165165

166166
- id: pyright
167-
name: Pyright Type Check
168-
entry: uv run pyright
167+
name: type check Python files with Pyright
168+
entry: uv run --frozen pyright
169169
language: system
170170
require_serial: true
171171
types: [python]
172172
exclude: ^tests/
173173

174174
- id: jinja-route-check
175-
name: Jinja Route Checker
175+
name: check Jinja2 routes
176176
description: Check whether routes used in Jinja2 templates actually exist
177-
entry: uv run python scripts/lint/jinja_route_checker.py
177+
entry: uv run --frozen python scripts/lint/jinja_route_checker.py
178+
language: system
179+
pass_filenames: false
180+
always_run: true
181+
182+
- id: check-when-dependencies-updated
183+
name: check when dependencies were updated
184+
description: Verify that dependencies were updated within the configured timeframe, for ASVS 15.2.1
185+
entry: uv run --frozen python scripts/check_when_dependencies_updated.py
178186
language: system
179187
pass_filenames: false
180188
always_run: true

.pre-commit-light.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ repos:
33
- repo: local
44
hooks:
55
- id: ruff
6-
name: Ruff Linter
6+
name: ruff linter
77
entry: ruff check --fix
88
language: system
99
types: [python]
1010

1111
- id: ruff-format
12-
name: Ruff Formatter
12+
name: ruff formatter
1313
entry: ruff format --force-exclude
1414
language: system
1515
types: [python]
1616

1717
- id: pyright
18-
name: Pyright Type Check
18+
name: pyright type check
1919
entry: pyright
2020
language: system
2121
require_serial: true

Makefile

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ bump-bootstrap:
3737

3838
certs:
3939
if test ! -f state/cert.pem || test ! -f state/key.pem; \
40-
then uv run scripts/generate-certificates; \
40+
then uv run --frozen scripts/generate-certificates; \
4141
fi
4242

4343
certs-local:
4444
cd state && mkcert localhost.apache.org localhost 127.0.0.1 ::1
4545

4646
check:
4747
git add -A
48-
uv run pre-commit run --all-files
48+
uv run --frozen pre-commit run --all-files
4949

5050
check-extra:
5151
@git add -A
@@ -54,11 +54,11 @@ check-extra:
5454

5555
check-heavy:
5656
git add -A
57-
uv run pre-commit run --all-files --config .pre-commit-heavy.yaml
57+
uv run --frozen pre-commit run --all-files --config .pre-commit-heavy.yaml
5858

5959
check-light:
6060
git add -A
61-
uv run pre-commit run --all-files --config .pre-commit-light.yaml
61+
uv run --frozen pre-commit run --all-files --config .pre-commit-light.yaml
6262

6363
commit:
6464
git add -A
@@ -68,16 +68,16 @@ commit:
6868

6969
docs:
7070
mkdir -p docs
71-
uv run python3 scripts/docs_check.py
71+
uv run --frozen python3 scripts/docs_check.py
7272
rm -f docs/*.html
73-
uv run python3 scripts/docs_build.py
73+
uv run --frozen python3 scripts/docs_build.py
7474
for fn in atr/docs/*.md; do out=$${fn#atr/}; cmark "$$fn" > "$${out%.md}.html"; done
75-
uv run python3 scripts/docs_post_process.py docs/*.html
76-
uv run python3 scripts/docs_check.py
75+
uv run --frozen python3 scripts/docs_post_process.py docs/*.html
76+
uv run --frozen python3 scripts/docs_check.py
7777

7878
generate-version:
7979
@rm -f atr/version.py
80-
@uv run python3 atr/metadata.py > /tmp/version.py
80+
@uv run --frozen python3 atr/metadata.py > /tmp/version.py
8181
@mv /tmp/version.py atr/version.py
8282
@cat atr/version.py
8383

@@ -101,23 +101,23 @@ run-playwright-slow:
101101
docker run --net=host -it atr-playwright python3 test.py --tidy
102102

103103
serve:
104-
SSH_HOST=127.0.0.1 uv run hypercorn --bind $(BIND) \
104+
SSH_HOST=127.0.0.1 uv run --frozen hypercorn --bind $(BIND) \
105105
--keyfile localhost.apache.org+3-key.pem --certfile localhost.apache.org+3.pem \
106106
atr.server:app --debug --reload
107107

108108
serve-local:
109109
APP_HOST=localhost.apache.org:8080 SECRET_KEY=insecure-local-key \
110-
ALLOW_TESTS=1 SSH_HOST=127.0.0.1 uv run hypercorn --bind $(BIND) \
110+
ALLOW_TESTS=1 SSH_HOST=127.0.0.1 uv run --frozen hypercorn --bind $(BIND) \
111111
--keyfile localhost.apache.org+3-key.pem --certfile localhost.apache.org+3.pem \
112112
atr.server:app --debug --reload
113113

114114
sync:
115-
uv sync --no-dev
115+
uv sync --frozen --no-dev
116116

117117
sync-all:
118-
uv sync --all-groups
118+
uv sync --frozen --all-groups
119119

120120
update-deps:
121121
pre-commit autoupdate || :
122-
uv lock --upgrade
123-
uv sync --all-groups
122+
uv lock --upgrade --exclude-newer "$$(date -u +%Y-%m-%dT%H:%M:%SZ)"
123+
uv sync --frozen --all-groups

notes/development.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ You will need to have a working [Python 3.13](https://www.python.org/downloads/r
55
Ensure that you have the pre-commit hook installed:
66

77
```shell
8-
make sync PYTHON="$(which python3)"
9-
poetry run pre-commit install
8+
make sync-all
9+
uv run --frozen pre-commit install
1010
```
1111

12-
To run the project, use the following commands, which will add a local CA root to your OS and browser certificate qstore if using Firefox:
12+
To run the project, use the following commands, which will add a local CA root to your OS and browser certificate store if using Firefox:
1313

1414
```shell
15-
uv sync --all-groups
15+
make sync-all
1616
make certs-local
1717
make serve
1818
```
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env python3
2+
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
import datetime
21+
import pathlib
22+
import sys
23+
from typing import Final
24+
25+
_MAX_AGE_DAYS: Final[int] = 30
26+
27+
28+
def main() -> None:
29+
lock_path = pathlib.Path("uv.lock")
30+
if not lock_path.exists():
31+
print("ERROR: uv.lock not found", file=sys.stderr)
32+
sys.exit(1)
33+
34+
exclude_newer = _parse_exclude_newer(lock_path)
35+
if exclude_newer is None:
36+
print("ERROR: No exclude-newer timestamp in uv.lock", file=sys.stderr)
37+
print("Run: make update-deps", file=sys.stderr)
38+
sys.exit(1)
39+
40+
timestamp = _parse_timestamp(exclude_newer)
41+
if timestamp is None:
42+
print(f"ERROR: Could not parse timestamp: {exclude_newer}", file=sys.stderr)
43+
sys.exit(1)
44+
45+
now = datetime.datetime.now(datetime.UTC)
46+
age = now - timestamp
47+
48+
if age > datetime.timedelta(days=_MAX_AGE_DAYS):
49+
print(f"ERROR: Dependencies are {age.days} days old (the limit is {_MAX_AGE_DAYS} days)", file=sys.stderr)
50+
print(f"Last updated: {exclude_newer}", file=sys.stderr)
51+
print("Run: make update-deps", file=sys.stderr)
52+
sys.exit(1)
53+
54+
print(f"OK: Dependencies are {age.days} days old (the limit is {_MAX_AGE_DAYS} days)")
55+
56+
57+
def _parse_exclude_newer(lock_path: pathlib.Path) -> str | None:
58+
for line in lock_path.read_text(encoding="utf-8").splitlines():
59+
if line.startswith("exclude-newer"):
60+
_, _, value = line.partition("=")
61+
return value.strip().strip('"')
62+
return None
63+
64+
65+
def _parse_timestamp(timestamp_str: str) -> datetime.datetime | None:
66+
try:
67+
return datetime.datetime.fromisoformat(timestamp_str.replace("Z", "+00:00"))
68+
except ValueError:
69+
return None
70+
71+
72+
if __name__ == "__main__":
73+
main()

uv.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)