Watch
1
0
Fork
You've already forked pkg-proxy
1
mirror of https://github.com/git-pkgs/proxy.git synced 2026-11-09 07:39:19 -05:00
pkg-proxy/internal/config/projects_test.go
Simon Chrzanowski 0bc0e903f8 Add a project inventory built from uploaded SBOMs
Repositories upload an SBOM of their default branch, for example from
syft in CI, to PUT /api/projects/{project}/sbom. The proxy records the
package versions it lists, keyed by the same unversioned PURL the
handlers record packages under, so the inventory joins with what the
proxy has cached and the vulnerabilities it holds.

That answers which repository uses which version of a package: the new
/ui/projects pages list each project's package versions with outdated
and vulnerability markers, package pages show the projects per version,
the dashboard lists vulnerable versions in use, and
GET /api/projects?purl= does the same for scripts.

The feature is off by default. Uploads and deletes need projects.token;
an upload replaces the project's components in one transaction.
projects.max_age removes projects that stopped uploading.
2026-10-27 19:30:34 +01:00

69 lines
2.5 KiB
Go

package config
import (
"testing"
"time"
)
func TestProjectsConfigValidate(t *testing.T) {
t.Setenv("PROJECTS_TEST_TOKEN", "from-env")
tests := []struct {
name string
projects ProjectsConfig
wantErr bool
maxAge time.Duration
}{
{name: "disabled without token", projects: ProjectsConfig{}},
{name: "enabled without token", projects: ProjectsConfig{Enabled: true}, wantErr: true},
{name: "enabled with token", projects: ProjectsConfig{Enabled: true, Token: "s3cret"}},
{name: "token from env reference", projects: ProjectsConfig{Enabled: true, Token: "${PROJECTS_TEST_TOKEN}"}},
{name: "token env reference unset", projects: ProjectsConfig{Enabled: true, Token: "${PROJECTS_TEST_UNSET}"}, wantErr: true},
{name: "max age in days", projects: ProjectsConfig{Enabled: true, Token: "s3cret", MaxAge: "90d"}, maxAge: 90 * 24 * time.Hour},
{name: "max age in hours", projects: ProjectsConfig{Enabled: true, Token: "s3cret", MaxAge: "36h"}, maxAge: 36 * time.Hour},
{name: "max age zero keeps projects", projects: ProjectsConfig{Enabled: true, Token: "s3cret", MaxAge: "0"}},
{name: "invalid max age", projects: ProjectsConfig{Enabled: true, Token: "s3cret", MaxAge: "soon"}, wantErr: true},
{name: "negative max age", projects: ProjectsConfig{Enabled: true, Token: "s3cret", MaxAge: "-1d"}, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.projects.Validate()
if (err != nil) != tt.wantErr {
t.Fatalf("Validate() error = %v, wantErr %v", err, tt.wantErr)
}
if got := tt.projects.MaxAgeDuration(); err == nil && got != tt.maxAge {
t.Errorf("MaxAgeDuration() = %v, want %v", got, tt.maxAge)
}
})
}
}
func TestLoadFromEnvProjects(t *testing.T) {
cfg := Default()
t.Setenv("PROXY_PROJECTS_ENABLED", "true")
t.Setenv("PROXY_PROJECTS_TOKEN", "env-token")
t.Setenv("PROXY_PROJECTS_MAX_AGE", "30d")
cfg.LoadFromEnv()
if !cfg.Projects.Enabled {
t.Error("Projects.Enabled not loaded from PROXY_PROJECTS_ENABLED")
}
if cfg.Projects.TokenExpanded() != "env-token" {
t.Errorf("Projects.Token = %q, want env-token", cfg.Projects.Token)
}
if err := cfg.Validate(); err != nil {
t.Fatalf("Validate: %v", err)
}
if got := cfg.Projects.MaxAgeDuration(); got != 30*24*time.Hour {
t.Errorf("MaxAgeDuration() = %v, want 30 days", got)
}
}
func TestValidateRejectsProjectsWithoutToken(t *testing.T) {
cfg := Default()
cfg.Projects = ProjectsConfig{Enabled: true}
if err := cfg.Validate(); err == nil {
t.Error("Validate() accepted projects.enabled without a token")
}
}