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
55f1b1e2da Reject a negative mirror.refresh.max_bytes 2026-11-05 14:53:36 +01:00
Simon Chrzanowski
010ed4761a Skip index entries whose path leaves the repository 2026-11-05 13:51:07 +01:00
Simon Chrzanowski
6f3e8c6f7e Merge remote-tracking branch 'origin/main' into feat/mirror-refresh
# Conflicts:
#	internal/database/schema.go
2026-11-05 13:50:08 +01:00
Simon Chrzanowski
903fd94df9 Test that apk index errors leave out the URL 2026-11-05 12:34:32 +01:00
Simon Chrzanowski
eb34a1ac6f Name the apk repository, not its URL, in index errors 2026-11-05 12:33:46 +01:00
Simon Chrzanowski
5c46a39b2d Merge remote-tracking branch 'origin/main' into feat/mirror-refresh
# Conflicts:
#	internal/database/schema.go
2026-11-05 12:21:49 +01:00
Simon Chrzanowski
4d70793351 Name the apk repository in mirror errors 2026-11-05 11:56:42 +01:00
Simon Chrzanowski
c20f64ebaa Keep the apk namespace for the mirror's repository lookup
The inventory drops the namespace from apk names so they match the
handler's, but the apk mirror picks the upstream.apk repository from it.
2026-11-05 10:48:44 +01:00
Simon Chrzanowski
1e916bf334 Merge remote-tracking branch 'origin/main' into feat/project-inventory 2026-11-05 10:47:14 +01:00
Simon Chrzanowski
7095ab67ef Keep the Projects link on an empty projects page
ProjectsListData.Projects hid Layout.Projects, so the header left the
link out when no project had been uploaded.
2026-11-04 16:16:35 +01:00
Simon Chrzanowski
4e25396331 Refuse distro qualifiers that aren't an Alpine release 2026-11-04 16:09:00 +01:00
Simon Chrzanowski
6d3410df41 Use sbom's ProjectRoots for the project's own packages
Drop projectRoots and readFromLockFile; sbom now decides which inferred
roots are the project. sbom is on the merge commit of git-pkgs/sbom#27
until it is tagged.
2026-11-04 16:05:16 +01:00
Simon Chrzanowski
adcda6ca8b Read APKINDEX.tar.gz also where Packages.adb is served beside it 2026-11-04 15:54:10 +01:00
Simon Chrzanowski
3e2a84a88a Mirror Alpine packages
The PURL namespace names the upstream.apk repository, and the distro and
arch qualifiers syft writes give the release and architecture. The package
is looked up in the main and community indexes of that release and cached
under the path the APK handler serves it from.
2026-11-04 15:44:01 +01:00
Simon Chrzanowski
88c0ba8ab3 Use sbom's root detection for the project's own packages
Bump sbom to v0.1.8 and replace lockFileRoots with sbom.Roots. Inferred
roots count as the project only when read from a lock file, so an image's
packages that nothing depends on are kept.
2026-11-04 13:20:29 +01:00
Simon Chrzanowski
e358666482 Merge remote-tracking branch 'origin/main' into feat/project-inventory
# Conflicts:
#	internal/database/database_test.go
#	internal/database/schema.go
#	internal/server/server.go
2026-11-04 13:19:09 +01:00
Simon Chrzanowski
82b45cbb1b Merge remote-tracking branch 'origin/main' into feat/composer-advisories
# Conflicts:
#	README.md
2026-11-04 13:05:10 +01:00
Andrew Nesbitt
5b10559636
Merge pull request #639 from simonchrz/feat/cooldown-withheld-versions
Show versions held back by cooldown on the package page and in the API
2026-11-04 12:01:24 +00:00
Simon Chrzanowski
cb330a5cbf Answer 502 when a Composer download's metadata lookup fails upstream
The lookup took any non-200 metadata response for a version that isn't
listed, so a Packagist outage or rate limit answered the archive request
with 404. Composer treats that as the version being gone.

