diff --git a/ent/authschema/BUILD.bazel b/ent/authschema/BUILD.bazel index 40e6994c..cfc1db4a 100644 --- a/ent/authschema/BUILD.bazel +++ b/ent/authschema/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//ent/gen/ent/privacy", "//ent/gen/ent/target", "//ent/gen/ent/testsummary", + "//ent/gen/ent/testtarget", "//ent/schema", "//internal/database/dbauthservice", "@io_entgo_ent//entql", diff --git a/ent/authschema/privacy.go b/ent/authschema/privacy.go index 366557eb..51bab1c5 100644 --- a/ent/authschema/privacy.go +++ b/ent/authschema/privacy.go @@ -14,6 +14,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/privacy" "github.com/buildbarn/bb-portal/ent/gen/ent/target" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/internal/database/dbauthservice" ) @@ -108,3 +109,18 @@ func (TestSummary) Policy() ent.Policy { }) }) } + +// Policy for TestTarget. +func (TestTarget) Policy() ent.Policy { + return privacy.FilterFunc(func(ctx context.Context, f privacy.Filter) error { + return privacyFilterFunc(ctx, f, func(f privacy.Filter, authorizedInstanceNames []any) entql.P { + return entql.HasEdgeWith( + testtarget.EdgeTarget, + entql.HasEdgeWith( + target.EdgeInstanceName, + entql.FieldIn(instancename.FieldName, authorizedInstanceNames...), + ), + ) + }) + }) +} diff --git a/ent/authschema/privacy_test.go b/ent/authschema/privacy_test.go index f99ddff0..3d021f79 100644 --- a/ent/authschema/privacy_test.go +++ b/ent/authschema/privacy_test.go @@ -48,7 +48,7 @@ func TestPrivacy(t *testing.T) { ctx = dbauthservice.NewContextWithDbAuthService(ctx, dbAuthService) t.Run("EmptyDatabase", func(t *testing.T) { - clock.EXPECT().Now().Return(time.Unix(10000000, 0)).Times(5) + clock.EXPECT().Now().Return(time.Unix(10000000, 0)).Times(6) invocations, err := db.BazelInvocation.Query().IDs(ctx) require.NoError(t, err) @@ -66,12 +66,16 @@ func TestPrivacy(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, len(targets)) + testTargets, err := db.TestTarget.Query().IDs(ctx) + require.NoError(t, err) + require.Equal(t, 0, len(testTargets)) + testSummaries, err := db.TestSummary.Query().IDs(ctx) require.NoError(t, err) require.Equal(t, 0, len(testSummaries)) }) - clock.EXPECT().Now().Return(time.Unix(20000000, 0)).Times(5) + clock.EXPECT().Now().Return(time.Unix(20000000, 0)).Times(6) deniedInstance := testutils.CreateInstanceName(ctx, t, db, "denied") deniedInvocation, err := testutils.StartCreateInvocation(db, deniedInstance).Save(ctx) @@ -82,6 +86,8 @@ func TestPrivacy(t *testing.T) { require.NoError(t, err) deniedTarget, err := db.Target.Create().SetInstanceName(deniedInstance).SetLabel("denied").SetAspect("aspect").SetTargetKind("targetKind").Save(ctx) require.NoError(t, err) + _, err = db.TestTarget.Create().SetTarget(deniedTarget).Save(ctx) + require.NoError(t, err) deniedInvocationTarget, err := db.InvocationTarget.Create().SetBazelInvocation(deniedInvocation).SetTarget(deniedTarget).SetAbortReason(invocationtarget.AbortReasonNONE).Save(ctx) require.NoError(t, err) @@ -89,7 +95,7 @@ func TestPrivacy(t *testing.T) { require.NoError(t, err) t.Run("PopulatedDatabaseWithDeniedInstance", func(t *testing.T) { - clock.EXPECT().Now().Return(time.Unix(30000000, 0)).Times(5) + clock.EXPECT().Now().Return(time.Unix(30000000, 0)).Times(6) invocations, err := db.BazelInvocation.Query().IDs(ctx) require.NoError(t, err) @@ -107,12 +113,16 @@ func TestPrivacy(t *testing.T) { require.NoError(t, err) require.Equal(t, 0, len(targets)) + testTargets, err := db.TestTarget.Query().IDs(ctx) + require.NoError(t, err) + require.Equal(t, 0, len(testTargets)) + testSummaries, err := db.TestSummary.Query().IDs(ctx) require.NoError(t, err) require.Equal(t, 0, len(testSummaries)) }) - clock.EXPECT().Now().Return(time.Unix(40000000, 0)).Times(5) + clock.EXPECT().Now().Return(time.Unix(40000000, 0)).Times(6) allowed1Instance := testutils.CreateInstanceName(ctx, t, db, "allowed1") allowed1Invocation, err := testutils.StartCreateInvocation(db, allowed1Instance).Save(ctx) @@ -123,13 +133,15 @@ func TestPrivacy(t *testing.T) { require.NoError(t, err) allowed1Target, err := db.Target.Create().SetInstanceName(allowed1Instance).SetLabel("allowed1").SetAspect("aspect").SetTargetKind("targetKind").Save(ctx) require.NoError(t, err) + allowed1TestTarget, err := db.TestTarget.Create().SetTarget(allowed1Target).Save(ctx) + require.NoError(t, err) allowed1InvocationTarget, err := db.InvocationTarget.Create().SetBazelInvocation(allowed1Invocation).SetTarget(allowed1Target).SetAbortReason(invocationtarget.AbortReasonNONE).Save(ctx) require.NoError(t, err) allowed1TestSummary, err := db.TestSummary.Create().SetInvocationTarget(allowed1InvocationTarget).Save(ctx) require.NoError(t, err) t.Run("PopulatedDatabase", func(t *testing.T) { - clock.EXPECT().Now().Return(time.Unix(50000000, 0)).Times(5) + clock.EXPECT().Now().Return(time.Unix(50000000, 0)).Times(6) invocations, err := db.BazelInvocation.Query().IDs(ctx) require.NoError(t, err) @@ -151,13 +163,18 @@ func TestPrivacy(t *testing.T) { require.Equal(t, 1, len(targets)) require.Contains(t, targets, allowed1Target.ID) + testTargets, err := db.TestTarget.Query().IDs(ctx) + require.NoError(t, err) + require.Equal(t, 1, len(testTargets)) + require.Contains(t, testTargets, allowed1TestTarget.ID) + testSummaries, err := db.TestSummary.Query().IDs(ctx) require.NoError(t, err) require.Equal(t, 1, len(testSummaries)) require.Contains(t, testSummaries, allowed1TestSummary.ID) }) - clock.EXPECT().Now().Return(time.Unix(50000000, 0)).Times(5) + clock.EXPECT().Now().Return(time.Unix(50000000, 0)).Times(6) allowed2Instance := testutils.CreateInstanceName(ctx, t, db, "allowed2") allowed2Invocation, err := testutils.StartCreateInvocation(db, allowed2Instance).Save(ctx) @@ -168,13 +185,15 @@ func TestPrivacy(t *testing.T) { require.NoError(t, err) allowed2Target, err := db.Target.Create().SetInstanceName(allowed2Instance).SetLabel("allowed2").SetAspect("aspect").SetTargetKind("targetKind").Save(ctx) require.NoError(t, err) + allowed2TestTarget, err := db.TestTarget.Create().SetTarget(allowed2Target).Save(ctx) + require.NoError(t, err) allowed2InvocationTarget, err := db.InvocationTarget.Create().SetBazelInvocation(allowed2Invocation).SetTarget(allowed2Target).SetAbortReason(invocationtarget.AbortReasonNONE).Save(ctx) require.NoError(t, err) allowed2TestSummary, err := db.TestSummary.Create().SetInvocationTarget(allowed2InvocationTarget).Save(ctx) require.NoError(t, err) t.Run("PopulatedDatabase2", func(t *testing.T) { - clock.EXPECT().Now().Return(time.Unix(60000000, 0)).Times(5) + clock.EXPECT().Now().Return(time.Unix(60000000, 0)).Times(6) invocations, err := db.BazelInvocation.Query().IDs(ctx) require.NoError(t, err) @@ -200,6 +219,12 @@ func TestPrivacy(t *testing.T) { require.Contains(t, targets, allowed1Target.ID) require.Contains(t, targets, allowed2Target.ID) + testTargets, err := db.TestTarget.Query().IDs(ctx) + require.NoError(t, err) + require.Equal(t, 2, len(testTargets)) + require.Contains(t, testTargets, allowed1TestTarget.ID) + require.Contains(t, testTargets, allowed2TestTarget.ID) + testSummaries, err := db.TestSummary.Query().IDs(ctx) require.NoError(t, err) require.Equal(t, 2, len(testSummaries)) diff --git a/ent/authschema/schema.go b/ent/authschema/schema.go index fd20bd87..7ff26eac 100644 --- a/ent/authschema/schema.go +++ b/ent/authschema/schema.go @@ -61,6 +61,8 @@ type ( TargetKindMapping struct{ schema.TargetKindMapping } // TargetMetrics reexport with auth policy added TargetMetrics struct{ schema.TargetMetrics } + // TestTarget reexport with auth policy added + TestTarget struct{ schema.TestTarget } // TestResult reexport with auth policy added TestResult struct{ schema.TestResult } // TestSummary reexport with auth policy added diff --git a/ent/gen/ent/BUILD.bazel b/ent/gen/ent/BUILD.bazel index f1b1a4d4..f9578513 100644 --- a/ent/gen/ent/BUILD.bazel +++ b/ent/gen/ent/BUILD.bazel @@ -165,6 +165,11 @@ go_library( "testsummary_delete.go", "testsummary_query.go", "testsummary_update.go", + "testtarget.go", + "testtarget_create.go", + "testtarget_delete.go", + "testtarget_query.go", + "testtarget_update.go", "timingmetrics.go", "timingmetrics_create.go", "timingmetrics_delete.go", @@ -208,6 +213,7 @@ go_library( "//ent/gen/ent/targetmetrics", "//ent/gen/ent/testresult", "//ent/gen/ent/testsummary", + "//ent/gen/ent/testtarget", "//ent/gen/ent/timingmetrics", "//pkg/invocation", "@com_github_99designs_gqlgen//graphql", diff --git a/ent/gen/ent/client.go b/ent/gen/ent/client.go index bad98d46..fef6819c 100644 --- a/ent/gen/ent/client.go +++ b/ent/gen/ent/client.go @@ -45,6 +45,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/targetmetrics" "github.com/buildbarn/bb-portal/ent/gen/ent/testresult" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/timingmetrics" stdsql "database/sql" @@ -115,6 +116,8 @@ type Client struct { TestResult *TestResultClient // TestSummary is the client for interacting with the TestSummary builders. TestSummary *TestSummaryClient + // TestTarget is the client for interacting with the TestTarget builders. + TestTarget *TestTargetClient // TimingMetrics is the client for interacting with the TimingMetrics builders. TimingMetrics *TimingMetricsClient // additional fields for node api @@ -160,6 +163,7 @@ func (c *Client) init() { c.TargetMetrics = NewTargetMetricsClient(c.config) c.TestResult = NewTestResultClient(c.config) c.TestSummary = NewTestSummaryClient(c.config) + c.TestTarget = NewTestTargetClient(c.config) c.TimingMetrics = NewTimingMetricsClient(c.config) } @@ -283,6 +287,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) { TargetMetrics: NewTargetMetricsClient(cfg), TestResult: NewTestResultClient(cfg), TestSummary: NewTestSummaryClient(cfg), + TestTarget: NewTestTargetClient(cfg), TimingMetrics: NewTimingMetricsClient(cfg), }, nil } @@ -333,6 +338,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) TargetMetrics: NewTargetMetricsClient(cfg), TestResult: NewTestResultClient(cfg), TestSummary: NewTestSummaryClient(cfg), + TestTarget: NewTestTargetClient(cfg), TimingMetrics: NewTimingMetricsClient(cfg), }, nil } @@ -370,7 +376,7 @@ func (c *Client) Use(hooks ...Hook) { c.InvocationFiles, c.InvocationTarget, c.MemoryMetrics, c.Metrics, c.MissDetail, c.NetworkMetrics, c.RunnerCount, c.SourceControl, c.SystemNetworkStats, c.Target, c.TargetKindMapping, c.TargetMetrics, - c.TestResult, c.TestSummary, c.TimingMetrics, + c.TestResult, c.TestSummary, c.TestTarget, c.TimingMetrics, } { n.Use(hooks...) } @@ -387,7 +393,7 @@ func (c *Client) Intercept(interceptors ...Interceptor) { c.InvocationFiles, c.InvocationTarget, c.MemoryMetrics, c.Metrics, c.MissDetail, c.NetworkMetrics, c.RunnerCount, c.SourceControl, c.SystemNetworkStats, c.Target, c.TargetKindMapping, c.TargetMetrics, - c.TestResult, c.TestSummary, c.TimingMetrics, + c.TestResult, c.TestSummary, c.TestTarget, c.TimingMetrics, } { n.Intercept(interceptors...) } @@ -456,6 +462,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) { return c.TestResult.mutate(ctx, m) case *TestSummaryMutation: return c.TestSummary.mutate(ctx, m) + case *TestTargetMutation: + return c.TestTarget.mutate(ctx, m) case *TimingMetricsMutation: return c.TimingMetrics.mutate(ctx, m) default: @@ -4907,6 +4915,22 @@ func (c *TargetClient) QueryTargetKindMappings(t *Target) *TargetKindMappingQuer return query } +// QueryTestTarget queries the test_target edge of a Target. +func (c *TargetClient) QueryTestTarget(t *Target) *TestTargetQuery { + query := (&TestTargetClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := t.ID + step := sqlgraph.NewStep( + sqlgraph.From(target.Table, target.FieldID, id), + sqlgraph.To(testtarget.Table, testtarget.FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, target.TestTargetTable, target.TestTargetColumn), + ) + fromV = sqlgraph.Neighbors(t.driver.Dialect(), step) + return fromV, nil + } + return query +} + // Hooks returns the client hooks. func (c *TargetClient) Hooks() []Hook { hooks := c.hooks.Target @@ -5562,6 +5586,156 @@ func (c *TestSummaryClient) mutate(ctx context.Context, m *TestSummaryMutation) } } +// TestTargetClient is a client for the TestTarget schema. +type TestTargetClient struct { + config +} + +// NewTestTargetClient returns a client for the TestTarget from the given config. +func NewTestTargetClient(c config) *TestTargetClient { + return &TestTargetClient{config: c} +} + +// Use adds a list of mutation hooks to the hooks stack. +// A call to `Use(f, g, h)` equals to `testtarget.Hooks(f(g(h())))`. +func (c *TestTargetClient) Use(hooks ...Hook) { + c.hooks.TestTarget = append(c.hooks.TestTarget, hooks...) +} + +// Intercept adds a list of query interceptors to the interceptors stack. +// A call to `Intercept(f, g, h)` equals to `testtarget.Intercept(f(g(h())))`. +func (c *TestTargetClient) Intercept(interceptors ...Interceptor) { + c.inters.TestTarget = append(c.inters.TestTarget, interceptors...) +} + +// Create returns a builder for creating a TestTarget entity. +func (c *TestTargetClient) Create() *TestTargetCreate { + mutation := newTestTargetMutation(c.config, OpCreate) + return &TestTargetCreate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// CreateBulk returns a builder for creating a bulk of TestTarget entities. +func (c *TestTargetClient) CreateBulk(builders ...*TestTargetCreate) *TestTargetCreateBulk { + return &TestTargetCreateBulk{config: c.config, builders: builders} +} + +// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates +// a builder and applies setFunc on it. +func (c *TestTargetClient) MapCreateBulk(slice any, setFunc func(*TestTargetCreate, int)) *TestTargetCreateBulk { + rv := reflect.ValueOf(slice) + if rv.Kind() != reflect.Slice { + return &TestTargetCreateBulk{err: fmt.Errorf("calling to TestTargetClient.MapCreateBulk with wrong type %T, need slice", slice)} + } + builders := make([]*TestTargetCreate, rv.Len()) + for i := 0; i < rv.Len(); i++ { + builders[i] = c.Create() + setFunc(builders[i], i) + } + return &TestTargetCreateBulk{config: c.config, builders: builders} +} + +// Update returns an update builder for TestTarget. +func (c *TestTargetClient) Update() *TestTargetUpdate { + mutation := newTestTargetMutation(c.config, OpUpdate) + return &TestTargetUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOne returns an update builder for the given entity. +func (c *TestTargetClient) UpdateOne(tt *TestTarget) *TestTargetUpdateOne { + mutation := newTestTargetMutation(c.config, OpUpdateOne, withTestTarget(tt)) + return &TestTargetUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// UpdateOneID returns an update builder for the given id. +func (c *TestTargetClient) UpdateOneID(id int64) *TestTargetUpdateOne { + mutation := newTestTargetMutation(c.config, OpUpdateOne, withTestTargetID(id)) + return &TestTargetUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// Delete returns a delete builder for TestTarget. +func (c *TestTargetClient) Delete() *TestTargetDelete { + mutation := newTestTargetMutation(c.config, OpDelete) + return &TestTargetDelete{config: c.config, hooks: c.Hooks(), mutation: mutation} +} + +// DeleteOne returns a builder for deleting the given entity. +func (c *TestTargetClient) DeleteOne(tt *TestTarget) *TestTargetDeleteOne { + return c.DeleteOneID(tt.ID) +} + +// DeleteOneID returns a builder for deleting the given entity by its id. +func (c *TestTargetClient) DeleteOneID(id int64) *TestTargetDeleteOne { + builder := c.Delete().Where(testtarget.ID(id)) + builder.mutation.id = &id + builder.mutation.op = OpDeleteOne + return &TestTargetDeleteOne{builder} +} + +// Query returns a query builder for TestTarget. +func (c *TestTargetClient) Query() *TestTargetQuery { + return &TestTargetQuery{ + config: c.config, + ctx: &QueryContext{Type: TypeTestTarget}, + inters: c.Interceptors(), + } +} + +// Get returns a TestTarget entity by its id. +func (c *TestTargetClient) Get(ctx context.Context, id int64) (*TestTarget, error) { + return c.Query().Where(testtarget.ID(id)).Only(ctx) +} + +// GetX is like Get, but panics if an error occurs. +func (c *TestTargetClient) GetX(ctx context.Context, id int64) *TestTarget { + obj, err := c.Get(ctx, id) + if err != nil { + panic(err) + } + return obj +} + +// QueryTarget queries the target edge of a TestTarget. +func (c *TestTargetClient) QueryTarget(tt *TestTarget) *TargetQuery { + query := (&TargetClient{config: c.config}).Query() + query.path = func(context.Context) (fromV *sql.Selector, _ error) { + id := tt.ID + step := sqlgraph.NewStep( + sqlgraph.From(testtarget.Table, testtarget.FieldID, id), + sqlgraph.To(target.Table, target.FieldID), + sqlgraph.Edge(sqlgraph.O2O, true, testtarget.TargetTable, testtarget.TargetColumn), + ) + fromV = sqlgraph.Neighbors(tt.driver.Dialect(), step) + return fromV, nil + } + return query +} + +// Hooks returns the client hooks. +func (c *TestTargetClient) Hooks() []Hook { + hooks := c.hooks.TestTarget + return append(hooks[:len(hooks):len(hooks)], testtarget.Hooks[:]...) +} + +// Interceptors returns the client interceptors. +func (c *TestTargetClient) Interceptors() []Interceptor { + return c.inters.TestTarget +} + +func (c *TestTargetClient) mutate(ctx context.Context, m *TestTargetMutation) (Value, error) { + switch m.Op() { + case OpCreate: + return (&TestTargetCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdate: + return (&TestTargetUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpUpdateOne: + return (&TestTargetUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx) + case OpDelete, OpDeleteOne: + return (&TestTargetDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx) + default: + return nil, fmt.Errorf("ent: unknown TestTarget mutation op: %q", m.Op()) + } +} + // TimingMetricsClient is a client for the TimingMetrics schema. type TimingMetricsClient struct { config @@ -5720,7 +5894,7 @@ type ( IncompleteBuildLog, InstanceName, InvocationFiles, InvocationTarget, MemoryMetrics, Metrics, MissDetail, NetworkMetrics, RunnerCount, SourceControl, SystemNetworkStats, Target, TargetKindMapping, TargetMetrics, TestResult, - TestSummary, TimingMetrics []ent.Hook + TestSummary, TestTarget, TimingMetrics []ent.Hook } inters struct { Action, ActionCacheStatistics, ActionData, ActionSummary, ArtifactMetrics, @@ -5729,7 +5903,7 @@ type ( IncompleteBuildLog, InstanceName, InvocationFiles, InvocationTarget, MemoryMetrics, Metrics, MissDetail, NetworkMetrics, RunnerCount, SourceControl, SystemNetworkStats, Target, TargetKindMapping, TargetMetrics, TestResult, - TestSummary, TimingMetrics []ent.Interceptor + TestSummary, TestTarget, TimingMetrics []ent.Interceptor } ) diff --git a/ent/gen/ent/ent.go b/ent/gen/ent/ent.go index 9855a5d3..0055b166 100644 --- a/ent/gen/ent/ent.go +++ b/ent/gen/ent/ent.go @@ -42,6 +42,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/targetmetrics" "github.com/buildbarn/bb-portal/ent/gen/ent/testresult" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/timingmetrics" ) @@ -133,6 +134,7 @@ func checkColumn(table, column string) error { targetmetrics.Table: targetmetrics.ValidColumn, testresult.Table: testresult.ValidColumn, testsummary.Table: testsummary.ValidColumn, + testtarget.Table: testtarget.ValidColumn, timingmetrics.Table: timingmetrics.ValidColumn, }) }) diff --git a/ent/gen/ent/entql.go b/ent/gen/ent/entql.go index bcc35762..934fa174 100644 --- a/ent/gen/ent/entql.go +++ b/ent/gen/ent/entql.go @@ -34,6 +34,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/targetmetrics" "github.com/buildbarn/bb-portal/ent/gen/ent/testresult" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/timingmetrics" "entgo.io/ent/dialect/sql" @@ -44,7 +45,7 @@ import ( // schemaGraph holds a representation of ent/schema at runtime. var schemaGraph = func() *sqlgraph.Schema { - graph := &sqlgraph.Schema{Nodes: make([]*sqlgraph.Node, 31)} + graph := &sqlgraph.Schema{Nodes: make([]*sqlgraph.Node, 32)} graph.Nodes[0] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: action.Table, @@ -613,6 +614,20 @@ var schemaGraph = func() *sqlgraph.Schema { }, } graph.Nodes[30] = &sqlgraph.Node{ + NodeSpec: sqlgraph.NodeSpec{ + Table: testtarget.Table, + Columns: testtarget.Columns, + ID: &sqlgraph.FieldSpec{ + Type: field.TypeInt64, + Column: testtarget.FieldID, + }, + }, + Type: "TestTarget", + Fields: map[string]*sqlgraph.FieldSpec{ + testtarget.FieldTargetID: {Type: field.TypeInt64, Column: testtarget.FieldTargetID}, + }, + } + graph.Nodes[31] = &sqlgraph.Node{ NodeSpec: sqlgraph.NodeSpec{ Table: timingmetrics.Table, Columns: timingmetrics.Columns, @@ -1386,6 +1401,18 @@ var schemaGraph = func() *sqlgraph.Schema { "Target", "TargetKindMapping", ) + graph.MustAddE( + "test_target", + &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: target.TestTargetTable, + Columns: []string{target.TestTargetColumn}, + Bidi: false, + }, + "Target", + "TestTarget", + ) graph.MustAddE( "bazel_invocation", &sqlgraph.EdgeSpec{ @@ -1458,6 +1485,18 @@ var schemaGraph = func() *sqlgraph.Schema { "TestSummary", "TestResult", ) + graph.MustAddE( + "target", + &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: testtarget.TargetTable, + Columns: []string{testtarget.TargetColumn}, + Bidi: false, + }, + "TestTarget", + "Target", + ) graph.MustAddE( "metrics", &sqlgraph.EdgeSpec{ @@ -4151,6 +4190,20 @@ func (f *TargetFilter) WhereHasTargetKindMappingsWith(preds ...predicate.TargetK }))) } +// WhereHasTestTarget applies a predicate to check if query has an edge test_target. +func (f *TargetFilter) WhereHasTestTarget() { + f.Where(entql.HasEdge("test_target")) +} + +// WhereHasTestTargetWith applies a predicate to check if query has an edge test_target with a given conditions (other predicates). +func (f *TargetFilter) WhereHasTestTargetWith(preds ...predicate.TestTarget) { + f.Where(entql.HasEdgeWith("test_target", sqlgraph.WrapFunc(func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }))) +} + // addPredicate implements the predicateAdder interface. func (tkmq *TargetKindMappingQuery) addPredicate(pred func(s *sql.Selector)) { tkmq.predicates = append(tkmq.predicates, pred) @@ -4540,6 +4593,65 @@ func (f *TestSummaryFilter) WhereHasTestResultsWith(preds ...predicate.TestResul }))) } +// addPredicate implements the predicateAdder interface. +func (ttq *TestTargetQuery) addPredicate(pred func(s *sql.Selector)) { + ttq.predicates = append(ttq.predicates, pred) +} + +// Filter returns a Filter implementation to apply filters on the TestTargetQuery builder. +func (ttq *TestTargetQuery) Filter() *TestTargetFilter { + return &TestTargetFilter{config: ttq.config, predicateAdder: ttq} +} + +// addPredicate implements the predicateAdder interface. +func (m *TestTargetMutation) addPredicate(pred func(s *sql.Selector)) { + m.predicates = append(m.predicates, pred) +} + +// Filter returns an entql.Where implementation to apply filters on the TestTargetMutation builder. +func (m *TestTargetMutation) Filter() *TestTargetFilter { + return &TestTargetFilter{config: m.config, predicateAdder: m} +} + +// TestTargetFilter provides a generic filtering capability at runtime for TestTargetQuery. +type TestTargetFilter struct { + predicateAdder + config +} + +// Where applies the entql predicate on the query filter. +func (f *TestTargetFilter) Where(p entql.P) { + f.addPredicate(func(s *sql.Selector) { + if err := schemaGraph.EvalP(schemaGraph.Nodes[30].Type, p, s); err != nil { + s.AddError(err) + } + }) +} + +// WhereID applies the entql int64 predicate on the id field. +func (f *TestTargetFilter) WhereID(p entql.Int64P) { + f.Where(p.Field(testtarget.FieldID)) +} + +// WhereTargetID applies the entql int64 predicate on the target_id field. +func (f *TestTargetFilter) WhereTargetID(p entql.Int64P) { + f.Where(p.Field(testtarget.FieldTargetID)) +} + +// WhereHasTarget applies a predicate to check if query has an edge target. +func (f *TestTargetFilter) WhereHasTarget() { + f.Where(entql.HasEdge("target")) +} + +// WhereHasTargetWith applies a predicate to check if query has an edge target with a given conditions (other predicates). +func (f *TestTargetFilter) WhereHasTargetWith(preds ...predicate.Target) { + f.Where(entql.HasEdgeWith("target", sqlgraph.WrapFunc(func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }))) +} + // addPredicate implements the predicateAdder interface. func (tmq *TimingMetricsQuery) addPredicate(pred func(s *sql.Selector)) { tmq.predicates = append(tmq.predicates, pred) @@ -4569,7 +4681,7 @@ type TimingMetricsFilter struct { // Where applies the entql predicate on the query filter. func (f *TimingMetricsFilter) Where(p entql.P) { f.addPredicate(func(s *sql.Selector) { - if err := schemaGraph.EvalP(schemaGraph.Nodes[30].Type, p, s); err != nil { + if err := schemaGraph.EvalP(schemaGraph.Nodes[31].Type, p, s); err != nil { s.AddError(err) } }) diff --git a/ent/gen/ent/gql_collection.go b/ent/gen/ent/gql_collection.go index b39204ed..36d1beda 100644 --- a/ent/gen/ent/gql_collection.go +++ b/ent/gen/ent/gql_collection.go @@ -33,6 +33,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/targetmetrics" "github.com/buildbarn/bb-portal/ent/gen/ent/testresult" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/timingmetrics" ) @@ -2942,6 +2943,17 @@ func (t *TargetQuery) collectField(ctx context.Context, oneNode bool, opCtx *gra t.WithNamedInvocationTargets(alias, func(wq *InvocationTargetQuery) { *wq = *query }) + + case "testTarget": + var ( + alias = field.Alias + path = append(path, alias) + query = (&TestTargetClient{config: t.config}).Query() + ) + if err := query.collectField(ctx, oneNode, opCtx, field, path, mayAddCondition(satisfies, testtargetImplementors)...); err != nil { + return err + } + t.withTestTarget = query case "label": if _, ok := fieldSeen[target.FieldLabel]; !ok { selectedFields = append(selectedFields, target.FieldLabel) @@ -3382,6 +3394,88 @@ func newTestSummaryPaginateArgs(rv map[string]any) *testsummaryPaginateArgs { return args } +// CollectFields tells the query-builder to eagerly load connected nodes by resolver context. +func (tt *TestTargetQuery) CollectFields(ctx context.Context, satisfies ...string) (*TestTargetQuery, error) { + fc := graphql.GetFieldContext(ctx) + if fc == nil { + return tt, nil + } + if err := tt.collectField(ctx, false, graphql.GetOperationContext(ctx), fc.Field, nil, satisfies...); err != nil { + return nil, err + } + return tt, nil +} + +func (tt *TestTargetQuery) collectField(ctx context.Context, oneNode bool, opCtx *graphql.OperationContext, collected graphql.CollectedField, path []string, satisfies ...string) error { + path = append([]string(nil), path...) + var ( + unknownSeen bool + fieldSeen = make(map[string]struct{}, len(testtarget.Columns)) + selectedFields = []string{testtarget.FieldID} + ) + for _, field := range graphql.CollectFields(opCtx, collected.Selections, satisfies) { + switch field.Name { + + case "target": + var ( + alias = field.Alias + path = append(path, alias) + query = (&TargetClient{config: tt.config}).Query() + ) + if err := query.collectField(ctx, oneNode, opCtx, field, path, mayAddCondition(satisfies, targetImplementors)...); err != nil { + return err + } + tt.withTarget = query + if _, ok := fieldSeen[testtarget.FieldTargetID]; !ok { + selectedFields = append(selectedFields, testtarget.FieldTargetID) + fieldSeen[testtarget.FieldTargetID] = struct{}{} + } + case "targetID": + if _, ok := fieldSeen[testtarget.FieldTargetID]; !ok { + selectedFields = append(selectedFields, testtarget.FieldTargetID) + fieldSeen[testtarget.FieldTargetID] = struct{}{} + } + case "id": + case "__typename": + default: + unknownSeen = true + } + } + if !unknownSeen { + tt.Select(selectedFields...) + } + return nil +} + +type testtargetPaginateArgs struct { + first, last *int + after, before *Cursor + opts []TestTargetPaginateOption +} + +func newTestTargetPaginateArgs(rv map[string]any) *testtargetPaginateArgs { + args := &testtargetPaginateArgs{} + if rv == nil { + return args + } + if v := rv[firstField]; v != nil { + args.first = v.(*int) + } + if v := rv[lastField]; v != nil { + args.last = v.(*int) + } + if v := rv[afterField]; v != nil { + args.after = v.(*Cursor) + } + if v := rv[beforeField]; v != nil { + args.before = v.(*Cursor) + } + if v, ok := rv[whereField].(*TestTargetWhereInput); ok { + args.opts = append(args.opts, WithTestTargetFilter(v.Filter)) + } + return args +} + // CollectFields tells the query-builder to eagerly load connected nodes by resolver context. func (tm *TimingMetricsQuery) CollectFields(ctx context.Context, satisfies ...string) (*TimingMetricsQuery, error) { fc := graphql.GetFieldContext(ctx) diff --git a/ent/gen/ent/gql_edge.go b/ent/gen/ent/gql_edge.go index bf7c9876..b5d3bd78 100644 --- a/ent/gen/ent/gql_edge.go +++ b/ent/gen/ent/gql_edge.go @@ -532,6 +532,14 @@ func (t *Target) InvocationTargets( return t.QueryInvocationTargets().Paginate(ctx, after, first, before, last, opts...) } +func (t *Target) TestTarget(ctx context.Context) (*TestTarget, error) { + result, err := t.Edges.TestTargetOrErr() + if IsNotLoaded(err) { + result, err = t.QueryTestTarget().Only(ctx) + } + return result, MaskNotFound(err) +} + func (tm *TargetMetrics) Metrics(ctx context.Context) (*Metrics, error) { result, err := tm.Edges.MetricsOrErr() if IsNotLoaded(err) { @@ -568,6 +576,14 @@ func (ts *TestSummary) TestResults(ctx context.Context) (result []*TestResult, e return result, err } +func (tt *TestTarget) Target(ctx context.Context) (*Target, error) { + result, err := tt.Edges.TargetOrErr() + if IsNotLoaded(err) { + result, err = tt.QueryTarget().Only(ctx) + } + return result, err +} + func (tm *TimingMetrics) Metrics(ctx context.Context) (*Metrics, error) { result, err := tm.Edges.MetricsOrErr() if IsNotLoaded(err) { diff --git a/ent/gen/ent/gql_node.go b/ent/gen/ent/gql_node.go index 7beff763..dc674088 100644 --- a/ent/gen/ent/gql_node.go +++ b/ent/gen/ent/gql_node.go @@ -38,6 +38,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/targetmetrics" "github.com/buildbarn/bb-portal/ent/gen/ent/testresult" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/timingmetrics" "github.com/hashicorp/go-multierror" "golang.org/x/sync/semaphore" @@ -173,6 +174,11 @@ var testsummaryImplementors = []string{"TestSummary", "Node"} // IsNode implements the Node interface check for GQLGen. func (*TestSummary) IsNode() {} +var testtargetImplementors = []string{"TestTarget", "Node"} + +// IsNode implements the Node interface check for GQLGen. +func (*TestTarget) IsNode() {} + var timingmetricsImplementors = []string{"TimingMetrics", "Node"} // IsNode implements the Node interface check for GQLGen. @@ -461,6 +467,15 @@ func (c *Client) noder(ctx context.Context, table string, id int64) (Noder, erro } } return query.Only(ctx) + case testtarget.Table: + query := c.TestTarget.Query(). + Where(testtarget.ID(id)) + if fc := graphql.GetFieldContext(ctx); fc != nil { + if err := query.collectField(ctx, true, graphql.GetOperationContext(ctx), fc.Field, nil, testtargetImplementors...); err != nil { + return nil, err + } + } + return query.Only(ctx) case timingmetrics.Table: query := c.TimingMetrics.Query(). Where(timingmetrics.ID(id)) @@ -943,6 +958,22 @@ func (c *Client) noders(ctx context.Context, table string, ids []int64) ([]Noder *noder = node } } + case testtarget.Table: + query := c.TestTarget.Query(). + Where(testtarget.IDIn(ids...)) + query, err := query.CollectFields(ctx, testtargetImplementors...) + if err != nil { + return nil, err + } + nodes, err := query.All(ctx) + if err != nil { + return nil, err + } + for _, node := range nodes { + for _, noder := range idmap[node.ID] { + *noder = node + } + } case timingmetrics.Table: query := c.TimingMetrics.Query(). Where(timingmetrics.IDIn(ids...)) diff --git a/ent/gen/ent/gql_pagination.go b/ent/gen/ent/gql_pagination.go index f6906ddb..d0158159 100644 --- a/ent/gen/ent/gql_pagination.go +++ b/ent/gen/ent/gql_pagination.go @@ -39,6 +39,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/targetmetrics" "github.com/buildbarn/bb-portal/ent/gen/ent/testresult" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/timingmetrics" "github.com/vektah/gqlparser/v2/gqlerror" ) @@ -6590,6 +6591,255 @@ func (ts *TestSummary) ToEdge(order *TestSummaryOrder) *TestSummaryEdge { } } +// TestTargetEdge is the edge representation of TestTarget. +type TestTargetEdge struct { + Node *TestTarget `json:"node"` + Cursor Cursor `json:"cursor"` +} + +// TestTargetConnection is the connection containing edges to TestTarget. +type TestTargetConnection struct { + Edges []*TestTargetEdge `json:"edges"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +func (c *TestTargetConnection) build(nodes []*TestTarget, pager *testtargetPager, after *Cursor, first *int, before *Cursor, last *int) { + c.PageInfo.HasNextPage = before != nil + c.PageInfo.HasPreviousPage = after != nil + if first != nil && *first+1 == len(nodes) { + c.PageInfo.HasNextPage = true + nodes = nodes[:len(nodes)-1] + } else if last != nil && *last+1 == len(nodes) { + c.PageInfo.HasPreviousPage = true + nodes = nodes[:len(nodes)-1] + } + var nodeAt func(int) *TestTarget + if last != nil { + n := len(nodes) - 1 + nodeAt = func(i int) *TestTarget { + return nodes[n-i] + } + } else { + nodeAt = func(i int) *TestTarget { + return nodes[i] + } + } + c.Edges = make([]*TestTargetEdge, len(nodes)) + for i := range nodes { + node := nodeAt(i) + c.Edges[i] = &TestTargetEdge{ + Node: node, + Cursor: pager.toCursor(node), + } + } + if l := len(c.Edges); l > 0 { + c.PageInfo.StartCursor = &c.Edges[0].Cursor + c.PageInfo.EndCursor = &c.Edges[l-1].Cursor + } + if c.TotalCount == 0 { + c.TotalCount = len(nodes) + } +} + +// TestTargetPaginateOption enables pagination customization. +type TestTargetPaginateOption func(*testtargetPager) error + +// WithTestTargetOrder configures pagination ordering. +func WithTestTargetOrder(order *TestTargetOrder) TestTargetPaginateOption { + if order == nil { + order = DefaultTestTargetOrder + } + o := *order + return func(pager *testtargetPager) error { + if err := o.Direction.Validate(); err != nil { + return err + } + if o.Field == nil { + o.Field = DefaultTestTargetOrder.Field + } + pager.order = &o + return nil + } +} + +// WithTestTargetFilter configures pagination filter. +func WithTestTargetFilter(filter func(*TestTargetQuery) (*TestTargetQuery, error)) TestTargetPaginateOption { + return func(pager *testtargetPager) error { + if filter == nil { + return errors.New("TestTargetQuery filter cannot be nil") + } + pager.filter = filter + return nil + } +} + +type testtargetPager struct { + reverse bool + order *TestTargetOrder + filter func(*TestTargetQuery) (*TestTargetQuery, error) +} + +func newTestTargetPager(opts []TestTargetPaginateOption, reverse bool) (*testtargetPager, error) { + pager := &testtargetPager{reverse: reverse} + for _, opt := range opts { + if err := opt(pager); err != nil { + return nil, err + } + } + if pager.order == nil { + pager.order = DefaultTestTargetOrder + } + return pager, nil +} + +func (p *testtargetPager) applyFilter(query *TestTargetQuery) (*TestTargetQuery, error) { + if p.filter != nil { + return p.filter(query) + } + return query, nil +} + +func (p *testtargetPager) toCursor(tt *TestTarget) Cursor { + return p.order.Field.toCursor(tt) +} + +func (p *testtargetPager) applyCursors(query *TestTargetQuery, after, before *Cursor) (*TestTargetQuery, error) { + direction := p.order.Direction + if p.reverse { + direction = direction.Reverse() + } + for _, predicate := range entgql.CursorsPredicate(after, before, DefaultTestTargetOrder.Field.column, p.order.Field.column, direction) { + query = query.Where(predicate) + } + return query, nil +} + +func (p *testtargetPager) applyOrder(query *TestTargetQuery) *TestTargetQuery { + direction := p.order.Direction + if p.reverse { + direction = direction.Reverse() + } + query = query.Order(p.order.Field.toTerm(direction.OrderTermOption())) + if p.order.Field != DefaultTestTargetOrder.Field { + query = query.Order(DefaultTestTargetOrder.Field.toTerm(direction.OrderTermOption())) + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(p.order.Field.column) + } + return query +} + +func (p *testtargetPager) orderExpr(query *TestTargetQuery) sql.Querier { + direction := p.order.Direction + if p.reverse { + direction = direction.Reverse() + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(p.order.Field.column) + } + return sql.ExprFunc(func(b *sql.Builder) { + b.Ident(p.order.Field.column).Pad().WriteString(string(direction)) + if p.order.Field != DefaultTestTargetOrder.Field { + b.Comma().Ident(DefaultTestTargetOrder.Field.column).Pad().WriteString(string(direction)) + } + }) +} + +// Paginate executes the query and returns a relay based cursor connection to TestTarget. +func (tt *TestTargetQuery) Paginate( + ctx context.Context, after *Cursor, first *int, + before *Cursor, last *int, opts ...TestTargetPaginateOption, +) (*TestTargetConnection, error) { + if err := validateFirstLast(first, last); err != nil { + return nil, err + } + pager, err := newTestTargetPager(opts, last != nil) + if err != nil { + return nil, err + } + if tt, err = pager.applyFilter(tt); err != nil { + return nil, err + } + conn := &TestTargetConnection{Edges: []*TestTargetEdge{}} + ignoredEdges := !hasCollectedField(ctx, edgesField) + needTotalCount := hasCollectedField(ctx, totalCountField) + needPageInfo := hasCollectedField(ctx, pageInfoField) + hasPagination := after != nil || first != nil || before != nil || last != nil + if (needTotalCount && hasPagination) || (ignoredEdges && (needTotalCount || needPageInfo)) { + c := tt.Clone() + c.ctx.Fields = nil + if conn.TotalCount, err = c.Count(ctx); err != nil { + return nil, err + } + conn.PageInfo.HasNextPage = first != nil && conn.TotalCount > 0 + conn.PageInfo.HasPreviousPage = last != nil && conn.TotalCount > 0 + } + if ignoredEdges || (first != nil && *first == 0) || (last != nil && *last == 0) { + return conn, nil + } + if tt, err = pager.applyCursors(tt, after, before); err != nil { + return nil, err + } + limit := paginateLimit(first, last) + if limit != 0 { + tt.Limit(limit) + } + if field := collectedField(ctx, edgesField, nodeField); field != nil { + if err := tt.collectField(ctx, limit == 1, graphql.GetOperationContext(ctx), *field, []string{edgesField, nodeField}); err != nil { + return nil, err + } + } + tt = pager.applyOrder(tt) + nodes, err := tt.All(ctx) + if err != nil { + return nil, err + } + conn.build(nodes, pager, after, first, before, last) + return conn, nil +} + +// TestTargetOrderField defines the ordering field of TestTarget. +type TestTargetOrderField struct { + // Value extracts the ordering value from the given TestTarget. + Value func(*TestTarget) (ent.Value, error) + column string // field or computed. + toTerm func(...sql.OrderTermOption) testtarget.OrderOption + toCursor func(*TestTarget) Cursor +} + +// TestTargetOrder defines the ordering of TestTarget. +type TestTargetOrder struct { + Direction OrderDirection `json:"direction"` + Field *TestTargetOrderField `json:"field"` +} + +// DefaultTestTargetOrder is the default ordering of TestTarget. +var DefaultTestTargetOrder = &TestTargetOrder{ + Direction: entgql.OrderDirectionAsc, + Field: &TestTargetOrderField{ + Value: func(tt *TestTarget) (ent.Value, error) { + return tt.ID, nil + }, + column: testtarget.FieldID, + toTerm: testtarget.ByID, + toCursor: func(tt *TestTarget) Cursor { + return Cursor{ID: tt.ID} + }, + }, +} + +// ToEdge converts TestTarget into TestTargetEdge. +func (tt *TestTarget) ToEdge(order *TestTargetOrder) *TestTargetEdge { + if order == nil { + order = DefaultTestTargetOrder + } + return &TestTargetEdge{ + Node: tt, + Cursor: order.Field.toCursor(tt), + } +} + // TimingMetricsEdge is the edge representation of TimingMetrics. type TimingMetricsEdge struct { Node *TimingMetrics `json:"node"` diff --git a/ent/gen/ent/gql_where_input.go b/ent/gen/ent/gql_where_input.go index d8f19d90..7c429a8b 100644 --- a/ent/gen/ent/gql_where_input.go +++ b/ent/gen/ent/gql_where_input.go @@ -33,6 +33,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/targetmetrics" "github.com/buildbarn/bb-portal/ent/gen/ent/testresult" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/timingmetrics" "github.com/google/uuid" ) @@ -9320,6 +9321,10 @@ type TargetWhereInput struct { // "invocation_targets" edge predicates. HasInvocationTargets *bool `json:"hasInvocationTargets,omitempty"` HasInvocationTargetsWith []*InvocationTargetWhereInput `json:"hasInvocationTargetsWith,omitempty"` + + // "test_target" edge predicates. + HasTestTarget *bool `json:"hasTestTarget,omitempty"` + HasTestTargetWith []*TestTargetWhereInput `json:"hasTestTargetWith,omitempty"` } // AddPredicates adds custom predicates to the where input to be used during the filtering phase. @@ -9571,6 +9576,24 @@ func (i *TargetWhereInput) P() (predicate.Target, error) { } predicates = append(predicates, target.HasInvocationTargetsWith(with...)) } + if i.HasTestTarget != nil { + p := target.HasTestTarget() + if !*i.HasTestTarget { + p = target.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasTestTargetWith) > 0 { + with := make([]predicate.TestTarget, 0, len(i.HasTestTargetWith)) + for _, w := range i.HasTestTargetWith { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'HasTestTargetWith'", err) + } + with = append(with, p) + } + predicates = append(predicates, target.HasTestTargetWith(with...)) + } switch len(predicates) { case 0: return nil, ErrEmptyTargetWhereInput @@ -11077,6 +11100,170 @@ func (i *TestSummaryWhereInput) P() (predicate.TestSummary, error) { } } +// TestTargetWhereInput represents a where input for filtering TestTarget queries. +type TestTargetWhereInput struct { + Predicates []predicate.TestTarget `json:"-"` + Not *TestTargetWhereInput `json:"not,omitempty"` + Or []*TestTargetWhereInput `json:"or,omitempty"` + And []*TestTargetWhereInput `json:"and,omitempty"` + + // "id" field predicates. + ID *int64 `json:"id,omitempty"` + IDNEQ *int64 `json:"idNEQ,omitempty"` + IDIn []int64 `json:"idIn,omitempty"` + IDNotIn []int64 `json:"idNotIn,omitempty"` + IDGT *int64 `json:"idGT,omitempty"` + IDGTE *int64 `json:"idGTE,omitempty"` + IDLT *int64 `json:"idLT,omitempty"` + IDLTE *int64 `json:"idLTE,omitempty"` + + // "target_id" field predicates. + TargetID *int64 `json:"targetID,omitempty"` + TargetIDNEQ *int64 `json:"targetIDNEQ,omitempty"` + TargetIDIn []int64 `json:"targetIDIn,omitempty"` + TargetIDNotIn []int64 `json:"targetIDNotIn,omitempty"` + + // "target" edge predicates. + HasTarget *bool `json:"hasTarget,omitempty"` + HasTargetWith []*TargetWhereInput `json:"hasTargetWith,omitempty"` +} + +// AddPredicates adds custom predicates to the where input to be used during the filtering phase. +func (i *TestTargetWhereInput) AddPredicates(predicates ...predicate.TestTarget) { + i.Predicates = append(i.Predicates, predicates...) +} + +// Filter applies the TestTargetWhereInput filter on the TestTargetQuery builder. +func (i *TestTargetWhereInput) Filter(q *TestTargetQuery) (*TestTargetQuery, error) { + if i == nil { + return q, nil + } + p, err := i.P() + if err != nil { + if err == ErrEmptyTestTargetWhereInput { + return q, nil + } + return nil, err + } + return q.Where(p), nil +} + +// ErrEmptyTestTargetWhereInput is returned in case the TestTargetWhereInput is empty. +var ErrEmptyTestTargetWhereInput = errors.New("ent: empty predicate TestTargetWhereInput") + +// P returns a predicate for filtering testtargets. +// An error is returned if the input is empty or invalid. +func (i *TestTargetWhereInput) P() (predicate.TestTarget, error) { + var predicates []predicate.TestTarget + if i.Not != nil { + p, err := i.Not.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'not'", err) + } + predicates = append(predicates, testtarget.Not(p)) + } + switch n := len(i.Or); { + case n == 1: + p, err := i.Or[0].P() + if err != nil { + return nil, fmt.Errorf("%w: field 'or'", err) + } + predicates = append(predicates, p) + case n > 1: + or := make([]predicate.TestTarget, 0, n) + for _, w := range i.Or { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'or'", err) + } + or = append(or, p) + } + predicates = append(predicates, testtarget.Or(or...)) + } + switch n := len(i.And); { + case n == 1: + p, err := i.And[0].P() + if err != nil { + return nil, fmt.Errorf("%w: field 'and'", err) + } + predicates = append(predicates, p) + case n > 1: + and := make([]predicate.TestTarget, 0, n) + for _, w := range i.And { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'and'", err) + } + and = append(and, p) + } + predicates = append(predicates, testtarget.And(and...)) + } + predicates = append(predicates, i.Predicates...) + if i.ID != nil { + predicates = append(predicates, testtarget.IDEQ(*i.ID)) + } + if i.IDNEQ != nil { + predicates = append(predicates, testtarget.IDNEQ(*i.IDNEQ)) + } + if len(i.IDIn) > 0 { + predicates = append(predicates, testtarget.IDIn(i.IDIn...)) + } + if len(i.IDNotIn) > 0 { + predicates = append(predicates, testtarget.IDNotIn(i.IDNotIn...)) + } + if i.IDGT != nil { + predicates = append(predicates, testtarget.IDGT(*i.IDGT)) + } + if i.IDGTE != nil { + predicates = append(predicates, testtarget.IDGTE(*i.IDGTE)) + } + if i.IDLT != nil { + predicates = append(predicates, testtarget.IDLT(*i.IDLT)) + } + if i.IDLTE != nil { + predicates = append(predicates, testtarget.IDLTE(*i.IDLTE)) + } + if i.TargetID != nil { + predicates = append(predicates, testtarget.TargetIDEQ(*i.TargetID)) + } + if i.TargetIDNEQ != nil { + predicates = append(predicates, testtarget.TargetIDNEQ(*i.TargetIDNEQ)) + } + if len(i.TargetIDIn) > 0 { + predicates = append(predicates, testtarget.TargetIDIn(i.TargetIDIn...)) + } + if len(i.TargetIDNotIn) > 0 { + predicates = append(predicates, testtarget.TargetIDNotIn(i.TargetIDNotIn...)) + } + + if i.HasTarget != nil { + p := testtarget.HasTarget() + if !*i.HasTarget { + p = testtarget.Not(p) + } + predicates = append(predicates, p) + } + if len(i.HasTargetWith) > 0 { + with := make([]predicate.Target, 0, len(i.HasTargetWith)) + for _, w := range i.HasTargetWith { + p, err := w.P() + if err != nil { + return nil, fmt.Errorf("%w: field 'HasTargetWith'", err) + } + with = append(with, p) + } + predicates = append(predicates, testtarget.HasTargetWith(with...)) + } + switch len(predicates) { + case 0: + return nil, ErrEmptyTestTargetWhereInput + case 1: + return predicates[0], nil + default: + return testtarget.And(predicates...), nil + } +} + // TimingMetricsWhereInput represents a where input for filtering TimingMetrics queries. type TimingMetricsWhereInput struct { Predicates []predicate.TimingMetrics `json:"-"` diff --git a/ent/gen/ent/hook/hook.go b/ent/gen/ent/hook/hook.go index d54ce0f8..04686864 100644 --- a/ent/gen/ent/hook/hook.go +++ b/ent/gen/ent/hook/hook.go @@ -369,6 +369,18 @@ func (f TestSummaryFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.TestSummaryMutation", m) } +// The TestTargetFunc type is an adapter to allow the use of ordinary +// function as TestTarget mutator. +type TestTargetFunc func(context.Context, *ent.TestTargetMutation) (ent.Value, error) + +// Mutate calls f(ctx, m). +func (f TestTargetFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if mv, ok := m.(*ent.TestTargetMutation); ok { + return f(ctx, mv) + } + return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.TestTargetMutation", m) +} + // The TimingMetricsFunc type is an adapter to allow the use of ordinary // function as TimingMetrics mutator. type TimingMetricsFunc func(context.Context, *ent.TimingMetricsMutation) (ent.Value, error) diff --git a/ent/gen/ent/migrate/schema.go b/ent/gen/ent/migrate/schema.go index bdf68f15..df35b597 100644 --- a/ent/gen/ent/migrate/schema.go +++ b/ent/gen/ent/migrate/schema.go @@ -1097,6 +1097,25 @@ var ( }, }, } + // TestTargetsColumns holds the columns for the "test_targets" table. + TestTargetsColumns = []*schema.Column{ + {Name: "id", Type: field.TypeInt64, Increment: true}, + {Name: "target_id", Type: field.TypeInt64, Unique: true}, + } + // TestTargetsTable holds the schema information for the "test_targets" table. + TestTargetsTable = &schema.Table{ + Name: "test_targets", + Columns: TestTargetsColumns, + PrimaryKey: []*schema.Column{TestTargetsColumns[0]}, + ForeignKeys: []*schema.ForeignKey{ + { + Symbol: "test_targets_targets_test_target", + Columns: []*schema.Column{TestTargetsColumns[1]}, + RefColumns: []*schema.Column{TargetsColumns[0]}, + OnDelete: schema.NoAction, + }, + }, + } // TimingMetricsColumns holds the columns for the "timing_metrics" table. TimingMetricsColumns = []*schema.Column{ {Name: "id", Type: field.TypeInt64, Increment: true}, @@ -1160,6 +1179,7 @@ var ( TargetMetricsTable, TestResultsTable, TestSummariesTable, + TestTargetsTable, TimingMetricsTable, } ) @@ -1199,5 +1219,6 @@ func init() { TargetMetricsTable.ForeignKeys[0].RefTable = MetricsTable TestResultsTable.ForeignKeys[0].RefTable = TestSummariesTable TestSummariesTable.ForeignKeys[0].RefTable = InvocationTargetsTable + TestTargetsTable.ForeignKeys[0].RefTable = TargetsTable TimingMetricsTable.ForeignKeys[0].RefTable = MetricsTable } diff --git a/ent/gen/ent/mutation.go b/ent/gen/ent/mutation.go index 9cf20645..a3f1b4dc 100644 --- a/ent/gen/ent/mutation.go +++ b/ent/gen/ent/mutation.go @@ -42,6 +42,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/targetmetrics" "github.com/buildbarn/bb-portal/ent/gen/ent/testresult" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/timingmetrics" "github.com/buildbarn/bb-portal/pkg/invocation" "github.com/google/uuid" @@ -86,6 +87,7 @@ const ( TypeTargetMetrics = "TargetMetrics" TypeTestResult = "TestResult" TypeTestSummary = "TestSummary" + TypeTestTarget = "TestTarget" TypeTimingMetrics = "TimingMetrics" ) @@ -23517,6 +23519,8 @@ type TargetMutation struct { target_kind_mappings map[int64]struct{} removedtarget_kind_mappings map[int64]struct{} clearedtarget_kind_mappings bool + test_target *int64 + clearedtest_target bool done bool oldValue func(context.Context) (*Target, error) predicates []predicate.Target @@ -23881,6 +23885,45 @@ func (m *TargetMutation) ResetTargetKindMappings() { m.removedtarget_kind_mappings = nil } +// SetTestTargetID sets the "test_target" edge to the TestTarget entity by id. +func (m *TargetMutation) SetTestTargetID(id int64) { + m.test_target = &id +} + +// ClearTestTarget clears the "test_target" edge to the TestTarget entity. +func (m *TargetMutation) ClearTestTarget() { + m.clearedtest_target = true +} + +// TestTargetCleared reports if the "test_target" edge to the TestTarget entity was cleared. +func (m *TargetMutation) TestTargetCleared() bool { + return m.clearedtest_target +} + +// TestTargetID returns the "test_target" edge ID in the mutation. +func (m *TargetMutation) TestTargetID() (id int64, exists bool) { + if m.test_target != nil { + return *m.test_target, true + } + return +} + +// TestTargetIDs returns the "test_target" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// TestTargetID instead. It exists only for internal usage by the builders. +func (m *TargetMutation) TestTargetIDs() (ids []int64) { + if id := m.test_target; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetTestTarget resets all changes to the "test_target" edge. +func (m *TargetMutation) ResetTestTarget() { + m.test_target = nil + m.clearedtest_target = false +} + // Where appends a list predicates to the TargetMutation builder. func (m *TargetMutation) Where(ps ...predicate.Target) { m.predicates = append(m.predicates, ps...) @@ -24048,7 +24091,7 @@ func (m *TargetMutation) ResetField(name string) error { // AddedEdges returns all edge names that were set/added in this mutation. func (m *TargetMutation) AddedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.instance_name != nil { edges = append(edges, target.EdgeInstanceName) } @@ -24058,6 +24101,9 @@ func (m *TargetMutation) AddedEdges() []string { if m.target_kind_mappings != nil { edges = append(edges, target.EdgeTargetKindMappings) } + if m.test_target != nil { + edges = append(edges, target.EdgeTestTarget) + } return edges } @@ -24081,13 +24127,17 @@ func (m *TargetMutation) AddedIDs(name string) []ent.Value { ids = append(ids, id) } return ids + case target.EdgeTestTarget: + if id := m.test_target; id != nil { + return []ent.Value{*id} + } } return nil } // RemovedEdges returns all edge names that were removed in this mutation. func (m *TargetMutation) RemovedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.removedinvocation_targets != nil { edges = append(edges, target.EdgeInvocationTargets) } @@ -24119,7 +24169,7 @@ func (m *TargetMutation) RemovedIDs(name string) []ent.Value { // ClearedEdges returns all edge names that were cleared in this mutation. func (m *TargetMutation) ClearedEdges() []string { - edges := make([]string, 0, 3) + edges := make([]string, 0, 4) if m.clearedinstance_name { edges = append(edges, target.EdgeInstanceName) } @@ -24129,6 +24179,9 @@ func (m *TargetMutation) ClearedEdges() []string { if m.clearedtarget_kind_mappings { edges = append(edges, target.EdgeTargetKindMappings) } + if m.clearedtest_target { + edges = append(edges, target.EdgeTestTarget) + } return edges } @@ -24142,6 +24195,8 @@ func (m *TargetMutation) EdgeCleared(name string) bool { return m.clearedinvocation_targets case target.EdgeTargetKindMappings: return m.clearedtarget_kind_mappings + case target.EdgeTestTarget: + return m.clearedtest_target } return false } @@ -24153,6 +24208,9 @@ func (m *TargetMutation) ClearEdge(name string) error { case target.EdgeInstanceName: m.ClearInstanceName() return nil + case target.EdgeTestTarget: + m.ClearTestTarget() + return nil } return fmt.Errorf("unknown Target unique edge %s", name) } @@ -24170,6 +24228,9 @@ func (m *TargetMutation) ResetEdge(name string) error { case target.EdgeTargetKindMappings: m.ResetTargetKindMappings() return nil + case target.EdgeTestTarget: + m.ResetTestTarget() + return nil } return fmt.Errorf("unknown Target edge %s", name) } @@ -28242,6 +28303,395 @@ func (m *TestSummaryMutation) ResetEdge(name string) error { return fmt.Errorf("unknown TestSummary edge %s", name) } +// TestTargetMutation represents an operation that mutates the TestTarget nodes in the graph. +type TestTargetMutation struct { + config + op Op + typ string + id *int64 + clearedFields map[string]struct{} + target *int64 + clearedtarget bool + done bool + oldValue func(context.Context) (*TestTarget, error) + predicates []predicate.TestTarget +} + +var _ ent.Mutation = (*TestTargetMutation)(nil) + +// testtargetOption allows management of the mutation configuration using functional options. +type testtargetOption func(*TestTargetMutation) + +// newTestTargetMutation creates new mutation for the TestTarget entity. +func newTestTargetMutation(c config, op Op, opts ...testtargetOption) *TestTargetMutation { + m := &TestTargetMutation{ + config: c, + op: op, + typ: TypeTestTarget, + clearedFields: make(map[string]struct{}), + } + for _, opt := range opts { + opt(m) + } + return m +} + +// withTestTargetID sets the ID field of the mutation. +func withTestTargetID(id int64) testtargetOption { + return func(m *TestTargetMutation) { + var ( + err error + once sync.Once + value *TestTarget + ) + m.oldValue = func(ctx context.Context) (*TestTarget, error) { + once.Do(func() { + if m.done { + err = errors.New("querying old values post mutation is not allowed") + } else { + value, err = m.Client().TestTarget.Get(ctx, id) + } + }) + return value, err + } + m.id = &id + } +} + +// withTestTarget sets the old TestTarget of the mutation. +func withTestTarget(node *TestTarget) testtargetOption { + return func(m *TestTargetMutation) { + m.oldValue = func(context.Context) (*TestTarget, error) { + return node, nil + } + m.id = &node.ID + } +} + +// Client returns a new `ent.Client` from the mutation. If the mutation was +// executed in a transaction (ent.Tx), a transactional client is returned. +func (m TestTargetMutation) Client() *Client { + client := &Client{config: m.config} + client.init() + return client +} + +// Tx returns an `ent.Tx` for mutations that were executed in transactions; +// it returns an error otherwise. +func (m TestTargetMutation) Tx() (*Tx, error) { + if _, ok := m.driver.(*txDriver); !ok { + return nil, errors.New("ent: mutation is not running in a transaction") + } + tx := &Tx{config: m.config} + tx.init() + return tx, nil +} + +// SetID sets the value of the id field. Note that this +// operation is only accepted on creation of TestTarget entities. +func (m *TestTargetMutation) SetID(id int64) { + m.id = &id +} + +// ID returns the ID value in the mutation. Note that the ID is only available +// if it was provided to the builder or after it was returned from the database. +func (m *TestTargetMutation) ID() (id int64, exists bool) { + if m.id == nil { + return + } + return *m.id, true +} + +// IDs queries the database and returns the entity ids that match the mutation's predicate. +// That means, if the mutation is applied within a transaction with an isolation level such +// as sql.LevelSerializable, the returned ids match the ids of the rows that will be updated +// or updated by the mutation. +func (m *TestTargetMutation) IDs(ctx context.Context) ([]int64, error) { + switch { + case m.op.Is(OpUpdateOne | OpDeleteOne): + id, exists := m.ID() + if exists { + return []int64{id}, nil + } + fallthrough + case m.op.Is(OpUpdate | OpDelete): + return m.Client().TestTarget.Query().Where(m.predicates...).IDs(ctx) + default: + return nil, fmt.Errorf("IDs is not allowed on %s operations", m.op) + } +} + +// SetTargetID sets the "target_id" field. +func (m *TestTargetMutation) SetTargetID(i int64) { + m.target = &i +} + +// TargetID returns the value of the "target_id" field in the mutation. +func (m *TestTargetMutation) TargetID() (r int64, exists bool) { + v := m.target + if v == nil { + return + } + return *v, true +} + +// OldTargetID returns the old "target_id" field's value of the TestTarget entity. +// If the TestTarget 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 *TestTargetMutation) OldTargetID(ctx context.Context) (v int64, err error) { + if !m.op.Is(OpUpdateOne) { + return v, errors.New("OldTargetID is only allowed on UpdateOne operations") + } + if m.id == nil || m.oldValue == nil { + return v, errors.New("OldTargetID requires an ID field in the mutation") + } + oldValue, err := m.oldValue(ctx) + if err != nil { + return v, fmt.Errorf("querying old value for OldTargetID: %w", err) + } + return oldValue.TargetID, nil +} + +// ResetTargetID resets all changes to the "target_id" field. +func (m *TestTargetMutation) ResetTargetID() { + m.target = nil +} + +// ClearTarget clears the "target" edge to the Target entity. +func (m *TestTargetMutation) ClearTarget() { + m.clearedtarget = true + m.clearedFields[testtarget.FieldTargetID] = struct{}{} +} + +// TargetCleared reports if the "target" edge to the Target entity was cleared. +func (m *TestTargetMutation) TargetCleared() bool { + return m.clearedtarget +} + +// TargetIDs returns the "target" edge IDs in the mutation. +// Note that IDs always returns len(IDs) <= 1 for unique edges, and you should use +// TargetID instead. It exists only for internal usage by the builders. +func (m *TestTargetMutation) TargetIDs() (ids []int64) { + if id := m.target; id != nil { + ids = append(ids, *id) + } + return +} + +// ResetTarget resets all changes to the "target" edge. +func (m *TestTargetMutation) ResetTarget() { + m.target = nil + m.clearedtarget = false +} + +// Where appends a list predicates to the TestTargetMutation builder. +func (m *TestTargetMutation) Where(ps ...predicate.TestTarget) { + m.predicates = append(m.predicates, ps...) +} + +// WhereP appends storage-level predicates to the TestTargetMutation builder. Using this method, +// users can use type-assertion to append predicates that do not depend on any generated package. +func (m *TestTargetMutation) WhereP(ps ...func(*sql.Selector)) { + p := make([]predicate.TestTarget, len(ps)) + for i := range ps { + p[i] = ps[i] + } + m.Where(p...) +} + +// Op returns the operation name. +func (m *TestTargetMutation) Op() Op { + return m.op +} + +// SetOp allows setting the mutation operation. +func (m *TestTargetMutation) SetOp(op Op) { + m.op = op +} + +// Type returns the node type of this mutation (TestTarget). +func (m *TestTargetMutation) Type() string { + return m.typ +} + +// Fields returns all fields that were changed during this mutation. Note that in +// order to get all numeric fields that were incremented/decremented, call +// AddedFields(). +func (m *TestTargetMutation) Fields() []string { + fields := make([]string, 0, 1) + if m.target != nil { + fields = append(fields, testtarget.FieldTargetID) + } + return fields +} + +// Field returns the value of a field with the given name. The second boolean +// return value indicates that this field was not set, or was not defined in the +// schema. +func (m *TestTargetMutation) Field(name string) (ent.Value, bool) { + switch name { + case testtarget.FieldTargetID: + return m.TargetID() + } + return nil, false +} + +// OldField returns the old value of the field from the database. An error is +// returned if the mutation operation is not UpdateOne, or the query to the +// database failed. +func (m *TestTargetMutation) OldField(ctx context.Context, name string) (ent.Value, error) { + switch name { + case testtarget.FieldTargetID: + return m.OldTargetID(ctx) + } + return nil, fmt.Errorf("unknown TestTarget field %s", name) +} + +// SetField sets the value of a field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *TestTargetMutation) SetField(name string, value ent.Value) error { + switch name { + case testtarget.FieldTargetID: + v, ok := value.(int64) + if !ok { + return fmt.Errorf("unexpected type %T for field %s", value, name) + } + m.SetTargetID(v) + return nil + } + return fmt.Errorf("unknown TestTarget field %s", name) +} + +// AddedFields returns all numeric fields that were incremented/decremented during +// this mutation. +func (m *TestTargetMutation) AddedFields() []string { + var fields []string + return fields +} + +// AddedField returns the numeric value that was incremented/decremented on a field +// with the given name. The second boolean return value indicates that this field +// was not set, or was not defined in the schema. +func (m *TestTargetMutation) AddedField(name string) (ent.Value, bool) { + switch name { + } + return nil, false +} + +// AddField adds the value to the field with the given name. It returns an error if +// the field is not defined in the schema, or if the type mismatched the field +// type. +func (m *TestTargetMutation) AddField(name string, value ent.Value) error { + switch name { + } + return fmt.Errorf("unknown TestTarget numeric field %s", name) +} + +// ClearedFields returns all nullable fields that were cleared during this +// mutation. +func (m *TestTargetMutation) ClearedFields() []string { + return nil +} + +// FieldCleared returns a boolean indicating if a field with the given name was +// cleared in this mutation. +func (m *TestTargetMutation) FieldCleared(name string) bool { + _, ok := m.clearedFields[name] + return ok +} + +// ClearField clears the value of the field with the given name. It returns an +// error if the field is not defined in the schema. +func (m *TestTargetMutation) ClearField(name string) error { + return fmt.Errorf("unknown TestTarget nullable field %s", name) +} + +// ResetField resets all changes in the mutation for the field with the given name. +// It returns an error if the field is not defined in the schema. +func (m *TestTargetMutation) ResetField(name string) error { + switch name { + case testtarget.FieldTargetID: + m.ResetTargetID() + return nil + } + return fmt.Errorf("unknown TestTarget field %s", name) +} + +// AddedEdges returns all edge names that were set/added in this mutation. +func (m *TestTargetMutation) AddedEdges() []string { + edges := make([]string, 0, 1) + if m.target != nil { + edges = append(edges, testtarget.EdgeTarget) + } + return edges +} + +// AddedIDs returns all IDs (to other nodes) that were added for the given edge +// name in this mutation. +func (m *TestTargetMutation) AddedIDs(name string) []ent.Value { + switch name { + case testtarget.EdgeTarget: + if id := m.target; id != nil { + return []ent.Value{*id} + } + } + return nil +} + +// RemovedEdges returns all edge names that were removed in this mutation. +func (m *TestTargetMutation) RemovedEdges() []string { + edges := make([]string, 0, 1) + return edges +} + +// RemovedIDs returns all IDs (to other nodes) that were removed for the edge with +// the given name in this mutation. +func (m *TestTargetMutation) RemovedIDs(name string) []ent.Value { + return nil +} + +// ClearedEdges returns all edge names that were cleared in this mutation. +func (m *TestTargetMutation) ClearedEdges() []string { + edges := make([]string, 0, 1) + if m.clearedtarget { + edges = append(edges, testtarget.EdgeTarget) + } + return edges +} + +// EdgeCleared returns a boolean which indicates if the edge with the given name +// was cleared in this mutation. +func (m *TestTargetMutation) EdgeCleared(name string) bool { + switch name { + case testtarget.EdgeTarget: + return m.clearedtarget + } + return false +} + +// ClearEdge clears the value of the edge with the given name. It returns an error +// if that edge is not defined in the schema. +func (m *TestTargetMutation) ClearEdge(name string) error { + switch name { + case testtarget.EdgeTarget: + m.ClearTarget() + return nil + } + return fmt.Errorf("unknown TestTarget unique edge %s", name) +} + +// ResetEdge resets all changes to the edge with the given name in this mutation. +// It returns an error if the edge is not defined in the schema. +func (m *TestTargetMutation) ResetEdge(name string) error { + switch name { + case testtarget.EdgeTarget: + m.ResetTarget() + return nil + } + return fmt.Errorf("unknown TestTarget edge %s", name) +} + // TimingMetricsMutation represents an operation that mutates the TimingMetrics nodes in the graph. type TimingMetricsMutation struct { config diff --git a/ent/gen/ent/predicate/predicate.go b/ent/gen/ent/predicate/predicate.go index 743e4cc0..74b63896 100644 --- a/ent/gen/ent/predicate/predicate.go +++ b/ent/gen/ent/predicate/predicate.go @@ -96,5 +96,8 @@ type TestResult func(*sql.Selector) // TestSummary is the predicate function for testsummary builders. type TestSummary func(*sql.Selector) +// TestTarget is the predicate function for testtarget builders. +type TestTarget func(*sql.Selector) + // TimingMetrics is the predicate function for timingmetrics builders. type TimingMetrics func(*sql.Selector) diff --git a/ent/gen/ent/privacy/privacy.go b/ent/gen/ent/privacy/privacy.go index 7349dd42..bb885eba 100644 --- a/ent/gen/ent/privacy/privacy.go +++ b/ent/gen/ent/privacy/privacy.go @@ -831,6 +831,30 @@ func (f TestSummaryMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mut return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.TestSummaryMutation", m) } +// The TestTargetQueryRuleFunc type is an adapter to allow the use of ordinary +// functions as a query rule. +type TestTargetQueryRuleFunc func(context.Context, *ent.TestTargetQuery) error + +// EvalQuery return f(ctx, q). +func (f TestTargetQueryRuleFunc) EvalQuery(ctx context.Context, q ent.Query) error { + if q, ok := q.(*ent.TestTargetQuery); ok { + return f(ctx, q) + } + return Denyf("ent/privacy: unexpected query type %T, expect *ent.TestTargetQuery", q) +} + +// The TestTargetMutationRuleFunc type is an adapter to allow the use of ordinary +// functions as a mutation rule. +type TestTargetMutationRuleFunc func(context.Context, *ent.TestTargetMutation) error + +// EvalMutation calls f(ctx, m). +func (f TestTargetMutationRuleFunc) EvalMutation(ctx context.Context, m ent.Mutation) error { + if m, ok := m.(*ent.TestTargetMutation); ok { + return f(ctx, m) + } + return Denyf("ent/privacy: unexpected mutation type %T, expect *ent.TestTargetMutation", m) +} + // The TimingMetricsQueryRuleFunc type is an adapter to allow the use of ordinary // functions as a query rule. type TimingMetricsQueryRuleFunc func(context.Context, *ent.TimingMetricsQuery) error @@ -950,6 +974,8 @@ func queryFilter(q ent.Query) (Filter, error) { return q.Filter(), nil case *ent.TestSummaryQuery: return q.Filter(), nil + case *ent.TestTargetQuery: + return q.Filter(), nil case *ent.TimingMetricsQuery: return q.Filter(), nil default: @@ -1019,6 +1045,8 @@ func mutationFilter(m ent.Mutation) (Filter, error) { return m.Filter(), nil case *ent.TestSummaryMutation: return m.Filter(), nil + case *ent.TestTargetMutation: + return m.Filter(), nil case *ent.TimingMetricsMutation: return m.Filter(), nil default: diff --git a/ent/gen/ent/runtime/BUILD.bazel b/ent/gen/ent/runtime/BUILD.bazel index 4c856313..d600b91c 100644 --- a/ent/gen/ent/runtime/BUILD.bazel +++ b/ent/gen/ent/runtime/BUILD.bazel @@ -13,6 +13,7 @@ go_library( "//ent/gen/ent/invocationtarget", "//ent/gen/ent/target", "//ent/gen/ent/testsummary", + "//ent/gen/ent/testtarget", "@io_entgo_ent//:ent", "@io_entgo_ent//privacy", ], diff --git a/ent/gen/ent/runtime/runtime.go b/ent/gen/ent/runtime/runtime.go index 7997c2c1..49c99de8 100644 --- a/ent/gen/ent/runtime/runtime.go +++ b/ent/gen/ent/runtime/runtime.go @@ -12,6 +12,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/invocationtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/target" "github.com/buildbarn/bb-portal/ent/gen/ent/testsummary" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" "entgo.io/ent" "entgo.io/ent/privacy" @@ -94,6 +95,15 @@ func init() { return next.Mutate(ctx, m) }) } + testtarget.Policy = privacy.NewPolicies(authschema.TestTarget{}) + testtarget.Hooks[0] = func(next ent.Mutator) ent.Mutator { + return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) { + if err := testtarget.Policy.EvalMutation(ctx, m); err != nil { + return nil, err + } + return next.Mutate(ctx, m) + }) + } } const ( diff --git a/ent/gen/ent/schema-viz.html b/ent/gen/ent/schema-viz.html index f1154ba6..06eb303b 100644 --- a/ent/gen/ent/schema-viz.html +++ b/ent/gen/ent/schema-viz.html @@ -70,7 +70,7 @@ } - const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"Action\",\"fields\":[{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"},{\"name\":\"configuration_id\",\"type\":\"int64\"},{\"name\":\"label\",\"type\":\"string\"},{\"name\":\"type\",\"type\":\"string\"},{\"name\":\"success\",\"type\":\"bool\"},{\"name\":\"exit_code\",\"type\":\"int32\"},{\"name\":\"command_line\",\"type\":\"[]string\"},{\"name\":\"start_time\",\"type\":\"time.Time\"},{\"name\":\"end_time\",\"type\":\"time.Time\"},{\"name\":\"failure_code\",\"type\":\"string\"},{\"name\":\"failure_message\",\"type\":\"string\"},{\"name\":\"stdout_hash\",\"type\":\"string\"},{\"name\":\"stdout_size_bytes\",\"type\":\"int64\"},{\"name\":\"stdout_hash_function\",\"type\":\"string\"},{\"name\":\"stderr_hash\",\"type\":\"string\"},{\"name\":\"stderr_size_bytes\",\"type\":\"int64\"},{\"name\":\"stderr_hash_function\",\"type\":\"string\"}]},{\"id\":\"ActionCacheStatistics\",\"fields\":[{\"name\":\"size_in_bytes\",\"type\":\"uint64\"},{\"name\":\"save_time_in_ms\",\"type\":\"uint64\"},{\"name\":\"load_time_in_ms\",\"type\":\"int64\"},{\"name\":\"hits\",\"type\":\"int32\"},{\"name\":\"misses\",\"type\":\"int32\"}]},{\"id\":\"ActionData\",\"fields\":[{\"name\":\"mnemonic\",\"type\":\"string\"},{\"name\":\"actions_executed\",\"type\":\"int64\"},{\"name\":\"actions_created\",\"type\":\"int64\"},{\"name\":\"first_started_ms\",\"type\":\"int64\"},{\"name\":\"last_ended_ms\",\"type\":\"int64\"},{\"name\":\"system_time\",\"type\":\"int64\"},{\"name\":\"user_time\",\"type\":\"int64\"}]},{\"id\":\"ActionSummary\",\"fields\":[{\"name\":\"actions_created\",\"type\":\"int64\"},{\"name\":\"actions_created_not_including_aspects\",\"type\":\"int64\"},{\"name\":\"actions_executed\",\"type\":\"int64\"},{\"name\":\"remote_cache_hits\",\"type\":\"int64\"}]},{\"id\":\"ArtifactMetrics\",\"fields\":[{\"name\":\"source_artifacts_read_size_in_bytes\",\"type\":\"int64\"},{\"name\":\"source_artifacts_read_count\",\"type\":\"int32\"},{\"name\":\"output_artifacts_seen_size_in_bytes\",\"type\":\"int64\"},{\"name\":\"output_artifacts_seen_count\",\"type\":\"int32\"},{\"name\":\"output_artifacts_from_action_cache_size_in_bytes\",\"type\":\"int64\"},{\"name\":\"output_artifacts_from_action_cache_count\",\"type\":\"int32\"},{\"name\":\"top_level_artifacts_size_in_bytes\",\"type\":\"int64\"},{\"name\":\"top_level_artifacts_count\",\"type\":\"int32\"}]},{\"id\":\"AuthenticatedUser\",\"fields\":[{\"name\":\"user_uuid\",\"type\":\"uuid.UUID\"},{\"name\":\"external_id\",\"type\":\"string\"},{\"name\":\"display_name\",\"type\":\"string\"},{\"name\":\"user_info\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"BazelInvocation\",\"fields\":[{\"name\":\"invocation_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_timestamp\",\"type\":\"time.Time\"},{\"name\":\"started_at\",\"type\":\"time.Time\"},{\"name\":\"ended_at\",\"type\":\"time.Time\"},{\"name\":\"change_number\",\"type\":\"int\"},{\"name\":\"patchset_number\",\"type\":\"int\"},{\"name\":\"bep_completed\",\"type\":\"bool\"},{\"name\":\"step_label\",\"type\":\"string\"},{\"name\":\"user_email\",\"type\":\"string\"},{\"name\":\"user_ldap\",\"type\":\"string\"},{\"name\":\"hostname\",\"type\":\"string\"},{\"name\":\"is_ci_worker\",\"type\":\"bool\"},{\"name\":\"num_fetches\",\"type\":\"int64\"},{\"name\":\"profile_name\",\"type\":\"string\"},{\"name\":\"bazel_version\",\"type\":\"string\"},{\"name\":\"exit_code_name\",\"type\":\"string\"},{\"name\":\"exit_code_code\",\"type\":\"int32\"},{\"name\":\"canonical_command_line\",\"type\":\"*invocation.CommandLineData\"},{\"name\":\"original_command_line\",\"type\":\"*invocation.CommandLineData\"},{\"name\":\"options_parsed\",\"type\":\"*invocation.ParsedCommandLineOptions\"},{\"name\":\"processed_event_started\",\"type\":\"bool\"},{\"name\":\"processed_event_build_metadata\",\"type\":\"bool\"},{\"name\":\"processed_event_build_finished\",\"type\":\"bool\"},{\"name\":\"processed_event_workspace_status\",\"type\":\"bool\"}]},{\"id\":\"Build\",\"fields\":[{\"name\":\"build_url\",\"type\":\"string\"},{\"name\":\"build_uuid\",\"type\":\"uuid.UUID\"},{\"name\":\"timestamp\",\"type\":\"time.Time\"}]},{\"id\":\"BuildGraphMetrics\",\"fields\":[{\"name\":\"action_lookup_value_count\",\"type\":\"int32\"},{\"name\":\"action_lookup_value_count_not_including_aspects\",\"type\":\"int32\"},{\"name\":\"action_count\",\"type\":\"int32\"},{\"name\":\"action_count_not_including_aspects\",\"type\":\"int32\"},{\"name\":\"input_file_configured_target_count\",\"type\":\"int32\"},{\"name\":\"output_file_configured_target_count\",\"type\":\"int32\"},{\"name\":\"other_configured_target_count\",\"type\":\"int32\"},{\"name\":\"output_artifact_count\",\"type\":\"int32\"},{\"name\":\"post_invocation_skyframe_node_count\",\"type\":\"int32\"}]},{\"id\":\"BuildLogChunk\",\"fields\":[{\"name\":\"data\",\"type\":\"[]byte\"},{\"name\":\"chunk_index\",\"type\":\"int\"},{\"name\":\"first_line_index\",\"type\":\"int64\"},{\"name\":\"last_line_index\",\"type\":\"int64\"}]},{\"id\":\"Configuration\",\"fields\":[{\"name\":\"configuration_id\",\"type\":\"string\"},{\"name\":\"mnemonic\",\"type\":\"string\"},{\"name\":\"platform_name\",\"type\":\"string\"},{\"name\":\"cpu\",\"type\":\"string\"},{\"name\":\"make_variables\",\"type\":\"map[string]string\"},{\"name\":\"is_tool\",\"type\":\"bool\"},{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"}]},{\"id\":\"ConnectionMetadata\",\"fields\":[{\"name\":\"connection_last_open_at\",\"type\":\"time.Time\"}]},{\"id\":\"EventMetadata\",\"fields\":[{\"name\":\"handled\",\"type\":\"[]byte\"},{\"name\":\"event_received_at\",\"type\":\"time.Time\"},{\"name\":\"version\",\"type\":\"int64\"},{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"}]},{\"id\":\"GarbageMetrics\",\"fields\":[{\"name\":\"type\",\"type\":\"string\"},{\"name\":\"garbage_collected\",\"type\":\"int64\"}]},{\"id\":\"IncompleteBuildLog\",\"fields\":[{\"name\":\"snippet_id\",\"type\":\"int32\"},{\"name\":\"log_snippet\",\"type\":\"[]byte\"},{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"}]},{\"id\":\"InstanceName\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"}]},{\"id\":\"InvocationFiles\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"content\",\"type\":\"string\"},{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"size_bytes\",\"type\":\"int64\"},{\"name\":\"digest_function\",\"type\":\"string\"}]},{\"id\":\"InvocationTarget\",\"fields\":[{\"name\":\"success\",\"type\":\"bool\"},{\"name\":\"tags\",\"type\":\"[]string\"},{\"name\":\"start_time_in_ms\",\"type\":\"int64\"},{\"name\":\"end_time_in_ms\",\"type\":\"int64\"},{\"name\":\"duration_in_ms\",\"type\":\"int64\"},{\"name\":\"failure_message\",\"type\":\"string\"},{\"name\":\"abort_reason\",\"type\":\"invocationtarget.AbortReason\"}]},{\"id\":\"MemoryMetrics\",\"fields\":[{\"name\":\"peak_post_gc_heap_size\",\"type\":\"int64\"},{\"name\":\"used_heap_size_post_build\",\"type\":\"int64\"},{\"name\":\"peak_post_gc_tenured_space_heap_size\",\"type\":\"int64\"}]},{\"id\":\"Metrics\",\"fields\":null},{\"id\":\"MissDetail\",\"fields\":[{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"count\",\"type\":\"int32\"}]},{\"id\":\"NetworkMetrics\",\"fields\":null},{\"id\":\"RunnerCount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"exec_kind\",\"type\":\"string\"},{\"name\":\"actions_executed\",\"type\":\"int64\"}]},{\"id\":\"SourceControl\",\"fields\":[{\"name\":\"provider\",\"type\":\"sourcecontrol.Provider\"},{\"name\":\"instance_url\",\"type\":\"string\"},{\"name\":\"repo\",\"type\":\"string\"},{\"name\":\"refs\",\"type\":\"string\"},{\"name\":\"commit_sha\",\"type\":\"string\"},{\"name\":\"actor\",\"type\":\"string\"},{\"name\":\"event_name\",\"type\":\"string\"},{\"name\":\"workflow\",\"type\":\"string\"},{\"name\":\"run_id\",\"type\":\"string\"},{\"name\":\"run_number\",\"type\":\"string\"},{\"name\":\"job\",\"type\":\"string\"},{\"name\":\"action\",\"type\":\"string\"},{\"name\":\"runner_name\",\"type\":\"string\"},{\"name\":\"runner_arch\",\"type\":\"string\"},{\"name\":\"runner_os\",\"type\":\"string\"},{\"name\":\"workspace\",\"type\":\"string\"}]},{\"id\":\"SystemNetworkStats\",\"fields\":[{\"name\":\"bytes_sent\",\"type\":\"uint64\"},{\"name\":\"bytes_recv\",\"type\":\"uint64\"},{\"name\":\"packets_sent\",\"type\":\"uint64\"},{\"name\":\"packets_recv\",\"type\":\"uint64\"},{\"name\":\"peak_bytes_sent_per_sec\",\"type\":\"uint64\"},{\"name\":\"peak_bytes_recv_per_sec\",\"type\":\"uint64\"},{\"name\":\"peak_packets_sent_per_sec\",\"type\":\"uint64\"},{\"name\":\"peak_packets_recv_per_sec\",\"type\":\"uint64\"}]},{\"id\":\"Target\",\"fields\":[{\"name\":\"label\",\"type\":\"string\"},{\"name\":\"aspect\",\"type\":\"string\"},{\"name\":\"target_kind\",\"type\":\"string\"}]},{\"id\":\"TargetKindMapping\",\"fields\":[{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"},{\"name\":\"target_id\",\"type\":\"int64\"},{\"name\":\"start_time_in_ms\",\"type\":\"int64\"}]},{\"id\":\"TargetMetrics\",\"fields\":[{\"name\":\"targets_loaded\",\"type\":\"int64\"},{\"name\":\"targets_configured\",\"type\":\"int64\"},{\"name\":\"targets_configured_not_including_aspects\",\"type\":\"int64\"}]},{\"id\":\"TestResult\",\"fields\":[{\"name\":\"run\",\"type\":\"int32\"},{\"name\":\"shard\",\"type\":\"int32\"},{\"name\":\"attempt\",\"type\":\"int32\"},{\"name\":\"status\",\"type\":\"string\"},{\"name\":\"status_details\",\"type\":\"string\"},{\"name\":\"cached_locally\",\"type\":\"bool\"},{\"name\":\"test_attempt_start\",\"type\":\"time.Time\"},{\"name\":\"test_attempt_duration_in_ms\",\"type\":\"int64\"},{\"name\":\"warning\",\"type\":\"[]string\"},{\"name\":\"strategy\",\"type\":\"string\"},{\"name\":\"cached_remotely\",\"type\":\"bool\"},{\"name\":\"exit_code\",\"type\":\"int32\"},{\"name\":\"hostname\",\"type\":\"string\"},{\"name\":\"timing_breakdown\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"TestSummary\",\"fields\":[{\"name\":\"overall_status\",\"type\":\"string\"},{\"name\":\"total_run_count\",\"type\":\"int32\"},{\"name\":\"run_count\",\"type\":\"int32\"},{\"name\":\"attempt_count\",\"type\":\"int32\"},{\"name\":\"shard_count\",\"type\":\"int32\"},{\"name\":\"total_num_cached\",\"type\":\"int32\"},{\"name\":\"first_start_time\",\"type\":\"time.Time\"},{\"name\":\"last_stop_time\",\"type\":\"time.Time\"},{\"name\":\"total_run_duration_in_ms\",\"type\":\"int64\"}]},{\"id\":\"TimingMetrics\",\"fields\":[{\"name\":\"cpu_time_in_ms\",\"type\":\"int64\"},{\"name\":\"wall_time_in_ms\",\"type\":\"int64\"},{\"name\":\"analysis_phase_time_in_ms\",\"type\":\"int64\"},{\"name\":\"execution_phase_time_in_ms\",\"type\":\"int64\"},{\"name\":\"actions_execution_start_in_ms\",\"type\":\"int64\"}]}],\"edges\":[{\"from\":\"Action\",\"to\":\"Configuration\",\"label\":\"configuration\"},{\"from\":\"ActionCacheStatistics\",\"to\":\"MissDetail\",\"label\":\"miss_details\"},{\"from\":\"ActionSummary\",\"to\":\"ActionData\",\"label\":\"action_data\"},{\"from\":\"ActionSummary\",\"to\":\"RunnerCount\",\"label\":\"runner_count\"},{\"from\":\"ActionSummary\",\"to\":\"ActionCacheStatistics\",\"label\":\"action_cache_statistics\"},{\"from\":\"AuthenticatedUser\",\"to\":\"BazelInvocation\",\"label\":\"bazel_invocations\"},{\"from\":\"BazelInvocation\",\"to\":\"EventMetadata\",\"label\":\"event_metadata\"},{\"from\":\"BazelInvocation\",\"to\":\"ConnectionMetadata\",\"label\":\"connection_metadata\"},{\"from\":\"BazelInvocation\",\"to\":\"Configuration\",\"label\":\"configurations\"},{\"from\":\"BazelInvocation\",\"to\":\"Action\",\"label\":\"actions\"},{\"from\":\"BazelInvocation\",\"to\":\"Metrics\",\"label\":\"metrics\"},{\"from\":\"BazelInvocation\",\"to\":\"IncompleteBuildLog\",\"label\":\"incomplete_build_logs\"},{\"from\":\"BazelInvocation\",\"to\":\"BuildLogChunk\",\"label\":\"build_log_chunks\"},{\"from\":\"BazelInvocation\",\"to\":\"InvocationFiles\",\"label\":\"invocation_files\"},{\"from\":\"BazelInvocation\",\"to\":\"InvocationTarget\",\"label\":\"invocation_targets\"},{\"from\":\"BazelInvocation\",\"to\":\"TargetKindMapping\",\"label\":\"target_kind_mappings\"},{\"from\":\"BazelInvocation\",\"to\":\"SourceControl\",\"label\":\"source_control\"},{\"from\":\"Build\",\"to\":\"BazelInvocation\",\"label\":\"invocations\"},{\"from\":\"InstanceName\",\"to\":\"BazelInvocation\",\"label\":\"bazel_invocations\"},{\"from\":\"InstanceName\",\"to\":\"Build\",\"label\":\"builds\"},{\"from\":\"InstanceName\",\"to\":\"Target\",\"label\":\"targets\"},{\"from\":\"InvocationTarget\",\"to\":\"Configuration\",\"label\":\"configuration\"},{\"from\":\"InvocationTarget\",\"to\":\"TestSummary\",\"label\":\"test_summary\"},{\"from\":\"MemoryMetrics\",\"to\":\"GarbageMetrics\",\"label\":\"garbage_metrics\"},{\"from\":\"Metrics\",\"to\":\"ActionSummary\",\"label\":\"action_summary\"},{\"from\":\"Metrics\",\"to\":\"MemoryMetrics\",\"label\":\"memory_metrics\"},{\"from\":\"Metrics\",\"to\":\"TargetMetrics\",\"label\":\"target_metrics\"},{\"from\":\"Metrics\",\"to\":\"TimingMetrics\",\"label\":\"timing_metrics\"},{\"from\":\"Metrics\",\"to\":\"ArtifactMetrics\",\"label\":\"artifact_metrics\"},{\"from\":\"Metrics\",\"to\":\"NetworkMetrics\",\"label\":\"network_metrics\"},{\"from\":\"Metrics\",\"to\":\"BuildGraphMetrics\",\"label\":\"build_graph_metrics\"},{\"from\":\"NetworkMetrics\",\"to\":\"SystemNetworkStats\",\"label\":\"system_network_stats\"},{\"from\":\"Target\",\"to\":\"InvocationTarget\",\"label\":\"invocation_targets\"},{\"from\":\"Target\",\"to\":\"TargetKindMapping\",\"label\":\"target_kind_mappings\"},{\"from\":\"TestSummary\",\"to\":\"TestResult\",\"label\":\"test_results\"}]}"); + const entGraph = JSON.parse("{\"nodes\":[{\"id\":\"Action\",\"fields\":[{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"},{\"name\":\"configuration_id\",\"type\":\"int64\"},{\"name\":\"label\",\"type\":\"string\"},{\"name\":\"type\",\"type\":\"string\"},{\"name\":\"success\",\"type\":\"bool\"},{\"name\":\"exit_code\",\"type\":\"int32\"},{\"name\":\"command_line\",\"type\":\"[]string\"},{\"name\":\"start_time\",\"type\":\"time.Time\"},{\"name\":\"end_time\",\"type\":\"time.Time\"},{\"name\":\"failure_code\",\"type\":\"string\"},{\"name\":\"failure_message\",\"type\":\"string\"},{\"name\":\"stdout_hash\",\"type\":\"string\"},{\"name\":\"stdout_size_bytes\",\"type\":\"int64\"},{\"name\":\"stdout_hash_function\",\"type\":\"string\"},{\"name\":\"stderr_hash\",\"type\":\"string\"},{\"name\":\"stderr_size_bytes\",\"type\":\"int64\"},{\"name\":\"stderr_hash_function\",\"type\":\"string\"}]},{\"id\":\"ActionCacheStatistics\",\"fields\":[{\"name\":\"size_in_bytes\",\"type\":\"uint64\"},{\"name\":\"save_time_in_ms\",\"type\":\"uint64\"},{\"name\":\"load_time_in_ms\",\"type\":\"int64\"},{\"name\":\"hits\",\"type\":\"int32\"},{\"name\":\"misses\",\"type\":\"int32\"}]},{\"id\":\"ActionData\",\"fields\":[{\"name\":\"mnemonic\",\"type\":\"string\"},{\"name\":\"actions_executed\",\"type\":\"int64\"},{\"name\":\"actions_created\",\"type\":\"int64\"},{\"name\":\"first_started_ms\",\"type\":\"int64\"},{\"name\":\"last_ended_ms\",\"type\":\"int64\"},{\"name\":\"system_time\",\"type\":\"int64\"},{\"name\":\"user_time\",\"type\":\"int64\"}]},{\"id\":\"ActionSummary\",\"fields\":[{\"name\":\"actions_created\",\"type\":\"int64\"},{\"name\":\"actions_created_not_including_aspects\",\"type\":\"int64\"},{\"name\":\"actions_executed\",\"type\":\"int64\"},{\"name\":\"remote_cache_hits\",\"type\":\"int64\"}]},{\"id\":\"ArtifactMetrics\",\"fields\":[{\"name\":\"source_artifacts_read_size_in_bytes\",\"type\":\"int64\"},{\"name\":\"source_artifacts_read_count\",\"type\":\"int32\"},{\"name\":\"output_artifacts_seen_size_in_bytes\",\"type\":\"int64\"},{\"name\":\"output_artifacts_seen_count\",\"type\":\"int32\"},{\"name\":\"output_artifacts_from_action_cache_size_in_bytes\",\"type\":\"int64\"},{\"name\":\"output_artifacts_from_action_cache_count\",\"type\":\"int32\"},{\"name\":\"top_level_artifacts_size_in_bytes\",\"type\":\"int64\"},{\"name\":\"top_level_artifacts_count\",\"type\":\"int32\"}]},{\"id\":\"AuthenticatedUser\",\"fields\":[{\"name\":\"user_uuid\",\"type\":\"uuid.UUID\"},{\"name\":\"external_id\",\"type\":\"string\"},{\"name\":\"display_name\",\"type\":\"string\"},{\"name\":\"user_info\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"BazelInvocation\",\"fields\":[{\"name\":\"invocation_id\",\"type\":\"uuid.UUID\"},{\"name\":\"created_timestamp\",\"type\":\"time.Time\"},{\"name\":\"started_at\",\"type\":\"time.Time\"},{\"name\":\"ended_at\",\"type\":\"time.Time\"},{\"name\":\"change_number\",\"type\":\"int\"},{\"name\":\"patchset_number\",\"type\":\"int\"},{\"name\":\"bep_completed\",\"type\":\"bool\"},{\"name\":\"step_label\",\"type\":\"string\"},{\"name\":\"user_email\",\"type\":\"string\"},{\"name\":\"user_ldap\",\"type\":\"string\"},{\"name\":\"hostname\",\"type\":\"string\"},{\"name\":\"is_ci_worker\",\"type\":\"bool\"},{\"name\":\"num_fetches\",\"type\":\"int64\"},{\"name\":\"profile_name\",\"type\":\"string\"},{\"name\":\"bazel_version\",\"type\":\"string\"},{\"name\":\"exit_code_name\",\"type\":\"string\"},{\"name\":\"exit_code_code\",\"type\":\"int32\"},{\"name\":\"canonical_command_line\",\"type\":\"*invocation.CommandLineData\"},{\"name\":\"original_command_line\",\"type\":\"*invocation.CommandLineData\"},{\"name\":\"options_parsed\",\"type\":\"*invocation.ParsedCommandLineOptions\"},{\"name\":\"processed_event_started\",\"type\":\"bool\"},{\"name\":\"processed_event_build_metadata\",\"type\":\"bool\"},{\"name\":\"processed_event_build_finished\",\"type\":\"bool\"},{\"name\":\"processed_event_workspace_status\",\"type\":\"bool\"}]},{\"id\":\"Build\",\"fields\":[{\"name\":\"build_url\",\"type\":\"string\"},{\"name\":\"build_uuid\",\"type\":\"uuid.UUID\"},{\"name\":\"timestamp\",\"type\":\"time.Time\"}]},{\"id\":\"BuildGraphMetrics\",\"fields\":[{\"name\":\"action_lookup_value_count\",\"type\":\"int32\"},{\"name\":\"action_lookup_value_count_not_including_aspects\",\"type\":\"int32\"},{\"name\":\"action_count\",\"type\":\"int32\"},{\"name\":\"action_count_not_including_aspects\",\"type\":\"int32\"},{\"name\":\"input_file_configured_target_count\",\"type\":\"int32\"},{\"name\":\"output_file_configured_target_count\",\"type\":\"int32\"},{\"name\":\"other_configured_target_count\",\"type\":\"int32\"},{\"name\":\"output_artifact_count\",\"type\":\"int32\"},{\"name\":\"post_invocation_skyframe_node_count\",\"type\":\"int32\"}]},{\"id\":\"BuildLogChunk\",\"fields\":[{\"name\":\"data\",\"type\":\"[]byte\"},{\"name\":\"chunk_index\",\"type\":\"int\"},{\"name\":\"first_line_index\",\"type\":\"int64\"},{\"name\":\"last_line_index\",\"type\":\"int64\"}]},{\"id\":\"Configuration\",\"fields\":[{\"name\":\"configuration_id\",\"type\":\"string\"},{\"name\":\"mnemonic\",\"type\":\"string\"},{\"name\":\"platform_name\",\"type\":\"string\"},{\"name\":\"cpu\",\"type\":\"string\"},{\"name\":\"make_variables\",\"type\":\"map[string]string\"},{\"name\":\"is_tool\",\"type\":\"bool\"},{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"}]},{\"id\":\"ConnectionMetadata\",\"fields\":[{\"name\":\"connection_last_open_at\",\"type\":\"time.Time\"}]},{\"id\":\"EventMetadata\",\"fields\":[{\"name\":\"handled\",\"type\":\"[]byte\"},{\"name\":\"event_received_at\",\"type\":\"time.Time\"},{\"name\":\"version\",\"type\":\"int64\"},{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"}]},{\"id\":\"GarbageMetrics\",\"fields\":[{\"name\":\"type\",\"type\":\"string\"},{\"name\":\"garbage_collected\",\"type\":\"int64\"}]},{\"id\":\"IncompleteBuildLog\",\"fields\":[{\"name\":\"snippet_id\",\"type\":\"int32\"},{\"name\":\"log_snippet\",\"type\":\"[]byte\"},{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"}]},{\"id\":\"InstanceName\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"}]},{\"id\":\"InvocationFiles\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"content\",\"type\":\"string\"},{\"name\":\"digest\",\"type\":\"string\"},{\"name\":\"size_bytes\",\"type\":\"int64\"},{\"name\":\"digest_function\",\"type\":\"string\"}]},{\"id\":\"InvocationTarget\",\"fields\":[{\"name\":\"success\",\"type\":\"bool\"},{\"name\":\"tags\",\"type\":\"[]string\"},{\"name\":\"start_time_in_ms\",\"type\":\"int64\"},{\"name\":\"end_time_in_ms\",\"type\":\"int64\"},{\"name\":\"duration_in_ms\",\"type\":\"int64\"},{\"name\":\"failure_message\",\"type\":\"string\"},{\"name\":\"abort_reason\",\"type\":\"invocationtarget.AbortReason\"}]},{\"id\":\"MemoryMetrics\",\"fields\":[{\"name\":\"peak_post_gc_heap_size\",\"type\":\"int64\"},{\"name\":\"used_heap_size_post_build\",\"type\":\"int64\"},{\"name\":\"peak_post_gc_tenured_space_heap_size\",\"type\":\"int64\"}]},{\"id\":\"Metrics\",\"fields\":null},{\"id\":\"MissDetail\",\"fields\":[{\"name\":\"reason\",\"type\":\"string\"},{\"name\":\"count\",\"type\":\"int32\"}]},{\"id\":\"NetworkMetrics\",\"fields\":null},{\"id\":\"RunnerCount\",\"fields\":[{\"name\":\"name\",\"type\":\"string\"},{\"name\":\"exec_kind\",\"type\":\"string\"},{\"name\":\"actions_executed\",\"type\":\"int64\"}]},{\"id\":\"SourceControl\",\"fields\":[{\"name\":\"provider\",\"type\":\"sourcecontrol.Provider\"},{\"name\":\"instance_url\",\"type\":\"string\"},{\"name\":\"repo\",\"type\":\"string\"},{\"name\":\"refs\",\"type\":\"string\"},{\"name\":\"commit_sha\",\"type\":\"string\"},{\"name\":\"actor\",\"type\":\"string\"},{\"name\":\"event_name\",\"type\":\"string\"},{\"name\":\"workflow\",\"type\":\"string\"},{\"name\":\"run_id\",\"type\":\"string\"},{\"name\":\"run_number\",\"type\":\"string\"},{\"name\":\"job\",\"type\":\"string\"},{\"name\":\"action\",\"type\":\"string\"},{\"name\":\"runner_name\",\"type\":\"string\"},{\"name\":\"runner_arch\",\"type\":\"string\"},{\"name\":\"runner_os\",\"type\":\"string\"},{\"name\":\"workspace\",\"type\":\"string\"}]},{\"id\":\"SystemNetworkStats\",\"fields\":[{\"name\":\"bytes_sent\",\"type\":\"uint64\"},{\"name\":\"bytes_recv\",\"type\":\"uint64\"},{\"name\":\"packets_sent\",\"type\":\"uint64\"},{\"name\":\"packets_recv\",\"type\":\"uint64\"},{\"name\":\"peak_bytes_sent_per_sec\",\"type\":\"uint64\"},{\"name\":\"peak_bytes_recv_per_sec\",\"type\":\"uint64\"},{\"name\":\"peak_packets_sent_per_sec\",\"type\":\"uint64\"},{\"name\":\"peak_packets_recv_per_sec\",\"type\":\"uint64\"}]},{\"id\":\"Target\",\"fields\":[{\"name\":\"label\",\"type\":\"string\"},{\"name\":\"aspect\",\"type\":\"string\"},{\"name\":\"target_kind\",\"type\":\"string\"}]},{\"id\":\"TargetKindMapping\",\"fields\":[{\"name\":\"bazel_invocation_id\",\"type\":\"int64\"},{\"name\":\"target_id\",\"type\":\"int64\"},{\"name\":\"start_time_in_ms\",\"type\":\"int64\"}]},{\"id\":\"TargetMetrics\",\"fields\":[{\"name\":\"targets_loaded\",\"type\":\"int64\"},{\"name\":\"targets_configured\",\"type\":\"int64\"},{\"name\":\"targets_configured_not_including_aspects\",\"type\":\"int64\"}]},{\"id\":\"TestResult\",\"fields\":[{\"name\":\"run\",\"type\":\"int32\"},{\"name\":\"shard\",\"type\":\"int32\"},{\"name\":\"attempt\",\"type\":\"int32\"},{\"name\":\"status\",\"type\":\"string\"},{\"name\":\"status_details\",\"type\":\"string\"},{\"name\":\"cached_locally\",\"type\":\"bool\"},{\"name\":\"test_attempt_start\",\"type\":\"time.Time\"},{\"name\":\"test_attempt_duration_in_ms\",\"type\":\"int64\"},{\"name\":\"warning\",\"type\":\"[]string\"},{\"name\":\"strategy\",\"type\":\"string\"},{\"name\":\"cached_remotely\",\"type\":\"bool\"},{\"name\":\"exit_code\",\"type\":\"int32\"},{\"name\":\"hostname\",\"type\":\"string\"},{\"name\":\"timing_breakdown\",\"type\":\"map[string]interface {}\"}]},{\"id\":\"TestSummary\",\"fields\":[{\"name\":\"overall_status\",\"type\":\"string\"},{\"name\":\"total_run_count\",\"type\":\"int32\"},{\"name\":\"run_count\",\"type\":\"int32\"},{\"name\":\"attempt_count\",\"type\":\"int32\"},{\"name\":\"shard_count\",\"type\":\"int32\"},{\"name\":\"total_num_cached\",\"type\":\"int32\"},{\"name\":\"first_start_time\",\"type\":\"time.Time\"},{\"name\":\"last_stop_time\",\"type\":\"time.Time\"},{\"name\":\"total_run_duration_in_ms\",\"type\":\"int64\"}]},{\"id\":\"TestTarget\",\"fields\":[{\"name\":\"target_id\",\"type\":\"int64\"}]},{\"id\":\"TimingMetrics\",\"fields\":[{\"name\":\"cpu_time_in_ms\",\"type\":\"int64\"},{\"name\":\"wall_time_in_ms\",\"type\":\"int64\"},{\"name\":\"analysis_phase_time_in_ms\",\"type\":\"int64\"},{\"name\":\"execution_phase_time_in_ms\",\"type\":\"int64\"},{\"name\":\"actions_execution_start_in_ms\",\"type\":\"int64\"}]}],\"edges\":[{\"from\":\"Action\",\"to\":\"Configuration\",\"label\":\"configuration\"},{\"from\":\"ActionCacheStatistics\",\"to\":\"MissDetail\",\"label\":\"miss_details\"},{\"from\":\"ActionSummary\",\"to\":\"ActionData\",\"label\":\"action_data\"},{\"from\":\"ActionSummary\",\"to\":\"RunnerCount\",\"label\":\"runner_count\"},{\"from\":\"ActionSummary\",\"to\":\"ActionCacheStatistics\",\"label\":\"action_cache_statistics\"},{\"from\":\"AuthenticatedUser\",\"to\":\"BazelInvocation\",\"label\":\"bazel_invocations\"},{\"from\":\"BazelInvocation\",\"to\":\"EventMetadata\",\"label\":\"event_metadata\"},{\"from\":\"BazelInvocation\",\"to\":\"ConnectionMetadata\",\"label\":\"connection_metadata\"},{\"from\":\"BazelInvocation\",\"to\":\"Configuration\",\"label\":\"configurations\"},{\"from\":\"BazelInvocation\",\"to\":\"Action\",\"label\":\"actions\"},{\"from\":\"BazelInvocation\",\"to\":\"Metrics\",\"label\":\"metrics\"},{\"from\":\"BazelInvocation\",\"to\":\"IncompleteBuildLog\",\"label\":\"incomplete_build_logs\"},{\"from\":\"BazelInvocation\",\"to\":\"BuildLogChunk\",\"label\":\"build_log_chunks\"},{\"from\":\"BazelInvocation\",\"to\":\"InvocationFiles\",\"label\":\"invocation_files\"},{\"from\":\"BazelInvocation\",\"to\":\"InvocationTarget\",\"label\":\"invocation_targets\"},{\"from\":\"BazelInvocation\",\"to\":\"TargetKindMapping\",\"label\":\"target_kind_mappings\"},{\"from\":\"BazelInvocation\",\"to\":\"SourceControl\",\"label\":\"source_control\"},{\"from\":\"Build\",\"to\":\"BazelInvocation\",\"label\":\"invocations\"},{\"from\":\"InstanceName\",\"to\":\"BazelInvocation\",\"label\":\"bazel_invocations\"},{\"from\":\"InstanceName\",\"to\":\"Build\",\"label\":\"builds\"},{\"from\":\"InstanceName\",\"to\":\"Target\",\"label\":\"targets\"},{\"from\":\"InvocationTarget\",\"to\":\"Configuration\",\"label\":\"configuration\"},{\"from\":\"InvocationTarget\",\"to\":\"TestSummary\",\"label\":\"test_summary\"},{\"from\":\"MemoryMetrics\",\"to\":\"GarbageMetrics\",\"label\":\"garbage_metrics\"},{\"from\":\"Metrics\",\"to\":\"ActionSummary\",\"label\":\"action_summary\"},{\"from\":\"Metrics\",\"to\":\"MemoryMetrics\",\"label\":\"memory_metrics\"},{\"from\":\"Metrics\",\"to\":\"TargetMetrics\",\"label\":\"target_metrics\"},{\"from\":\"Metrics\",\"to\":\"TimingMetrics\",\"label\":\"timing_metrics\"},{\"from\":\"Metrics\",\"to\":\"ArtifactMetrics\",\"label\":\"artifact_metrics\"},{\"from\":\"Metrics\",\"to\":\"NetworkMetrics\",\"label\":\"network_metrics\"},{\"from\":\"Metrics\",\"to\":\"BuildGraphMetrics\",\"label\":\"build_graph_metrics\"},{\"from\":\"NetworkMetrics\",\"to\":\"SystemNetworkStats\",\"label\":\"system_network_stats\"},{\"from\":\"Target\",\"to\":\"InvocationTarget\",\"label\":\"invocation_targets\"},{\"from\":\"Target\",\"to\":\"TargetKindMapping\",\"label\":\"target_kind_mappings\"},{\"from\":\"Target\",\"to\":\"TestTarget\",\"label\":\"test_target\"},{\"from\":\"TestSummary\",\"to\":\"TestResult\",\"label\":\"test_results\"}]}"); const nodes = new vis.DataSet((entGraph.nodes || []).map(n => ({ id: n.id, diff --git a/ent/gen/ent/target.go b/ent/gen/ent/target.go index ccb4bdd7..66ece476 100644 --- a/ent/gen/ent/target.go +++ b/ent/gen/ent/target.go @@ -10,6 +10,7 @@ import ( "entgo.io/ent/dialect/sql" "github.com/buildbarn/bb-portal/ent/gen/ent/instancename" "github.com/buildbarn/bb-portal/ent/gen/ent/target" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" ) // Target is the model entity for the Target schema. @@ -38,11 +39,13 @@ type TargetEdges struct { InvocationTargets []*InvocationTarget `json:"invocation_targets,omitempty"` // TargetKindMappings holds the value of the target_kind_mappings edge. TargetKindMappings []*TargetKindMapping `json:"target_kind_mappings,omitempty"` + // TestTarget holds the value of the test_target edge. + TestTarget *TestTarget `json:"test_target,omitempty"` // loadedTypes holds the information for reporting if a // type was loaded (or requested) in eager-loading or not. - loadedTypes [3]bool + loadedTypes [4]bool // totalCount holds the count of the edges above. - totalCount [2]map[string]int + totalCount [3]map[string]int namedInvocationTargets map[string][]*InvocationTarget namedTargetKindMappings map[string][]*TargetKindMapping @@ -77,6 +80,17 @@ func (e TargetEdges) TargetKindMappingsOrErr() ([]*TargetKindMapping, error) { return nil, &NotLoadedError{edge: "target_kind_mappings"} } +// TestTargetOrErr returns the TestTarget value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e TargetEdges) TestTargetOrErr() (*TestTarget, error) { + if e.TestTarget != nil { + return e.TestTarget, nil + } else if e.loadedTypes[3] { + return nil, &NotFoundError{label: testtarget.Label} + } + return nil, &NotLoadedError{edge: "test_target"} +} + // scanValues returns the types for scanning values from sql.Rows. func (*Target) scanValues(columns []string) ([]any, error) { values := make([]any, len(columns)) @@ -162,6 +176,11 @@ func (t *Target) QueryTargetKindMappings() *TargetKindMappingQuery { return NewTargetClient(t.config).QueryTargetKindMappings(t) } +// QueryTestTarget queries the "test_target" edge of the Target entity. +func (t *Target) QueryTestTarget() *TestTargetQuery { + return NewTargetClient(t.config).QueryTestTarget(t) +} + // Update returns a builder for updating this Target. // Note that you need to call Target.Unwrap() before calling this method if this Target // was returned from a transaction, and the transaction was committed or rolled back. diff --git a/ent/gen/ent/target/target.go b/ent/gen/ent/target/target.go index 1ce792d6..c3363a25 100644 --- a/ent/gen/ent/target/target.go +++ b/ent/gen/ent/target/target.go @@ -25,6 +25,8 @@ const ( EdgeInvocationTargets = "invocation_targets" // EdgeTargetKindMappings holds the string denoting the target_kind_mappings edge name in mutations. EdgeTargetKindMappings = "target_kind_mappings" + // EdgeTestTarget holds the string denoting the test_target edge name in mutations. + EdgeTestTarget = "test_target" // Table holds the table name of the target in the database. Table = "targets" // InstanceNameTable is the table that holds the instance_name relation/edge. @@ -48,6 +50,13 @@ const ( TargetKindMappingsInverseTable = "target_kind_mappings" // TargetKindMappingsColumn is the table column denoting the target_kind_mappings relation/edge. TargetKindMappingsColumn = "target_id" + // TestTargetTable is the table that holds the test_target relation/edge. + TestTargetTable = "test_targets" + // TestTargetInverseTable is the table name for the TestTarget entity. + // It exists in this package in order to avoid circular dependency with the "testtarget" package. + TestTargetInverseTable = "test_targets" + // TestTargetColumn is the table column denoting the test_target relation/edge. + TestTargetColumn = "target_id" ) // Columns holds all SQL columns for target fields. @@ -146,6 +155,13 @@ func ByTargetKindMappings(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOptio sqlgraph.OrderByNeighborTerms(s, newTargetKindMappingsStep(), append([]sql.OrderTerm{term}, terms...)...) } } + +// ByTestTargetField orders the results by test_target field. +func ByTestTargetField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newTestTargetStep(), sql.OrderByField(field, opts...)) + } +} func newInstanceNameStep() *sqlgraph.Step { return sqlgraph.NewStep( sqlgraph.From(Table, FieldID), @@ -167,3 +183,10 @@ func newTargetKindMappingsStep() *sqlgraph.Step { sqlgraph.Edge(sqlgraph.O2M, false, TargetKindMappingsTable, TargetKindMappingsColumn), ) } +func newTestTargetStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(TestTargetInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, TestTargetTable, TestTargetColumn), + ) +} diff --git a/ent/gen/ent/target/where.go b/ent/gen/ent/target/where.go index ab652ced..e434ad95 100644 --- a/ent/gen/ent/target/where.go +++ b/ent/gen/ent/target/where.go @@ -327,6 +327,29 @@ func HasTargetKindMappingsWith(preds ...predicate.TargetKindMapping) predicate.T }) } +// HasTestTarget applies the HasEdge predicate on the "test_target" edge. +func HasTestTarget() predicate.Target { + return predicate.Target(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, TestTargetTable, TestTargetColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasTestTargetWith applies the HasEdge predicate on the "test_target" edge with a given conditions (other predicates). +func HasTestTargetWith(preds ...predicate.TestTarget) predicate.Target { + return predicate.Target(func(s *sql.Selector) { + step := newTestTargetStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + // And groups predicates with the AND operator between them. func And(predicates ...predicate.Target) predicate.Target { return predicate.Target(sql.AndPredicates(predicates...)) diff --git a/ent/gen/ent/target_create.go b/ent/gen/ent/target_create.go index af4484d6..490785ef 100644 --- a/ent/gen/ent/target_create.go +++ b/ent/gen/ent/target_create.go @@ -14,6 +14,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/invocationtarget" "github.com/buildbarn/bb-portal/ent/gen/ent/target" "github.com/buildbarn/bb-portal/ent/gen/ent/targetkindmapping" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" ) // TargetCreate is the builder for creating a Target entity. @@ -89,6 +90,25 @@ func (tc *TargetCreate) AddTargetKindMappings(t ...*TargetKindMapping) *TargetCr return tc.AddTargetKindMappingIDs(ids...) } +// SetTestTargetID sets the "test_target" edge to the TestTarget entity by ID. +func (tc *TargetCreate) SetTestTargetID(id int64) *TargetCreate { + tc.mutation.SetTestTargetID(id) + return tc +} + +// SetNillableTestTargetID sets the "test_target" edge to the TestTarget entity by ID if the given value is not nil. +func (tc *TargetCreate) SetNillableTestTargetID(id *int64) *TargetCreate { + if id != nil { + tc = tc.SetTestTargetID(*id) + } + return tc +} + +// SetTestTarget sets the "test_target" edge to the TestTarget entity. +func (tc *TargetCreate) SetTestTarget(t *TestTarget) *TargetCreate { + return tc.SetTestTargetID(t.ID) +} + // Mutation returns the TargetMutation object of the builder. func (tc *TargetCreate) Mutation() *TargetMutation { return tc.mutation @@ -229,6 +249,22 @@ func (tc *TargetCreate) createSpec() (*Target, *sqlgraph.CreateSpec) { } _spec.Edges = append(_spec.Edges, edge) } + if nodes := tc.mutation.TestTargetIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: target.TestTargetTable, + Columns: []string{target.TestTargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges = append(_spec.Edges, edge) + } return _node, _spec } diff --git a/ent/gen/ent/target_query.go b/ent/gen/ent/target_query.go index 82b78501..65e449c4 100644 --- a/ent/gen/ent/target_query.go +++ b/ent/gen/ent/target_query.go @@ -18,6 +18,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/predicate" "github.com/buildbarn/bb-portal/ent/gen/ent/target" "github.com/buildbarn/bb-portal/ent/gen/ent/targetkindmapping" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" ) // TargetQuery is the builder for querying Target entities. @@ -30,6 +31,7 @@ type TargetQuery struct { withInstanceName *InstanceNameQuery withInvocationTargets *InvocationTargetQuery withTargetKindMappings *TargetKindMappingQuery + withTestTarget *TestTargetQuery withFKs bool loadTotal []func(context.Context, []*Target) error modifiers []func(*sql.Selector) @@ -137,6 +139,28 @@ func (tq *TargetQuery) QueryTargetKindMappings() *TargetKindMappingQuery { return query } +// QueryTestTarget chains the current query on the "test_target" edge. +func (tq *TargetQuery) QueryTestTarget() *TestTargetQuery { + query := (&TestTargetClient{config: tq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := tq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := tq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(target.Table, target.FieldID, selector), + sqlgraph.To(testtarget.Table, testtarget.FieldID), + sqlgraph.Edge(sqlgraph.O2O, false, target.TestTargetTable, target.TestTargetColumn), + ) + fromU = sqlgraph.SetNeighbors(tq.driver.Dialect(), step) + return fromU, nil + } + return query +} + // First returns the first Target entity from the query. // Returns a *NotFoundError when no Target was found. func (tq *TargetQuery) First(ctx context.Context) (*Target, error) { @@ -332,6 +356,7 @@ func (tq *TargetQuery) Clone() *TargetQuery { withInstanceName: tq.withInstanceName.Clone(), withInvocationTargets: tq.withInvocationTargets.Clone(), withTargetKindMappings: tq.withTargetKindMappings.Clone(), + withTestTarget: tq.withTestTarget.Clone(), // clone intermediate query. sql: tq.sql.Clone(), path: tq.path, @@ -372,6 +397,17 @@ func (tq *TargetQuery) WithTargetKindMappings(opts ...func(*TargetKindMappingQue return tq } +// WithTestTarget tells the query-builder to eager-load the nodes that are connected to +// the "test_target" edge. The optional arguments are used to configure the query builder of the edge. +func (tq *TargetQuery) WithTestTarget(opts ...func(*TestTargetQuery)) *TargetQuery { + query := (&TestTargetClient{config: tq.config}).Query() + for _, opt := range opts { + opt(query) + } + tq.withTestTarget = query + return tq +} + // GroupBy is used to group vertices by one or more fields/columns. // It is often used with aggregate functions, like: count, max, mean, min, sum. // @@ -457,10 +493,11 @@ func (tq *TargetQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Targe nodes = []*Target{} withFKs = tq.withFKs _spec = tq.querySpec() - loadedTypes = [3]bool{ + loadedTypes = [4]bool{ tq.withInstanceName != nil, tq.withInvocationTargets != nil, tq.withTargetKindMappings != nil, + tq.withTestTarget != nil, } ) if tq.withInstanceName != nil { @@ -512,6 +549,12 @@ func (tq *TargetQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Targe return nil, err } } + if query := tq.withTestTarget; query != nil { + if err := tq.loadTestTarget(ctx, query, nodes, nil, + func(n *Target, e *TestTarget) { n.Edges.TestTarget = e }); err != nil { + return nil, err + } + } for name, query := range tq.withNamedInvocationTargets { if err := tq.loadInvocationTargets(ctx, query, nodes, func(n *Target) { n.appendNamedInvocationTargets(name) }, @@ -627,6 +670,33 @@ func (tq *TargetQuery) loadTargetKindMappings(ctx context.Context, query *Target } return nil } +func (tq *TargetQuery) loadTestTarget(ctx context.Context, query *TestTargetQuery, nodes []*Target, init func(*Target), assign func(*Target, *TestTarget)) error { + fks := make([]driver.Value, 0, len(nodes)) + nodeids := make(map[int64]*Target) + for i := range nodes { + fks = append(fks, nodes[i].ID) + nodeids[nodes[i].ID] = nodes[i] + } + if len(query.ctx.Fields) > 0 { + query.ctx.AppendFieldOnce(testtarget.FieldTargetID) + } + query.Where(predicate.TestTarget(func(s *sql.Selector) { + s.Where(sql.InValues(s.C(target.TestTargetColumn), fks...)) + })) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + fk := n.TargetID + node, ok := nodeids[fk] + if !ok { + return fmt.Errorf(`unexpected referenced foreign-key "target_id" returned %v for node %v`, fk, n.ID) + } + assign(node, n) + } + return nil +} func (tq *TargetQuery) sqlCount(ctx context.Context) (int, error) { _spec := tq.querySpec() diff --git a/ent/gen/ent/target_update.go b/ent/gen/ent/target_update.go index 17a13930..e8d849e7 100644 --- a/ent/gen/ent/target_update.go +++ b/ent/gen/ent/target_update.go @@ -15,6 +15,7 @@ import ( "github.com/buildbarn/bb-portal/ent/gen/ent/predicate" "github.com/buildbarn/bb-portal/ent/gen/ent/target" "github.com/buildbarn/bb-portal/ent/gen/ent/targetkindmapping" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" ) // TargetUpdate is the builder for updating Target entities. @@ -114,6 +115,25 @@ func (tu *TargetUpdate) AddTargetKindMappings(t ...*TargetKindMapping) *TargetUp return tu.AddTargetKindMappingIDs(ids...) } +// SetTestTargetID sets the "test_target" edge to the TestTarget entity by ID. +func (tu *TargetUpdate) SetTestTargetID(id int64) *TargetUpdate { + tu.mutation.SetTestTargetID(id) + return tu +} + +// SetNillableTestTargetID sets the "test_target" edge to the TestTarget entity by ID if the given value is not nil. +func (tu *TargetUpdate) SetNillableTestTargetID(id *int64) *TargetUpdate { + if id != nil { + tu = tu.SetTestTargetID(*id) + } + return tu +} + +// SetTestTarget sets the "test_target" edge to the TestTarget entity. +func (tu *TargetUpdate) SetTestTarget(t *TestTarget) *TargetUpdate { + return tu.SetTestTargetID(t.ID) +} + // Mutation returns the TargetMutation object of the builder. func (tu *TargetUpdate) Mutation() *TargetMutation { return tu.mutation @@ -167,6 +187,12 @@ func (tu *TargetUpdate) RemoveTargetKindMappings(t ...*TargetKindMapping) *Targe return tu.RemoveTargetKindMappingIDs(ids...) } +// ClearTestTarget clears the "test_target" edge to the TestTarget entity. +func (tu *TargetUpdate) ClearTestTarget() *TargetUpdate { + tu.mutation.ClearTestTarget() + return tu +} + // Save executes the query and returns the number of nodes affected by the update operation. func (tu *TargetUpdate) Save(ctx context.Context) (int, error) { return withHooks(ctx, tu.sqlSave, tu.mutation, tu.hooks) @@ -348,6 +374,35 @@ func (tu *TargetUpdate) sqlSave(ctx context.Context) (n int, err error) { } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if tu.mutation.TestTargetCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: target.TestTargetTable, + Columns: []string{target.TestTargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tu.mutation.TestTargetIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: target.TestTargetTable, + Columns: []string{target.TestTargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _spec.AddModifiers(tu.modifiers...) if n, err = sqlgraph.UpdateNodes(ctx, tu.driver, _spec); err != nil { if _, ok := err.(*sqlgraph.NotFoundError); ok { @@ -453,6 +508,25 @@ func (tuo *TargetUpdateOne) AddTargetKindMappings(t ...*TargetKindMapping) *Targ return tuo.AddTargetKindMappingIDs(ids...) } +// SetTestTargetID sets the "test_target" edge to the TestTarget entity by ID. +func (tuo *TargetUpdateOne) SetTestTargetID(id int64) *TargetUpdateOne { + tuo.mutation.SetTestTargetID(id) + return tuo +} + +// SetNillableTestTargetID sets the "test_target" edge to the TestTarget entity by ID if the given value is not nil. +func (tuo *TargetUpdateOne) SetNillableTestTargetID(id *int64) *TargetUpdateOne { + if id != nil { + tuo = tuo.SetTestTargetID(*id) + } + return tuo +} + +// SetTestTarget sets the "test_target" edge to the TestTarget entity. +func (tuo *TargetUpdateOne) SetTestTarget(t *TestTarget) *TargetUpdateOne { + return tuo.SetTestTargetID(t.ID) +} + // Mutation returns the TargetMutation object of the builder. func (tuo *TargetUpdateOne) Mutation() *TargetMutation { return tuo.mutation @@ -506,6 +580,12 @@ func (tuo *TargetUpdateOne) RemoveTargetKindMappings(t ...*TargetKindMapping) *T return tuo.RemoveTargetKindMappingIDs(ids...) } +// ClearTestTarget clears the "test_target" edge to the TestTarget entity. +func (tuo *TargetUpdateOne) ClearTestTarget() *TargetUpdateOne { + tuo.mutation.ClearTestTarget() + return tuo +} + // Where appends a list predicates to the TargetUpdate builder. func (tuo *TargetUpdateOne) Where(ps ...predicate.Target) *TargetUpdateOne { tuo.mutation.Where(ps...) @@ -717,6 +797,35 @@ func (tuo *TargetUpdateOne) sqlSave(ctx context.Context) (_node *Target, err err } _spec.Edges.Add = append(_spec.Edges.Add, edge) } + if tuo.mutation.TestTargetCleared() { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: target.TestTargetTable, + Columns: []string{target.TestTargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64), + }, + } + _spec.Edges.Clear = append(_spec.Edges.Clear, edge) + } + if nodes := tuo.mutation.TestTargetIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: false, + Table: target.TestTargetTable, + Columns: []string{target.TestTargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _spec.Edges.Add = append(_spec.Edges.Add, edge) + } _spec.AddModifiers(tuo.modifiers...) _node = &Target{config: tuo.config} _spec.Assign = _node.assignValues diff --git a/ent/gen/ent/testtarget.go b/ent/gen/ent/testtarget.go new file mode 100644 index 00000000..ba7c7093 --- /dev/null +++ b/ent/gen/ent/testtarget.go @@ -0,0 +1,132 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "fmt" + "strings" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "github.com/buildbarn/bb-portal/ent/gen/ent/target" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" +) + +// TestTarget is the model entity for the TestTarget schema. +type TestTarget struct { + config `json:"-"` + // ID of the ent. + ID int64 `json:"id,omitempty"` + // TargetID holds the value of the "target_id" field. + TargetID int64 `json:"target_id,omitempty"` + // Edges holds the relations/edges for other nodes in the graph. + // The values are being populated by the TestTargetQuery when eager-loading is set. + Edges TestTargetEdges `json:"edges"` + selectValues sql.SelectValues +} + +// TestTargetEdges holds the relations/edges for other nodes in the graph. +type TestTargetEdges struct { + // Target holds the value of the target edge. + Target *Target `json:"target,omitempty"` + // loadedTypes holds the information for reporting if a + // type was loaded (or requested) in eager-loading or not. + loadedTypes [1]bool + // totalCount holds the count of the edges above. + totalCount [1]map[string]int +} + +// TargetOrErr returns the Target value or an error if the edge +// was not loaded in eager-loading, or loaded but was not found. +func (e TestTargetEdges) TargetOrErr() (*Target, error) { + if e.Target != nil { + return e.Target, nil + } else if e.loadedTypes[0] { + return nil, &NotFoundError{label: target.Label} + } + return nil, &NotLoadedError{edge: "target"} +} + +// scanValues returns the types for scanning values from sql.Rows. +func (*TestTarget) scanValues(columns []string) ([]any, error) { + values := make([]any, len(columns)) + for i := range columns { + switch columns[i] { + case testtarget.FieldID, testtarget.FieldTargetID: + values[i] = new(sql.NullInt64) + default: + values[i] = new(sql.UnknownType) + } + } + return values, nil +} + +// assignValues assigns the values that were returned from sql.Rows (after scanning) +// to the TestTarget fields. +func (tt *TestTarget) assignValues(columns []string, values []any) error { + if m, n := len(values), len(columns); m < n { + return fmt.Errorf("mismatch number of scan values: %d != %d", m, n) + } + for i := range columns { + switch columns[i] { + case testtarget.FieldID: + value, ok := values[i].(*sql.NullInt64) + if !ok { + return fmt.Errorf("unexpected type %T for field id", value) + } + tt.ID = int64(value.Int64) + case testtarget.FieldTargetID: + if value, ok := values[i].(*sql.NullInt64); !ok { + return fmt.Errorf("unexpected type %T for field target_id", values[i]) + } else if value.Valid { + tt.TargetID = value.Int64 + } + default: + tt.selectValues.Set(columns[i], values[i]) + } + } + return nil +} + +// Value returns the ent.Value that was dynamically selected and assigned to the TestTarget. +// This includes values selected through modifiers, order, etc. +func (tt *TestTarget) Value(name string) (ent.Value, error) { + return tt.selectValues.Get(name) +} + +// QueryTarget queries the "target" edge of the TestTarget entity. +func (tt *TestTarget) QueryTarget() *TargetQuery { + return NewTestTargetClient(tt.config).QueryTarget(tt) +} + +// Update returns a builder for updating this TestTarget. +// Note that you need to call TestTarget.Unwrap() before calling this method if this TestTarget +// was returned from a transaction, and the transaction was committed or rolled back. +func (tt *TestTarget) Update() *TestTargetUpdateOne { + return NewTestTargetClient(tt.config).UpdateOne(tt) +} + +// Unwrap unwraps the TestTarget entity that was returned from a transaction after it was closed, +// so that all future queries will be executed through the driver which created the transaction. +func (tt *TestTarget) Unwrap() *TestTarget { + _tx, ok := tt.config.driver.(*txDriver) + if !ok { + panic("ent: TestTarget is not a transactional entity") + } + tt.config.driver = _tx.drv + return tt +} + +// String implements the fmt.Stringer. +func (tt *TestTarget) String() string { + var builder strings.Builder + builder.WriteString("TestTarget(") + builder.WriteString(fmt.Sprintf("id=%v, ", tt.ID)) + builder.WriteString("target_id=") + builder.WriteString(fmt.Sprintf("%v", tt.TargetID)) + builder.WriteByte(')') + return builder.String() +} + +// TestTargets is a parsable slice of TestTarget. +type TestTargets []*TestTarget diff --git a/ent/gen/ent/testtarget/BUILD.bazel b/ent/gen/ent/testtarget/BUILD.bazel new file mode 100644 index 00000000..41e87b69 --- /dev/null +++ b/ent/gen/ent/testtarget/BUILD.bazel @@ -0,0 +1,17 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "testtarget", + srcs = [ + "testtarget.go", + "where.go", + ], + importpath = "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget", + visibility = ["//visibility:public"], + deps = [ + "//ent/gen/ent/predicate", + "@io_entgo_ent//:ent", + "@io_entgo_ent//dialect/sql", + "@io_entgo_ent//dialect/sql/sqlgraph", + ], +) diff --git a/ent/gen/ent/testtarget/testtarget.go b/ent/gen/ent/testtarget/testtarget.go new file mode 100644 index 00000000..14332f98 --- /dev/null +++ b/ent/gen/ent/testtarget/testtarget.go @@ -0,0 +1,82 @@ +// Code generated by ent, DO NOT EDIT. + +package testtarget + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" +) + +const ( + // Label holds the string label denoting the testtarget type in the database. + Label = "test_target" + // FieldID holds the string denoting the id field in the database. + FieldID = "id" + // FieldTargetID holds the string denoting the target_id field in the database. + FieldTargetID = "target_id" + // EdgeTarget holds the string denoting the target edge name in mutations. + EdgeTarget = "target" + // Table holds the table name of the testtarget in the database. + Table = "test_targets" + // TargetTable is the table that holds the target relation/edge. + TargetTable = "test_targets" + // TargetInverseTable is the table name for the Target entity. + // It exists in this package in order to avoid circular dependency with the "target" package. + TargetInverseTable = "targets" + // TargetColumn is the table column denoting the target relation/edge. + TargetColumn = "target_id" +) + +// Columns holds all SQL columns for testtarget fields. +var Columns = []string{ + FieldID, + FieldTargetID, +} + +// ValidColumn reports if the column name is valid (part of the table columns). +func ValidColumn(column string) bool { + for i := range Columns { + if column == Columns[i] { + return true + } + } + return false +} + +// Note that the variables below are initialized by the runtime +// package on the initialization of the application. Therefore, +// it should be imported in the main as follows: +// +// import _ "github.com/buildbarn/bb-portal/ent/gen/ent/runtime" +var ( + Hooks [1]ent.Hook + Policy ent.Policy +) + +// OrderOption defines the ordering options for the TestTarget queries. +type OrderOption func(*sql.Selector) + +// ByID orders the results by the id field. +func ByID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldID, opts...).ToFunc() +} + +// ByTargetID orders the results by the target_id field. +func ByTargetID(opts ...sql.OrderTermOption) OrderOption { + return sql.OrderByField(FieldTargetID, opts...).ToFunc() +} + +// ByTargetField orders the results by target field. +func ByTargetField(field string, opts ...sql.OrderTermOption) OrderOption { + return func(s *sql.Selector) { + sqlgraph.OrderByNeighborTerms(s, newTargetStep(), sql.OrderByField(field, opts...)) + } +} +func newTargetStep() *sqlgraph.Step { + return sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.To(TargetInverseTable, FieldID), + sqlgraph.Edge(sqlgraph.O2O, true, TargetTable, TargetColumn), + ) +} diff --git a/ent/gen/ent/testtarget/where.go b/ent/gen/ent/testtarget/where.go new file mode 100644 index 00000000..170702ce --- /dev/null +++ b/ent/gen/ent/testtarget/where.go @@ -0,0 +1,117 @@ +// Code generated by ent, DO NOT EDIT. + +package testtarget + +import ( + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "github.com/buildbarn/bb-portal/ent/gen/ent/predicate" +) + +// ID filters vertices based on their ID field. +func ID(id int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldEQ(FieldID, id)) +} + +// IDEQ applies the EQ predicate on the ID field. +func IDEQ(id int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldEQ(FieldID, id)) +} + +// IDNEQ applies the NEQ predicate on the ID field. +func IDNEQ(id int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldNEQ(FieldID, id)) +} + +// IDIn applies the In predicate on the ID field. +func IDIn(ids ...int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldIn(FieldID, ids...)) +} + +// IDNotIn applies the NotIn predicate on the ID field. +func IDNotIn(ids ...int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldNotIn(FieldID, ids...)) +} + +// IDGT applies the GT predicate on the ID field. +func IDGT(id int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldGT(FieldID, id)) +} + +// IDGTE applies the GTE predicate on the ID field. +func IDGTE(id int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldGTE(FieldID, id)) +} + +// IDLT applies the LT predicate on the ID field. +func IDLT(id int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldLT(FieldID, id)) +} + +// IDLTE applies the LTE predicate on the ID field. +func IDLTE(id int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldLTE(FieldID, id)) +} + +// TargetID applies equality check predicate on the "target_id" field. It's identical to TargetIDEQ. +func TargetID(v int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldEQ(FieldTargetID, v)) +} + +// TargetIDEQ applies the EQ predicate on the "target_id" field. +func TargetIDEQ(v int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldEQ(FieldTargetID, v)) +} + +// TargetIDNEQ applies the NEQ predicate on the "target_id" field. +func TargetIDNEQ(v int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldNEQ(FieldTargetID, v)) +} + +// TargetIDIn applies the In predicate on the "target_id" field. +func TargetIDIn(vs ...int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldIn(FieldTargetID, vs...)) +} + +// TargetIDNotIn applies the NotIn predicate on the "target_id" field. +func TargetIDNotIn(vs ...int64) predicate.TestTarget { + return predicate.TestTarget(sql.FieldNotIn(FieldTargetID, vs...)) +} + +// HasTarget applies the HasEdge predicate on the "target" edge. +func HasTarget() predicate.TestTarget { + return predicate.TestTarget(func(s *sql.Selector) { + step := sqlgraph.NewStep( + sqlgraph.From(Table, FieldID), + sqlgraph.Edge(sqlgraph.O2O, true, TargetTable, TargetColumn), + ) + sqlgraph.HasNeighbors(s, step) + }) +} + +// HasTargetWith applies the HasEdge predicate on the "target" edge with a given conditions (other predicates). +func HasTargetWith(preds ...predicate.Target) predicate.TestTarget { + return predicate.TestTarget(func(s *sql.Selector) { + step := newTargetStep() + sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) { + for _, p := range preds { + p(s) + } + }) + }) +} + +// And groups predicates with the AND operator between them. +func And(predicates ...predicate.TestTarget) predicate.TestTarget { + return predicate.TestTarget(sql.AndPredicates(predicates...)) +} + +// Or groups predicates with the OR operator between them. +func Or(predicates ...predicate.TestTarget) predicate.TestTarget { + return predicate.TestTarget(sql.OrPredicates(predicates...)) +} + +// Not applies the not operator on the given predicate. +func Not(p predicate.TestTarget) predicate.TestTarget { + return predicate.TestTarget(sql.NotPredicates(p)) +} diff --git a/ent/gen/ent/testtarget_create.go b/ent/gen/ent/testtarget_create.go new file mode 100644 index 00000000..6a9354a0 --- /dev/null +++ b/ent/gen/ent/testtarget_create.go @@ -0,0 +1,472 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/buildbarn/bb-portal/ent/gen/ent/target" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" +) + +// TestTargetCreate is the builder for creating a TestTarget entity. +type TestTargetCreate struct { + config + mutation *TestTargetMutation + hooks []Hook + conflict []sql.ConflictOption +} + +// SetTargetID sets the "target_id" field. +func (ttc *TestTargetCreate) SetTargetID(i int64) *TestTargetCreate { + ttc.mutation.SetTargetID(i) + return ttc +} + +// SetID sets the "id" field. +func (ttc *TestTargetCreate) SetID(i int64) *TestTargetCreate { + ttc.mutation.SetID(i) + return ttc +} + +// SetTarget sets the "target" edge to the Target entity. +func (ttc *TestTargetCreate) SetTarget(t *Target) *TestTargetCreate { + return ttc.SetTargetID(t.ID) +} + +// Mutation returns the TestTargetMutation object of the builder. +func (ttc *TestTargetCreate) Mutation() *TestTargetMutation { + return ttc.mutation +} + +// Save creates the TestTarget in the database. +func (ttc *TestTargetCreate) Save(ctx context.Context) (*TestTarget, error) { + return withHooks(ctx, ttc.sqlSave, ttc.mutation, ttc.hooks) +} + +// SaveX calls Save and panics if Save returns an error. +func (ttc *TestTargetCreate) SaveX(ctx context.Context) *TestTarget { + v, err := ttc.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ttc *TestTargetCreate) Exec(ctx context.Context) error { + _, err := ttc.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ttc *TestTargetCreate) ExecX(ctx context.Context) { + if err := ttc.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (ttc *TestTargetCreate) check() error { + if _, ok := ttc.mutation.TargetID(); !ok { + return &ValidationError{Name: "target_id", err: errors.New(`ent: missing required field "TestTarget.target_id"`)} + } + if len(ttc.mutation.TargetIDs()) == 0 { + return &ValidationError{Name: "target", err: errors.New(`ent: missing required edge "TestTarget.target"`)} + } + return nil +} + +func (ttc *TestTargetCreate) sqlSave(ctx context.Context) (*TestTarget, error) { + if err := ttc.check(); err != nil { + return nil, err + } + _node, _spec := ttc.createSpec() + if err := sqlgraph.CreateNode(ctx, ttc.driver, _spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + if _spec.ID.Value != _node.ID { + id := _spec.ID.Value.(int64) + _node.ID = int64(id) + } + ttc.mutation.id = &_node.ID + ttc.mutation.done = true + return _node, nil +} + +func (ttc *TestTargetCreate) createSpec() (*TestTarget, *sqlgraph.CreateSpec) { + var ( + _node = &TestTarget{config: ttc.config} + _spec = sqlgraph.NewCreateSpec(testtarget.Table, sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64)) + ) + _spec.OnConflict = ttc.conflict + if id, ok := ttc.mutation.ID(); ok { + _node.ID = id + _spec.ID.Value = id + } + if nodes := ttc.mutation.TargetIDs(); len(nodes) > 0 { + edge := &sqlgraph.EdgeSpec{ + Rel: sqlgraph.O2O, + Inverse: true, + Table: testtarget.TargetTable, + Columns: []string{testtarget.TargetColumn}, + Bidi: false, + Target: &sqlgraph.EdgeTarget{ + IDSpec: sqlgraph.NewFieldSpec(target.FieldID, field.TypeInt64), + }, + } + for _, k := range nodes { + edge.Target.Nodes = append(edge.Target.Nodes, k) + } + _node.TargetID = nodes[0] + _spec.Edges = append(_spec.Edges, edge) + } + return _node, _spec +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.TestTarget.Create(). +// SetTargetID(v). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.TestTargetUpsert) { +// SetTargetID(v+v). +// }). +// Exec(ctx) +func (ttc *TestTargetCreate) OnConflict(opts ...sql.ConflictOption) *TestTargetUpsertOne { + ttc.conflict = opts + return &TestTargetUpsertOne{ + create: ttc, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.TestTarget.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (ttc *TestTargetCreate) OnConflictColumns(columns ...string) *TestTargetUpsertOne { + ttc.conflict = append(ttc.conflict, sql.ConflictColumns(columns...)) + return &TestTargetUpsertOne{ + create: ttc, + } +} + +type ( + // TestTargetUpsertOne is the builder for "upsert"-ing + // one TestTarget node. + TestTargetUpsertOne struct { + create *TestTargetCreate + } + + // TestTargetUpsert is the "OnConflict" setter. + TestTargetUpsert struct { + *sql.UpdateSet + } +) + +// 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: +// +// client.TestTarget.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(testtarget.FieldID) +// }), +// ). +// Exec(ctx) +func (u *TestTargetUpsertOne) UpdateNewValues() *TestTargetUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + if _, exists := u.create.mutation.ID(); exists { + s.SetIgnore(testtarget.FieldID) + } + if _, exists := u.create.mutation.TargetID(); exists { + s.SetIgnore(testtarget.FieldTargetID) + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.TestTarget.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *TestTargetUpsertOne) Ignore() *TestTargetUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *TestTargetUpsertOne) DoNothing() *TestTargetUpsertOne { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the TestTargetCreate.OnConflict +// documentation for more info. +func (u *TestTargetUpsertOne) Update(set func(*TestTargetUpsert)) *TestTargetUpsertOne { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&TestTargetUpsert{UpdateSet: update}) + })) + return u +} + +// Exec executes the query. +func (u *TestTargetUpsertOne) Exec(ctx context.Context) error { + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for TestTargetCreate.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *TestTargetUpsertOne) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} + +// Exec executes the UPSERT query and returns the inserted/updated ID. +func (u *TestTargetUpsertOne) ID(ctx context.Context) (id int64, err error) { + node, err := u.create.Save(ctx) + if err != nil { + return id, err + } + return node.ID, nil +} + +// IDX is like ID, but panics if an error occurs. +func (u *TestTargetUpsertOne) IDX(ctx context.Context) int64 { + id, err := u.ID(ctx) + if err != nil { + panic(err) + } + return id +} + +// TestTargetCreateBulk is the builder for creating many TestTarget entities in bulk. +type TestTargetCreateBulk struct { + config + err error + builders []*TestTargetCreate + conflict []sql.ConflictOption +} + +// Save creates the TestTarget entities in the database. +func (ttcb *TestTargetCreateBulk) Save(ctx context.Context) ([]*TestTarget, error) { + if ttcb.err != nil { + return nil, ttcb.err + } + specs := make([]*sqlgraph.CreateSpec, len(ttcb.builders)) + nodes := make([]*TestTarget, len(ttcb.builders)) + mutators := make([]Mutator, len(ttcb.builders)) + for i := range ttcb.builders { + func(i int, root context.Context) { + builder := ttcb.builders[i] + var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) { + mutation, ok := m.(*TestTargetMutation) + if !ok { + return nil, fmt.Errorf("unexpected mutation type %T", m) + } + if err := builder.check(); err != nil { + return nil, err + } + builder.mutation = mutation + var err error + nodes[i], specs[i] = builder.createSpec() + if i < len(mutators)-1 { + _, err = mutators[i+1].Mutate(root, ttcb.builders[i+1].mutation) + } else { + spec := &sqlgraph.BatchCreateSpec{Nodes: specs} + spec.OnConflict = ttcb.conflict + // Invoke the actual operation on the latest mutation in the chain. + if err = sqlgraph.BatchCreate(ctx, ttcb.driver, spec); err != nil { + if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + } + } + if err != nil { + return nil, err + } + mutation.id = &nodes[i].ID + if specs[i].ID.Value != nil && nodes[i].ID == 0 { + id := specs[i].ID.Value.(int64) + nodes[i].ID = int64(id) + } + mutation.done = true + return nodes[i], nil + }) + for i := len(builder.hooks) - 1; i >= 0; i-- { + mut = builder.hooks[i](mut) + } + mutators[i] = mut + }(i, ctx) + } + if len(mutators) > 0 { + if _, err := mutators[0].Mutate(ctx, ttcb.builders[0].mutation); err != nil { + return nil, err + } + } + return nodes, nil +} + +// SaveX is like Save, but panics if an error occurs. +func (ttcb *TestTargetCreateBulk) SaveX(ctx context.Context) []*TestTarget { + v, err := ttcb.Save(ctx) + if err != nil { + panic(err) + } + return v +} + +// Exec executes the query. +func (ttcb *TestTargetCreateBulk) Exec(ctx context.Context) error { + _, err := ttcb.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ttcb *TestTargetCreateBulk) ExecX(ctx context.Context) { + if err := ttcb.Exec(ctx); err != nil { + panic(err) + } +} + +// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause +// of the `INSERT` statement. For example: +// +// client.TestTarget.CreateBulk(builders...). +// OnConflict( +// // Update the row with the new values +// // the was proposed for insertion. +// sql.ResolveWithNewValues(), +// ). +// // Override some of the fields with custom +// // update values. +// Update(func(u *ent.TestTargetUpsert) { +// SetTargetID(v+v). +// }). +// Exec(ctx) +func (ttcb *TestTargetCreateBulk) OnConflict(opts ...sql.ConflictOption) *TestTargetUpsertBulk { + ttcb.conflict = opts + return &TestTargetUpsertBulk{ + create: ttcb, + } +} + +// OnConflictColumns calls `OnConflict` and configures the columns +// as conflict target. Using this option is equivalent to using: +// +// client.TestTarget.Create(). +// OnConflict(sql.ConflictColumns(columns...)). +// Exec(ctx) +func (ttcb *TestTargetCreateBulk) OnConflictColumns(columns ...string) *TestTargetUpsertBulk { + ttcb.conflict = append(ttcb.conflict, sql.ConflictColumns(columns...)) + return &TestTargetUpsertBulk{ + create: ttcb, + } +} + +// TestTargetUpsertBulk is the builder for "upsert"-ing +// a bulk of TestTarget nodes. +type TestTargetUpsertBulk struct { + create *TestTargetCreateBulk +} + +// UpdateNewValues updates the mutable fields using the new values that +// were set on create. Using this option is equivalent to using: +// +// client.TestTarget.Create(). +// OnConflict( +// sql.ResolveWithNewValues(), +// sql.ResolveWith(func(u *sql.UpdateSet) { +// u.SetIgnore(testtarget.FieldID) +// }), +// ). +// Exec(ctx) +func (u *TestTargetUpsertBulk) UpdateNewValues() *TestTargetUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues()) + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) { + for _, b := range u.create.builders { + if _, exists := b.mutation.ID(); exists { + s.SetIgnore(testtarget.FieldID) + } + if _, exists := b.mutation.TargetID(); exists { + s.SetIgnore(testtarget.FieldTargetID) + } + } + })) + return u +} + +// Ignore sets each column to itself in case of conflict. +// Using this option is equivalent to using: +// +// client.TestTarget.Create(). +// OnConflict(sql.ResolveWithIgnore()). +// Exec(ctx) +func (u *TestTargetUpsertBulk) Ignore() *TestTargetUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore()) + return u +} + +// DoNothing configures the conflict_action to `DO NOTHING`. +// Supported only by SQLite and PostgreSQL. +func (u *TestTargetUpsertBulk) DoNothing() *TestTargetUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.DoNothing()) + return u +} + +// Update allows overriding fields `UPDATE` values. See the TestTargetCreateBulk.OnConflict +// documentation for more info. +func (u *TestTargetUpsertBulk) Update(set func(*TestTargetUpsert)) *TestTargetUpsertBulk { + u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) { + set(&TestTargetUpsert{UpdateSet: update}) + })) + return u +} + +// Exec executes the query. +func (u *TestTargetUpsertBulk) Exec(ctx context.Context) error { + if u.create.err != nil { + return u.create.err + } + for i, b := range u.create.builders { + if len(b.conflict) != 0 { + return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the TestTargetCreateBulk instead", i) + } + } + if len(u.create.conflict) == 0 { + return errors.New("ent: missing options for TestTargetCreateBulk.OnConflict") + } + return u.create.Exec(ctx) +} + +// ExecX is like Exec, but panics if an error occurs. +func (u *TestTargetUpsertBulk) ExecX(ctx context.Context) { + if err := u.create.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/gen/ent/testtarget_delete.go b/ent/gen/ent/testtarget_delete.go new file mode 100644 index 00000000..607ecb24 --- /dev/null +++ b/ent/gen/ent/testtarget_delete.go @@ -0,0 +1,88 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/buildbarn/bb-portal/ent/gen/ent/predicate" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" +) + +// TestTargetDelete is the builder for deleting a TestTarget entity. +type TestTargetDelete struct { + config + hooks []Hook + mutation *TestTargetMutation +} + +// Where appends a list predicates to the TestTargetDelete builder. +func (ttd *TestTargetDelete) Where(ps ...predicate.TestTarget) *TestTargetDelete { + ttd.mutation.Where(ps...) + return ttd +} + +// Exec executes the deletion query and returns how many vertices were deleted. +func (ttd *TestTargetDelete) Exec(ctx context.Context) (int, error) { + return withHooks(ctx, ttd.sqlExec, ttd.mutation, ttd.hooks) +} + +// ExecX is like Exec, but panics if an error occurs. +func (ttd *TestTargetDelete) ExecX(ctx context.Context) int { + n, err := ttd.Exec(ctx) + if err != nil { + panic(err) + } + return n +} + +func (ttd *TestTargetDelete) sqlExec(ctx context.Context) (int, error) { + _spec := sqlgraph.NewDeleteSpec(testtarget.Table, sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64)) + if ps := ttd.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + affected, err := sqlgraph.DeleteNodes(ctx, ttd.driver, _spec) + if err != nil && sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + ttd.mutation.done = true + return affected, err +} + +// TestTargetDeleteOne is the builder for deleting a single TestTarget entity. +type TestTargetDeleteOne struct { + ttd *TestTargetDelete +} + +// Where appends a list predicates to the TestTargetDelete builder. +func (ttdo *TestTargetDeleteOne) Where(ps ...predicate.TestTarget) *TestTargetDeleteOne { + ttdo.ttd.mutation.Where(ps...) + return ttdo +} + +// Exec executes the deletion query. +func (ttdo *TestTargetDeleteOne) Exec(ctx context.Context) error { + n, err := ttdo.ttd.Exec(ctx) + switch { + case err != nil: + return err + case n == 0: + return &NotFoundError{testtarget.Label} + default: + return nil + } +} + +// ExecX is like Exec, but panics if an error occurs. +func (ttdo *TestTargetDeleteOne) ExecX(ctx context.Context) { + if err := ttdo.Exec(ctx); err != nil { + panic(err) + } +} diff --git a/ent/gen/ent/testtarget_query.go b/ent/gen/ent/testtarget_query.go new file mode 100644 index 00000000..c80ba251 --- /dev/null +++ b/ent/gen/ent/testtarget_query.go @@ -0,0 +1,642 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + "math" + + "entgo.io/ent" + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/buildbarn/bb-portal/ent/gen/ent/predicate" + "github.com/buildbarn/bb-portal/ent/gen/ent/target" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" +) + +// TestTargetQuery is the builder for querying TestTarget entities. +type TestTargetQuery struct { + config + ctx *QueryContext + order []testtarget.OrderOption + inters []Interceptor + predicates []predicate.TestTarget + withTarget *TargetQuery + loadTotal []func(context.Context, []*TestTarget) error + modifiers []func(*sql.Selector) + // intermediate query (i.e. traversal path). + sql *sql.Selector + path func(context.Context) (*sql.Selector, error) +} + +// Where adds a new predicate for the TestTargetQuery builder. +func (ttq *TestTargetQuery) Where(ps ...predicate.TestTarget) *TestTargetQuery { + ttq.predicates = append(ttq.predicates, ps...) + return ttq +} + +// Limit the number of records to be returned by this query. +func (ttq *TestTargetQuery) Limit(limit int) *TestTargetQuery { + ttq.ctx.Limit = &limit + return ttq +} + +// Offset to start from. +func (ttq *TestTargetQuery) Offset(offset int) *TestTargetQuery { + ttq.ctx.Offset = &offset + return ttq +} + +// Unique configures the query builder to filter duplicate records on query. +// By default, unique is set to true, and can be disabled using this method. +func (ttq *TestTargetQuery) Unique(unique bool) *TestTargetQuery { + ttq.ctx.Unique = &unique + return ttq +} + +// Order specifies how the records should be ordered. +func (ttq *TestTargetQuery) Order(o ...testtarget.OrderOption) *TestTargetQuery { + ttq.order = append(ttq.order, o...) + return ttq +} + +// QueryTarget chains the current query on the "target" edge. +func (ttq *TestTargetQuery) QueryTarget() *TargetQuery { + query := (&TargetClient{config: ttq.config}).Query() + query.path = func(ctx context.Context) (fromU *sql.Selector, err error) { + if err := ttq.prepareQuery(ctx); err != nil { + return nil, err + } + selector := ttq.sqlQuery(ctx) + if err := selector.Err(); err != nil { + return nil, err + } + step := sqlgraph.NewStep( + sqlgraph.From(testtarget.Table, testtarget.FieldID, selector), + sqlgraph.To(target.Table, target.FieldID), + sqlgraph.Edge(sqlgraph.O2O, true, testtarget.TargetTable, testtarget.TargetColumn), + ) + fromU = sqlgraph.SetNeighbors(ttq.driver.Dialect(), step) + return fromU, nil + } + return query +} + +// First returns the first TestTarget entity from the query. +// Returns a *NotFoundError when no TestTarget was found. +func (ttq *TestTargetQuery) First(ctx context.Context) (*TestTarget, error) { + nodes, err := ttq.Limit(1).All(setContextOp(ctx, ttq.ctx, ent.OpQueryFirst)) + if err != nil { + return nil, err + } + if len(nodes) == 0 { + return nil, &NotFoundError{testtarget.Label} + } + return nodes[0], nil +} + +// FirstX is like First, but panics if an error occurs. +func (ttq *TestTargetQuery) FirstX(ctx context.Context) *TestTarget { + node, err := ttq.First(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return node +} + +// FirstID returns the first TestTarget ID from the query. +// Returns a *NotFoundError when no TestTarget ID was found. +func (ttq *TestTargetQuery) FirstID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = ttq.Limit(1).IDs(setContextOp(ctx, ttq.ctx, ent.OpQueryFirstID)); err != nil { + return + } + if len(ids) == 0 { + err = &NotFoundError{testtarget.Label} + return + } + return ids[0], nil +} + +// FirstIDX is like FirstID, but panics if an error occurs. +func (ttq *TestTargetQuery) FirstIDX(ctx context.Context) int64 { + id, err := ttq.FirstID(ctx) + if err != nil && !IsNotFound(err) { + panic(err) + } + return id +} + +// Only returns a single TestTarget entity found by the query, ensuring it only returns one. +// Returns a *NotSingularError when more than one TestTarget entity is found. +// Returns a *NotFoundError when no TestTarget entities are found. +func (ttq *TestTargetQuery) Only(ctx context.Context) (*TestTarget, error) { + nodes, err := ttq.Limit(2).All(setContextOp(ctx, ttq.ctx, ent.OpQueryOnly)) + if err != nil { + return nil, err + } + switch len(nodes) { + case 1: + return nodes[0], nil + case 0: + return nil, &NotFoundError{testtarget.Label} + default: + return nil, &NotSingularError{testtarget.Label} + } +} + +// OnlyX is like Only, but panics if an error occurs. +func (ttq *TestTargetQuery) OnlyX(ctx context.Context) *TestTarget { + node, err := ttq.Only(ctx) + if err != nil { + panic(err) + } + return node +} + +// OnlyID is like Only, but returns the only TestTarget ID in the query. +// Returns a *NotSingularError when more than one TestTarget ID is found. +// Returns a *NotFoundError when no entities are found. +func (ttq *TestTargetQuery) OnlyID(ctx context.Context) (id int64, err error) { + var ids []int64 + if ids, err = ttq.Limit(2).IDs(setContextOp(ctx, ttq.ctx, ent.OpQueryOnlyID)); err != nil { + return + } + switch len(ids) { + case 1: + id = ids[0] + case 0: + err = &NotFoundError{testtarget.Label} + default: + err = &NotSingularError{testtarget.Label} + } + return +} + +// OnlyIDX is like OnlyID, but panics if an error occurs. +func (ttq *TestTargetQuery) OnlyIDX(ctx context.Context) int64 { + id, err := ttq.OnlyID(ctx) + if err != nil { + panic(err) + } + return id +} + +// All executes the query and returns a list of TestTargets. +func (ttq *TestTargetQuery) All(ctx context.Context) ([]*TestTarget, error) { + ctx = setContextOp(ctx, ttq.ctx, ent.OpQueryAll) + if err := ttq.prepareQuery(ctx); err != nil { + return nil, err + } + qr := querierAll[[]*TestTarget, *TestTargetQuery]() + return withInterceptors[[]*TestTarget](ctx, ttq, qr, ttq.inters) +} + +// AllX is like All, but panics if an error occurs. +func (ttq *TestTargetQuery) AllX(ctx context.Context) []*TestTarget { + nodes, err := ttq.All(ctx) + if err != nil { + panic(err) + } + return nodes +} + +// IDs executes the query and returns a list of TestTarget IDs. +func (ttq *TestTargetQuery) IDs(ctx context.Context) (ids []int64, err error) { + if ttq.ctx.Unique == nil && ttq.path != nil { + ttq.Unique(true) + } + ctx = setContextOp(ctx, ttq.ctx, ent.OpQueryIDs) + if err = ttq.Select(testtarget.FieldID).Scan(ctx, &ids); err != nil { + return nil, err + } + return ids, nil +} + +// IDsX is like IDs, but panics if an error occurs. +func (ttq *TestTargetQuery) IDsX(ctx context.Context) []int64 { + ids, err := ttq.IDs(ctx) + if err != nil { + panic(err) + } + return ids +} + +// Count returns the count of the given query. +func (ttq *TestTargetQuery) Count(ctx context.Context) (int, error) { + ctx = setContextOp(ctx, ttq.ctx, ent.OpQueryCount) + if err := ttq.prepareQuery(ctx); err != nil { + return 0, err + } + return withInterceptors[int](ctx, ttq, querierCount[*TestTargetQuery](), ttq.inters) +} + +// CountX is like Count, but panics if an error occurs. +func (ttq *TestTargetQuery) CountX(ctx context.Context) int { + count, err := ttq.Count(ctx) + if err != nil { + panic(err) + } + return count +} + +// Exist returns true if the query has elements in the graph. +func (ttq *TestTargetQuery) Exist(ctx context.Context) (bool, error) { + ctx = setContextOp(ctx, ttq.ctx, ent.OpQueryExist) + switch _, err := ttq.FirstID(ctx); { + case IsNotFound(err): + return false, nil + case err != nil: + return false, fmt.Errorf("ent: check existence: %w", err) + default: + return true, nil + } +} + +// ExistX is like Exist, but panics if an error occurs. +func (ttq *TestTargetQuery) ExistX(ctx context.Context) bool { + exist, err := ttq.Exist(ctx) + if err != nil { + panic(err) + } + return exist +} + +// Clone returns a duplicate of the TestTargetQuery builder, including all associated steps. It can be +// used to prepare common query builders and use them differently after the clone is made. +func (ttq *TestTargetQuery) Clone() *TestTargetQuery { + if ttq == nil { + return nil + } + return &TestTargetQuery{ + config: ttq.config, + ctx: ttq.ctx.Clone(), + order: append([]testtarget.OrderOption{}, ttq.order...), + inters: append([]Interceptor{}, ttq.inters...), + predicates: append([]predicate.TestTarget{}, ttq.predicates...), + withTarget: ttq.withTarget.Clone(), + // clone intermediate query. + sql: ttq.sql.Clone(), + path: ttq.path, + modifiers: append([]func(*sql.Selector){}, ttq.modifiers...), + } +} + +// WithTarget tells the query-builder to eager-load the nodes that are connected to +// the "target" edge. The optional arguments are used to configure the query builder of the edge. +func (ttq *TestTargetQuery) WithTarget(opts ...func(*TargetQuery)) *TestTargetQuery { + query := (&TargetClient{config: ttq.config}).Query() + for _, opt := range opts { + opt(query) + } + ttq.withTarget = query + return ttq +} + +// GroupBy is used to group vertices by one or more fields/columns. +// It is often used with aggregate functions, like: count, max, mean, min, sum. +// +// Example: +// +// var v []struct { +// TargetID int64 `json:"target_id,omitempty"` +// Count int `json:"count,omitempty"` +// } +// +// client.TestTarget.Query(). +// GroupBy(testtarget.FieldTargetID). +// Aggregate(ent.Count()). +// Scan(ctx, &v) +func (ttq *TestTargetQuery) GroupBy(field string, fields ...string) *TestTargetGroupBy { + ttq.ctx.Fields = append([]string{field}, fields...) + grbuild := &TestTargetGroupBy{build: ttq} + grbuild.flds = &ttq.ctx.Fields + grbuild.label = testtarget.Label + grbuild.scan = grbuild.Scan + return grbuild +} + +// Select allows the selection one or more fields/columns for the given query, +// instead of selecting all fields in the entity. +// +// Example: +// +// var v []struct { +// TargetID int64 `json:"target_id,omitempty"` +// } +// +// client.TestTarget.Query(). +// Select(testtarget.FieldTargetID). +// Scan(ctx, &v) +func (ttq *TestTargetQuery) Select(fields ...string) *TestTargetSelect { + ttq.ctx.Fields = append(ttq.ctx.Fields, fields...) + sbuild := &TestTargetSelect{TestTargetQuery: ttq} + sbuild.label = testtarget.Label + sbuild.flds, sbuild.scan = &ttq.ctx.Fields, sbuild.Scan + return sbuild +} + +// Aggregate returns a TestTargetSelect configured with the given aggregations. +func (ttq *TestTargetQuery) Aggregate(fns ...AggregateFunc) *TestTargetSelect { + return ttq.Select().Aggregate(fns...) +} + +func (ttq *TestTargetQuery) prepareQuery(ctx context.Context) error { + for _, inter := range ttq.inters { + if inter == nil { + return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)") + } + if trv, ok := inter.(Traverser); ok { + if err := trv.Traverse(ctx, ttq); err != nil { + return err + } + } + } + for _, f := range ttq.ctx.Fields { + if !testtarget.ValidColumn(f) { + return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + } + if ttq.path != nil { + prev, err := ttq.path(ctx) + if err != nil { + return err + } + ttq.sql = prev + } + if testtarget.Policy == nil { + return errors.New("ent: uninitialized testtarget.Policy (forgotten import ent/runtime?)") + } + if err := testtarget.Policy.EvalQuery(ctx, ttq); err != nil { + return err + } + return nil +} + +func (ttq *TestTargetQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*TestTarget, error) { + var ( + nodes = []*TestTarget{} + _spec = ttq.querySpec() + loadedTypes = [1]bool{ + ttq.withTarget != nil, + } + ) + _spec.ScanValues = func(columns []string) ([]any, error) { + return (*TestTarget).scanValues(nil, columns) + } + _spec.Assign = func(columns []string, values []any) error { + node := &TestTarget{config: ttq.config} + nodes = append(nodes, node) + node.Edges.loadedTypes = loadedTypes + return node.assignValues(columns, values) + } + if len(ttq.modifiers) > 0 { + _spec.Modifiers = ttq.modifiers + } + for i := range hooks { + hooks[i](ctx, _spec) + } + if err := sqlgraph.QueryNodes(ctx, ttq.driver, _spec); err != nil { + return nil, err + } + if len(nodes) == 0 { + return nodes, nil + } + if query := ttq.withTarget; query != nil { + if err := ttq.loadTarget(ctx, query, nodes, nil, + func(n *TestTarget, e *Target) { n.Edges.Target = e }); err != nil { + return nil, err + } + } + for i := range ttq.loadTotal { + if err := ttq.loadTotal[i](ctx, nodes); err != nil { + return nil, err + } + } + return nodes, nil +} + +func (ttq *TestTargetQuery) loadTarget(ctx context.Context, query *TargetQuery, nodes []*TestTarget, init func(*TestTarget), assign func(*TestTarget, *Target)) error { + ids := make([]int64, 0, len(nodes)) + nodeids := make(map[int64][]*TestTarget) + for i := range nodes { + fk := nodes[i].TargetID + if _, ok := nodeids[fk]; !ok { + ids = append(ids, fk) + } + nodeids[fk] = append(nodeids[fk], nodes[i]) + } + if len(ids) == 0 { + return nil + } + query.Where(target.IDIn(ids...)) + neighbors, err := query.All(ctx) + if err != nil { + return err + } + for _, n := range neighbors { + nodes, ok := nodeids[n.ID] + if !ok { + return fmt.Errorf(`unexpected foreign-key "target_id" returned %v`, n.ID) + } + for i := range nodes { + assign(nodes[i], n) + } + } + return nil +} + +func (ttq *TestTargetQuery) sqlCount(ctx context.Context) (int, error) { + _spec := ttq.querySpec() + if len(ttq.modifiers) > 0 { + _spec.Modifiers = ttq.modifiers + } + _spec.Node.Columns = ttq.ctx.Fields + if len(ttq.ctx.Fields) > 0 { + _spec.Unique = ttq.ctx.Unique != nil && *ttq.ctx.Unique + } + return sqlgraph.CountNodes(ctx, ttq.driver, _spec) +} + +func (ttq *TestTargetQuery) querySpec() *sqlgraph.QuerySpec { + _spec := sqlgraph.NewQuerySpec(testtarget.Table, testtarget.Columns, sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64)) + _spec.From = ttq.sql + if unique := ttq.ctx.Unique; unique != nil { + _spec.Unique = *unique + } else if ttq.path != nil { + _spec.Unique = true + } + if fields := ttq.ctx.Fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, testtarget.FieldID) + for i := range fields { + if fields[i] != testtarget.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, fields[i]) + } + } + if ttq.withTarget != nil { + _spec.Node.AddColumnOnce(testtarget.FieldTargetID) + } + } + if ps := ttq.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + if limit := ttq.ctx.Limit; limit != nil { + _spec.Limit = *limit + } + if offset := ttq.ctx.Offset; offset != nil { + _spec.Offset = *offset + } + if ps := ttq.order; len(ps) > 0 { + _spec.Order = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + return _spec +} + +func (ttq *TestTargetQuery) sqlQuery(ctx context.Context) *sql.Selector { + builder := sql.Dialect(ttq.driver.Dialect()) + t1 := builder.Table(testtarget.Table) + columns := ttq.ctx.Fields + if len(columns) == 0 { + columns = testtarget.Columns + } + selector := builder.Select(t1.Columns(columns...)...).From(t1) + if ttq.sql != nil { + selector = ttq.sql + selector.Select(selector.Columns(columns...)...) + } + if ttq.ctx.Unique != nil && *ttq.ctx.Unique { + selector.Distinct() + } + for _, m := range ttq.modifiers { + m(selector) + } + for _, p := range ttq.predicates { + p(selector) + } + for _, p := range ttq.order { + p(selector) + } + if offset := ttq.ctx.Offset; offset != nil { + // limit is mandatory for offset clause. We start + // with default value, and override it below if needed. + selector.Offset(*offset).Limit(math.MaxInt32) + } + if limit := ttq.ctx.Limit; limit != nil { + selector.Limit(*limit) + } + return selector +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (ttq *TestTargetQuery) Modify(modifiers ...func(s *sql.Selector)) *TestTargetSelect { + ttq.modifiers = append(ttq.modifiers, modifiers...) + return ttq.Select() +} + +// TestTargetGroupBy is the group-by builder for TestTarget entities. +type TestTargetGroupBy struct { + selector + build *TestTargetQuery +} + +// Aggregate adds the given aggregation functions to the group-by query. +func (ttgb *TestTargetGroupBy) Aggregate(fns ...AggregateFunc) *TestTargetGroupBy { + ttgb.fns = append(ttgb.fns, fns...) + return ttgb +} + +// Scan applies the selector query and scans the result into the given value. +func (ttgb *TestTargetGroupBy) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, ttgb.build.ctx, ent.OpQueryGroupBy) + if err := ttgb.build.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*TestTargetQuery, *TestTargetGroupBy](ctx, ttgb.build, ttgb, ttgb.build.inters, v) +} + +func (ttgb *TestTargetGroupBy) sqlScan(ctx context.Context, root *TestTargetQuery, v any) error { + selector := root.sqlQuery(ctx).Select() + aggregation := make([]string, 0, len(ttgb.fns)) + for _, fn := range ttgb.fns { + aggregation = append(aggregation, fn(selector)) + } + if len(selector.SelectedColumns()) == 0 { + columns := make([]string, 0, len(*ttgb.flds)+len(ttgb.fns)) + for _, f := range *ttgb.flds { + columns = append(columns, selector.C(f)) + } + columns = append(columns, aggregation...) + selector.Select(columns...) + } + selector.GroupBy(selector.Columns(*ttgb.flds...)...) + if err := selector.Err(); err != nil { + return err + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := ttgb.build.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// TestTargetSelect is the builder for selecting fields of TestTarget entities. +type TestTargetSelect struct { + *TestTargetQuery + selector +} + +// Aggregate adds the given aggregation functions to the selector query. +func (tts *TestTargetSelect) Aggregate(fns ...AggregateFunc) *TestTargetSelect { + tts.fns = append(tts.fns, fns...) + return tts +} + +// Scan applies the selector query and scans the result into the given value. +func (tts *TestTargetSelect) Scan(ctx context.Context, v any) error { + ctx = setContextOp(ctx, tts.ctx, ent.OpQuerySelect) + if err := tts.prepareQuery(ctx); err != nil { + return err + } + return scanWithInterceptors[*TestTargetQuery, *TestTargetSelect](ctx, tts.TestTargetQuery, tts, tts.inters, v) +} + +func (tts *TestTargetSelect) sqlScan(ctx context.Context, root *TestTargetQuery, v any) error { + selector := root.sqlQuery(ctx) + aggregation := make([]string, 0, len(tts.fns)) + for _, fn := range tts.fns { + aggregation = append(aggregation, fn(selector)) + } + switch n := len(*tts.selector.flds); { + case n == 0 && len(aggregation) > 0: + selector.Select(aggregation...) + case n != 0 && len(aggregation) > 0: + selector.AppendSelect(aggregation...) + } + rows := &sql.Rows{} + query, args := selector.Query() + if err := tts.driver.Query(ctx, query, args, rows); err != nil { + return err + } + defer rows.Close() + return sql.ScanSlice(rows, v) +} + +// Modify adds a query modifier for attaching custom logic to queries. +func (tts *TestTargetSelect) Modify(modifiers ...func(s *sql.Selector)) *TestTargetSelect { + tts.modifiers = append(tts.modifiers, modifiers...) + return tts +} diff --git a/ent/gen/ent/testtarget_update.go b/ent/gen/ent/testtarget_update.go new file mode 100644 index 00000000..758693a9 --- /dev/null +++ b/ent/gen/ent/testtarget_update.go @@ -0,0 +1,213 @@ +// Code generated by ent, DO NOT EDIT. + +package ent + +import ( + "context" + "errors" + "fmt" + + "entgo.io/ent/dialect/sql" + "entgo.io/ent/dialect/sql/sqlgraph" + "entgo.io/ent/schema/field" + "github.com/buildbarn/bb-portal/ent/gen/ent/predicate" + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" +) + +// TestTargetUpdate is the builder for updating TestTarget entities. +type TestTargetUpdate struct { + config + hooks []Hook + mutation *TestTargetMutation + modifiers []func(*sql.UpdateBuilder) +} + +// Where appends a list predicates to the TestTargetUpdate builder. +func (ttu *TestTargetUpdate) Where(ps ...predicate.TestTarget) *TestTargetUpdate { + ttu.mutation.Where(ps...) + return ttu +} + +// Mutation returns the TestTargetMutation object of the builder. +func (ttu *TestTargetUpdate) Mutation() *TestTargetMutation { + return ttu.mutation +} + +// Save executes the query and returns the number of nodes affected by the update operation. +func (ttu *TestTargetUpdate) Save(ctx context.Context) (int, error) { + return withHooks(ctx, ttu.sqlSave, ttu.mutation, ttu.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ttu *TestTargetUpdate) SaveX(ctx context.Context) int { + affected, err := ttu.Save(ctx) + if err != nil { + panic(err) + } + return affected +} + +// Exec executes the query. +func (ttu *TestTargetUpdate) Exec(ctx context.Context) error { + _, err := ttu.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ttu *TestTargetUpdate) ExecX(ctx context.Context) { + if err := ttu.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (ttu *TestTargetUpdate) check() error { + if ttu.mutation.TargetCleared() && len(ttu.mutation.TargetIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "TestTarget.target"`) + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (ttu *TestTargetUpdate) Modify(modifiers ...func(u *sql.UpdateBuilder)) *TestTargetUpdate { + ttu.modifiers = append(ttu.modifiers, modifiers...) + return ttu +} + +func (ttu *TestTargetUpdate) sqlSave(ctx context.Context) (n int, err error) { + if err := ttu.check(); err != nil { + return n, err + } + _spec := sqlgraph.NewUpdateSpec(testtarget.Table, testtarget.Columns, sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64)) + if ps := ttu.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + _spec.AddModifiers(ttu.modifiers...) + if n, err = sqlgraph.UpdateNodes(ctx, ttu.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{testtarget.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return 0, err + } + ttu.mutation.done = true + return n, nil +} + +// TestTargetUpdateOne is the builder for updating a single TestTarget entity. +type TestTargetUpdateOne struct { + config + fields []string + hooks []Hook + mutation *TestTargetMutation + modifiers []func(*sql.UpdateBuilder) +} + +// Mutation returns the TestTargetMutation object of the builder. +func (ttuo *TestTargetUpdateOne) Mutation() *TestTargetMutation { + return ttuo.mutation +} + +// Where appends a list predicates to the TestTargetUpdate builder. +func (ttuo *TestTargetUpdateOne) Where(ps ...predicate.TestTarget) *TestTargetUpdateOne { + ttuo.mutation.Where(ps...) + return ttuo +} + +// Select allows selecting one or more fields (columns) of the returned entity. +// The default is selecting all fields defined in the entity schema. +func (ttuo *TestTargetUpdateOne) Select(field string, fields ...string) *TestTargetUpdateOne { + ttuo.fields = append([]string{field}, fields...) + return ttuo +} + +// Save executes the query and returns the updated TestTarget entity. +func (ttuo *TestTargetUpdateOne) Save(ctx context.Context) (*TestTarget, error) { + return withHooks(ctx, ttuo.sqlSave, ttuo.mutation, ttuo.hooks) +} + +// SaveX is like Save, but panics if an error occurs. +func (ttuo *TestTargetUpdateOne) SaveX(ctx context.Context) *TestTarget { + node, err := ttuo.Save(ctx) + if err != nil { + panic(err) + } + return node +} + +// Exec executes the query on the entity. +func (ttuo *TestTargetUpdateOne) Exec(ctx context.Context) error { + _, err := ttuo.Save(ctx) + return err +} + +// ExecX is like Exec, but panics if an error occurs. +func (ttuo *TestTargetUpdateOne) ExecX(ctx context.Context) { + if err := ttuo.Exec(ctx); err != nil { + panic(err) + } +} + +// check runs all checks and user-defined validators on the builder. +func (ttuo *TestTargetUpdateOne) check() error { + if ttuo.mutation.TargetCleared() && len(ttuo.mutation.TargetIDs()) > 0 { + return errors.New(`ent: clearing a required unique edge "TestTarget.target"`) + } + return nil +} + +// Modify adds a statement modifier for attaching custom logic to the UPDATE statement. +func (ttuo *TestTargetUpdateOne) Modify(modifiers ...func(u *sql.UpdateBuilder)) *TestTargetUpdateOne { + ttuo.modifiers = append(ttuo.modifiers, modifiers...) + return ttuo +} + +func (ttuo *TestTargetUpdateOne) sqlSave(ctx context.Context) (_node *TestTarget, err error) { + if err := ttuo.check(); err != nil { + return _node, err + } + _spec := sqlgraph.NewUpdateSpec(testtarget.Table, testtarget.Columns, sqlgraph.NewFieldSpec(testtarget.FieldID, field.TypeInt64)) + id, ok := ttuo.mutation.ID() + if !ok { + return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "TestTarget.id" for update`)} + } + _spec.Node.ID.Value = id + if fields := ttuo.fields; len(fields) > 0 { + _spec.Node.Columns = make([]string, 0, len(fields)) + _spec.Node.Columns = append(_spec.Node.Columns, testtarget.FieldID) + for _, f := range fields { + if !testtarget.ValidColumn(f) { + return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)} + } + if f != testtarget.FieldID { + _spec.Node.Columns = append(_spec.Node.Columns, f) + } + } + } + if ps := ttuo.mutation.predicates; len(ps) > 0 { + _spec.Predicate = func(selector *sql.Selector) { + for i := range ps { + ps[i](selector) + } + } + } + _spec.AddModifiers(ttuo.modifiers...) + _node = &TestTarget{config: ttuo.config} + _spec.Assign = _node.assignValues + _spec.ScanValues = _node.scanValues + if err = sqlgraph.UpdateNode(ctx, ttuo.driver, _spec); err != nil { + if _, ok := err.(*sqlgraph.NotFoundError); ok { + err = &NotFoundError{testtarget.Label} + } else if sqlgraph.IsConstraintError(err) { + err = &ConstraintError{msg: err.Error(), wrap: err} + } + return nil, err + } + ttuo.mutation.done = true + return _node, nil +} diff --git a/ent/gen/ent/tx.go b/ent/gen/ent/tx.go index d7531473..0f0ff2e8 100644 --- a/ent/gen/ent/tx.go +++ b/ent/gen/ent/tx.go @@ -74,6 +74,8 @@ type Tx struct { TestResult *TestResultClient // TestSummary is the client for interacting with the TestSummary builders. TestSummary *TestSummaryClient + // TestTarget is the client for interacting with the TestTarget builders. + TestTarget *TestTargetClient // TimingMetrics is the client for interacting with the TimingMetrics builders. TimingMetrics *TimingMetricsClient @@ -237,6 +239,7 @@ func (tx *Tx) init() { tx.TargetMetrics = NewTargetMetricsClient(tx.config) tx.TestResult = NewTestResultClient(tx.config) tx.TestSummary = NewTestSummaryClient(tx.config) + tx.TestTarget = NewTestTargetClient(tx.config) tx.TimingMetrics = NewTimingMetricsClient(tx.config) } diff --git a/ent/schema/BUILD.bazel b/ent/schema/BUILD.bazel index 0db98487..d4363925 100644 --- a/ent/schema/BUILD.bazel +++ b/ent/schema/BUILD.bazel @@ -34,6 +34,7 @@ go_library( "targetmetrics.go", "testresult.go", "testsummary.go", + "testtarget.go", "timingmetrics.go", ], importpath = "github.com/buildbarn/bb-portal/ent/schema", diff --git a/ent/schema/target.go b/ent/schema/target.go index e8735ea3..929c4590 100644 --- a/ent/schema/target.go +++ b/ent/schema/target.go @@ -50,6 +50,9 @@ func (Target) Edges() []ent.Edge { Annotations( entsql.OnDelete(entsql.Cascade), ), + + edge.To("test_target", TestTarget.Type). + Unique(), } } diff --git a/ent/schema/testtarget.go b/ent/schema/testtarget.go new file mode 100644 index 00000000..1df7ee14 --- /dev/null +++ b/ent/schema/testtarget.go @@ -0,0 +1,42 @@ +package schema + +import ( + "entgo.io/ent" + "entgo.io/ent/dialect/entsql" + "entgo.io/ent/schema/edge" + "entgo.io/ent/schema/field" +) + +// TestTarget holds the schema definition for the TestTarget entity. +type TestTarget struct { + ent.Schema +} + +// Fields of the TestTarget. +func (TestTarget) Fields() []ent.Field { + return []ent.Field{ + field.Int64("target_id").Immutable(), + } +} + +// Edges of the TestTarget. +func (TestTarget) Edges() []ent.Edge { + return []ent.Edge{ + edge.From("target", Target.Type). + Ref("test_target"). + Field("target_id"). + Unique(). + Required(). + Immutable(). + Annotations( + entsql.OnDelete(entsql.Cascade), + ), + } +} + +// Mixin of the TestTarget. +func (TestTarget) Mixin() []ent.Mixin { + return []ent.Mixin{ + Int64IdMixin{}, + } +} diff --git a/frontend/src/components/TestGrid/index.tsx b/frontend/src/components/TestGrid/index.tsx index 1dc725cb..257375e4 100644 --- a/frontend/src/components/TestGrid/index.tsx +++ b/frontend/src/components/TestGrid/index.tsx @@ -31,7 +31,7 @@ const TestGrid: React.FC = () => { variables: { where: { and: [ - { hasInvocationTargetsWith: { hasTestSummary: true } }, + { hasTestTarget: true }, ...filterVariables, ], }, diff --git a/frontend/src/graphql/__generated__/graphql.ts b/frontend/src/graphql/__generated__/graphql.ts index bd9d30c7..f04059c5 100644 --- a/frontend/src/graphql/__generated__/graphql.ts +++ b/frontend/src/graphql/__generated__/graphql.ts @@ -2586,6 +2586,7 @@ export type Target = Node & { invocationTargetsTotalDurationMillis: Scalars['Int']['output']; label: Scalars['String']['output']; targetKind: Scalars['String']['output']; + testTarget?: Maybe; }; @@ -2708,6 +2709,9 @@ export type TargetWhereInput = { /** invocation_targets edge predicates */ hasInvocationTargets?: InputMaybe; hasInvocationTargetsWith?: InputMaybe>; + /** test_target edge predicates */ + hasTestTarget?: InputMaybe; + hasTestTargetWith?: InputMaybe>; /** id field predicates */ id?: InputMaybe; idGT?: InputMaybe; @@ -3104,6 +3108,40 @@ export type TestSummaryWhereInput = { totalRunDurationInMsNotNil?: InputMaybe; }; +export type TestTarget = Node & { + __typename?: 'TestTarget'; + id: Scalars['ID']['output']; + target: Target; + targetID: Scalars['ID']['output']; +}; + +/** + * TestTargetWhereInput is used for filtering TestTarget objects. + * Input was generated by ent. + */ +export type TestTargetWhereInput = { + and?: InputMaybe>; + /** target edge predicates */ + hasTarget?: InputMaybe; + hasTargetWith?: InputMaybe>; + /** id field predicates */ + id?: InputMaybe; + idGT?: InputMaybe; + idGTE?: InputMaybe; + idIn?: InputMaybe>; + idLT?: InputMaybe; + idLTE?: InputMaybe; + idNEQ?: InputMaybe; + idNotIn?: InputMaybe>; + not?: InputMaybe; + or?: InputMaybe>; + /** target_id field predicates */ + targetID?: InputMaybe; + targetIDIn?: InputMaybe>; + targetIDNEQ?: InputMaybe; + targetIDNotIn?: InputMaybe>; +}; + export type TimingMetrics = Node & { __typename?: 'TimingMetrics'; actionsExecutionStartInMs?: Maybe; diff --git a/internal/database/buildeventrecorder/save_target_completed.go b/internal/database/buildeventrecorder/save_target_completed.go index 9e925afb..b0ac5375 100644 --- a/internal/database/buildeventrecorder/save_target_completed.go +++ b/internal/database/buildeventrecorder/save_target_completed.go @@ -72,7 +72,7 @@ func (r *buildEventRecorder) saveTargetCompletedBatch(ctx context.Context, batch return util.StatusWrap(err, "Failed to bulk insert invocation targets") } - if err := r.createTestSummariesFromTargetCompletedChildren(ctx, tx, batch); err != nil { + if err := r.createTestSummariesFromTargetCompletedChildren(ctx, tx, batch, targetInfoMap); err != nil { return util.StatusWrap(err, "Failed to bulk insert test summaries") } @@ -155,7 +155,7 @@ func createInvocationTargetsBulk(ctx context.Context, isRealTime bool, invocatio return nil } -func (r *buildEventRecorder) createTestSummariesFromTargetCompletedChildren(ctx context.Context, tx database.Handle, batch []BuildEventWithInfo) error { +func (r *buildEventRecorder) createTestSummariesFromTargetCompletedChildren(ctx context.Context, tx database.Handle, batch []BuildEventWithInfo, targetInfoMap map[invocationTargetKey]completedTargetInfo) error { params := sqlc.CreateTestSummariesBulkParams{ BazelInvocationID: int64(r.InvocationDbID), InstanceNameID: int64(r.InstanceNameDbID), @@ -163,6 +163,8 @@ func (r *buildEventRecorder) createTestSummariesFromTargetCompletedChildren(ctx ConfigIds: make([]string, 0, len(batch)), } + var testTargetIDs []int64 + for _, x := range batch { be := x.Event targetCompletedID := be.GetId().GetTargetCompleted() @@ -173,6 +175,14 @@ func (r *buildEventRecorder) createTestSummariesFromTargetCompletedChildren(ctx params.Labels = append(params.Labels, targetCompletedID.Label) params.ConfigIds = append(params.ConfigIds, targetCompletedID.GetConfiguration().GetId()) + key := invocationTargetKey{ + label: targetCompletedID.Label, + aspect: stripParams(targetCompletedID.Aspect), + } + if targetInfo, ok := targetInfoMap[key]; ok { + testTargetIDs = append(testTargetIDs, int64(targetInfo.targetID)) + } + if targetCompletedID.Aspect != "" { slog.Warn( "Got TargetCompleted event with non-empty aspect and TestSummary child event. Buildbarn portal assumes that this should not happen, and the targets shown for this invocation might not be entirely correct.", @@ -189,6 +199,12 @@ func (r *buildEventRecorder) createTestSummariesFromTargetCompletedChildren(ctx return nil } + if len(testTargetIDs) > 0 { + if err := tx.Sqlc().CreateTestTargetsBulk(ctx, testTargetIDs); err != nil { + return util.StatusWrap(err, "Failed to bulk insert test targets") + } + } + affectedRows, err := tx.Sqlc().CreateTestSummariesBulk(ctx, params) if err != nil { return util.StatusWrap(err, "Failed to bulk insert test summaries") diff --git a/internal/database/dbcleanupservice/BUILD.bazel b/internal/database/dbcleanupservice/BUILD.bazel index 6c6ff962..d086b46a 100644 --- a/internal/database/dbcleanupservice/BUILD.bazel +++ b/internal/database/dbcleanupservice/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "lockinvocations.go", "next_slice.go", "remove_old_invocations.go", + "remove_orphaned_test_targets.go", "remove_target_kind_mappings.go", "remove_unused_targets.go", "removeinactiveusers.go", @@ -23,6 +24,7 @@ go_library( "//ent/gen/ent/incompletebuildlog", "//ent/gen/ent/target", "//ent/gen/ent/targetkindmapping", + "//ent/gen/ent/testtarget", "//internal/api/grpc/bes", "//internal/database", "//internal/database/dbauthservice", @@ -45,6 +47,7 @@ go_test( "dbcleanupservice_test.go", "lockinvocations_test.go", "remove_old_invocations_test.go", + "remove_orphaned_test_targets_test.go", "remove_target_kind_mappings_test.go", "remove_unused_targets_test.go", "removeinactiveusers_test.go", @@ -57,6 +60,7 @@ go_test( "//ent/gen/ent/incompletebuildlog", "//ent/gen/ent/invocationtarget", "//ent/gen/ent/runtime", + "//ent/gen/ent/testtarget", "//internal/database", "//internal/database/dbauthservice", "//internal/database/embedded", diff --git a/internal/database/dbcleanupservice/dbcleanupservice.go b/internal/database/dbcleanupservice/dbcleanupservice.go index 3cb6c4a4..3a820262 100644 --- a/internal/database/dbcleanupservice/dbcleanupservice.go +++ b/internal/database/dbcleanupservice/dbcleanupservice.go @@ -113,6 +113,9 @@ func (dc *DbCleanupService) StartDbCleanupService(ctx context.Context, group pro if err := dc.RemoveUnusedTargets(ctx); err != nil { slog.Warn("Failed to remove unused targets", "err", err) } + if err := dc.RemoveOrphanedTestTargets(ctx); err != nil { + slog.Warn("Failed to remove orphaned test targets", "err", err) + } } } }) diff --git a/internal/database/dbcleanupservice/remove_orphaned_test_targets.go b/internal/database/dbcleanupservice/remove_orphaned_test_targets.go new file mode 100644 index 00000000..f5424f1f --- /dev/null +++ b/internal/database/dbcleanupservice/remove_orphaned_test_targets.go @@ -0,0 +1,33 @@ +package dbcleanupservice + +import ( + "context" + + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" + "github.com/buildbarn/bb-portal/internal/database/sqlc" + "github.com/buildbarn/bb-storage/pkg/util" + "go.opentelemetry.io/otel/attribute" +) + +// RemoveOrphanedTestTargets remove the test target marker from targest +// which no longer are referred to as tests by any invocation. +func (dc *DbCleanupService) RemoveOrphanedTestTargets(ctx context.Context) error { + ctx, span := dc.tracer.Start(ctx, "DbCleanupService.RemoveOrphanedTestTargets") + defer span.End() + + start, count, err := dc.nextSlice(ctx, testtarget.Table) + if err != nil { + return err + } + + deleted, err := dc.db.Sqlc().DeleteOrphanedTestTargetsFromPages(ctx, sqlc.DeleteOrphanedTestTargetsFromPagesParams{ + FromPage: start, + Pages: count, + }) + if err != nil { + return util.StatusWrap(err, "Failed to remove orphaned test targets") + } + + span.SetAttributes(attribute.Int64("deleted_test_targets", deleted)) + return nil +} diff --git a/internal/database/dbcleanupservice/remove_orphaned_test_targets_test.go b/internal/database/dbcleanupservice/remove_orphaned_test_targets_test.go new file mode 100644 index 00000000..3c78347f --- /dev/null +++ b/internal/database/dbcleanupservice/remove_orphaned_test_targets_test.go @@ -0,0 +1,65 @@ +package dbcleanupservice_test + +import ( + "context" + "testing" + + "github.com/buildbarn/bb-portal/ent/gen/ent/testtarget" + "github.com/buildbarn/bb-portal/internal/database/dbauthservice" + "github.com/buildbarn/bb-portal/internal/mock" + "github.com/buildbarn/bb-portal/test/testutils" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/otel/trace/noop" + "go.uber.org/mock/gomock" +) + +func TestDbCleanupService_RemoveOrphanedTestTargets(t *testing.T) { + ctrl, ctx := gomock.WithContext(context.Background(), t) + ctx = dbauthservice.NewContextWithDbAuthServiceBypass(ctx) + db := testutils.SetupTestDB(t, dbProvider) + mockClock := mock.NewMockClock(ctrl) + + cleanupService, err := getNewDbCleanupService(db, mockClock, noop.NewTracerProvider()) + require.NoError(t, err) + + instance := testutils.CreateInstanceName(ctx, t, db.Ent(), "orphan_test_instance") + invocation, err := testutils.StartCreateInvocation(db.Ent(), instance).Save(ctx) + require.NoError(t, err) + + validTarget, err := db.Ent().Target.Create().SetInstanceName(instance).SetLabel("//app:valid").SetTargetKind("cc_test rule").SetAspect("").Save(ctx) + require.NoError(t, err) + + validTestTarget, err := db.Ent().TestTarget.Create().SetTarget(validTarget).Save(ctx) + require.NoError(t, err) + + validInvTarget, err := db.Ent().InvocationTarget.Create().SetBazelInvocation(invocation).SetTarget(validTarget).SetAbortReason("NONE").Save(ctx) + require.NoError(t, err) + + _, err = db.Ent().TestSummary.Create().SetInvocationTarget(validInvTarget).SetOverallStatus("PASSED").Save(ctx) + require.NoError(t, err) + + orphanedTarget, err := db.Ent().Target.Create().SetInstanceName(instance).SetLabel("//app:orphaned").SetTargetKind("cc_test rule").SetAspect("").Save(ctx) + require.NoError(t, err) + + orphanedTestTarget, err := db.Ent().TestTarget.Create().SetTarget(orphanedTarget).Save(ctx) + require.NoError(t, err) + + count, err := db.Ent().TestTarget.Query().Count(ctx) + require.NoError(t, err) + require.Equal(t, 2, count, "Both TestTargets should exist before cleanup") + + err = cleanupService.RemoveOrphanedTestTargets(ctx) + require.NoError(t, err) + + remainingCount, err := db.Ent().TestTarget.Query().Count(ctx) + require.NoError(t, err) + require.Equal(t, 1, remainingCount, "Exactly one TestTarget should remain") + + validExists, err := db.Ent().TestTarget.Query().Where(testtarget.IDEQ(validTestTarget.ID)).Exist(ctx) + require.NoError(t, err) + require.True(t, validExists, "The valid TestTarget must survive") + + orphanedExists, err := db.Ent().TestTarget.Query().Where(testtarget.IDEQ(orphanedTestTarget.ID)).Exist(ctx) + require.NoError(t, err) + require.False(t, orphanedExists, "The orphaned TestTarget must be deleted") +} diff --git a/internal/database/sqlc/BUILD.bazel b/internal/database/sqlc/BUILD.bazel index 5d10f091..78632ebb 100644 --- a/internal/database/sqlc/BUILD.bazel +++ b/internal/database/sqlc/BUILD.bazel @@ -17,6 +17,7 @@ go_library( "targets.sql.go", "test_result.sql.go", "test_summary.sql.go", + "test_targets.sql.go", ], importpath = "github.com/buildbarn/bb-portal/internal/database/sqlc", visibility = ["//:__subpackages__"], diff --git a/internal/database/sqlc/models.go b/internal/database/sqlc/models.go index 236b81d6..01e31834 100644 --- a/internal/database/sqlc/models.go +++ b/internal/database/sqlc/models.go @@ -374,6 +374,11 @@ type TestSummary struct { InvocationTargetTestSummary int64 } +type TestTarget struct { + ID int64 + TargetID int64 +} + type TimingMetric struct { ID int64 CpuTimeInMs sql.NullInt64 diff --git a/internal/database/sqlc/querier.go b/internal/database/sqlc/querier.go index 92a63302..64da1690 100644 --- a/internal/database/sqlc/querier.go +++ b/internal/database/sqlc/querier.go @@ -41,8 +41,10 @@ type Querier interface { CreateTestResultsBulk(ctx context.Context, arg CreateTestResultsBulkParams) (int64, error) // STAGE 2: Join the rest using the specific Target IDs we found CreateTestSummariesBulk(ctx context.Context, arg CreateTestSummariesBulkParams) (int64, error) + CreateTestTargetsBulk(ctx context.Context, targetIds []int64) error DeleteIncompleteLogsFromPages(ctx context.Context, arg DeleteIncompleteLogsFromPagesParams) (int64, error) DeleteOldInvocationsFromPages(ctx context.Context, arg DeleteOldInvocationsFromPagesParams) (int64, error) + DeleteOrphanedTestTargetsFromPages(ctx context.Context, arg DeleteOrphanedTestTargetsFromPagesParams) (int64, error) DeleteTargetKindMappingsFromPages(ctx context.Context, arg DeleteTargetKindMappingsFromPagesParams) (int64, error) DeleteUnusedTargetsFromPages(ctx context.Context, arg DeleteUnusedTargetsFromPagesParams) (int64, error) FindMappedTargets(ctx context.Context, arg FindMappedTargetsParams) ([]FindMappedTargetsRow, error) diff --git a/internal/database/sqlc/test_targets.sql.go b/internal/database/sqlc/test_targets.sql.go new file mode 100644 index 00000000..4e0e252a --- /dev/null +++ b/internal/database/sqlc/test_targets.sql.go @@ -0,0 +1,50 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: test_targets.sql + +package sqlc + +import ( + "context" + + "github.com/lib/pq" +) + +const createTestTargetsBulk = `-- name: CreateTestTargetsBulk :exec +INSERT INTO test_targets (target_id) +SELECT unnest($1::bigint[]) as target_id +ORDER BY target_id +ON CONFLICT (target_id) DO NOTHING +` + +func (q *Queries) CreateTestTargetsBulk(ctx context.Context, targetIds []int64) error { + _, err := q.db.ExecContext(ctx, createTestTargetsBulk, pq.Array(targetIds)) + return err +} + +const deleteOrphanedTestTargetsFromPages = `-- name: DeleteOrphanedTestTargetsFromPages :execrows +DELETE FROM test_targets +WHERE + ctid >= format('(%s,0)', $1::bigint)::tid + AND ctid < format('(%s,0)', $1::bigint + $2::bigint)::tid + AND NOT EXISTS ( + SELECT 1 + FROM invocation_targets it + JOIN test_summaries ts ON ts.invocation_target_test_summary = it.id + WHERE it.target_invocation_targets = test_targets.target_id + ) +` + +type DeleteOrphanedTestTargetsFromPagesParams struct { + FromPage int64 + Pages int64 +} + +func (q *Queries) DeleteOrphanedTestTargetsFromPages(ctx context.Context, arg DeleteOrphanedTestTargetsFromPagesParams) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteOrphanedTestTargetsFromPages, arg.FromPage, arg.Pages) + if err != nil { + return 0, err + } + return result.RowsAffected() +} diff --git a/internal/graphql/ent.resolvers.go b/internal/graphql/ent.resolvers.go index 5f755fd5..238d2ee1 100644 --- a/internal/graphql/ent.resolvers.go +++ b/internal/graphql/ent.resolvers.go @@ -240,6 +240,16 @@ func (r *testSummaryResolver) ID(ctx context.Context, obj *ent.TestSummary) (str return helpers.GraphQLIDFromTypeAndID("TestSummary", obj.ID), nil } +// ID is the resolver for the id field. +func (r *testTargetResolver) ID(ctx context.Context, obj *ent.TestTarget) (string, error) { + return helpers.GraphQLIDFromTypeAndID("TestTarget", obj.ID), nil +} + +// TargetID is the resolver for the targetID field. +func (r *testTargetResolver) TargetID(ctx context.Context, obj *ent.TestTarget) (string, error) { + panic(fmt.Errorf("not implemented: TargetID - targetID")) +} + // ID is the resolver for the id field. func (r *timingMetricsResolver) ID(ctx context.Context, obj *ent.TimingMetrics) (string, error) { return helpers.GraphQLIDFromTypeAndID("TimingMetrics", obj.ID), nil @@ -1252,6 +1262,66 @@ func (r *testSummaryWhereInputResolver) IDLte(ctx context.Context, obj *ent.Test panic(fmt.Errorf("not implemented: IDLte - idLTE")) } +// ID is the resolver for the id field. +func (r *testTargetWhereInputResolver) ID(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error { + panic(fmt.Errorf("not implemented: ID - id")) +} + +// IDNeq is the resolver for the idNEQ field. +func (r *testTargetWhereInputResolver) IDNeq(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error { + panic(fmt.Errorf("not implemented: IDNeq - idNEQ")) +} + +// IDIn is the resolver for the idIn field. +func (r *testTargetWhereInputResolver) IDIn(ctx context.Context, obj *ent.TestTargetWhereInput, data []string) error { + panic(fmt.Errorf("not implemented: IDIn - idIn")) +} + +// IDNotIn is the resolver for the idNotIn field. +func (r *testTargetWhereInputResolver) IDNotIn(ctx context.Context, obj *ent.TestTargetWhereInput, data []string) error { + panic(fmt.Errorf("not implemented: IDNotIn - idNotIn")) +} + +// IDGt is the resolver for the idGT field. +func (r *testTargetWhereInputResolver) IDGt(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error { + panic(fmt.Errorf("not implemented: IDGt - idGT")) +} + +// IDGte is the resolver for the idGTE field. +func (r *testTargetWhereInputResolver) IDGte(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error { + panic(fmt.Errorf("not implemented: IDGte - idGTE")) +} + +// IDLt is the resolver for the idLT field. +func (r *testTargetWhereInputResolver) IDLt(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error { + panic(fmt.Errorf("not implemented: IDLt - idLT")) +} + +// IDLte is the resolver for the idLTE field. +func (r *testTargetWhereInputResolver) IDLte(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error { + panic(fmt.Errorf("not implemented: IDLte - idLTE")) +} + +// TargetID is the resolver for the targetID field. +func (r *testTargetWhereInputResolver) TargetID(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error { + panic(fmt.Errorf("not implemented: TargetID - targetID")) +} + +// TargetIdneq is the resolver for the targetIDNEQ field. +func (r *testTargetWhereInputResolver) TargetIdneq(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error { + panic(fmt.Errorf("not implemented: TargetIdneq - targetIDNEQ")) +} + +// TargetIDIn is the resolver for the targetIDIn field. +func (r *testTargetWhereInputResolver) TargetIDIn(ctx context.Context, obj *ent.TestTargetWhereInput, data []string) error { + panic(fmt.Errorf("not implemented: TargetIDIn - targetIDIn")) +} + +// TargetIDNotIn is the resolver for the targetIDNotIn field. +func (r *testTargetWhereInputResolver) TargetIDNotIn(ctx context.Context, obj *ent.TestTargetWhereInput, data []string) error { + panic(fmt.Errorf("not implemented: TargetIDNotIn - targetIDNotIn")) +} + // ID is the resolver for the id field. func (r *timingMetricsWhereInputResolver) ID(ctx context.Context, obj *ent.TimingMetricsWhereInput, data *string) error { panic(fmt.Errorf("not implemented: ID - id")) @@ -1380,6 +1450,9 @@ func (r *Resolver) TestResult() TestResultResolver { return &testResultResolver{ // TestSummary returns TestSummaryResolver implementation. func (r *Resolver) TestSummary() TestSummaryResolver { return &testSummaryResolver{r} } +// TestTarget returns TestTargetResolver implementation. +func (r *Resolver) TestTarget() TestTargetResolver { return &testTargetResolver{r} } + // TimingMetrics returns TimingMetricsResolver implementation. func (r *Resolver) TimingMetrics() TimingMetricsResolver { return &timingMetricsResolver{r} } @@ -1502,6 +1575,11 @@ func (r *Resolver) TestSummaryWhereInput() TestSummaryWhereInputResolver { return &testSummaryWhereInputResolver{r} } +// TestTargetWhereInput returns TestTargetWhereInputResolver implementation. +func (r *Resolver) TestTargetWhereInput() TestTargetWhereInputResolver { + return &testTargetWhereInputResolver{r} +} + // TimingMetricsWhereInput returns TimingMetricsWhereInputResolver implementation. func (r *Resolver) TimingMetricsWhereInput() TimingMetricsWhereInputResolver { return &timingMetricsWhereInputResolver{r} @@ -1534,6 +1612,7 @@ type ( targetMetricsResolver struct{ *Resolver } testResultResolver struct{ *Resolver } testSummaryResolver struct{ *Resolver } + testTargetResolver struct{ *Resolver } timingMetricsResolver struct{ *Resolver } actionCacheStatisticsWhereInputResolver struct{ *Resolver } actionDataWhereInputResolver struct{ *Resolver } @@ -1560,5 +1639,6 @@ type ( targetWhereInputResolver struct{ *Resolver } testResultWhereInputResolver struct{ *Resolver } testSummaryWhereInputResolver struct{ *Resolver } + testTargetWhereInputResolver struct{ *Resolver } timingMetricsWhereInputResolver struct{ *Resolver } ) diff --git a/internal/graphql/schema/ent.graphql b/internal/graphql/schema/ent.graphql index 9ac148e8..a62c7e86 100644 --- a/internal/graphql/schema/ent.graphql +++ b/internal/graphql/schema/ent.graphql @@ -3072,6 +3072,7 @@ type Target implements Node { """ where: InvocationTargetWhereInput ): InvocationTargetConnection! + testTarget: TestTarget } """ A connection to a list of items. @@ -3251,6 +3252,11 @@ input TargetWhereInput { """ hasInvocationTargets: Boolean hasInvocationTargetsWith: [InvocationTargetWhereInput!] + """ + test_target edge predicates + """ + hasTestTarget: Boolean + hasTestTargetWith: [TestTargetWhereInput!] } type TestResult implements Node { id: ID! @@ -3669,6 +3675,43 @@ input TestSummaryWhereInput { hasTestResults: Boolean hasTestResultsWith: [TestResultWhereInput!] } +type TestTarget implements Node { + id: ID! + targetID: ID! + target: Target! +} +""" +TestTargetWhereInput is used for filtering TestTarget objects. +Input was generated by ent. +""" +input TestTargetWhereInput { + not: TestTargetWhereInput + and: [TestTargetWhereInput!] + or: [TestTargetWhereInput!] + """ + id field predicates + """ + id: ID + idNEQ: ID + idIn: [ID!] + idNotIn: [ID!] + idGT: ID + idGTE: ID + idLT: ID + idLTE: ID + """ + target_id field predicates + """ + targetID: ID + targetIDNEQ: ID + targetIDIn: [ID!] + targetIDNotIn: [ID!] + """ + target edge predicates + """ + hasTarget: Boolean + hasTargetWith: [TargetWhereInput!] +} type TimingMetrics implements Node { id: ID! cpuTimeInMs: Int diff --git a/internal/graphql/server_gen.go b/internal/graphql/server_gen.go index a8c98ca1..6a753d14 100644 --- a/internal/graphql/server_gen.go +++ b/internal/graphql/server_gen.go @@ -72,6 +72,7 @@ type ResolverRoot interface { TargetMetrics() TargetMetricsResolver TestResult() TestResultResolver TestSummary() TestSummaryResolver + TestTarget() TestTargetResolver TimingMetrics() TimingMetricsResolver ActionCacheStatisticsWhereInput() ActionCacheStatisticsWhereInputResolver ActionDataWhereInput() ActionDataWhereInputResolver @@ -98,6 +99,7 @@ type ResolverRoot interface { TargetWhereInput() TargetWhereInputResolver TestResultWhereInput() TestResultWhereInputResolver TestSummaryWhereInput() TestSummaryWhereInputResolver + TestTargetWhereInput() TestTargetWhereInputResolver TimingMetricsWhereInput() TimingMetricsWhereInputResolver } @@ -434,6 +436,7 @@ type ComplexityRoot struct { InvocationTargetsTotalDurationMillis func(childComplexity int) int Label func(childComplexity int) int TargetKind func(childComplexity int) int + TestTarget func(childComplexity int) int } TargetConnection struct { @@ -500,6 +503,12 @@ type ComplexityRoot struct { Node func(childComplexity int) int } + TestTarget struct { + ID func(childComplexity int) int + Target func(childComplexity int) int + TargetID func(childComplexity int) int + } + TimingMetrics struct { ActionsExecutionStartInMs func(childComplexity int) int AnalysisPhaseTimeInMs func(childComplexity int) int @@ -617,6 +626,10 @@ type TestResultResolver interface { type TestSummaryResolver interface { ID(ctx context.Context, obj *ent.TestSummary) (string, error) } +type TestTargetResolver interface { + ID(ctx context.Context, obj *ent.TestTarget) (string, error) + TargetID(ctx context.Context, obj *ent.TestTarget) (string, error) +} type TimingMetricsResolver interface { ID(ctx context.Context, obj *ent.TimingMetrics) (string, error) } @@ -871,6 +884,20 @@ type TestSummaryWhereInputResolver interface { IDLt(ctx context.Context, obj *ent.TestSummaryWhereInput, data *string) error IDLte(ctx context.Context, obj *ent.TestSummaryWhereInput, data *string) error } +type TestTargetWhereInputResolver interface { + ID(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error + IDNeq(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error + IDIn(ctx context.Context, obj *ent.TestTargetWhereInput, data []string) error + IDNotIn(ctx context.Context, obj *ent.TestTargetWhereInput, data []string) error + IDGt(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error + IDGte(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error + IDLt(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error + IDLte(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error + TargetID(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error + TargetIdneq(ctx context.Context, obj *ent.TestTargetWhereInput, data *string) error + TargetIDIn(ctx context.Context, obj *ent.TestTargetWhereInput, data []string) error + TargetIDNotIn(ctx context.Context, obj *ent.TestTargetWhereInput, data []string) error +} type TimingMetricsWhereInputResolver interface { ID(ctx context.Context, obj *ent.TimingMetricsWhereInput, data *string) error IDNeq(ctx context.Context, obj *ent.TimingMetricsWhereInput, data *string) error @@ -2637,6 +2664,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.Target.TargetKind(childComplexity), true + case "Target.testTarget": + if e.complexity.Target.TestTarget == nil { + break + } + + return e.complexity.Target.TestTarget(childComplexity), true + case "TargetConnection.edges": if e.complexity.TargetConnection.Edges == nil { break @@ -2938,6 +2972,27 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin return e.complexity.TestSummaryEdge.Node(childComplexity), true + case "TestTarget.id": + if e.complexity.TestTarget.ID == nil { + break + } + + return e.complexity.TestTarget.ID(childComplexity), true + + case "TestTarget.target": + if e.complexity.TestTarget.Target == nil { + break + } + + return e.complexity.TestTarget.Target(childComplexity), true + + case "TestTarget.targetID": + if e.complexity.TestTarget.TargetID == nil { + break + } + + return e.complexity.TestTarget.TargetID(childComplexity), true + case "TimingMetrics.actionsExecutionStartInMs": if e.complexity.TimingMetrics.ActionsExecutionStartInMs == nil { break @@ -3045,6 +3100,7 @@ func (e *executableSchema) Exec(ctx context.Context) graphql.ResponseHandler { ec.unmarshalInputTestResultWhereInput, ec.unmarshalInputTestSummaryOrder, ec.unmarshalInputTestSummaryWhereInput, + ec.unmarshalInputTestTargetWhereInput, ec.unmarshalInputTimingMetricsWhereInput, ) first := true @@ -11409,6 +11465,8 @@ func (ec *executionContext) fieldContext_InstanceName_targets(_ context.Context, return ec.fieldContext_Target_instanceName(ctx, field) case "invocationTargets": return ec.fieldContext_Target_invocationTargets(ctx, field) + case "testTarget": + return ec.fieldContext_Target_testTarget(ctx, field) case "invocationTargetsTotalDurationMillis": return ec.fieldContext_Target_invocationTargetsTotalDurationMillis(ctx, field) } @@ -11912,6 +11970,8 @@ func (ec *executionContext) fieldContext_InvocationTarget_target(_ context.Conte return ec.fieldContext_Target_instanceName(ctx, field) case "invocationTargets": return ec.fieldContext_Target_invocationTargets(ctx, field) + case "testTarget": + return ec.fieldContext_Target_testTarget(ctx, field) case "invocationTargetsTotalDurationMillis": return ec.fieldContext_Target_invocationTargetsTotalDurationMillis(ctx, field) } @@ -14535,6 +14595,8 @@ func (ec *executionContext) fieldContext_Query_getTarget(ctx context.Context, fi return ec.fieldContext_Target_instanceName(ctx, field) case "invocationTargets": return ec.fieldContext_Target_invocationTargets(ctx, field) + case "testTarget": + return ec.fieldContext_Target_testTarget(ctx, field) case "invocationTargetsTotalDurationMillis": return ec.fieldContext_Target_invocationTargetsTotalDurationMillis(ctx, field) } @@ -16433,6 +16495,55 @@ func (ec *executionContext) fieldContext_Target_invocationTargets(ctx context.Co return fc, nil } +func (ec *executionContext) _Target_testTarget(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_Target_testTarget(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.TestTarget(ctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*ent.TestTarget) + fc.Result = res + return ec.marshalOTestTarget2ᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTarget(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_Target_testTarget(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "Target", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_TestTarget_id(ctx, field) + case "targetID": + return ec.fieldContext_TestTarget_targetID(ctx, field) + case "target": + return ec.fieldContext_TestTarget_target(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type TestTarget", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _Target_invocationTargetsTotalDurationMillis(ctx context.Context, field graphql.CollectedField, obj *ent.Target) (ret graphql.Marshaler) { fc, err := ec.fieldContext_Target_invocationTargetsTotalDurationMillis(ctx, field) if err != nil { @@ -16670,6 +16781,8 @@ func (ec *executionContext) fieldContext_TargetEdge_node(_ context.Context, fiel return ec.fieldContext_Target_instanceName(ctx, field) case "invocationTargets": return ec.fieldContext_Target_invocationTargets(ctx, field) + case "testTarget": + return ec.fieldContext_Target_testTarget(ctx, field) case "invocationTargetsTotalDurationMillis": return ec.fieldContext_Target_invocationTargetsTotalDurationMillis(ctx, field) } @@ -18462,6 +18575,156 @@ func (ec *executionContext) fieldContext_TestSummaryEdge_cursor(_ context.Contex return fc, nil } +func (ec *executionContext) _TestTarget_id(ctx context.Context, field graphql.CollectedField, obj *ent.TestTarget) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TestTarget_id(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.TestTarget().ID(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TestTarget_id(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TestTarget", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _TestTarget_targetID(ctx context.Context, field graphql.CollectedField, obj *ent.TestTarget) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TestTarget_targetID(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return ec.resolvers.TestTarget().TargetID(rctx, obj) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(string) + fc.Result = res + return ec.marshalNID2string(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TestTarget_targetID(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TestTarget", + Field: field, + IsMethod: true, + IsResolver: true, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type ID does not have child fields") + }, + } + return fc, nil +} + +func (ec *executionContext) _TestTarget_target(ctx context.Context, field graphql.CollectedField, obj *ent.TestTarget) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_TestTarget_target(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) { + ctx = rctx // use context from middleware stack in children + return obj.Target(ctx) + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + if !graphql.HasFieldError(ctx, fc) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(*ent.Target) + fc.Result = res + return ec.marshalNTarget2ᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTarget(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_TestTarget_target(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "TestTarget", + Field: field, + IsMethod: true, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + switch field.Name { + case "id": + return ec.fieldContext_Target_id(ctx, field) + case "label": + return ec.fieldContext_Target_label(ctx, field) + case "aspect": + return ec.fieldContext_Target_aspect(ctx, field) + case "targetKind": + return ec.fieldContext_Target_targetKind(ctx, field) + case "instanceName": + return ec.fieldContext_Target_instanceName(ctx, field) + case "invocationTargets": + return ec.fieldContext_Target_invocationTargets(ctx, field) + case "testTarget": + return ec.fieldContext_Target_testTarget(ctx, field) + case "invocationTargetsTotalDurationMillis": + return ec.fieldContext_Target_invocationTargetsTotalDurationMillis(ctx, field) + } + return nil, fmt.Errorf("no field named %q was found under type Target", field.Name) + }, + } + return fc, nil +} + func (ec *executionContext) _TimingMetrics_id(ctx context.Context, field graphql.CollectedField, obj *ent.TimingMetrics) (ret graphql.Marshaler) { fc, err := ec.fieldContext_TimingMetrics_id(ctx, field) if err != nil { @@ -33598,7 +33861,7 @@ func (ec *executionContext) unmarshalInputTargetWhereInput(ctx context.Context, asMap[k] = v } - fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "label", "labelNEQ", "labelIn", "labelNotIn", "labelGT", "labelGTE", "labelLT", "labelLTE", "labelContains", "labelHasPrefix", "labelHasSuffix", "labelEqualFold", "labelContainsFold", "aspect", "aspectNEQ", "aspectIn", "aspectNotIn", "aspectGT", "aspectGTE", "aspectLT", "aspectLTE", "aspectContains", "aspectHasPrefix", "aspectHasSuffix", "aspectEqualFold", "aspectContainsFold", "targetKind", "targetKindNEQ", "targetKindIn", "targetKindNotIn", "targetKindGT", "targetKindGTE", "targetKindLT", "targetKindLTE", "targetKindContains", "targetKindHasPrefix", "targetKindHasSuffix", "targetKindEqualFold", "targetKindContainsFold", "hasInstanceName", "hasInstanceNameWith", "hasInvocationTargets", "hasInvocationTargetsWith"} + fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "label", "labelNEQ", "labelIn", "labelNotIn", "labelGT", "labelGTE", "labelLT", "labelLTE", "labelContains", "labelHasPrefix", "labelHasSuffix", "labelEqualFold", "labelContainsFold", "aspect", "aspectNEQ", "aspectIn", "aspectNotIn", "aspectGT", "aspectGTE", "aspectLT", "aspectLTE", "aspectContains", "aspectHasPrefix", "aspectHasSuffix", "aspectEqualFold", "aspectContainsFold", "targetKind", "targetKindNEQ", "targetKindIn", "targetKindNotIn", "targetKindGT", "targetKindGTE", "targetKindLT", "targetKindLTE", "targetKindContains", "targetKindHasPrefix", "targetKindHasSuffix", "targetKindEqualFold", "targetKindContainsFold", "hasInstanceName", "hasInstanceNameWith", "hasInvocationTargets", "hasInvocationTargetsWith", "hasTestTarget", "hasTestTargetWith"} for _, k := range fieldsInOrder { v, ok := asMap[k] if !ok { @@ -33999,6 +34262,20 @@ func (ec *executionContext) unmarshalInputTargetWhereInput(ctx context.Context, return it, err } it.HasInvocationTargetsWith = data + case "hasTestTarget": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasTestTarget")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.HasTestTarget = data + case "hasTestTargetWith": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasTestTargetWith")) + data, err := ec.unmarshalOTestTargetWhereInput2ᚕᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTargetWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.HasTestTargetWith = data } } @@ -35830,6 +36107,169 @@ func (ec *executionContext) unmarshalInputTestSummaryWhereInput(ctx context.Cont return it, nil } +func (ec *executionContext) unmarshalInputTestTargetWhereInput(ctx context.Context, obj any) (ent.TestTargetWhereInput, error) { + var it ent.TestTargetWhereInput + asMap := map[string]any{} + for k, v := range obj.(map[string]any) { + asMap[k] = v + } + + fieldsInOrder := [...]string{"not", "and", "or", "id", "idNEQ", "idIn", "idNotIn", "idGT", "idGTE", "idLT", "idLTE", "targetID", "targetIDNEQ", "targetIDIn", "targetIDNotIn", "hasTarget", "hasTargetWith"} + for _, k := range fieldsInOrder { + v, ok := asMap[k] + if !ok { + continue + } + switch k { + case "not": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("not")) + data, err := ec.unmarshalOTestTargetWhereInput2ᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTargetWhereInput(ctx, v) + if err != nil { + return it, err + } + it.Not = data + case "and": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("and")) + data, err := ec.unmarshalOTestTargetWhereInput2ᚕᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTargetWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.And = data + case "or": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("or")) + data, err := ec.unmarshalOTestTargetWhereInput2ᚕᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTargetWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.Or = data + case "id": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("id")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().ID(ctx, &it, data); err != nil { + return it, err + } + case "idNEQ": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNEQ")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().IDNeq(ctx, &it, data); err != nil { + return it, err + } + case "idIn": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idIn")) + data, err := ec.unmarshalOID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().IDIn(ctx, &it, data); err != nil { + return it, err + } + case "idNotIn": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idNotIn")) + data, err := ec.unmarshalOID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().IDNotIn(ctx, &it, data); err != nil { + return it, err + } + case "idGT": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGT")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().IDGt(ctx, &it, data); err != nil { + return it, err + } + case "idGTE": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idGTE")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().IDGte(ctx, &it, data); err != nil { + return it, err + } + case "idLT": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLT")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().IDLt(ctx, &it, data); err != nil { + return it, err + } + case "idLTE": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("idLTE")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().IDLte(ctx, &it, data); err != nil { + return it, err + } + case "targetID": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("targetID")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().TargetID(ctx, &it, data); err != nil { + return it, err + } + case "targetIDNEQ": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("targetIDNEQ")) + data, err := ec.unmarshalOID2ᚖstring(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().TargetIdneq(ctx, &it, data); err != nil { + return it, err + } + case "targetIDIn": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("targetIDIn")) + data, err := ec.unmarshalOID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().TargetIDIn(ctx, &it, data); err != nil { + return it, err + } + case "targetIDNotIn": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("targetIDNotIn")) + data, err := ec.unmarshalOID2ᚕstringᚄ(ctx, v) + if err != nil { + return it, err + } + if err = ec.resolvers.TestTargetWhereInput().TargetIDNotIn(ctx, &it, data); err != nil { + return it, err + } + case "hasTarget": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasTarget")) + data, err := ec.unmarshalOBoolean2ᚖbool(ctx, v) + if err != nil { + return it, err + } + it.HasTarget = data + case "hasTargetWith": + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithField("hasTargetWith")) + data, err := ec.unmarshalOTargetWhereInput2ᚕᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTargetWhereInputᚄ(ctx, v) + if err != nil { + return it, err + } + it.HasTargetWith = data + } + } + + return it, nil +} + func (ec *executionContext) unmarshalInputTimingMetricsWhereInput(ctx context.Context, obj any) (ent.TimingMetricsWhereInput, error) { var it ent.TimingMetricsWhereInput asMap := map[string]any{} @@ -36320,6 +36760,11 @@ func (ec *executionContext) _Node(ctx context.Context, sel ast.SelectionSet, obj return graphql.Null } return ec._TimingMetrics(ctx, sel, obj) + case *ent.TestTarget: + if obj == nil { + return graphql.Null + } + return ec._TestTarget(ctx, sel, obj) case *ent.TestSummary: if obj == nil { return graphql.Null @@ -40908,6 +41353,39 @@ func (ec *executionContext) _Target(ctx context.Context, sel ast.SelectionSet, o continue } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "testTarget": + field := field + + innerFunc := func(ctx context.Context, _ *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._Target_testTarget(ctx, field, obj) + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) case "invocationTargetsTotalDurationMillis": field := field @@ -41551,6 +42029,148 @@ func (ec *executionContext) _TestSummaryEdge(ctx context.Context, sel ast.Select return out } +var testTargetImplementors = []string{"TestTarget", "Node"} + +func (ec *executionContext) _TestTarget(ctx context.Context, sel ast.SelectionSet, obj *ent.TestTarget) graphql.Marshaler { + fields := graphql.CollectFields(ec.OperationContext, sel, testTargetImplementors) + + out := graphql.NewFieldSet(fields) + deferred := make(map[string]*graphql.FieldSet) + for i, field := range fields { + switch field.Name { + case "__typename": + out.Values[i] = graphql.MarshalString("TestTarget") + case "id": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._TestTarget_id(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "targetID": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._TestTarget_targetID(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + case "target": + field := field + + innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) { + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + } + }() + res = ec._TestTarget_target(ctx, field, obj) + if res == graphql.Null { + atomic.AddUint32(&fs.Invalids, 1) + } + return res + } + + if field.Deferrable != nil { + dfs, ok := deferred[field.Deferrable.Label] + di := 0 + if ok { + dfs.AddField(field) + di = len(dfs.Values) - 1 + } else { + dfs = graphql.NewFieldSet([]graphql.CollectedField{field}) + deferred[field.Deferrable.Label] = dfs + } + dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler { + return innerFunc(ctx, dfs) + }) + + // don't run the out.Concurrently() call below + out.Values[i] = graphql.Null + continue + } + + out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) }) + default: + panic("unknown field " + strconv.Quote(field.Name)) + } + } + out.Dispatch(ctx) + if out.Invalids > 0 { + return graphql.Null + } + + atomic.AddInt32(&ec.deferred, int32(len(deferred))) + + for label, dfs := range deferred { + ec.processDeferredGroup(graphql.DeferredGroup{ + Label: label, + Path: graphql.GetPath(ctx), + FieldSet: dfs, + Context: ctx, + }) + } + + return out +} + var timingMetricsImplementors = []string{"TimingMetrics", "Node"} func (ec *executionContext) _TimingMetrics(ctx context.Context, sel ast.SelectionSet, obj *ent.TimingMetrics) graphql.Marshaler { @@ -42657,6 +43277,11 @@ func (ec *executionContext) unmarshalNTestSummaryWhereInput2ᚖgithubᚗcomᚋbu return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) unmarshalNTestTargetWhereInput2ᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTargetWhereInput(ctx context.Context, v any) (*ent.TestTargetWhereInput, error) { + res, err := ec.unmarshalInputTestTargetWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalNTime2timeᚐTime(ctx context.Context, v any) (time.Time, error) { res, err := graphql.UnmarshalTime(v) return res, graphql.ErrorOnPath(ctx, err) @@ -45193,6 +45818,39 @@ func (ec *executionContext) unmarshalOTestSummaryWhereInput2ᚖgithubᚗcomᚋbu return &res, graphql.ErrorOnPath(ctx, err) } +func (ec *executionContext) marshalOTestTarget2ᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTarget(ctx context.Context, sel ast.SelectionSet, v *ent.TestTarget) graphql.Marshaler { + if v == nil { + return graphql.Null + } + return ec._TestTarget(ctx, sel, v) +} + +func (ec *executionContext) unmarshalOTestTargetWhereInput2ᚕᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTargetWhereInputᚄ(ctx context.Context, v any) ([]*ent.TestTargetWhereInput, error) { + if v == nil { + return nil, nil + } + var vSlice []any + vSlice = graphql.CoerceList(v) + var err error + res := make([]*ent.TestTargetWhereInput, len(vSlice)) + for i := range vSlice { + ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i)) + res[i], err = ec.unmarshalNTestTargetWhereInput2ᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTargetWhereInput(ctx, vSlice[i]) + if err != nil { + return nil, err + } + } + return res, nil +} + +func (ec *executionContext) unmarshalOTestTargetWhereInput2ᚖgithubᚗcomᚋbuildbarnᚋbbᚑportalᚋentᚋgenᚋentᚐTestTargetWhereInput(ctx context.Context, v any) (*ent.TestTargetWhereInput, error) { + if v == nil { + return nil, nil + } + res, err := ec.unmarshalInputTestTargetWhereInput(ctx, v) + return &res, graphql.ErrorOnPath(ctx, err) +} + func (ec *executionContext) unmarshalOTime2timeᚐTime(ctx context.Context, v any) (time.Time, error) { res, err := graphql.UnmarshalTime(v) return res, graphql.ErrorOnPath(ctx, err) diff --git a/sql/migrations/schema.sql b/sql/migrations/schema.sql index 6c037c3a..ab6acb18 100644 --- a/sql/migrations/schema.sql +++ b/sql/migrations/schema.sql @@ -98,6 +98,8 @@ CREATE TABLE "test_summaries" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDEN CREATE INDEX "testsummary_invocation_target_test_summary" ON "test_summaries" ("invocation_target_test_summary"); CREATE TABLE "test_results" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "run" integer NOT NULL, "shard" integer NOT NULL, "attempt" integer NOT NULL, "status" character varying NULL, "status_details" character varying NULL, "cached_locally" boolean NULL, "test_attempt_start" timestamptz NULL, "test_attempt_duration_in_ms" bigint NULL, "warning" jsonb NULL, "strategy" character varying NULL, "cached_remotely" boolean NULL, "exit_code" integer NULL, "hostname" character varying NULL, "timing_breakdown" jsonb NULL, "test_summary_test_results" bigint NOT NULL, PRIMARY KEY ("id"), CONSTRAINT "test_results_test_summaries_test_results" FOREIGN KEY ("test_summary_test_results") REFERENCES "test_summaries" ("id") ON DELETE CASCADE); CREATE INDEX "testresult_test_summary_test_results" ON "test_results" ("test_summary_test_results"); +CREATE TABLE "test_targets" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "target_id" bigint NOT NULL, PRIMARY KEY ("id"), CONSTRAINT "test_targets_targets_test_target" FOREIGN KEY ("target_id") REFERENCES "targets" ("id") ON DELETE NO ACTION); +CREATE UNIQUE INDEX "test_targets_target_id_key" ON "test_targets" ("target_id"); CREATE TABLE "timing_metrics" ("id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "cpu_time_in_ms" bigint NULL, "wall_time_in_ms" bigint NULL, "analysis_phase_time_in_ms" bigint NULL, "execution_phase_time_in_ms" bigint NULL, "actions_execution_start_in_ms" bigint NULL, "metrics_timing_metrics" bigint NULL, PRIMARY KEY ("id"), CONSTRAINT "timing_metrics_metrics_timing_metrics" FOREIGN KEY ("metrics_timing_metrics") REFERENCES "metrics" ("id") ON DELETE CASCADE); CREATE UNIQUE INDEX "timing_metrics_metrics_timing_metrics_key" ON "timing_metrics" ("metrics_timing_metrics"); CREATE INDEX "timingmetrics_metrics_timing_metrics" ON "timing_metrics" ("metrics_timing_metrics"); diff --git a/sql/queries/test_targets.sql b/sql/queries/test_targets.sql new file mode 100644 index 00000000..a48a063e --- /dev/null +++ b/sql/queries/test_targets.sql @@ -0,0 +1,17 @@ +-- name: CreateTestTargetsBulk :exec +INSERT INTO test_targets (target_id) +SELECT unnest(@target_ids::bigint[]) as target_id +ORDER BY target_id +ON CONFLICT (target_id) DO NOTHING; + +-- name: DeleteOrphanedTestTargetsFromPages :execrows +DELETE FROM test_targets +WHERE + ctid >= format('(%s,0)', sqlc.arg(from_page)::bigint)::tid + AND ctid < format('(%s,0)', sqlc.arg(from_page)::bigint + sqlc.arg(pages)::bigint)::tid + AND NOT EXISTS ( + SELECT 1 + FROM invocation_targets it + JOIN test_summaries ts ON ts.invocation_target_test_summary = it.id + WHERE it.target_invocation_targets = test_targets.target_id + );