From 034abdfe2bd6d8eb0b6439e1e0d39f7bbb42932e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 05:14:18 +0000 Subject: [PATCH 1/4] feat: update ConversionOutcome to output as string in JSON This implements the json.Marshaler and json.Unmarshaler interfaces for the `ConversionOutcome` enum so that the `outcome` field in the `ConversionMetrics` output shows the string value (e.g. "Successful") instead of its integer value. Co-authored-by: jess-lowe <86962800+jess-lowe@users.noreply.github.com> --- vulnfeeds/models/metrics.go | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/vulnfeeds/models/metrics.go b/vulnfeeds/models/metrics.go index e8b9565ac9a..8e64dc4db4b 100644 --- a/vulnfeeds/models/metrics.go +++ b/vulnfeeds/models/metrics.go @@ -1,6 +1,7 @@ package models import ( + "encoding/json" "fmt" "log/slog" @@ -36,8 +37,33 @@ var RefTagDenyList = []string{ "Broken Link", // Actively ignore these. } +var conversionOutcomeStrings = [...]string{ + "ConversionUnknown", "Successful", "Rejected", "NoSoftware", "NoRepos", "NoCommitRanges", "NoRanges", "FixUnresolvable", "Error", +} + func (c ConversionOutcome) String() string { - return [...]string{"ConversionUnknown", "Successful", "Rejected", "NoSoftware", "NoRepos", "NoCommitRanges", "NoRanges", "FixUnresolvable", "Error"}[c] + if int(c) >= 0 && int(c) < len(conversionOutcomeStrings) { + return conversionOutcomeStrings[c] + } + return fmt.Sprintf("ConversionOutcome(%d)", c) +} + +func (c ConversionOutcome) MarshalJSON() ([]byte, error) { + return json.Marshal(c.String()) +} + +func (c *ConversionOutcome) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + for i, val := range conversionOutcomeStrings { + if val == s { + *c = ConversionOutcome(i) + return nil + } + } + return fmt.Errorf("invalid ConversionOutcome %q", s) } // ConversionMetrics holds the collected data about the conversion process for a single CVE. From c75bc728bf3132b59a4cc913135a028bf4edf6ed Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 13 Mar 2026 06:30:34 +0000 Subject: [PATCH 2/4] feat: update ConversionOutcome to output as string in JSON This implements the json.Marshaler and json.Unmarshaler interfaces for the `ConversionOutcome` enum so that the `outcome` field in the `ConversionMetrics` output shows the string value (e.g. "Successful") instead of its integer value. The receivers were correctly adjusted to use value receivers for String() and MarshalJSON(), and pointer receiver for UnmarshalJSON(), which fixes the `recvcheck` linter error by silencing it on the UnmarshalJSON method. Blank lines were also added to adhere to `nlreturn` rules. Co-authored-by: jess-lowe <86962800+jess-lowe@users.noreply.github.com> --- vulnfeeds/models/metrics.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vulnfeeds/models/metrics.go b/vulnfeeds/models/metrics.go index 8e64dc4db4b..2758c9d6334 100644 --- a/vulnfeeds/models/metrics.go +++ b/vulnfeeds/models/metrics.go @@ -45,6 +45,7 @@ func (c ConversionOutcome) String() string { if int(c) >= 0 && int(c) < len(conversionOutcomeStrings) { return conversionOutcomeStrings[c] } + return fmt.Sprintf("ConversionOutcome(%d)", c) } @@ -52,6 +53,7 @@ func (c ConversionOutcome) MarshalJSON() ([]byte, error) { return json.Marshal(c.String()) } +//nolint:recvcheck // UnmarshalJSON requires a pointer receiver func (c *ConversionOutcome) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { @@ -60,9 +62,11 @@ func (c *ConversionOutcome) UnmarshalJSON(b []byte) error { for i, val := range conversionOutcomeStrings { if val == s { *c = ConversionOutcome(i) + return nil } } + return fmt.Errorf("invalid ConversionOutcome %q", s) } From e464c6c3c5fdd82eeb51723d341bbb5488b0010e Mon Sep 17 00:00:00 2001 From: Jess Lowe Date: Sun, 15 Mar 2026 22:43:12 +0000 Subject: [PATCH 3/4] fix lint --- vulnfeeds/models/metrics.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vulnfeeds/models/metrics.go b/vulnfeeds/models/metrics.go index 2758c9d6334..dc594376752 100644 --- a/vulnfeeds/models/metrics.go +++ b/vulnfeeds/models/metrics.go @@ -9,6 +9,7 @@ import ( "github.com/ossf/osv-schema/bindings/go/osvschema" ) +//nolint:recvcheck type ConversionOutcome int const ( @@ -53,7 +54,6 @@ func (c ConversionOutcome) MarshalJSON() ([]byte, error) { return json.Marshal(c.String()) } -//nolint:recvcheck // UnmarshalJSON requires a pointer receiver func (c *ConversionOutcome) UnmarshalJSON(b []byte) error { var s string if err := json.Unmarshal(b, &s); err != nil { From f6e275cd5e854226f3119645263817e08c0c801c Mon Sep 17 00:00:00 2001 From: Jess Lowe Date: Mon, 16 Mar 2026 03:00:51 +0000 Subject: [PATCH 4/4] returning 0 is fine if it doesnt exist --- vulnfeeds/models/metrics.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vulnfeeds/models/metrics.go b/vulnfeeds/models/metrics.go index dc594376752..2befba51d4f 100644 --- a/vulnfeeds/models/metrics.go +++ b/vulnfeeds/models/metrics.go @@ -47,7 +47,7 @@ func (c ConversionOutcome) String() string { return conversionOutcomeStrings[c] } - return fmt.Sprintf("ConversionOutcome(%d)", c) + return conversionOutcomeStrings[ConversionUnknown] } func (c ConversionOutcome) MarshalJSON() ([]byte, error) {