Skip to content

Commit 68b738a

Browse files
committed
Enable possibility to use capabilities in images jobs
Make capabilities and additional_architectures equivalent during transition. Both fields are merged into a unified capabilities list via AllCapabilities(). For architecture-specific logic (e.g. ResolveMultiArch), ArchitectureCapabilities() filters the merged list against valid architecture strings. - Add AllCapabilities() and ArchitectureCapabilities() helpers - Mark AdditionalArchitectures as deprecated in favor of Capabilities - Update prowgen, validation, project_image, and image-graph-generator to use the new helpers instead of accessing fields directly - Add validation for Capabilities values - Fix Capabilities comment on image build config (was "test runs") Signed-off-by: Jakub Guzik <jguzik@redhat.com>
1 parent 9908494 commit 68b738a

10 files changed

Lines changed: 145 additions & 22 deletions

pkg/api/types.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2810,11 +2810,16 @@ type ProjectDirectoryImageBuildStepConfiguration struct {
28102810
MultiArch bool `json:"multi_arch,omitempty"`
28112811

28122812
// AdditionalArchitectures is a list of additional architectures to build for. AMD64 architecture is included by default.
2813+
// DEPRECATED: use Capabilities instead
28132814
AdditionalArchitectures []string `json:"additional_architectures,omitempty"`
28142815

28152816
// Ref is an optional string linking to the extra_ref in "org.repo" format that this belongs to
28162817
Ref string `json:"ref,omitempty"`
28172818

2819+
// Capabilities is the list of strings that
2820+
// define additional capabilities needed by the image build jobs
2821+
Capabilities []string `json:"capabilities,omitempty"`
2822+
28182823
// isBundleImage indicates that this build step is a bundle image
28192824
isBundleImage bool
28202825
}
@@ -2834,6 +2839,33 @@ func (p *ProjectDirectoryImageBuildStepConfiguration) WithBundleImage(isBundleIm
28342839
return p
28352840
}
28362841

