-
Notifications
You must be signed in to change notification settings - Fork 19
Statemachine-Refactoring #1524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Statemachine-Refactoring #1524
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR refactors vulnerability state management by introducing a dedicated state machine package. The refactoring consolidates vulnerability lifecycle logic that was previously scattered across service layers into a centralized, reusable state machine implementation.
Key changes:
- Creates new
statemachinepackage withApplyfunction and vulnerability diff utilities (DiffScanResults,DiffVulnsBetweenBranches) - Moves
Applymethod fromVulnEventmodel to the state machine package for better separation of concerns - Migrates tests from
services/asset_version_service_test.gotostatemachine/dependency_vuln_statemachine_test.go
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| utils/slice.go | Adds DereferenceSlice helper function to convert pointer slices to value slices |
| statemachine/dependency_vuln_statemachine.go | New state machine implementation containing Apply, DiffScanResults, and DiffVulnsBetweenBranches functions |
| statemachine/dependency_vuln_statemachine_test.go | Comprehensive test suite for state machine functions, migrated from service tests |
| shared/common_interfaces.go | Updates interface signatures to use new BranchVulnMatch type from state machine |
| services/dependency_vuln_service.go | Refactors to use state machine's Apply and new BranchVulnMatch type |
| services/first_party_vuln_service.go | Updates to use state machine's Apply function |
| services/license_risk_service.go | Updates to use state machine's Apply function |
| services/asset_version_service.go | Refactors to use state machine diff functions and DereferenceSlice utility |
| services/config_service.go | Minor formatting change (extra blank line in imports) |
| services/asset_version_service_test.go | Removes duplicate tests now located in state machine package |
| database/models/vulnevent_model.go | Removes Apply method, now handled by state machine |
| database/models/vulnerability_model.go | Adds required methods to Vuln interface for state machine compatibility |
Comments suppressed due to low confidence (1)
services/dependency_vuln_service.go:102
- The events extracted from other branches and stored in EventsToCopy are not being updated with the correct VulnID for the current branch's vulnerability before being saved. The events still reference the original vulnerability IDs from other branches. The VulnID field of each event in EventsToCopy should be set to the current branch vulnerability's hash before saving to the database.
func (s *DependencyVulnService) UserDetectedExistingVulnOnDifferentBranch(tx shared.DB, scannerID string, dependencyVulns []statemachine.BranchVulnMatch[*models.DependencyVuln], assetVersion models.AssetVersion, asset models.Asset) error {
if len(dependencyVulns) == 0 {
return nil
}
vulns := utils.Map(dependencyVulns, func(el statemachine.BranchVulnMatch[*models.DependencyVuln]) models.DependencyVuln {
return *el.CurrentBranchVuln
})
events := utils.Map(dependencyVulns, func(el statemachine.BranchVulnMatch[*models.DependencyVuln]) []models.VulnEvent {
return el.EventsToCopy
})
err := s.dependencyVulnRepository.SaveBatchBestEffort(tx, vulns)
if err != nil {
return err
}
return s.vulnEventRepository.SaveBatchBestEffort(tx, utils.Flat(events))
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| UserFixedFirstPartyVulns(tx DB, userID string, firstPartyVulns []models.FirstPartyVuln) error | ||
| UserDetectedFirstPartyVulns(tx DB, userID string, scannerID string, firstPartyVulns []models.FirstPartyVuln) error | ||
| UserDetectedExistingFirstPartyVulnOnDifferentBranch(tx DB, scannerID string, firstPartyVulns []models.FirstPartyVuln, alreadyExistingEvents [][]models.VulnEvent, assetVersion models.AssetVersion, asset models.Asset) error | ||
| UserDetectedExistingFirstPartyVulnOnDifferentBranch(tx DB, scannerID string, firstPartyVulns []statemachine.BranchVulnMatch[*models.FirstPartyVuln], assetVersion models.AssetVersion, asset models.Asset) error |
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The interface signature has been updated to accept []statemachine.BranchVulnMatch[*models.FirstPartyVuln], but the actual implementation in first_party_vuln_service.go still has the old signature with []models.FirstPartyVuln, alreadyExistingEvents [][]models.VulnEvent. This will cause a compilation error. The implementation needs to be updated to match the new interface signature and use the BranchVulnMatch structure to extract the vulnerability and events.
| // extractRelevantEvents consolidates events from all matching vulnerabilities | ||
| func extractRelevantEvents[T models.Vuln](vulns []T) []models.VulnEvent { | ||
| allEvents := make([]models.VulnEvent, 0) | ||
|
|
||
| for _, vuln := range vulns { | ||
| // Filter events: exclude risk assessment updates and already-copied events | ||
| relevantEvents := utils.Filter(vuln.GetEvents(), func(ev models.VulnEvent) bool { | ||
| return ev.OriginalAssetVersionName == nil && | ||
| ev.Type != dtos.EventTypeRawRiskAssessmentUpdated | ||
| }) | ||
|
|
||
| // Tag events with their source branch | ||
| taggedEvents := utils.Map(relevantEvents, func(event models.VulnEvent) models.VulnEvent { | ||
| event.OriginalAssetVersionName = utils.Ptr(vuln.GetAssetVersionName()) | ||
| return event | ||
| }) | ||
|
|
||
| allEvents = append(allEvents, taggedEvents...) | ||
| } | ||
|
|
||
| return allEvents | ||
| } |
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The events extracted from other branches are not having their ID field reset to uuid.Nil before being stored in EventsToCopy. This means when these events are saved to the database, they may conflict with existing event IDs from the source branches. Each event should have its ID reset to ensure new database entries are created.
|
|
||
| "github.com/l3montree-dev/devguard/database/models" | ||
| "github.com/l3montree-dev/devguard/database/repositories" | ||
|
|
Copilot
AI
Jan 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An extra blank line has been added between imports without any clear reason. This is a minor style inconsistency that could be removed to maintain code formatting uniformity.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Tim Bastin <38261809+timbastin@users.noreply.github.com>
No description provided.