Module continuous_delivery_scripts.plugins.golang

Plugin for Golang projects.

Classes

class Go
Expand source code
class Go(BaseLanguage):
    """Specific actions for a Golang project."""

    def get_related_language(self) -> str:
        """Gets the related language."""
        return str(get_language_from_file_name(__file__))

    def get_version_tag(self, version: str) -> str:
        """Gets tag based on version."""
        cleansed_version = version.strip().lstrip("v")
        return f"v{cleansed_version}"

    def package_software(self, mode: CommitType, version: str) -> None:
        """No operation."""
        super().package_software(mode, version)
        _call_goreleaser_check(version)

    def release_package_to_repository(self, mode: CommitType, version: str) -> None:
        """No operation."""
        super().release_package_to_repository(mode, version)
        self._call_goreleaser_release(version)

    def check_credentials(self) -> None:
        """Checks any credentials."""
        super().check_credentials()
        configuration.get_value(ConfigurationVariable.GIT_TOKEN)

    def generate_code_documentation(self, output_directory: Path, module_to_document: str) -> None:
        """Generates the code documentation."""
        super().generate_code_documentation(output_directory, module_to_document)
        _call_doc2go(output_directory, module_to_document if module_to_document else "./...")

    def can_add_licence_headers(self) -> bool:
        """States that licence headers can be added."""
        return True

    def can_get_project_metadata(self) -> bool:
        """States whether project metadata can be retrieved."""
        return True

    def get_secret_registry_exclude_files(self) -> List[str]:
        """Gets additional detect-secrets exclude patterns for Go projects."""
        return [
            r".*go\.sum$",
            r"^\.circleci[\\/].*",
            r"^workflows/.*",
            (r"^\.github[\\/]workflows[\\/].*"),
        ]

    def get_current_spdx_project(self) -> Optional[SpdxProject]:
        """Gets current SPDX description."""
        return SpdxProject(GoProjectMetadataFetcher())

    def should_clean_before_packaging(self) -> bool:
        """States whether the repository must be cleaned before packaging happens."""
        return True

    def tag_release(self, git: GitWrapper, version: str, shortcuts: Dict[str, bool]) -> None:
        """Tags release commit."""
        super().tag_release(git, version, shortcuts)
        for go_tag in _determine_go_module_tag(self.get_version_tag(version)):
            git.create_tag(go_tag, message=f"Golang module release: {go_tag}")

    def _call_goreleaser_release(self, version: str) -> None:
        """Calls go releaser release to upload packages."""
        env = os.environ
        env[ENVVAR_GO_MOD] = GO_MOD_ON_VALUE
        _ensure_go_tool_installed(
            tool_name="syft",
            version_command=["syft", "--version"],
            install_command=_install_syft_command_list(),
            env=env,
        )
        _ensure_go_tool_installed(
            tool_name="goreleaser",
            version_command=["goreleaser", "--version"],
            install_command=_install_goreleaser_command_list(),
            env=env,
        )
        tag = self.get_version_tag(version)
        # The tag of the release must be retrieved
        # See https://github.com/goreleaser/goreleaser/discussions/1426
        logger.info(f"Checking out tag: {tag}.")
        with LocalProjectRepository() as git:
            git.configure_for_github()
            git.fetch()
            git.checkout(f"tags/{tag}")
        logger.info("Release package.")
        changelogPath = configuration.get_value(ConfigurationVariable.CHANGELOG_FILE_PATH)
        env[ENVVAR_GORELEASER_CUSTOMISED_TAG] = tag
        env[ENVVAR_GORELEASER_GIT_TOKEN] = configuration.get_value(ConfigurationVariable.GIT_TOKEN)
        check_call(
            _generate_goreleaser_release_command_list(changelogPath),
            cwd=ROOT_DIR,
            env=env,
        )

Specific actions for a Golang project.

Ancestors

Methods

def can_add_licence_headers(self) ‑> bool
Expand source code
def can_add_licence_headers(self) -> bool:
    """States that licence headers can be added."""
    return True

States that licence headers can be added.

def check_credentials(self) ‑> None
Expand source code
def check_credentials(self) -> None:
    """Checks any credentials."""
    super().check_credentials()
    configuration.get_value(ConfigurationVariable.GIT_TOKEN)

Checks any credentials.

def get_current_spdx_project(self) ‑> SpdxProject | None
Expand source code
def get_current_spdx_project(self) -> Optional[SpdxProject]:
    """Gets current SPDX description."""
    return SpdxProject(GoProjectMetadataFetcher())

Gets current SPDX description.

Expand source code
def get_related_language(self) -> str:
    """Gets the related language."""
    return str(get_language_from_file_name(__file__))

Gets the related language.

def get_secret_registry_exclude_files(self) ‑> List[str]
Expand source code
def get_secret_registry_exclude_files(self) -> List[str]:
    """Gets additional detect-secrets exclude patterns for Go projects."""
    return [
        r".*go\.sum$",
        r"^\.circleci[\\/].*",
        r"^workflows/.*",
        (r"^\.github[\\/]workflows[\\/].*"),
    ]

Gets additional detect-secrets exclude patterns for Go projects.

def get_version_tag(self, version: str) ‑> str
Expand source code
def get_version_tag(self, version: str) -> str:
    """Gets tag based on version."""
    cleansed_version = version.strip().lstrip("v")
    return f"v{cleansed_version}"

Gets tag based on version.

