182 lines
4.7 KiB
Go
182 lines
4.7 KiB
Go
package models
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
cairnapi "github.com/mattnite/cairn/internal/api"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type CreateArtifactParams struct {
|
|
RepositoryID uint
|
|
CommitID uint
|
|
BuildID *uint
|
|
CampaignID *uint
|
|
Type string
|
|
BlobKey string
|
|
BlobSize int64
|
|
CrashMessage *string
|
|
StackTrace *string
|
|
Tags json.RawMessage
|
|
Metadata json.RawMessage
|
|
}
|
|
|
|
func CreateArtifact(ctx context.Context, db *gorm.DB, p CreateArtifactParams) (*cairnapi.Artifact, error) {
|
|
if p.Tags == nil {
|
|
p.Tags = json.RawMessage("{}")
|
|
}
|
|
if p.Metadata == nil {
|
|
p.Metadata = json.RawMessage("{}")
|
|
}
|
|
|
|
a := &Artifact{
|
|
RepositoryID: p.RepositoryID,
|
|
CommitID: p.CommitID,
|
|
BuildID: p.BuildID,
|
|
CampaignID: p.CampaignID,
|
|
Type: p.Type,
|
|
BlobKey: p.BlobKey,
|
|
BlobSize: p.BlobSize,
|
|
CrashMessage: p.CrashMessage,
|
|
StackTrace: p.StackTrace,
|
|
Tags: p.Tags,
|
|
Metadata: p.Metadata,
|
|
}
|
|
|
|
if err := db.WithContext(ctx).Create(a).Error; err != nil {
|
|
return nil, fmt.Errorf("creating artifact: %w", err)
|
|
}
|
|
return enrichArtifact(ctx, db, *a)
|
|
}
|
|
|
|
func GetArtifact(ctx context.Context, db *gorm.DB, id uint) (*cairnapi.Artifact, error) {
|
|
a := &Artifact{}
|
|
if err := db.WithContext(ctx).First(a, id).Error; err != nil {
|
|
return nil, fmt.Errorf("getting artifact: %w", err)
|
|
}
|
|
return enrichArtifact(ctx, db, *a)
|
|
}
|
|
|
|
type ListArtifactsParams struct {
|
|
RepositoryID *uint
|
|
CommitSHA string
|
|
Type string
|
|
SignatureID *uint
|
|
CampaignID *uint
|
|
Limit int
|
|
Offset int
|
|
}
|
|
|
|
func ListArtifacts(ctx context.Context, db *gorm.DB, p ListArtifactsParams) ([]cairnapi.Artifact, int64, error) {
|
|
if p.Limit <= 0 {
|
|
p.Limit = 50
|
|
}
|
|
|
|
query := db.WithContext(ctx).Model(&Artifact{})
|
|
|
|
if p.RepositoryID != nil {
|
|
query = query.Where("repository_id = ?", *p.RepositoryID)
|
|
}
|
|
if p.Type != "" {
|
|
query = query.Where("type = ?", p.Type)
|
|
}
|
|
if p.SignatureID != nil {
|
|
query = query.Where("crash_signature_id = ?", *p.SignatureID)
|
|
}
|
|
if p.CampaignID != nil {
|
|
query = query.Where("campaign_id = ?", *p.CampaignID)
|
|
}
|
|
if p.CommitSHA != "" {
|
|
query = query.Joins("JOIN commits ON commits.id = artifacts.commit_id").Where("commits.sha = ?", p.CommitSHA)
|
|
}
|
|
|
|
var total int64
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, 0, fmt.Errorf("counting artifacts: %w", err)
|
|
}
|
|
|
|
var dbArtifacts []Artifact
|
|
if err := query.Order("created_at DESC").Limit(p.Limit).Offset(p.Offset).Find(&dbArtifacts).Error; err != nil {
|
|
return nil, 0, fmt.Errorf("listing artifacts: %w", err)
|
|
}
|
|
|
|
artifacts := make([]cairnapi.Artifact, 0, len(dbArtifacts))
|
|
for _, m := range dbArtifacts {
|
|
a, err := enrichArtifact(ctx, db, m)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
artifacts = append(artifacts, *a)
|
|
}
|
|
|
|
return artifacts, total, nil
|
|
}
|
|
|
|
func SearchArtifacts(ctx context.Context, db *gorm.DB, query string, limit, offset int) ([]cairnapi.Artifact, int64, error) {
|
|
if limit <= 0 {
|
|
limit = 50
|
|
}
|
|
|
|
q := db.WithContext(ctx).Model(&Artifact{}).Where(
|
|
"type ILIKE ? OR crash_message ILIKE ? OR stack_trace ILIKE ?",
|
|
"%"+query+"%", "%"+query+"%", "%"+query+"%",
|
|
)
|
|
|
|
var total int64
|
|
if err := q.Count(&total).Error; err != nil {
|
|
return nil, 0, fmt.Errorf("counting search results: %w", err)
|
|
}
|
|
|
|
var dbArtifacts []Artifact
|
|
if err := q.Order("created_at DESC").Limit(limit).Offset(offset).Find(&dbArtifacts).Error; err != nil {
|
|
return nil, 0, fmt.Errorf("searching artifacts: %w", err)
|
|
}
|
|
|
|
artifacts := make([]cairnapi.Artifact, 0, len(dbArtifacts))
|
|
for _, m := range dbArtifacts {
|
|
a, err := enrichArtifact(ctx, db, m)
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
artifacts = append(artifacts, *a)
|
|
}
|
|
|
|
return artifacts, total, nil
|
|
}
|
|
|
|
func enrichArtifact(ctx context.Context, db *gorm.DB, model Artifact) (*cairnapi.Artifact, error) {
|
|
repo := &Repository{}
|
|
if err := db.WithContext(ctx).First(repo, model.RepositoryID).Error; err != nil {
|
|
return nil, fmt.Errorf("loading artifact repository: %w", err)
|
|
}
|
|
commit := &Commit{}
|
|
if err := db.WithContext(ctx).First(commit, model.CommitID).Error; err != nil {
|
|
return nil, fmt.Errorf("loading artifact commit: %w", err)
|
|
}
|
|
artifact := artifactFromModel(model)
|
|
artifact.RepoName = repo.Name
|
|
artifact.CommitSHA = commit.SHA
|
|
return &artifact, nil
|
|
}
|
|
|
|
func artifactFromModel(m Artifact) cairnapi.Artifact {
|
|
return cairnapi.Artifact{
|
|
ID: m.ID,
|
|
RepositoryID: m.RepositoryID,
|
|
CommitID: m.CommitID,
|
|
BuildID: m.BuildID,
|
|
CampaignID: m.CampaignID,
|
|
CrashSignatureID: m.CrashSignatureID,
|
|
Type: m.Type,
|
|
BlobKey: m.BlobKey,
|
|
BlobSize: m.BlobSize,
|
|
CrashMessage: m.CrashMessage,
|
|
StackTrace: m.StackTrace,
|
|
Tags: m.Tags,
|
|
Metadata: m.Metadata,
|
|
CreatedAt: m.CreatedAt,
|
|
}
|
|
}
|