Skip to content

Commit

Permalink
✨ Kai support (#631)
Browse files Browse the repository at this point in the history
closes #630 

- Added endpoint:
  - GET /applications/:id/analyses/issues
  - GET /analyses
  - GET /analyses/:id/issues
- Updated api.Analysis to omit issues, summary. Struct never used this
way.
- Add field: Analysis.Commit. migration=13.

Added IssueWriter to support new endpoints.

---
migration/14
```
diff -bur migration/v13/model/analysis.go migration/v14/model/analysis.go
--- migration/v13/model/analysis.go	2024-06-11 03:29:34.402853992 -0700
+++ migration/v14/model/analysis.go	2024-06-11 04:29:29.898613621 -0700
@@ -6,7 +6,8 @@
 type Analysis struct {
 	Model
 	Effort        int
-	Archived      bool             `json:"archived"`
+	Commit        string
+	Archived      bool
 	Summary       JSON             `gorm:"type:json"`
 	Issues        []Issue          `gorm:"constraint:OnDelete:CASCADE"`
 	Dependencies  []TechDependency `gorm:"constraint:OnDelete:CASCADE"`
diff -bur migration/v13/model/application.go migration/v14/model/application.go
--- migration/v13/model/application.go	2024-06-11 03:29:34.402853992 -0700
+++ migration/v14/model/application.go	2024-06-11 04:29:29.898613621 -0700
@@ -76,7 +76,7 @@
 	return
 }
 
-// Validation Hook to avoid cyclic dependencies.
+// BeforeCreate detects cyclic dependencies.
 func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) {
 	var nextDeps []*Dependency
 	var nextAppsIDs []uint
@@ -96,11 +96,11 @@
 	return
 }
 
-// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code.
+// DependencyCyclicError reports cyclic Dependency error.
 type DependencyCyclicError struct{}
 
-func (err DependencyCyclicError) Error() string {
-	return "cyclic dependencies are not allowed"
+func (e DependencyCyclicError) Error() string {
+	return "Cyclic dependencies are not permitted."
 }
 
 type BusinessService struct {

```

---------

Signed-off-by: Jeff Ortel <jortel@redhat.com>
  • Loading branch information
jortel committed Jun 11, 2024
1 parent c28822e commit 5359ea3
Show file tree
Hide file tree
Showing 11 changed files with 1,489 additions and 160 deletions.
624 changes: 493 additions & 131 deletions api/analysis.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions hack/add/analysis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ version: 8
#
file=${aPath}
echo -n "---
commit: "42b22a90"
issues:
dependencies:
" > ${file}
Expand Down
2 changes: 2 additions & 0 deletions migration/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
v11 "github.com/konveyor/tackle2-hub/migration/v11"
v12 "github.com/konveyor/tackle2-hub/migration/v12"
v13 "github.com/konveyor/tackle2-hub/migration/v13"
v14 "github.com/konveyor/tackle2-hub/migration/v14"
v2 "github.com/konveyor/tackle2-hub/migration/v2"
v3 "github.com/konveyor/tackle2-hub/migration/v3"
v4 "github.com/konveyor/tackle2-hub/migration/v4"
Expand Down Expand Up @@ -54,5 +55,6 @@ func All() []Migration {
v11.Migration{},
v12.Migration{},
v13.Migration{},
v14.Migration{},
}
}
20 changes: 20 additions & 0 deletions migration/v14/migrate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package v14

import (
"github.com/jortel/go-utils/logr"
"github.com/konveyor/tackle2-hub/migration/v14/model"
"gorm.io/gorm"
)

var log = logr.WithName("migration|v13")

type Migration struct{}

func (r Migration) Apply(db *gorm.DB) (err error) {
err = db.AutoMigrate(r.Models()...)
return
}

func (r Migration) Models() []interface{} {
return model.All()
}
157 changes: 157 additions & 0 deletions migration/v14/model/analysis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package model

import "gorm.io/gorm"

// Analysis report.
type Analysis struct {
Model
Effort int
Commit string
Archived bool
Summary JSON `gorm:"type:json"`
Issues []Issue `gorm:"constraint:OnDelete:CASCADE"`
Dependencies []TechDependency `gorm:"constraint:OnDelete:CASCADE"`
ApplicationID uint `gorm:"index;not null"`
Application *Application
}

