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
98 changes: 98 additions & 0 deletions deploy/crds/shipwright.io_buildruns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7734,6 +7734,39 @@ spec:
description: Labels references the additional labels to
be applied on the image
type: object
multiArch:
description: |-
MultiArch configures building container images for multiple OS and CPU
architecture combinations. When set, the build controller will orchestrate
parallel builds for each specified platform and assemble the results into
an OCI image index.
properties:
platforms:
description: Platforms is the list of os/architecture
combinations to build for.
items:
description: |-
ImagePlatform describes the operating system and CPU architecture
of a container image, following the OCI image index specification.
properties:
arch:
description: Arch is the CPU architecture of
the image platform (e.g. "amd64", "arm64",
"s390x", "ppc64le").
type: string
os:
description: OS is the operating system of the
image platform (e.g. "linux").
type: string
required:
- arch
- os
type: object
minItems: 1
type: array
required:
- platforms
type: object
pushSecret:
description: Describes the secret name for pushing a container
image.
Expand Down Expand Up @@ -10332,6 +10365,38 @@ spec:
description: Labels references the additional labels to be applied
on the image
type: object
multiArch:
description: |-
MultiArch configures building container images for multiple OS and CPU
architecture combinations. When set, the build controller will orchestrate
parallel builds for each specified platform and assemble the results into
an OCI image index.
properties:
platforms:
description: Platforms is the list of os/architecture combinations
to build for.
items:
description: |-
ImagePlatform describes the operating system and CPU architecture
of a container image, following the OCI image index specification.
properties:
arch:
description: Arch is the CPU architecture of the image
platform (e.g. "amd64", "arm64", "s390x", "ppc64le").
type: string
os:
description: OS is the operating system of the image
platform (e.g. "linux").
type: string
required:
- arch
- os
type: object
minItems: 1
type: array
required:
- platforms
type: object
pushSecret:
description: Describes the secret name for pushing a container
image.
Expand Down Expand Up @@ -12756,6 +12821,39 @@ spec:
description: Labels references the additional labels to be
applied on the image
type: object
multiArch:
description: |-
MultiArch configures building container images for multiple OS and CPU
architecture combinations. When set, the build controller will orchestrate
parallel builds for each specified platform and assemble the results into
an OCI image index.
properties:
platforms:
description: Platforms is the list of os/architecture
combinations to build for.
items:
description: |-
ImagePlatform describes the operating system and CPU architecture
of a container image, following the OCI image index specification.
properties:
arch:
description: Arch is the CPU architecture of the
image platform (e.g. "amd64", "arm64", "s390x",
"ppc64le").
type: string
os:
description: OS is the operating system of the image
platform (e.g. "linux").
type: string
required:
- arch
- os
type: object
minItems: 1
type: array
required:
- platforms
type: object
pushSecret:
description: Describes the secret name for pushing a container
image.
Expand Down
32 changes: 32 additions & 0 deletions deploy/crds/shipwright.io_builds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2813,6 +2813,38 @@ spec:
description: Labels references the additional labels to be applied
on the image
type: object
multiArch:
description: |-
MultiArch configures building container images for multiple OS and CPU
architecture combinations. When set, the build controller will orchestrate
parallel builds for each specified platform and assemble the results into
an OCI image index.
properties:
platforms:
description: Platforms is the list of os/architecture combinations
to build for.
items:
description: |-
ImagePlatform describes the operating system and CPU architecture
of a container image, following the OCI image index specification.
properties:
arch:
description: Arch is the CPU architecture of the image
platform (e.g. "amd64", "arm64", "s390x", "ppc64le").
type: string
os:
description: OS is the operating system of the image
platform (e.g. "linux").
type: string
required:
- arch
- os
type: object
minItems: 1
type: array
required:
- platforms
type: object
pushSecret:
description: Describes the secret name for pushing a container
image.
Expand Down
35 changes: 35 additions & 0 deletions pkg/apis/build/v1beta1/build_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ const (
SchedulerNameNotValid BuildReason = "SchedulerNameNotValid"
// RuntimeClassNameNotValid indicates that the RuntimeClassName is not valid
RuntimeClassNameNotValid BuildReason = "RuntimeClassNameNotValid"
// MultiArchNodeSelectorConflict indicates that nodeSelector contains kubernetes.io/os or
// kubernetes.io/arch which conflicts with multi-arch platform scheduling
MultiArchNodeSelectorConflict BuildReason = "MultiArchNodeSelectorConflict"
// MultiArchInvalidPlatform indicates that a multi-arch platform entry has invalid or empty fields
MultiArchInvalidPlatform BuildReason = "MultiArchInvalidPlatform"
// AllValidationsSucceeded indicates a Build was successfully validated
AllValidationsSucceeded = "all validations succeeded"
)
Expand Down Expand Up @@ -271,6 +276,28 @@ type VulnerabilityScanOptions struct {
Ignore *VulnerabilityIgnoreOptions `json:"ignore,omitempty"`
}

