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,301 @@
1
+ import os
2
+ import json
3
+ from datetime import datetime, timedelta,timezone
4
+ import yaml
5
+ from ..GeneralUtilities import GeneralUtilities
6
+ from ..ScriptCollectionCore import ScriptCollectionCore
7
+ from ..SCLog import LogLevel
8
+ from .TFCPS_CodeUnit_BuildCodeUnit import TFCPS_CodeUnit_BuildCodeUnit
9
+ from .TFCPS_Tools_General import TFCPS_Tools_General
10
+
11
+ class TFCPS_CodeUnit_BuildCodeUnits:
12
+ repository:str=None
13
+ tfcps_tools_general:TFCPS_Tools_General=None
14
+ sc:ScriptCollectionCore=None
15
+ target_environment_type:str=None
16
+ additionalargumentsfile:str=None
17
+ __use_cache:bool
18
+ __is_pre_merge:bool
19
+
20
+ def __init__(self,repository:str,loglevel:LogLevel,target_environment_type:str,additionalargumentsfile:str,use_cache:bool,is_pre_merge:bool):
21
+ self.sc=ScriptCollectionCore()
22
+ self.sc.log.loglevel=loglevel
23
+ self.__use_cache=use_cache
24
+ self.sc.assert_is_git_repository(repository)
25
+ self.repository=repository
26
+ self.tfcps_tools_general:TFCPS_Tools_General=TFCPS_Tools_General(self.sc)
27
+ allowed_target_environment_types=["Development","QualityCheck","Productive"]
28
+ GeneralUtilities.assert_condition(target_environment_type in allowed_target_environment_types,"Unknown target-environment-type. Allowed values are: "+", ".join(allowed_target_environment_types))
29
+ self.target_environment_type=target_environment_type
30
+ self.additionalargumentsfile=additionalargumentsfile
31
+ self.__is_pre_merge=is_pre_merge
32
+
33
+ @GeneralUtilities.check_arguments
34
+ def build_codeunits(self) -> None:
35
+ self.sc.log.log(GeneralUtilities.get_line())
36
+ start_time:datetime=GeneralUtilities.get_now()
37
+ self.sc.log.log(f"Start building codeunits at {GeneralUtilities.datetime_to_string_for_readable_entry(start_time,False)}. (Target environment-type: {self.target_environment_type})")
38
+
39
+ #check if changelog exists
40
+ changelog_file=os.path.join(self.repository,"Other","Resources","Changelog",f"v{self.tfcps_tools_general.get_version_of_project(self.repository)}.md")
41
+ GeneralUtilities.assert_file_exists(changelog_file,f"Changelogfile \"{changelog_file}\" does not exist. Try to create it for example using \"sccreatechangelogentry -m ...\".")
42
+
43
+ #run prepare-script
44
+ self.run_prepare_script()
45
+
46
+ #mark current version as supported
47
+ now = GeneralUtilities.get_now()
48
+ project_version:str=self.tfcps_tools_general.get_version_of_project(self.repository)
49
+ if not self.tfcps_tools_general.suport_information_exists(self.repository, project_version):
50
+ amount_of_years_for_support:int=1
51
+ support_time = timedelta(days=365*amount_of_years_for_support+30*3+1)
52
+ until = now + support_time
53
+ until_day = datetime(until.year, until.month, until.day, 0, 0, 0)
54
+ from_day = datetime(now.year, now.month, now.day, 0, 0, 0)
55
+ self.tfcps_tools_general.mark_current_version_as_supported(self.repository,project_version,from_day,until_day)
56
+
57
+ codeunits:list[str]=self.tfcps_tools_general.get_codeunits(self.repository)
58
+ GeneralUtilities.assert_condition(0<len(codeunits),f"No codeunits found in repository {self.repository}.")
59
+ self.sc.log.log("Codeunits will be built in the following order:")
60
+ for codeunit_name in codeunits:
61
+ self.sc.log.log(f" - {codeunit_name}")
62
+ for codeunit_name in codeunits:
63
+ tFCPS_CodeUnit_BuildCodeUnit:TFCPS_CodeUnit_BuildCodeUnit = TFCPS_CodeUnit_BuildCodeUnit(os.path.join(self.repository,codeunit_name),self.sc.log.loglevel,self.target_environment_type,self.additionalargumentsfile,self.use_cache(),self.is_pre_merge())
64
+ self.sc.log.log(GeneralUtilities.get_line())
65
+ tFCPS_CodeUnit_BuildCodeUnit.build_codeunit()
66
+
67
+ self.sc.log.log(GeneralUtilities.get_line())
68
+ self.__search_for_vulnerabilities()
69
+ self.__search_for_secrets()
70
+ if self.is_pre_merge():
71
+ self.__translate()
72
+ self.__collect_metrics()
73
+ self.__generate_loc_diagram()
74
+ end_time:datetime=GeneralUtilities.get_now()
75
+ duration=end_time-start_time
76
+ self.sc.log.log(f"Finished building codeunits at {GeneralUtilities.datetime_to_string_for_readable_entry(end_time,False)}. (Duration: {GeneralUtilities.timedelta_to_simple_string(duration)})")
77
+ self.sc.log.log(GeneralUtilities.get_line())
78
+
79
+ @GeneralUtilities.check_arguments
80
+ def run_prepare_script(self):
81
+ args=["--repository",self.repository,"--targetenvironmenttype",self.target_environment_type,"--verbosity",str(int(self.sc.log.loglevel))]
82
+ if GeneralUtilities.string_has_content(self.additionalargumentsfile):
83
+ args=args+["--additionalargumentsfile", self.additionalargumentsfile]
84
+ if not self.__use_cache:
85
+ if self.sc.git_repository_has_uncommitted_changes(self.repository):
86
+ self.sc.log.log("No-cache-option can not be applied because there are uncommited changes in the repository.",LogLevel.Warning)
87
+ else:
88
+ args=args+["--nocache"]
89
+
90
+ if os.path.isfile( os.path.join( self.sc.get_scriptcollection_configuration_folder(),"TFCPS","CustomPreCodeUnitBuildScript.py")):
91
+ self.sc.log.log("Run custom pre-codeunitbuild script...")
92
+ self.sc.run_program_argsasarray(GeneralUtilities.get_python_executable(),["CustomPreCodeUnitBuildScript.py"]+args, os.path.join( self.sc.get_scriptcollection_configuration_folder(),"TFCPS"),print_live_output=True)
93
+
94
+ if os.path.isfile( os.path.join(self.repository,"Other","Scripts","PrepareBuildCodeunits.py")):
95
+ self.sc.log.log("Prepare build codeunits...")
96
+ self.sc.run_program_argsasarray(GeneralUtilities.get_python_executable(),["PrepareBuildCodeunits.py"]+args, os.path.join(self.repository,"Other","Scripts"),print_live_output=True)
97
+
98
+ @GeneralUtilities.check_arguments
99
+ def build_codeunits_in_container(self) -> None:
100
+ raise ValueError("Not implemented.")
101
+
102
+ @GeneralUtilities.check_arguments
103
+ def __translate(self) -> None:
104
+ for taskfile_name in ("Taskfile.yml", "Taskfile.yaml"):
105
+ taskfile = os.path.join(self.repository, taskfile_name)
106
+ if os.path.isfile(taskfile):
107
+ with open(taskfile, "r", encoding="utf-8") as f:
108
+ taskfile_content = yaml.safe_load(f)
109
+ if isinstance(taskfile_content.get("tasks"), dict) and "Translate" in taskfile_content["tasks"]:
110
+ self.sc.run_program("task", "Translate", self.repository, print_live_output=self.sc.log.loglevel == LogLevel.Debug)
111
+ break
112
+
113
+ @GeneralUtilities.check_arguments
114
+ def __collect_metrics(self) -> None:
115
+ project_version: str=self.tfcps_tools_general.get_version_of_project(self.repository)
116
+ self.sc.log.log("Collect metrics...")
117
+ loc = self.sc.get_lines_of_code_with_default_excluded_patterns(self.repository)
118
+ loc_metric_folder = os.path.join(self.repository, "Other", "Metrics")
119
+ GeneralUtilities.ensure_directory_exists(loc_metric_folder)
120
+ loc_metric_file = os.path.join(loc_metric_folder, "RepositoryStatisticsPerCommit.csv")
121
+ GeneralUtilities.ensure_file_exists(loc_metric_file)
122
+
123
+ #remove legacy metrics-file. the following 2 lines should be removed after 2026-12-31
124
+ legacy_metrics_file = os.path.join(loc_metric_folder, "LinesOfCode.csv")
125
+ GeneralUtilities.ensure_file_does_not_exist(legacy_metrics_file)
126
+
127
+ old_lines = GeneralUtilities.read_nonempty_lines_from_file(loc_metric_file)
128
+ header_line="Version;Timestamp;LinesOfCode"
129
+ new_lines = [header_line]
130
+ current_version_string=f"v{project_version}"
131
+ for old_line in old_lines:
132
+ if not old_line.startswith(current_version_string+";") and old_line!=header_line:
133
+ new_lines.append(old_line)
134
+ c_date:datetime=GeneralUtilities.get_now().astimezone(timezone.utc)
135
+ commit_date=GeneralUtilities.datetime_to_string_for_logfile_entry(c_date,False)
136
+ new_lines.append(f"{current_version_string};{commit_date};{loc}")
137
+ GeneralUtilities.write_lines_to_file(loc_metric_file, new_lines)
138
+
139
+
140
+ @GeneralUtilities.check_arguments
141
+ def __generate_loc_diagram(self):
142
+ self.sc.log.log("Generate LoC-diagram...")
143
+ loc_metric_folder = os.path.join(self.repository, "Other", "Metrics")
144
+ GeneralUtilities.ensure_directory_exists(loc_metric_folder)
145
+ loc_metric_file = os.path.join(loc_metric_folder, "RepositoryStatisticsPerCommit.csv")
146
+ GeneralUtilities.ensure_file_exists(loc_metric_file)
147
+
148
+ filenamebase="LoC-Diagram"
149
+
150
+ diagram_definition_folder=os.path.join(self.repository, "Other", "Reference","Technical","Diagrams")
151
+ GeneralUtilities.ensure_directory_exists(diagram_definition_folder)
152
+
153
+ diagram_definition_file=os.path.join(diagram_definition_folder,f"{filenamebase}.json")
154
+ GeneralUtilities.ensure_file_exists(diagram_definition_file)
155
+ GeneralUtilities.write_text_to_file(diagram_definition_file,GeneralUtilities.empty_string)
156
+
157
+ loc_data_file=os.path.join(diagram_definition_folder,f"{filenamebase}.csv")
158
+ GeneralUtilities.ensure_file_exists(loc_data_file)
159
+ csv_lines=[]
160
+ for line in GeneralUtilities.read_lines_from_file(loc_metric_file):
161
+ if GeneralUtilities.string_has_content(line):
162
+ splitted=line.split(";")
163
+ v=splitted[0]
164
+ t=splitted[1]
165
+ loc=splitted[2]
166
+ csv_lines.append(f"{v},{t},{loc}")
167
+ GeneralUtilities.write_lines_to_file(loc_data_file,csv_lines)
168
+ diagram_json = {
169
+ "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
170
+ "description": "Lines of Code over time",
171
+ "width": 800,
172
+ "height": 400,
173
+ "data": {
174
+ "url": f"./{filenamebase}.csv",
175
+ "format": {
176
+ "type": "csv"
177
+ }
178
+ },
179
+ "mark": {
180
+ "type": "line",
181
+ "point": True
182
+ },
183
+ "encoding": {
184
+ "x": {
185
+ "field": "Timestamp",
186
+ "type": "temporal",
187
+ "title": "Date"
188
+ },
189
+ "y": {
190
+ "field": "LinesOfCode",
191
+ "type": "quantitative",
192
+ "title": "Lines of Code"
193
+ },
194
+ "tooltip": [
195
+ {
196
+ "field": "Version",
197
+ "type": "ordinal"
198
+ },
199
+ {
200
+ "field": "LinesOfCode",
201
+ "type": "quantitative"
202
+ },
203
+ {
204
+ "field": "Timestamp",
205
+ "type": "temporal"
206
+ }
207
+ ]
208
+ }
209
+ }
210
+
211
+ with open(diagram_definition_file, "w", encoding="utf-8") as f:
212
+ json.dump(
213
+ diagram_json,
214
+ f,
215
+ indent=2,
216
+ sort_keys=False,
217
+ ensure_ascii=False
218
+ )
219
+ diagram_svg_file=os.path.join(self.repository,"Other","Reference","Technical","Diagrams",f"{filenamebase}.svg")
220
+ GeneralUtilities.ensure_file_exists(diagram_svg_file)
221
+ GeneralUtilities.assert_condition(not self.sc.file_is_git_ignored(f"Other/Reference/Technical/Diagrams/{filenamebase}.svg",self.repository),f"Other/Reference/Technical/Diagrams/{filenamebase}.svg must not be git-ignored")#because it should be referencable in markdown-files and viewable without building the codeunits.
222
+ self.sc.generate_chart_diagram(diagram_definition_file,os.path.basename(diagram_svg_file))
223
+ self.sc.format_xml_file(diagram_svg_file)
224
+
225
+ @GeneralUtilities.check_arguments
226
+ def __search_for_vulnerabilities(self):
227
+ pass#TODO
228
+
229
+ @GeneralUtilities.check_arguments
230
+ def __search_for_secrets(self):
231
+ enabled:bool=False#TODO reenable when a solution is found to ignore false positives
232
+ if enabled:
233
+ exe_paths=self.tfcps_tools_general.ensure_trufflehog_is_available()
234
+ exe_path:str=None
235
+ if GeneralUtilities.current_system_is_windows():
236
+ exe_path=exe_paths["Windows"]
237
+ elif GeneralUtilities.current_system_is_linux():
238
+ exe_path=exe_paths["Linux"]
239
+ else:
240
+ raise ValueError("unsupported")#TODO check for macos
241
+ result=self.sc.run_program(exe_path,"filesystem . --json",self.repository)
242
+
243
+ self.sc.log.log("Secret-scan-result:")#TODO replace this by real analysis
244
+ for line in GeneralUtilities.string_to_lines(result[1]):
245
+ self.sc.log.log(line)
246
+ for line in GeneralUtilities.string_to_lines(result[2]):
247
+ self.sc.log.log(line,LogLevel.Error)
248
+
249
+ @GeneralUtilities.check_arguments
250
+ def use_cache(self) -> bool:
251
+ return self.__use_cache
252
+
253
+
254
+ @GeneralUtilities.check_arguments
255
+ def is_pre_merge(self) -> bool:
256
+ return self.__is_pre_merge
257
+
258
+ @GeneralUtilities.check_arguments
259
+ def update_dependencies(self) -> None:
260
+ repository=self.repository
261
+ self.sc.log.log("Update dependencies...")
262
+ self.update_year_in_license_file()
263
+ self.sc.assert_is_git_repository(repository)
264
+ self.sc.assert_no_uncommitted_changes(repository)
265
+ self.run_prepare_script()
266
+ if os.path.isfile(os.path.join(repository,"Other","Scripts","UpdateDependencies.py")):
267
+ self.sc.run_program(GeneralUtilities.get_python_executable(),"UpdateDependencies.py",os.path.join(repository,"Other","Scripts"))
268
+ codeunits:list[str]=self.tfcps_tools_general.get_codeunits(repository)
269
+ for codeunit_name in codeunits:
270
+ self.sc.log.log(f"Update dependencies of codeunit {codeunit_name}...")
271
+ codeunit_folder=os.path.join(repository,codeunit_name)
272
+ tFCPS_CodeUnit_BuildCodeUnit:TFCPS_CodeUnit_BuildCodeUnit = TFCPS_CodeUnit_BuildCodeUnit(codeunit_folder,self.sc.log.loglevel,"QualityCheck",None,True,False)
273
+ tFCPS_CodeUnit_BuildCodeUnit.build_codeunit()#ensure requirements for updating are there (some programming-languages needs this)
274
+ if self.tfcps_tools_general.codeunit_has_updatable_dependencies(os.path.join(codeunit_folder,f"{codeunit_name}.codeunit.xml")):
275
+ self.sc.run_program(GeneralUtilities.get_python_executable(),"UpdateDependencies.py",os.path.join(codeunit_folder,"Other"))
276
+ tFCPS_CodeUnit_BuildCodeUnit.build_codeunit()#check if codeunit is still buildable
277
+ if self.sc.git_repository_has_uncommitted_changes(repository):
278
+ changelog_folder = os.path.join(repository, "Other", "Resources", "Changelog")
279
+ project_version:str=self.tfcps_tools_general.get_version_of_project(repository)
280
+ changelog_file = os.path.join(changelog_folder, f"v{project_version}.md")
281
+ if not os.path.isfile(changelog_file):
282
+ self.__ensure_changelog_file_is_added(repository, project_version)
283
+ t=TFCPS_CodeUnit_BuildCodeUnits(repository,self.sc.log.loglevel,"QualityCheck",None,True,False)
284
+ t.build_codeunits()#check codeunits are buildable at all
285
+ self.sc.git_commit(repository, "Updated dependencies", stage_all_changes=True)
286
+
287
+ @GeneralUtilities.check_arguments
288
+ def __ensure_changelog_file_is_added(self, repository_folder: str, version_of_project: str):
289
+ changelog_file = os.path.join(repository_folder, "Other", "Resources", "Changelog", f"v{version_of_project}.md")
290
+ if not os.path.isfile(changelog_file):
291
+ GeneralUtilities.ensure_file_exists(changelog_file)
292
+ GeneralUtilities.write_text_to_file(changelog_file, """# Release notes
293
+
294
+ ## Changes
295
+
296
+ - Updated dependencies.
297
+ """)
298
+
299
+ @GeneralUtilities.check_arguments
300
+ def update_year_in_license_file(self) -> None:
301
+ self.sc.update_year_in_first_line_of_file(os.path.join(self.repository, "License.txt"))
@@ -0,0 +1,98 @@
1
+ import os
2
+ from ..GeneralUtilities import GeneralUtilities
3
+ from ..ScriptCollectionCore import ScriptCollectionCore
4
+ from ..SCLog import LogLevel
5
+ from .TFCPS_Tools_General import TFCPS_Tools_General
6
+ from .TFCPS_MergeToMain import TFCPS_MergeToMain,MergeToMainConfiguration
7
+ from .TFCPS_MergeToStable import TFCPS_MergeToStable,MergeToStableConfiguration
8
+
9
+
10
+ class TFCPS_CreateReleaseConfiguration:
11
+
12
+ product_name: str
13
+ branch_to_be_released:str
14
+ additional_arguments_file:str
15
+ log_level:LogLevel
16
+ main_branch:str
17
+ stable_branch:str
18
+ build_repository:str
19
+ repository:str
20
+ reference_repository:str
21
+ common_remote_name:str
22
+ build_repo_main_branch_name:str
23
+ reference_repo_main_branch_name:str
24
+ reference_remote_name:str
25
+ build_repo_remote_name:str
26
+ artifacts_target_folder:str
27
+ common_remote_url:str
28
+
29
+ def __init__(self, current_file: str, product_name: str,branch_to_be_released:str,log_level:LogLevel,additional_arguments_file:str,main_branch:str,stable_branch:str,common_remote_name:str,build_repo_main_branch_name:str,reference_repo_main_branch_name:str,reference_remote_name:str,build_repo_remote_name:str,artifacts_target_folder:str,common_remote_url:str):
30
+ self.product_name = product_name
31
+ self.branch_to_be_released=branch_to_be_released
32
+ self.additional_arguments_file=additional_arguments_file
33
+ self.log_level=log_level
34
+ self.main_branch=main_branch
35
+ self.stable_branch=stable_branch
36
+ self.build_repository=ScriptCollectionCore().search_repository_folder(current_file)
37
+ self.repository=os.path.join(self.build_repository,"Submodules",product_name)
38
+ self.reference_repository=os.path.join(self.build_repository,"Submodules",product_name+"Reference")
39
+ self.common_remote_name=common_remote_name
40
+ self.build_repo_main_branch_name=build_repo_main_branch_name
41
+ self.reference_repo_main_branch_name=reference_repo_main_branch_name
42
+ self.reference_remote_name=reference_remote_name
43
+ self.build_repo_remote_name=build_repo_remote_name
44
+ self.artifacts_target_folder=artifacts_target_folder
45
+ self.common_remote_url=common_remote_url
46
+
47
+ class TFCPS_CreateRelease:
48
+
49
+ sc:ScriptCollectionCore
50
+ tFCPS_Tools_General:TFCPS_Tools_General
51
+
52
+ def __init__(self):
53
+ self.sc=ScriptCollectionCore()
54
+ self.tFCPS_Tools_General=TFCPS_Tools_General(self.sc)
55
+
56
+ @GeneralUtilities.check_arguments
57
+ def do_release(self,tfcps_CreateReleaseConfiguration:TFCPS_CreateReleaseConfiguration)->bool:
58
+ self.sc.log.loglevel=tfcps_CreateReleaseConfiguration.log_level
59
+ return self.sc.do_and_log_task(f"Release {tfcps_CreateReleaseConfiguration.product_name}",lambda : self.__do(tfcps_CreateReleaseConfiguration))
60
+
61
+ @GeneralUtilities.check_arguments
62
+ def __do(self,tfcps_CreateReleaseConfiguration:TFCPS_CreateReleaseConfiguration)->bool:
63
+ self.sc.log.log("Do checks...",LogLevel.Information)
64
+
65
+ self.sc.assert_is_git_repository(tfcps_CreateReleaseConfiguration.build_repository)
66
+ self.sc.assert_no_uncommitted_changes(tfcps_CreateReleaseConfiguration.build_repository)
67
+
68
+ self.sc.assert_is_git_repository(tfcps_CreateReleaseConfiguration.repository)
69
+ self.sc.assert_no_uncommitted_changes(tfcps_CreateReleaseConfiguration.repository)
70
+
71
+ self.sc.assert_is_git_repository(tfcps_CreateReleaseConfiguration.reference_repository)
72
+ self.sc.assert_no_uncommitted_changes(tfcps_CreateReleaseConfiguration.reference_repository)
73
+
74
+ release_was_done:bool=False
75
+
76
+ branch_to_be_released_commit_id = self.sc.git_get_commit_id(tfcps_CreateReleaseConfiguration.repository, tfcps_CreateReleaseConfiguration.branch_to_be_released)
77
+ main_branch_commit_id = self.sc.git_get_commit_id(tfcps_CreateReleaseConfiguration.repository, tfcps_CreateReleaseConfiguration.main_branch)
78
+ if branch_to_be_released_commit_id == main_branch_commit_id:
79
+ self.sc.log.log("Merge to main-branch will not be done because there are no changed which can be merged.")
80
+ else:
81
+ self.sc.log.log("Merge to main-branch...",LogLevel.Information)
82
+ mergeToMainConfiguration:MergeToMainConfiguration=MergeToMainConfiguration(tfcps_CreateReleaseConfiguration.current_file,tfcps_CreateReleaseConfiguration.product_name,tfcps_CreateReleaseConfiguration.product_name,tfcps_CreateReleaseConfiguration.branch_to_be_released,tfcps_CreateReleaseConfiguration.log_level,tfcps_CreateReleaseConfiguration.additional_arguments_file,tfcps_CreateReleaseConfiguration.main_branch,tfcps_CreateReleaseConfiguration.common_remote_name,tfcps_CreateReleaseConfiguration.build_repository)
83
+ tFCPS_MergeToMain:TFCPS_MergeToMain=TFCPS_MergeToMain(mergeToMainConfiguration)
84
+ tFCPS_MergeToMain.merge_to_main_branch()
85
+
86
+ main_branch_commit_id = self.sc.git_get_commit_id(tfcps_CreateReleaseConfiguration.repository, tfcps_CreateReleaseConfiguration.main_branch)
87
+ stable_branch_commit_id = self.sc.git_get_commit_id(tfcps_CreateReleaseConfiguration.repository, tfcps_CreateReleaseConfiguration.stable_branch)
88
+ if main_branch_commit_id == stable_branch_commit_id:
89
+ self.sc.log.log("Merge to stable-branch will not be done because there are no changed which can be released.")
90
+ else:
91
+ self.sc.log.log("Merge to stable-branch...",LogLevel.Information)
92
+ mergeToStableConfiguration:MergeToStableConfiguration=MergeToStableConfiguration(tfcps_CreateReleaseConfiguration.log_level,tfcps_CreateReleaseConfiguration.main_branch,tfcps_CreateReleaseConfiguration.stable_branch,tfcps_CreateReleaseConfiguration.repository,tfcps_CreateReleaseConfiguration.build_repository,tfcps_CreateReleaseConfiguration.common_remote_name,tfcps_CreateReleaseConfiguration.build_repo_main_branch_name,tfcps_CreateReleaseConfiguration.reference_repo_main_branch_name,tfcps_CreateReleaseConfiguration.reference_remote_name,tfcps_CreateReleaseConfiguration.build_repo_remote_name,tfcps_CreateReleaseConfiguration.artifacts_target_folder,tfcps_CreateReleaseConfiguration.common_remote_url,tfcps_CreateReleaseConfiguration.additional_arguments_file)
93
+ tFCPS_MergeToStable:TFCPS_MergeToStable=TFCPS_MergeToStable(mergeToStableConfiguration)
94
+ tFCPS_MergeToStable.merge_to_stable_branch()
95
+
96
+ release_was_done=True
97
+
98
+ return release_was_done
@@ -0,0 +1,44 @@
1
+ import argparse
2
+ from ..ScriptCollectionCore import ScriptCollectionCore
3
+ from ..SCLog import LogLevel
4
+ from .TFCPS_Tools_General import TFCPS_Tools_General
5
+
6
+ class TFCPS_Generic_Functions:
7
+ script_file:str
8
+ repository_folder:str=None
9
+ targetenvironmenttype:str
10
+ additionalargumentsfile:str
11
+ verbosity:LogLevel
12
+ sc:ScriptCollectionCore
13
+ tfcps_Tools_General:TFCPS_Tools_General
14
+ __use_cache:bool
15
+
16
+ def __init__(self,script_file:str,targetenvironmenttype:str,additionalargumentsfile:str,verbosity:LogLevel,use_cache:bool):
17
+ self.verbosity=verbosity
18
+ self.script_file=script_file
19
+ self.sc=ScriptCollectionCore()
20
+ self.sc.log.loglevel=self.verbosity
21
+ self.tfcps_Tools_General=TFCPS_Tools_General(self.sc)
22
+ self.repository_folder=self.sc.search_repository_folder(script_file)
23
+ self.targetenvironmenttype=targetenvironmenttype
24
+ self.__use_cache=use_cache
25
+ self.additionalargumentsfile=additionalargumentsfile
26
+
27
+ def use_cache(self)->bool:
28
+ return self.__use_cache
29
+
30
+
31
+ class TFCPS_Generic_CLI:
32
+
33
+ @staticmethod
34
+ def parse(file:str)->TFCPS_Generic_Functions:
35
+ parser = argparse.ArgumentParser()
36
+ verbosity_values = ", ".join(f"{lvl.value}={lvl.name}" for lvl in LogLevel)
37
+ parser.add_argument('-r', '--repository', required=False, default=None)
38
+ parser.add_argument('-e', '--targetenvironmenttype', required=False, default="QualityCheck")
39
+ parser.add_argument('-a', '--additionalargumentsfile', required=False, default=None)
40
+ parser.add_argument('-v', '--verbosity', required=False, default=3, help=f"Sets the loglevel. Possible values: {verbosity_values}")
41
+ parser.add_argument('-c', '--nocache', action='store_true', required=False, default=False)
42
+ args=parser.parse_args()
43
+ result:TFCPS_Generic_Functions=TFCPS_Generic_Functions(file,args.targetenvironmenttype,args.additionalargumentsfile,LogLevel(int(args.verbosity)),not args.nocache)
44
+ return result
@@ -0,0 +1,128 @@
1
+ import argparse
2
+ import os
3
+ from ..GeneralUtilities import GeneralUtilities
4
+ from ..SCLog import LogLevel
5
+ from ..ScriptCollectionCore import ScriptCollectionCore
6
+ from .TFCPS_Tools_General import TFCPS_Tools_General
7
+ from .TFCPS_CodeUnit_BuildCodeUnits import TFCPS_CodeUnit_BuildCodeUnits
8
+ from .TFCPS_Generic import TFCPS_Generic_Functions
9
+
10
+ class MergeToMainConfiguration:
11
+ product_name: str
12
+ merge_source_branch:str
13
+ additional_arguments_file:str
14
+ log_level:LogLevel
15
+ main_branch:str
16
+ repository_folder:str
17
+ tFCPS_Generic_Functions:TFCPS_Generic_Functions
18
+ common_remote_name:str
19
+ build_repo:str
20
+ sc:ScriptCollectionCore=ScriptCollectionCore()
21
+
22
+ def __init__(self, current_file: str,repository:str, product_name: str,merge_source_branch:str,log_level:LogLevel,additional_arguments_file:str,main_branch:str,common_remote_name:str,build_repo:str):
23
+ self.sc.log.loglevel=log_level
24
+ self.repository_folder = repository
25
+ self.product_name = product_name
26
+ self.merge_source_branch=merge_source_branch
27
+ self.additional_arguments_file=additional_arguments_file
28
+ self.log_level=log_level
29
+ self.main_branch=main_branch
30
+ self.common_remote_name=common_remote_name
31
+ self.build_repo=build_repo
32
+
33
+ class TFCPS_MergeToMain:
34
+
35
+ sc:ScriptCollectionCore
36
+ tFCPS_Tools_General:TFCPS_Tools_General
37
+ generic_prepare_new_release_arguments:MergeToMainConfiguration=None
38
+
39
+ def __init__(self,generic_prepare_new_release_arguments:MergeToMainConfiguration):
40
+ self.sc=ScriptCollectionCore()
41
+ self.tFCPS_Tools_General=TFCPS_Tools_General(self.sc)
42
+ self.generic_prepare_new_release_arguments=generic_prepare_new_release_arguments
43
+
44
+ @GeneralUtilities.check_arguments
45
+ def merge_to_main_branch(self ) -> None:
46
+ self.sc.log.loglevel=self.generic_prepare_new_release_arguments.log_level
47
+ self.sc.log.log("Merge to main-branch...")
48
+ fast_forward_source_branch: bool=True
49
+ source_branch: str=self.generic_prepare_new_release_arguments.merge_source_branch
50
+ target_branch: str=self.generic_prepare_new_release_arguments.main_branch
51
+ self.sc.assert_is_git_repository(self.generic_prepare_new_release_arguments.repository_folder)
52
+
53
+ if self.sc.git_get_commit_id(self.generic_prepare_new_release_arguments.repository_folder,source_branch)==self.sc.git_get_commit_id(self.generic_prepare_new_release_arguments.repository_folder,target_branch):
54
+ self.sc.log.log("Source- and target-branch are on the same commit.")
55
+ return
56
+
57
+ self.sc.assert_no_uncommitted_changes(self.generic_prepare_new_release_arguments.repository_folder)
58
+ self.sc.git_checkout(self.generic_prepare_new_release_arguments.repository_folder, source_branch)
59
+ self.sc.assert_no_uncommitted_changes(self.generic_prepare_new_release_arguments.repository_folder)
60
+
61
+ #premerge-build
62
+ #TODO the premerge-build is now supposed to be in MergeToStable
63
+ try:
64
+ tfcps_CodeUnit_BuildCodeUnits:TFCPS_CodeUnit_BuildCodeUnits=TFCPS_CodeUnit_BuildCodeUnits(self.generic_prepare_new_release_arguments.repository_folder,self.sc.log.loglevel,"QualityCheck",self.generic_prepare_new_release_arguments.additional_arguments_file,False,True)
65
+ tfcps_CodeUnit_BuildCodeUnits.build_codeunits()
66
+ except Exception:
67
+ self.sc.log.log(f"Branch {source_branch} is not buildable.",LogLevel.Error)
68
+ self.sc.git_undo_all_changes(self.generic_prepare_new_release_arguments.repository_folder)
69
+ raise
70
+ self.sc.git_commit(self.generic_prepare_new_release_arguments.repository_folder, 'Pre-merge-commit', stage_all_changes=True, no_changes_behavior=0)
71
+
72
+
73
+ if fast_forward_source_branch:
74
+ self.sc.git_checkout(self.generic_prepare_new_release_arguments.repository_folder, source_branch)
75
+ project_version:str=self.tFCPS_Tools_General.get_version_of_project(self.generic_prepare_new_release_arguments.repository_folder)
76
+ self.sc.git_merge(self.generic_prepare_new_release_arguments.repository_folder, source_branch, target_branch, False, True)
77
+ self.sc.git_merge(self.generic_prepare_new_release_arguments.repository_folder, target_branch, source_branch, True, True)
78
+ self.sc.git_create_tag(self.generic_prepare_new_release_arguments.repository_folder,target_branch,f"v{project_version}")
79
+
80
+ self.sc.log.log("Push branches...")
81
+ self.sc.git_push_with_retry(self.generic_prepare_new_release_arguments.repository_folder,self.generic_prepare_new_release_arguments.common_remote_name,source_branch,source_branch)
82
+ self.sc.git_push_with_retry(self.generic_prepare_new_release_arguments.repository_folder,self.generic_prepare_new_release_arguments.common_remote_name,target_branch,target_branch)
83
+ self.sc.git_commit(self.generic_prepare_new_release_arguments.build_repo,"Updated submodule")
84
+
85
+ class TFCPS_MergeToMain_CLI:
86
+
87
+ @staticmethod
88
+ @GeneralUtilities.check_arguments
89
+ def get_with_overwritable_defaults(file:str,default_merge_source_branch:str=None,default_loglevel:LogLevel=None,default_additionalargumentsfile:str=None,default_main_branch:str=None,default_common_remote_name:str=None)->TFCPS_MergeToMain:
90
+ parser = argparse.ArgumentParser()
91
+ verbosity_values = ", ".join(f"{lvl.value}={lvl.name}" for lvl in LogLevel)
92
+ parser.add_argument('-s', '--mergesourcebranch', required=False)
93
+ parser.add_argument('-a', '--additionalargumentsfile', required=False)
94
+ parser.add_argument('-t', '--mainbranch', required=False)
95
+ parser.add_argument('-r', '--commonremotename', required=False)
96
+ parser.add_argument('-v', '--verbosity', required=False, help=f"Sets the loglevel. Possible values: {verbosity_values}")
97
+ args=parser.parse_args()
98
+
99
+ sc:ScriptCollectionCore=ScriptCollectionCore()
100
+
101
+ build_repo=GeneralUtilities.resolve_relative_path("../../..",file)
102
+ sc.assert_is_git_repository(build_repo)
103
+
104
+ default_product_name=os.path.basename(build_repo)[:-len("Build")]
105
+
106
+ if args.mergesourcebranch is not None:
107
+ default_merge_source_branch=args.mergesourcebranch#other/next-release
108
+ GeneralUtilities.assert_not_null(default_merge_source_branch,"mergesourcebranch is not set")
109
+
110
+ if args.verbosity is not None:
111
+ default_loglevel=LogLevel(int( args.verbosity))
112
+ GeneralUtilities.assert_not_null(default_loglevel,"verbosity is not set")
113
+
114
+ if args.additionalargumentsfile is not None:
115
+ default_additionalargumentsfile=args.additionalargumentsfile
116
+
117
+ if args.mainbranch is not None:
118
+ default_main_branch=args.mainbranch#main
119
+ GeneralUtilities.assert_not_null(default_main_branch,"mainbranch is not set")
120
+
121
+ if args.commonremotename is not None:
122
+ default_common_remote_name=args.commonremotename
123
+ GeneralUtilities.assert_not_null(default_common_remote_name,"commonremotename is not set")
124
+
125
+ repository=os.path.join(build_repo,"Submodules",default_product_name)
126
+ config:MergeToMainConfiguration=MergeToMainConfiguration(file,repository,default_product_name,default_merge_source_branch,default_loglevel,default_additionalargumentsfile,default_main_branch,default_common_remote_name,build_repo)
127
+ tFCPS_MergeToMain:TFCPS_MergeToMain=TFCPS_MergeToMain(config)
128
+ return tFCPS_MergeToMain