Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-11 00:29:15 -05:00
Commit graph pkg-proxy/internal
Author SHA1 Message Date
Simon Chrzanowski
1fbcdc95c8 Rewrite project links in the PyPI root simple index
pypi.org's HTML root index links each project as /simple/<name>/. The
proxy relayed it unchanged, but it is mounted at /pypi, so following a
link went to /simple/<name>/ on the proxy and got 404. Rewrite those
hrefs to the proxy's /pypi/simple/ while streaming the response, since
the index is tens of megabytes. The JSON index has no links and is left
alone.
2026-11-08 08:01:34 +01:00
Simon Chrzanowski
81c6ea26c2 Treat git keys differing only in case as one repository
On a case-insensitive file system, as macOS and Windows use by default,
acme/WIDGETS and acme/widgets name the same cache directory but were
tracked as two repositories. Users of one spelling didn't keep the other
from being evicted, so eviction could move the directory away while it
was being read, and each entry had its own write lock, so two refreshes
could fetch into the directory at once.

Check at startup whether the cache directory ignores case and, if so,
track repositories under their lowercased key. The directory and the
upstream URL keep the spelling requested. Case-sensitive file systems,
and so existing caches on Linux, are unchanged.
2026-11-08 08:00:50 +01:00
Simon Chrzanowski
3860a6cae5 Don't cache Maven paths with dotted group directories
parsePath joins the group directories with dots, and the cache filename
is the file's base name, so org.foo/bar/1.0/bar-1.0.jar and
org/foo/bar/1.0/bar-1.0.jar shared one cache entry. Only upstreams that
serve content at such directories, such as raw or hosted repositories,
are affected.

The Maven layout splits a group at its dots, so a group directory never
contains a dot or is empty. Treat such paths as outside the layout and
proxy them uncached, which keeps every existing cache entry valid.
2026-11-08 08:00:50 +01:00
Simon Chrzanowski
fcdf8ebc3a Serve metadata with the validators of the bytes sent
Cached metadata responses took their ETag, Last-Modified and stale
flag from the cache row as it was after the fetch, not from the
document actually sent. When a refetch got a new document but could
not store it, the client got the new body with the old ETag and a
Warning header, and a client still holding the old document got a
304 for it. With metadata_ttl 0 the stale fallback had no Warning at
all, since staleness was inferred from the row's age.

