Skip to content

Commit 403642d

Browse files
committed
Apply OKD config to late-resolved parent images
rh-pre-commit.version: 2.3.2 rh-pre-commit.check-secrets: ENABLED
1 parent fbf2864 commit 403642d

File tree

4 files changed

+101
-57
lines changed

4 files changed

+101
-57
lines changed

doozer/doozerlib/cli/images_konflux.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,32 @@ def __init__(
220220
@start_as_current_span_async(TRACER, "images:konflux:build")
221221
async def run(self):
222222
runtime = self.runtime
223-
runtime.initialize(mode='images', clone_distgits=False)
224223

224+
# IMPORTANT: For OKD builds, set up OKD configuration BEFORE loading images
225+
# This ensures that when images (including parent images) are loaded during initialization,
226+
# they use the correct OKD-specific branch (e.g., rhel-10 instead of rhel-9 for OKD 5.0)
225227
if self.variant is BuildVariant.OKD:
226-
group_config = self.runtime.group_config.copy()
228+
# Step 1: Initialize only group and assembly configs (config_only=True)
229+
# This loads group_config but doesn't load images yet
230+
runtime.initialize(mode='images', clone_distgits=False, config_only=True)
231+
232+
# Step 2: Merge OKD configuration into group config BEFORE loading images
233+
group_config = runtime.group_config.copy()
227234
if group_config.get('okd'):
228235
LOGGER.info('Build images using OKD group configuration')
229236
group_config = deep_merge(group_config, group_config['okd'])
230-
runtime.group_config = Model(group_config)
237+
runtime._group_config = Model(group_config)
238+
# Update runtime.branch to use the OKD branch override
239+
# This ensures parent images use the correct rhel-10 branch instead of rhel-9
240+
if group_config.get('branch'):
241+
runtime.branch = group_config['branch']
242+
LOGGER.info(f'Updated runtime branch to OKD variant: {runtime.branch}')
243+
244+
# Step 3: Now do full initialization with OKD config already applied
245+
runtime.initialize(mode='images', clone_distgits=False)
246+
else:
247+
# For non-OKD builds, initialize normally
248+
runtime.initialize(mode='images', clone_distgits=False)
231249

232250
runtime.konflux_db.bind(KonfluxBuildRecord)
233251
assert runtime.source_resolver is not None, "source_resolver is not initialized. Doozer bug?"

doozer/doozerlib/cli/images_okd.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,55 @@ def __init__(
9494
self.state = {}
9595

9696
async def run(self):
97-
self.runtime.initialize(mode='images', clone_distgits=False, build_system='konflux')
97+
# IMPORTANT: Set up OKD configuration BEFORE loading images
98+
# This ensures that when images (including parent images) are loaded during initialization,
99+
# they use the correct OKD-specific branch (e.g., rhel-10 instead of rhel-9 for OKD 5.0)
98100

101+
# Step 1: Initialize only group and assembly configs (config_only=True)
102+
# This loads group_config but doesn't load images yet
103+
self.runtime.initialize(mode='images', clone_distgits=False, build_system='konflux', config_only=True)
104+
105+
# Step 2: Merge OKD configuration into group config BEFORE loading images
99106
group_config = self.runtime.group_config.copy()
100107
if group_config.get('okd', None):
101108
self.logger.info('Using OKD group configuration')
102109
group_config = deep_merge(group_config, group_config['okd'])
103-
self.runtime.group_config = Model(group_config)
110+
# Set the merged config on runtime BEFORE loading images
111+
self.runtime._group_config = Model(group_config)
112+
# Update runtime.branch to use the OKD branch override
113+
# This ensures parent images use the correct rhel-10 branch instead of rhel-9
114+
if group_config.get('branch'):
115+
self.runtime.branch = group_config['branch']
116+
self.logger.info(f'Updated runtime branch to OKD variant: {self.runtime.branch}')
117+
118+
# Step 3: Now do full initialization with OKD config already applied
119+
# Initialize with disabled=True to load all images (including those with mode: disabled)
120+
# This is necessary because some parent images may be disabled for OCP but enabled for OKD
121+
self.runtime.initialize(mode='images', clone_distgits=False, build_system='konflux', disabled=True)
122+
123+
# Step 4: Apply OKD config to ALL loaded images
124+
# This ensures that parent images also get the OKD branch overrides
125+
for image_meta in self.runtime.image_metas():
126+
if image_meta.config.okd is not Missing:
127+
# Apply the OKD configuration to this image
128+
image_meta.config = self.get_okd_image_config(image_meta)
129+
self.logger.debug(f'Applied OKD config to {image_meta.distgit_key}')
130+
131+
# Step 5: Wrap late_resolve_image to apply OKD config to any images loaded during rebase
132+
# This handles parent images that are loaded on-demand when not explicitly included via --images
133+
original_late_resolve_image = self.runtime.late_resolve_image
134+
135+
def okd_late_resolve_image(distgit_name, add=False, required=True):
136+
# Call the original method to load the image
137+
meta = original_late_resolve_image(distgit_name, add=add, required=required)
138+
# Apply OKD config if this image has one
139+
if meta and meta.config.okd is not Missing:
140+
meta.config = self.get_okd_image_config(meta)
141+
self.logger.debug(f'Applied OKD config to late-resolved image {meta.distgit_key}')
142+
return meta
143+
144+
# Replace the method on the runtime instance
145+
self.runtime.late_resolve_image = okd_late_resolve_image
104146

105147
# For OKD, we need to use the OKD group variant (e.g., okd-4.20 instead of openshift-4.20)
106148
# This ensures the Konflux DB cache is loaded for the correct group
@@ -119,6 +161,7 @@ async def run(self):
119161
image_repo=self.image_repo,
120162
)
121163

164+
# Rebase all loaded images (filtered by --images flag if specified)
122165
metas = self.runtime.ordered_image_metas()
123166
tasks = [self.rebase_image(image_meta, rebaser) for image_meta in metas]
124167
await asyncio.gather(*tasks, return_exceptions=False)

doozer/doozerlib/cli/scan_sources_konflux.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1715,6 +1715,22 @@ async def config_scan_source_changes_konflux(runtime: Runtime, ci_kubeconfig, as
17151715

17161716
# Initialize group config: we need this to determine the canonical builders behavior
17171717
runtime.initialize(config_only=True)
1718+
1719+
# IMPORTANT: For OKD scans, merge OKD configuration BEFORE loading images
1720+
# This ensures that when images (including parent images) are loaded during initialization,
1721+
# they use the correct OKD-specific branch (e.g., rhel-10 instead of rhel-9 for OKD 5.0)
1722+
if variant == BuildVariant.OKD.value:
1723+
group_config = runtime.group_config.copy()
1724+
if group_config.get('okd'):
1725+
runtime._logger.info('Scanning sources using OKD group configuration')
1726+
group_config = deep_merge(group_config, group_config['okd'])
1727+
runtime._group_config = Model(group_config)
1728+
# Update runtime.branch to use the OKD branch override
1729+
# This ensures parent images use the correct rhel-10 branch instead of rhel-9
1730+
if group_config.get('branch'):
1731+
runtime.branch = group_config['branch']
1732+
runtime._logger.info(f'Updated runtime branch to OKD variant: {runtime.branch}')
1733+
17181734
runtime.initialize(mode='both' if variant != BuildVariant.OKD.value else 'images', clone_distgits=False)
17191735

17201736
async with aiohttp.ClientSession() as session:

pyartcd/pyartcd/pipelines/okd.py

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,11 @@ async def init_build_plan(self):
126126
load_okd_only=True,
127127
)
128128

129-
# Filter to only include payload images
130-
self.group_images = await self._filter_payload_images(all_group_images)
129+
# For OKD, do NOT filter to payload-only images
130+
# We need to include base/parent images (like openshift-enterprise-base-rhel9)
131+
# even though they don't have for_payload=true, because they're needed to build payload images.
132+
# Doozer's images:okd rebase/build commands will process whatever images are loaded.
133+
self.group_images = all_group_images
131134
self.build_plan.active_image_count = len(self.group_images)
132135

133136
# Set the image list based on the build strategies
@@ -136,46 +139,6 @@ async def init_build_plan(self):
136139
# Log the initial build plan
137140
self.logger.info('Initial build plan:\n%s', self.build_plan)
138141

139-
async def _filter_payload_images(self, image_names: list) -> list:
140-
"""
141-
Filter image list to only include images marked for_payload.
142-
Non-payload images will be excluded from rebase, build, and imagestream operations.
143-
144-
Arg(s):
145-
image_names (list): List of image names to filter
146-
Return Value(s):
147-
list: Filtered list containing only payload images
148-
"""
149-
ocp_build_data_path = Path(self.runtime.doozer_working) / 'ocp-build-data' / 'images'
150-
payload_images = []
151-
non_payload_images = []
152-
153-
for image_name in image_names:
154-
yaml_file = ocp_build_data_path / f'{image_name}.yml'
155-
156-
try:
157-
with open(yaml_file) as f:
158-
image_metadata = yaml.safe_load(f)
159-
160-
if image_metadata.get('for_payload', False):
161-
payload_images.append(image_name)
162-
else:
163-
non_payload_images.append(image_name)
164-
165-
except Exception as e:
166-
self.logger.warning('Failed to load metadata for %s: %s. Excluding from build.', image_name, e)
167-
non_payload_images.append(image_name)
168-
169-
if non_payload_images:
170-
self.logger.info(
171-
'Excluding %d non-payload images from pipeline: %s',
172-
len(non_payload_images),
173-
', '.join(non_payload_images),
174-
)
175-
176-
self.logger.info('Pipeline will operate on %d payload images', len(payload_images))
177-
return payload_images
178-
179142
def check_building_images(self):
180143
if self.build_plan.image_build_strategy == BuildStrategy.NONE:
181144
jenkins.update_title('[NO IMAGES]')
@@ -187,16 +150,16 @@ def check_building_images(self):
187150
jenkins.update_title(f'[{self.build_plan.active_image_count}] images')
188151

189152
elif self.build_plan.image_build_strategy == BuildStrategy.ONLY:
190-
# Filter image_list to only include payload images (from self.group_images)
153+
# Filter image_list to only include images that exist in the group
191154
self.build_plan.images_included = [img for img in self.image_list if img in self.group_images]
192155
self.build_plan.images_excluded = []
193156

194-
# Warn if any requested images are not payload images
195-
non_payload_requested = [img for img in self.image_list if img not in self.group_images]
196-
if non_payload_requested:
157+
# Warn if any requested images don't exist in the group
158+
non_existent_requested = [img for img in self.image_list if img not in self.group_images]
159+
if non_existent_requested:
197160
self.logger.warning(
198-
'Requested images are not payload images and will be skipped: %s',
199-
', '.join(non_payload_requested),
161+
'Requested images do not exist in the group and will be skipped: %s',
162+
', '.join(non_existent_requested),
200163
)
201164

202165
n_images = len(self.build_plan.images_included)
@@ -622,7 +585,11 @@ async def update_imagestreams(self):
622585
continue
623586

624587
# Determine payload tag name
625-
# Note: All images in the pipeline are already filtered to be payload images
588+
# Note: Only images with for_payload=true should be tagged into imagestreams
589+
if not image_metadata.get('for_payload', False):
590+
self.logger.debug('Skipping non-payload image %s from imagestream tagging', image_name)
591+
continue
592+
626593
payload_tag = self._get_payload_tag_name(image_name, image_metadata)
627594
image_pullspec = image.get('image_pullspec')
628595
image_tag = image.get('image_tag')
@@ -773,9 +740,9 @@ def building_images(self):
773740
def include_exclude_param(self):
774741
"""
775742
Returns the include/exclude parameters for the Doozer command based on the image build strategy.
776-
Note: self.group_images contains only payload images, and images_included/images_excluded
777-
have already been filtered in check_building_images() to only contain payload images.
778-
We must always pass explicit --images parameter to enforce payload-only filtering to doozer.
743+
Note: self.group_images contains all enabled OKD images (including base/parent images).
744+
images_included/images_excluded have already been filtered in check_building_images()
745+
to only contain images that exist in the group.
779746
"""
780747

781748
build_strategy = self.build_plan.image_build_strategy

0 commit comments

Comments
 (0)