ScriptCollection 3.4.58__py3-none-any.whl → 3.5.0__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.
- ScriptCollection/ProgramRunnerPopen.py +2 -6
- ScriptCollection/ScriptCollectionCore.py +78 -110
- ScriptCollection/TasksForCommonProjectStructure.py +234 -111
- {ScriptCollection-3.4.58.dist-info → ScriptCollection-3.5.0.dist-info}/METADATA +9 -9
- ScriptCollection-3.5.0.dist-info/RECORD +14 -0
- ScriptCollection-3.4.58.dist-info/RECORD +0 -14
- {ScriptCollection-3.4.58.dist-info → ScriptCollection-3.5.0.dist-info}/WHEEL +0 -0
- {ScriptCollection-3.4.58.dist-info → ScriptCollection-3.5.0.dist-info}/entry_points.txt +0 -0
- {ScriptCollection-3.4.58.dist-info → ScriptCollection-3.5.0.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import sys
|
|
2
2
|
from subprocess import PIPE, Popen
|
|
3
3
|
from .GeneralUtilities import GeneralUtilities
|
|
4
4
|
from .ProgramRunnerBase import ProgramRunnerBase
|
|
@@ -13,14 +13,10 @@ class ProgramRunnerPopen(ProgramRunnerBase):
|
|
|
13
13
|
# "shell=True" is not allowed because it is not recommended and also something like
|
|
14
14
|
# "ScriptCollectionCore().run_program('curl', 'https://example.com/dataset?id=1&format=json')"
|
|
15
15
|
# would not be possible anymore because the ampersand will be treated as shell-command.
|
|
16
|
-
cwd = os.getcwd()
|
|
17
16
|
try:
|
|
18
|
-
|
|
19
|
-
result = Popen(arguments_for_process, stdout=PIPE, stderr=PIPE, shell=False) # pylint: disable=consider-using-with
|
|
17
|
+
result = Popen(arguments_for_process, cwd=working_directory, stdin=sys.stdin, stdout=PIPE, stderr=PIPE, shell=False) # pylint: disable=consider-using-with
|
|
20
18
|
except FileNotFoundError as fileNotFoundError:
|
|
21
19
|
raise FileNotFoundError(f"Starting '{program}' in '{working_directory}' resulted in a FileNotFoundError: '{fileNotFoundError.filename}'")
|
|
22
|
-
finally:
|
|
23
|
-
os.chdir(cwd)
|
|
24
20
|
return result
|
|
25
21
|
|
|
26
22
|
# Return-values program_runner: Exitcode, StdOut, StdErr, Pid
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import time
|
|
1
2
|
from datetime import timedelta, datetime
|
|
2
3
|
import json
|
|
3
4
|
import binascii
|
|
@@ -28,7 +29,7 @@ from .ProgramRunnerPopen import ProgramRunnerPopen
|
|
|
28
29
|
from .ProgramRunnerEpew import ProgramRunnerEpew, CustomEpewArgument
|
|
29
30
|
|
|
30
31
|
|
|
31
|
-
version = "3.
|
|
32
|
+
version = "3.5.0"
|
|
32
33
|
__version__ = version
|
|
33
34
|
|
|
34
35
|
|
|
@@ -176,7 +177,7 @@ class ScriptCollectionCore:
|
|
|
176
177
|
|
|
177
178
|
@GeneralUtilities.check_arguments
|
|
178
179
|
def git_commit_is_ancestor(self, repository_folder: str, ancestor: str, descendant: str = "HEAD") -> bool:
|
|
179
|
-
exit_code = self.run_program_argsasarray("git", ["merge-base", "--is-ancestor", ancestor, descendant],
|
|
180
|
+
exit_code = self.run_program_argsasarray("git", ["merge-base", "--is-ancestor", ancestor, descendant], repository_folder, throw_exception_if_exitcode_is_not_zero=False)[0]
|
|
180
181
|
if exit_code == 0:
|
|
181
182
|
return True
|
|
182
183
|
elif exit_code == 1:
|
|
@@ -222,12 +223,12 @@ class ScriptCollectionCore:
|
|
|
222
223
|
|
|
223
224
|
@GeneralUtilities.check_arguments
|
|
224
225
|
def git_get_commit_id(self, repository_folder: str, commit: str = "HEAD") -> str:
|
|
225
|
-
result: tuple[int, str, str, int] = self.run_program_argsasarray("git", ["rev-parse", "--verify", commit],
|
|
226
|
+
result: tuple[int, str, str, int] = self.run_program_argsasarray("git", ["rev-parse", "--verify", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
|
226
227
|
return result[1].replace('\n', '')
|
|
227
228
|
|
|
228
229
|
@GeneralUtilities.check_arguments
|
|
229
230
|
def git_get_commit_date(self, repository_folder: str, commit: str = "HEAD") -> datetime:
|
|
230
|
-
result: tuple[int, str, str, int] = self.run_program_argsasarray("git", ["show", "-s", "--format=%ci", commit],
|
|
231
|
+
result: tuple[int, str, str, int] = self.run_program_argsasarray("git", ["show", "-s", "--format=%ci", commit], repository_folder, throw_exception_if_exitcode_is_not_zero=True, verbosity=0)
|
|
231
232
|
date_as_string = result[1].replace('\n', '')
|
|
232
233
|
result = datetime.strptime(date_as_string, '%Y-%m-%d %H:%M:%S %z')
|
|
233
234
|
return result
|
|
@@ -1150,7 +1151,7 @@ class ScriptCollectionCore:
|
|
|
1150
1151
|
# <run programs>
|
|
1151
1152
|
|
|
1152
1153
|
@GeneralUtilities.check_arguments
|
|
1153
|
-
def __run_program_argsasarray_async_helper(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, verbosity: int = 1,
|
|
1154
|
+
def __run_program_argsasarray_async_helper(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, verbosity: int = 1, print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False, title: str = None, log_namespace: str = "", arguments_for_log: list[str] = None, custom_argument: object = None) -> Popen:
|
|
1154
1155
|
# Verbosity:
|
|
1155
1156
|
# 0=Quiet (No output will be printed.)
|
|
1156
1157
|
# 1=Normal (If the exitcode of the executed program is not 0 then the StdErr will be printed.)
|
|
@@ -1180,105 +1181,94 @@ class ScriptCollectionCore:
|
|
|
1180
1181
|
# Return-values program_runner: Exitcode, StdOut, StdErr, Pid
|
|
1181
1182
|
|
|
1182
1183
|
@GeneralUtilities.check_arguments
|
|
1183
|
-
def run_program_argsasarray(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, verbosity: int = 1,
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
arguments_for_log
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1184
|
+
def run_program_argsasarray(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, verbosity: int = 1, print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False, title: str = None, log_namespace: str = "", arguments_for_log: list[str] = None, throw_exception_if_exitcode_is_not_zero: bool = True, custom_argument: object = None) -> tuple[int, str, str, int]:
|
|
1185
|
+
try:
|
|
1186
|
+
mock_loader_result = self.__try_load_mock(program, ' '.join(arguments_as_array), working_directory)
|
|
1187
|
+
if mock_loader_result[0]:
|
|
1188
|
+
return mock_loader_result[1]
|
|
1189
|
+
|
|
1190
|
+
if arguments_for_log is None:
|
|
1191
|
+
arguments_for_log = arguments_as_array
|
|
1192
|
+
|
|
1193
|
+
arguments_for_exception_as_string = ' '.join(arguments_for_log)
|
|
1194
|
+
|
|
1195
|
+
process: Popen = self.__run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, verbosity, print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, arguments_for_log, custom_argument)
|
|
1196
|
+
pid = process.pid
|
|
1197
|
+
|
|
1198
|
+
stdout_lines=list[str]()
|
|
1199
|
+
stderr_lines=list[str]()
|
|
1200
|
+
|
|
1201
|
+
live_console_output_printing=1<verbosity
|
|
1202
|
+
|
|
1203
|
+
log_to_file=log_file is not None
|
|
1204
|
+
if log_to_file:
|
|
1205
|
+
GeneralUtilities.ensure_file_exists(log_file)
|
|
1206
|
+
def stream_process(process):
|
|
1207
|
+
try:
|
|
1208
|
+
|
|
1209
|
+
go = process.poll() is None
|
|
1210
|
+
for line in process.stdout:
|
|
1211
|
+
line_str=GeneralUtilities.bytes_to_string(line).strip().replace('\r', '').replace('\n', '')
|
|
1212
|
+
stdout_lines.append(line_str)
|
|
1213
|
+
if live_console_output_printing:
|
|
1214
|
+
GeneralUtilities.write_message_to_stdout(line_str)
|
|
1215
|
+
if log_to_file:
|
|
1216
|
+
GeneralUtilities.append_line_to_file(log_file, line_str)
|
|
1217
|
+
for line in process.stderr:
|
|
1218
|
+
line_str=GeneralUtilities.bytes_to_string(line).strip().replace('\r', '').replace('\n', '')
|
|
1219
|
+
stderr_lines.append(line_str)
|
|
1220
|
+
if live_console_output_printing:
|
|
1221
|
+
if print_errors_as_information:
|
|
1222
|
+
GeneralUtilities.write_message_to_stdout(line_str)
|
|
1223
|
+
else:
|
|
1224
|
+
GeneralUtilities.write_message_to_stderr(line_str)
|
|
1225
|
+
if log_to_file:
|
|
1226
|
+
GeneralUtilities.append_line_to_file(log_file, line_str)
|
|
1227
|
+
return go
|
|
1228
|
+
except Exception:
|
|
1229
|
+
return None
|
|
1230
|
+
while stream_process(process):
|
|
1231
|
+
time.sleep(0.1)
|
|
1232
|
+
|
|
1233
|
+
exit_code = process.poll()
|
|
1234
|
+
stdout = '\n'.join(stdout_lines)
|
|
1235
|
+
stderr = '\n'.join(stderr_lines)
|
|
1236
|
+
|
|
1237
|
+
if arguments_for_exception_as_string is None:
|
|
1238
|
+
arguments_for_exception_as_string = ' '.join(arguments_as_array)
|
|
1239
|
+
else:
|
|
1240
|
+
arguments_for_exception_as_string = ' '.join(arguments_for_log)
|
|
1227
1241
|
|
|
1228
|
-
if arguments_for_log_as_string is None:
|
|
1229
|
-
arguments_for_log_as_string = ' '.join(arguments_as_array)
|
|
1230
|
-
else:
|
|
1231
|
-
arguments_for_log_as_string = ' '.join(arguments_for_log)
|
|
1232
1242
|
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
info_for_log = title
|
|
1243
|
+
if throw_exception_if_exitcode_is_not_zero and exit_code != 0:
|
|
1244
|
+
arguments_for_exception_as_string = ' '.join(arguments_for_log)
|
|
1245
|
+
raise ValueError(f"Program '{working_directory}>{program} {arguments_for_exception_as_string}' resulted in exitcode {exit_code}. (StdOut: '{stdout}', StdErr: '{stderr}')")
|
|
1237
1246
|
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
if not program_manages_output_itself:
|
|
1244
|
-
if verbosity == 1 and exit_code != 0:
|
|
1245
|
-
self.__write_error_output(print_errors_as_information, stderr)
|
|
1246
|
-
if verbosity == 2:
|
|
1247
|
-
GeneralUtilities.write_message_to_stdout(stdout)
|
|
1248
|
-
self.__write_error_output(print_errors_as_information, stderr)
|
|
1249
|
-
if verbosity == 3:
|
|
1250
|
-
GeneralUtilities.write_message_to_stdout(stdout)
|
|
1251
|
-
self.__write_error_output(print_errors_as_information, stderr)
|
|
1252
|
-
formatted = self.__format_program_execution_information(title=info_for_log, program=program, argument=arguments_for_log_as_string, workingdirectory=working_directory)
|
|
1253
|
-
GeneralUtilities.write_message_to_stdout(f"Finished '{info_for_log}'. Details: '{formatted}")
|
|
1254
|
-
|
|
1255
|
-
if throw_exception_if_exitcode_is_not_zero and exit_code != 0:
|
|
1256
|
-
arguments_for_log_as_string = ' '.join(arguments_for_log)
|
|
1257
|
-
raise ValueError(f"Program '{working_directory}>{program} {arguments_for_log_as_string}' resulted in exitcode {exit_code}. (StdOut: '{stdout}', StdErr: '{stderr}')")
|
|
1258
|
-
|
|
1259
|
-
result = (exit_code, stdout, stderr, pid)
|
|
1260
|
-
return result
|
|
1247
|
+
result = (exit_code, stdout, stderr, pid)
|
|
1248
|
+
return result
|
|
1249
|
+
except Exception as e:
|
|
1250
|
+
raise e
|
|
1261
1251
|
|
|
1262
1252
|
# Return-values program_runner: Exitcode, StdOut, StdErr, Pid
|
|
1263
1253
|
@GeneralUtilities.check_arguments
|
|
1264
|
-
def run_program(self, program: str, arguments: str = "", working_directory: str = None, verbosity: int = 1,
|
|
1265
|
-
return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(arguments), working_directory, verbosity, print_errors_as_information,
|
|
1254
|
+
def run_program(self, program: str, arguments: str = "", working_directory: str = None, verbosity: int = 1, print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False, title: str = None, log_namespace: str = "", arguments_for_log: list[str] = None, throw_exception_if_exitcode_is_not_zero: bool = True, custom_argument: object = None) -> tuple[int, str, str, int]:
|
|
1255
|
+
return self.run_program_argsasarray(program, GeneralUtilities.arguments_to_array(arguments), working_directory, verbosity, print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, arguments_for_log, throw_exception_if_exitcode_is_not_zero, custom_argument)
|
|
1266
1256
|
|
|
1267
1257
|
# Return-values program_runner: Pid
|
|
1268
1258
|
@GeneralUtilities.check_arguments
|
|
1269
|
-
def run_program_argsasarray_async(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, verbosity: int = 1,
|
|
1259
|
+
def run_program_argsasarray_async(self, program: str, arguments_as_array: list[str] = [], working_directory: str = None, verbosity: int = 1, print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False, title: str = None, log_namespace: str = "", arguments_for_log: list[str] = None, custom_argument: object = None) -> int:
|
|
1270
1260
|
mock_loader_result = self.__try_load_mock(program, ' '.join(arguments_as_array), working_directory)
|
|
1271
1261
|
if mock_loader_result[0]:
|
|
1272
1262
|
return mock_loader_result[1]
|
|
1273
1263
|
|
|
1274
|
-
process: Popen = self.__run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, verbosity,
|
|
1264
|
+
process: Popen = self.__run_program_argsasarray_async_helper(program, arguments_as_array, working_directory, verbosity, print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, arguments_for_log, custom_argument)
|
|
1275
1265
|
return process.pid
|
|
1276
1266
|
|
|
1277
1267
|
# Return-values program_runner: Pid
|
|
1278
1268
|
@GeneralUtilities.check_arguments
|
|
1279
1269
|
def run_program_async(self, program: str, arguments: str = "", working_directory: str = None, verbosity: int = 1,
|
|
1280
|
-
print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False,
|
|
1281
|
-
return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, verbosity,
|
|
1270
|
+
print_errors_as_information: bool = False, log_file: str = None, timeoutInSeconds: int = 600, addLogOverhead: bool = False, title: str = None, log_namespace: str = "", arguments_for_log: list[str] = None, custom_argument: object = None) -> int:
|
|
1271
|
+
return self.run_program_argsasarray_async(program, GeneralUtilities.arguments_to_array(arguments), working_directory, verbosity, print_errors_as_information, log_file, timeoutInSeconds, addLogOverhead, title, log_namespace, arguments_for_log, custom_argument)
|
|
1282
1272
|
|
|
1283
1273
|
@GeneralUtilities.check_arguments
|
|
1284
1274
|
def __try_load_mock(self, program: str, arguments: str, working_directory: str) -> tuple[bool, tuple[int, str, str, int]]:
|
|
@@ -1297,28 +1287,6 @@ class ScriptCollectionCore:
|
|
|
1297
1287
|
else:
|
|
1298
1288
|
return GeneralUtilities.resolve_relative_path_from_current_working_directory(workingdirectory)
|
|
1299
1289
|
|
|
1300
|
-
@GeneralUtilities.check_arguments
|
|
1301
|
-
def __write_error_output(self, print_errors_as_information: bool, stderr: str):
|
|
1302
|
-
if print_errors_as_information:
|
|
1303
|
-
GeneralUtilities.write_message_to_stdout(stderr)
|
|
1304
|
-
else:
|
|
1305
|
-
GeneralUtilities.write_message_to_stderr(stderr)
|
|
1306
|
-
|
|
1307
|
-
@GeneralUtilities.check_arguments
|
|
1308
|
-
def __format_program_execution_information(self, exitcode: int = None, stdout: str = None, stderr: str = None, program: str = None, argument: str = None, workingdirectory: str = None, title: str = None, pid: int = None, execution_duration: timedelta = None):
|
|
1309
|
-
result = ""
|
|
1310
|
-
if (exitcode is not None and stdout is not None and stderr is not None):
|
|
1311
|
-
result = f"{result} Exitcode: {exitcode}; StdOut: '{stdout}'; StdErr: '{stderr}'"
|
|
1312
|
-
if (pid is not None):
|
|
1313
|
-
result = f"Pid: '{pid}'; {result}"
|
|
1314
|
-
if (program is not None and argument is not None and workingdirectory is not None):
|
|
1315
|
-
result = f"Command: '{workingdirectory}> {program} {argument}'; {result}"
|
|
1316
|
-
if (execution_duration is not None):
|
|
1317
|
-
result = f"{result}; Duration: '{str(execution_duration)}'"
|
|
1318
|
-
if (title is not None):
|
|
1319
|
-
result = f"Title: '{title}'; {result}"
|
|
1320
|
-
return result.strip()
|
|
1321
|
-
|
|
1322
1290
|
@GeneralUtilities.check_arguments
|
|
1323
1291
|
def verify_no_pending_mock_program_calls(self):
|
|
1324
1292
|
if (len(self.__mocked_program_calls) > 0):
|
|
@@ -1451,8 +1419,8 @@ class ScriptCollectionCore:
|
|
|
1451
1419
|
@GeneralUtilities.check_arguments
|
|
1452
1420
|
def get_version_from_gitversion(self, folder: str, variable: str) -> str:
|
|
1453
1421
|
# called twice as workaround for issue 1877 in gitversion ( https://github.com/GitTools/GitVersion/issues/1877 )
|
|
1454
|
-
result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder)
|
|
1455
|
-
result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder)
|
|
1422
|
+
result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder,verbosity=0)
|
|
1423
|
+
result = self.run_program_argsasarray("gitversion", ["/showVariable", variable], folder,verbosity=0)
|
|
1456
1424
|
result = GeneralUtilities.strip_new_line_character(result[1])
|
|
1457
1425
|
|
|
1458
1426
|
return result
|
|
@@ -21,7 +21,6 @@ from .GeneralUtilities import GeneralUtilities
|
|
|
21
21
|
from .ScriptCollectionCore import ScriptCollectionCore
|
|
22
22
|
from .ProgramRunnerEpew import ProgramRunnerEpew
|
|
23
23
|
|
|
24
|
-
|
|
25
24
|
class CreateReleaseConfiguration():
|
|
26
25
|
projectname: str
|
|
27
26
|
remotename: str
|
|
@@ -146,27 +145,27 @@ class TasksForCommonProjectStructure:
|
|
|
146
145
|
@GeneralUtilities.check_arguments
|
|
147
146
|
def get_testcoverage_threshold_from_codeunit_file(self, codeunit_file: str):
|
|
148
147
|
root: etree._ElementTree = etree.parse(codeunit_file)
|
|
149
|
-
return float(str(root.xpath('//cps:properties/cps:testsettings/@minimalcodecoverageinpercent', namespaces={
|
|
148
|
+
return float(str(root.xpath('//cps:properties/cps:testsettings/@minimalcodecoverageinpercent', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
|
|
150
149
|
|
|
151
150
|
@GeneralUtilities.check_arguments
|
|
152
151
|
def codeunit_has_testable_sourcecode(self, codeunit_file: str) -> bool:
|
|
153
152
|
root: etree._ElementTree = etree.parse(codeunit_file)
|
|
154
|
-
return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@codeunithastestablesourcecode', namespaces={
|
|
153
|
+
return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@codeunithastestablesourcecode', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
|
|
155
154
|
|
|
156
155
|
@GeneralUtilities.check_arguments
|
|
157
156
|
def codeunit_throws_exception_if_codeunitfile_is_not_validatable(self, codeunit_file: str) -> bool:
|
|
158
157
|
root: etree._ElementTree = etree.parse(codeunit_file)
|
|
159
|
-
return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@throwexceptionifcodeunitfilecannotbevalidated', namespaces={
|
|
158
|
+
return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@throwexceptionifcodeunitfilecannotbevalidated', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
|
|
160
159
|
|
|
161
160
|
@GeneralUtilities.check_arguments
|
|
162
161
|
def codeunit_has_updatable_dependencies(self, codeunit_file: str) -> bool:
|
|
163
162
|
root: etree._ElementTree = etree.parse(codeunit_file)
|
|
164
|
-
return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@codeunithasupdatabledependencies', namespaces={
|
|
163
|
+
return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:properties/@codeunithasupdatabledependencies', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
|
|
165
164
|
|
|
166
165
|
@GeneralUtilities.check_arguments
|
|
167
166
|
def get_codeunit_description(self, codeunit_file: str) -> bool:
|
|
168
167
|
root: etree._ElementTree = etree.parse(codeunit_file)
|
|
169
|
-
return str(root.xpath('//cps:properties/@description', namespaces={
|
|
168
|
+
return str(root.xpath('//cps:properties/@description', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0])
|
|
170
169
|
|
|
171
170
|
@GeneralUtilities.check_arguments
|
|
172
171
|
def check_testcoverage(self, testcoverage_file_in_cobertura_format: str, repository_folder: str, codeunitname: str) -> None:
|
|
@@ -194,7 +193,7 @@ class TasksForCommonProjectStructure:
|
|
|
194
193
|
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
|
|
195
194
|
repository_folder: str = str(Path(os.path.dirname(run_testcases_file)).parent.parent.parent.absolute())
|
|
196
195
|
codeunit_folder = os.path.join(repository_folder, codeunitname)
|
|
197
|
-
self.__sc.run_program("coverage", f"run -m pytest ./{codeunitname}Tests", codeunit_folder, verbosity=verbosity)
|
|
196
|
+
self.__sc.run_program("coverage", f"run -m pytest -s ./{codeunitname}Tests", codeunit_folder, verbosity=verbosity)
|
|
198
197
|
self.__sc.run_program("coverage", "xml", codeunit_folder, verbosity=verbosity)
|
|
199
198
|
coveragefolder = os.path.join(repository_folder, codeunitname, "Other/Artifacts/TestCoverage")
|
|
200
199
|
GeneralUtilities.ensure_directory_exists(coveragefolder)
|
|
@@ -227,11 +226,11 @@ class TasksForCommonProjectStructure:
|
|
|
227
226
|
codeunit_name = os.path.basename(codeunit_folder)
|
|
228
227
|
src_folder = GeneralUtilities.resolve_relative_path(package_name, codeunit_folder) # TODO replace packagename
|
|
229
228
|
artifacts_folder = os.path.join(codeunit_folder, "Other", "Artifacts")
|
|
230
|
-
verbosity=self.get_verbosity_from_commandline_arguments(args,verbosity)
|
|
229
|
+
verbosity = self.get_verbosity_from_commandline_arguments(args, verbosity)
|
|
231
230
|
for target in targets:
|
|
232
231
|
GeneralUtilities.write_message_to_stdout(f"Build package {package_name} for target {target}...")
|
|
233
|
-
sc=ScriptCollectionCore()
|
|
234
|
-
sc.program_runner=ProgramRunnerEpew()
|
|
232
|
+
sc = ScriptCollectionCore()
|
|
233
|
+
sc.program_runner = ProgramRunnerEpew()
|
|
235
234
|
sc.run_program("flutter", f"build {target}", src_folder, verbosity)
|
|
236
235
|
if target == "web":
|
|
237
236
|
web_relase_folder = os.path.join(src_folder, "build/web")
|
|
@@ -291,11 +290,11 @@ class TasksForCommonProjectStructure:
|
|
|
291
290
|
GeneralUtilities.ensure_directory_exists(bom_folder_full)
|
|
292
291
|
if not os.path.isfile(os.path.join(codeunit_folder, "requirements.txt")):
|
|
293
292
|
raise ValueError(f"Codeunit {codeunitname} does not have a 'requirements.txt'-file.")
|
|
294
|
-
#TODO check that all values from setup.cfg are contained in requirements.txt
|
|
295
|
-
result=self.__sc.run_program("cyclonedx-py", "requirements", codeunit_folder, verbosity=verbosity)
|
|
296
|
-
bom_file=os.path.join(codeunit_folder, f"{bom_folder}/{codeunitname}.{codeunitversion}.bom.json")
|
|
293
|
+
# TODO check that all values from setup.cfg are contained in requirements.txt
|
|
294
|
+
result = self.__sc.run_program("cyclonedx-py", "requirements", codeunit_folder, verbosity=verbosity)
|
|
295
|
+
bom_file = os.path.join(codeunit_folder, f"{bom_folder}/{codeunitname}.{codeunitversion}.bom.json")
|
|
297
296
|
GeneralUtilities.ensure_file_exists(bom_file)
|
|
298
|
-
GeneralUtilities.write_text_to_file(bom_file,result[1])
|
|
297
|
+
GeneralUtilities.write_text_to_file(bom_file, result[1])
|
|
299
298
|
|
|
300
299
|
@GeneralUtilities.check_arguments
|
|
301
300
|
def standardized_tasks_push_wheel_file_to_registry(self, wheel_file: str, api_key: str, repository: str, gpg_identity: str, verbosity: int) -> None:
|
|
@@ -415,14 +414,14 @@ class TasksForCommonProjectStructure:
|
|
|
415
414
|
@GeneralUtilities.check_arguments
|
|
416
415
|
def get_property_from_commandline_arguments(commandline_arguments: list[str], property_name: str) -> str:
|
|
417
416
|
result: str = None
|
|
418
|
-
count=len(commandline_arguments)
|
|
419
|
-
loop_index
|
|
417
|
+
count = len(commandline_arguments)
|
|
418
|
+
loop_index = -1
|
|
420
419
|
for commandline_argument in commandline_arguments:
|
|
421
|
-
loop_index=loop_index+1
|
|
422
|
-
if loop_index<count-1:
|
|
420
|
+
loop_index = loop_index+1
|
|
421
|
+
if loop_index < count-1:
|
|
423
422
|
prefix = f"--overwrite_{property_name}"
|
|
424
|
-
if commandline_argument==prefix:
|
|
425
|
-
result= commandline_arguments[loop_index+1]
|
|
423
|
+
if commandline_argument == prefix:
|
|
424
|
+
result = commandline_arguments[loop_index+1]
|
|
426
425
|
return result
|
|
427
426
|
return result
|
|
428
427
|
|
|
@@ -641,15 +640,15 @@ class TasksForCommonProjectStructure:
|
|
|
641
640
|
license_file = os.path.join(repository_folder, "License.txt")
|
|
642
641
|
target = os.path.join(outputfolder, f"{codeunit_name}.License.txt")
|
|
643
642
|
shutil.copyfile(license_file, target)
|
|
644
|
-
if 0<len(files_to_sign):
|
|
643
|
+
if 0 < len(files_to_sign):
|
|
645
644
|
for key, value in files_to_sign.items():
|
|
646
|
-
dll_file=key
|
|
647
|
-
snk_file=value
|
|
648
|
-
dll_file_full=os.path.join(outputfolder,dll_file)
|
|
645
|
+
dll_file = key
|
|
646
|
+
snk_file = value
|
|
647
|
+
dll_file_full = os.path.join(outputfolder, dll_file)
|
|
649
648
|
if os.path.isfile(dll_file_full):
|
|
650
|
-
GeneralUtilities.assert_condition(self.__sc.run_program("sn",f"-vf {dll_file}", outputfolder,throw_exception_if_exitcode_is_not_zero=False)[0]==1, f"Pre-verifying of {dll_file} failed.")
|
|
651
|
-
self.__sc.run_program("sn",f"-R {dll_file} {snk_file}", outputfolder)
|
|
652
|
-
GeneralUtilities.assert_condition(self.__sc.run_program("sn",f"-vf {dll_file}", outputfolder,throw_exception_if_exitcode_is_not_zero=False)[0]==0, f"Verifying of {dll_file} failed.")
|
|
649
|
+
GeneralUtilities.assert_condition(self.__sc.run_program("sn", f"-vf {dll_file}", outputfolder, throw_exception_if_exitcode_is_not_zero=False)[0] == 1, f"Pre-verifying of {dll_file} failed.")
|
|
650
|
+
self.__sc.run_program("sn", f"-R {dll_file} {snk_file}", outputfolder)
|
|
651
|
+
GeneralUtilities.assert_condition(self.__sc.run_program("sn", f"-vf {dll_file}", outputfolder, throw_exception_if_exitcode_is_not_zero=False)[0] == 0, f"Verifying of {dll_file} failed.")
|
|
653
652
|
sarif_filename = f"{csproj_file_name_without_extension}.sarif"
|
|
654
653
|
sarif_source_file = os.path.join(sarif_folder, sarif_filename)
|
|
655
654
|
if os.path.exists(sarif_source_file):
|
|
@@ -787,9 +786,9 @@ class TasksForCommonProjectStructure:
|
|
|
787
786
|
history_folder_full = os.path.join(repository_folder, history_folder)
|
|
788
787
|
GeneralUtilities.ensure_directory_exists(history_folder_full)
|
|
789
788
|
history_argument = f" -historydir:{history_folder}"
|
|
790
|
-
argument=(f"-reports:{codeunitname}/Other/Artifacts/TestCoverage/TestCoverage.xml " +
|
|
791
|
-
|
|
792
|
-
|
|
789
|
+
argument = (f"-reports:{codeunitname}/Other/Artifacts/TestCoverage/TestCoverage.xml " +
|
|
790
|
+
f"-targetdir:{codeunitname}/Other/Artifacts/TestCoverageReport --verbosity:{verbose_argument_for_reportgenerator}{history_argument} " +
|
|
791
|
+
f"-title:{codeunitname} -tag:v{codeunit_version}")
|
|
793
792
|
self.__sc.run_program("reportgenerator", argument,
|
|
794
793
|
repository_folder, verbosity=verbosity)
|
|
795
794
|
if not add_testcoverage_history_entry:
|
|
@@ -806,13 +805,12 @@ class TasksForCommonProjectStructure:
|
|
|
806
805
|
f"--verbosity:{verbose_argument_for_reportgenerator}", os.path.join(repository_folder, codeunitname),
|
|
807
806
|
verbosity=verbosity)
|
|
808
807
|
|
|
809
|
-
|
|
810
808
|
@GeneralUtilities.check_arguments
|
|
811
809
|
def standardized_tasks_run_testcases_for_dotnet_project(self, runtestcases_file: str, targetenvironmenttype: str, verbosity: int, generate_badges: bool, target_environmenttype_mapping: dict[str, str], commandline_arguments: list[str]) -> None:
|
|
812
810
|
dotnet_build_configuration: str = target_environmenttype_mapping[targetenvironmenttype]
|
|
813
811
|
codeunit_name: str = os.path.basename(str(Path(os.path.dirname(runtestcases_file)).parent.parent.absolute()))
|
|
814
812
|
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
|
|
815
|
-
repository_folder: str = str(Path(os.path.dirname(runtestcases_file)).parent.parent.parent.absolute()).replace("\\","/")
|
|
813
|
+
repository_folder: str = str(Path(os.path.dirname(runtestcases_file)).parent.parent.parent.absolute()).replace("\\", "/")
|
|
816
814
|
coverage_file_folder = os.path.join(repository_folder, codeunit_name, "Other/Artifacts/TestCoverage")
|
|
817
815
|
temp_folder = os.path.join(tempfile.gettempdir(), str(uuid.uuid4()))
|
|
818
816
|
GeneralUtilities.ensure_directory_exists(temp_folder)
|
|
@@ -828,11 +826,11 @@ class TasksForCommonProjectStructure:
|
|
|
828
826
|
os.rename(os.path.join(coverage_file_folder, "Testcoverage.cobertura.xml"), target_file)
|
|
829
827
|
self.__remove_unrelated_package_from_testcoverage_file(target_file, codeunit_name)
|
|
830
828
|
root: etree._ElementTree = etree.parse(target_file)
|
|
831
|
-
source_base_path_in_coverage_file
|
|
832
|
-
content=GeneralUtilities.read_text_from_file(target_file)
|
|
829
|
+
source_base_path_in_coverage_file: str = root.xpath("//coverage/sources/source/text()")[0].replace("\\", "/")
|
|
830
|
+
content = GeneralUtilities.read_text_from_file(target_file)
|
|
833
831
|
GeneralUtilities.assert_condition(source_base_path_in_coverage_file.startswith(repository_folder) or repository_folder.startswith(source_base_path_in_coverage_file), f"Unexpected path for coverage. Sourcepath: \"{source_base_path_in_coverage_file}\"; repository: \"{repository_folder}\"")
|
|
834
832
|
content = re.sub('\\\\', '/', content)
|
|
835
|
-
content= re.sub("filename=\"([^\"]+)\"",lambda match: self.__standardized_tasks_run_testcases_for_dotnet_project_helper(source_base_path_in_coverage_file,codeunit_folder,match), content)
|
|
833
|
+
content = re.sub("filename=\"([^\"]+)\"", lambda match: self.__standardized_tasks_run_testcases_for_dotnet_project_helper(source_base_path_in_coverage_file, codeunit_folder, match), content)
|
|
836
834
|
GeneralUtilities.write_text_to_file(target_file, content)
|
|
837
835
|
self.run_testcases_common_post_task(repository_folder, codeunit_name, verbosity, generate_badges, targetenvironmenttype, commandline_arguments)
|
|
838
836
|
|
|
@@ -852,34 +850,34 @@ class TasksForCommonProjectStructure:
|
|
|
852
850
|
filename = "TestCoverage.xml"
|
|
853
851
|
full_file = os.path.join(folder, filename)
|
|
854
852
|
GeneralUtilities.write_text_to_file(full_file, re.sub("<source>.+<\\/source>", f"<source><!--[repository]/-->./{codeunitname}/</source>", GeneralUtilities.read_text_from_file(full_file)))
|
|
855
|
-
TasksForCommonProjectStructure.__remove_not_existing_files_from_testcoverage_file(full_file,repository_folder, codeunitname)
|
|
853
|
+
TasksForCommonProjectStructure.__remove_not_existing_files_from_testcoverage_file(full_file, repository_folder, codeunitname)
|
|
856
854
|
|
|
857
855
|
@GeneralUtilities.check_arguments
|
|
858
|
-
def __standardized_tasks_run_testcases_for_dotnet_project_helper(self,source:str,codeunit_folder:str,match:re.Match)->str:
|
|
859
|
-
filename=match.group(1)
|
|
860
|
-
file=os.path.join(source,filename)
|
|
861
|
-
#GeneralUtilities.assert_condition(os.path.isfile(file),f"File \"{file}\" does not exist.")
|
|
856
|
+
def __standardized_tasks_run_testcases_for_dotnet_project_helper(self, source: str, codeunit_folder: str, match: re.Match) -> str:
|
|
857
|
+
filename = match.group(1)
|
|
858
|
+
file = os.path.join(source, filename)
|
|
859
|
+
# GeneralUtilities.assert_condition(os.path.isfile(file),f"File \"{file}\" does not exist.")
|
|
862
860
|
GeneralUtilities.assert_condition(file.startswith(codeunit_folder),
|
|
863
|
-
|
|
864
|
-
filename_relative= f".{file[len(codeunit_folder):]}"
|
|
861
|
+
f"Unexpected path for coverage-file. File: \"{file}\"; codeunitfolder: \"{codeunit_folder}\"")
|
|
862
|
+
filename_relative = f".{file[len(codeunit_folder):]}"
|
|
865
863
|
return f'filename="{filename_relative}"'
|
|
866
864
|
|
|
867
865
|
@staticmethod
|
|
868
866
|
@GeneralUtilities.check_arguments
|
|
869
|
-
def __remove_not_existing_files_from_testcoverage_file(testcoveragefile: str,repository_folder:str, codeunit_name: str) -> None:
|
|
867
|
+
def __remove_not_existing_files_from_testcoverage_file(testcoveragefile: str, repository_folder: str, codeunit_name: str) -> None:
|
|
870
868
|
root: etree._ElementTree = etree.parse(testcoveragefile)
|
|
871
|
-
codeunit_folder=os.path.join(repository_folder,codeunit_name)
|
|
872
|
-
xpath=f"//coverage/packages/package[@name='{codeunit_name}']/classes/class"
|
|
869
|
+
codeunit_folder = os.path.join(repository_folder, codeunit_name)
|
|
870
|
+
xpath = f"//coverage/packages/package[@name='{codeunit_name}']/classes/class"
|
|
873
871
|
classes = root.xpath(xpath)
|
|
874
|
-
found_existing_files=False
|
|
872
|
+
found_existing_files = False
|
|
875
873
|
for clas in classes:
|
|
876
|
-
filename=clas.attrib['filename']
|
|
877
|
-
file=os.path.join(codeunit_folder,filename)
|
|
874
|
+
filename = clas.attrib['filename']
|
|
875
|
+
file = os.path.join(codeunit_folder, filename)
|
|
878
876
|
if os.path.isfile(file):
|
|
879
|
-
found_existing_files=True
|
|
877
|
+
found_existing_files = True
|
|
880
878
|
else:
|
|
881
879
|
clas.getparent().remove(clas)
|
|
882
|
-
GeneralUtilities.assert_condition(found_existing_files,f"No existing files in testcoderage-report-file \"{testcoveragefile}\".")
|
|
880
|
+
GeneralUtilities.assert_condition(found_existing_files, f"No existing files in testcoderage-report-file \"{testcoveragefile}\".")
|
|
883
881
|
result = etree.tostring(root).decode("utf-8")
|
|
884
882
|
GeneralUtilities.write_text_to_file(testcoveragefile, result)
|
|
885
883
|
|
|
@@ -1151,7 +1149,7 @@ class TasksForCommonProjectStructure:
|
|
|
1151
1149
|
@GeneralUtilities.check_arguments
|
|
1152
1150
|
def codeunit_is_enabled(self, codeunit_file: str) -> bool:
|
|
1153
1151
|
root: etree._ElementTree = etree.parse(codeunit_file)
|
|
1154
|
-
return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:codeunit/@enabled', namespaces={
|
|
1152
|
+
return GeneralUtilities.string_to_boolean(str(root.xpath('//cps:codeunit/@enabled', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'})[0]))
|
|
1155
1153
|
|
|
1156
1154
|
@GeneralUtilities.check_arguments
|
|
1157
1155
|
def merge_to_main_branch(self, repository_folder: str, source_branch: str = "other/next-release", target_branch: str = "main", verbosity: int = 1, additional_arguments_file: str = None, fast_forward_source_branch: bool = False) -> None:
|
|
@@ -1161,7 +1159,7 @@ class TasksForCommonProjectStructure:
|
|
|
1161
1159
|
|
|
1162
1160
|
src_branch_commit_id = self.__sc.git_get_commit_id(repository_folder, source_branch)
|
|
1163
1161
|
if (src_branch_commit_id == self.__sc.git_get_commit_id(repository_folder, target_branch)):
|
|
1164
|
-
raise ValueError(
|
|
1162
|
+
raise ValueError(f"Can not merge because the source-branch and the target-branch are on the same commit (commit-id: {src_branch_commit_id})")
|
|
1165
1163
|
|
|
1166
1164
|
self.__sc.git_checkout(repository_folder, source_branch)
|
|
1167
1165
|
self.build_codeunits(repository_folder, verbosity, "QualityCheck", additional_arguments_file, True, None)
|
|
@@ -1278,9 +1276,9 @@ class TasksForCommonProjectStructure:
|
|
|
1278
1276
|
@GeneralUtilities.check_arguments
|
|
1279
1277
|
def push_docker_build_artifact(self, push_artifacts_file: str, registry: str, verbosity: int, push_readme: bool, commandline_arguments: list[str], repository_folder_name: str) -> None:
|
|
1280
1278
|
folder_of_this_file = os.path.dirname(push_artifacts_file)
|
|
1281
|
-
filename=os.path.basename(push_artifacts_file)
|
|
1282
|
-
codeunitname_regex:str="([a-zA-Z0-9]+)"
|
|
1283
|
-
filename_regex:str=f"PushArtifacts\\.{codeunitname_regex}\\.py"
|
|
1279
|
+
filename = os.path.basename(push_artifacts_file)
|
|
1280
|
+
codeunitname_regex: str = "([a-zA-Z0-9]+)"
|
|
1281
|
+
filename_regex: str = f"PushArtifacts\\.{codeunitname_regex}\\.py"
|
|
1284
1282
|
if match := re.search(filename_regex, filename, re.IGNORECASE):
|
|
1285
1283
|
codeunitname = match.group(1)
|
|
1286
1284
|
else:
|
|
@@ -1312,11 +1310,11 @@ class TasksForCommonProjectStructure:
|
|
|
1312
1310
|
@GeneralUtilities.check_arguments
|
|
1313
1311
|
def get_dependent_code_units(self, codeunit_file: str) -> set[str]:
|
|
1314
1312
|
root: etree._ElementTree = etree.parse(codeunit_file)
|
|
1315
|
-
return set(root.xpath('//cps:dependentcodeunit/text()', namespaces={
|
|
1313
|
+
return set(root.xpath('//cps:dependentcodeunit/text()', namespaces={'cps': 'https://projects.aniondev.de/PublicProjects/Common/ProjectTemplates/-/tree/main/Conventions/RepositoryStructure/CommonProjectStructure'}))
|
|
1316
1314
|
|
|
1317
1315
|
@GeneralUtilities.check_arguments
|
|
1318
|
-
def dependent_codeunit_exists(self, repository:str,codeunit:str) -> None:
|
|
1319
|
-
codeunit_file=f"{repository}/{codeunit}/{codeunit}.codeunit.xml"
|
|
1316
|
+
def dependent_codeunit_exists(self, repository: str, codeunit: str) -> None:
|
|
1317
|
+
codeunit_file = f"{repository}/{codeunit}/{codeunit}.codeunit.xml"
|
|
1320
1318
|
return os.path.isfile(codeunit_file)
|
|
1321
1319
|
|
|
1322
1320
|
@GeneralUtilities.check_arguments
|
|
@@ -1411,7 +1409,7 @@ class TasksForCommonProjectStructure:
|
|
|
1411
1409
|
actual_author_formatted = f"{actual_author[0]} <{actual_author[1]}>"
|
|
1412
1410
|
raise ValueError(f'Author/Comitter "{actual_author_formatted}" is not in the codeunit-developer-team. If {actual_author} is a authorized developer for this codeunit you should consider defining this in the codeunit-file or adapting the name using a .mailmap-file (see https://git-scm.com/docs/gitmailmap). The developer-team-check can also be disabled using the property validate_developers_of_repository.')
|
|
1413
1411
|
|
|
1414
|
-
dependent_codeunits=self.get_dependent_code_units(codeunit_file)
|
|
1412
|
+
dependent_codeunits = self.get_dependent_code_units(codeunit_file)
|
|
1415
1413
|
for dependent_codeunit in dependent_codeunits:
|
|
1416
1414
|
if not self.dependent_codeunit_exists(repository_folder, dependent_codeunit):
|
|
1417
1415
|
raise ValueError(f"Codeunit {codeunit_name} does have dependent codeunit {dependent_codeunit} which does not exist.")
|
|
@@ -1467,7 +1465,7 @@ class TasksForCommonProjectStructure:
|
|
|
1467
1465
|
src_prefix = latest_tag
|
|
1468
1466
|
dst = "HEAD"
|
|
1469
1467
|
dst_prefix = f"v{current_version}"
|
|
1470
|
-
self.__sc.run_program_argsasarray(
|
|
1468
|
+
self.__sc.run_program_argsasarray("sh", ['-c', f'git diff --src-prefix={src_prefix}/ --dst-prefix={dst_prefix}/ {src} {dst} -- {codeunit_name} | pygmentize -l diff -f html -O full -o {target_file} -P style=github-dark'], repository_folder)
|
|
1471
1469
|
|
|
1472
1470
|
@GeneralUtilities.check_arguments
|
|
1473
1471
|
def get_version_of_project(self, repository_folder: str) -> str:
|
|
@@ -1504,36 +1502,36 @@ class TasksForCommonProjectStructure:
|
|
|
1504
1502
|
# TODO check if there are errors in sarif-file
|
|
1505
1503
|
|
|
1506
1504
|
@GeneralUtilities.check_arguments
|
|
1507
|
-
def standardized_tasks_run_testcases_for_flutter_project_in_common_project_structure(self, script_file: str, verbosity: int, args: list[str], package_name: str,build_environment_target_type: str, generate_badges: bool):
|
|
1505
|
+
def standardized_tasks_run_testcases_for_flutter_project_in_common_project_structure(self, script_file: str, verbosity: int, args: list[str], package_name: str, build_environment_target_type: str, generate_badges: bool):
|
|
1508
1506
|
codeunit_folder = GeneralUtilities.resolve_relative_path("../../..", script_file)
|
|
1509
1507
|
repository_folder = GeneralUtilities.resolve_relative_path("..", codeunit_folder)
|
|
1510
|
-
codeunit_name=os.path.basename(codeunit_folder)
|
|
1508
|
+
codeunit_name = os.path.basename(codeunit_folder)
|
|
1511
1509
|
src_folder = GeneralUtilities.resolve_relative_path(package_name, codeunit_folder)
|
|
1512
|
-
verbosity=self.get_verbosity_from_commandline_arguments(args,verbosity)
|
|
1513
|
-
sc=ScriptCollectionCore()
|
|
1514
|
-
sc.program_runner=ProgramRunnerEpew()
|
|
1510
|
+
verbosity = self.get_verbosity_from_commandline_arguments(args, verbosity)
|
|
1511
|
+
sc = ScriptCollectionCore()
|
|
1512
|
+
sc.program_runner = ProgramRunnerEpew()
|
|
1515
1513
|
sc.run_program("flutter", "test --coverage", src_folder, verbosity)
|
|
1516
|
-
test_coverage_folder_relative="Other/Artifacts/TestCoverage"
|
|
1517
|
-
test_coverage_folder=GeneralUtilities.resolve_relative_path(test_coverage_folder_relative, codeunit_folder)
|
|
1514
|
+
test_coverage_folder_relative = "Other/Artifacts/TestCoverage"
|
|
1515
|
+
test_coverage_folder = GeneralUtilities.resolve_relative_path(test_coverage_folder_relative, codeunit_folder)
|
|
1518
1516
|
GeneralUtilities.ensure_directory_exists(test_coverage_folder)
|
|
1519
|
-
coverage_file_relative=f"{test_coverage_folder_relative}/TestCoverage.xml"
|
|
1520
|
-
coverage_file=GeneralUtilities.resolve_relative_path(coverage_file_relative, codeunit_folder)
|
|
1517
|
+
coverage_file_relative = f"{test_coverage_folder_relative}/TestCoverage.xml"
|
|
1518
|
+
coverage_file = GeneralUtilities.resolve_relative_path(coverage_file_relative, codeunit_folder)
|
|
1521
1519
|
sc.run_program("lcov_cobertura", f"coverage/lcov.info --base-dir . --excludes test --output ../{coverage_file_relative} --demangle", src_folder, verbosity)
|
|
1522
|
-
content=GeneralUtilities.read_text_from_file(coverage_file)
|
|
1520
|
+
content = GeneralUtilities.read_text_from_file(coverage_file)
|
|
1523
1521
|
content = re.sub('<![^<]+>', '', content)
|
|
1524
1522
|
content = re.sub('\\\\', '/', content)
|
|
1525
1523
|
content = re.sub('\\ name=\\"lib\\"', '', content)
|
|
1526
1524
|
content = re.sub('<package ', f'<package name="{codeunit_name}" ', content)
|
|
1527
1525
|
content = re.sub('\\ filename=\\"lib/', f' filename="{package_name}/lib/', content)
|
|
1528
|
-
GeneralUtilities.write_text_to_file(coverage_file,content)
|
|
1529
|
-
self.run_testcases_common_post_task(repository_folder,codeunit_name,verbosity,generate_badges,build_environment_target_type,args)
|
|
1526
|
+
GeneralUtilities.write_text_to_file(coverage_file, content)
|
|
1527
|
+
self.run_testcases_common_post_task(repository_folder, codeunit_name, verbosity, generate_badges, build_environment_target_type, args)
|
|
1530
1528
|
|
|
1531
1529
|
@GeneralUtilities.check_arguments
|
|
1532
1530
|
def standardized_tasks_run_testcases_for_angular_codeunit(self, runtestcases_script_file: str, build_environment_target_type: str, generate_badges: bool, verbosity: int, commandline_arguments: list[str]) -> None:
|
|
1533
1531
|
codeunit_name: str = os.path.basename(str(Path(os.path.dirname(runtestcases_script_file)).parent.parent.absolute()))
|
|
1534
1532
|
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, verbosity)
|
|
1535
1533
|
codeunit_folder = GeneralUtilities.resolve_relative_path("../..", os.path.dirname(runtestcases_script_file))
|
|
1536
|
-
repository_folder=os.path.dirname(codeunit_folder)
|
|
1534
|
+
repository_folder = os.path.dirname(codeunit_folder)
|
|
1537
1535
|
self.run_with_epew(
|
|
1538
1536
|
"ng", "test --watch=false --browsers ChromeHeadless --code-coverage", codeunit_folder, verbosity=verbosity)
|
|
1539
1537
|
coverage_folder = os.path.join(codeunit_folder, "Other", "Artifacts", "TestCoverage")
|
|
@@ -1541,7 +1539,7 @@ class TasksForCommonProjectStructure:
|
|
|
1541
1539
|
GeneralUtilities.ensure_file_does_not_exist(target_file)
|
|
1542
1540
|
os.rename(os.path.join(coverage_folder, "cobertura-coverage.xml"), target_file)
|
|
1543
1541
|
self.__rename_packagename_in_coverage_file(target_file, codeunit_name)
|
|
1544
|
-
content=GeneralUtilities.read_text_from_file(target_file)
|
|
1542
|
+
content = GeneralUtilities.read_text_from_file(target_file)
|
|
1545
1543
|
content = re.sub('\\\\', '/', content)
|
|
1546
1544
|
self.run_testcases_common_post_task(repository_folder, codeunit_name, verbosity, generate_badges, build_environment_target_type, commandline_arguments)
|
|
1547
1545
|
|
|
@@ -1596,7 +1594,7 @@ class TasksForCommonProjectStructure:
|
|
|
1596
1594
|
@GeneralUtilities.check_arguments
|
|
1597
1595
|
def set_constant_for_codeunitmajorversion(self, codeunit_folder: str) -> None:
|
|
1598
1596
|
codeunit_version: str = self.get_version_of_codeunit_folder(codeunit_folder)
|
|
1599
|
-
major_version=int(codeunit_version.split(".")[0])
|
|
1597
|
+
major_version = int(codeunit_version.split(".")[0])
|
|
1600
1598
|
self.set_constant(codeunit_folder, "CodeUnitMajorVersion", str(major_version))
|
|
1601
1599
|
|
|
1602
1600
|
@GeneralUtilities.check_arguments
|
|
@@ -1774,8 +1772,8 @@ class TasksForCommonProjectStructure:
|
|
|
1774
1772
|
shutil.copytree(artifacts_folder, target_folder)
|
|
1775
1773
|
|
|
1776
1774
|
@GeneralUtilities.check_arguments
|
|
1777
|
-
def add_github_release(self, productname: str, projectversion: str, build_artifacts_folder: str, github_username: str, repository_folder: str,
|
|
1778
|
-
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments,
|
|
1775
|
+
def add_github_release(self, productname: str, projectversion: str, build_artifacts_folder: str, github_username: str, repository_folder: str, commandline_arguments: list[str]) -> None:
|
|
1776
|
+
verbosity = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(commandline_arguments, 1)
|
|
1779
1777
|
github_repo = f"{github_username}/{productname}"
|
|
1780
1778
|
artifact_files = []
|
|
1781
1779
|
codeunits = self.get_codeunits(repository_folder)
|
|
@@ -1807,7 +1805,7 @@ class TasksForCommonProjectStructure:
|
|
|
1807
1805
|
codeunit_name = os.path.basename(codeunit_folder)
|
|
1808
1806
|
|
|
1809
1807
|
build_folder = os.path.join(codeunit_folder, "Other", "Build")
|
|
1810
|
-
self.__sc.run_program("python", "Build.py", build_folder)
|
|
1808
|
+
self.__sc.run_program("python", "Build.py", build_folder, verbosity)
|
|
1811
1809
|
|
|
1812
1810
|
csproj_file = os.path.join(codeunit_folder, codeunit_name, f"{codeunit_name}.csproj")
|
|
1813
1811
|
self.__sc.update_dependencies_of_dotnet_project(csproj_file, verbosity)
|
|
@@ -1819,11 +1817,11 @@ class TasksForCommonProjectStructure:
|
|
|
1819
1817
|
pass # TODO generalize and add option to ignore certain dependencies
|
|
1820
1818
|
|
|
1821
1819
|
@GeneralUtilities.check_arguments
|
|
1822
|
-
def run_local_test_service(self, file:str):
|
|
1823
|
-
example_folder=os.path.dirname(file)
|
|
1824
|
-
example_name=os.path.basename(example_folder)
|
|
1825
|
-
title=f"Test{example_name}"
|
|
1826
|
-
self.__sc.run_program("docker",f"compose -p {title.lower()} up",example_folder,title=title)
|
|
1820
|
+
def run_local_test_service(self, file: str):
|
|
1821
|
+
example_folder = os.path.dirname(file)
|
|
1822
|
+
example_name = os.path.basename(example_folder)
|
|
1823
|
+
title = f"Test{example_name}"
|
|
1824
|
+
self.__sc.run_program("docker", f"compose -p {title.lower()} up", example_folder, title=title)
|
|
1827
1825
|
|
|
1828
1826
|
@GeneralUtilities.check_arguments
|
|
1829
1827
|
def standardized_tasks_update_version_in_docker_examples(self, file, codeunit_version) -> None:
|
|
@@ -1850,9 +1848,9 @@ class TasksForCommonProjectStructure:
|
|
|
1850
1848
|
image_filename = os.path.basename(sc.find_file_by_extension(oci_image_artifacts_folder, "tar"))
|
|
1851
1849
|
codeunit_name = os.path.basename(GeneralUtilities.resolve_relative_path("../../../../..", folder))
|
|
1852
1850
|
if remove_old_container:
|
|
1853
|
-
docker_compose_file=f"{folder}/docker-compose.yml"
|
|
1854
|
-
container_names=[]
|
|
1855
|
-
lines=GeneralUtilities.read_lines_from_file(docker_compose_file)
|
|
1851
|
+
docker_compose_file = f"{folder}/docker-compose.yml"
|
|
1852
|
+
container_names = []
|
|
1853
|
+
lines = GeneralUtilities.read_lines_from_file(docker_compose_file)
|
|
1856
1854
|
for line in lines:
|
|
1857
1855
|
if match := re.search("container_name:\\s*'?([^']+)'?", line):
|
|
1858
1856
|
container_names.append(match.group(1))
|
|
@@ -1873,7 +1871,6 @@ class TasksForCommonProjectStructure:
|
|
|
1873
1871
|
GeneralUtilities.write_message_to_stdout("Start docker-container...")
|
|
1874
1872
|
sc_epew.run_program("docker", f"compose --project-name {docker_project_name} up --abort-on-container-exit", folder, verbosity=verbosity)
|
|
1875
1873
|
|
|
1876
|
-
|
|
1877
1874
|
@GeneralUtilities.check_arguments
|
|
1878
1875
|
def create_artifact_for_development_certificate(self, codeunit_folder: str):
|
|
1879
1876
|
ce_source_folder = GeneralUtilities.resolve_relative_path("Other/Resources/DevelopmentCertificate", codeunit_folder)
|
|
@@ -1894,6 +1891,18 @@ class TasksForCommonProjectStructure:
|
|
|
1894
1891
|
result.append(str(item))
|
|
1895
1892
|
return result
|
|
1896
1893
|
|
|
1894
|
+
@GeneralUtilities.check_arguments
|
|
1895
|
+
def get_project_name(self, repository_folder: str) -> str:
|
|
1896
|
+
for file in GeneralUtilities.get_direct_files_of_folder(repository_folder):
|
|
1897
|
+
if file.endswith(".code-workspace"):
|
|
1898
|
+
return Path(file).stem
|
|
1899
|
+
raise ValueError(f'Project-name can not be calculated for repository "{repository_folder}"')
|
|
1900
|
+
|
|
1901
|
+
def __check_target_environmenttype(self, target_environmenttype: str):
|
|
1902
|
+
allowed_values = list(self.get_default_target_environmenttype_mapping().values())
|
|
1903
|
+
if not (target_environmenttype in allowed_values):
|
|
1904
|
+
raise ValueError(f"Invalid target-environmenttype: '{target_environmenttype}'")
|
|
1905
|
+
|
|
1897
1906
|
@GeneralUtilities.check_arguments
|
|
1898
1907
|
def build_codeunit(self, codeunit_folder: str, verbosity: int = 1, target_environmenttype: str = "QualityCheck",
|
|
1899
1908
|
additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None,
|
|
@@ -1905,7 +1914,7 @@ class TasksForCommonProjectStructure:
|
|
|
1905
1914
|
is_pre_merge, export_target_directory, assume_dependent_codeunits_are_already_built)
|
|
1906
1915
|
|
|
1907
1916
|
@GeneralUtilities.check_arguments
|
|
1908
|
-
def build_codeunitsC(self, repository_folder: str, image:str, verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None) -> None:
|
|
1917
|
+
def build_codeunitsC(self, repository_folder: str, image: str, verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None) -> None:
|
|
1909
1918
|
if target_environmenttype == "Development":
|
|
1910
1919
|
raise ValueError(f"build_codeunitsC is not available for target_environmenttype {target_environmenttype}.")
|
|
1911
1920
|
# TODO handle additional_arguments_file
|
|
@@ -1918,19 +1927,14 @@ class TasksForCommonProjectStructure:
|
|
|
1918
1927
|
|
|
1919
1928
|
@GeneralUtilities.check_arguments
|
|
1920
1929
|
def build_codeunits(self, repository_folder: str, verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None) -> None:
|
|
1930
|
+
self.__check_target_environmenttype(target_environmenttype)
|
|
1921
1931
|
repository_folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(repository_folder)
|
|
1922
1932
|
codeunits = self.get_codeunits(repository_folder, False)
|
|
1923
1933
|
self.build_specific_codeunits(repository_folder, codeunits, verbosity, target_environmenttype, additional_arguments_file, is_pre_merge, export_target_directory)
|
|
1924
1934
|
|
|
1925
|
-
@GeneralUtilities.check_arguments
|
|
1926
|
-
def get_project_name(self, repository_folder:str) -> str:
|
|
1927
|
-
for file in GeneralUtilities.get_direct_files_of_folder(repository_folder):
|
|
1928
|
-
if file.endswith(".code-workspace"):
|
|
1929
|
-
return Path(file).stem
|
|
1930
|
-
raise ValueError(f'Project-name can not be calculated for repository "{repository_folder}"')
|
|
1931
|
-
|
|
1932
1935
|
@GeneralUtilities.check_arguments
|
|
1933
1936
|
def build_specific_codeunits(self, repository_folder: str, codeunits: list[str], verbosity: int = 1, target_environmenttype: str = "QualityCheck", additional_arguments_file: str = None, is_pre_merge: bool = False, export_target_directory: str = None, assume_dependent_codeunits_are_already_built: bool = True) -> None:
|
|
1937
|
+
self.__check_target_environmenttype(target_environmenttype)
|
|
1934
1938
|
repository_folder = GeneralUtilities.resolve_relative_path_from_current_working_directory(repository_folder)
|
|
1935
1939
|
contains_uncommitted_changes = self.__sc.git_repository_has_uncommitted_changes(repository_folder)
|
|
1936
1940
|
if is_pre_merge and contains_uncommitted_changes:
|
|
@@ -2009,14 +2013,13 @@ class TasksForCommonProjectStructure:
|
|
|
2009
2013
|
|
|
2010
2014
|
@GeneralUtilities.check_arguments
|
|
2011
2015
|
def __check_whether_workspace_file_exists(self, repository_folder: str) -> None:
|
|
2012
|
-
count=0
|
|
2016
|
+
count = 0
|
|
2013
2017
|
for file in GeneralUtilities.get_direct_files_of_folder(repository_folder):
|
|
2014
2018
|
if file.endswith(".code-workspace"):
|
|
2015
2019
|
count = count + 1
|
|
2016
2020
|
if count != 1:
|
|
2017
2021
|
raise ValueError('The repository must contain exactly one ".code-workspace"-file on the top-level.')
|
|
2018
2022
|
|
|
2019
|
-
|
|
2020
2023
|
@GeneralUtilities.check_arguments
|
|
2021
2024
|
def update_dependency_in_resources_folder(self, update_dependencies_file, dependency_name: str, latest_version_function: str) -> None:
|
|
2022
2025
|
dependency_folder = GeneralUtilities.resolve_relative_path(f"../Resources/Dependencies/{dependency_name}", update_dependencies_file)
|
|
@@ -2129,7 +2132,7 @@ class TasksForCommonProjectStructure:
|
|
|
2129
2132
|
for file in GeneralUtilities.get_all_files_of_folder(files_folder):
|
|
2130
2133
|
if file.endswith(".plantuml"):
|
|
2131
2134
|
argument = ['-jar', f'{plant_uml_folder}/plantuml.jar', os.path.basename(file).replace("\\", "/"), '-tsvg']
|
|
2132
|
-
sc.run_program_argsasarray("java", argument, os.path.dirname(file))
|
|
2135
|
+
sc.run_program_argsasarray("java", argument, os.path.dirname(file),verbosity=0)
|
|
2133
2136
|
|
|
2134
2137
|
@GeneralUtilities.check_arguments
|
|
2135
2138
|
def load_deb_control_file_content(self, file: str, codeunitname: str, codeunitversion: str, installedsize: int, maintainername: str, maintaineremail: str, description: str,) -> str:
|
|
@@ -2161,34 +2164,29 @@ class TasksForCommonProjectStructure:
|
|
|
2161
2164
|
control_file_content = self.load_deb_control_file_content(control_file, codeunit_name, self.get_version_of_codeunit_folder(codeunit_folder), installedsize, maintainername, maintaineremail, description)
|
|
2162
2165
|
self.__sc.create_deb_package(codeunit_name, binary_folder, control_file_content, deb_output_folder, verbosity, 555)
|
|
2163
2166
|
|
|
2164
|
-
|
|
2165
2167
|
@GeneralUtilities.check_arguments
|
|
2166
2168
|
def update_year_in_license_file_in_common_scripts_file(self, common_tasks_scripts_file: str) -> None:
|
|
2167
|
-
self.update_year_in_license_file(GeneralUtilities.resolve_relative_path("../../..",common_tasks_scripts_file))
|
|
2168
|
-
|
|
2169
|
+
self.update_year_in_license_file(GeneralUtilities.resolve_relative_path("../../..", common_tasks_scripts_file))
|
|
2169
2170
|
|
|
2170
2171
|
@GeneralUtilities.check_arguments
|
|
2171
2172
|
def update_year_in_license_file(self, repository_folder: str) -> None:
|
|
2172
|
-
self.__sc.update_year_in_first_line_of_file(os.path.join(repository_folder,"License.txt"))
|
|
2173
|
-
|
|
2173
|
+
self.__sc.update_year_in_first_line_of_file(os.path.join(repository_folder, "License.txt"))
|
|
2174
2174
|
|
|
2175
2175
|
@GeneralUtilities.check_arguments
|
|
2176
2176
|
def update_year_for_dotnet_codeunit_in_common_scripts_file(self, common_tasks_scripts_file: str) -> None:
|
|
2177
|
-
self.update_year_for_dotnet_codeunit(GeneralUtilities.resolve_relative_path("../..",common_tasks_scripts_file))
|
|
2178
|
-
|
|
2177
|
+
self.update_year_for_dotnet_codeunit(GeneralUtilities.resolve_relative_path("../..", common_tasks_scripts_file))
|
|
2179
2178
|
|
|
2180
2179
|
@GeneralUtilities.check_arguments
|
|
2181
2180
|
def update_year_for_dotnet_codeunit(self, codeunit_folder: str) -> None:
|
|
2182
|
-
codeunit_name=os.path.basename(codeunit_folder)
|
|
2183
|
-
csproj_file=os.path.join(codeunit_folder,codeunit_name,f"{codeunit_name}.csproj")
|
|
2181
|
+
codeunit_name = os.path.basename(codeunit_folder)
|
|
2182
|
+
csproj_file = os.path.join(codeunit_folder, codeunit_name, f"{codeunit_name}.csproj")
|
|
2184
2183
|
self.__sc.update_year_in_copyright_tags(csproj_file)
|
|
2185
|
-
csprojtests_file=os.path.join(codeunit_folder,f"{codeunit_name}Tests",f"{codeunit_name}Tests.csproj")
|
|
2184
|
+
csprojtests_file = os.path.join(codeunit_folder, f"{codeunit_name}Tests", f"{codeunit_name}Tests.csproj")
|
|
2186
2185
|
self.__sc.update_year_in_copyright_tags(csprojtests_file)
|
|
2187
|
-
nuspec_file=os.path.join(codeunit_folder,"Other","Build",f"{codeunit_name}.nuspec")
|
|
2186
|
+
nuspec_file = os.path.join(codeunit_folder, "Other", "Build", f"{codeunit_name}.nuspec")
|
|
2188
2187
|
if os.path.isfile(nuspec_file):
|
|
2189
2188
|
self.__sc.update_year_in_copyright_tags(nuspec_file)
|
|
2190
2189
|
|
|
2191
|
-
|
|
2192
2190
|
@GeneralUtilities.check_arguments
|
|
2193
2191
|
def repository_has_codeunits(self, repository: str, ignore_disabled_codeunits: bool = True) -> bool:
|
|
2194
2192
|
return len(self.get_codeunits(repository, ignore_disabled_codeunits))
|
|
@@ -2285,7 +2283,7 @@ class TasksForCommonProjectStructure:
|
|
|
2285
2283
|
codeunit_hast_testable_sourcecode = self.codeunit_has_testable_sourcecode(codeunit_file)
|
|
2286
2284
|
if codeunit_hast_testable_sourcecode:
|
|
2287
2285
|
GeneralUtilities.write_message_to_stdout('Run "RunTestcases.py"...')
|
|
2288
|
-
self.__sc.run_program("python", f"RunTestcases.py{additional_arguments_r}{general_argument}",quality_folder, verbosity=verbosity_for_executed_programs, throw_exception_if_exitcode_is_not_zero=True)
|
|
2286
|
+
self.__sc.run_program("python", f"RunTestcases.py{additional_arguments_r}{general_argument}", quality_folder, verbosity=verbosity_for_executed_programs, throw_exception_if_exitcode_is_not_zero=True)
|
|
2289
2287
|
self.verify_artifact_exists(codeunit_folder, dict[str, bool]({"TestCoverage": True, "TestCoverageReport": False}))
|
|
2290
2288
|
|
|
2291
2289
|
GeneralUtilities.write_message_to_stdout('Run "Linting.py"...')
|
|
@@ -2323,3 +2321,128 @@ class TasksForCommonProjectStructure:
|
|
|
2323
2321
|
</cps:artifactsinformation>""")
|
|
2324
2322
|
# TODO validate artifactsinformation_file against xsd
|
|
2325
2323
|
GeneralUtilities.write_message_to_stdout(f"Finished building codeunit {codeunit_name} without errors.")
|
|
2324
|
+
|
|
2325
|
+
@GeneralUtilities.check_arguments
|
|
2326
|
+
def generic_update_dependencies(self, repository_folder: str):
|
|
2327
|
+
codeunits = self.get_codeunits(repository_folder)
|
|
2328
|
+
updated_dependencies = False
|
|
2329
|
+
for codeunit in codeunits:
|
|
2330
|
+
codeunit_file = os.path.join(repository_folder, codeunit, f"{codeunit}.codeunit.xml")
|
|
2331
|
+
codeunit_has_updatable_dependencies = self.codeunit_has_updatable_dependencies(codeunit_file)
|
|
2332
|
+
if codeunit_has_updatable_dependencies:
|
|
2333
|
+
codeunit_folder = os.path.join(repository_folder, codeunit)
|
|
2334
|
+
update_dependencies_script_folder = os.path.join(codeunit_folder, "Other")
|
|
2335
|
+
self.__sc.run_program("python", "UpdateDependencies.py", update_dependencies_script_folder)#TODO set verbosity
|
|
2336
|
+
if self.__sc.git_repository_has_uncommitted_changes(repository_folder):
|
|
2337
|
+
version_of_project = self.get_version_of_project(repository_folder)
|
|
2338
|
+
changelog_file = os.path.join(repository_folder, "Other", "Resources", "Changelog", f"v{version_of_project}.md")
|
|
2339
|
+
if not os.path.isfile(changelog_file):
|
|
2340
|
+
GeneralUtilities.write_text_to_file(changelog_file, """# Release notes
|
|
2341
|
+
|
|
2342
|
+
## Changes
|
|
2343
|
+
|
|
2344
|
+
- Updated dependencies.
|
|
2345
|
+
""")
|
|
2346
|
+
GeneralUtilities.write_message_to_stdout(f"Updated dependencies in codeunit {codeunit}.")
|
|
2347
|
+
updated_dependencies = True
|
|
2348
|
+
else:
|
|
2349
|
+
GeneralUtilities.write_message_to_stdout(f"There are no dependencies to update in codeunit {codeunit}.")
|
|
2350
|
+
if updated_dependencies:
|
|
2351
|
+
self.__sc.run_program("scbuildcodeunits", "--targetenvironment QualityCheck", repository_folder)#TODO set verbosity
|
|
2352
|
+
self.__sc.git_commit(repository_folder, "Updated dependencies")
|
|
2353
|
+
|
|
2354
|
+
class GenericPrepareNewReleaseArguments:
|
|
2355
|
+
current_file: str
|
|
2356
|
+
product_name: str
|
|
2357
|
+
commandline_arguments: list[str]
|
|
2358
|
+
|
|
2359
|
+
def __init__(self, current_file: str, product_name: str, commandline_arguments: list[str]):
|
|
2360
|
+
self.current_file = current_file
|
|
2361
|
+
self.product_name = product_name
|
|
2362
|
+
self.commandline_arguments = commandline_arguments
|
|
2363
|
+
|
|
2364
|
+
@GeneralUtilities.check_arguments
|
|
2365
|
+
def generic_prepare_new_release(self, generic_prepare_new_release_arguments: GenericPrepareNewReleaseArguments):
|
|
2366
|
+
|
|
2367
|
+
# constants
|
|
2368
|
+
folder_of_this_file = os.path.dirname(generic_prepare_new_release_arguments.current_file)
|
|
2369
|
+
build_repository_folder = GeneralUtilities.resolve_relative_path("../..", folder_of_this_file)
|
|
2370
|
+
|
|
2371
|
+
repository_folder = GeneralUtilities.resolve_relative_path(f"../../Submodules/{generic_prepare_new_release_arguments.product_name}", folder_of_this_file)
|
|
2372
|
+
verbosity: int = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(generic_prepare_new_release_arguments.commandline_arguments, 1)
|
|
2373
|
+
merge_source_branch = "other/next-release"
|
|
2374
|
+
|
|
2375
|
+
# prepare
|
|
2376
|
+
self.assert_no_uncommitted_changes(repository_folder)
|
|
2377
|
+
self.__sc.git_checkout(repository_folder, merge_source_branch)
|
|
2378
|
+
self.generic_update_dependencies(repository_folder)
|
|
2379
|
+
self.merge_to_main_branch(repository_folder, merge_source_branch, verbosity=verbosity, fast_forward_source_branch=True)
|
|
2380
|
+
self.__sc.git_commit(build_repository_folder, "Updated submodule due to merge to main-branch.")
|
|
2381
|
+
|
|
2382
|
+
class GenericCreateReleaseArguments():
|
|
2383
|
+
current_file: str
|
|
2384
|
+
product_name: str
|
|
2385
|
+
common_remote_name: str
|
|
2386
|
+
artifacts_target_folder: str
|
|
2387
|
+
commandline_arguments: list[str]
|
|
2388
|
+
|
|
2389
|
+
def __init__(self, current_file: str, product_name: str, common_remote_name: str, artifacts_target_folder: str,commandline_arguments: list[str]):
|
|
2390
|
+
self.current_file = current_file
|
|
2391
|
+
self.product_name = product_name
|
|
2392
|
+
self.common_remote_name = common_remote_name
|
|
2393
|
+
self.artifacts_target_folder = artifacts_target_folder
|
|
2394
|
+
self.commandline_arguments = commandline_arguments
|
|
2395
|
+
|
|
2396
|
+
@GeneralUtilities.check_arguments
|
|
2397
|
+
def generic_create_release(self, generic_create_release_arguments:GenericCreateReleaseArguments) -> str:
|
|
2398
|
+
folder_of_this_file = os.path.dirname(generic_create_release_arguments.current_file)
|
|
2399
|
+
build_repository_folder = GeneralUtilities.resolve_relative_path("../..", folder_of_this_file)
|
|
2400
|
+
repository_folder_name = generic_create_release_arguments.product_name
|
|
2401
|
+
repository_folder = GeneralUtilities.resolve_relative_path(f"../../Submodules/{generic_create_release_arguments.product_name}", folder_of_this_file)
|
|
2402
|
+
additional_arguments_file = os.path.join(folder_of_this_file, "AdditionalArguments.configuration")
|
|
2403
|
+
verbosity: int = TasksForCommonProjectStructure.get_verbosity_from_commandline_arguments(generic_create_release_arguments.commandline_arguments, 1)
|
|
2404
|
+
createReleaseConfiguration: CreateReleaseConfiguration = CreateReleaseConfiguration(
|
|
2405
|
+
generic_create_release_arguments.product_name, generic_create_release_arguments.common_remote_name, generic_create_release_arguments.artifacts_target_folder, folder_of_this_file, verbosity, repository_folder, additional_arguments_file, repository_folder_name)
|
|
2406
|
+
self.__sc.git_commit(build_repository_folder, "Updated submodule")
|
|
2407
|
+
|
|
2408
|
+
# create release
|
|
2409
|
+
new_version = self.merge_to_stable_branch(generic_create_release_arguments.current_file, createReleaseConfiguration)
|
|
2410
|
+
return new_version
|
|
2411
|
+
|
|
2412
|
+
class UpdateHTTPDocumentationArguments:
|
|
2413
|
+
current_file: str
|
|
2414
|
+
product_name: str
|
|
2415
|
+
common_remote_name: str
|
|
2416
|
+
new_project_version: str
|
|
2417
|
+
reference_repository_name: str
|
|
2418
|
+
commandline_arguments: list[str]
|
|
2419
|
+
main_branch_name: str
|
|
2420
|
+
|
|
2421
|
+
def __init__(self, current_file: str, product_name: str, common_remote_name: str, new_project_version: str, reference_repository_name: str, commandline_arguments: list[str]):
|
|
2422
|
+
self.current_file = current_file
|
|
2423
|
+
self.product_name = product_name
|
|
2424
|
+
self.common_remote_name = common_remote_name
|
|
2425
|
+
self.new_project_version = new_project_version
|
|
2426
|
+
self.reference_repository_name = reference_repository_name
|
|
2427
|
+
self.commandline_arguments = commandline_arguments
|
|
2428
|
+
self.main_branch_name = "main"
|
|
2429
|
+
|
|
2430
|
+
@GeneralUtilities.check_arguments
|
|
2431
|
+
def update_http_documentation(self, update_http_documentation_arguments: UpdateHTTPDocumentationArguments):
|
|
2432
|
+
folder_of_this_file = str(os.path.dirname(update_http_documentation_arguments.current_file))
|
|
2433
|
+
|
|
2434
|
+
ref_repo = GeneralUtilities.resolve_relative_path(f"../../Submodules/{update_http_documentation_arguments.reference_repository_name}", folder_of_this_file)
|
|
2435
|
+
self.__sc.git_checkout(ref_repo, update_http_documentation_arguments.main_branch_name)
|
|
2436
|
+
|
|
2437
|
+
# update reference
|
|
2438
|
+
target = os.path.join(ref_repo, "Reference", update_http_documentation_arguments.product_name)
|
|
2439
|
+
GeneralUtilities.ensure_directory_does_not_exist(target)
|
|
2440
|
+
shutil.copytree(GeneralUtilities.resolve_relative_path(f"../../Submodules/{update_http_documentation_arguments.product_name}Reference/ReferenceContent", folder_of_this_file), target)
|
|
2441
|
+
self.__sc.git_commit(ref_repo, f"Added reference of {update_http_documentation_arguments.product_name} v{update_http_documentation_arguments.new_project_version}")
|
|
2442
|
+
|
|
2443
|
+
# Sync reference-repository
|
|
2444
|
+
self.__sc.git_fetch(ref_repo, update_http_documentation_arguments.common_remote_name)
|
|
2445
|
+
self.__sc.git_merge(ref_repo, update_http_documentation_arguments.common_remote_name+"/"+update_http_documentation_arguments.main_branch_name, update_http_documentation_arguments.main_branch_name)
|
|
2446
|
+
self.__sc.git_checkout(ref_repo, update_http_documentation_arguments.main_branch_name)
|
|
2447
|
+
self.__sc.git_push(ref_repo, update_http_documentation_arguments.common_remote_name, update_http_documentation_arguments.main_branch_name, update_http_documentation_arguments.main_branch_name)
|
|
2448
|
+
self.__sc.git_commit(GeneralUtilities.resolve_relative_path("../..", folder_of_this_file), f"Updated content of {update_http_documentation_arguments.product_name} v{update_http_documentation_arguments.new_project_version} in {update_http_documentation_arguments.reference_repository_name}-submodule")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ScriptCollection
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: The ScriptCollection is the place for reusable scripts.
|
|
5
5
|
Home-page: https://github.com/anionDev/ScriptCollection
|
|
6
6
|
Author: Marius Göcke
|
|
@@ -22,25 +22,25 @@ Classifier: Topic :: Terminals
|
|
|
22
22
|
Classifier: Topic :: Utilities
|
|
23
23
|
Requires-Python: >=3.10
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
|
-
Requires-Dist: build >=1.
|
|
26
|
-
Requires-Dist: coverage >=7.
|
|
27
|
-
Requires-Dist: cyclonedx-bom >=4.
|
|
25
|
+
Requires-Dist: build >=1.2.1
|
|
26
|
+
Requires-Dist: coverage >=7.5.0
|
|
27
|
+
Requires-Dist: cyclonedx-bom >=4.4.3
|
|
28
28
|
Requires-Dist: defusedxml >=0.7.1
|
|
29
29
|
Requires-Dist: keyboard >=0.13.5
|
|
30
30
|
Requires-Dist: lcov-cobertura >=2.0.2
|
|
31
|
-
Requires-Dist: lxml >=5.1
|
|
31
|
+
Requires-Dist: lxml >=5.2.1
|
|
32
32
|
Requires-Dist: ntplib >=0.4.0
|
|
33
|
-
Requires-Dist: Pillow >=10.
|
|
33
|
+
Requires-Dist: Pillow >=10.3.0
|
|
34
34
|
Requires-Dist: pycdlib >=1.14.0
|
|
35
35
|
Requires-Dist: Pygments >=2.17.2
|
|
36
36
|
Requires-Dist: pylint >=3.1.0
|
|
37
37
|
Requires-Dist: pyOpenSSL >=24.1.0
|
|
38
38
|
Requires-Dist: PyPDF2 >=3.0.1
|
|
39
|
-
Requires-Dist: pytest >=8.
|
|
39
|
+
Requires-Dist: pytest >=8.2.0
|
|
40
40
|
Requires-Dist: qrcode >=7.4.2
|
|
41
|
-
Requires-Dist: send2trash >=1.8.
|
|
41
|
+
Requires-Dist: send2trash >=1.8.3
|
|
42
42
|
Requires-Dist: twine >=5.0.0
|
|
43
|
-
Requires-Dist: xmlschema >=3.1
|
|
43
|
+
Requires-Dist: xmlschema >=3.3.1
|
|
44
44
|
|
|
45
45
|
# ScriptCollection
|
|
46
46
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
ScriptCollection/Executables.py,sha256=F8ar_pRplVZm0mHLJ_Ono5HKTfqr6wTceG3Hcbx_tow,19282
|
|
2
|
+
ScriptCollection/GeneralUtilities.py,sha256=Mcp6ghb6AbS1KsOjEnRw3x4a4mBrAZ6DAjV2j8-LZFM,35589
|
|
3
|
+
ScriptCollection/ProgramRunnerBase.py,sha256=2kyOuoM3oFjBfLc9Q5t5RTz7Ya2CjUxFtB1rBBDmnjU,1937
|
|
4
|
+
ScriptCollection/ProgramRunnerEpew.py,sha256=nIzY4dG6W-xEpkeoTbozwNZtFSIo-bU_W6t6u1AZKtE,6275
|
|
5
|
+
ScriptCollection/ProgramRunnerPopen.py,sha256=kV7KVuDenKjOyNBFurMTcuhuLuLZ74MaaSrwaPjaHCs,3158
|
|
6
|
+
ScriptCollection/ScriptCollectionCore.py,sha256=LXHRp3sWZmIdWRhOXFbQxGE4aPel194AhMXgD8LCKOs,92657
|
|
7
|
+
ScriptCollection/TasksForCommonProjectStructure.py,sha256=4ZxLkYtT7nszV46AT0E7_TuAziFokFnG1UcZ9VFYfzk,173711
|
|
8
|
+
ScriptCollection/UpdateCertificates.py,sha256=3C_E9og5SZec35aD3BFYLchzJtonsg1KR4enFCb5Jzk,7914
|
|
9
|
+
ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
ScriptCollection-3.5.0.dist-info/METADATA,sha256=RVO_ZaAz9cLgXhOTyAZUMvA7eqk9pMGPvmAUEcDEqeQ,7648
|
|
11
|
+
ScriptCollection-3.5.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
12
|
+
ScriptCollection-3.5.0.dist-info/entry_points.txt,sha256=dwvB9HRGvqst5xlYIGmmwuFN7lBKhxvndmnNrQOfu8w,2153
|
|
13
|
+
ScriptCollection-3.5.0.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
|
|
14
|
+
ScriptCollection-3.5.0.dist-info/RECORD,,
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
ScriptCollection/Executables.py,sha256=F8ar_pRplVZm0mHLJ_Ono5HKTfqr6wTceG3Hcbx_tow,19282
|
|
2
|
-
ScriptCollection/GeneralUtilities.py,sha256=Mcp6ghb6AbS1KsOjEnRw3x4a4mBrAZ6DAjV2j8-LZFM,35589
|
|
3
|
-
ScriptCollection/ProgramRunnerBase.py,sha256=2kyOuoM3oFjBfLc9Q5t5RTz7Ya2CjUxFtB1rBBDmnjU,1937
|
|
4
|
-
ScriptCollection/ProgramRunnerEpew.py,sha256=nIzY4dG6W-xEpkeoTbozwNZtFSIo-bU_W6t6u1AZKtE,6275
|
|
5
|
-
ScriptCollection/ProgramRunnerPopen.py,sha256=veDNRg2Z0u0vd4iKWAycVFKbTm_uWYfuK6NTiwlbgrM,3230
|
|
6
|
-
ScriptCollection/ScriptCollectionCore.py,sha256=BhKnb3B9-EJDdpBCZ-OxfJ3gCYw3l2gTlTS6f6p4U94,95610
|
|
7
|
-
ScriptCollection/TasksForCommonProjectStructure.py,sha256=2JjsnakLb9cL8x0KaSKoEtJhQXGGcgy9cBYGhbW7IYY,164656
|
|
8
|
-
ScriptCollection/UpdateCertificates.py,sha256=3C_E9og5SZec35aD3BFYLchzJtonsg1KR4enFCb5Jzk,7914
|
|
9
|
-
ScriptCollection/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
ScriptCollection-3.4.58.dist-info/METADATA,sha256=ooyyqkaSxGR4PUclox2lThp46-edMlCMI8aBO7TQDRU,7649
|
|
11
|
-
ScriptCollection-3.4.58.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
12
|
-
ScriptCollection-3.4.58.dist-info/entry_points.txt,sha256=dwvB9HRGvqst5xlYIGmmwuFN7lBKhxvndmnNrQOfu8w,2153
|
|
13
|
-
ScriptCollection-3.4.58.dist-info/top_level.txt,sha256=hY2hOVH0V0Ce51WB76zKkIWTUNwMUdHo4XDkR2vYVwg,17
|
|
14
|
-
ScriptCollection-3.4.58.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|