Only 404 and 410 now mean the document is missing. A 429 is passed on as
503 with Retry-After while the upstream is held, and any other status
answers 502.
2026-11-03 20:10:24 +01:00
Simon Chrzanowski
683455aecb Test available_at through the API and drop FillVersionPublishedAt
The API handler takes the enrichment calls it uses as an interface, so
the test can answer them without reaching a registry.

Remove FillVersionPublishedAt until the shared cooldown filter calls it.
2026-11-03 14:39:36 +01:00
Simon Chrzanowski
8aebf94f5d Merge remote-tracking branch 'origin/main' into feat/change-feeds
# Conflicts:
#	go.mod
#	go.sum
2026-11-03 11:23:40 +01:00
Simon Chrzanowski
83524b7485 Merge remote-tracking branch 'origin/main' into feat/cooldown-withheld-versions 2026-11-03 11:23:22 +01:00
Andrew Nesbitt
c1a1149bd8
Merge pull request #622 from simonchrz/feat/apk-snapshots
Serve dated snapshots of Alpine APK indexes
2026-11-03 09:36:40 +00:00
Andrew Nesbitt
abee8ef879
Merge pull request #640 from simonchrz/feat/npm-stream-rewrite
Stream npm packuments through storage when rewriting them
2026-11-03 09:33:36 +00:00
Andrew Nesbitt
7cb905638c
Keep proxyCachedWithEncoding doc on the function it describes 2026-11-03 09:28:29 +00:00
Andrew Nesbitt
47ed4b4194
Merge pull request #649 from simonchrz/fix/truncated-upstream-metadata
Fail metadata reads when upstream cuts a document off
2026-11-03 09:22:25 +00:00
Andrew Nesbitt
83a0822979
Merge pull request #644 from simonchrz/mirror-parallel-blobs
Fetch an image's blobs concurrently when mirroring
2026-11-03 09:15:16 +00:00
Simon Chrzanowski
26cae44e41 Bump cooldown to v0.3.1 and set cooldown directly in stream tests
v0.3.1 parses a Config once when it is first used concurrently, so the
stream tests no longer need cooldown.NewPolicy.
2026-11-02 11:33:11 +01:00
Simon Chrzanowski
98ff4fd4a2 Merge remote-tracking branch 'origin/main' into feat/npm-stream-rewrite
# Conflicts:
#	cmd/proxy/main.go
2026-11-01 12:54:47 +01:00
Simon Chrzanowski
b08cebf9e4 Cap npm packuments streamed into storage
metadata_max_size bounds what is read into memory, but a packument
streamed from upstream into storage had no limit, and with cooldown was
stored twice. It is now capped by metadata_stream_max_size, 1 GB by
default. A document over the cap fails as an upstream failure: nothing is
stored, and the stored copy, if any, is served instead.

