diff --git a/Dockerfile b/Dockerfile index a8dd85b0d..2b92f1c3b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,6 @@ FROM alpine:3.20.3 LABEL maintainer="olivier.korach@gmail.com" +ENV IN_DOCKER="Yes" ARG USERNAME=sonar ARG USER_UID=1000 @@ -33,7 +34,7 @@ RUN pip install --upgrade pip \ && pip install --no-cache-dir -r requirements.txt \ && pip install --no-cache-dir --upgrade pip setuptools wheel \ && python setup.py bdist_wheel \ -&& pip install dist/*-py3-*.whl --force-reinstall +&& pip install dist/sonar_tools-*-py3-*.whl --force-reinstall USER ${USERNAME} WORKDIR /home/${USERNAME} diff --git a/cli/migration.py b/cli/migration.py index bc9e2acea..a017b351b 100644 --- a/cli/migration.py +++ b/cli/migration.py @@ -22,8 +22,6 @@ Exports SonarQube platform configuration as JSON """ import sys -import json -import yaml from cli import options from sonar import exceptions, errcodes, utilities @@ -84,7 +82,7 @@ def __parse_args(desc): f"By default the export will show the value as '{utilities.DEFAULT}' " "and the setting will not be imported at import time", ) - args = options.parse_and_check(parser=parser, logger_name="sonar-migration") + args = options.parse_and_check(parser=parser, logger_name="sonar-migration", is_migration=True) return args diff --git a/cli/options.py b/cli/options.py index 09ece9cec..7e2e57c4c 100644 --- a/cli/options.py +++ b/cli/options.py @@ -176,7 +176,7 @@ def __check_file_writeable(file: str) -> None: os.remove(file) -def parse_and_check(parser: ArgumentParser, logger_name: str = None, verify_token: bool = True) -> ArgumentParser: +def parse_and_check(parser: ArgumentParser, logger_name: str = None, verify_token: bool = True, is_migration: bool = False) -> ArgumentParser: """Parses arguments, applies default settings and perform common environment checks""" try: args = parser.parse_args() @@ -187,7 +187,12 @@ def parse_and_check(parser: ArgumentParser, logger_name: str = None, verify_toke log.set_logger(filename=kwargs[LOGFILE], logger_name=logger_name) log.set_debug_level(kwargs[VERBOSE]) del kwargs[VERBOSE] - log.info("sonar-tools version %s", version.PACKAGE_VERSION) + if is_migration: + log.info("sonar-migration version %s", version.MIGRATION_TOOL_VERSION) + else: + log.info("sonar-tools version %s", version.PACKAGE_VERSION) + if os.getenv("IN_DOCKER", "No") == "Yes": + kwargs[URL] = kwargs[URL].replace("http://localhost", "http://host.docker.internal") if log.get_level() == log.DEBUG: sanitized_args = kwargs.copy() sanitized_args[TOKEN] = utilities.redacted_token(sanitized_args[TOKEN]) diff --git a/deploy-migration.sh b/deploy-migration.sh index bc8fc299c..28ae82f4b 100755 --- a/deploy-migration.sh +++ b/deploy-migration.sh @@ -48,7 +48,7 @@ python3 setup_migration.py bdist_wheel pip install --upgrade --force-reinstall dist/sonar_migration-*-py3-*.whl if [ "$build_image" == "1" ]; then - docker build -t sonar-migration:latest . + docker build -t sonar-migration:latest -f migration.Dockerfile . fi if [ "$build_docs" == "1" ]; then diff --git a/migration.Dockerfile b/migration.Dockerfile new file mode 100644 index 000000000..35cb679c8 --- /dev/null +++ b/migration.Dockerfile @@ -0,0 +1,42 @@ +FROM alpine:3.20.3 +LABEL maintainer="olivier.korach@gmail.com" +ENV IN_DOCKER="Yes" + +ARG USERNAME=sonar +ARG USER_UID=1000 +ARG GROUPNAME=sonar + +# Create the user +RUN addgroup -S ${GROUPNAME} && adduser -u ${USER_UID} -S ${USERNAME} -G ${GROUPNAME} + +# Install python/pip +ENV PYTHONUNBUFFERED=1 +RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python + +# create a virtual environment and add it to PATH so that it is +# applied for all future RUN and CMD calls +ENV VIRTUAL_ENV=/opt/venv +RUN python3 -m venv ${VIRTUAL_ENV} +ENV PATH="${VIRTUAL_ENV}/bin:${PATH}" + +WORKDIR /opt/sonar-migration + +COPY ./sonar sonar +COPY ./requirements.txt . +COPY ./cli cli +COPY ./setup_migration.py . +COPY ./sonar_migration . +COPY ./README.md . +COPY ./LICENSE . +COPY ./sonar/audit sonar/audit + +RUN pip install --upgrade pip \ +&& pip install --no-cache-dir -r requirements.txt \ +&& pip install --no-cache-dir --upgrade pip setuptools wheel \ +&& python setup_migration.py bdist_wheel \ +&& pip install dist/sonar_migration-py3-*.whl --force-reinstall + +USER ${USERNAME} +WORKDIR /home/${USERNAME} + +ENTRYPOINT ["sonar-migration"] diff --git a/setup_migration.py b/setup_migration.py index 9a69dafef..25b12b7c1 100644 --- a/setup_migration.py +++ b/setup_migration.py @@ -26,16 +26,15 @@ import setuptools from sonar import version - with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read() setuptools.setup( name="sonar-migration", - version=version.PACKAGE_VERSION, + version=version.MIGRATION_TOOL_VERSION, scripts=["sonar_migration"], author="Olivier Korach", author_email="olivier.korach@gmail.com", - description="A collection of utility scripts for SonarQube and SonarCloud", + description="A SonarQube collection tool to use in the context of SonarQube to SonarCloud migration", long_description=long_description, long_description_content_type="text/markdown", url="https://github.com/okorach/sonar-tools", diff --git a/sonar/issues.py b/sonar/issues.py index 637caa15d..fe50e4fb1 100644 --- a/sonar/issues.py +++ b/sonar/issues.py @@ -34,7 +34,7 @@ import sonar.platform as pf from sonar.util.types import ApiParams, ApiPayload, ObjectJsonRepr, ConfigSettings -from sonar import users, syncer, sqobject, findings, changelog, projects +from sonar import users, sqobject, findings, changelog, projects import sonar.utilities as util API_SET_TAGS = "issues/set_tags" @@ -430,6 +430,8 @@ def accept(self) -> bool: return self.do_transition("accept") def __apply_event(self, event: str, settings: ConfigSettings) -> bool: + from sonar import syncer + log.debug("Applying event %s", str(event)) # origin = f"originally by *{event['userName']}* on original branch" (event_type, data) = event.changelog_type() @@ -491,6 +493,8 @@ def apply_changelog(self, source_issue: Issue, settings: ConfigSettings) -> bool """ :meta private: """ + from sonar import syncer + events = source_issue.changelog() if events is None or not events: log.debug("Sibling %s has no changelog, no action taken", source_issue.key) diff --git a/sonar/projects.py b/sonar/projects.py index d8730cc28..69be5d74b 100644 --- a/sonar/projects.py +++ b/sonar/projects.py @@ -42,7 +42,7 @@ from sonar.util import types from sonar import exceptions, errcodes -from sonar import sqobject, components, qualitygates, qualityprofiles, rules, tasks, settings, webhooks, devops, syncer +from sonar import sqobject, components, qualitygates, qualityprofiles, tasks, settings, webhooks, devops import sonar.permissions.permissions as perms from sonar import pull_requests, branches import sonar.utilities as util @@ -799,6 +799,8 @@ def count_third_party_issues(self, filters: dict[str, str] = None) -> dict[str, def __sync_community(self, another_project: object, sync_settings: types.ConfigSettings) -> tuple[list[dict[str, str]], dict[str, int]]: """Syncs 2 projects findings on a community edition""" + from sonar import syncer + report, counters = [], {} log.info("Syncing %s and %s issues", str(self), str(another_project)) (report, counters) = syncer.sync_lists( @@ -993,7 +995,7 @@ def export(self, export_settings: types.ConfigSettings, settings_list: dict[str, "taskHistory": [t._json for t in self.task_history()], } json_data["thirdPartyIssues"] = self.count_third_party_issues() - log.info("%s has %d 3rd party issues", str(self), sum(v for v in json_data["thirdPartyIssues"].values())) + log.debug("%s has %d 3rd party issues", str(self), sum(v for v in json_data["thirdPartyIssues"].values())) settings_dict = settings.get_bulk(endpoint=self.endpoint, component=self, settings_list=settings_list, include_not_set=False) # json_data.update({s.to_json() for s in settings_dict.values() if include_inherited or not s.inherited}) diff --git a/sonar/version.py b/sonar/version.py index c5c6df432..9ae637341 100644 --- a/sonar/version.py +++ b/sonar/version.py @@ -25,3 +25,4 @@ """ PACKAGE_VERSION = "3.4" +MIGRATION_TOOL_VERSION = "0.1"