Merge branch 'pylint-fixes' into 'ddd-intro'
Pylint fixes See merge request domaindrivenarchitecture/dda-devops-build!11
This commit is contained in:
commit
7c4933c6d9
8 changed files with 67 additions and 72 deletions
|
@ -27,7 +27,7 @@ pylint:
|
||||||
stage: lint&test
|
stage: lint&test
|
||||||
script:
|
script:
|
||||||
- pip install -r dev_requirements.txt
|
- pip install -r dev_requirements.txt
|
||||||
- pylint -d C0301,W0614,C0114,C0115,C0116,similarities,W0702,W0702,R0913,R0902,R0914,R1732 src/main/python/ddadevops/
|
- pylint -d W0511,R0903,C0301,W0614,C0114,C0115,C0116,similarities,W1203,W0719,W0702,W0702,R0913,R0902,R0914,R1732 src/main/python/ddadevops/
|
||||||
|
|
||||||
pytest:
|
pytest:
|
||||||
stage: lint&test
|
stage: lint&test
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from subprocess import run, CalledProcessError
|
|
||||||
import deprecation
|
import deprecation
|
||||||
from .domain import Devops
|
from .domain import Devops
|
||||||
from .infrastructure import ProjectRepository, FileApi
|
from .infrastructure import ProjectRepository, FileApi
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import deprecation
|
|
||||||
import logging
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
import logging
|
||||||
|
import deprecation
|
||||||
|
|
||||||
def filter_none(list_to_filter):
|
def filter_none(list_to_filter):
|
||||||
return [x for x in list_to_filter if x is not None]
|
return [x for x in list_to_filter if x is not None]
|
||||||
|
@ -10,8 +10,8 @@ class Validateable:
|
||||||
value = self.__dict__[field_name]
|
value = self.__dict__[field_name]
|
||||||
if value is None or value == "":
|
if value is None or value == "":
|
||||||
return [f"Field '{field_name}' must not be empty."]
|
return [f"Field '{field_name}' must not be empty."]
|
||||||
else:
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def validate(self) -> List[str]:
|
def validate(self) -> List[str]:
|
||||||
return []
|
return []
|
||||||
|
@ -24,7 +24,6 @@ class Validateable:
|
||||||
issues = '\n'.join(self.validate())
|
issues = '\n'.join(self.validate())
|
||||||
raise ValueError(f"Invalid Validateable: {issues}")
|
raise ValueError(f"Invalid Validateable: {issues}")
|
||||||
|
|
||||||
|
|
||||||
class DnsRecord(Validateable):
|
class DnsRecord(Validateable):
|
||||||
def __init__(self, fqdn, ipv4=None, ipv6=None):
|
def __init__(self, fqdn, ipv4=None, ipv6=None):
|
||||||
self.fqdn = fqdn
|
self.fqdn = fqdn
|
||||||
|
@ -46,7 +45,7 @@ class Devops(Validateable):
|
||||||
self.stage = stage
|
self.stage = stage
|
||||||
self.name = name
|
self.name = name
|
||||||
self.project_root_path = project_root_path
|
self.project_root_path = project_root_path
|
||||||
logging.warn(f"Set project root in DevOps {self.project_root_path}")
|
logging.warning(f"Set project root in DevOps {self.project_root_path}")
|
||||||
self.module = module
|
self.module = module
|
||||||
if not name:
|
if not name:
|
||||||
self.name = module
|
self.name = module
|
||||||
|
@ -56,22 +55,23 @@ class Devops(Validateable):
|
||||||
|
|
||||||
@deprecation.deprecated(deprecated_in="3.2")
|
@deprecation.deprecated(deprecated_in="3.2")
|
||||||
# use .name instead
|
# use .name instead
|
||||||
|
#pylint: disable=method-hidden
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def build_path(self):
|
def build_path(self):
|
||||||
path = [self.project_root_path, self.build_dir_name, self.name, self.module]
|
path = [self.project_root_path, self.build_dir_name, self.name, self.module]
|
||||||
logging.warn(f"Set project build_path in Devops {path}")
|
logging.warning(f"Set project build_path in Devops {path}")
|
||||||
return "/".join(filter_none(path))
|
return "/".join(filter_none(path))
|
||||||
|
|
||||||
def __put__(self, key, value):
|
def __put__(self, key, value):
|
||||||
self.stack[key] = value
|
self.stack[key] = value
|
||||||
|
|
||||||
def __get__(self, key):
|
def __get(self, key):
|
||||||
return self.stack[key]
|
return self.stack[key]
|
||||||
|
|
||||||
def __get_keys__(self, keys):
|
def __get_keys__(self, keys):
|
||||||
result = {}
|
result = {}
|
||||||
for key in keys:
|
for key in keys:
|
||||||
result[key] = self.__get__(key)
|
result[key] = self.__get(key)
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from typing import Optional
|
|
||||||
from .common import (
|
from .common import (
|
||||||
filter_none,
|
filter_none,
|
||||||
Validateable,
|
Validateable,
|
||||||
|
@ -11,7 +10,6 @@ class Image(Validateable):
|
||||||
dockerhub_user,
|
dockerhub_user,
|
||||||
dockerhub_password,
|
dockerhub_password,
|
||||||
devops: Devops,
|
devops: Devops,
|
||||||
build_dir_name="target",
|
|
||||||
use_package_common_files=True,
|
use_package_common_files=True,
|
||||||
build_commons_path=None,
|
build_commons_path=None,
|
||||||
docker_build_commons_dir_name="docker",
|
docker_build_commons_dir_name="docker",
|
||||||
|
@ -26,5 +24,5 @@ class Image(Validateable):
|
||||||
self.devops = devops
|
self.devops = devops
|
||||||
|
|
||||||
def docker_build_commons_path(self):
|
def docker_build_commons_path(self):
|
||||||
list = [self.build_commons_path, self.docker_build_commons_dir_name]
|
commons_path = [self.build_commons_path, self.docker_build_commons_dir_name]
|
||||||
return "/".join(filter_none(list)) + "/"
|
return "/".join(filter_none(commons_path)) + "/"
|
||||||
|
|
|
@ -2,7 +2,6 @@ from enum import Enum
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from .common import (
|
from .common import (
|
||||||
filter_none,
|
|
||||||
Validateable,
|
Validateable,
|
||||||
Devops,
|
Devops,
|
||||||
)
|
)
|
||||||
|
@ -19,8 +18,8 @@ class EnvironmentKeys(Enum):
|
||||||
|
|
||||||
class Version():
|
class Version():
|
||||||
|
|
||||||
def __init__(self, id: Path, version_list: list):
|
def __init__(self, path: Path, version_list: list):
|
||||||
self.id = id
|
self.path = path
|
||||||
self.version_list = version_list
|
self.version_list = version_list
|
||||||
self.version_string: Optional[str | None] = None
|
self.version_string: Optional[str | None] = None
|
||||||
self.is_snapshot: Optional[bool | None] = None
|
self.is_snapshot: Optional[bool | None] = None
|
||||||
|
@ -43,7 +42,7 @@ class Version():
|
||||||
self.version_list[ReleaseType.MINOR.value] = 0
|
self.version_list[ReleaseType.MINOR.value] = 0
|
||||||
self.version_list[ReleaseType.MAJOR.value] += 1
|
self.version_list[ReleaseType.MAJOR.value] += 1
|
||||||
case None:
|
case None:
|
||||||
raise Exception("Release Type was not set!")
|
raise RuntimeError("Release Type was not set!")
|
||||||
|
|
||||||
def get_version_string(self) -> str:
|
def get_version_string(self) -> str:
|
||||||
self.version_string = ".".join([str(x) for x in self.version_list])
|
self.version_string = ".".join([str(x) for x in self.version_list])
|
||||||
|
@ -52,13 +51,13 @@ class Version():
|
||||||
return self.version_string
|
return self.version_string
|
||||||
|
|
||||||
def create_release_version(self, release_type: ReleaseType | None):
|
def create_release_version(self, release_type: ReleaseType | None):
|
||||||
release_version = Version(self.id, self.version_list.copy())
|
release_version = Version(self.path, self.version_list.copy())
|
||||||
release_version.is_snapshot = self.is_snapshot
|
release_version.is_snapshot = self.is_snapshot
|
||||||
release_version.increment(release_type)
|
release_version.increment(release_type)
|
||||||
return release_version
|
return release_version
|
||||||
|
|
||||||
def create_bump_version(self):
|
def create_bump_version(self):
|
||||||
bump_version = Version(self.id, self.version_list.copy())
|
bump_version = Version(self.path, self.version_list.copy())
|
||||||
bump_version.is_snapshot = self.is_snapshot
|
bump_version.is_snapshot = self.is_snapshot
|
||||||
bump_version.increment(ReleaseType.BUMP)
|
bump_version.increment(ReleaseType.BUMP)
|
||||||
return bump_version
|
return bump_version
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import subprocess as sub
|
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -26,7 +25,7 @@ class FileHandler(ABC):
|
||||||
case '.py':
|
case '.py':
|
||||||
file_handler = PythonFileHandler()
|
file_handler = PythonFileHandler()
|
||||||
case _:
|
case _:
|
||||||
raise Exception(
|
raise RuntimeError(
|
||||||
f'The file type "{config_file_type}" is not implemented')
|
f'The file type "{config_file_type}" is not implemented')
|
||||||
# TODO: Attribute is only set in classmethod. Should this be initialized outside of this class?
|
# TODO: Attribute is only set in classmethod. Should this be initialized outside of this class?
|
||||||
file_handler.config_file_path = file_path
|
file_handler.config_file_path = file_path
|
||||||
|
@ -47,7 +46,7 @@ class JsonFileHandler(FileHandler):
|
||||||
def parse(self) -> tuple[list[int], bool]:
|
def parse(self) -> tuple[list[int], bool]:
|
||||||
if self.config_file_path is None:
|
if self.config_file_path is None:
|
||||||
raise ValueError("No file name given.")
|
raise ValueError("No file name given.")
|
||||||
with open(self.config_file_path, 'r') as json_file:
|
with open(self.config_file_path, 'r', encoding='utf-8') as json_file:
|
||||||
json_version = json.load(json_file)['version']
|
json_version = json.load(json_file)['version']
|
||||||
is_snapshot = False
|
is_snapshot = False
|
||||||
if '-SNAPSHOT' in json_version:
|
if '-SNAPSHOT' in json_version:
|
||||||
|
@ -57,7 +56,7 @@ class JsonFileHandler(FileHandler):
|
||||||
return version, is_snapshot
|
return version, is_snapshot
|
||||||
|
|
||||||
def write(self, version_string):
|
def write(self, version_string):
|
||||||
with open(self.config_file_path, 'r+') as json_file:
|
with open(self.config_file_path, 'r+', encoding='utf-8') as json_file:
|
||||||
json_data = json.load(json_file)
|
json_data = json.load(json_file)
|
||||||
json_data['version'] = version_string
|
json_data['version'] = version_string
|
||||||
json_file.seek(0)
|
json_file.seek(0)
|
||||||
|
@ -70,7 +69,7 @@ class GradleFileHandler(FileHandler):
|
||||||
def parse(self) -> tuple[list[int], bool]:
|
def parse(self) -> tuple[list[int], bool]:
|
||||||
if self.config_file_path is None:
|
if self.config_file_path is None:
|
||||||
raise ValueError("No file name given.")
|
raise ValueError("No file name given.")
|
||||||
with open(self.config_file_path, 'r') as gradle_file:
|
with open(self.config_file_path, 'r', encoding='utf-8') as gradle_file:
|
||||||
contents = gradle_file.read()
|
contents = gradle_file.read()
|
||||||
version_line = re.search("\nversion = .*", contents)
|
version_line = re.search("\nversion = .*", contents)
|
||||||
exception = Exception("Version not found in gradle file")
|
exception = Exception("Version not found in gradle file")
|
||||||
|
@ -94,7 +93,7 @@ class GradleFileHandler(FileHandler):
|
||||||
return version, is_snapshot
|
return version, is_snapshot
|
||||||
|
|
||||||
def write(self, version_string):
|
def write(self, version_string):
|
||||||
with open(self.config_file_path, 'r+') as gradle_file:
|
with open(self.config_file_path, 'r+', encoding='utf-8') as gradle_file:
|
||||||
contents = gradle_file.read()
|
contents = gradle_file.read()
|
||||||
version_substitute = re.sub(
|
version_substitute = re.sub(
|
||||||
'\nversion = "[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?"', f'\nversion = "{version_string}"', contents)
|
'\nversion = "[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?"', f'\nversion = "{version_string}"', contents)
|
||||||
|
@ -108,7 +107,7 @@ class PythonFileHandler(FileHandler):
|
||||||
def parse(self) -> tuple[list[int], bool]:
|
def parse(self) -> tuple[list[int], bool]:
|
||||||
if self.config_file_path is None:
|
if self.config_file_path is None:
|
||||||
raise ValueError("No file name given.")
|
raise ValueError("No file name given.")
|
||||||
with open(self.config_file_path, 'r') as python_file:
|
with open(self.config_file_path, 'r', encoding='utf-8') as python_file:
|
||||||
contents = python_file.read()
|
contents = python_file.read()
|
||||||
version_line = re.search("\nversion = .*\n", contents)
|
version_line = re.search("\nversion = .*\n", contents)
|
||||||
exception = Exception("Version not found in gradle file")
|
exception = Exception("Version not found in gradle file")
|
||||||
|
@ -132,7 +131,7 @@ class PythonFileHandler(FileHandler):
|
||||||
return version, is_snapshot
|
return version, is_snapshot
|
||||||
|
|
||||||
def write(self, version_string):
|
def write(self, version_string):
|
||||||
with open(self.config_file_path, 'r+') as python_file:
|
with open(self.config_file_path, 'r+', encoding='utf-8') as python_file:
|
||||||
contents = python_file.read()
|
contents = python_file.read()
|
||||||
version_substitute = re.sub(
|
version_substitute = re.sub(
|
||||||
'\nversion = "[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?"', f'\nversion = "{version_string}"', contents)
|
'\nversion = "[0-9]*\\.[0-9]*\\.[0-9]*(-SNAPSHOT)?"', f'\nversion = "{version_string}"', contents)
|
||||||
|
@ -146,7 +145,7 @@ class ClojureFileHandler(FileHandler):
|
||||||
def parse(self) -> tuple[list[int], bool]:
|
def parse(self) -> tuple[list[int], bool]:
|
||||||
if self.config_file_path is None:
|
if self.config_file_path is None:
|
||||||
raise ValueError("No file name given.")
|
raise ValueError("No file name given.")
|
||||||
with open(self.config_file_path, 'r') as clj_file:
|
with open(self.config_file_path, 'r', encoding='utf-8') as clj_file:
|
||||||
contents = clj_file.read()
|
contents = clj_file.read()
|
||||||
version_line = re.search("^\\(defproject .*\n", contents)
|
version_line = re.search("^\\(defproject .*\n", contents)
|
||||||
exception = Exception("Version not found in clj file")
|
exception = Exception("Version not found in clj file")
|
||||||
|
@ -170,7 +169,7 @@ class ClojureFileHandler(FileHandler):
|
||||||
return version, is_snapshot
|
return version, is_snapshot
|
||||||
|
|
||||||
def write(self, version_string):
|
def write(self, version_string):
|
||||||
with open(self.config_file_path, 'r+') as clj_file:
|
with open(self.config_file_path, 'r+', encoding='utf-8') as clj_file:
|
||||||
clj_first = clj_file.readline()
|
clj_first = clj_file.readline()
|
||||||
clj_rest = clj_file.read()
|
clj_rest = clj_file.read()
|
||||||
version_substitute = re.sub(
|
version_substitute = re.sub(
|
||||||
|
@ -186,6 +185,7 @@ class GitApi():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.execution_api = ExecutionApi()
|
self.execution_api = ExecutionApi()
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name
|
||||||
def get_latest_n_commits(self, n: int):
|
def get_latest_n_commits(self, n: int):
|
||||||
return self.execution_api.execute(
|
return self.execution_api.execute(
|
||||||
f'git log --oneline --format="%s %b" -n {n}')
|
f'git log --oneline --format="%s %b" -n {n}')
|
||||||
|
@ -204,11 +204,10 @@ class GitApi():
|
||||||
return self.execution_api.execute('git describe --tags --abbrev=0')
|
return self.execution_api.execute('git describe --tags --abbrev=0')
|
||||||
|
|
||||||
def get_current_branch(self):
|
def get_current_branch(self):
|
||||||
self.execution_api.execute('git branch --show-current')
|
return ''.join(self.execution_api.execute('git branch --show-current')).rstrip()
|
||||||
return ''.join(self.execution_api.stdout).rstrip()
|
|
||||||
|
|
||||||
def init(self, default_branch: str = "main"):
|
def init(self, default_branch: str = "main"):
|
||||||
self.execution_api.execute(f'git init')
|
self.execution_api.execute('git init')
|
||||||
self.execution_api.execute(f'git checkout -b {default_branch}')
|
self.execution_api.execute(f'git checkout -b {default_branch}')
|
||||||
|
|
||||||
def set_user_config(self, email: str, name: str):
|
def set_user_config(self, email: str, name: str):
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
from typing import Optional
|
|
||||||
from src.main.python.ddadevops.domain import (
|
from src.main.python.ddadevops.domain import (
|
||||||
ReleaseContext,
|
ReleaseContext,
|
||||||
Version,
|
Version,
|
||||||
ReleaseType,
|
ReleaseType,
|
||||||
EnvironmentKeys,
|
EnvironmentKeys,
|
||||||
)
|
)
|
||||||
from src.main.python.ddadevops.infrastructure.release_mixin import (
|
from src.main.python.ddadevops.infrastructure.release_mixin.infrastructure_api import (
|
||||||
FileHandler,
|
FileHandler,
|
||||||
GitApi,
|
GitApi,
|
||||||
EnvironmentApi,
|
EnvironmentApi,
|
||||||
|
@ -23,9 +23,8 @@ class VersionRepository:
|
||||||
|
|
||||||
def write_file(self, version_string):
|
def write_file(self, version_string):
|
||||||
if self.file_handler is None:
|
if self.file_handler is None:
|
||||||
raise Exception("Version was not created by load_file method.")
|
raise RuntimeError("Version was not created by load_file method.")
|
||||||
else:
|
self.file_handler.write(version_string)
|
||||||
self.file_handler.write(version_string)
|
|
||||||
|
|
||||||
def parse_file(self):
|
def parse_file(self):
|
||||||
version_list, is_snapshot = self.file_handler.parse()
|
version_list, is_snapshot = self.file_handler.parse()
|
||||||
|
@ -53,29 +52,30 @@ class ReleaseTypeRepository:
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_git(cls, git_api: GitApi):
|
def from_git(cls, git_api: GitApi):
|
||||||
releaseTypeRepo = cls(git_api=git_api)
|
release_type_repo = cls(git_api=git_api)
|
||||||
releaseTypeRepo.get_from_git = True
|
release_type_repo.get_from_git = True
|
||||||
return releaseTypeRepo
|
return release_type_repo
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_environment(cls, environment_api: EnvironmentApi):
|
def from_environment(cls, environment_api: EnvironmentApi):
|
||||||
releaseTypeRepo = cls(environment_api=environment_api)
|
release_type_repo = cls(environment_api=environment_api)
|
||||||
releaseTypeRepo.get_from_env = True
|
release_type_repo.get_from_env = True
|
||||||
return releaseTypeRepo
|
return release_type_repo
|
||||||
|
|
||||||
def __get_release_type_git(self) -> ReleaseType | None:
|
def __get_release_type_git(self) -> ReleaseType | None:
|
||||||
latest_commit = self.git_api.get_latest_commit()
|
latest_commit = self.git_api.get_latest_commit()
|
||||||
|
|
||||||
if ReleaseType.MAJOR.name in latest_commit.upper():
|
match latest_commit.upper():
|
||||||
return ReleaseType.MAJOR
|
case ReleaseType.MAJOR.name:
|
||||||
elif ReleaseType.MINOR.name in latest_commit.upper():
|
return ReleaseType.MAJOR
|
||||||
return ReleaseType.MINOR
|
case ReleaseType.MINOR.name:
|
||||||
elif ReleaseType.PATCH.name in latest_commit.upper():
|
return ReleaseType.MINOR
|
||||||
return ReleaseType.PATCH
|
case ReleaseType.PATCH.name:
|
||||||
elif ReleaseType.SNAPSHOT.name in latest_commit.upper():
|
return ReleaseType.PATCH
|
||||||
return ReleaseType.SNAPSHOT
|
case ReleaseType.SNAPSHOT.name:
|
||||||
else:
|
return ReleaseType.SNAPSHOT
|
||||||
return None
|
case _:
|
||||||
|
return None
|
||||||
|
|
||||||
def __get_release_type_environment(self) -> ReleaseType | None:
|
def __get_release_type_environment(self) -> ReleaseType | None:
|
||||||
release_name = self.environment_api.get(
|
release_name = self.environment_api.get(
|
||||||
|
@ -86,24 +86,25 @@ class ReleaseTypeRepository:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Release Name not found. Is the Environment correctly configured?"
|
"Release Name not found. Is the Environment correctly configured?"
|
||||||
)
|
)
|
||||||
elif ReleaseType.MAJOR.name in release_name.upper():
|
|
||||||
return ReleaseType.MAJOR
|
match release_name.upper():
|
||||||
elif ReleaseType.MINOR.name in release_name.upper():
|
case ReleaseType.MAJOR.name:
|
||||||
return ReleaseType.MINOR
|
return ReleaseType.MAJOR
|
||||||
elif ReleaseType.PATCH.name in release_name.upper():
|
case ReleaseType.MINOR.name:
|
||||||
return ReleaseType.PATCH
|
return ReleaseType.MINOR
|
||||||
elif ReleaseType.SNAPSHOT.name in release_name.upper():
|
case ReleaseType.PATCH.name:
|
||||||
return ReleaseType.SNAPSHOT
|
return ReleaseType.PATCH
|
||||||
else:
|
case ReleaseType.SNAPSHOT.name:
|
||||||
return None
|
return ReleaseType.SNAPSHOT
|
||||||
|
case _:
|
||||||
|
return None
|
||||||
|
|
||||||
def get_release_type(self) -> ReleaseType | None:
|
def get_release_type(self) -> ReleaseType | None:
|
||||||
if self.get_from_git:
|
if self.get_from_git:
|
||||||
return self.__get_release_type_git()
|
return self.__get_release_type_git()
|
||||||
elif self.get_from_env:
|
if self.get_from_env:
|
||||||
return self.__get_release_type_environment()
|
return self.__get_release_type_environment()
|
||||||
else:
|
raise ValueError("No valid api passed to ReleaseTypeRepository")
|
||||||
raise ValueError("No valid api passed to ReleaseTypeRepository")
|
|
||||||
|
|
||||||
|
|
||||||
class ReleaseContextRepository:
|
class ReleaseContextRepository:
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from typing import Optional
|
|
||||||
from pybuilder.core import Project
|
from pybuilder.core import Project
|
||||||
from src.main.python.ddadevops.devops_build import DevopsBuild
|
from src.main.python.ddadevops.devops_build import DevopsBuild
|
||||||
from src.main.python.ddadevops.infrastructure.release_mixin import ReleaseContextRepository, ReleaseTypeRepository, VersionRepository, GitApi, EnvironmentApi
|
from src.main.python.ddadevops.infrastructure.release_mixin import ReleaseContextRepository, ReleaseTypeRepository, VersionRepository, GitApi, EnvironmentApi
|
||||||
|
|
Loading…
Reference in a new issue