From 604349712e0210ba5c66db5fa2da167c42fce726 Mon Sep 17 00:00:00 2001 From: Agustin Isasmendi Date: Tue, 27 Jan 2026 18:43:36 +0100 Subject: [PATCH 1/7] feat(service): add db version info to status response --- go.mod | 5 +- go.sum | 6 +- pkg/cmd/server.go | 2 +- pkg/service/component_service.go | 94 +++++++++++++++++++++------ pkg/service/component_service_test.go | 18 ++--- 5 files changed, 90 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index 12e7561..4d58524 100644 --- a/go.mod +++ b/go.mod @@ -10,9 +10,10 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/jmoiron/sqlx v1.4.0 github.com/lib/pq v1.10.9 - github.com/scanoss/go-grpc-helper v0.9.0 + github.com/scanoss/go-grpc-helper v0.11.0 + github.com/scanoss/go-models v0.3.0 github.com/scanoss/go-purl-helper v0.2.1 - github.com/scanoss/papi v0.21.0 + github.com/scanoss/papi v0.28.0 github.com/scanoss/zap-logging-helper v0.4.0 go.opentelemetry.io/otel v1.38.0 go.opentelemetry.io/otel/metric v1.38.0 diff --git a/go.sum b/go.sum index 82b10f5..cf21ef7 100644 --- a/go.sum +++ b/go.sum @@ -616,14 +616,12 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= -github.com/scanoss/go-grpc-helper v0.9.0 h1:lK9JtKtyOqR9XxjnYR0wbW5KCNDH82P1E1LJwwP5Xb4= -github.com/scanoss/go-grpc-helper v0.9.0/go.mod h1:EPI1NBg+DJ+krWehxC9eHyNpM5Pii5odOJcNdNG9qA0= github.com/scanoss/go-purl-helper v0.2.1 h1:jp960a585ycyJSlqZky1NatMJBIQi/JGITDfNSu/9As= github.com/scanoss/go-purl-helper v0.2.1/go.mod h1:v20/bKD8G+vGrILdiq6r0hyRD2bO8frCJlu9drEcQ38= github.com/scanoss/ipfilter/v2 v2.0.2 h1:GaB9i8kVJg9JQZm5XGStYkEpiaCVdsrj7ezI2wV/oh8= github.com/scanoss/ipfilter/v2 v2.0.2/go.mod h1:AwrpX4XGbZ7EKISMi1d6E5csBk1nWB8+ugpvXHFcTpA= -github.com/scanoss/papi v0.21.0 h1:aVt0q9pxaPHMq3QsFFnlIXju1NYpou/ziweWdIIkkPs= -github.com/scanoss/papi v0.21.0/go.mod h1:Z4E/4IpwYdzHHRJXTgBCGG1GjksgrFjNW5cvhbKUfeU= +github.com/scanoss/papi v0.28.0 h1:uvevFYoxwzvSH1hvgBoAkScIGTK2U1+rLzHSoJdnARk= +github.com/scanoss/papi v0.28.0/go.mod h1:Z4E/4IpwYdzHHRJXTgBCGG1GjksgrFjNW5cvhbKUfeU= github.com/scanoss/zap-logging-helper v0.4.0 h1:2qTYoaFa9+MlD2/1wmPtiDHfh+42NIEwgKVU3rPpl0Y= github.com/scanoss/zap-logging-helper v0.4.0/go.mod h1:9QuEZcq73g/0Izv1tWeOWukoIK0oTBzM4jSNQ5kRR1w= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= diff --git a/pkg/cmd/server.go b/pkg/cmd/server.go index a84711f..1cdef9d 100644 --- a/pkg/cmd/server.go +++ b/pkg/cmd/server.go @@ -111,7 +111,7 @@ func RunServer() error { // Setup dynamic logging (if necessary) zlog.SetupAppDynamicLogging(cfg.Logging.DynamicPort, cfg.Logging.DynamicLogging) // Register the component service - v2API := service.NewComponentServer(db, cfg) + v2API := service.NewComponentServer(db, cfg, strings.TrimSpace(version)) ctx := context.Background() // Start the REST grpc-gateway if requested var srv *http.Server diff --git a/pkg/service/component_service.go b/pkg/service/component_service.go index d8f78b0..131da89 100644 --- a/pkg/service/component_service.go +++ b/pkg/service/component_service.go @@ -19,26 +19,35 @@ package service import ( "context" + "time" + "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" "github.com/jmoiron/sqlx" "github.com/scanoss/go-grpc-helper/pkg/grpc/database" + gomodels "github.com/scanoss/go-models/pkg/models" common "github.com/scanoss/papi/api/commonv2" pb "github.com/scanoss/papi/api/componentsv2" myconfig "scanoss.com/components/pkg/config" se "scanoss.com/components/pkg/errors" "scanoss.com/components/pkg/usecase" - "time" ) type componentServer struct { pb.ComponentsServer - db *sqlx.DB - config *myconfig.ServerConfig + db *sqlx.DB + config *myconfig.ServerConfig + version string + dbVersionModel *gomodels.DBVersionModel } -func NewComponentServer(db *sqlx.DB, config *myconfig.ServerConfig) pb.ComponentsServer { +func NewComponentServer(db *sqlx.DB, config *myconfig.ServerConfig, version string) pb.ComponentsServer { setupMetrics() - return &componentServer{db: db, config: config} + return &componentServer{ + db: db, + config: config, + version: version, + dbVersionModel: gomodels.NewDBVersionModel(db), + } } // Echo sends back the same message received @@ -54,30 +63,47 @@ func (d componentServer) SearchComponents(ctx context.Context, request *pb.CompS s := ctxzap.Extract(ctx).Sugar() s.Info("Processing component name request...") if len(request.Search) == 0 && len(request.Component) == 0 && len(request.Vendor) == 0 { - return &pb.CompSearchResponse{Status: se.HandleServiceError(ctx, s, se.NewBadRequestError("No data supplied", nil))}, nil + status := se.HandleServiceError(ctx, s, se.NewBadRequestError("No data supplied", nil)) + status.Db = d.getDBVersion() + status.Server = &common.StatusResponse_Server{Version: d.version} + return &pb.CompSearchResponse{Status: status}, nil } dtoRequest, err := convertSearchComponentInput(s, request) // Convert to internal DTO for processing if err != nil { - return &pb.CompSearchResponse{Status: se.HandleServiceError(ctx, s, err)}, nil + status := se.HandleServiceError(ctx, s, err) + status.Db = d.getDBVersion() + status.Server = &common.StatusResponse_Server{Version: d.version} + return &pb.CompSearchResponse{Status: status}, nil } // Search the KB for information about the components compUc := usecase.NewComponents(ctx, s, d.db, database.NewDBSelectContext(s, d.db, nil, d.config.Database.Trace)) dtoComponents, err := compUc.SearchComponents(dtoRequest) if err != nil { - return &pb.CompSearchResponse{Status: se.HandleServiceError(ctx, s, err)}, nil + status := se.HandleServiceError(ctx, s, err) + status.Db = d.getDBVersion() + status.Server = &common.StatusResponse_Server{Version: d.version} + return &pb.CompSearchResponse{Status: status}, nil } s.Debugf("Parsed Components: %+v", dtoComponents) componentsResponse, err := convertSearchComponentOutput(s, dtoComponents) // Convert the internal data into a response object if err != nil { s.Errorf("Failed to convert parsed components: %v", err) - statusResp := common.StatusResponse{Status: common.StatusCode_FAILED, Message: "Problems encountered extracting components data"} - return &pb.CompSearchResponse{Status: &statusResp}, nil + return &pb.CompSearchResponse{Status: &common.StatusResponse{ + Status: common.StatusCode_FAILED, + Message: "Problems encountered extracting components data", + Db: d.getDBVersion(), + Server: &common.StatusResponse_Server{Version: d.version}, + }}, nil } telemetryCompNameRequestTime(ctx, d.config, requestStartTime) // Record the request processing time // Set the status and respond with the data - statusResp := common.StatusResponse{Status: common.StatusCode_SUCCESS, Message: "Success"} - return &pb.CompSearchResponse{Components: componentsResponse.Components, Status: &statusResp}, nil + return &pb.CompSearchResponse{Components: componentsResponse.Components, Status: &common.StatusResponse{ + Status: common.StatusCode_SUCCESS, + Message: "Success", + Db: d.getDBVersion(), + Server: &common.StatusResponse_Server{Version: d.version}, + }}, nil } func (d componentServer) GetComponentVersions(ctx context.Context, request *pb.CompVersionRequest) (*pb.CompVersionResponse, error) { @@ -87,30 +113,47 @@ func (d componentServer) GetComponentVersions(ctx context.Context, request *pb.C s.Info("Processing component versions request...") //Verify the input request if len(request.Purl) == 0 { - return &pb.CompVersionResponse{Status: se.HandleServiceError(ctx, s, se.NewBadRequestError("No purl supplied", nil))}, nil + status := se.HandleServiceError(ctx, s, se.NewBadRequestError("No purl supplied", nil)) + status.Db = d.getDBVersion() + status.Server = &common.StatusResponse_Server{Version: d.version} + return &pb.CompVersionResponse{Status: status}, nil } //Convert the request to internal DTO dtoRequest, err := convertCompVersionsInput(s, request) if err != nil { - return &pb.CompVersionResponse{Status: se.HandleServiceError(ctx, s, err)}, nil + status := se.HandleServiceError(ctx, s, err) + status.Db = d.getDBVersion() + status.Server = &common.StatusResponse_Server{Version: d.version} + return &pb.CompVersionResponse{Status: status}, nil } // Creates the use case compUc := usecase.NewComponents(ctx, s, d.db, database.NewDBSelectContext(s, d.db, nil, d.config.Database.Trace)) dtoOutput, err := compUc.GetComponentVersions(dtoRequest) if err != nil { - return &pb.CompVersionResponse{Status: se.HandleServiceError(ctx, s, err)}, nil + status := se.HandleServiceError(ctx, s, err) + status.Db = d.getDBVersion() + status.Server = &common.StatusResponse_Server{Version: d.version} + return &pb.CompVersionResponse{Status: status}, nil } reqResponse, err := convertCompVersionsOutput(s, dtoOutput) if err != nil { s.Errorf("Failed to convert parsed components: %v", err) - statusResp := common.StatusResponse{Status: common.StatusCode_FAILED, Message: "Problems encountered extracting components data"} - return &pb.CompVersionResponse{Status: &statusResp}, nil + return &pb.CompVersionResponse{Status: &common.StatusResponse{ + Status: common.StatusCode_FAILED, + Message: "Problems encountered extracting components data", + Db: d.getDBVersion(), + Server: &common.StatusResponse_Server{Version: d.version}, + }}, nil } telemetryCompVersionRequestTime(ctx, d.config, requestStartTime) // Set the status and respond with the data - statusResp := common.StatusResponse{Status: common.StatusCode_SUCCESS, Message: "Success"} - return &pb.CompVersionResponse{Component: reqResponse.Component, Status: &statusResp}, nil + return &pb.CompVersionResponse{Component: reqResponse.Component, Status: &common.StatusResponse{ + Status: common.StatusCode_SUCCESS, + Message: "Success", + Db: d.getDBVersion(), + Server: &common.StatusResponse_Server{Version: d.version}, + }}, nil } // telemetryCompNameRequestTime records the name request time to telemetry. @@ -128,3 +171,16 @@ func telemetryCompVersionRequestTime(ctx context.Context, config *myconfig.Serve oltpMetrics.compVersionHistogram.Record(ctx, elapsedTime) // Record dep request time } } + +// getDBVersion fetches the database version from the db_version table. +// Returns nil if the table doesn't exist or query fails (backward compatibility). +func (d componentServer) getDBVersion() *common.StatusResponse_DB { + dbVersion, err := d.dbVersionModel.GetCurrentVersion(context.Background()) + if err != nil || len(dbVersion.SchemaVersion) == 0 { + return nil + } + return &common.StatusResponse_DB{ + SchemaVersion: dbVersion.SchemaVersion, + CreatedAt: dbVersion.CreatedAt, + } +} diff --git a/pkg/service/component_service_test.go b/pkg/service/component_service_test.go index dd7d4b3..c95228a 100644 --- a/pkg/service/component_service_test.go +++ b/pkg/service/component_service_test.go @@ -48,7 +48,7 @@ func TestComponentServer_Echo(t *testing.T) { if err != nil { t.Fatalf("failed to load Config: %v", err) } - s := NewComponentServer(db, myConfig) + s := NewComponentServer(db, myConfig, "test-version") type args struct { ctx context.Context @@ -106,7 +106,7 @@ func TestComponentServer_SearchComponents(t *testing.T) { if err != nil { t.Fatalf("failed to load Config: %v", err) } - s := NewComponentServer(db, myConfig) + s := NewComponentServer(db, myConfig, "test-version") var compRequestData = `{ "component": "react", @@ -137,7 +137,7 @@ func TestComponentServer_SearchComponents(t *testing.T) { ctx: ctx, req: &compReq, }, - want: &pb.CompSearchResponse{Status: &common.StatusResponse{Status: common.StatusCode_FAILED, Message: "No components found matching the search criteria"}}, + want: &pb.CompSearchResponse{Status: &common.StatusResponse{Status: common.StatusCode_FAILED, Message: "No components found matching the search criteria", Server: &common.StatusResponse_Server{Version: "test-version"}}}, }, { name: "Search for a empty request", @@ -146,7 +146,7 @@ func TestComponentServer_SearchComponents(t *testing.T) { ctx: ctx, req: &pb.CompSearchRequest{}, }, - want: &pb.CompSearchResponse{Status: &common.StatusResponse{Status: common.StatusCode_FAILED, Message: "No data supplied"}}, + want: &pb.CompSearchResponse{Status: &common.StatusResponse{Status: common.StatusCode_FAILED, Message: "No data supplied", Server: &common.StatusResponse_Server{Version: "test-version"}}}, wantErr: false, }, } @@ -159,7 +159,7 @@ func TestComponentServer_SearchComponents(t *testing.T) { return } if err == nil && !reflect.DeepEqual(got.Status, tt.want.Status) { - t.Errorf("service.SearchComponents() = %v, want %v", got, tt.want) + t.Errorf("service.SearchComponents() status = %v, want %v", got.Status, tt.want.Status) } }) } @@ -186,7 +186,7 @@ func TestComponentServer_GetComponentVersions(t *testing.T) { if err != nil { t.Fatalf("failed to load Config: %v", err) } - s := NewComponentServer(db, myConfig) + s := NewComponentServer(db, myConfig, "test-version") var compVersionRequestData = `{ "purl": "pkg:npm/react" @@ -216,7 +216,7 @@ func TestComponentServer_GetComponentVersions(t *testing.T) { ctx: ctx, req: &compVersionReq, }, - want: &pb.CompVersionResponse{Status: &common.StatusResponse{Status: common.StatusCode_SUCCESS, Message: "Success"}}, + want: &pb.CompVersionResponse{Status: &common.StatusResponse{Status: common.StatusCode_SUCCESS, Message: "Success", Server: &common.StatusResponse_Server{Version: "test-version"}}}, }, { name: "Search for a empty request", @@ -225,7 +225,7 @@ func TestComponentServer_GetComponentVersions(t *testing.T) { ctx: ctx, req: &pb.CompVersionRequest{}, }, - want: &pb.CompVersionResponse{Status: &common.StatusResponse{Status: common.StatusCode_FAILED, Message: "No purl supplied"}}, + want: &pb.CompVersionResponse{Status: &common.StatusResponse{Status: common.StatusCode_FAILED, Message: "No purl supplied", Server: &common.StatusResponse_Server{Version: "test-version"}}}, wantErr: false, }, } @@ -238,7 +238,7 @@ func TestComponentServer_GetComponentVersions(t *testing.T) { return } if err == nil && !reflect.DeepEqual(got.Status, tt.want.Status) { - t.Errorf("service.SearchComponents() = %v, want %v", got, tt.want) + t.Errorf("service.GetComponentVersions() status = %v, want %v", got.Status, tt.want.Status) } }) } From a77fab0789a6685466157c0cc6647ed9072ff310 Mon Sep 17 00:00:00 2001 From: Agustin Isasmendi Date: Tue, 27 Jan 2026 18:58:48 +0100 Subject: [PATCH 2/7] feat(cmd): log sqlite database version info on service startup --- pkg/cmd/server.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/cmd/server.go b/pkg/cmd/server.go index 1cdef9d..03ea860 100644 --- a/pkg/cmd/server.go +++ b/pkg/cmd/server.go @@ -27,6 +27,7 @@ import ( "github.com/scanoss/go-grpc-helper/pkg/files" gd "github.com/scanoss/go-grpc-helper/pkg/grpc/database" gs "github.com/scanoss/go-grpc-helper/pkg/grpc/server" + gomodels "github.com/scanoss/go-models/pkg/models" zlog "github.com/scanoss/zap-logging-helper/pkg/logger" _ "modernc.org/sqlite" "net/http" @@ -108,6 +109,17 @@ func RunServer() error { return err } defer gd.CloseDBConnection(db) + // Log database version info + dbVersionModel := gomodels.NewDBVersionModel(db) + dbVersion, dbVersionErr := dbVersionModel.GetCurrentVersion(context.Background()) + if dbVersionErr != nil { + zlog.S.Warnf("Could not read db_version table: %v", dbVersionErr) + } else if len(dbVersion.SchemaVersion) > 0 { + zlog.S.Infof("Loaded decoration DB: package=%s, schema=%s, created_at=%s", + dbVersion.PackageName, dbVersion.SchemaVersion, dbVersion.CreatedAt) + } else { + zlog.S.Warn("db_version table is empty") + } // Setup dynamic logging (if necessary) zlog.SetupAppDynamicLogging(cfg.Logging.DynamicPort, cfg.Logging.DynamicLogging) // Register the component service From 6a370c221865d08eb635f5f72fba1e9943a41a2a Mon Sep 17 00:00:00 2001 From: Agustin Isasmendi Date: Fri, 30 Jan 2026 15:57:54 +0100 Subject: [PATCH 3/7] chore(gitignore): exclude test config files from version control --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index ded2bd9..b8a066b 100644 --- a/.gitignore +++ b/.gitignore @@ -36,3 +36,5 @@ local-build-commands.txt .idea +config/*test* + From 5f61b9e767c54d52789a208fedde7a90431fb887 Mon Sep 17 00:00:00 2001 From: Agustin Isasmendi Date: Fri, 30 Jan 2026 15:58:53 +0100 Subject: [PATCH 4/7] feat(service): improve logging for database version retrieval errors --- pkg/service/component_service.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pkg/service/component_service.go b/pkg/service/component_service.go index 131da89..7359ff6 100644 --- a/pkg/service/component_service.go +++ b/pkg/service/component_service.go @@ -19,6 +19,7 @@ package service import ( "context" + "errors" "time" "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap" @@ -176,7 +177,14 @@ func telemetryCompVersionRequestTime(ctx context.Context, config *myconfig.Serve // Returns nil if the table doesn't exist or query fails (backward compatibility). func (d componentServer) getDBVersion() *common.StatusResponse_DB { dbVersion, err := d.dbVersionModel.GetCurrentVersion(context.Background()) - if err != nil || len(dbVersion.SchemaVersion) == 0 { + if err != nil { + if !errors.Is(err, gomodels.ErrTableNotFound) { + s := ctxzap.Extract(context.Background()).Sugar() + s.Errorf("Failed to get db version: %v", err) + } + return nil + } + if len(dbVersion.SchemaVersion) == 0 { return nil } return &common.StatusResponse_DB{ From 74abc0750905c9b99a7c2c475968fa158b53fc73 Mon Sep 17 00:00:00 2001 From: Agustin Isasmendi Date: Fri, 30 Jan 2026 16:19:55 +0100 Subject: [PATCH 5/7] feat(config): make server version configurable and improve version propagation --- CHANGELOG.md | 14 +++++++++++++- pkg/cmd/server.go | 10 +++++++--- pkg/config/server_config.go | 1 + pkg/protocol/grpc/server.go | 4 ++-- pkg/service/component_service.go | 24 +++++++++++------------- pkg/service/component_service_test.go | 9 ++++++--- 6 files changed, 40 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e09f6d..d6cecd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - Upcoming changes... -- + +## [0.7.0] - 2026-01-30 +### Added +- Added database version info (`schema_version`, `created_at`) to `StatusResponse` across all component service endpoints +- Added server version to `StatusResponse` +- Log database version info on service startup +### Changed +- Moved server version from constructor parameter to `ServerConfig.App.Version`, configurable via `APP_VERSION` env var (defaults to embedded binary version) +- Log error when querying db version fails with an error other than `ErrTableNotFound` +- Updated `github.com/scanoss/go-models` to v0.3.0 +- Updated `github.com/scanoss/go-grpc-helper` to v0.11.0 + ## [0.6.0] - 2025-09-18 ### Added - Added `name` field to component search and version response DTOs @@ -28,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - ? +[0.7.0]: https://github.com/scanoss/components/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/scanoss/components/compare/v0.5.0...v0.6.0 [0.5.0]: https://github.com/scanoss/components/compare/v0.4.0...v0.5.0 [0.0.1]: https://github.com/scanoss/components/compare/v0.0.0...v0.0.1 diff --git a/pkg/cmd/server.go b/pkg/cmd/server.go index 03ea860..4294788 100644 --- a/pkg/cmd/server.go +++ b/pkg/cmd/server.go @@ -97,7 +97,11 @@ func RunServer() error { return err } - zlog.S.Infof("Starting SCANOSS Component Service: %v", strings.TrimSpace(version)) + // Set the default version from the embedded binary version if not overridden by config/env + if len(cfg.App.Version) == 0 { + cfg.App.Version = strings.TrimSpace(version) + } + zlog.S.Infof("Starting SCANOSS Component Service: %v", cfg.App.Version) // Setup database connection pool db, err := gd.OpenDBConnection(cfg.Database.Dsn, cfg.Database.Driver, cfg.Database.User, cfg.Database.Passwd, @@ -123,7 +127,7 @@ func RunServer() error { // Setup dynamic logging (if necessary) zlog.SetupAppDynamicLogging(cfg.Logging.DynamicPort, cfg.Logging.DynamicLogging) // Register the component service - v2API := service.NewComponentServer(db, cfg, strings.TrimSpace(version)) + v2API := service.NewComponentServer(db, cfg) ctx := context.Background() // Start the REST grpc-gateway if requested var srv *http.Server @@ -133,7 +137,7 @@ func RunServer() error { } } // Start the gRPC service - server, err := grpc.RunServer(cfg, v2API, cfg.App.GRPCPort, allowedIPs, deniedIPs, startTLS, version) + server, err := grpc.RunServer(cfg, v2API, cfg.App.GRPCPort, allowedIPs, deniedIPs, startTLS) if err != nil { return err } diff --git a/pkg/config/server_config.go b/pkg/config/server_config.go index d0e0f4c..58c10ea 100644 --- a/pkg/config/server_config.go +++ b/pkg/config/server_config.go @@ -30,6 +30,7 @@ const ( type ServerConfig struct { App struct { Name string `env:"APP_NAME"` + Version string `env:"APP_VERSION"` GRPCPort string `env:"APP_PORT"` RESTPort string `env:"REST_PORT"` Debug bool `env:"APP_DEBUG"` // true/false diff --git a/pkg/protocol/grpc/server.go b/pkg/protocol/grpc/server.go index 7ced095..9ccf02e 100644 --- a/pkg/protocol/grpc/server.go +++ b/pkg/protocol/grpc/server.go @@ -28,12 +28,12 @@ import ( // RunServer runs gRPC service to publish. func RunServer(config *myconfig.ServerConfig, v2API pb.ComponentsServer, port string, - allowedIPs, deniedIPs []string, startTLS bool, version string) (*grpc.Server, error) { + allowedIPs, deniedIPs []string, startTLS bool) (*grpc.Server, error) { // Start up Open Telemetry is requested var oltpShutdown = func() {} if config.Telemetry.Enabled { var err error - oltpShutdown, err = otel.InitTelemetryProviders(config.App.Name, "scanoss-components", version, + oltpShutdown, err = otel.InitTelemetryProviders(config.App.Name, "scanoss-components", config.App.Version, config.Telemetry.OltpExporter, otel.GetTraceSampler(config.App.Mode), false) if err != nil { return nil, err diff --git a/pkg/service/component_service.go b/pkg/service/component_service.go index 7359ff6..ab08a16 100644 --- a/pkg/service/component_service.go +++ b/pkg/service/component_service.go @@ -37,16 +37,14 @@ type componentServer struct { pb.ComponentsServer db *sqlx.DB config *myconfig.ServerConfig - version string dbVersionModel *gomodels.DBVersionModel } -func NewComponentServer(db *sqlx.DB, config *myconfig.ServerConfig, version string) pb.ComponentsServer { +func NewComponentServer(db *sqlx.DB, config *myconfig.ServerConfig) pb.ComponentsServer { setupMetrics() return &componentServer{ db: db, config: config, - version: version, dbVersionModel: gomodels.NewDBVersionModel(db), } } @@ -66,14 +64,14 @@ func (d componentServer) SearchComponents(ctx context.Context, request *pb.CompS if len(request.Search) == 0 && len(request.Component) == 0 && len(request.Vendor) == 0 { status := se.HandleServiceError(ctx, s, se.NewBadRequestError("No data supplied", nil)) status.Db = d.getDBVersion() - status.Server = &common.StatusResponse_Server{Version: d.version} + status.Server = &common.StatusResponse_Server{Version: d.config.App.Version} return &pb.CompSearchResponse{Status: status}, nil } dtoRequest, err := convertSearchComponentInput(s, request) // Convert to internal DTO for processing if err != nil { status := se.HandleServiceError(ctx, s, err) status.Db = d.getDBVersion() - status.Server = &common.StatusResponse_Server{Version: d.version} + status.Server = &common.StatusResponse_Server{Version: d.config.App.Version} return &pb.CompSearchResponse{Status: status}, nil } @@ -83,7 +81,7 @@ func (d componentServer) SearchComponents(ctx context.Context, request *pb.CompS if err != nil { status := se.HandleServiceError(ctx, s, err) status.Db = d.getDBVersion() - status.Server = &common.StatusResponse_Server{Version: d.version} + status.Server = &common.StatusResponse_Server{Version: d.config.App.Version} return &pb.CompSearchResponse{Status: status}, nil } s.Debugf("Parsed Components: %+v", dtoComponents) @@ -94,7 +92,7 @@ func (d componentServer) SearchComponents(ctx context.Context, request *pb.CompS Status: common.StatusCode_FAILED, Message: "Problems encountered extracting components data", Db: d.getDBVersion(), - Server: &common.StatusResponse_Server{Version: d.version}, + Server: &common.StatusResponse_Server{Version: d.config.App.Version}, }}, nil } telemetryCompNameRequestTime(ctx, d.config, requestStartTime) // Record the request processing time @@ -103,7 +101,7 @@ func (d componentServer) SearchComponents(ctx context.Context, request *pb.CompS Status: common.StatusCode_SUCCESS, Message: "Success", Db: d.getDBVersion(), - Server: &common.StatusResponse_Server{Version: d.version}, + Server: &common.StatusResponse_Server{Version: d.config.App.Version}, }}, nil } @@ -116,7 +114,7 @@ func (d componentServer) GetComponentVersions(ctx context.Context, request *pb.C if len(request.Purl) == 0 { status := se.HandleServiceError(ctx, s, se.NewBadRequestError("No purl supplied", nil)) status.Db = d.getDBVersion() - status.Server = &common.StatusResponse_Server{Version: d.version} + status.Server = &common.StatusResponse_Server{Version: d.config.App.Version} return &pb.CompVersionResponse{Status: status}, nil } //Convert the request to internal DTO @@ -124,7 +122,7 @@ func (d componentServer) GetComponentVersions(ctx context.Context, request *pb.C if err != nil { status := se.HandleServiceError(ctx, s, err) status.Db = d.getDBVersion() - status.Server = &common.StatusResponse_Server{Version: d.version} + status.Server = &common.StatusResponse_Server{Version: d.config.App.Version} return &pb.CompVersionResponse{Status: status}, nil } // Creates the use case @@ -133,7 +131,7 @@ func (d componentServer) GetComponentVersions(ctx context.Context, request *pb.C if err != nil { status := se.HandleServiceError(ctx, s, err) status.Db = d.getDBVersion() - status.Server = &common.StatusResponse_Server{Version: d.version} + status.Server = &common.StatusResponse_Server{Version: d.config.App.Version} return &pb.CompVersionResponse{Status: status}, nil } @@ -144,7 +142,7 @@ func (d componentServer) GetComponentVersions(ctx context.Context, request *pb.C Status: common.StatusCode_FAILED, Message: "Problems encountered extracting components data", Db: d.getDBVersion(), - Server: &common.StatusResponse_Server{Version: d.version}, + Server: &common.StatusResponse_Server{Version: d.config.App.Version}, }}, nil } telemetryCompVersionRequestTime(ctx, d.config, requestStartTime) @@ -153,7 +151,7 @@ func (d componentServer) GetComponentVersions(ctx context.Context, request *pb.C Status: common.StatusCode_SUCCESS, Message: "Success", Db: d.getDBVersion(), - Server: &common.StatusResponse_Server{Version: d.version}, + Server: &common.StatusResponse_Server{Version: d.config.App.Version}, }}, nil } diff --git a/pkg/service/component_service_test.go b/pkg/service/component_service_test.go index c95228a..a5452fb 100644 --- a/pkg/service/component_service_test.go +++ b/pkg/service/component_service_test.go @@ -48,7 +48,8 @@ func TestComponentServer_Echo(t *testing.T) { if err != nil { t.Fatalf("failed to load Config: %v", err) } - s := NewComponentServer(db, myConfig, "test-version") + myConfig.App.Version = "test-version" + s := NewComponentServer(db, myConfig) type args struct { ctx context.Context @@ -106,7 +107,8 @@ func TestComponentServer_SearchComponents(t *testing.T) { if err != nil { t.Fatalf("failed to load Config: %v", err) } - s := NewComponentServer(db, myConfig, "test-version") + myConfig.App.Version = "test-version" + s := NewComponentServer(db, myConfig) var compRequestData = `{ "component": "react", @@ -186,7 +188,8 @@ func TestComponentServer_GetComponentVersions(t *testing.T) { if err != nil { t.Fatalf("failed to load Config: %v", err) } - s := NewComponentServer(db, myConfig, "test-version") + myConfig.App.Version = "test-version" + s := NewComponentServer(db, myConfig) var compVersionRequestData = `{ "purl": "pkg:npm/react" From e9967f26f976b4ef813d341a40639261264b5824 Mon Sep 17 00:00:00 2001 From: Agustin Isasmendi Date: Fri, 30 Jan 2026 16:57:18 +0100 Subject: [PATCH 6/7] chore(deps): update go-models to v0.4.0 --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4d58524..db385fb 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/jmoiron/sqlx v1.4.0 github.com/lib/pq v1.10.9 github.com/scanoss/go-grpc-helper v0.11.0 - github.com/scanoss/go-models v0.3.0 + github.com/scanoss/go-models v0.4.0 github.com/scanoss/go-purl-helper v0.2.1 github.com/scanoss/papi v0.28.0 github.com/scanoss/zap-logging-helper v0.4.0 diff --git a/go.sum b/go.sum index cf21ef7..b4c5901 100644 --- a/go.sum +++ b/go.sum @@ -616,6 +616,10 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= +github.com/scanoss/go-grpc-helper v0.11.0 h1:DifUX7KrQObTo9ta/vc4vqSzAdDEy1yNl+zWKuX5iOc= +github.com/scanoss/go-grpc-helper v0.11.0/go.mod h1:p2lhQTs6X5Y4E2F50qG6DbGpATtX/YYMycEcFwo9XVE= +github.com/scanoss/go-models v0.4.0 h1:TPAWgFzseChYe12RHVcsfdouZH8AleiPphKA7TwOd04= +github.com/scanoss/go-models v0.4.0/go.mod h1:Dq8ag9CI/3h0sqDWYUrTjW/jO8l5L6oopWJRKtJxzqA= github.com/scanoss/go-purl-helper v0.2.1 h1:jp960a585ycyJSlqZky1NatMJBIQi/JGITDfNSu/9As= github.com/scanoss/go-purl-helper v0.2.1/go.mod h1:v20/bKD8G+vGrILdiq6r0hyRD2bO8frCJlu9drEcQ38= github.com/scanoss/ipfilter/v2 v2.0.2 h1:GaB9i8kVJg9JQZm5XGStYkEpiaCVdsrj7ezI2wV/oh8= From b7101869d0edca4d9d389148bcdb6951fa35ccbb Mon Sep 17 00:00:00 2001 From: Agustin Isasmendi Date: Fri, 30 Jan 2026 17:20:04 +0100 Subject: [PATCH 7/7] docs(server): add TODO comment about moving app version config to server_config --- pkg/cmd/server.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/cmd/server.go b/pkg/cmd/server.go index 4294788..e82992c 100644 --- a/pkg/cmd/server.go +++ b/pkg/cmd/server.go @@ -39,6 +39,9 @@ import ( "strings" ) +//TODO: Now the config includes the app version. +// This might be worth moving to the file pkg/config/server_config.go + //go:generate bash ../../get_version.sh //go:embed version.txt var version string