Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ proxy/
│ │ └── queries.go # CRUD operations
│ ├── storage/ # Artifact file storage
│ │ ├── storage.go # Storage interface
│ │ └── filesystem.go # Local filesystem impl
│ │ └── blob.go # gocloud.dev/blob backends (file, S3, Azure)
│ ├── upstream/ # Upstream registry clients
│ │ ├── fetcher.go # HTTP artifact fetching
│ │ └── resolver.go # Download URL resolution
Expand Down Expand Up @@ -72,7 +72,7 @@ Key types:

### `internal/storage`

Artifact file storage abstraction. Currently implements local filesystem storage. Designed to allow future backends (S3, GCS).
Artifact file storage abstraction backed by `gocloud.dev/blob`. Supports local filesystem (`file://`), S3 (`s3://`), and Azure (`azblob://`) URLs.

Interface:
```go
Expand Down
156 changes: 80 additions & 76 deletions go.mod

Large diffs are not rendered by default.

367 changes: 178 additions & 189 deletions go.sum

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -928,8 +928,7 @@ func ParseSize(s string) (int64, error) {
}

for _, s2 := range suffixes {
if strings.HasSuffix(s, s2.suffix) {
numStr := strings.TrimSuffix(s, s2.suffix)
if numStr, ok := strings.CutSuffix(s, s2.suffix); ok {
num, err := strconv.ParseFloat(numStr, 64)
if err != nil {
return 0, fmt.Errorf("invalid number %q", numStr)
Expand Down
50 changes: 0 additions & 50 deletions internal/enrichment/enrichment.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,43 +201,6 @@ func (s *Service) CheckVulnerabilities(ctx context.Context, ecosystem, name, ver
return results, nil
}

// BulkCheckVulnerabilities queries vulnerabilities for multiple package versions.
func (s *Service) BulkCheckVulnerabilities(ctx context.Context, packages []struct{ Ecosystem, Name, Version string }) (map[string][]VulnInfo, error) {
purls := make([]*purl.PURL, len(packages))
for i, pkg := range packages {
purls[i] = purl.MakePURL(pkg.Ecosystem, pkg.Name, pkg.Version)
}

vulnResults, err := s.vulnSource.QueryBatch(ctx, purls)
if err != nil {
return nil, err
}

result := make(map[string][]VulnInfo, len(packages))
for i, vulnList := range vulnResults {
pkg := packages[i]
key := purl.MakePURLString(pkg.Ecosystem, pkg.Name, pkg.Version)

var infos []VulnInfo
for _, v := range vulnList {
info := VulnInfo{
ID: v.ID,
Summary: v.Summary,
Severity: v.SeverityLevel(),
CVSSScore: v.CVSSScore(),
FixedVersion: v.FixedVersion(pkg.Ecosystem, pkg.Name),
}
for _, ref := range v.References {
info.References = append(info.References, ref.URL)
}
infos = append(infos, info)
}
result[key] = infos
}

return result, nil
}

// IsOutdated checks if a version is older than the latest version.
func (s *Service) IsOutdated(currentVersion, latestVersion string) bool {
if latestVersion == "" || currentVersion == "" {
Expand Down Expand Up @@ -288,19 +251,6 @@ func (s *Service) CategorizeLicense(license string) LicenseCategory {
return LicenseUnknown
}

// NormalizeLicense normalizes a license string to SPDX format.
func (s *Service) NormalizeLicense(license string) string {
if license == "" {
return ""
}

if normalized, err := spdx.NormalizeExpressionLax(license); err == nil {
return normalized
}

return license
}

// EnrichmentResult contains all enrichment data for a package version.
type EnrichmentResult struct {
Package *PackageInfo
Expand Down
22 changes: 0 additions & 22 deletions internal/enrichment/enrichment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,3 @@ func TestCategorizeLicense(t *testing.T) {
}
}
}

func TestNormalizeLicense(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
svc := New(logger)

tests := []struct {
input string
expected string
}{
{"MIT", "MIT"},
{"Apache 2", "Apache-2.0"},
{"Apache-2.0", "Apache-2.0"},
{"", ""},
}

for _, tc := range tests {
result := svc.NormalizeLicense(tc.input)
if result != tc.expected {
t.Errorf("NormalizeLicense(%q) = %q, want %q", tc.input, result, tc.expected)
}
}
}
16 changes: 0 additions & 16 deletions internal/mirror/registry.go

This file was deleted.

46 changes: 0 additions & 46 deletions internal/mirror/registry_test.go

This file was deleted.

8 changes: 4 additions & 4 deletions internal/server/eviction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/git-pkgs/proxy/internal/storage"
)

func setupEvictionTest(t *testing.T) (*database.DB, *storage.Filesystem) {
func setupEvictionTest(t *testing.T) (*database.DB, *storage.Blob) {
t.Helper()

tempDir := t.TempDir()
Expand All @@ -27,7 +27,7 @@ func setupEvictionTest(t *testing.T) (*database.DB, *storage.Filesystem) {
t.Fatalf("failed to create database: %v", err)
}

store, err := storage.NewFilesystem(storagePath)
store, err := storage.OpenBucket(context.Background(), "file://"+storagePath)
if err != nil {
_ = db.Close()
t.Fatalf("failed to create storage: %v", err)
Expand Down Expand Up @@ -243,7 +243,7 @@ func TestStartEvictionLoop_UnlimitedSkips(t *testing.T) {
}
defer func() { _ = db.Close() }()

store, err := storage.NewFilesystem(storagePath)
store, err := storage.OpenBucket(context.Background(), "file://"+storagePath)
if err != nil {
t.Fatalf("failed to create storage: %v", err)
}
Expand Down Expand Up @@ -280,7 +280,7 @@ func defaultTestConfig(storagePath, dbPath string) *config.Config {
return &config.Config{
Listen: ":8080",
BaseURL: "http://localhost:8080",
Storage: config.StorageConfig{Path: storagePath, MaxSize: ""},
Storage: config.StorageConfig{URL: "file://" + storagePath, MaxSize: ""},
Database: config.DatabaseConfig{
Driver: "sqlite",
Path: dbPath,
Expand Down
6 changes: 3 additions & 3 deletions internal/server/health_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type fakeStorage struct {
// Failure injection.
storeErr error
openErr error
readErr error // returned by the io.ReadCloser.Read after partial bytes
readErr error // returned by the io.ReadCloser.Read after partial bytes
deleteErr error

// Misbehavior knobs.
Expand Down Expand Up @@ -132,8 +132,8 @@ func (f *fakeStorage) SignedURL(ctx context.Context, path string, expiry time.Du
return "", storage.ErrSignedURLUnsupported
}
func (f *fakeStorage) UsedSpace(ctx context.Context) (int64, error) { return 0, nil }
func (f *fakeStorage) URL() string { return "fake://" }
func (f *fakeStorage) Close() error { return nil }
func (f *fakeStorage) URL() string { return "fake://" }
func (f *fakeStorage) Close() error { return nil }

// --- Tests follow. First test: happy path ---

Expand Down
14 changes: 0 additions & 14 deletions internal/server/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,3 @@ func requestEcosystem(path string) string {
return "other"
}
}

// ActiveRequestsMiddleware tracks the number of active requests using Prometheus metrics.
func ActiveRequestsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Don't track metrics endpoint itself
if r.URL.Path == "/metrics" {
next.ServeHTTP(w, r)
return
}

// Implemented in server.go where metrics package is imported
next.ServeHTTP(w, r)
})
}
30 changes: 0 additions & 30 deletions internal/server/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,36 +73,6 @@ func TestGetRequestID(t *testing.T) {
}
}

func TestActiveRequestsMiddleware(t *testing.T) {
handler := ActiveRequestsMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))

req := httptest.NewRequest(http.MethodGet, "/test", nil)
rec := httptest.NewRecorder()

handler.ServeHTTP(rec, req)

if rec.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", rec.Code)
}
}

func TestActiveRequestsMiddleware_SkipsMetricsEndpoint(t *testing.T) {
handler := ActiveRequestsMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))

req := httptest.NewRequest(http.MethodGet, "/metrics", nil)
rec := httptest.NewRecorder()

handler.ServeHTTP(rec, req)

if rec.Code != http.StatusOK {
t.Errorf("expected status 200, got %d", rec.Code)
}
}

func TestLoggerMiddleware(t *testing.T) {
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
s := &Server{logger: logger}
Expand Down
7 changes: 4 additions & 3 deletions internal/server/server_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package server

import (
"context"
"database/sql"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -51,7 +52,7 @@ func newTestServer(t *testing.T) *testServer {
t.Fatalf("failed to create database: %v", err)
}

store, err := storage.NewFilesystem(storagePath)
store, err := storage.OpenBucket(context.Background(), "file://"+storagePath)
if err != nil {
_ = db.Close()
_ = os.RemoveAll(tempDir)
Expand All @@ -65,7 +66,7 @@ func newTestServer(t *testing.T) *testServer {

cfg := &config.Config{
BaseURL: "http://localhost:8080",
Storage: config.StorageConfig{Path: storagePath},
Storage: config.StorageConfig{URL: "file://" + storagePath},
Database: config.DatabaseConfig{Path: dbPath},
}

Expand Down Expand Up @@ -1348,7 +1349,7 @@ func TestNewServer_InvalidAccessLogFailsBeforeDatabaseInit(t *testing.T) {
tempDir := t.TempDir()
dbPath := filepath.Join(tempDir, "test.db")
cfg := &config.Config{
Storage: config.StorageConfig{Path: filepath.Join(tempDir, "artifacts")},
Storage: config.StorageConfig{URL: "file://" + filepath.Join(tempDir, "artifacts")},
Database: config.DatabaseConfig{Path: dbPath},
AccessLog: config.AccessLogConfig{Path: filepath.Join(tempDir, "missing", "access.jsonl")},
}
Expand Down
Loading