scriptcollection 4.2.81__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.
Files changed (62) hide show
  1. ScriptCollection/AnionBuildPlatform.py +199 -0
  2. ScriptCollection/CertificateUpdater.py +149 -0
  3. ScriptCollection/Executables.py +921 -0
  4. ScriptCollection/GeneralUtilities.py +1589 -0
  5. ScriptCollection/HTTPMaintenanceOverheadHelper.py +36 -0
  6. ScriptCollection/OCIImages/AbstractImageHandler.py +38 -0
  7. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerDebian.py +20 -0
  8. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerDebianSlim.py +20 -0
  9. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerGeneric.py +20 -0
  10. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerGenericV.py +20 -0
  11. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerGitlabCE.py +20 -0
  12. ScriptCollection/OCIImages/ConcreteImageHandlers/ImageHandlerGitlabEE.py +20 -0
  13. ScriptCollection/OCIImages/ConcreteImageHandlers/__init__.py +0 -0
  14. ScriptCollection/OCIImages/OCIImageManager.py +190 -0
  15. ScriptCollection/OCIImages/__init__.py +0 -0
  16. ScriptCollection/ProcessesRunner.py +43 -0
  17. ScriptCollection/ProgramRunnerBase.py +47 -0
  18. ScriptCollection/ProgramRunnerMock.py +2 -0
  19. ScriptCollection/ProgramRunnerPopen.py +57 -0
  20. ScriptCollection/ProgramRunnerSudo.py +108 -0
  21. ScriptCollection/Resources/CultureChooser/CultureChooser.js +29 -0
  22. ScriptCollection/Resources/CultureChooser/index.html +15 -0
  23. ScriptCollection/Resources/MaintenanceSite/MaintenanceSite.html +15 -0
  24. ScriptCollection/SCLog.py +115 -0
  25. ScriptCollection/ScriptCollectionCore.py +3485 -0
  26. ScriptCollection/TFCPS/Docker/TFCPS_CodeUnitSpecific_Docker.py +192 -0
  27. ScriptCollection/TFCPS/Docker/__init__.py +0 -0
  28. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationBase.py +8 -0
  29. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationGenerate.py +6 -0
  30. ScriptCollection/TFCPS/DotNet/CertificateGeneratorInformationNoGenerate.py +7 -0
  31. ScriptCollection/TFCPS/DotNet/TFCPS_CodeUnitSpecific_DotNet.py +547 -0
  32. ScriptCollection/TFCPS/DotNet/__init__.py +0 -0
  33. ScriptCollection/TFCPS/Flutter/TFCPS_CodeUnitSpecific_Flutter.py +137 -0
  34. ScriptCollection/TFCPS/Flutter/__init__.py +0 -0
  35. ScriptCollection/TFCPS/Go/TFCPS_CodeUnitSpecific_Go.py +72 -0
  36. ScriptCollection/TFCPS/Go/__init__.py +0 -0
  37. ScriptCollection/TFCPS/Maven/TFCPS_CodeUnitSpecific_Maven.py +42 -0
  38. ScriptCollection/TFCPS/Maven/__init__.py +0 -0
  39. ScriptCollection/TFCPS/NodeJS/TFCPS_CodeUnitSpecific_NodeJS.py +232 -0
  40. ScriptCollection/TFCPS/NodeJS/__init__.py +0 -0
  41. ScriptCollection/TFCPS/Python/TFCPS_CodeUnitSpecific_Python.py +239 -0
  42. ScriptCollection/TFCPS/Python/__init__.py +0 -0
  43. ScriptCollection/TFCPS/Rust/TFCPS_CodeUnitSpecific_Rust.py +42 -0
  44. ScriptCollection/TFCPS/Rust/__init__.py +0 -0
  45. ScriptCollection/TFCPS/TFCPS_CodeUnitSpecific_Base.py +433 -0
  46. ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnit.py +135 -0
  47. ScriptCollection/TFCPS/TFCPS_CodeUnit_BuildCodeUnits.py +301 -0
  48. ScriptCollection/TFCPS/TFCPS_CreateRelease.py +98 -0
  49. ScriptCollection/TFCPS/TFCPS_Generic.py +44 -0
  50. ScriptCollection/TFCPS/TFCPS_MergeToMain.py +128 -0
  51. ScriptCollection/TFCPS/TFCPS_MergeToStable.py +356 -0
  52. ScriptCollection/TFCPS/TFCPS_PreBuildCodeunitsScript.py +48 -0
  53. ScriptCollection/TFCPS/TFCPS_Tools_General.py +1565 -0
  54. ScriptCollection/TFCPS/__init__.py +0 -0
  55. ScriptCollection/__init__.py +0 -0
  56. ScriptCollection/__pycache__/GeneralUtilities.cpython-311.pyc +0 -0
  57. ScriptCollection/__pycache__/__init__.cpython-311.pyc +0 -0
  58. scriptcollection-4.2.81.dist-info/METADATA +169 -0
  59. scriptcollection-4.2.81.dist-info/RECORD +62 -0
  60. scriptcollection-4.2.81.dist-info/WHEEL +5 -0
  61. scriptcollection-4.2.81.dist-info/entry_points.txt +67 -0
  62. scriptcollection-4.2.81.dist-info/top_level.txt +1 -0
