33
44from unittest .mock import patch
55
6+ import pytest
7+
8+ from fabric_cli .core .fab_exceptions import FabricCLIError
9+
610
711class TestDeployBulkPublish :
812 """
@@ -11,27 +15,30 @@ class TestDeployBulkPublish:
1115 HTTP cassettes.
1216 """
1317
14- def _run_deploy (self , tmp_path , bulk_publish , mock_fab_set_state_config ):
15- """Invoke deploy_with_config_file with fabric-cicd mocked, returning the
16- append_feature_flag mock for assertions."""
18+ def _create_deploy_args (self , tmp_path , bulk_publish ):
19+ """Create arguments for deploy_with_config_file."""
1720 from argparse import Namespace
1821
19- import fabric_cli .commands .fs .deploy .fab_fs_deploy_config_file as deploy_mod
20- from fabric_cli .core import fab_constant
21-
22- # disable debug mode so fabric-cicd file logging is disabled during the run
23- mock_fab_set_state_config (fab_constant .FAB_DEBUG_ENABLED , "false" )
24-
25- args = Namespace (
22+ return Namespace (
2623 config = str (tmp_path / "config.yml" ),
2724 target_env = "dev" ,
2825 params = None ,
2926 bulk_publish = bulk_publish ,
3027 command_path = "deploy" ,
3128 )
3229
30+ def _run_deploy_success (self , tmp_path , bulk_publish , mock_fab_set_state_config ):
31+ """Run a successful deployment and return feature flag mocks."""
32+ import fabric_cli .commands .fs .deploy .fab_fs_deploy_config_file as deploy_mod
33+ from fabric_cli .core import fab_constant
34+
35+ # disable debug mode so fabric-cicd file logging is disabled during the run
36+ mock_fab_set_state_config (fab_constant .FAB_DEBUG_ENABLED , "false" )
37+ args = self ._create_deploy_args (tmp_path , bulk_publish )
38+
3339 with (
3440 patch .object (deploy_mod , "append_feature_flag" ) as mock_flag ,
41+ patch .object (deploy_mod , "remove_feature_flag" ) as mock_remove_flag ,
3542 patch .object (deploy_mod , "deploy_with_config" , return_value = None ),
3643 patch .object (deploy_mod , "disable_file_logging" ),
3744 patch .object (deploy_mod , "configure_external_file_logging" ),
@@ -41,28 +48,74 @@ def _run_deploy(self, tmp_path, bulk_publish, mock_fab_set_state_config):
4148 ):
4249 deploy_mod .deploy_with_config_file (args )
4350
44- return mock_flag
51+ return mock_flag , mock_remove_flag
52+
53+ def _run_deploy_failure (self , tmp_path , bulk_publish , mock_fab_set_state_config ):
54+ """Run a failed deployment and return feature flag mocks."""
55+ import fabric_cli .commands .fs .deploy .fab_fs_deploy_config_file as deploy_mod
56+ from fabric_cli .core import fab_constant
57+
58+ # disable debug mode so fabric-cicd file logging is disabled during the run
59+ mock_fab_set_state_config (fab_constant .FAB_DEBUG_ENABLED , "false" )
60+ args = self ._create_deploy_args (tmp_path , bulk_publish )
61+
62+ with (
63+ patch .object (deploy_mod , "append_feature_flag" ) as mock_flag ,
64+ patch .object (deploy_mod , "remove_feature_flag" ) as mock_remove_flag ,
65+ patch .object (
66+ deploy_mod ,
67+ "deploy_with_config" ,
68+ side_effect = Exception ("Simulated deployment failure" ),
69+ ),
70+ patch .object (deploy_mod , "disable_file_logging" ),
71+ patch .object (deploy_mod , "configure_external_file_logging" ),
72+ patch .object (
73+ deploy_mod , "create_fabric_token_credential" , return_value = None
74+ ),
75+ ):
76+ with pytest .raises (FabricCLIError ):
77+ deploy_mod .deploy_with_config_file (args )
78+
79+ return mock_flag , mock_remove_flag
4580
4681 def test_deploy_bulk_publish_enabled_appends_experimental_flags_success (
4782 self , tmp_path , mock_fab_set_state_config
4883 ):
4984 """When --bulk_publish is set, both experimental bulk publish flags are appended."""
50- mock_flag = self ._run_deploy (tmp_path , True , mock_fab_set_state_config )
85+ mock_flag , mock_remove_flag = self ._run_deploy_success (
86+ tmp_path , True , mock_fab_set_state_config
87+ )
5188
5289 appended = [call .args [0 ] for call in mock_flag .call_args_list ]
5390 assert "enable_experimental_features" in appended
5491 assert "enable_bulk_publish" in appended
5592 # existing behavior is preserved
5693 assert "disable_print_identity" in appended
94+ removed = [call .args [0 ] for call in mock_remove_flag .call_args_list ]
95+ assert removed == ["enable_experimental_features" , "enable_bulk_publish" ]
96+
97+ def test_deploy_bulk_publish_enabled_removes_flags_on_failure (
98+ self , tmp_path , mock_fab_set_state_config
99+ ):
100+ """Bulk publish flags are removed when deployment raises an exception."""
101+ _ , mock_remove_flag = self ._run_deploy_failure (
102+ tmp_path , True , mock_fab_set_state_config
103+ )
104+
105+ removed = [call .args [0 ] for call in mock_remove_flag .call_args_list ]
106+ assert removed == ["enable_experimental_features" , "enable_bulk_publish" ]
57107
58108 def test_deploy_bulk_publish_disabled_by_default_omits_flags_success (
59109 self , tmp_path , mock_fab_set_state_config
60110 ):
61- """When --bulk_publish is not set (default), bulk publish flags are not appended."""
62- mock_flag = self ._run_deploy (tmp_path , False , mock_fab_set_state_config )
111+ """When --bulk_publish is not set, bulk publish flags are not changed."""
112+ mock_flag , mock_remove_flag = self ._run_deploy_success (
113+ tmp_path , False , mock_fab_set_state_config
114+ )
63115
64116 appended = [call .args [0 ] for call in mock_flag .call_args_list ]
65117 assert "enable_experimental_features" not in appended
66118 assert "enable_bulk_publish" not in appended
67119 # existing behavior is preserved
68120 assert "disable_print_identity" in appended
121+ mock_remove_flag .assert_not_called ()
0 commit comments