// TechDependency report dependency.
type TechDependency struct {
Model
Provider string `gorm:"uniqueIndex:depA"`
Name string `gorm:"uniqueIndex:depA"`
Version string `gorm:"uniqueIndex:depA"`
SHA string `gorm:"uniqueIndex:depA"`
Indirect bool
Labels JSON `gorm:"type:json"`
AnalysisID uint `gorm:"index;uniqueIndex:depA;not null"`
Analysis *Analysis
}

// Issue report issue (violation).
type Issue struct {
Model
RuleSet string `gorm:"uniqueIndex:issueA;not null"`
Rule string `gorm:"uniqueIndex:issueA;not null"`
Name string `gorm:"index"`
Description string
Category string `gorm:"index;not null"`
Incidents []Incident `gorm:"foreignKey:IssueID;constraint:OnDelete:CASCADE"`
Links JSON `gorm:"type:json"`
Facts JSON `gorm:"type:json"`
Labels JSON `gorm:"type:json"`
Effort int `gorm:"index;not null"`
AnalysisID uint `gorm:"index;uniqueIndex:issueA;not null"`
Analysis *Analysis
}

// Incident report an issue incident.
type Incident struct {
Model
File string `gorm:"index;not null"`
Line int
Message string
CodeSnip string
Facts JSON `gorm:"type:json"`
IssueID uint `gorm:"index;not null"`
Issue *Issue
}

// Link URL link.
type Link struct {
URL string `json:"url"`
Title string `json:"title,omitempty"`
}

// ArchivedIssue resource created when issues are archived.
type ArchivedIssue struct {
RuleSet string `json:"ruleSet"`
Rule string `json:"rule"`
Name string `json:"name,omitempty" yaml:",omitempty"`
Description string `json:"description,omitempty" yaml:",omitempty"`
Category string `json:"category"`
Effort int `json:"effort"`
Incidents int `json:"incidents"`
}

// RuleSet - Analysis ruleset.
type RuleSet struct {
Model
UUID *string `gorm:"uniqueIndex"`
Kind string
Name string `gorm:"uniqueIndex;not null"`
Description string
Repository JSON `gorm:"type:json"`
IdentityID *uint `gorm:"index"`
Identity *Identity
Rules []Rule `gorm:"constraint:OnDelete:CASCADE"`
DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"`
}

func (r *RuleSet) Builtin() bool {
return r.UUID != nil
}

// BeforeUpdate hook to avoid cyclic dependencies.
func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) {
seen := make(map[uint]bool)
var nextDeps []RuleSet
var nextRuleSetIDs []uint
for _, dep := range r.DependsOn {
nextRuleSetIDs = append(nextRuleSetIDs, dep.ID)
}
for len(nextRuleSetIDs) != 0 {
result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps)
if result.Error != nil {
err = result.Error
return
}
nextRuleSetIDs = nextRuleSetIDs[:0]
for _, nextDep := range nextDeps {
for _, dep := range nextDep.DependsOn {
if seen[dep.ID] {
continue
}
if dep.ID == r.ID {
err = DependencyCyclicError{}
return
}
seen[dep.ID] = true
nextRuleSetIDs = append(nextRuleSetIDs, dep.ID)
}
}
}

return
}

// Rule - Analysis rule.
type Rule struct {
Model
Name string
Description string
Labels JSON `gorm:"type:json"`
RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"`
RuleSet *RuleSet
FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"`
File *File
}

// Target - analysis rule selector.
type Target struct {
Model
UUID *string `gorm:"uniqueIndex"`
Name string `gorm:"uniqueIndex;not null"`
Description string
Provider string
Choice bool
Labels JSON `gorm:"type:json"`
ImageID uint `gorm:"index" ref:"file"`
Image *File
RuleSetID *uint `gorm:"index"`
RuleSet *RuleSet
}

func (r *Target) Builtin() bool {
return r.UUID != nil
}
Loading

0 comments on commit 5359ea3

Please sign in to comment.