The metadata settings move into configureMetadata to keep serve under
the maintidx limit.
2026-11-01 12:53:00 +01:00
Simon Chrzanowski
6dbda21faf Move the in-memory truncation fix to its own pull request
The change to ReadMetadataSized and fetchUpstreamMetadata, with its tests,
is now #649. upstreamBodyReader stays for storeUpstreamMetadata, in a file
of its own that #649 adds with the same content.
2026-11-01 12:49:09 +01:00
Simon Chrzanowski
143eef7f05 Test snapshots on cache hits and record them through proxyCachedWithEncoding
TestAPKSnapshots_CacheHit covers the cache-hit branch with a metadata TTL
above 0. proxyCachedWithEncoding takes optional hooks for a cache hit and a
fetched body, so the APK handler no longer keeps a copy of it.
2026-11-01 12:48:37 +01:00
Simon Chrzanowski
358b1355a9 Fail metadata reads when upstream cuts a document off
ReadMetadataSized took the transport's io.ErrUnexpectedEOF for the end of
a body shorter than its size hint. A document upstream closed before its
Content-Length was served with a 200 and cached, or failed the cooldown
filter with a 502, instead of the cached copy being served. Upstream
bodies are now read through a reader that marks their read errors, and
such a body fails the read as an upstream failure.
2026-11-01 12:48:04 +01:00
Simon Chrzanowski
7b91897fbb Merge remote-tracking branch 'origin/main' into feat/apk-snapshots
# Conflicts:
#	internal/server/server.go
2026-11-01 12:44:35 +01:00
Simon Chrzanowski
3a0e79d6b4 Fuzz SBOM parsing and test concurrent project uploads
FuzzParse checks that an uploaded body never makes the inventory panic
and that every component it records has a package URL, ecosystem and
version. TestSaveProjectConcurrentUploads saves one project from eight
uploads at once and checks that each succeeds and the components of
exactly one remain.
2026-10-31 18:26:17 +01:00
Simon Chrzanowski
fd16ba1664 Let in-flight blobs finish when one fails
errgroup.WithContext cancelled the blobs being fetched as soon as one
failed. A client pull sharing one of those fetches failed with it, and the
next run had to fetch them again. A failure now only stops further blobs
from starting.
2026-10-31 18:15:11 +01:00
Simon Chrzanowski
83a018bfd4 Test that stats versions add up with orphan publish times
Covers namespaced npm and Maven PURLs, a publish time under an alias of
a package row's ecosystem, and a PURL starting with the orphan prefix,
and checks the per-ecosystem versions against GetCacheStats' total.
2026-10-31 18:09:05 +01:00
Simon Chrzanowski
b73980e8ed Refresh each suite of a shared Debian pool on its own
An index file was mirrored only when it was newer than every cached
version of the package and architecture. Debian suites share one pool, so
once curl from trixie was cached, bookworm's security updates to curl
were older than it and never mirrored. A run now mirrors the newest file
an index lists when it isn't cached and an older version is, which still
never downgrades and leaves a suite alone that only has a newer version
cached.

Tests also cover repositories listing several versions, an unreadable
index next to working ones, Architecture: all packages, scoped npm
packages, denied releases, a listing failure next to other packages, a
cancelled run and Go version lines.
2026-10-31 17:58:00 +01:00
Simon Chrzanowski
f0c96e87a8 Keep the stored copy when upstream cuts a metadata document off
A body that ended before its Content-Length was read as complete in
memory: ReadMetadataSized took the transport's io.ErrUnexpectedEOF for
the end of a body shorter than its size hint. The half document was
served and cached, or failed the filter with a 502, instead of the stored
copy being served. Upstream bodies are now read through a reader that
marks their read errors, and such a failure is an upstream failure on
both paths: streamed, it no longer counts as a failure to store, which
had sent the request to the bounded in-memory path.

A stored packument whose bytes no longer match its row's digest is now
fetched again like a missing one.

