From 12542853e83843f78b4dc85ebaae0d64b816d823 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Fri, 11 Apr 2025 16:38:29 +0200 Subject: [PATCH 1/2] feat: add latest flag Signed-off-by: Miguel Martinez --- .../ent/migrate/migrations/20250411122516.sql | 19 ++++++ .../pkg/data/ent/migrate/migrations/atlas.sum | 3 +- .../pkg/data/ent/migrate/schema.go | 5 +- app/controlplane/pkg/data/ent/mutation.go | 56 +++++++++++++++- .../pkg/data/ent/projectversion.go | 13 +++- .../data/ent/projectversion/projectversion.go | 10 +++ .../pkg/data/ent/projectversion/where.go | 15 +++++ .../pkg/data/ent/projectversion_create.go | 65 +++++++++++++++++++ .../pkg/data/ent/projectversion_update.go | 34 ++++++++++ app/controlplane/pkg/data/ent/runtime.go | 4 ++ app/controlplane/pkg/data/ent/schema-viz.html | 2 +- .../pkg/data/ent/schema/projectversion.go | 1 + app/controlplane/pkg/data/projectversion.go | 31 +++++++-- app/controlplane/pkg/data/referrer.go | 4 +- app/controlplane/pkg/data/workflowrun.go | 10 +-- 15 files changed, 249 insertions(+), 23 deletions(-) create mode 100644 app/controlplane/pkg/data/ent/migrate/migrations/20250411122516.sql diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/20250411122516.sql b/app/controlplane/pkg/data/ent/migrate/migrations/20250411122516.sql new file mode 100644 index 000000000..000605d3c --- /dev/null +++ b/app/controlplane/pkg/data/ent/migrate/migrations/20250411122516.sql @@ -0,0 +1,19 @@ +-- Modify "project_versions" table +ALTER TABLE "project_versions" ADD COLUMN "latest" boolean NOT NULL DEFAULT false; + +-- Reset all latest flags to false +UPDATE "project_versions" SET "latest" = false; + +-- Set latest to true for the most recent version of each project +WITH latest_versions AS ( + SELECT DISTINCT ON (project_id) id + FROM "project_versions" + WHERE deleted_at IS NULL + ORDER BY project_id, created_at DESC +) +UPDATE "project_versions" pv +SET "latest" = true +FROM latest_versions lv +WHERE pv.id = lv.id; + + diff --git a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum index e62167436..e33968cba 100644 --- a/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum +++ b/app/controlplane/pkg/data/ent/migrate/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:6sY+6+wQ/2pBGPP/+t/PcZkL1HxZR2wcel340cIBLAo= +h1:JyTOIqNoC4fnlehZxRclu3MD/5YT2eqUZpYUHAC6lFs= 20230706165452_init-schema.sql h1:VvqbNFEQnCvUVyj2iDYVQQxDM0+sSXqocpt/5H64k8M= 20230710111950-cas-backend.sql h1:A8iBuSzZIEbdsv9ipBtscZQuaBp3V5/VMw7eZH6GX+g= 20230712094107-cas-backends-workflow-runs.sql h1:a5rzxpVGyd56nLRSsKrmCFc9sebg65RWzLghKHh5xvI= @@ -80,3 +80,4 @@ h1:6sY+6+wQ/2pBGPP/+t/PcZkL1HxZR2wcel340cIBLAo= 20250303153626.sql h1:y38iNqTO+lutsb2hPu+gepPDgSDmsTcWbgu7kMpbIzE= 20250326110627.sql h1:kTneMHSqpE7I8Gl88jjTy2olXpdg/np0yA45lqIxBic= 20250327120254.sql h1:g7J945QzvonLcydhUryeIt2qXX/BLRo8XdClt2B6264= +20250411122516.sql h1:OyL+DBJQyf+QYMQ8+6763c63MULo0roe8kC0niidCbk= diff --git a/app/controlplane/pkg/data/ent/migrate/schema.go b/app/controlplane/pkg/data/ent/migrate/schema.go index 27f0754d4..d1bbfa711 100644 --- a/app/controlplane/pkg/data/ent/migrate/schema.go +++ b/app/controlplane/pkg/data/ent/migrate/schema.go @@ -347,6 +347,7 @@ var ( {Name: "prerelease", Type: field.TypeBool, Default: true}, {Name: "workflow_run_count", Type: field.TypeInt, Default: 0}, {Name: "released_at", Type: field.TypeTime, Nullable: true}, + {Name: "latest", Type: field.TypeBool, Default: false}, {Name: "project_id", Type: field.TypeUUID}, } // ProjectVersionsTable holds the schema information for the "project_versions" table. @@ -357,7 +358,7 @@ var ( ForeignKeys: []*schema.ForeignKey{ { Symbol: "project_versions_projects_versions", - Columns: []*schema.Column{ProjectVersionsColumns[7]}, + Columns: []*schema.Column{ProjectVersionsColumns[8]}, RefColumns: []*schema.Column{ProjectsColumns[0]}, OnDelete: schema.Cascade, }, @@ -366,7 +367,7 @@ var ( { Name: "projectversion_version_project_id", Unique: true, - Columns: []*schema.Column{ProjectVersionsColumns[1], ProjectVersionsColumns[7]}, + Columns: []*schema.Column{ProjectVersionsColumns[1], ProjectVersionsColumns[8]}, Annotation: &entsql.IndexAnnotation{ Where: "deleted_at IS NULL", }, diff --git a/app/controlplane/pkg/data/ent/mutation.go b/app/controlplane/pkg/data/ent/mutation.go index 0a3875383..962c8fa74 100644 --- a/app/controlplane/pkg/data/ent/mutation.go +++ b/app/controlplane/pkg/data/ent/mutation.go @@ -7848,6 +7848,7 @@ type ProjectVersionMutation struct { workflow_run_count *int addworkflow_run_count *int released_at *time.Time + latest *bool clearedFields map[string]struct{} project *uuid.UUID clearedproject bool @@ -8261,6 +8262,42 @@ func (m *ProjectVersionMutation) ResetReleasedAt() { delete(m.clearedFields, projectversion.FieldReleasedAt) } +// SetLatest sets the "latest" field. +func (m *ProjectVersionMutation) SetLatest(b bool) { + m.latest = &b +} + +// Latest returns the value of the "latest" field in the mutation. +func (m *ProjectVersionMutation) Latest() (r bool, exists bool) { + v := m.latest + if v == nil { + return + } + return *v, true +} + +// OldLatest returns the old "latest" field's value of the ProjectVersion entity. +// If the ProjectVersion object wasn't provided to the builder, the object is fetched from the database. +// An error is returned if the mutation operation is not UpdateOne, or the database query fails. +func (m *ProjectVersionMutation) OldLatest(ctx context.Context) (v bool, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldLatest is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldLatest requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldLatest: %w", err) + } + return oldValue.Latest, nil +} + +// ResetLatest resets all changes to the "latest" field. +func (m *ProjectVersionMutation) ResetLatest() { + m.latest = nil +} + // ClearProject clears the "project" edge to the Project entity. func (m *ProjectVersionMutation) ClearProject() { m.clearedproject = true @@ -8376,7 +8413,7 @@ func (m *ProjectVersionMutation) Type() string { // order to get all numeric fields that were incremented/decremented, call // AddedFields(). func (m *ProjectVersionMutation) Fields() []string { - fields := make([]string, 0, 7) + fields := make([]string, 0, 8) if m.version != nil { fields = append(fields, projectversion.FieldVersion) } @@ -8398,6 +8435,9 @@ func (m *ProjectVersionMutation) Fields() []string { if m.released_at != nil { fields = append(fields, projectversion.FieldReleasedAt) } + if m.latest != nil { + fields = append(fields, projectversion.FieldLatest) + } return fields } @@ -8420,6 +8460,8 @@ func (m *ProjectVersionMutation) Field(name string) (ent.Value, bool) { return m.WorkflowRunCount() case projectversion.FieldReleasedAt: return m.ReleasedAt() + case projectversion.FieldLatest: + return m.Latest() } return nil, false } @@ -8443,6 +8485,8 @@ func (m *ProjectVersionMutation) OldField(ctx context.Context, name string) (ent return m.OldWorkflowRunCount(ctx) case projectversion.FieldReleasedAt: return m.OldReleasedAt(ctx) + case projectversion.FieldLatest: + return m.OldLatest(ctx) } return nil, fmt.Errorf("unknown ProjectVersion field %s", name) } @@ -8501,6 +8545,13 @@ func (m *ProjectVersionMutation) SetField(name string, value ent.Value) error { } m.SetReleasedAt(v) return nil + case projectversion.FieldLatest: + v, ok := value.(bool) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetLatest(v) + return nil } return fmt.Errorf("unknown ProjectVersion field %s", name) } @@ -8601,6 +8652,9 @@ func (m *ProjectVersionMutation) ResetField(name string) error { case projectversion.FieldReleasedAt: m.ResetReleasedAt() return nil + case projectversion.FieldLatest: + m.ResetLatest() + return nil } return fmt.Errorf("unknown ProjectVersion field %s", name) } diff --git a/app/controlplane/pkg/data/ent/projectversion.go b/app/controlplane/pkg/data/ent/projectversion.go index 521b3f480..e29a3438c 100644 --- a/app/controlplane/pkg/data/ent/projectversion.go +++ b/app/controlplane/pkg/data/ent/projectversion.go @@ -33,6 +33,8 @@ type ProjectVersion struct { WorkflowRunCount int `json:"workflow_run_count,omitempty"` // ReleasedAt holds the value of the "released_at" field. ReleasedAt time.Time `json:"released_at,omitempty"` + // Whether this is the latest version of the project + Latest bool `json:"latest,omitempty"` // Edges holds the relations/edges for other nodes in the graph. // The values are being populated by the ProjectVersionQuery when eager-loading is set. Edges ProjectVersionEdges `json:"edges"` @@ -75,7 +77,7 @@ func (*ProjectVersion) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) for i := range columns { switch columns[i] { - case projectversion.FieldPrerelease: + case projectversion.FieldPrerelease, projectversion.FieldLatest: values[i] = new(sql.NullBool) case projectversion.FieldWorkflowRunCount: values[i] = new(sql.NullInt64) @@ -148,6 +150,12 @@ func (pv *ProjectVersion) assignValues(columns []string, values []any) error { } else if value.Valid { pv.ReleasedAt = value.Time } + case projectversion.FieldLatest: + if value, ok := values[i].(*sql.NullBool); !ok { + return fmt.Errorf("unexpected type %T for field latest", values[i]) + } else if value.Valid { + pv.Latest = value.Bool + } default: pv.selectValues.Set(columns[i], values[i]) } @@ -214,6 +222,9 @@ func (pv *ProjectVersion) String() string { builder.WriteString(", ") builder.WriteString("released_at=") builder.WriteString(pv.ReleasedAt.Format(time.ANSIC)) + builder.WriteString(", ") + builder.WriteString("latest=") + builder.WriteString(fmt.Sprintf("%v", pv.Latest)) builder.WriteByte(')') return builder.String() } diff --git a/app/controlplane/pkg/data/ent/projectversion/projectversion.go b/app/controlplane/pkg/data/ent/projectversion/projectversion.go index 1a2c4f32f..ab4ad77c1 100644 --- a/app/controlplane/pkg/data/ent/projectversion/projectversion.go +++ b/app/controlplane/pkg/data/ent/projectversion/projectversion.go @@ -29,6 +29,8 @@ const ( FieldWorkflowRunCount = "workflow_run_count" // FieldReleasedAt holds the string denoting the released_at field in the database. FieldReleasedAt = "released_at" + // FieldLatest holds the string denoting the latest field in the database. + FieldLatest = "latest" // EdgeProject holds the string denoting the project edge name in mutations. EdgeProject = "project" // EdgeRuns holds the string denoting the runs edge name in mutations. @@ -61,6 +63,7 @@ var Columns = []string{ FieldPrerelease, FieldWorkflowRunCount, FieldReleasedAt, + FieldLatest, } // ValidColumn reports if the column name is valid (part of the table columns). @@ -84,6 +87,8 @@ var ( DefaultPrerelease bool // DefaultWorkflowRunCount holds the default value on creation for the "workflow_run_count" field. DefaultWorkflowRunCount int + // DefaultLatest holds the default value on creation for the "latest" field. + DefaultLatest bool // DefaultID holds the default value on creation for the "id" field. DefaultID func() uuid.UUID ) @@ -131,6 +136,11 @@ func ByReleasedAt(opts ...sql.OrderTermOption) OrderOption { return sql.OrderByField(FieldReleasedAt, opts...).ToFunc() } +// ByLatest orders the results by the latest field. +func ByLatest(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldLatest, opts...).ToFunc() +} + // ByProjectField orders the results by project field. func ByProjectField(field string, opts ...sql.OrderTermOption) OrderOption { return func(s *sql.Selector) { diff --git a/app/controlplane/pkg/data/ent/projectversion/where.go b/app/controlplane/pkg/data/ent/projectversion/where.go index 4412f7bc8..9cd356261 100644 --- a/app/controlplane/pkg/data/ent/projectversion/where.go +++ b/app/controlplane/pkg/data/ent/projectversion/where.go @@ -91,6 +91,11 @@ func ReleasedAt(v time.Time) predicate.ProjectVersion { return predicate.ProjectVersion(sql.FieldEQ(FieldReleasedAt, v)) } +// Latest applies equality check predicate on the "latest" field. It's identical to LatestEQ. +func Latest(v bool) predicate.ProjectVersion { + return predicate.ProjectVersion(sql.FieldEQ(FieldLatest, v)) +} + // VersionEQ applies the EQ predicate on the "version" field. func VersionEQ(v string) predicate.ProjectVersion { return predicate.ProjectVersion(sql.FieldEQ(FieldVersion, v)) @@ -366,6 +371,16 @@ func ReleasedAtNotNil() predicate.ProjectVersion { return predicate.ProjectVersion(sql.FieldNotNull(FieldReleasedAt)) } +// LatestEQ applies the EQ predicate on the "latest" field. +func LatestEQ(v bool) predicate.ProjectVersion { + return predicate.ProjectVersion(sql.FieldEQ(FieldLatest, v)) +} + +// LatestNEQ applies the NEQ predicate on the "latest" field. +func LatestNEQ(v bool) predicate.ProjectVersion { + return predicate.ProjectVersion(sql.FieldNEQ(FieldLatest, v)) +} + // HasProject applies the HasEdge predicate on the "project" edge. func HasProject() predicate.ProjectVersion { return predicate.ProjectVersion(func(s *sql.Selector) { diff --git a/app/controlplane/pkg/data/ent/projectversion_create.go b/app/controlplane/pkg/data/ent/projectversion_create.go index 4db375f9b..c8c0a12c2 100644 --- a/app/controlplane/pkg/data/ent/projectversion_create.go +++ b/app/controlplane/pkg/data/ent/projectversion_create.go @@ -116,6 +116,20 @@ func (pvc *ProjectVersionCreate) SetNillableReleasedAt(t *time.Time) *ProjectVer return pvc } +// SetLatest sets the "latest" field. +func (pvc *ProjectVersionCreate) SetLatest(b bool) *ProjectVersionCreate { + pvc.mutation.SetLatest(b) + return pvc +} + +// SetNillableLatest sets the "latest" field if the given value is not nil. +func (pvc *ProjectVersionCreate) SetNillableLatest(b *bool) *ProjectVersionCreate { + if b != nil { + pvc.SetLatest(*b) + } + return pvc +} + // SetID sets the "id" field. func (pvc *ProjectVersionCreate) SetID(u uuid.UUID) *ProjectVersionCreate { pvc.mutation.SetID(u) @@ -201,6 +215,10 @@ func (pvc *ProjectVersionCreate) defaults() { v := projectversion.DefaultWorkflowRunCount pvc.mutation.SetWorkflowRunCount(v) } + if _, ok := pvc.mutation.Latest(); !ok { + v := projectversion.DefaultLatest + pvc.mutation.SetLatest(v) + } if _, ok := pvc.mutation.ID(); !ok { v := projectversion.DefaultID() pvc.mutation.SetID(v) @@ -229,6 +247,9 @@ func (pvc *ProjectVersionCreate) check() error { if _, ok := pvc.mutation.WorkflowRunCount(); !ok { return &ValidationError{Name: "workflow_run_count", err: errors.New(`ent: missing required field "ProjectVersion.workflow_run_count"`)} } + if _, ok := pvc.mutation.Latest(); !ok { + return &ValidationError{Name: "latest", err: errors.New(`ent: missing required field "ProjectVersion.latest"`)} + } if len(pvc.mutation.ProjectIDs()) == 0 { return &ValidationError{Name: "project", err: errors.New(`ent: missing required edge "ProjectVersion.project"`)} } @@ -292,6 +313,10 @@ func (pvc *ProjectVersionCreate) createSpec() (*ProjectVersion, *sqlgraph.Create _spec.SetField(projectversion.FieldReleasedAt, field.TypeTime, value) _node.ReleasedAt = value } + if value, ok := pvc.mutation.Latest(); ok { + _spec.SetField(projectversion.FieldLatest, field.TypeBool, value) + _node.Latest = value + } if nodes := pvc.mutation.ProjectIDs(); len(nodes) > 0 { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, @@ -455,6 +480,18 @@ func (u *ProjectVersionUpsert) ClearReleasedAt() *ProjectVersionUpsert { return u } +// SetLatest sets the "latest" field. +func (u *ProjectVersionUpsert) SetLatest(v bool) *ProjectVersionUpsert { + u.Set(projectversion.FieldLatest, v) + return u +} + +// UpdateLatest sets the "latest" field to the value that was provided on create. +func (u *ProjectVersionUpsert) UpdateLatest() *ProjectVersionUpsert { + u.SetExcluded(projectversion.FieldLatest) + return u +} + // UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field. // Using this option is equivalent to using: // @@ -600,6 +637,20 @@ func (u *ProjectVersionUpsertOne) ClearReleasedAt() *ProjectVersionUpsertOne { }) } +// SetLatest sets the "latest" field. +func (u *ProjectVersionUpsertOne) SetLatest(v bool) *ProjectVersionUpsertOne { + return u.Update(func(s *ProjectVersionUpsert) { + s.SetLatest(v) + }) +} + +// UpdateLatest sets the "latest" field to the value that was provided on create. +func (u *ProjectVersionUpsertOne) UpdateLatest() *ProjectVersionUpsertOne { + return u.Update(func(s *ProjectVersionUpsert) { + s.UpdateLatest() + }) +} + // Exec executes the query. func (u *ProjectVersionUpsertOne) Exec(ctx context.Context) error { if len(u.create.conflict) == 0 { @@ -912,6 +963,20 @@ func (u *ProjectVersionUpsertBulk) ClearReleasedAt() *ProjectVersionUpsertBulk { }) } +// SetLatest sets the "latest" field. +func (u *ProjectVersionUpsertBulk) SetLatest(v bool) *ProjectVersionUpsertBulk { + return u.Update(func(s *ProjectVersionUpsert) { + s.SetLatest(v) + }) +} + +// UpdateLatest sets the "latest" field to the value that was provided on create. +func (u *ProjectVersionUpsertBulk) UpdateLatest() *ProjectVersionUpsertBulk { + return u.Update(func(s *ProjectVersionUpsert) { + s.UpdateLatest() + }) +} + // Exec executes the query. func (u *ProjectVersionUpsertBulk) Exec(ctx context.Context) error { if u.create.err != nil { diff --git a/app/controlplane/pkg/data/ent/projectversion_update.go b/app/controlplane/pkg/data/ent/projectversion_update.go index d4cbfd924..24383279e 100644 --- a/app/controlplane/pkg/data/ent/projectversion_update.go +++ b/app/controlplane/pkg/data/ent/projectversion_update.go @@ -121,6 +121,20 @@ func (pvu *ProjectVersionUpdate) ClearReleasedAt() *ProjectVersionUpdate { return pvu } +// SetLatest sets the "latest" field. +func (pvu *ProjectVersionUpdate) SetLatest(b bool) *ProjectVersionUpdate { + pvu.mutation.SetLatest(b) + return pvu +} + +// SetNillableLatest sets the "latest" field if the given value is not nil. +func (pvu *ProjectVersionUpdate) SetNillableLatest(b *bool) *ProjectVersionUpdate { + if b != nil { + pvu.SetLatest(*b) + } + return pvu +} + // SetProject sets the "project" edge to the Project entity. func (pvu *ProjectVersionUpdate) SetProject(p *Project) *ProjectVersionUpdate { return pvu.SetProjectID(p.ID) @@ -247,6 +261,9 @@ func (pvu *ProjectVersionUpdate) sqlSave(ctx context.Context) (n int, err error) if pvu.mutation.ReleasedAtCleared() { _spec.ClearField(projectversion.FieldReleasedAt, field.TypeTime) } + if value, ok := pvu.mutation.Latest(); ok { + _spec.SetField(projectversion.FieldLatest, field.TypeBool, value) + } if pvu.mutation.ProjectCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, @@ -432,6 +449,20 @@ func (pvuo *ProjectVersionUpdateOne) ClearReleasedAt() *ProjectVersionUpdateOne return pvuo } +// SetLatest sets the "latest" field. +func (pvuo *ProjectVersionUpdateOne) SetLatest(b bool) *ProjectVersionUpdateOne { + pvuo.mutation.SetLatest(b) + return pvuo +} + +// SetNillableLatest sets the "latest" field if the given value is not nil. +func (pvuo *ProjectVersionUpdateOne) SetNillableLatest(b *bool) *ProjectVersionUpdateOne { + if b != nil { + pvuo.SetLatest(*b) + } + return pvuo +} + // SetProject sets the "project" edge to the Project entity. func (pvuo *ProjectVersionUpdateOne) SetProject(p *Project) *ProjectVersionUpdateOne { return pvuo.SetProjectID(p.ID) @@ -588,6 +619,9 @@ func (pvuo *ProjectVersionUpdateOne) sqlSave(ctx context.Context) (_node *Projec if pvuo.mutation.ReleasedAtCleared() { _spec.ClearField(projectversion.FieldReleasedAt, field.TypeTime) } + if value, ok := pvuo.mutation.Latest(); ok { + _spec.SetField(projectversion.FieldLatest, field.TypeBool, value) + } if pvuo.mutation.ProjectCleared() { edge := &sqlgraph.EdgeSpec{ Rel: sqlgraph.M2O, diff --git a/app/controlplane/pkg/data/ent/runtime.go b/app/controlplane/pkg/data/ent/runtime.go index 3a3b6b834..54a35e3c3 100644 --- a/app/controlplane/pkg/data/ent/runtime.go +++ b/app/controlplane/pkg/data/ent/runtime.go @@ -183,6 +183,10 @@ func init() { projectversionDescWorkflowRunCount := projectversionFields[6].Descriptor() // projectversion.DefaultWorkflowRunCount holds the default value on creation for the workflow_run_count field. projectversion.DefaultWorkflowRunCount = projectversionDescWorkflowRunCount.Default.(int) + // projectversionDescLatest is the schema descriptor for latest field. + projectversionDescLatest := projectversionFields[8].Descriptor() + // projectversion.DefaultLatest holds the default value on creation for the latest field. + projectversion.DefaultLatest = projectversionDescLatest.Default.(bool) // projectversionDescID is the schema descriptor for id field. projectversionDescID := projectversionFields[0].Descriptor() // projectversion.DefaultID holds the default value on creation for the id field. diff --git a/app/controlplane/pkg/data/ent/schema-viz.html b/app/controlplane/pkg/data/ent/schema-viz.html index d0f076be2..a5d20ba3b 100644 --- a/app/controlplane/pkg/data/ent/schema-viz.html +++ b/app/controlplane/pkg/data/ent/schema-viz.html @@ -70,7 +70,7 @@ } - const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); + const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"APIToken\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"expires_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Attestation\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"bundle\",\"type\":\"[]byte\"},{\"name\":\"workflowrun_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"CASBackend\",\"fields\":[{\"name\":\"location\",\"type\":\"string\"},{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"provider\",\"type\":\"biz.CASBackendProvider\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"validation_status\",\"type\":\"biz.CASBackendValidationStatus\"},{\"name\":\"validated_at\",\"type\":\"time.Time\"},{\"name\":\"default\",\"type\":\"bool\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"fallback\",\"type\":\"bool\"},{\"name\":\"max_blob_size_bytes\",\"type\":\"int64\"}]},{\"id\":\"CASMapping\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_run_id\",\"type\":\"uuid.UUID\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Integration\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"secret_name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"}]},{\"id\":\"IntegrationAttachment\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"configuration\",\"type\":\"[]byte\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"Membership\",\"fields\":[{\"name\":\"current\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"OrgInvitation\",\"fields\":[{\"name\":\"receiver_email\",\"type\":\"string\"},{\"name\":\"status\",\"type\":\"biz.OrgInvitationStatus\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"sender_id\",\"type\":\"uuid.UUID\"},{\"name\":\"role\",\"type\":\"authz.Role\"}]},{\"id\":\"Organization\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"block_on_policy_violation\",\"type\":\"bool\"}]},{\"id\":\"Project\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"}]},{\"id\":\"ProjectVersion\",\"fields\":[{\"name\":\"version\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"prerelease\",\"type\":\"bool\"},{\"name\":\"workflow_run_count\",\"type\":\"int\"},{\"name\":\"released_at\",\"type\":\"time.Time\"},{\"name\":\"latest\",\"type\":\"bool\"}]},{\"id\":\"Referrer\",\"fields\":[{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"kind\",\"type\":\"string\"},{\"name\":\"downloadable\",\"type\":\"bool\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"metadata\",\"type\":\"map[string]string\"},{\"name\":\"annotations\",\"type\":\"map[string]string\"}]},{\"id\":\"RobotAccount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"revoked_at\",\"type\":\"time.Time\"}]},{\"id\":\"User\",\"fields\":[{\"name\":\"email\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"has_restricted_access\",\"type\":\"bool\"}]},{\"id\":\"Workflow\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"project_old\",\"type\":\"string\"},{\"name\":\"team\",\"type\":\"string\"},{\"name\":\"runs_count\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"updated_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"public\",\"type\":\"bool\"},{\"name\":\"organization_id\",\"type\":\"uuid.UUID\"},{\"name\":\"project_id\",\"type\":\"uuid.UUID\"},{\"name\":\"latest_run\",\"type\":\"uuid.UUID\"},{\"name\":\"description\",\"type\":\"string\"},{\"name\":\"metadata\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"WorkflowContract\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"deleted_at\",\"type\":\"time.Time\"},{\"name\":\"description\",\"type\":\"string\"}]},{\"id\":\"WorkflowContractVersion\",\"fields\":[{\"name\":\"body\",\"type\":\"[]byte\"},{\"name\":\"raw_body\",\"type\":\"[]byte\"},{\"name\":\"raw_body_format\",\"type\":\"unmarshal.RawFormat\"},{\"name\":\"revision\",\"type\":\"int\"},{\"name\":\"created_at\",\"type\":\"time.Time\"}]},{\"id\":\"WorkflowRun\",\"fields\":[{\"name\":\"created_at\",\"type\":\"time.Time\"},{\"name\":\"finished_at\",\"type\":\"time.Time\"},{\"name\":\"state\",\"type\":\"biz.WorkflowRunStatus\"},{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"run_url\",\"type\":\"string\"},{\"name\":\"runner_type\",\"type\":\"string\"},{\"name\":\"attestation\",\"type\":\"*dsse.Envelope\"},{\"name\":\"attestation_digest\",\"type\":\"string\"},{\"name\":\"attestation_state\",\"type\":\"[]byte\"},{\"name\":\"contract_revision_used\",\"type\":\"int\"},{\"name\":\"contract_revision_latest\",\"type\":\"int\"},{\"name\":\"version_id\",\"type\":\"uuid.UUID\"},{\"name\":\"workflow_id\",\"type\":\"uuid.UUID\"}]}],\"edges\":[{\"from\":\"CASMapping\",\"to\":\"CASBackend\",\"label\":\"cas_backend\"},{\"from\":\"CASMapping\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Integration\",\"label\":\"integration\"},{\"from\":\"IntegrationAttachment\",\"to\":\"Workflow\",\"label\":\"workflow\"},{\"from\":\"OrgInvitation\",\"to\":\"Organization\",\"label\":\"organization\"},{\"from\":\"OrgInvitation\",\"to\":\"User\",\"label\":\"sender\"},{\"from\":\"Organization\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Organization\",\"to\":\"WorkflowContract\",\"label\":\"workflow_contracts\"},{\"from\":\"Organization\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Organization\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"Organization\",\"to\":\"Integration\",\"label\":\"integrations\"},{\"from\":\"Organization\",\"to\":\"APIToken\",\"label\":\"api_tokens\"},{\"from\":\"Organization\",\"to\":\"Project\",\"label\":\"projects\"},{\"from\":\"Project\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"Project\",\"to\":\"ProjectVersion\",\"label\":\"versions\"},{\"from\":\"ProjectVersion\",\"to\":\"WorkflowRun\",\"label\":\"runs\"},{\"from\":\"Referrer\",\"to\":\"Referrer\",\"label\":\"references\"},{\"from\":\"Referrer\",\"to\":\"Workflow\",\"label\":\"workflows\"},{\"from\":\"User\",\"to\":\"Membership\",\"label\":\"memberships\"},{\"from\":\"Workflow\",\"to\":\"RobotAccount\",\"label\":\"robotaccounts\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"workflowruns\"},{\"from\":\"Workflow\",\"to\":\"WorkflowContract\",\"label\":\"contract\"},{\"from\":\"Workflow\",\"to\":\"WorkflowRun\",\"label\":\"latest_workflow_run\"},{\"from\":\"WorkflowContract\",\"to\":\"WorkflowContractVersion\",\"label\":\"versions\"},{\"from\":\"WorkflowRun\",\"to\":\"WorkflowContractVersion\",\"label\":\"contract_version\"},{\"from\":\"WorkflowRun\",\"to\":\"CASBackend\",\"label\":\"cas_backends\"},{\"from\":\"WorkflowRun\",\"to\":\"Attestation\",\"label\":\"attestation_bundle\"}]}"); const nodes = new vis.DataSet((entGraph.nodes || []).map(n => ({ id: n.id, diff --git a/app/controlplane/pkg/data/ent/schema/projectversion.go b/app/controlplane/pkg/data/ent/schema/projectversion.go index b7bcd2437..fa4cf260c 100644 --- a/app/controlplane/pkg/data/ent/schema/projectversion.go +++ b/app/controlplane/pkg/data/ent/schema/projectversion.go @@ -55,6 +55,7 @@ func (ProjectVersion) Fields() []ent.Field { field.Int("workflow_run_count").Default(0), // When the version was released field.Time("released_at").Optional(), + field.Bool("latest").Default(false).Comment("Whether this is the latest version of the project"), } } diff --git a/app/controlplane/pkg/data/projectversion.go b/app/controlplane/pkg/data/projectversion.go index d6a9e91f2..ba7e031d1 100644 --- a/app/controlplane/pkg/data/projectversion.go +++ b/app/controlplane/pkg/data/projectversion.go @@ -78,16 +78,35 @@ func (r *ProjectVersionRepo) Update(ctx context.Context, id uuid.UUID, updates * } func (r *ProjectVersionRepo) Create(ctx context.Context, projectID uuid.UUID, version string, prerelease bool) (*biz.ProjectVersion, error) { - pv, err := r.data.DB.ProjectVersion.Create(). + var res *ent.ProjectVersion + if err := WithTx(ctx, r.data.DB, func(tx *ent.Tx) error { + var err error + res, err = createProjectWithTx(ctx, tx, projectID, version, prerelease) + return err + }); err != nil { + return nil, err + } + + return entProjectVersionToBiz(res), nil +} + +func createProjectWithTx(ctx context.Context, tx *ent.Tx, projectID uuid.UUID, version string, prerelease bool) (*ent.ProjectVersion, error) { + // Update all existing versions of this project to not be the latest + if err := tx.ProjectVersion.Update(). + Where( + projectversion.ProjectID(projectID), + projectversion.DeletedAtIsNil(), + projectversion.Latest(true), + ).SetLatest(false).Exec(ctx); err != nil { + return nil, err + } + + return tx.ProjectVersion.Create(). SetProjectID(projectID). SetVersion(version). SetPrerelease(prerelease). + SetLatest(true). Save(ctx) - if err != nil { - return nil, err - } - - return entProjectVersionToBiz(pv), nil } func entProjectVersionToBiz(v *ent.ProjectVersion) *biz.ProjectVersion { diff --git a/app/controlplane/pkg/data/referrer.go b/app/controlplane/pkg/data/referrer.go index 2ff436471..bd238fb21 100644 --- a/app/controlplane/pkg/data/referrer.go +++ b/app/controlplane/pkg/data/referrer.go @@ -58,13 +58,13 @@ func (r *ReferrerRepo) Save(ctx context.Context, referrers []*biz.Referrer, work for _, ref := range referrers { // Check if it exists already, if not create it - storedID := r.data.DB.Referrer.Create(). + storedID, err := r.data.DB.Referrer.Create(). SetDigest(ref.Digest).SetKind(ref.Kind).SetDownloadable(ref.Downloadable). SetMetadata(ref.Metadata).SetAnnotations(ref.Annotations). AddWorkflowIDs(workflowID). OnConflictColumns( referrer.FieldDigest, referrer.FieldKind, - ).UpdateNewValues().IDX(ctx) + ).UpdateNewValues().ID(ctx) if err != nil { return fmt.Errorf("failed to create referrer: %w", err) } diff --git a/app/controlplane/pkg/data/workflowrun.go b/app/controlplane/pkg/data/workflowrun.go index 29aee3013..e8e3cb735 100644 --- a/app/controlplane/pkg/data/workflowrun.go +++ b/app/controlplane/pkg/data/workflowrun.go @@ -65,18 +65,10 @@ func (r *WorkflowRunRepo) Create(ctx context.Context, opts *biz.WorkflowRunRepoC // Create version and workflow in a transaction if err = WithTx(ctx, r.data.DB, func(tx *ent.Tx) error { if version == nil { - // Find or create version. - versionID, err := tx.ProjectVersion.Create().SetVersion(opts.ProjectVersion).SetProjectID(wf.ProjectID). - OnConflict( - sql.ConflictColumns(projectversion.FieldVersion, projectversion.FieldProjectID), - // Since we are using a partial index, we need to explicitly craft the upsert query - sql.ConflictWhere(sql.IsNull(projectversion.FieldDeletedAt)), - ).Ignore().ID(ctx) + version, err = createProjectWithTx(ctx, tx, wf.ProjectID, opts.ProjectVersion, true) if err != nil { return fmt.Errorf("creating version: %w", err) } - - version = &ent.ProjectVersion{ID: versionID, Version: opts.ProjectVersion, ProjectID: wf.ProjectID, Prerelease: true} } // Create workflow run From 1d1ec0a1c9d615b70d0a669fa7c22017aca39804 Mon Sep 17 00:00:00 2001 From: Miguel Martinez Date: Fri, 11 Apr 2025 16:55:48 +0200 Subject: [PATCH 2/2] chore: remove non-used code Signed-off-by: Miguel Martinez --- app/controlplane/pkg/data/projectversion.go | 4 ++-- app/controlplane/pkg/data/workflowrun.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controlplane/pkg/data/projectversion.go b/app/controlplane/pkg/data/projectversion.go index ba7e031d1..5a64c7e6e 100644 --- a/app/controlplane/pkg/data/projectversion.go +++ b/app/controlplane/pkg/data/projectversion.go @@ -81,7 +81,7 @@ func (r *ProjectVersionRepo) Create(ctx context.Context, projectID uuid.UUID, ve var res *ent.ProjectVersion if err := WithTx(ctx, r.data.DB, func(tx *ent.Tx) error { var err error - res, err = createProjectWithTx(ctx, tx, projectID, version, prerelease) + res, err = createProjectVersionWithTx(ctx, tx, projectID, version, prerelease) return err }); err != nil { return nil, err @@ -90,7 +90,7 @@ func (r *ProjectVersionRepo) Create(ctx context.Context, projectID uuid.UUID, ve return entProjectVersionToBiz(res), nil } -func createProjectWithTx(ctx context.Context, tx *ent.Tx, projectID uuid.UUID, version string, prerelease bool) (*ent.ProjectVersion, error) { +func createProjectVersionWithTx(ctx context.Context, tx *ent.Tx, projectID uuid.UUID, version string, prerelease bool) (*ent.ProjectVersion, error) { // Update all existing versions of this project to not be the latest if err := tx.ProjectVersion.Update(). Where( diff --git a/app/controlplane/pkg/data/workflowrun.go b/app/controlplane/pkg/data/workflowrun.go index e8e3cb735..00e1be659 100644 --- a/app/controlplane/pkg/data/workflowrun.go +++ b/app/controlplane/pkg/data/workflowrun.go @@ -65,7 +65,7 @@ func (r *WorkflowRunRepo) Create(ctx context.Context, opts *biz.WorkflowRunRepoC // Create version and workflow in a transaction if err = WithTx(ctx, r.data.DB, func(tx *ent.Tx) error { if version == nil { - version, err = createProjectWithTx(ctx, tx, wf.ProjectID, opts.ProjectVersion, true) + version, err = createProjectVersionWithTx(ctx, tx, wf.ProjectID, opts.ProjectVersion, true) if err != nil { return fmt.Errorf("creating version: %w", err) }