Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/api/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ func (config *ReleaseBuildConfiguration) Default() {
for i := range config.Tests {
defTest(&config.Tests[i])
}

if config.BuildType == "" {
config.BuildType = BuildTypeOpenshift
}
}

// ImageStreamFor guesses at the ImageStream that will hold a tag.
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type ReleaseBuildConfiguration struct {

InputConfiguration `json:",inline"`

BuildType string `json:"build_type,omitempty"`
// BinaryBuildCommands will create a "bin" image based on "src" that
// contains the output of this command. This allows reuse of binary artifacts
// across other steps. If empty, no "bin" image will be created.
Expand Down Expand Up @@ -1822,3 +1823,8 @@ type ClusterClaimOwnerDetails struct {
const (
EphemeralClusterTestDoneSignalSecretName = "test-done-signal"
)

const (
// BuildTypeOpenshift indicates the Openshift Build
BuildTypeOpenshift = "openshift"
)
2 changes: 1 addition & 1 deletion pkg/defaults/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func FromConfig(ctx context.Context, cfg *Config) ([]api.Step, []api.Step, error
if err != nil {
return nil, nil, fmt.Errorf("could not get build client for cluster config: %w", err)
}
buildClient := steps.NewBuildClient(client, buildGetter.RESTClient(), cfg.NodeArchitectures, cfg.ManifestToolDockerCfg, cfg.LocalRegistryDNS, cfg.MetricsAgent)
buildClient := steps.NewBuildClient(client, api.BuildTypeOpenshift, buildGetter.RESTClient(), cfg.NodeArchitectures, cfg.ManifestToolDockerCfg, cfg.LocalRegistryDNS, cfg.MetricsAgent)
Comment thread
hector-vido marked this conversation as resolved.

coreGetter, err := coreclientset.NewForConfig(cfg.ClusterConfig)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/defaults/defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@ func TestFromConfig(t *testing.T) {
t.Fatal(err)
}
}
buildClient := steps.NewBuildClient(client, nil, nil, "", "", nil)
buildClient := steps.NewBuildClient(client, api.BuildTypeOpenshift, nil, nil, "", "", nil)
podClient := kubernetes.NewPodClient(client, nil, nil, 0, nil)

clusterPool := hivev1.ClusterPool{
Expand Down
9 changes: 8 additions & 1 deletion pkg/steps/build_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type BuildClient interface {
ManifestToolDockerCfg() string
LocalRegistryDNS() string
MetricsAgent() *metrics.MetricsAgent
BuildType() string
}

type buildClient struct {
Expand All @@ -30,16 +31,18 @@ type buildClient struct {
manifestToolDockerCfg string
localRegistryDNS string
metricsAgent *metrics.MetricsAgent
buildType string
}

func NewBuildClient(client loggingclient.LoggingClient, restClient rest.Interface, nodeArchitectures []string, manifestToolDockerCfg, localRegistryDNS string, metricsAgent *metrics.MetricsAgent) BuildClient {
func NewBuildClient(client loggingclient.LoggingClient, buildType string, restClient rest.Interface, nodeArchitectures []string, manifestToolDockerCfg, localRegistryDNS string, metricsAgent *metrics.MetricsAgent) BuildClient {
return &buildClient{
LoggingClient: client,
client: restClient,
nodeArchitectures: nodeArchitectures,
manifestToolDockerCfg: manifestToolDockerCfg,
localRegistryDNS: localRegistryDNS,
metricsAgent: metricsAgent,
buildType: buildType,
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Expand Down Expand Up @@ -72,3 +75,7 @@ func (c *buildClient) MetricsAgent() *metrics.MetricsAgent {
func (c *buildClient) Client() loggingclient.LoggingClient {
return c.LoggingClient
}

func (c *buildClient) BuildType() string {
return c.buildType
}
2 changes: 1 addition & 1 deletion pkg/steps/index_generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func TestDatabaseIndex(t *testing.T) {
if err := yaml.Unmarshal(rawImageStreamTag, ist); err != nil {
t.Fatalf("failed to unmarshal imagestreamTag: %v", err)
}
actual, actualErr := databaseIndex(NewBuildClient(loggingclient.New(fakectrlruntimeclient.NewClientBuilder().WithObjects(ist, image).Build(), nil), nil, nil, "", "", nil),
actual, actualErr := databaseIndex(NewBuildClient(loggingclient.New(fakectrlruntimeclient.NewClientBuilder().WithObjects(ist, image).Build(), nil), api.BuildTypeOpenshift, nil, nil, "", "", nil),
testCase.isTagName, "ns")
if diff := cmp.Diff(testCase.expectedErr, actualErr, testhelper.EquateErrorMessage); diff != "" {
t.Fatalf("actual did not match expected, diff: %s", diff)
Expand Down
24 changes: 15 additions & 9 deletions pkg/steps/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,9 +492,15 @@ func handleBuilds(ctx context.Context, buildClient BuildClient, podClient kubern
wg.Add(len(builds))
for _, build := range builds {
go func(b buildapi.Build) {
var err error
defer wg.Done()
metricsAgent.AddNodeWorkload(ctx, b.Namespace, fmt.Sprintf("%s-build", b.Name), b.Name, podClient)
if err := handleBuild(ctx, buildClient, podClient, b); err != nil {
if buildClient.BuildType() == api.BuildTypeOpenshift {
err = handleOpenshiftBuild(ctx, buildClient, podClient, b)
} else {
err = fmt.Errorf("undefined build type %s", buildClient.BuildType())
}
if err != nil {
errChan <- fmt.Errorf("error occurred handling build %s: %w", b.Name, err)
}
metricsAgent.RemoveNodeWorkload(b.Name)
Comment on lines +495 to 506

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Duplicate workload registration: AddNodeWorkload called twice.

Line 497 calls metricsAgent.AddNodeWorkload(...) before dispatching. Then handleOpenshiftBuild calls the same thing again at line 577. The workload gets registered twice for the same build.

Either remove the call here (lines 497) or remove it from handleOpenshiftBuild — but not both places.

🐛 Proposed fix: remove the call from handleBuilds
 	for _, build := range builds {
 		go func(b buildapi.Build) {
 			var err error
 			defer wg.Done()
-			metricsAgent.AddNodeWorkload(ctx, b.Namespace, fmt.Sprintf("%s-build", b.Name), b.Name, podClient)
 			if buildClient.BuildType() == api.BuildTypeOpenshift {
 				err = handleOpenshiftBuild(ctx, buildClient, podClient, b)
 			} else {
 				err = fmt.Errorf("undefined build type %s", buildClient.BuildType())
 			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/steps/source.go` around lines 495 - 506, The code registers the same
workload twice: metricsAgent.AddNodeWorkload is called in the goroutine where
builds are dispatched and again inside handleOpenshiftBuild; remove the
duplicate by deleting the AddNodeWorkload call from the dispatching goroutine
(the call shown in the snippet) and leave the registration in
handleOpenshiftBuild, ensuring RemoveNodeWorkload(b.Name) remains paired for
cleanup; keep the rest of the error handling (err, errChan) and wg.Done as-is.

Expand Down Expand Up @@ -552,35 +558,35 @@ func constructMultiArchBuilds(build buildapi.Build, stepArchitectures []string)
return ret
}

func handleBuild(ctx context.Context, client BuildClient, podClient kubernetes.PodClient, build buildapi.Build) error {
func handleOpenshiftBuild(ctx context.Context, buildClient BuildClient, podClient kubernetes.PodClient, build buildapi.Build) error {
const attempts = 5
ns, name := build.Namespace, build.Name
var errs []error
if err := wait.ExponentialBackoff(wait.Backoff{Duration: time.Minute, Factor: 1.5, Steps: attempts}, func() (bool, error) {
var attempt buildapi.Build

build.DeepCopyInto(&attempt)
if err := client.Create(ctx, &attempt); err == nil {
if err := buildClient.Create(ctx, &attempt); err == nil {
logrus.Infof("Created build %q", name)
} else if kerrors.IsAlreadyExists(err) {
logrus.Infof("Found existing build %q", name)
} else {
return false, fmt.Errorf("could not create build %s: %w", name, err)
}

client.MetricsAgent().AddNodeWorkload(ctx, ns, fmt.Sprintf("%s-build", name), name, podClient)
client.MetricsAgent().StoreMachinesSnapshotForBuildPod(ctx, ns, fmt.Sprintf("%s-build", name), podClient)
if err := waitForBuildOrTimeout(ctx, client, podClient, ns, name); err != nil {
buildClient.MetricsAgent().AddNodeWorkload(ctx, ns, fmt.Sprintf("%s-build", name), name, podClient)
buildClient.MetricsAgent().StoreMachinesSnapshotForBuildPod(ctx, ns, fmt.Sprintf("%s-build", name), podClient)
if err := waitForBuildOrTimeout(ctx, buildClient, podClient, ns, name); err != nil {
errs = append(errs, err)
return false, handleFailedBuild(ctx, client, ns, name, err)
return false, handleFailedBuild(ctx, buildClient, ns, name, err)
}
if err := gatherSuccessfulBuildLog(client, ns, name); err != nil {
if err := gatherSuccessfulBuildLog(buildClient, ns, name); err != nil {
// log error but do not fail successful build
logrus.WithError(err).Warnf("Failed gathering successful build %s logs into artifacts.", name)
}
return true, nil
}); err != nil {
if err == wait.ErrWaitTimeout {
if wait.Interrupted(err) {
return fmt.Errorf("build not successful after %d attempts: %w", attempts, utilerrors.NewAggregate(errs))
}
return err
Expand Down
14 changes: 9 additions & 5 deletions pkg/steps/source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ func TestWaitForBuild(t *testing.T) {
CompletionTimestamp: &end,
},
},
).Build(), nil), nil, nil, "", "", nil),
).Build(), nil), api.BuildTypeOpenshift, nil, nil, "", "", nil),
expected: fmt.Errorf("build didn't start running within 0s (phase: Pending)"),
},
{
Expand Down Expand Up @@ -430,7 +430,7 @@ func TestWaitForBuild(t *testing.T) {
Namespace: ns,
},
},
).Build(), nil), nil, nil, "", "", nil),
).Build(), nil), api.BuildTypeOpenshift, nil, nil, "", "", nil),
expected: fmt.Errorf("build didn't start running within 0s (phase: Pending):\nFound 0 events for Pod some-build-build:"),
},
{
Expand Down Expand Up @@ -471,7 +471,7 @@ func TestWaitForBuild(t *testing.T) {
}},
},
},
).Build(), nil), nil, nil, "", "", nil),
).Build(), nil), api.BuildTypeOpenshift, nil, nil, "", "", nil),
expected: fmt.Errorf(`build didn't start running within 0s (phase: Pending):
* Container the-container is not ready with reason the_reason and message the_message
Found 0 events for Pod some-build-build:`),
Expand All @@ -490,7 +490,7 @@ Found 0 events for Pod some-build-build:`),
StartTimestamp: &start,
CompletionTimestamp: &end,
},
}).Build(), nil), nil, nil, "", "", nil),
}).Build(), nil), api.BuildTypeOpenshift, nil, nil, "", "", nil),
timeout: 30 * time.Minute,
},
{
Expand Down Expand Up @@ -534,7 +534,7 @@ Found 0 events for Pod some-build-build:`),
Time: now.Add(-59 * time.Minute),
},
},
}).Build(), nil), nil, nil, "", "", nil),
}).Build(), nil), api.BuildTypeOpenshift, nil, nil, "", "", nil),
timeout: 30 * time.Minute,
},
{
Expand Down Expand Up @@ -721,6 +721,10 @@ func (c *fakeBuildClient) Client() loggingclient.LoggingClient {
return c.LoggingClient
}

func (c *fakeBuildClient) BuildType() string {
return api.BuildTypeOpenshift
}

func Test_constructMultiArchBuilds(t *testing.T) {
tests := []struct {
name string
Expand Down