Tests also cover concurrent requests sharing one fetch, client
revalidation and upstream failures with nothing cached. The stream tests
build cooldown through cooldown.NewPolicy as the server does, since a
bare cooldown.Config parses itself on first use without locking.
2026-10-31 17:50:24 +01:00
Simon Chrzanowski
11ff4cf314 Fetch an npm packument again when its stored copy is gone within the TTL
A row within its TTL was served without checking its blob, so a missing
blob failed the streamed read and the request fell back to the bounded
in-memory path. A read that finds the stored copy missing now fetches the
packument again into storage, ignoring that row, and reads it once more,
for packument, version and tarball requests.
2026-10-31 16:55:15 +01:00
Simon Chrzanowski
c4979b9e76 Count stored publish times under their ecosystem in the stats
Cooldown stores the publish time of every version it looks up, also of
packages nobody downloaded, which have no package row. The ecosystem stats
counted those versions as unattributed. They now count under the type of
their package PURL; only a PURL that can't be parsed stays unattributed.
2026-10-31 15:19:11 +01:00
Simon Chrzanowski
e50179d0cc Refresh Swift and Helm packages, leave Julia out 2026-10-31 14:09:59 +01:00
Simon Chrzanowski
2f2d01a414 Refresh Debian, Alpine and RPM packages from their indexes
These clients find new versions in a repository index. The refresh fetches
the InRelease, APKINDEX and repomd.xml files clients fetched again, reads
the Packages and primary indexes they point at for the repositories the
most used packages came from, and mirrors the newer file per package and
architecture, checked against the index's SHA-256 where it has one.
2026-10-31 14:05:05 +01:00
Simon Chrzanowski
3e4491287d Record the upstream URL of cached metadata
The refresh fetches Debian, Alpine and RPM indexes again from the URLs
clients fetched them from, which the hashed cache keys don't keep. Rows
cached before get their URL on the next revalidation, even on a 304.
2026-10-31 13:57:49 +01:00
Simon Chrzanowski
29863e858a Refresh the most used packages in the background
mirror.refresh mirrors, for the top packages per ecosystem by recent
downloads, the newest release of each major line a version is cached on.
Releases within cooldown or on the denylist are skipped, and PyPI and conda
get only the kinds of files clients fetched before. max_versions and
max_bytes cap one run. Instances sharing a database take turns as for
schedules.
2026-10-31 13:53:37 +01:00
simon chrzanowski
1979fb098e
Accept Swift source repository PURLs in the denylist and retention rules (#641)
* Accept Swift source repository PURLs in the denylist and retention rules

Closes #613. pkg:swift/github.com/apple/swift-nio, as SBOM tools and GHSA
write Swift packages, is resolved to its registry identity through the
upstream's /identifiers:

- Denylist entries are resolved at startup, and the proxy refuses to start
  when one can't be, since a skipped entry would let the version through.
- Retention keys are accepted at validation and kept pending. The
  retention loop resolves them before each sweep, and Swift isn't swept
  while any is pending, so a rule that keeps a package is never skipped.

The mirror's source URL helper moves to the handler as SwiftSourceURL.

* Resolve Swift source denylist entries in proxy mirror too

serve resolved source-form Swift denylist entries through the upstream,
but proxy mirror built its denylist directly, so such an entry never
matched a mirror download. Both now use server.ConfigureDenylist, and
neither runs when an entry can't be resolved.

* Apply Swift source policies to every listed identity

A Swift registry may list several identities for one source repository,
but a denylist entry or retention rule naming the repository only
covered the first. Denying pkg:swift/github.com/acme/widget@1.0.0 let
acme.widget through when the registry listed other.widget first, and a
never-evict rule cleared the cached apple.swift-nio archive when
other.swift-nio came first.

Both now cover every identity the registry lists. A retention rule that
conflicts with another rule for any of them stays pending, with none
applied. Mirroring a source PURL still downloads the first identity.
2026-10-31 11:34:05 +00:00
Simon Chrzanowski
1cadc4a7ba Compare Go main modules with their case
purl v0.2.1 keeps the case of Go module paths, so the inventory no
longer lowercases syft's mainModule. Module paths are case-sensitive:
github.com/azure/foo is a dependency of github.com/Azure/foo, not part
of it.
2026-10-31 11:33:31 +01:00
Simon Chrzanowski
7a77baf01a Keep namespace/name for Swift package URLs in the handler mapping
With purl v0.2.1, FullName returns a Swift package as its registry
identity, scope.name. The mirror splits namespace/name again to find
the scope or the source repository, so HandlerPackage keeps that form,
as mirrorTarget did before the two mappings were shared.
2026-10-31 11:33:31 +01:00
Simon Chrzanowski
c6635f3165 Merge remote-tracking branch 'origin/main' into feat/project-inventory 2026-10-31 11:29:24 +01:00
Andrew Nesbitt
3eadb3eb46
Preserve Swift and Go compatibility when upgrading PURL (#642)
* Handle Swift registry identities in cache and vulnerability APIs

* Preserve Go cache and policy behavior when upgrading PURL
2026-10-31 09:49:35 +00:00