internal/worker: store CVERecord change history
Change-Id: I68c53b263e6c801d9ec4bdb5b34cfac6da2841eb
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/370837
Trust: Jonathan Amsterdam <jba@google.com>
Run-TryBot: Jonathan Amsterdam <jba@google.com>
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/internal/worker/store/store.go b/internal/worker/store/store.go
index be99c49..c916a99 100644
--- a/internal/worker/store/store.go
+++ b/internal/worker/store/store.go
@@ -45,6 +45,10 @@
// IssueCreatedAt is the time when the issue was created.
// Set only after a GitHub issue has been successfully created.
IssueCreatedAt time.Time
+
+ // History holds previous states of a CVERecord,
+ // from most to least recent.
+ History []*CVERecordSnapshot
}
// Validate returns an error if the CVERecord is not valid.
@@ -99,6 +103,24 @@
}
}
+// CVERecordSnapshot holds a previous state of a CVERecord.
+// The fields mean the same as those of CVERecord.
+type CVERecordSnapshot struct {
+ CommitHash string
+ CVEState string
+ TriageState TriageState
+ TriageStateReason string
+}
+
+func (r *CVERecord) Snapshot() *CVERecordSnapshot {
+ return &CVERecordSnapshot{
+ CommitHash: r.CommitHash,
+ CVEState: r.CVEState,
+ TriageState: r.TriageState,
+ TriageStateReason: r.TriageStateReason,
+ }
+}
+
// A CommitUpdateRecord describes a single update operation, which reconciles
// a commit in the CVE list repo with the DB state.
type CommitUpdateRecord struct {
diff --git a/internal/worker/update.go b/internal/worker/update.go
index b9724f3..7c85a34 100644
--- a/internal/worker/update.go
+++ b/internal/worker/update.go
@@ -316,10 +316,13 @@
mp = result.modulePath
}
mod.TriageStateReason = fmt.Sprintf("CVE changed; affected module = %q", mp)
- // TODO(golang/go#49733): keep a history of the previous states and their commits.
default:
return false, fmt.Errorf("unknown TriageState: %q", old.TriageState)
}
+ // If the triage state changed, add the old state to the history at the beginning.
+ if old.TriageState != mod.TriageState {
+ mod.History = append([]*store.CVERecordSnapshot{old.Snapshot()}, mod.History...)
+ }
// If we're here, then mod is a modification to the DB.
if err := tx.SetCVERecord(&mod); err != nil {
return false, err
diff --git a/internal/worker/update_test.go b/internal/worker/update_test.go
index af765ee..d577289 100644
--- a/internal/worker/update_test.go
+++ b/internal/worker/update_test.go
@@ -83,6 +83,9 @@
if !m.IssueCreatedAt.IsZero() {
panic("unsupported modification")
}
+ if m.History != nil {
+ c.History = m.History
+ }
return &c
}
@@ -182,10 +185,21 @@
}),
},
want: []*store.CVERecord{
- rs[0],
+ modify(rs[0], &store.CVERecord{
+ History: []*store.CVERecordSnapshot{{
+ CommitHash: commitHash,
+ CVEState: cveschema.StatePublic,
+ TriageState: store.TriageStateNoActionNeeded,
+ }},
+ }),
modify(rs[1], &store.CVERecord{
Module: clearString,
CVE: clearCVE,
+ History: []*store.CVERecordSnapshot{{
+ CommitHash: commitHash,
+ CVEState: cveschema.StateReserved,
+ TriageState: store.TriageStateNeedsIssue,
+ }},
}),
rs[2],
rs[3],
@@ -208,6 +222,11 @@
modify(rs[0], &store.CVERecord{
TriageState: store.TriageStateUpdatedSinceIssueCreation,
TriageStateReason: `CVE changed; affected module = "golang.org/x/mod"`,
+ History: []*store.CVERecordSnapshot{{
+ CommitHash: commitHash,
+ CVEState: cveschema.StatePublic,
+ TriageState: store.TriageStateIssueCreated,
+ }},
}),
modify(rs[1], &store.CVERecord{
TriageState: store.TriageStateUpdatedSinceIssueCreation,