2842+
// ValidArchitectures is the set of supported architecture strings for image builds.
2843+
var ValidArchitectures = sets.New[string](
2844+
"amd64", // x86-64
2845+
"arm64", // AArch64
2846+
"ppc64le", // PowerPC 64-bit Little Endian
2847+
"s390x", // IBM System z 64-bit
2848+
)
2849+
2850+
// AllCapabilities returns the deduplicated, sorted union of Capabilities and
2851+
// AdditionalArchitectures. Both fields are treated as equivalent during the
2852+
// transition period while AdditionalArchitectures is being phased out.
2853+
func (p *ProjectDirectoryImageBuildStepConfiguration) AllCapabilities() []string {
2854+
return sets.List(sets.New[string](append(p.Capabilities, p.AdditionalArchitectures...)...))
2855+
}
2856+
2857+
// ArchitectureCapabilities returns the subset of AllCapabilities that are valid
2858+
// architecture strings (e.g. "arm64", "ppc64le").
2859+
func (p *ProjectDirectoryImageBuildStepConfiguration) ArchitectureCapabilities() []string {
2860+
var arches []string
2861+
for _, c := range p.AllCapabilities() {
2862+
if ValidArchitectures.Has(c) {
2863+
arches = append(arches, c)
2864+
}
2865+
}
2866+
return arches
2867+
}
2868+
28372869
// ProjectDirectoryImageBuildInputs holds inputs for an image build from the repo under test
28382870
type ProjectDirectoryImageBuildInputs struct {
28392871
// ContextDir is the directory in the project

pkg/api/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/image-graph-generator/operator.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,7 @@ func (o *Operator) callback(c *api.ReleaseBuildConfiguration, i *config.Info) er
104104

105105
for _, image := range c.Images {
106106
if !excludedImages.Has(string(image.To)) {
107-
multiArch := false
108-
if len(image.AdditionalArchitectures) > 0 {
109-
multiArch = true
110-
}
107+
multiArch := len(image.ArchitectureCapabilities()) > 0
111108
if err := o.UpdateImage(image, c.BaseImages, target, branchID, multiArch); err != nil {
112109
errs = append(errs, err)
113110
}

pkg/prowgen/prowgen.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func GenerateJobs(configSpec *cioperatorapi.ReleaseBuildConfiguration, info *Pro
126126
}
127127
imagesTestName := "images"
128128
jobBaseGen := newJobBaseBuilder().TestName(imagesTestName)
129-
injectArchitectureLabels(jobBaseGen, configSpec.Images)
129+
injectCapabilitiesForImgJobs(jobBaseGen, configSpec.Images)
130130

131131
optional := false
132132
for _, image := range configSpec.Images {
@@ -143,7 +143,7 @@ func GenerateJobs(configSpec *cioperatorapi.ReleaseBuildConfiguration, info *Pro
143143

144144
if configSpec.PromotionConfiguration != nil {
145145
jobBaseGen = newJobBaseBuilder().TestName(imagesTestName)
146-
injectArchitectureLabels(jobBaseGen, configSpec.Images)
146+
injectCapabilitiesForImgJobs(jobBaseGen, configSpec.Images)
147147

148148
jobBaseGen.PodSpec.Add(Promotion(), Targets(imageTargets.UnsortedList()...))
149149
// Note: Slack reporter config for images postsubmit is now handled in generatePostsubmitForTest
@@ -436,10 +436,10 @@ func injectCapabilities(labels map[string]string, capabilities []string) {
436436
}
437437
}
438438

439-
func injectArchitectureLabels(g *prowJobBaseBuilder, imagesConfig []cioperatorapi.ProjectDirectoryImageBuildStepConfiguration) {
440-
for _, imageConfig := range imagesConfig {
441-
for _, arch := range imageConfig.AdditionalArchitectures {
442-
g.WithLabel(fmt.Sprintf("capability/%s", arch), arch)
439+
func injectCapabilitiesForImgJobs(g *prowJobBaseBuilder, imagesConfig []cioperatorapi.ProjectDirectoryImageBuildStepConfiguration) {
440+
for _, img := range imagesConfig {
441+
for _, c := range img.AllCapabilities() {
442+
g.WithLabel(fmt.Sprintf("capability/%s", c), c)
443443
}
444444
}
445445
}

pkg/prowgen/prowgen_test.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,52 @@ func TestGenerateJobs(t *testing.T) {
730730
},
731731
},
732732
},
733+
{
734+
id: "multiarch postsubmit images, using capabilities",
735+
config: &ciop.ReleaseBuildConfiguration{
736+
Images: []ciop.ProjectDirectoryImageBuildStepConfiguration{
737+
{
738+
From: "os",
739+
To: "ci-tools",
740+
Capabilities: []string{"arm64"},
741+
},
742+
{
743+
From: "os",
744+
To: "test",
745+
Capabilities: []string{"arm64", "ppc64-le"},
746+
},
747+
},
748+
PromotionConfiguration: &ciop.PromotionConfiguration{},
749+
},
750+
repoInfo: &ProwgenInfo{
751+
Metadata: ciop.Metadata{
752+
Org: "organization",
753+
Repo: "repository",
754+
Branch: "branch",
755+
},
756+
},
757+
},
758+
{
759+
id: "merge capabilities and architecture labels",
760+
config: &ciop.ReleaseBuildConfiguration{
761+
Images: []ciop.ProjectDirectoryImageBuildStepConfiguration{
762+
{
763+
From: "os",
764+
To: "ci-tools",
765+
Capabilities: []string{"arm64"},
766+
AdditionalArchitectures: []string{"ppc64-le"},
767+
},
768+
},
769+
PromotionConfiguration: &ciop.PromotionConfiguration{},
770+
},
771+
repoInfo: &ProwgenInfo{
772+
Metadata: ciop.Metadata{
773+
Org: "organization",
774+
Repo: "repository",
775+
Branch: "branch",
776+
},
777+
},
778+
},
733779
{
734780
id: "multiarch test job",
735781
config: &ciop.ReleaseBuildConfiguration{
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
postsubmits:
2+
organization/repository:
3+
- always_run: true
4+
labels:
5+
capability/arm64: arm64
6+
capability/ppc64-le: ppc64-le
7+
ci-operator.openshift.io/is-promotion: "true"
8+
max_concurrency: 1
9+
name: branch-ci-organization-repository-branch-images
10+
presubmits:
11+
organization/repository:
12+
- always_run: false
13+
labels:
14+
capability/arm64: arm64
15+
capability/ppc64-le: ppc64-le
16+
pj-rehearse.openshift.io/can-be-rehearsed: "true"
17+
name: pull-ci-organization-repository-branch-images
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
postsubmits:
2+
organization/repository:
3+
- always_run: true
4+
labels:
5+
capability/arm64: arm64
6+
capability/ppc64-le: ppc64-le
7+
ci-operator.openshift.io/is-promotion: "true"
8+
max_concurrency: 1
9+
name: branch-ci-organization-repository-branch-images
10+
presubmits:
11+
organization/repository:
12+
- always_run: false
13+
labels:
14+
capability/arm64: arm64
15+
capability/ppc64-le: ppc64-le
16+
pj-rehearse.openshift.io/can-be-rehearsed: "true"
17+
name: pull-ci-organization-repository-branch-images

pkg/steps/project_image.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ func (s *projectDirectoryImageBuildStep) Objects() []ctrlruntimeclient.Object {
200200

201201
func (s *projectDirectoryImageBuildStep) ResolveMultiArch() sets.Set[string] {
202202
s.architectures.Insert(string(api.NodeArchitectureAMD64))
203-
s.architectures.Insert(s.config.AdditionalArchitectures...)
203+
s.architectures.Insert(s.config.ArchitectureCapabilities()...)
204204

205205
// TODO: deprecated when the multi_arch field is removed from the configuration
206206
if s.multiArch {

pkg/validation/config.go

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"errors"
55
"fmt"
66
"regexp"
7-
"sort"
87
"strings"
98

109
"k8s.io/apimachinery/pkg/api/resource"
@@ -307,13 +306,6 @@ func validateBuildRootImageStreamTag(ctx *configContext, buildRoot api.ImageStre
307306
func ValidateImages(ctx *configContext, images []api.ProjectDirectoryImageBuildStepConfiguration) []error {
308307
var validationErrors []error
309308

310-
var validArchitectures = sets.New(
311-
"amd64", // x86-64
312-
"arm64", // AArch64
313-
"ppc64le", // PowerPC 64-bit Little Endian
314-
"s390x", // IBM System z 64-bit
315-
)
316-
317309
for num, image := range images {
318310
ctxN := ctx.addIndex(num)
319311
if image.To == "" {
@@ -326,12 +318,19 @@ func ValidateImages(ctx *configContext, images []api.ProjectDirectoryImageBuildS
326318
validationErrors = append(validationErrors, ctxN.errorf("dockerfile_literal is mutually exclusive with context_dir and dockerfile_path"))
327319
}
328320
for _, arch := range image.AdditionalArchitectures {
329-
if !validArchitectures.Has(arch) {
330-
archList := validArchitectures.UnsortedList()
331-
sort.Strings(archList)
321+
if !api.ValidArchitectures.Has(arch) {
322+
archList := sets.List(api.ValidArchitectures)
332323
validationErrors = append(validationErrors, ctxN.errorf("invalid architecture: %s. Use one of %s", arch, strings.Join(archList, ", ")))
333324
}
334325
}
326+
for _, cap := range image.Capabilities {
327+
if api.ValidArchitectures.Has(cap) {
328+
continue
329+
}
330+
if err := validation.IsQualifiedName(cap); len(err) > 0 {
331+
validationErrors = append(validationErrors, ctxN.errorf("invalid capability: %s", cap))
332+
}
333+
}
335334

336335
}
337336
return validationErrors

pkg/webreg/zz_generated.ci_operator_reference.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ const ciOperatorReferenceYaml = "# The list of base images describe\n" +
185185
"# and can be used to build only a specific image.\n" +
186186
"images:\n" +
187187
" - # AdditionalArchitectures is a list of additional architectures to build for. AMD64 architecture is included by default.\n" +
188+
" # DEPRECATED: use Capabilities instead\n" +
188189
" additional_architectures:\n" +
189190
" - \"\"\n" +
190191
" # BuildArgs contains build arguments that will be resolved in the Dockerfile.\n" +
@@ -194,6 +195,10 @@ const ciOperatorReferenceYaml = "# The list of base images describe\n" +
194195
" name: ' '\n" +
195196
" # Value of the build arg.\n" +
196197
" value: ' '\n" +
198+
" # Capabilities is the list of strings that\n" +
199+
" # define additional capabilities needed by the image build jobs\n" +
200+
" capabilities:\n" +
201+
" - \"\"\n" +
197202
" # ContextDir is the directory in the project\n" +
198203
" # from which this build should be run.\n" +
199204
" context_dir: ' '\n" +
@@ -426,6 +431,7 @@ const ciOperatorReferenceYaml = "# The list of base images describe\n" +
426431
" ref: ' '\n" +
427432
" project_directory_image_build_step:\n" +
428433
" # AdditionalArchitectures is a list of additional architectures to build for. AMD64 architecture is included by default.\n" +
434+
" # DEPRECATED: use Capabilities instead\n" +
429435
" additional_architectures:\n" +
430436
" - \"\"\n" +
431437
" # BuildArgs contains build arguments that will be resolved in the Dockerfile.\n" +
@@ -435,6 +441,10 @@ const ciOperatorReferenceYaml = "# The list of base images describe\n" +
435441
" name: ' '\n" +
436442
" # Value of the build arg.\n" +
437443
" value: ' '\n" +
444+
" # Capabilities is the list of strings that\n" +
445+
" # define additional capabilities needed by the image build jobs\n" +
446+
" capabilities:\n" +
447+
" - \"\"\n" +
438448
" # ContextDir is the directory in the project\n" +
439449
" # from which this build should be run.\n" +
440450
" context_dir: ' '\n" +

0 commit comments

Comments
 (0)