@@ -249,11 +249,14 @@ def test_handle_containerized_merge_request_success(
249249 ),
250250 )
251251
252- # Verify OPM version was set
252+ # Verify OPM version was set with effective_index_image_resolved (target when provided)
253253 mock_opm .set_opm_version .assert_called_once_with (prebuild_info ['target_index_resolved' ])
254254
255- # Verify git repository was prepared
255+ # Verify git repository was prepared with effective values
256256 mock_pgrfb .assert_called_once ()
257+ pgrfb_kwargs = mock_pgrfb .call_args [1 ]
258+ assert pgrfb_kwargs ['from_index' ] == target_index
259+ assert pgrfb_kwargs ['branch' ] == prebuild_info ['target_ocp_version' ]
257260
258261 # Verify index.db artifacts were fetched
259262 assert mock_favida .call_count == 2
@@ -273,11 +276,12 @@ def test_handle_containerized_merge_request_success(
273276 expected_bundles = set (source_bundles_pull_spec + target_bundles_pull_spec )
274277 assert set (bundles_arg ) == expected_bundles
275278
276- # Verify missing bundles were identified
279+ # Verify missing bundles were identified with effective ocp_version
277280 mock_gmbfts .assert_called_once ()
278281 gmbfts_kwargs = mock_gmbfts .call_args [1 ]
279282 assert gmbfts_kwargs ['request_id' ] == request_id
280283 assert gmbfts_kwargs ['ignore_bundle_ocp_version' ] is False
284+ assert gmbfts_kwargs ['ocp_version' ] == prebuild_info ['target_ocp_version' ]
281285
282286 # Verify missing bundles were added
283287 mock_ora .assert_called_once ()
@@ -294,8 +298,10 @@ def test_handle_containerized_merge_request_success(
294298 # Verify FBC validation
295299 mock_ov .assert_called_once ()
296300
297- # Verify build metadata was written
301+ # Verify build metadata was written with effective ocp_version
298302 mock_wbm .assert_called_once ()
303+ wbm_args = mock_wbm .call_args [0 ]
304+ assert wbm_args [2 ] == prebuild_info ['target_ocp_version' ]
299305
300306 # Verify git commit/push
301307 mock_gccmop .assert_called_once ()
@@ -306,8 +312,16 @@ def test_handle_containerized_merge_request_success(
306312 # Verify image replication
307313 mock_ritd .assert_called_once ()
308314
309- # Verify index.db push
315+ # Verify _update_index_image_pull_spec with effective values
316+ mock_uiips .assert_called_once ()
317+ uiips_kwargs = mock_uiips .call_args [1 ]
318+ assert uiips_kwargs ['from_index' ] == target_index
319+ assert uiips_kwargs ['resolved_prebuild_from_index' ] == prebuild_info ['target_index_resolved' ]
320+
321+ # Verify index.db push with effective from_index
310322 mock_pida .assert_called_once ()
323+ pida_kwargs = mock_pida .call_args [1 ]
324+ assert pida_kwargs ['from_index' ] == target_index
311325
312326 # Verify final state
313327 final_call = mock_srs .call_args_list [- 1 ]
@@ -523,7 +537,7 @@ def test_handle_containerized_merge_request_success_with_deprecations(
523537 ),
524538 )
525539
526- # Verify OPM version was set
540+ # Verify OPM version was set with effective_index_image_resolved (target when provided)
527541 mock_opm .set_opm_version .assert_called_once_with (prebuild_info ['target_index_resolved' ])
528542
529543 # Verify git repository was prepared
@@ -2028,6 +2042,15 @@ def test_handle_containerized_merge_request_without_target_index(
20282042 index_to_gitlab_push_map = {'quay.io/namespace/source-index' : index_git_repo },
20292043 )
20302044
2045+ # Verify OPM version was set with source_from_index_resolved (fallback when no target)
2046+ mock_opm .set_opm_version .assert_called_once_with (prebuild_info ['source_from_index_resolved' ])
2047+
2048+ # Verify git repository was prepared with source_from_index and source_ocp_version
2049+ mock_pgrfb .assert_called_once ()
2050+ pgrfb_kwargs = mock_pgrfb .call_args [1 ]
2051+ assert pgrfb_kwargs ['from_index' ] == source_from_index
2052+ assert pgrfb_kwargs ['branch' ] == prebuild_info ['source_ocp_version' ]
2053+
20312054 # Verify only source index.db was fetched (not target)
20322055 assert mock_favida .call_count == 1
20332056 mock_favida .assert_called_once_with (source_from_index , temp_dir )
@@ -2045,21 +2068,216 @@ def test_handle_containerized_merge_request_without_target_index(
20452068 # Should only contain source bundles
20462069 assert set (bundles_arg ) == set (source_bundles_pull_spec )
20472070
2048- # Verify get_missing_bundles_from_target_to_source was called with empty target bundles
2071+ # Verify get_missing_bundles_from_target_to_source was called with
2072+ # empty target bundles and source ocp_version
20492073 mock_gmbfts .assert_called_once ()
20502074 gmbfts_call_args = mock_gmbfts .call_args
20512075 assert gmbfts_call_args [1 ]['target_index_bundles' ] == []
2076+ assert gmbfts_call_args [1 ]['ocp_version' ] == prebuild_info ['source_ocp_version' ]
20522077
2053- # Verify _opm_registry_add was called with empty list (no missing bundles)
2078+ # Verify _opm_registry_add was not called (no missing bundles, no target_index_db_path )
20542079 mock_ora .assert_not_called ()
20552080
20562081 # Verify deprecation was processed
20572082 mock_gbfdl .assert_called_once ()
20582083 mock_gblv .assert_called_once ()
20592084 mock_dbd .assert_called_once ()
20602085
2086+ # Verify build metadata was written with source_ocp_version
2087+ mock_wbm .assert_called_once ()
2088+ wbm_args = mock_wbm .call_args [0 ]
2089+ assert wbm_args [2 ] == prebuild_info ['source_ocp_version' ]
2090+
2091+ # Verify _update_index_image_pull_spec was called with source values
2092+ mock_uiips .assert_called_once ()
2093+ uiips_kwargs = mock_uiips .call_args [1 ]
2094+ assert uiips_kwargs ['from_index' ] == source_from_index
2095+ assert (
2096+ uiips_kwargs ['resolved_prebuild_from_index' ] == prebuild_info ['source_from_index_resolved' ]
2097+ )
2098+
2099+ # Verify index.db push was called with source_from_index
2100+ mock_pida .assert_called_once ()
2101+ pida_kwargs = mock_pida .call_args [1 ]
2102+ assert pida_kwargs ['from_index' ] == source_from_index
2103+
20612104 # Verify final state
20622105 final_call = mock_srs .call_args_list [- 1 ]
20632106 assert final_call [0 ][0 ] == request_id
20642107 assert final_call [0 ][1 ] == 'complete'
20652108 assert 'successfully merged' in final_call [0 ][2 ]
2109+
2110+
2111+ @pytest .mark .parametrize (
2112+ 'overwrite_target_index, overwrite_target_index_token' ,
2113+ [
2114+ (True , None ),
2115+ (False , 'user:token' ),
2116+ (True , 'user:token' ),
2117+ ],
2118+ )
2119+ @mock .patch ('iib.workers.tasks.build_containerized_merge.reset_docker_config' )
2120+ @mock .patch ('iib.workers.api_utils.set_request_state' )
2121+ @mock .patch ('iib.workers.api_utils.get_request' )
2122+ @mock .patch ('iib.workers.tasks.build_containerized_merge.set_request_state' )
2123+ def test_handle_containerized_merge_request_overwrite_without_target_index (
2124+ mock_srs ,
2125+ mock_get_request ,
2126+ mock_srs_api ,
2127+ mock_rdc ,
2128+ overwrite_target_index ,
2129+ overwrite_target_index_token ,
2130+ ):
2131+ """Test that overwrite_target_index or token without target_index raises IIBError."""
2132+ mock_get_request .return_value = {'user' : 'test-user' }
2133+
2134+ with pytest .raises (
2135+ IIBError ,
2136+ match = "Parameter 'target_index' must be set when 'overwrite_target_index' "
2137+ "or 'overwrite_target_index_token' is provided" ,
2138+ ):
2139+ build_containerized_merge .handle_containerized_merge_request (
2140+ source_from_index = 'quay.io/namespace/source-index:v4.14' ,
2141+ deprecation_list = [],
2142+ request_id = 1 ,
2143+ target_index = None ,
2144+ overwrite_target_index = overwrite_target_index ,
2145+ overwrite_target_index_token = overwrite_target_index_token ,
2146+ )
2147+
2148+
2149+ @mock .patch ('iib.workers.tasks.build_containerized_merge.reset_docker_config' )
2150+ @mock .patch ('iib.workers.tasks.build_containerized_merge.cleanup_on_failure' )
2151+ @mock .patch ('iib.workers.tasks.build_containerized_merge.cleanup_merge_request_if_exists' )
2152+ @mock .patch ('iib.workers.tasks.build_containerized_merge.push_index_db_artifact' )
2153+ @mock .patch ('iib.workers.tasks.build_containerized_merge._update_index_image_pull_spec' )
2154+ @mock .patch ('iib.workers.tasks.build_containerized_merge.replicate_image_to_tagged_destinations' )
2155+ @mock .patch ('iib.workers.tasks.build_containerized_merge.monitor_pipeline_and_extract_image' )
2156+ @mock .patch ('iib.workers.tasks.build_containerized_merge.git_commit_and_create_mr_or_push' )
2157+ @mock .patch ('iib.workers.tasks.build_containerized_merge.write_build_metadata' )
2158+ @mock .patch ('iib.workers.tasks.build_containerized_merge.opm_validate' )
2159+ @mock .patch ('iib.workers.tasks.build_containerized_merge.shutil.copytree' )
2160+ @mock .patch ('iib.workers.tasks.build_containerized_merge.merge_catalogs_dirs' )
2161+ @mock .patch ('iib.workers.tasks.build_containerized_merge.opm_migrate' )
2162+ @mock .patch ('iib.workers.tasks.build_containerized_merge.get_list_bundles' )
2163+ @mock .patch ('iib.workers.tasks.build_containerized_merge.deprecate_bundles_db' )
2164+ @mock .patch ('iib.workers.tasks.build_containerized_merge.get_bundles_latest_version' )
2165+ @mock .patch ('iib.workers.tasks.build_containerized_merge.get_bundles_from_deprecation_list' )
2166+ @mock .patch ('iib.workers.tasks.build_containerized_merge._opm_registry_add' )
2167+ @mock .patch ('iib.workers.tasks.build_containerized_merge.get_missing_bundles_from_target_to_source' )
2168+ @mock .patch ('iib.workers.tasks.build_containerized_merge.validate_bundles_in_parallel' )
2169+ @mock .patch ('iib.workers.tasks.build_containerized_merge._get_present_bundles' )
2170+ @mock .patch ('iib.workers.tasks.build_containerized_merge.fetch_and_verify_index_db_artifact' )
2171+ @mock .patch ('iib.workers.tasks.build_containerized_merge.prepare_git_repository_for_build' )
2172+ @mock .patch ('iib.workers.tasks.build_containerized_merge._update_index_image_build_state' )
2173+ @mock .patch ('iib.workers.tasks.build_containerized_merge.Opm' )
2174+ @mock .patch ('iib.workers.tasks.build_containerized_merge.prepare_request_for_build' )
2175+ @mock .patch ('iib.workers.api_utils.set_request_state' )
2176+ @mock .patch ('iib.workers.api_utils.get_request' )
2177+ @mock .patch ('iib.workers.tasks.build_containerized_merge.set_request_state' )
2178+ @mock .patch ('iib.workers.tasks.build_containerized_merge.set_registry_token' )
2179+ @mock .patch ('iib.workers.tasks.build_containerized_merge.tempfile.TemporaryDirectory' )
2180+ @mock .patch ('iib.workers.tasks.build_containerized_merge.os.rename' )
2181+ @mock .patch ('iib.workers.tasks.build_containerized_merge.shutil.rmtree' )
2182+ @mock .patch ('iib.workers.tasks.build_containerized_merge.shutil.move' )
2183+ @mock .patch ('iib.workers.tasks.build_containerized_merge.os.path.exists' )
2184+ @mock .patch ('builtins.set' , side_effect = _mock_set_for_bundles )
2185+ def test_handle_containerized_merge_request_without_target_index_failure_uses_source (
2186+ mock_set ,
2187+ mock_exists ,
2188+ mock_move ,
2189+ mock_rmtree ,
2190+ mock_rename ,
2191+ mock_tempdir ,
2192+ mock_set_registry_token ,
2193+ mock_srs ,
2194+ mock_srs_api ,
2195+ mock_get_request ,
2196+ mock_prfb ,
2197+ mock_opm ,
2198+ mock_uiibs ,
2199+ mock_pgrfb ,
2200+ mock_favida ,
2201+ mock_gpb ,
2202+ mock_vbip ,
2203+ mock_gmbfts ,
2204+ mock_ora ,
2205+ mock_gbfdl ,
2206+ mock_gblv ,
2207+ mock_dbd ,
2208+ mock_glb ,
2209+ mock_om ,
2210+ mock_mcd ,
2211+ mock_copytree ,
2212+ mock_ov ,
2213+ mock_wbm ,
2214+ mock_gccmop ,
2215+ mock_mpaei ,
2216+ mock_ritd ,
2217+ mock_uiips ,
2218+ mock_pida ,
2219+ mock_cmrif ,
2220+ mock_cof ,
2221+ mock_rdc ,
2222+ ):
2223+ """Test that cleanup_on_failure uses source_from_index when target_index is None."""
2224+ request_id = 11
2225+ source_from_index = 'quay.io/namespace/source-index:v4.14'
2226+
2227+ temp_dir = '/tmp/iib-11-test'
2228+ mock_tempdir .return_value .__enter__ .return_value = temp_dir
2229+ mock_get_request .return_value = {'user' : 'test-user' }
2230+
2231+ prebuild_info = {
2232+ 'arches' : {'amd64' },
2233+ 'binary_image_resolved' : 'registry.io/binary@sha256:abc' ,
2234+ 'source_from_index_resolved' : 'quay.io/namespace/source-index@sha256:def' ,
2235+ 'target_index_resolved' : None ,
2236+ 'ocp_version' : 'v4.14' ,
2237+ 'target_ocp_version' : 'v4.14' ,
2238+ 'source_ocp_version' : 'v4.14' ,
2239+ 'distribution_scope' : 'prod' ,
2240+ }
2241+ mock_prfb .return_value = prebuild_info
2242+ mock_opm .opm_version = 'v1.28.0'
2243+
2244+ index_git_repo = 'https://gitlab.com/repo'
2245+ local_git_repo_path = os .path .join (temp_dir , 'git_repo' )
2246+ localized_git_catalog_path = os .path .join (local_git_repo_path , 'catalogs' )
2247+ mock_pgrfb .return_value = (index_git_repo , local_git_repo_path , localized_git_catalog_path )
2248+
2249+ source_index_db_path = os .path .join (temp_dir , 'source_index.db' )
2250+ mock_favida .return_value = source_index_db_path
2251+
2252+ source_bundles = [
2253+ {'bundlePath' : 'bundle1@sha256:111' , 'csvName' : 'bundle1-1.0' , 'packageName' : 'bundle1' },
2254+ ]
2255+ mock_gpb .return_value = (source_bundles , ['bundle1@sha256:111' ])
2256+ mock_gmbfts .return_value = ([], [])
2257+ mock_gbfdl .return_value = []
2258+
2259+ bundles_in_db = [{'bundlePath' : 'bundle1@sha256:111' , 'packageName' : 'bundle1' }]
2260+ mock_glb .return_value = bundles_in_db
2261+
2262+ fbc_dir = os .path .join (temp_dir , 'fbc_catalog' )
2263+ mock_om .return_value = (fbc_dir , None )
2264+ mock_exists .return_value = True
2265+
2266+ mock_gccmop .return_value = (None , 'commit_sha' )
2267+
2268+ # Pipeline fails
2269+ mock_mpaei .side_effect = IIBError ('Pipeline failed' )
2270+
2271+ with pytest .raises (IIBError , match = 'Failed to merge operators' ):
2272+ build_containerized_merge .handle_containerized_merge_request (
2273+ source_from_index = source_from_index ,
2274+ deprecation_list = [],
2275+ request_id = request_id ,
2276+ target_index = None ,
2277+ )
2278+
2279+ # Verify cleanup_on_failure was called with source_from_index
2280+ mock_cof .assert_called_once ()
2281+ cof_kwargs = mock_cof .call_args [1 ]
2282+ assert cof_kwargs ['from_index' ] == source_from_index
2283+ assert 'Pipeline failed' in cof_kwargs ['reason' ]
0 commit comments