scripts/relock.ps1
Rama main · réplica de lectura del repositorio original.
<#
.SYNOPSIS
Regenerate backend/requirements*.txt with the exact uv commands CI checks
against, so the "Lock freshness check" gate in .github/workflows/ci.yml
passes.
.DESCRIPTION
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
relock.sh and pushes the result (with a PAT, because a GITHUB_TOKEN push
starts no workflow runs). Run this by hand after editing a .in file
yourself, or when that workflow's RELOCK_TOKEN secret is missing.
.EXAMPLE
./scripts/relock.ps1
#>
[CmdletBinding()]
param()
# Deliberately NOT 'Stop'. Both native commands here write to stderr on the
# happy path -- uv reports "Resolved N packages" and git emits CRLF warnings --
# and Windows PowerShell turns any native stderr into a NativeCommandError when
# this is 'Stop', which would abort a perfectly successful run. Correctness
# comes from the explicit $LASTEXITCODE checks below instead, and leaving
# stderr on the console is what makes a real resolution error visible.
$ErrorActionPreference = 'Continue'
$repoRoot = Split-Path -Parent $PSScriptRoot
$backend = Join-Path $repoRoot 'backend'
if ($null -eq (Get-Command uv -ErrorAction SilentlyContinue)) {
throw 'uv not found. Install it: pipx install uv (or) pip install uv'
}
Push-Location $backend
try {
Write-Host "$(uv --version) - 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 is left alone so a
# resolution error still surfaces.
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" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "uv pip compile failed for requirements.in (exit $LASTEXITCODE)" }
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" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "uv pip compile failed for requirements-dev.in (exit $LASTEXITCODE)" }
git diff --quiet -- requirements.txt requirements-dev.txt
if ($LASTEXITCODE -eq 0) {
Write-Host 'Locks already match the .in files. Nothing to do.'
return
}
git --no-pager diff --stat -- requirements.txt requirements-dev.txt
Write-Host @'
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.
'@
}
finally {
Pop-Location
}