@@ -0,0 +1,547 @@
1
+ import os
2
+ import re
3
+ import shutil
4
+ import tempfile
5
+ import uuid
6
+ import json
7
+ from lxml import etree
8
+ import yaml
9
+ from .CertificateGeneratorInformationBase import CertificateGeneratorInformationBase
10
+ from ...GeneralUtilities import GeneralUtilities
11
+ from ...SCLog import LogLevel
12
+ from ..TFCPS_CodeUnitSpecific_Base import TFCPS_CodeUnitSpecific_Base,TFCPS_CodeUnitSpecific_Base_CLI
13
+
14
+ class TFCPS_CodeUnitSpecific_DotNet_Functions(TFCPS_CodeUnitSpecific_Base):
15
+
16
+ is_library:bool
17
+ csproj_file:bool
18
+
19
+ def __init__(self,current_file:str,verbosity:LogLevel,targetenvironmenttype:str,use_cache:bool,is_pre_merge:bool):
20
+ super().__init__(current_file, verbosity,targetenvironmenttype,use_cache,is_pre_merge)
21
+ self.csproj_file=os.path.join(self.get_codeunit_folder(), self.get_codeunit_name(), self.get_codeunit_name() + ".csproj")
22
+ self.is_library="<OutputType>Library</OutputType>" in GeneralUtilities.read_text_from_file(self.csproj_file)#TODO do a real check by checking this property using xpath
23
+
24
+ @GeneralUtilities.check_arguments
25
+ def build(self,runtimes:list[str],generate_open_api_spec:bool) -> None:
26
+ if self.is_library:
27
+ self.standardized_tasks_build_for_dotnet_library_project(runtimes)
28
+ GeneralUtilities.assert_condition(not generate_open_api_spec,"OpenAPI-Specification can not be generated for a library.")
29
+ else:
30
+ self.standardized_tasks_build_for_dotnet_project(runtimes)
31
+ if generate_open_api_spec:
32
+ self.generate_openapi_file(runtimes[0])
33
+
34
+ @GeneralUtilities.check_arguments
35
+ def generate_openapi_file(self, runtime: str) -> None:
36
+ swagger_document_name: str = "APISpecification"
37
+ self._protected_sc.log.log("Generate OpenAPI-specification-file...")
38
+ codeunitname =self.get_codeunit_name()
39
+ repository_folder =self.get_repository_folder()
40
+ codeunit_folder = os.path.join(repository_folder, codeunitname)
41
+ artifacts_folder = os.path.join(codeunit_folder, "Other", "Artifacts")
42
+ GeneralUtilities.ensure_directory_exists(os.path.join(artifacts_folder, "APISpecification"))
43
+ codeunit_version = self.tfcps_Tools_General.get_version_of_codeunit(os.path.join(codeunit_folder,f"{codeunitname}.codeunit.xml"))
44
+
45
+ versioned_api_spec_file = f"APISpecification/{codeunitname}.v{codeunit_version}.api.json"
46
+ self._protected_sc.run_program("swagger", f"tofile --output {versioned_api_spec_file} BuildResult_DotNet_{runtime}/{codeunitname}.dll {swagger_document_name}", artifacts_folder,print_live_output=self.get_verbosity()==LogLevel.Debug)
47
+ api_file: str = os.path.join(artifacts_folder, versioned_api_spec_file)
48
+ shutil.copyfile(api_file, os.path.join(artifacts_folder, f"APISpecification/{codeunitname}.latest.api.json"))
49
+
50
+ resources_folder = os.path.join(codeunit_folder, "Other", "Resources")
51
+ GeneralUtilities.ensure_directory_exists(resources_folder)
52
+ resources_apispec_folder = os.path.join(resources_folder, "APISpecification")
53
+ GeneralUtilities.ensure_directory_exists(resources_apispec_folder)
54
+ resource_target_file = os.path.join(resources_apispec_folder, f"{codeunitname}.api.json")
55
+ GeneralUtilities.ensure_file_does_not_exist(resource_target_file)
56
+ shutil.copyfile(api_file, resource_target_file)
57
+
58
+ with open(api_file, encoding="utf-8") as api_file_content:
59
+ reloaded_json = json.load(api_file_content)
60
+
61
+ yamlfile1: str = str(os.path.join(artifacts_folder, f"APISpecification/{codeunitname}.v{codeunit_version}.api.yaml"))
62
+ GeneralUtilities.ensure_file_does_not_exist(yamlfile1)
63
+ GeneralUtilities.ensure_file_exists(yamlfile1)
64
+ with open(yamlfile1, "w+", encoding="utf-8") as yamlfile:
65
+ yaml.dump(reloaded_json, yamlfile, allow_unicode=True)
66
+
67
+ yamlfile2: str = str(os.path.join(artifacts_folder, f"APISpecification/{codeunitname}.latest.api.yaml"))
68
+ GeneralUtilities.ensure_file_does_not_exist(yamlfile2)
69
+ shutil.copyfile(yamlfile1, yamlfile2)
70
+
71
+ yamlfile3: str = str(os.path.join(resources_apispec_folder, f"{codeunitname}.api.yaml"))
72
+ GeneralUtilities.ensure_file_does_not_exist(yamlfile3)
73
+ shutil.copyfile(yamlfile1, yamlfile3)
74
+
75
+ @GeneralUtilities.check_arguments
76
+ def __standardized_tasks_build_for_dotnet_build(self, csproj_file: str, originaloutputfolder: str, files_to_sign: dict[str, str], commitid: str, runtimes: list[str], target_environmenttype_mapping: dict[str, str], copy_license_file_to_target_folder: bool, repository_folder: str, codeunit_name: str) -> None:
77
+ self._protected_sc.assert_is_git_repository(repository_folder)
78
+ csproj_filename = os.path.basename(csproj_file)
79
+ self._protected_sc.log.log(f"Build {csproj_filename}...")
80
+ dotnet_build_configuration: str = self.get_target_environment_type()
81
+ codeunit_folder = os.path.join(repository_folder, codeunit_name)
82
+ csproj_file_folder = os.path.dirname(csproj_file)
83
+ csproj_file_name = os.path.basename(csproj_file)
84
+ csproj_file_name_without_extension = csproj_file_name.split(".")[0]
85
+ sarif_folder = os.path.join(codeunit_folder, "Other", "Resources", "CodeAnalysisResult")
86
+ GeneralUtilities.ensure_directory_exists(sarif_folder)
87
+ gitkeep_file = os.path.join(sarif_folder, ".gitkeep")
88
+ GeneralUtilities.ensure_file_exists(gitkeep_file)
89
+ for runtime in runtimes:
90
+ outputfolder = originaloutputfolder+runtime
91
+ GeneralUtilities.ensure_directory_does_not_exist(os.path.join(csproj_file_folder, "obj"))
92
+ GeneralUtilities.ensure_directory_does_not_exist(outputfolder)
93
+ self._protected_sc.run_program("dotnet", "clean", csproj_file_folder)
94
+ GeneralUtilities.ensure_directory_exists(outputfolder)
95
+ self._protected_sc.run_program("dotnet", "restore", codeunit_folder,print_live_output=self.get_verbosity()==LogLevel.Debug)
96
+ self._protected_sc.run_program_argsasarray("dotnet", ["build", csproj_file_name, "-c", dotnet_build_configuration, "-o", outputfolder, "--runtime", runtime], csproj_file_folder,print_live_output=self.get_verbosity()==LogLevel.Debug)
97
+ if copy_license_file_to_target_folder:
98
+ license_file = os.path.join(repository_folder, "License.txt")
99
+ target = os.path.join(outputfolder, f"{codeunit_name}.License.txt")
100
+ shutil.copyfile(license_file, target)
101
+ if 0 < len(files_to_sign):
102
+ for key, value in files_to_sign.items():
103
+ dll_file = key
104
+ snk_file = value
105
+ dll_file_full = os.path.join(outputfolder, dll_file)
106
+ if os.path.isfile(dll_file_full):
107
+ GeneralUtilities.assert_condition(self._protected_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.")
108
+ self._protected_sc.run_program_argsasarray("sn", ["-R", dll_file, snk_file], outputfolder)
109
+ GeneralUtilities.assert_condition(self._protected_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.")
110
+ sarif_filename = f"{csproj_file_name_without_extension}.sarif"
111
+ sarif_source_file = os.path.join(sarif_folder, sarif_filename)
112
+ if os.path.exists(sarif_source_file):
113
+ sarif_folder_target = os.path.join(codeunit_folder, "Other", "Artifacts", "CodeAnalysisResult")
114
+ GeneralUtilities.ensure_directory_exists(sarif_folder_target)
115
+ sarif_target_file = os.path.join(sarif_folder_target, sarif_filename)
116
+ GeneralUtilities.ensure_file_does_not_exist(sarif_target_file)
117
+ shutil.copyfile(sarif_source_file, sarif_target_file)
118
+
119
+ @GeneralUtilities.check_arguments
120
+ def standardized_tasks_build_for_dotnet_project(self,runtimes:list[str]) -> None:
121
+ self.__standardized_tasks_build_for_dotnet_project(runtimes)
122
+
123
+ @GeneralUtilities.check_arguments
124
+ def standardized_tasks_build_for_dotnet_library_project(self,runtimes:list[str]) -> None:
125
+ self.__standardized_tasks_build_for_dotnet_project(runtimes)
126
+ self.__standardized_tasks_build_nupkg_for_dotnet_create_package(runtimes)
127
+
128
+
129
+ @staticmethod
130
+ @GeneralUtilities.check_arguments
131
+ def get_filestosign_from_commandline_arguments( default_value: dict[str, str]) -> dict[str, str]:
132
+ result_plain =None# TODO TasksForCommonProjectStructure.get_property_from_commandline_arguments(commandline_arguments, "sign")
133
+ if result_plain is None:
134
+ return default_value
135
+ else:
136
+ result: dict[str, str] = dict[str, str]()
137
+ files_tuples = GeneralUtilities.to_list(result_plain, ";")
138
+ for files_tuple in files_tuples:
139
+ splitted = files_tuple.split("=")
140
+ result[splitted[0]] = splitted[1]
141
+ return result
142
+
143
+ @GeneralUtilities.check_arguments
144
+ def __standardized_tasks_build_for_dotnet_project(self,runtimes:list[str]) -> None:
145
+
146
+ target_environment_type: str=self.get_target_environment_type()
147
+ copy_license_file_to_target_folder: bool=True
148
+ codeunitname: str = self.get_codeunit_name()
149
+
150
+ workspace_folder=os.path.join(self.get_codeunit_folder(),"Other","Workspace")
151
+ GeneralUtilities.ensure_directory_does_not_exist(workspace_folder)
152
+
153
+ files_to_sign: dict[str, str] = self.get_filestosign_from_commandline_arguments( dict())
154
+ repository_folder: str = self.get_repository_folder()
155
+ commitid = self._protected_sc.git_get_commit_id(repository_folder)
156
+ outputfolder = GeneralUtilities.resolve_relative_path("./Other/Artifacts", self.get_codeunit_folder())
157
+ codeunit_folder = os.path.join(repository_folder, codeunitname)
158
+ csproj_file = os.path.join(codeunit_folder, codeunitname, codeunitname + ".csproj")
159
+ csproj_test_file = os.path.join(codeunit_folder, codeunitname+"Tests", codeunitname+"Tests.csproj")
160
+ self.__standardized_tasks_build_for_dotnet_build(csproj_file, os.path.join(outputfolder, "BuildResult_DotNet_"), files_to_sign, commitid, runtimes, target_environment_type, copy_license_file_to_target_folder, repository_folder, codeunitname)
161
+ self.__standardized_tasks_build_for_dotnet_build(csproj_test_file, os.path.join(outputfolder, "BuildResultTests_DotNet_"), files_to_sign, commitid, runtimes, target_environment_type, copy_license_file_to_target_folder, repository_folder, codeunitname)
162
+ self.generate_sbom_for_dotnet_project(codeunit_folder)
163
+ self.copy_source_files_to_output_directory()
164
+
165
+ @GeneralUtilities.check_arguments
166
+ def __standardized_tasks_build_nupkg_for_dotnet_create_package(self,runtimes:list[str]) -> None:
167
+ codeunitname: str = self.get_codeunit_name()
168
+ repository_folder: str =self.get_repository_folder()
169
+ build_folder = os.path.join(repository_folder, codeunitname, "Other", "Build")
170
+ outputfolder = GeneralUtilities.resolve_relative_path("./Other/Artifacts/BuildResult_NuGet",self.get_codeunit_folder())
171
+ root: etree._ElementTree = etree.parse(os.path.join(build_folder, f"{codeunitname}.nuspec"))
172
+ current_version = root.xpath("//*[name() = 'package']/*[name() = 'metadata']/*[name() = 'version']/text()")[0]
173
+ nupkg_filename = f"{codeunitname}.{current_version}.nupkg"
174
+ nupkg_file = f"{build_folder}/{nupkg_filename}"
175
+ GeneralUtilities.ensure_file_does_not_exist(nupkg_file)
176
+ commit_id = self._protected_sc.git_get_commit_id(repository_folder)
177
+ self._protected_sc.run_program("nuget", f"pack {codeunitname}.nuspec -Properties \"commitid={commit_id}\"", build_folder)
178
+ GeneralUtilities.ensure_directory_does_not_exist(outputfolder)
179
+ GeneralUtilities.ensure_directory_exists(outputfolder)
180
+ os.rename(nupkg_file, f"{outputfolder}/{nupkg_filename}")
181
+
182
+ @GeneralUtilities.check_arguments
183
+ def generate_sbom_for_dotnet_project(self, codeunit_folder: str) -> None:
184
+ self._protected_sc.log.log("Generate SBOM...")
185
+ codeunit_name = os.path.basename(codeunit_folder)
186
+ bomfile_folder = "Other\\Artifacts\\BOM"
187
+ self._protected_sc.run_program_argsasarray("dotnet", ["CycloneDX", f"{codeunit_name}\\{codeunit_name}.csproj", "-o", bomfile_folder], codeunit_folder)
188
+ codeunitversion = self.tfcps_Tools_General.get_version_of_codeunit(os.path.join(codeunit_folder, f"{codeunit_name}.codeunit.xml"))
189
+ target = f"{codeunit_folder}\\{bomfile_folder}\\{codeunit_name}.{codeunitversion}.sbom.xml"
190
+ GeneralUtilities.ensure_file_does_not_exist(target)
191
+ os.rename(f"{codeunit_folder}\\{bomfile_folder}\\bom.xml", target)
192
+ self._protected_sc.format_xml_file(target)
193
+
194
+ @GeneralUtilities.check_arguments
195
+ def get_dotnet_build_diagnostics(self) -> list[tuple[LogLevel, str, str | None, int | None]]:
196
+ codeunit_name = self.get_codeunit_name()
197
+ codeunit_folder = self.get_codeunit_folder()
198
+ sln_file = os.path.join(codeunit_folder, codeunit_name + ".sln")
199
+ temp_output_folder = os.path.join(tempfile.gettempdir(), str(uuid.uuid4()))
200
+ GeneralUtilities.ensure_directory_exists(temp_output_folder)
201
+ try:
202
+ run_result = self._protected_sc.run_program("dotnet", f"build \"{sln_file}\" -nologo -v minimal -o \"{temp_output_folder}\"", codeunit_folder, throw_exception_if_exitcode_is_not_zero=False)
203
+ finally:
204
+ GeneralUtilities.ensure_directory_does_not_exist(temp_output_folder)
205
+ diagnostics: list[tuple[LogLevel, str, str | None, int | None]] = []
206
+ pattern = re.compile(r"^\s*(?:(.+?)\((\d+),\d+\): )?(error|warning|message|info) [^:]+: (.+?)(?:\s*\[.+\])?\s*$", re.IGNORECASE)
207
+ #TODO fix this function. this does not work. fyi output looks like this:
208
+ #E:\Data\Projects\GRYLibrary\GRYLibrary>dotnet build GRYLibrary.sln -nologo -v minimal
209
+ #Restore succeeded with 11 warning(s) in 0,9s
210
+ # E:\Data\Projects\GRYLibrary\GRYLibrary\GRYLibrary\GRYLibrary.csproj : warning NU1510: PackageReference Microsoft.CSharp will not be pruned. Consider removing this package from your dependencies, as it is likely unnecessary.
211
+ # E:\Data\Projects\GRYLibrary\GRYLibrary\GRYLibraryTests\GRYLibraryTests.csproj : warning NU1510: PackageReference Microsoft.Win32.Registry will not be pruned. Consider removing this package from your dependencies, as it is likely unnecessary.
212
+ for line in GeneralUtilities.string_to_lines(run_result[1] + "\n" + run_result[2]):
213
+ m = pattern.match(line)
214
+ if m:
215
+ file_path = m.group(1)
216
+ line_number = int(m.group(2)) if m.group(2) else None
217
+ level_str = m.group(3).lower()
218
+ message = m.group(4)
219
+ if level_str == "error":
220
+ level = LogLevel.Error
221
+ elif level_str == "warning":
222
+ level = LogLevel.Warning
223
+ else:
224
+ level = LogLevel.Information
225
+ diagnostics.append((level, message, file_path, line_number))
226
+ return diagnostics
227
+
228
+ @GeneralUtilities.check_arguments
229
+ def linting(self) -> None:
230
+ codeunit_name = self.get_codeunit_name()
231
+ codeunit_folder = self.get_codeunit_folder()
232
+ self._protected_sc.format_xml_file(os.path.join(codeunit_folder, codeunit_name, codeunit_name + ".csproj"), add_xml_declaration=False)
233
+ self._protected_sc.format_xml_file(os.path.join(codeunit_folder, codeunit_name + "Tests", codeunit_name + "Tests.csproj"), add_xml_declaration=False)
234
+ self.standardized_task_verify_standard_format_csproj_files()
235
+ diagnostics = self.get_dotnet_build_diagnostics()
236
+ has_errors = False
237
+ for (level, message, file, line) in diagnostics:
238
+ location = f" ({file}:{line})" if file else ""
239
+ self._protected_sc.log.log(f"{message}{location}", level)
240
+ if level == LogLevel.Error:#should not occurr on scbuildcodeunits because then the build would have failed already.
241
+ has_errors = True
242
+ if has_errors:
243
+ raise ValueError("Linting-issues occurred.")
244
+
245
+ @GeneralUtilities.check_arguments
246
+ def do_common_tasks(self,current_codeunit_version:str,certificateGeneratorInformation:CertificateGeneratorInformationBase)-> None:
247
+ self.do_common_tasks_base(current_codeunit_version)
248
+ codeunit_name =self.get_codeunit_name()
249
+ codeunit_version = self.tfcps_Tools_General.get_version_of_project(self.get_repository_folder()) # Should always be the same as the project-version #TODO make this configurable from outside
250
+ folder_of_current_file =os.path.join(self.get_codeunit_folder(),"Other")
251
+ self._protected_sc.replace_version_in_csproj_file(GeneralUtilities.resolve_relative_path(f"../{codeunit_name}/{codeunit_name}.csproj", folder_of_current_file), codeunit_version)
252
+ self._protected_sc.replace_version_in_csproj_file(GeneralUtilities.resolve_relative_path(f"../{codeunit_name}Tests/{codeunit_name}Tests.csproj", folder_of_current_file), codeunit_version)
253
+ if self.is_library:
254
+ self._protected_sc.replace_version_in_nuspec_file(GeneralUtilities.resolve_relative_path(f"./Build/{codeunit_name}.nuspec", folder_of_current_file), codeunit_version)
255
+ if certificateGeneratorInformation.generate_certificate():
256
+ self.tfcps_Tools_General.set_constants_for_certificate_private_information(self.get_codeunit_folder())
257
+
258
+ @GeneralUtilities.check_arguments
259
+ def standardized_task_verify_standard_format_csproj_files(self) -> bool:
260
+ codeunit_folder=self.get_codeunit_folder()
261
+ repository_folder = os.path.dirname(codeunit_folder)
262
+ codeunit_name = os.path.basename(codeunit_folder)
263
+ codeunit_folder = os.path.join(repository_folder, codeunit_name)
264
+ codeunit_version = self.tfcps_Tools_General.get_version_of_codeunit(self.get_codeunit_file())
265
+
266
+ csproj_project_name = codeunit_name
267
+ csproj_file = os.path.join(codeunit_folder, csproj_project_name, csproj_project_name+".csproj")
268
+ result1: tuple[bool, str, list[str]] = self.__standardized_task_verify_standard_format_for_project_csproj_file(csproj_file, codeunit_folder, codeunit_name, codeunit_version)
269
+ if not result1[0]:
270
+ hints: str = "\n".join(result1[2])
271
+ raise ValueError(f"'{csproj_file}' with content '{GeneralUtilities.read_text_from_file(csproj_file)}' does not match the standardized .csproj-file-format which is defined by the regex '{result1[1]}'.\n{hints}")
272
+
273
+ test_csproj_project_name = csproj_project_name+"Tests"
274
+ test_csproj_file = os.path.join(codeunit_folder, test_csproj_project_name, test_csproj_project_name+".csproj")
275
+ result2: tuple[bool, str, list[str]] = self.__standardized_task_verify_standard_format_for_test_csproj_file(test_csproj_file, codeunit_name, codeunit_version)
276
+ if not result2[0]:
277
+ hints: str = "\n".join(result2[2])
278
+ raise ValueError(f"'{test_csproj_file}' with content '{GeneralUtilities.read_text_from_file(test_csproj_file)}' does not match the standardized .csproj-file-format which is defined by the regex '{result2[1]}'.\n{hints}")
279
+
280
+ def __standardized_task_verify_standard_format_for_project_csproj_file(self, csproj_file: str, codeunit_folder: str, codeunit_name: str, codeunit_version: str) -> tuple[bool, str, str]:
281
+ codeunit_name_regex = re.escape(codeunit_name)
282
+ codeunit_description = self.tfcps_Tools_General.get_codeunit_description(self.get_codeunit_file())
283
+ codeunit_version_regex = re.escape(codeunit_version)
284
+ codeunit_description_regex = re.escape(codeunit_description)
285
+ regex = f"""^<Project Sdk=\\"Microsoft\\.NET\\.Sdk\\">
286
+ <PropertyGroup>
287
+ <TargetFramework>([^<]+)<\\/TargetFramework>
288
+ <Authors>([^<]+)<\\/Authors>
289
+ <Version>{codeunit_version_regex}<\\/Version>
290
+ <AssemblyVersion>{codeunit_version_regex}<\\/AssemblyVersion>
291
+ <FileVersion>{codeunit_version_regex}<\\/FileVersion>
292
+ <SelfContained>false<\\/SelfContained>
293
+ <IsPackable>false<\\/IsPackable>
294
+ <PreserveCompilationContext>false<\\/PreserveCompilationContext>
295
+ <GenerateRuntimeConfigurationFiles>true<\\/GenerateRuntimeConfigurationFiles>
296
+ <Copyright>([^<]+)<\\/Copyright>
297
+ <Description>{codeunit_description_regex}<\\/Description>
298
+ <PackageProjectUrl>https:\\/\\/([^<]+)<\\/PackageProjectUrl>
299
+ <RepositoryUrl>https:\\/\\/([^<]+)\\.git<\\/RepositoryUrl>
300
+ <RootNamespace>([^<]+)\\.Core<\\/RootNamespace>
301
+ <ProduceReferenceAssembly>false<\\/ProduceReferenceAssembly>
302
+ <Nullable>(disable|enable|warnings|annotations)<\\/Nullable>
303
+ <Configurations>Development;QualityCheck;Productive<\\/Configurations>
304
+ <IsTestProject>false<\\/IsTestProject>
305
+ <LangVersion>([^<]+)<\\/LangVersion>
306
+ <PackageRequireLicenseAcceptance>true<\\/PackageRequireLicenseAcceptance>
307
+ <GenerateSerializationAssemblies>Off<\\/GenerateSerializationAssemblies>
308
+ <AppendTargetFrameworkToOutputPath>false<\\/AppendTargetFrameworkToOutputPath>
309
+ <OutputPath>\\.\\.\\\\Other\\\\Artifacts\\\\BuildResult_DotNet_win\\-x64<\\/OutputPath>
310
+ <PlatformTarget>([^<]+)<\\/PlatformTarget>
311
+ <WarningLevel>\\d<\\/WarningLevel>
312
+ <Prefer32Bit>false<\\/Prefer32Bit>
313
+ <SignAssembly>true<\\/SignAssembly>
314
+ <AssemblyOriginatorKeyFile>\\.\\.\\\\\\.\\.\\\\Other\\\\Resources\\\\PublicKeys\\\\StronglyNamedKey\\\\([^<]+)PublicKey\\.snk<\\/AssemblyOriginatorKeyFile>
315
+ <DelaySign>true<\\/DelaySign>
316
+ <NoWarn>([^<]+)<\\/NoWarn>
317
+ <WarningsAsErrors>([^<]+)<\\/WarningsAsErrors>
318
+ <ErrorLog>\\.\\.\\\\Other\\\\Resources\\\\CodeAnalysisResult\\\\{codeunit_name_regex}\\.sarif<\\/ErrorLog>
319
+ <OutputType>([^<]+)<\\/OutputType>
320
+ <DocumentationFile>\\.\\.\\\\Other\\\\Artifacts\\\\MetaInformation\\\\{codeunit_name_regex}\\.xml<\\/DocumentationFile>(\\n|.)*
321
+ <\\/PropertyGroup>
322
+ <PropertyGroup Condition=\\\"'\\$\\(Configuration\\)'=='Development'\\\">
323
+ <DebugType>full<\\/DebugType>
324
+ <DebugSymbols>true<\\/DebugSymbols>
325
+ <Optimize>false<\\/Optimize>
326
+ <DefineConstants>TRACE;DEBUG;Development<\\/DefineConstants>
327
+ <ErrorReport>prompt<\\/ErrorReport>
328
+ <\\/PropertyGroup>
329
+ <PropertyGroup Condition=\\\"'\\$\\(Configuration\\)'=='QualityCheck'\\\">
330
+ <DebugType>portable<\\/DebugType>
331
+ <DebugSymbols>true<\\/DebugSymbols>
332
+ <Optimize>false<\\/Optimize>
333
+ <DefineConstants>TRACE;QualityCheck<\\/DefineConstants>
334
+ <ErrorReport>none<\\/ErrorReport>
335
+ <\\/PropertyGroup>
336
+ <PropertyGroup Condition=\\\"'\\$\\(Configuration\\)'=='Productive'\\\">
337
+ <DebugType>portable<\\/DebugType>
338
+ <DebugSymbols>true<\\/DebugSymbols>
339
+ <Optimize>false<\\/Optimize>
340
+ <DefineConstants>Productive<\\/DefineConstants>
341
+ <ErrorReport>none<\\/ErrorReport>
342
+ <\\/PropertyGroup>(\\n|.)*
343
+ <\\/Project>\\n?$"""
344
+ result = self.__standardized_task_verify_standard_format_for_csproj_files(regex, csproj_file)
345
+ return (result[0], regex, result[1])
346
+
347
+ def __standardized_task_verify_standard_format_for_test_csproj_file(self, csproj_file: str, codeunit_name: str, codeunit_version: str) -> tuple[bool, str, str]:
348
+ codeunit_name_regex = re.escape(codeunit_name)
349
+ codeunit_version_regex = re.escape(codeunit_version)
350
+ regex = f"""^<Project Sdk=\\"Microsoft\\.NET\\.Sdk\\">
351
+ <PropertyGroup>
352
+ <TargetFramework>([^<]+)<\\/TargetFramework>
353
+ <Authors>([^<]+)<\\/Authors>
354
+ <Version>{codeunit_version_regex}<\\/Version>
355
+ <AssemblyVersion>{codeunit_version_regex}<\\/AssemblyVersion>
356
+ <FileVersion>{codeunit_version_regex}<\\/FileVersion>
357
+ <SelfContained>false<\\/SelfContained>
358
+ <IsPackable>false<\\/IsPackable>
359
+ <PreserveCompilationContext>false<\\/PreserveCompilationContext>
360
+ <GenerateRuntimeConfigurationFiles>true<\\/GenerateRuntimeConfigurationFiles>
361
+ <Copyright>([^<]+)<\\/Copyright>
362
+ <Description>{codeunit_name_regex}Tests is the test-project for {codeunit_name_regex}\\.<\\/Description>
363
+ <PackageProjectUrl>https:\\/\\/([^<]+)<\\/PackageProjectUrl>
364
+ <RepositoryUrl>https:\\/\\/([^<]+)\\.git</RepositoryUrl>
365
+ <RootNamespace>([^<]+)\\.Tests<\\/RootNamespace>
366
+ <ProduceReferenceAssembly>false<\\/ProduceReferenceAssembly>
367
+ <Nullable>(disable|enable|warnings|annotations)<\\/Nullable>
368
+ <Configurations>Development;QualityCheck;Productive<\\/Configurations>
369
+ <IsTestProject>true<\\/IsTestProject>
370
+ <LangVersion>([^<]+)<\\/LangVersion>
371
+ <PackageRequireLicenseAcceptance>true<\\/PackageRequireLicenseAcceptance>
372
+ <GenerateSerializationAssemblies>Off<\\/GenerateSerializationAssemblies>
373
+ <AppendTargetFrameworkToOutputPath>false<\\/AppendTargetFrameworkToOutputPath>
374
+ <OutputPath>\\.\\.\\\\Other\\\\Artifacts\\\\BuildResultTests_DotNet_win\\-x64<\\/OutputPath>
375
+ <PlatformTarget>([^<]+)<\\/PlatformTarget>
376
+ <WarningLevel>\\d<\\/WarningLevel>
377
+ <Prefer32Bit>false<\\/Prefer32Bit>
378
+ <SignAssembly>true<\\/SignAssembly>
379
+ <AssemblyOriginatorKeyFile>\\.\\.\\\\\\.\\.\\\\Other\\\\Resources\\\\PublicKeys\\\\StronglyNamedKey\\\\([^<]+)PublicKey\\.snk<\\/AssemblyOriginatorKeyFile>
380
+ <DelaySign>true<\\/DelaySign>
381
+ <NoWarn>([^<]+)<\\/NoWarn>
382
+ <WarningsAsErrors>([^<]+)<\\/WarningsAsErrors>
383
+ <ErrorLog>\\.\\.\\\\Other\\\\Resources\\\\CodeAnalysisResult\\\\{codeunit_name_regex}Tests\\.sarif<\\/ErrorLog>
384
+ <OutputType>Library<\\/OutputType>(\\n|.)*
385
+ <\\/PropertyGroup>
386
+ <PropertyGroup Condition=\\\"'\\$\\(Configuration\\)'=='Development'\\\">
387
+ <DebugType>full<\\/DebugType>
388
+ <DebugSymbols>true<\\/DebugSymbols>
389
+ <Optimize>false<\\/Optimize>
390
+ <DefineConstants>TRACE;DEBUG;Development<\\/DefineConstants>
391
+ <ErrorReport>prompt<\\/ErrorReport>
392
+ <\\/PropertyGroup>
393
+ <PropertyGroup Condition=\\\"'\\$\\(Configuration\\)'=='QualityCheck'\\\">
394
+ <DebugType>portable<\\/DebugType>
395
+ <DebugSymbols>true<\\/DebugSymbols>
396
+ <Optimize>false<\\/Optimize>
397
+ <DefineConstants>TRACE;QualityCheck<\\/DefineConstants>
398
+ <ErrorReport>none<\\/ErrorReport>
399
+ <\\/PropertyGroup>
400
+ <PropertyGroup Condition=\\\"'\\$\\(Configuration\\)'=='Productive'\\\">
401
+ <DebugType>portable<\\/DebugType>
402
+ <DebugSymbols>true<\\/DebugSymbols>
403
+ <Optimize>false<\\/Optimize>
404
+ <DefineConstants>Productive<\\/DefineConstants>
405
+ <ErrorReport>none<\\/ErrorReport>
406
+ <\\/PropertyGroup>(\\n|.)*
407
+ <\\/Project>\\n?$"""
408
+ result = self.__standardized_task_verify_standard_format_for_csproj_files(regex, csproj_file)
409
+ return (result[0], regex, result[1])
410
+
411
+ def __standardized_task_verify_standard_format_for_csproj_files(self, regex: str, csproj_file: str) -> tuple[bool, list[str]]:
412
+ filename = os.path.basename(csproj_file)
413
+ self._protected_sc.log.log(f"Check {filename}...",LogLevel.Debug)
414
+ file_content = GeneralUtilities.read_text_from_file(csproj_file)
415
+ regex_for_check = regex.replace("\r", GeneralUtilities.empty_string).replace("\n", "\\n")
416
+ file_content = file_content.replace("\r", GeneralUtilities.empty_string)
417
+ match = re.match(regex_for_check, file_content)
418
+ result = match is not None
419
+ hints = None
420
+ if not result:
421
+ hints = self.get_hints_for_csproj(regex, file_content)
422
+ return (result, hints)
423
+
424
+ @GeneralUtilities.check_arguments
425
+ def get_hints_for_csproj(self, regex: str, file_content: str) -> list[str]:
426
+ result: list[str] = []
427
+ regex_lines = GeneralUtilities.string_to_lines(regex)
428
+ file_content_lines = GeneralUtilities.string_to_lines(file_content)
429
+ #amount_of_regexes = len(regex_lines)
430
+ amount_of_lines = len(file_content_lines)
431
+ if amount_of_lines< len(regex_lines):
432
+ result.append("csproj-file has less lines than the regex requires.")
433
+ return result
434
+ for i in range(35):
435
+ s = file_content_lines[i]
436
+ r = regex_lines[i]
437
+ if not re.match(r, s):
438
+ result.append(f"Line {i+1} does not match: Regex='{r}' String='{s}'")
439
+ return result
440
+
441
+ @GeneralUtilities.check_arguments
442
+ def generate_reference(self) -> None:
443
+ self.generate_reference_using_docfx()
444
+
445
+
446
+ @GeneralUtilities.check_arguments
447
+ def update_year_for_dotnet_codeunit(self) -> None:
448
+ codeunit_folder:str=self.get_codeunit_folder()
449
+ codeunit_name = os.path.basename(codeunit_folder)
450
+ csproj_file = os.path.join(codeunit_folder, codeunit_name, f"{codeunit_name}.csproj")
451
+ self._protected_sc.update_year_in_copyright_tags(csproj_file)
452
+ csprojtests_file = os.path.join(codeunit_folder, f"{codeunit_name}Tests", f"{codeunit_name}Tests.csproj")
453
+ self._protected_sc.update_year_in_copyright_tags(csprojtests_file)
454
+ nuspec_file = os.path.join(codeunit_folder, "Other", "Build", f"{codeunit_name}.nuspec")
455
+ if os.path.isfile(nuspec_file):
456
+ self._protected_sc.update_year_in_copyright_tags(nuspec_file)
457
+
458
+ @GeneralUtilities.check_arguments
459
+ def run_testcases(self) -> None:
460
+ self._protected_sc.log.log("Run testcases...")
461
+ dotnet_build_configuration: str = self.get_target_environment_type()
462
+ codeunit_name: str = self.get_codeunit_name()
463
+
464
+ repository_folder: str = self.get_repository_folder().replace("\\", "/")
465
+ coverage_file_folder = os.path.join(repository_folder, codeunit_name, "Other/Artifacts/TestCoverage")
466
+ temp_folder = os.path.join(tempfile.gettempdir(), str(uuid.uuid4()))
467
+ GeneralUtilities.ensure_directory_exists(temp_folder)
468
+ runsettings_file = "runsettings.xml"
469
+ codeunit_folder = f"{repository_folder}/{codeunit_name}"
470
+ args: list[str] = ["test", ".", "-c", dotnet_build_configuration]
471
+ if os.path.isfile(os.path.join(codeunit_folder, runsettings_file)):
472
+ args += ["--settings", runsettings_file]
473
+ args += ["--collect:XPlat Code Coverage", "--results-directory", temp_folder]
474
+ self._protected_sc.run_program_argsasarray("dotnet", args, codeunit_folder, print_live_output=self.get_verbosity()==LogLevel.Debug, timeoutInSeconds=60*20)
475
+ # coverlet.collector writes the report to <temp_folder>/<run-guid>/coverage.cobertura.xml
476
+ generated_coverage_file: str = None
477
+ for root_dir, _, files in os.walk(temp_folder):
478
+ for f in files:
479
+ if f == "coverage.cobertura.xml":
480
+ generated_coverage_file = os.path.join(root_dir, f)
481
+ break
482
+ if generated_coverage_file is not None:
483
+ break
484
+ GeneralUtilities.assert_condition(generated_coverage_file is not None, f"Coverage file 'coverage.cobertura.xml' was not found under '{temp_folder}'.")
485
+ GeneralUtilities.ensure_directory_exists(coverage_file_folder)
486
+ target_file = os.path.join(coverage_file_folder, "TestCoverage.xml")
487
+ GeneralUtilities.ensure_file_does_not_exist(target_file)
488
+ shutil.copyfile(generated_coverage_file, target_file)
489
+ GeneralUtilities.ensure_directory_does_not_exist(temp_folder)
490
+ self.__remove_unrelated_package_from_testcoverage_file(target_file, codeunit_name)
491
+ root: etree._ElementTree = etree.parse(target_file)
492
+ source_base_path_in_coverage_file: str = root.xpath("//coverage/sources/source/text()")[0].replace("\\", "/")
493
+ content = GeneralUtilities.read_text_from_file(target_file)
494
+ 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}\"")
495
+ content = re.sub('\\\\', '/', content)
496
+ 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)
497
+ GeneralUtilities.write_text_to_file(target_file, content)
498
+ self.run_testcases_common_post_task(repository_folder, codeunit_name, True, self.get_target_environment_type())
499
+ artifacts_folder = os.path.join(repository_folder, codeunit_name, "Other", "Artifacts")
500
+ for subfolder in GeneralUtilities.get_direct_folders_of_folder(artifacts_folder):
501
+ if os.path.basename(subfolder).startswith("BuildResultTests_DotNet_"):
502
+ GeneralUtilities.ensure_directory_does_not_exist(subfolder)
503
+
504
+
505
+ @GeneralUtilities.check_arguments
506
+ def __remove_unrelated_package_from_testcoverage_file(self, file: str, codeunit_name: str) -> None:
507
+ root: etree._ElementTree = etree.parse(file)
508
+ packages = root.xpath('//coverage/packages/package')
509
+ for package in packages:
510
+ if package.attrib['name'] != codeunit_name:
511
+ package.getparent().remove(package)
512
+ result = etree.tostring(root).decode("utf-8")
513
+ GeneralUtilities.write_text_to_file(file, result)
514
+
515
+ @GeneralUtilities.check_arguments
516
+ def __standardized_tasks_run_testcases_for_dotnet_project_helper(self, source: str, codeunit_folder: str, match: re.Match) -> str:
517
+ filename = match.group(1)
518
+ file = os.path.join(source, filename)
519
+ GeneralUtilities.assert_condition(file.startswith(codeunit_folder), f"Unexpected path for coverage-file. File: \"{file}\"; codeunitfolder: \"{codeunit_folder}\"")
520
+ filename_relative = f".{file[len(codeunit_folder):]}"
521
+ return f'filename="{filename_relative}"'
522
+
523
+
524
+ def get_dependencies(self)->dict[str,set[str]]:
525
+ return dict[str,set[str]]()#TODO
526
+
527
+ @GeneralUtilities.check_arguments
528
+ def get_available_versions(self,dependencyname:str)->list[str]:
529
+ return []#TODO
530
+
531
+ def set_dependency_version(self,name:str,new_version:str)->None:
532
+ raise ValueError(f"Operation is not implemented.")
533
+ #self.update_year_for_dotnet_codeunit()
534
+ #csproj_file:str=os.path.join(self.get_codeunit_folder(), self.get_codeunit_name(), self.get_codeunit_name() + ".csproj")
535
+ #self._protected_sc.update_dependencies_of_dotnet_project(csproj_file,[])#TODO set ignored codeunits
536
+
537
+
538
+ class TFCPS_CodeUnitSpecific_DotNet_CLI:
539
+
540
+ @staticmethod
541
+ @GeneralUtilities.check_arguments
542
+ def parse(file:str)->TFCPS_CodeUnitSpecific_DotNet_Functions:
543
+ parser=TFCPS_CodeUnitSpecific_Base_CLI.get_base_parser()
544
+ #add custom parameter if desired
545
+ args=parser.parse_args()
546
+ result:TFCPS_CodeUnitSpecific_DotNet_Functions=TFCPS_CodeUnitSpecific_DotNet_Functions(file,LogLevel(int(args.verbosity)),args.targetenvironmenttype,not args.nocache,args.ispremerge)
547
+ return result
File without changes