Skip to content

Commit

Permalink
👻 refactored migrations.
Browse files Browse the repository at this point in the history
Signed-off-by: Jeff Ortel <[email protected]>
  • Loading branch information
jortel committed Oct 3, 2023
1 parent bb3d5f0 commit fd7ede7
Show file tree
Hide file tree
Showing 114 changed files with 6,114 additions and 2,029 deletions.
41 changes: 5 additions & 36 deletions hack/next-migration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ importRoot="github.com/konveyor/tackle2-hub/migration"
#
# Determine migration versions.
#
migrations=($(find ${root} -maxdepth 1 -type d -name 'v*' -printf '%f\n' | sort))
migrations=($(find ${root} -maxdepth 1 -type d -name 'v*' -printf '%f\n' | cut -c2-10 | sort -n))
current=${migrations[-1]}
n=${current#"v"}

Expand All @@ -31,9 +31,9 @@ echo "Current: ${currentDir}"
echo "Next: ${nextDir}"

#
# Create directores.
# New package.
#
mkdir -p ${nextDir}/model
mkdir -p ${nextDir}

#
# Build migrate.go
Expand Down Expand Up @@ -66,40 +66,9 @@ EOF
echo "${migrate}" > ${file}

#
# Build model/pkg.go
# Copy model
#
file=${nextDir}/model/pkg.go
pkg=$(cat << EOF
package model
import "${importRoot}/${current}/model"
//
// JSON field (data) type.
type JSON = []byte
EOF
)

echo "${pkg}" > ${file}

echo "" >> ${file}
models=$(grep "type" model/pkg.go | grep "model")
echo "${models}" >> ${file}
echo -n "
//
// 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{}{
" >> ${file}
models=$(grep "{}," ${currentDir}/model/pkg.go)
echo "${models}" | while read m
do
echo -e "\t\t${m}" >> ${file}
done
echo -e "\t}" >> ${file}
echo "}" >> ${file}
cp -r ${currentDir}/model ${nextDir}

#
# Register new migration.
Expand Down
71 changes: 70 additions & 1 deletion migration/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,13 @@ import (
liberr "github.com/jortel/go-utils/error"
"github.com/konveyor/tackle2-hub/database"
"github.com/konveyor/tackle2-hub/model"
"github.com/konveyor/tackle2-hub/nas"
"gorm.io/gorm"
"os"
"path"
"regexp"
"strconv"
"strings"
)

//
Expand Down Expand Up @@ -80,7 +86,11 @@ func Migrate(migrations []Migration) (err error) {
err = liberr.Wrap(err, "version", ver)
return
}

err = writeSchema(db, ver)
if err != nil {
err = liberr.Wrap(err, "version", ver)
return
}
err = database.Close(db)
if err != nil {
err = liberr.Wrap(err, "version", ver)
Expand Down Expand Up @@ -134,3 +144,62 @@ func autoMigrate(db *gorm.DB, models []interface{}) (err error) {
}
return
}

//
// writeSchema - writes the migrated schema to a file.
func writeSchema(db *gorm.DB, version int) (err error) {
var list []struct {
Type string `gorm:"column:type"`
Name string `gorm:"column:name"`
Table string `gorm:"column:tbl_name"`
RootPage int `gorm:"column:rootpage"`
SQL string `gorm:"column:sql"`
}
db = db.Table("sqlite_schema")
db = db.Order("1, 2")
err = db.Find(&list).Error
if err != nil {
return
}
dir := path.Join(
path.Dir(Settings.Hub.DB.Path),
"migration")
err = nas.MkDir(dir, 0755)
f, err := os.Create(path.Join(dir, strconv.Itoa(version)))
if err != nil {
return
}
defer func() {
_ = f.Close()
}()
pattern := regexp.MustCompile(`[,()]`)
SQL := func(in string) (out string) {
indent := "\n "
for {
m := pattern.FindStringIndex(in)
if m == nil {
out += in
break
}
out += indent
out += in[:m[0]]
out += indent
out += in[m[0]:m[1]]
in = in[m[1]:]
}
return
}
for _, m := range list {
s := strings.Join([]string{
m.Type,
m.Name,
m.Table,
SQL(m.SQL),
}, "|")
_, err = f.WriteString(s + "\n")
if err != nil {
return
}
}
return
}
87 changes: 87 additions & 0 deletions migration/v10/model/analysis.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package model

import "gorm.io/gorm"

//
// Analysis report.
type Analysis struct {
Expand Down Expand Up @@ -76,3 +78,88 @@ type ArchivedIssue struct {
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
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 fd7ede7

Please sign in to comment.