The lookup result now carries the validators of its body (upstream's
for a fetched document, the row's for a stored one) and whether it is
a stale fallback, and the response is written from those.

A 304 also trusted whatever was stored at the row's path. Another
instance sharing the store may have replaced it meanwhile, and the
new bytes were then served and stored under the old ETag. The stored
bytes are now checked against the row's digest, and a 304 whose row
can no longer be refreshed is fetched again without validators
instead of storing the old document back over the new one.
2026-11-08 08:00:26 +01:00
Simon Chrzanowski
d073fdcd52 Close npm, PyPI and pub cooldown gaps in metadata and downloads
npm: a tarball request for a version the cached packument did not list
yet (cached within metadata_ttl before the release) found no publish
time and was let through cooldown, and fetched without integrity. When
cooldown applies and the cached packument lacks the version, fetch it
again and decide on what upstream lists now; if it can't be fetched,
fail as when a publish time can't be read.

npm: cooldown only moved dist-tags.latest. Other tags kept naming
versions in cooldown, while the denylist removes such tags. Cooldown
now removes them too, and drops latest when no version is left, in
both the in-memory and streamed rewrites.

PyPI: the simple JSON rewrite removed filtered files but left their
versions in the PEP 700 versions list. Remove them there too.

pub: latest was never rewritten, so its archive_url pointed at pub.dev,
it kept naming a version in cooldown when no version was left, and the
replacement was the last list entry, which may be a prerelease. Point
latest's archive_url at the proxy, replace a held back latest with the
newest stable version left (or the newest prerelease), and drop it
when nothing is left.
2026-11-08 08:00:14 +01:00
Simon Chrzanowski
2a6c809103 Reject negative and out-of-range sizes and TTLs
ParseSize accepted "-5GB", "NaNGB", "InfGB" and "1e30GB", the last
two clamping to the largest int64. A negative or NaN storage.max_size
passed validation, and eviction treats a limit of zero or less as
unlimited.

Reject negative, NaN, infinite and overflowing sizes in ParseSize, and
reject negative metadata_ttl and storage.direct_serve_ttl at startup.
2026-11-08 07:58:49 +01:00
Simon Chrzanowski
6398ed63f6 Validate and normalise scanner ecosystem names
scanning.scanners[].ecosystems was never checked, and the scanner group
compared it exactly against the keys handlers pass. Natural names such
as go, docker and rubygems passed validation but never matched the
handler keys golang, oci and gem, so a block-mode scanner restricted to
them silently never ran.

Map common aliases to the handler keys, reject unknown names at
startup, and normalise the names again when building the group.
2026-11-08 07:57:30 +01:00
Simon Chrzanowski
0b399c248d Accept sha512 OCI blob digests and check HEAD digests
The blob route and blobPathPattern only matched sha256 digests, so a
sha512 blob got 404 although the fetch path can verify sha512. The image
mirror rejected sha512 digests in index entries, configs and layers for
the same reason. Accept sha512 in both, with exact digest lengths.

A HEAD for an uncached manifest by digest passed on whatever digest the
upstream named. GET checks the body against the requested digest; HEAD
now answers DIGEST_INVALID when the upstream names a different digest
of the same algorithm.
2026-11-08 07:57:26 +01:00
Simon Chrzanowski
b9f047f8dc Parse boolean environment variables strictly
Every boolean PROXY_* variable was true only for exactly "true" or
"1". Anything else, including "True", "TRUE" or a typo, silently
meant false, so PROXY_SCANNING_ENABLED=True turned scanning off and
validation still passed.

Parse them with strconv.ParseBool like
PROXY_GRADLE_BUILD_CACHE_READ_ONLY already does. An unrecognised value
now keeps the current setting and is logged as a warning at startup.
2026-11-08 07:56:56 +01:00
Simon Chrzanowski
cbbeed423b Cache RPM packages under their full path
RPM packages were cached under their bare filename. With upstream.rpm
pointing at a mirror root that serves several distributions, Rocky and
Alma both publish bash-5.1.8-9.el9.x86_64.rpm with different bytes, and
whichever was fetched first was served for both, so dnf failed the
checksum or signature check.

Use the path under the upstream as the cache filename, as the APK and
Arch handlers do. Packages cached before this change are no longer
found and are fetched again once; retention still matches them by
package name.
2026-11-08 07:56:52 +01:00
Simon Chrzanowski
70d9db2906 Add CRAN routes for macOS arch layout and Meta files
R 4.3 and later on macOS fetch binaries from a two-segment platform path
such as bin/macosx/big-sur-arm64/contrib/4.4/. The router only matched a
single platform segment, so both the PACKAGES indexes and the .tgz
downloads returned 404. Add routes for that layout and include the arch
in the stored version so arm64 and x86_64 builds stay apart.

src/contrib/Meta/archive.rds and current.rds, which remotes and pak use
to install archived versions, had no route either. Serve .rds files under
Meta as cached metadata.
2026-11-08 07:55:24 +01:00
Milas Bowman
ae0be48b36
chore: clean-up/clarity around signing across providers 2026-11-07 18:29:31 -05:00
Milas Bowman
9f400c34af
fix: compile error in cooldown after merge (remove direct serve URL) 2026-11-07 17:13:27 -05:00
Milas Bowman
163665f4dc
Merge remote-tracking branch 'upstream/main' into milas/s3-fixes 2026-11-07 17:09:37 -05:00
Milas Bowman
dadc94dd62
chore: add some godoc on modified complex funcs 2026-11-07 17:06:44 -05:00
Milas Bowman
e4bc1f5f11
fix: do not prepend host on signing 2026-11-07 16:50:24 -05:00
Milas Bowman
7d84bf7682
chore: remove deb source pkg logic / fix root-level pkg caching 2026-11-07 15:31:42 -05:00
Milas Bowman
5c1eaa9fe5
chore: test reliability / godoc on methods
Code review feedback
2026-11-07 13:57:40 -05:00
Simon Chrzanowski
d58b07b2a7 Skip discarded npm packument values with jsontext
ScanPackument and LookupVersion read with a jsontext.Decoder, skipping
values they don't keep with SkipValue and reading the one LookupVersion
returns with ReadValue, instead of decoding each into a json.RawMessage.
Repeated names and invalid UTF-8 are still accepted as encoding/json
accepts them. Go 1.27 is now required, for encoding/json/jsontext.

Benchmarks for both use the 5,000-version packument the handler benchmarks
build, now shared in internal/metadata/npm/npmbench.
2026-11-07 18:02:59 +01:00
Simon Chrzanowski
7f2ac614c4 Mirror commits whose .gitmodules lists no submodule
git config --get-regexp exits 1 when nothing matches, which failed the
mirror of a commit with an empty .gitmodules. The submodules are now read
from --list.
2026-11-07 17:51:13 +01:00
Simon Chrzanowski
e9aa078a85 Mirror pkg:git tags and the submodules a commit pins
A pkg:git version can now be a tag as well as a full commit ID. With a
version, the submodules the commit records are mirrored at the commits it
pins, from the upstream.git hosts serving them; one no host serves is
skipped with a warning.
2026-11-07 17:29:03 +01:00
Simon Chrzanowski
794ea98a28 Match abi3 wheels whatever minimum Python they name
The python tag of an abi3 wheel is a minimum, so cp38-abi3 and cp311-abi3
wheels are now the same kind as a cached cp39-abi3 one.
2026-11-07 17:04:29 +01:00
Simon Chrzanowski
c0ae2e98b3 Merge remote-tracking branch 'origin/main' into feat/mirror-refresh
# Conflicts:
#	internal/database/schema.go
2026-11-07 17:01:32 +01:00
Andrew Nesbitt
72aa8fdc43
Merge pull request #667 from simonchrz/feat/mirror-git
Mirror pkg:git commits into the git cache
2026-11-07 14:58:02 +00:00
Andrew Nesbitt
7e18c6a020
Merge pull request #664 from simonchrz/fix/retention-mirrored-images
Keep blobs of scheduled images from retention
2026-11-07 14:43:06 +00:00
Andrew Nesbitt
f153a83b3a
Cover Fedora updates and Conda defaults in setup docs 2026-11-07 09:46:54 +00:00
Milas Bowman
611feb003a
fix(debian): route packages by filename rather than /pool prefix 2026-11-06 20:12:14 -05:00
Milas Bowman
f82ec69006
fix(storage): restore Azure/GCS direct serve signing 2026-11-06 20:06:36 -05:00
Milas Bowman
909e2e464a
fix(s3): signatures for alternate hosts 2026-11-06 19:28:45 -05:00
Andrew Nesbitt
292ecc1488
Correct package manager configuration examples 2026-11-06 22:36:47 +00:00
Simon Chrzanowski
b0566aa456 Fail a mirror whose refresh is past max_repo_size
The repository is dropped once released, so a cached commit in it would
not be served for long.
2026-11-06 13:00:31 +01:00
Simon Chrzanowski
abe94017a1 Renew wanted refs of mirrored commits and count refreshes that fetched
Mirroring a commit on no branch or tag again writes a fresh wanted ref, so
its 7 days count from the last mirror run. A cached repository whose refresh
fetched new commits is no longer reported as cached.
2026-11-06 11:36:42 +01:00
Andrew Nesbitt
563f58e5cc
Merge pull request #666 from git-pkgs/cooldown-profiles
Add cooldown profiles selected by registry URL
2026-11-06 09:59:37 +00:00
Andrew Nesbitt
691088b947
Merge pull request #658 from git-pkgs/hide-stats-connection-details
Remove connection details from stats response
2026-11-06 09:40:43 +00:00
Andrew Nesbitt
c2dd16903a
Share publish indexes across cooldown profiles 2026-11-06 09:38:07 +00:00
Andrew Nesbitt
0ed91b5872
Redact storage passwords in startup logs 2026-11-06 09:20:43 +00:00
Simon Chrzanowski
03be03b8fe Mirror pkg:git commits into the git cache
proxy mirror, mirror API jobs and SBOMs take pkg:git/{host}/{path}@{commit}
and cache the repository and commit in the cache /git serves, so a later
clone is a cache hit, also with the upstream down. Part of #403.
2026-11-06 07:48:51 +01:00
Andrew Nesbitt
79be33049a
Add cooldown profiles selected by registry URL 2026-11-05 21:42:44 +00:00
Andrew Nesbitt
61ac273862
Check primary metadata before allowing untimed downloads 2026-11-05 20:00:19 +00:00
Andrew Nesbitt
b9dcbd27fc
Handle cooldown lookup failures and reuse download indexes 2026-11-05 18:41:03 +00:00
Christian Heim
3ab7dcc1dc
The UTC test compares the zone offset, since Postgres reads TIMESTAMP back as a fixed +0000 zone rather than time.UTC. 2026-11-05 18:30:44 +00:00
Christian Heim
5db16cbb99
Conda reads repodata as a stream for the download check, under the same bound as the repodata filter, so a repodata.json over metadata_max_size no longer lets a package in cooldown through. If even the compressed copy is too large to cache, the check streams it from upstream. 2026-11-05 18:30:44 +00:00
Christian Heim
89c60abd1a
Conda now checks each package file against its own timestamp, because builds of one version differ. Conda repodata and helm indexes are parsed once per cached document instead of on every download. 2026-11-05 18:30:43 +00:00
Christian Heim
3456b394be
Cargo, gem, hex, pub, conda and helm now check cooldown on artifact downloads too, so a version inside the window is withheld even when it was cached before. Publish times are stored in UTC. Fixes #521. 2026-11-05 18:30:42 +00:00
Simon Chrzanowski
0300ad2522 Limit APKINDEX to maxIndexBytes once decompressed 2026-11-05 17:44:12 +01:00
Simon Chrzanowski
14d04955b4 Match wheels on any of their alternative tags 2026-11-05 17:43:33 +01:00
Simon Chrzanowski
0f26841f56 Keep blobs of scheduled images from retention
A mirror run that finds a blob cached records it in mirrored_at, which
retention counts as use. LRU eviction keeps using last_accessed_at, so
#508's decision not to count mirror runs as cache hits stands.

Fixes #648.
2026-11-05 17:39:19 +01:00
Simon Chrzanowski
34524a4056 Limit a refreshed index to 512 MiB once decompressed 2026-11-05 17:20:06 +01:00
Simon Chrzanowski
f8c5fa9a1d Match wheels on OS and architecture, and conda builds without the hash anywhere 2026-11-05 17:18:56 +01:00
Andrew Nesbitt
308cc133ab
Remove connection details from stats response 2026-11-05 15:09:16 +00:00