def package_software(self,
mode: CommitType,
version: str) ‑> None
Expand source code
def package_software(self, mode: CommitType, version: str) -> None:
    """No operation."""
    super().package_software(mode, version)
    _call_goreleaser_check(version)

No operation.

def release_package_to_repository(self,
mode: CommitType,
version: str) ‑> None
Expand source code
def release_package_to_repository(self, mode: CommitType, version: str) -> None:
    """No operation."""
    super().release_package_to_repository(mode, version)
    self._call_goreleaser_release(version)

No operation.

Inherited members

class GoProjectMetadataFetcher
Expand source code
class GoProjectMetadataFetcher(ProjectMetadataFetcher):
    """Retrieve Go dependency licences for the shared SPDX and compliance report."""

    def __init__(self) -> None:
        """Initialise with the configured project name."""
        super().__init__(str(configuration.get_value(ConfigurationVariable.PROJECT_NAME)))

    def fetch_project_metadata(self) -> ProjectMetadata:
        """Collect module dependencies using go-licenses without replacing shared policy checks."""
        module_directories = _go_licence_module_directories()
        env = os.environ.copy()
        env[ENVVAR_GO_MOD] = GO_MOD_ON_VALUE
        executable = _ensure_go_tool_installed(
            tool_name="go-licenses",
            version_command=["go-licenses", "report", "--help"],
            install_command=_install_go_licenses_command_list(),
            env=env,
        )
        project = ProjectMetadata(self._package_name)
        project.project_metadata = PackageMetadata.from_fields(
            name=self._package_name,
            licence=str(configuration.get_value(ConfigurationVariable.FILE_LICENCE_IDENTIFIER)),
            licence_source=LicenceSource.CONFIGURATION,
        )
        dependencies: Dict[str, PackageMetadata] = {}
        modules = [(module_dir, _go_module_name(module_dir, env)) for module_dir in module_directories]
        with TemporaryDirectory() as temporary_dir:
            template_path = Path(temporary_dir) / "go-licenses.tpl"
            template_path.write_text(GO_LICENSES_TEMPLATE, encoding="utf8")
            with _stage_root_licence_files_for_modules(module_directories):
                for module_dir, _ in modules:
                    output = _run_go_licenses_report(executable, module_dir, template_path, env)
                    for package in _parse_go_licences(output):
                        if any(package.name == name or package.name.startswith(f"{name}/") for _, name in modules):
                            continue
                        existing = dependencies.get(package.name)
                        if existing and (existing.version, existing.licence) != (package.version, package.licence):
                            candidates = existing.licence_candidates or [existing.licence]
                            dependencies[package.name] = PackageMetadata.from_fields(
                                name=package.name,
                                version=UNKNOWN if existing.version != package.version else package.version,
                                licence=UNKNOWN,
                                licence_source=LicenceSource.UNKNOWN,
                                licence_candidates=sorted(set(candidates + [package.licence])),
                                licence_evidence=existing.licence_evidence + package.licence_evidence,
                            )
                        elif existing is None:
                            dependencies[package.name] = package
        for dependency in dependencies.values():
            project.add_dependency_metadata(dependency)
        return project

Retrieve Go dependency licences for the shared SPDX and compliance report.

Initialise with the configured project name.

Ancestors

Methods

def fetch_project_metadata(self) ‑> ProjectMetadata
Expand source code
def fetch_project_metadata(self) -> ProjectMetadata:
    """Collect module dependencies using go-licenses without replacing shared policy checks."""
    module_directories = _go_licence_module_directories()
    env = os.environ.copy()
    env[ENVVAR_GO_MOD] = GO_MOD_ON_VALUE
    executable = _ensure_go_tool_installed(
        tool_name="go-licenses",
        version_command=["go-licenses", "report", "--help"],
        install_command=_install_go_licenses_command_list(),
        env=env,
    )
    project = ProjectMetadata(self._package_name)
    project.project_metadata = PackageMetadata.from_fields(
        name=self._package_name,
        licence=str(configuration.get_value(ConfigurationVariable.FILE_LICENCE_IDENTIFIER)),
        licence_source=LicenceSource.CONFIGURATION,
    )
    dependencies: Dict[str, PackageMetadata] = {}
    modules = [(module_dir, _go_module_name(module_dir, env)) for module_dir in module_directories]
    with TemporaryDirectory() as temporary_dir:
        template_path = Path(temporary_dir) / "go-licenses.tpl"
        template_path.write_text(GO_LICENSES_TEMPLATE, encoding="utf8")
        with _stage_root_licence_files_for_modules(module_directories):
            for module_dir, _ in modules:
                output = _run_go_licenses_report(executable, module_dir, template_path, env)
                for package in _parse_go_licences(output):
                    if any(package.name == name or package.name.startswith(f"{name}/") for _, name in modules):
                        continue
                    existing = dependencies.get(package.name)
                    if existing and (existing.version, existing.licence) != (package.version, package.licence):
                        candidates = existing.licence_candidates or [existing.licence]
                        dependencies[package.name] = PackageMetadata.from_fields(
                            name=package.name,
                            version=UNKNOWN if existing.version != package.version else package.version,
                            licence=UNKNOWN,
                            licence_source=LicenceSource.UNKNOWN,
                            licence_candidates=sorted(set(candidates + [package.licence])),
                            licence_evidence=existing.licence_evidence + package.licence_evidence,
                        )
                    elif existing is None:
                        dependencies[package.name] = package
    for dependency in dependencies.values():
        project.add_dependency_metadata(dependency)
    return project

Collect module dependencies using go-licenses without replacing shared policy checks.

Inherited members