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
17 changes: 14 additions & 3 deletions ecosystems.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,22 @@ type EcosystemsClient struct {

// NewEcosystemsClient creates a client that uses the ecosyste.ms API.
func NewEcosystemsClient() (*EcosystemsClient, error) {
return newEcosystemsClient(defaultUserAgent)
return newEcosystemsClient(options{userAgent: defaultUserAgent})
}

func newEcosystemsClient(userAgent string) (*EcosystemsClient, error) {
client, err := ecosystems.NewClient(userAgent)
func newEcosystemsClient(o options) (*EcosystemsClient, error) {
clientOpts := []ecosystems.Option{}
if o.from != "" {
clientOpts = append(clientOpts, ecosystems.WithFrom(o.from))
}
if o.apiKey != "" {
clientOpts = append(clientOpts, ecosystems.WithAPIKey(o.apiKey))
}
if o.batchSize > 0 {
clientOpts = append(clientOpts, ecosystems.WithBatchSize(o.batchSize))
}

client, err := ecosystems.NewClient(o.userAgent, clientOpts...)
if err != nil {
return nil, err
}
Expand Down
46 changes: 46 additions & 0 deletions enrichment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,52 @@ func TestNewClientWithUserAgent(t *testing.T) {
}
}

func TestBuildOptions(t *testing.T) {
o := buildOptions([]Option{
WithUserAgent("ua"),
WithFrom("dev@example.com"),
WithAPIKey("secret"),
WithBatchSize(25),
})
if o.userAgent != "ua" {
t.Errorf("userAgent = %q, want %q", o.userAgent, "ua")
}
if o.from != "dev@example.com" {
t.Errorf("from = %q, want %q", o.from, "dev@example.com")
}
if o.apiKey != "secret" {
t.Errorf("apiKey = %q, want %q", o.apiKey, "secret")
}
if o.batchSize != 25 {
t.Errorf("batchSize = %d, want %d", o.batchSize, 25)
}
}

func TestBuildOptionsDefaults(t *testing.T) {
o := buildOptions(nil)
if o.userAgent != defaultUserAgent {
t.Errorf("userAgent = %q, want %q", o.userAgent, defaultUserAgent)
}
if o.from != "" || o.apiKey != "" || o.batchSize != 0 {
t.Errorf("expected zero values for from/apiKey/batchSize, got %+v", o)
}
}

func TestNewEcosystemsClientWithAllOptions(t *testing.T) {
c, err := newEcosystemsClient(options{
userAgent: "git-pkgs/test",
from: "dev@example.com",
apiKey: "secret",
batchSize: 25,
})
if err != nil {
t.Fatalf("newEcosystemsClient: %v", err)
}
if c == nil || c.client == nil {
t.Fatal("expected non-nil client")
}
}

func TestDepsDevBulkLookup(t *testing.T) {
callCount := 0
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
Expand Down
32 changes: 31 additions & 1 deletion factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ type Option func(*options)

type options struct {
userAgent string
from string
apiKey string
batchSize int
}

// WithUserAgent sets the User-Agent header for API requests.
Expand All @@ -22,6 +25,33 @@ func WithUserAgent(ua string) Option {
}
}

// WithFrom sets the From header (email address) for ecosyste.ms API
// requests. Identifying the client moves it out of the shared
// rate-limit pool, which reduces stream-level rejections.
// Ignored by the direct registries client.
func WithFrom(email string) Option {
return func(o *options) {
o.from = email
}
}

// WithAPIKey sets the bearer token sent on ecosyste.ms API requests.
// Ignored by the direct registries client.
func WithAPIKey(key string) Option {
return func(o *options) {
o.apiKey = key
}
}

// WithBatchSize sets the per-request batch size for ecosyste.ms bulk
// lookups. Values <= 0 or above the upstream maximum fall back to the
// upstream default. Ignored by the direct registries client.
func WithBatchSize(size int) Option {
return func(o *options) {
o.batchSize = size
}
}

func buildOptions(opts []Option) options {
o := options{userAgent: defaultUserAgent}
for _, opt := range opts {
Expand All @@ -44,7 +74,7 @@ func NewClient(opts ...Option) (Client, error) { //nolint:ireturn // returns dif
if directMode() {
return newRegistriesClient(o.userAgent), nil
}
return newHybridClient(o.userAgent)
return newHybridClient(o)
}

// directMode checks if direct registry mode is enabled.
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/git-pkgs/enrichment
go 1.25.6

require (
github.com/ecosyste-ms/ecosystems-go v0.1.1
github.com/ecosyste-ms/ecosystems-go v0.2.0
github.com/git-pkgs/purl v0.1.12
github.com/git-pkgs/registries v0.6.1
github.com/git-pkgs/vers v0.2.6
Expand All @@ -16,6 +16,6 @@ require (
github.com/git-pkgs/spdx v0.1.4 // indirect
github.com/github/go-spdx/v2 v2.7.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/oapi-codegen/runtime v1.1.2 // indirect
github.com/oapi-codegen/runtime v1.4.1 // indirect
github.com/package-url/packageurl-go v0.1.6 // indirect
)
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvF
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ecosyste-ms/ecosystems-go v0.1.1 h1:YYiBK9TCCTeE+BtmpN2FssaRFcmF+T0v4LrupIOjehQ=
github.com/ecosyste-ms/ecosystems-go v0.1.1/go.mod h1:VczXs1CO9nL8XbL1NwvgmwIaqzMsAxcsXnTpRtwi9gU=
github.com/ecosyste-ms/ecosystems-go v0.2.0 h1:Nhpg54C+St8Sd/mf8bNJmQqx35ZgHw33TfFoxaXMQI8=
github.com/ecosyste-ms/ecosystems-go v0.2.0/go.mod h1:CCdzT1iAZirbEZAbFSnWpK88eKKaIWex7gjtZ0UudXA=
github.com/git-pkgs/packageurl-go v0.3.1 h1:WM3RBABQZLaRBxgKyYughc3cVBE8KyQxbSC6Jt5ak7M=
github.com/git-pkgs/packageurl-go v0.3.1/go.mod h1:rcIxiG37BlQLB6FZfgdj9Fm7yjhRQd3l+5o7J0QPAk4=
github.com/git-pkgs/pom v0.1.4 h1:C6st+XSbF75eKuwfdkDZZtYHoTcaWRIEQYar5VtszUo=
Expand All @@ -24,16 +24,18 @@ github.com/github/go-spdx/v2 v2.7.0/go.mod h1:Ftc45YYG1WzpzwEPKRVm9Jv8vDqOrN4gWo
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/oapi-codegen/runtime v1.1.2 h1:P2+CubHq8fO4Q6fV1tqDBZHCwpVpvPg7oKiYzQgXIyI=
github.com/oapi-codegen/runtime v1.1.2/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/oapi-codegen/nullable v1.1.0 h1:eAh8JVc5430VtYVnq00Hrbpag9PFRGWLjxR1/3KntMs=
github.com/oapi-codegen/nullable v1.1.0/go.mod h1:KUZ3vUzkmEKY90ksAmit2+5juDIhIZhfDl+0PwOQlFY=
github.com/oapi-codegen/runtime v1.4.1 h1:9nwLoI+KrWxzbBcp0jO/R8uXqbik/HUyCvPeU68Y/qo=
github.com/oapi-codegen/runtime v1.4.1/go.mod h1:GwV7hC2hviaMzj+ITfHVRESK5J2W/GefVwIND/bMGvU=
github.com/package-url/packageurl-go v0.1.6 h1:YO3p6u1XmCUliivUg/qWphaY8vI6hxSnnPv7Bfg3m5M=
github.com/package-url/packageurl-go v0.1.6/go.mod h1:nKAWB8E6uk1MHqiS/lQb9pYBGH2+mdJ2PJc2s50dQY0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
8 changes: 4 additions & 4 deletions hybrid.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ type HybridClient struct {

// NewHybridClient creates a client that routes based on PURL qualifiers.
func NewHybridClient() (*HybridClient, error) {
return newHybridClient(defaultUserAgent)
return newHybridClient(options{userAgent: defaultUserAgent})
}

func newHybridClient(userAgent string) (*HybridClient, error) {
eco, err := newEcosystemsClient(userAgent)
func newHybridClient(o options) (*HybridClient, error) {
eco, err := newEcosystemsClient(o)
if err != nil {
return nil, err
}
return &HybridClient{
ecosystems: eco,
registries: newRegistriesClient(userAgent),
registries: newRegistriesClient(o.userAgent),
}, nil
}

Expand Down