Skip to content
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

✨ Analysis archiving #493

Merged
merged 9 commits into from
Sep 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 78 additions & 1 deletion api/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,17 @@ func (h AnalysisHandler) AppCreate(ctx *gin.Context) {
_ = ctx.Error(result.Error)
return
}
err := h.archive(ctx)
if err != nil {
_ = ctx.Error(err)
return
}
analysis := &model.Analysis{}
analysis.ApplicationID = id
analysis.CreateUser = h.BaseHandler.CurrentUser(ctx)
db := h.DB(ctx)
db.Logger = db.Logger.LogMode(logger.Error)
err := db.Create(analysis).Error
err = db.Create(analysis).Error
if err != nil {
_ = ctx.Error(err)
return
Expand Down Expand Up @@ -1728,20 +1733,85 @@ func (h *AnalysisHandler) depIDs(ctx *gin.Context, f qf.Filter) (q *gorm.DB) {
return
}

//
// archive
// - Set the 'archived' flag.
// - Set the 'summary' field with archived issues.
// - Delete issues.
// - Delete dependencies.
func (h *AnalysisHandler) archive(ctx *gin.Context) (err error) {
appId := h.pk(ctx)
var unarchived []model.Analysis
db := h.DB(ctx)
db = db.Where("ApplicationID", appId)
db = db.Where("Archived", false)
err = db.Find(&unarchived).Error
if err != nil {
return
}
for _, m := range unarchived {
db := h.DB(ctx)
db = db.Select(
"i.RuleSet",
"i.Rule",
"i.Name",
"i.Description",
"i.Category",
"i.Effort",
"COUNT(n.ID) Incidents")
db = db.Table("Issue i,")
db = db.Joins("Incident n")
db = db.Where("n.IssueID = i.ID")
db = db.Where("i.AnalysisID", m.ID)
db = db.Group("i.ID")
summary := []ArchivedIssue{}
err = db.Scan(&summary).Error
if err != nil {
return
}
db = h.DB(ctx)
db = db.Model(m)
db = db.Omit(clause.Associations)
m.Archived = true
m.Summary, _ = json.Marshal(summary)
err = db.Updates(h.fields(&m)).Error
if err != nil {
return
}
db = h.DB(ctx)
db = db.Where("AnalysisID", m.ID)
err = db.Delete(&model.Issue{}).Error
if err != nil {
return
}
db = h.DB(ctx)
db = db.Where("AnalysisID", m.ID)
err = db.Delete(&model.TechDependency{}).Error
if err != nil {
return
}
}

return
}

//
// Analysis REST resource.
type Analysis struct {
Resource `yaml:",inline"`
Effort int `json:"effort"`
Archived bool `json:"archived,omitempty" yaml:",omitempty"`
Issues []Issue `json:"issues,omitempty" yaml:",omitempty"`
Dependencies []TechDependency `json:"dependencies,omitempty" yaml:",omitempty"`
Summary []ArchivedIssue `json:"summary,omitempty" yaml:",omitempty"`
}

//
// With updates the resource with the model.
func (r *Analysis) With(m *model.Analysis) {
r.Resource.With(&m.Model)
r.Effort = m.Effort
r.Archived = m.Archived
r.Issues = []Issue{}
for i := range m.Issues {
n := Issue{}
Expand All @@ -1758,6 +1828,9 @@ func (r *Analysis) With(m *model.Analysis) {
r.Dependencies,
n)
}
if m.Summary != nil {
_ = json.Unmarshal(m.Summary, &r.Summary)
}
}

//
Expand Down Expand Up @@ -1932,6 +2005,10 @@ type Link struct {
Title string `json:"title,omitempty" yaml:",omitempty"`
}

//
// ArchivedIssue created when issues are archived.
type ArchivedIssue model.ArchivedIssue

//
// RuleReport REST resource.
type RuleReport struct {
Expand Down
2 changes: 2 additions & 0 deletions migration/pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package migration

import (
"github.com/jortel/go-utils/logr"
v10 "github.com/konveyor/tackle2-hub/migration/v10"
"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 @@ -51,5 +52,6 @@ func All() []Migration {
v7.Migration{},
v8.Migration{},
v9.Migration{},
v10.Migration{},
}
}
20 changes: 20 additions & 0 deletions migration/v10/migrate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package v10

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

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

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()
}
78 changes: 78 additions & 0 deletions migration/v10/model/analysis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package model

//
// Analysis report.
type Analysis struct {
Model
Effort int
Archived bool `json:"archived"`
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"`
}
87 changes: 87 additions & 0 deletions migration/v10/model/pkg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package model

import "github.com/konveyor/tackle2-hub/migration/v9/model"

//
// JSON field (data) type.
type JSON = []byte

type Model = model.Model
type Application = model.Application
type Archetype = model.Archetype
type Assessment = model.Assessment
type Bucket = model.Bucket
type BucketOwner = model.BucketOwner
type BusinessService = model.BusinessService
type Dependency = model.Dependency
type File = model.File
type Fact = model.Fact
type Identity = model.Identity
type Import = model.Import
type ImportSummary = model.ImportSummary
type ImportTag = model.ImportTag
type JobFunction = model.JobFunction
type MigrationWave = model.MigrationWave
type Proxy = model.Proxy
type Questionnaire = model.Questionnaire
type Review = model.Review
type Setting = model.Setting
type RuleSet = model.RuleSet
type Rule = model.Rule
type Stakeholder = model.Stakeholder
type StakeholderGroup = model.StakeholderGroup
type Tag = model.Tag
type TagCategory = model.TagCategory
type Target = model.Target
type Task = model.Task
type TaskGroup = model.TaskGroup
type TaskReport = model.TaskReport
type Ticket = model.Ticket
type Tracker = model.Tracker
type TTL = model.TTL
type ApplicationTag = model.ApplicationTag
type DependencyCyclicError = model.DependencyCyclicError

//
// All builds all models.
// Models are enumerated such that each are listed after
// all the other models on which they may depend.
func All() []interface{} {
return []interface{}{
Application{},
TechDependency{},
Incident{},
Analysis{},
Issue{},
Bucket{},
BusinessService{},
Dependency{},
File{},
Fact{},
Identity{},
Import{},
ImportSummary{},
ImportTag{},
JobFunction{},
MigrationWave{},
Proxy{},
Review{},
Setting{},
RuleSet{},
Rule{},
Stakeholder{},
StakeholderGroup{},
Tag{},
TagCategory{},
Target{},
Task{},
TaskGroup{},
TaskReport{},
Ticket{},
Tracker{},
ApplicationTag{},
Questionnaire{},
Assessment{},
Archetype{},
}
}
3 changes: 2 additions & 1 deletion model/pkg.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package model

import (
"github.com/konveyor/tackle2-hub/migration/v9/model"
"github.com/konveyor/tackle2-hub/migration/v10/model"
"gorm.io/datatypes"
)

Expand All @@ -18,6 +18,7 @@ type Assessment = model.Assessment
type TechDependency = model.TechDependency
type Incident = model.Incident
type Analysis = model.Analysis
type ArchivedIssue = model.ArchivedIssue
type Issue = model.Issue
type Bucket = model.Bucket
type BucketOwner = model.BucketOwner
Expand Down
Loading