// ImagePlatform describes the operating system and CPU architecture
// of a container image, following the OCI image index specification.
type ImagePlatform struct {
// OS is the operating system of the image platform (e.g. "linux").
// +required
OS string `json:"os"`

// Arch is the CPU architecture of the image platform (e.g. "amd64", "arm64", "s390x", "ppc64le").
// +required
Arch string `json:"arch"`
}

// MultiArch configures multi-architecture image builds. When specified,
// the build controller will orchestrate parallel builds for each platform
// and assemble the results into an OCI image index (manifest list).
type MultiArch struct {
// Platforms is the list of os/architecture combinations to build for.
// +required
// +kubebuilder:validation:MinItems=1
Platforms []ImagePlatform `json:"platforms"`
}

// Image refers to an container image with credentials
type Image struct {
// Image is the reference of the image.
Expand Down Expand Up @@ -310,6 +337,14 @@ type Image struct {
//
// +optional
Timestamp *string `json:"timestamp,omitempty"`

// MultiArch configures building container images for multiple OS and CPU
// architecture combinations. When set, the build controller will orchestrate
// parallel builds for each specified platform and assemble the results into
// an OCI image index.
//
// +optional
MultiArch *MultiArch `json:"multiArch,omitempty"`
}

// BuildStatus defines the observed state of Build
Expand Down
40 changes: 40 additions & 0 deletions pkg/apis/build/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 45 additions & 0 deletions pkg/validate/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ package validate

import (
"context"
"fmt"
"strconv"

build "github.com/shipwright-io/build/pkg/apis/build/v1beta1"
corev1 "k8s.io/api/core/v1"
"k8s.io/utils/ptr"
)

Expand Down Expand Up @@ -47,10 +49,53 @@ func (b *BuildSpecOutputValidator) ValidatePath(_ context.Context) error {
}
}

if b.Build.Spec.Output.MultiArch != nil {
b.validateMultiArch()
}

return nil
}

func (b *BuildSpecOutputValidator) validateMultiArch() {
if valid, reason, msg := ValidateMultiArchPlatforms(b.Build.Spec.Output.MultiArch.Platforms); !valid {
b.Build.Status.Reason = ptr.To[build.BuildReason](reason)
b.Build.Status.Message = ptr.To(msg)
return
}
if valid, reason, msg := ValidateMultiArchNodeSelector(b.Build.Spec.NodeSelector); !valid {
b.Build.Status.Reason = ptr.To[build.BuildReason](reason)
b.Build.Status.Message = ptr.To(msg)
return
}
}

func (b *BuildSpecOutputValidator) isEmptySource() bool {
return b.Build.Spec.Source == nil ||
b.Build.Spec.Source.Git == nil && b.Build.Spec.Source.OCIArtifact == nil && b.Build.Spec.Source.Local == nil
}

// ValidateMultiArchPlatforms validates the platforms in a multiArch configuration.
// This is used by BuildRun validation which doesn't go through the Build validator.
func ValidateMultiArchPlatforms(platforms []build.ImagePlatform) (bool, build.BuildReason, string) {
if len(platforms) == 0 {
return false, build.MultiArchInvalidPlatform, "multiArch.platforms must contain at least one platform entry"
}
for i, p := range platforms {
if p.OS == "" || p.Arch == "" {
return false, build.MultiArchInvalidPlatform, fmt.Sprintf("multiArch.platforms[%d] must specify both os and arch", i)
}
}
return true, "", ""
}

// ValidateMultiArchNodeSelector checks that nodeSelector does not conflict with multi-arch scheduling.
func ValidateMultiArchNodeSelector(nodeSelector map[string]string) (bool, build.BuildReason, string) {
if _, ok := nodeSelector[corev1.LabelOSStable]; ok {
return false, build.MultiArchNodeSelectorConflict, fmt.Sprintf("nodeSelector must not contain %q when multiArch is configured; the build controller manages os/arch scheduling", corev1.LabelOSStable)
}
if _, ok := nodeSelector[corev1.LabelArchStable]; ok {
return false, build.MultiArchNodeSelectorConflict, fmt.Sprintf("nodeSelector must not contain %q when multiArch is configured; the build controller manages os/arch scheduling", corev1.LabelArchStable)
}
return true, "", ""
}

Loading
Loading