scripts/relock.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
#
# Regenerate backend/requirements*.txt with the exact uv commands CI checks
# against, so the "Lock freshness check" gate in .github/workflows/ci.yml
# passes.
#
# Why this exists: Dependabot does not use uv. It rewrites the locks in its own
# style, which differs from `uv pip compile --universal` three ways:
#
# 1. Environment markers are dropped. uvloop loses its
# `sys_platform != 'win32'` guard and pywin32/colorama/async-timeout/tomli
# disappear entirely. This is the load-bearing one -- uvloop publishes no
# Windows wheel, so an unguarded pin makes `pip install` fail on a Windows
# checkout, and the repo is developed on Windows.
# 2. Extras are written into the pin (`sqlalchemy[asyncio]`,
# `httpx[brotli,http2,socks]`, `coverage[toml]`, `fakeredis[lua]`,
# `scrapling[fetchers]`, `sentry-sdk[fastapi]`). uv resolves extras but
# emits the bare name, so these are pure drift against the gate.
# 3. The dev lock's `# via -c requirements.txt` annotations collapse away.
#
# The gate compares byte-for-byte, so every pip Dependabot PR needs the locks
# regenerated before it can merge.
#
# For Dependabot's own pip PRs, .github/workflows/dependabot.yml runs this
# script and pushes the result (with a PAT, because a GITHUB_TOKEN push starts
# no workflow runs). Run it by hand after editing a .in file yourself, or when
# that workflow's RELOCK_TOKEN secret is missing.
#
# Usage:
# ./scripts/relock.sh # regenerate on the current branch
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKEND="$(dirname "$SCRIPT_DIR")/backend"
if [ "$#" -gt 0 ]; then
echo "unexpected argument: $1 (this script takes none)" >&2
exit 2
fi
if ! command -v uv >/dev/null 2>&1; then
echo "uv not found. Install it: pipx install uv (or) pip install uv" >&2
exit 1
fi
cd "$BACKEND"
echo "uv $(uv --version | awk '{print $2}') - regenerating locks in $BACKEND"
# Copied verbatim from CI. --custom-compile-command pins the header line
# independently of how the command was typed, so an identical resolution
# invoked with a different argument order does not rewrite it.
#
# uv echoes the whole compiled lock to stdout on top of writing -o, which buries
# the diff this script exists to show; stderr (resolution errors) is kept.
uv pip compile requirements.in -o requirements.txt \
--universal --python-version 3.11 --generate-hashes \
--custom-compile-command "uv pip compile requirements.in -o requirements.txt --universal --python-version 3.11 --generate-hashes" >/dev/null
uv pip compile requirements-dev.in -o requirements-dev.txt \
--universal --python-version 3.11 --generate-hashes -c requirements.txt \
--custom-compile-command "uv pip compile requirements-dev.in -o requirements-dev.txt --universal --python-version 3.11 --generate-hashes -c requirements.txt" >/dev/null
if git diff --quiet -- requirements.txt requirements-dev.txt; then
echo "Locks already match the .in files. Nothing to do."
exit 0
fi
git --no-pager diff --stat -- requirements.txt requirements-dev.txt
cat <<'EOF'
Regenerated. Review the diff, then commit on the PR branch:
git add backend/requirements.txt backend/requirements-dev.txt
git commit -m "chore(backend): regenerate locks with the documented uv commands"
git push
If CI still reports drift after this, your uv is older than the one CI installs
(it runs a bare `pip install uv`, i.e. the latest release). Run `uv self update`
and regenerate again.
EOF