cumulusci-plus 5.0.43__py3-none-any.whl → 5.0.45__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cumulusci/__about__.py +1 -1
- cumulusci/cli/cci.py +3 -2
- cumulusci/core/config/sfdx_org_config.py +4 -1
- cumulusci/tasks/utility/secretsToEnv.py +40 -9
- cumulusci/tasks/utility/tests/test_secretsToEnv.py +1198 -47
- {cumulusci_plus-5.0.43.dist-info → cumulusci_plus-5.0.45.dist-info}/METADATA +4 -5
- {cumulusci_plus-5.0.43.dist-info → cumulusci_plus-5.0.45.dist-info}/RECORD +11 -11
- {cumulusci_plus-5.0.43.dist-info → cumulusci_plus-5.0.45.dist-info}/WHEEL +0 -0
- {cumulusci_plus-5.0.43.dist-info → cumulusci_plus-5.0.45.dist-info}/entry_points.txt +0 -0
- {cumulusci_plus-5.0.43.dist-info → cumulusci_plus-5.0.45.dist-info}/licenses/AUTHORS.rst +0 -0
- {cumulusci_plus-5.0.43.dist-info → cumulusci_plus-5.0.45.dist-info}/licenses/LICENSE +0 -0
cumulusci/__about__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "5.0.
|
|
1
|
+
__version__ = "5.0.45"
|
cumulusci/cli/cci.py
CHANGED
|
@@ -173,11 +173,11 @@ def main(args=None):
|
|
|
173
173
|
with set_debug_mode(debug):
|
|
174
174
|
try:
|
|
175
175
|
runtime = CliRuntime(load_keychain=False)
|
|
176
|
+
runtime.check_cumulusci_version()
|
|
176
177
|
except Exception as e:
|
|
177
178
|
handle_exception(e, is_error_command, tempfile_path, debug)
|
|
178
179
|
sys.exit(1)
|
|
179
180
|
|
|
180
|
-
runtime.check_cumulusci_version()
|
|
181
181
|
should_show_stacktraces = runtime.universal_config.cli__show_stacktraces
|
|
182
182
|
|
|
183
183
|
init_logger(debug=debug)
|
|
@@ -233,7 +233,8 @@ def handle_exception(
|
|
|
233
233
|
with open(logfile_path, "a") as log_file:
|
|
234
234
|
traceback.print_exc(file=log_file) # log stacktrace silently
|
|
235
235
|
|
|
236
|
-
|
|
236
|
+
# Show stacktraces when explicitly requested (e.g., --debug flag)
|
|
237
|
+
if should_show_stacktraces:
|
|
237
238
|
error_console.print_exception()
|
|
238
239
|
|
|
239
240
|
|
|
@@ -53,7 +53,10 @@ class SfdxOrgConfig(OrgConfig):
|
|
|
53
53
|
"Failed to parse json from output.\n "
|
|
54
54
|
f"Exception: {e.__class__.__name__}\n Output: {''.join(stdout_list)}"
|
|
55
55
|
)
|
|
56
|
-
org_id =
|
|
56
|
+
org_id = (
|
|
57
|
+
org_info["result"].get("id")
|
|
58
|
+
or org_info["result"]["accessToken"].split("!")[0]
|
|
59
|
+
)
|
|
57
60
|
|
|
58
61
|
sfdx_info = {
|
|
59
62
|
"instance_url": org_info["result"]["instanceUrl"],
|
|
@@ -64,18 +64,21 @@ class SecretsToEnv(BaseTask):
|
|
|
64
64
|
|
|
65
65
|
self._init_secrets()
|
|
66
66
|
|
|
67
|
-
output_file = self.parsed_options.env_path
|
|
68
|
-
|
|
69
67
|
for secret_key, secret_name in self.secrets.items():
|
|
70
68
|
if secret_key == "*":
|
|
71
69
|
self.env_values.update(
|
|
72
70
|
self._get_all_credentials(secret_key, secret_name=secret_name)
|
|
73
71
|
)
|
|
74
72
|
else:
|
|
75
|
-
|
|
73
|
+
self.env_values[secret_key] = self._get_credential(
|
|
76
74
|
secret_key, secret_key, secret_name=secret_name
|
|
77
75
|
)
|
|
78
|
-
|
|
76
|
+
self.return_values = {"env_values": self.env_values}
|
|
77
|
+
self._write_env_file()
|
|
78
|
+
|
|
79
|
+
def _write_env_file(self):
|
|
80
|
+
safe_env_values = {}
|
|
81
|
+
output_file = self.parsed_options.env_path
|
|
79
82
|
|
|
80
83
|
# Ensure output directory exists
|
|
81
84
|
os.makedirs(os.path.dirname(output_file) or ".", exist_ok=True)
|
|
@@ -83,7 +86,37 @@ class SecretsToEnv(BaseTask):
|
|
|
83
86
|
# Write env file with UTF-8 encoding to support Unicode characters
|
|
84
87
|
with open(output_file, "w", encoding="utf-8") as env_file:
|
|
85
88
|
for key, value in self.env_values.items():
|
|
86
|
-
|
|
89
|
+
safe_env_values[key] = self._escape_env_value(value)
|
|
90
|
+
env_file.write(f'{key}="{safe_env_values[key]}"\n')
|
|
91
|
+
|
|
92
|
+
self.return_values["safe_env_values"] = safe_env_values
|
|
93
|
+
|
|
94
|
+
# https://pypi.org/project/python-dotenv/ -> README -> Escaping Values
|
|
95
|
+
def _escape_env_value(self, value):
|
|
96
|
+
"""
|
|
97
|
+
Escape special characters for .env file values in double quotes.
|
|
98
|
+
Escapes: \\, \', \", \a, \b, \f, \n, \r, \t, \v
|
|
99
|
+
"""
|
|
100
|
+
if not isinstance(value, str):
|
|
101
|
+
return value
|
|
102
|
+
|
|
103
|
+
escape_map = {
|
|
104
|
+
"\\": "\\\\", # Backslash must be first
|
|
105
|
+
"'": "\\'", # Single quote
|
|
106
|
+
'"': '\\"', # Double quote
|
|
107
|
+
"\a": "\\a", # Bell/Alert
|
|
108
|
+
"\b": "\\b", # Backspace
|
|
109
|
+
"\f": "\\f", # Form feed
|
|
110
|
+
"\n": "\\n", # Newline
|
|
111
|
+
"\r": "\\r", # Carriage return
|
|
112
|
+
"\t": "\\t", # Tab
|
|
113
|
+
"\v": "\\v", # Vertical tab
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for char, escaped in escape_map.items():
|
|
117
|
+
value = value.replace(char, escaped)
|
|
118
|
+
|
|
119
|
+
return value
|
|
87
120
|
|
|
88
121
|
def _get_credential(
|
|
89
122
|
self,
|
|
@@ -108,8 +141,7 @@ class SecretsToEnv(BaseTask):
|
|
|
108
141
|
self.logger.info(
|
|
109
142
|
f"Set secrets env var from {self.provider.provider_type}: {env_key}={display_value}"
|
|
110
143
|
)
|
|
111
|
-
|
|
112
|
-
return safe_value, cred_secret_value
|
|
144
|
+
return cred_secret_value
|
|
113
145
|
|
|
114
146
|
def _get_all_credentials(
|
|
115
147
|
self, credential_key, display_value="*****", secret_name=None
|
|
@@ -129,7 +161,6 @@ class SecretsToEnv(BaseTask):
|
|
|
129
161
|
self.logger.info(
|
|
130
162
|
f"Set secrets env var from {self.provider.provider_type}: {key}={display_value}"
|
|
131
163
|
)
|
|
132
|
-
|
|
133
|
-
dict_values[key] = safe_value
|
|
164
|
+
dict_values[key] = value
|
|
134
165
|
|
|
135
166
|
return dict_values
|