Commit c0396efe authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

ci(ruff): add Ruff

parent 8b6a51d1
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
include:
  # $TBC_NAMESPACE is a group variable; can be globally overridden
  # Docker template
  - component: "gitlab.com/$TBC_NAMESPACE/docker/gitlab-ci-docker@5.9"
  - component: "gitlab.com/$TBC_NAMESPACE/docker/gitlab-ci-docker@5"
    inputs:
      healthcheck-disabled: true
      sbom-disabled: true
@@ -9,9 +9,10 @@ include:
      prod-publish-strategy: "auto"
      release-extra-tags: "latest \\g<major>.\\g<minor>\\g<build> \\g<major>\\g<build>"
  # Python template
  - component: "gitlab.com/$TBC_NAMESPACE/python/gitlab-ci-python@6.7"
  - component: "gitlab.com/$TBC_NAMESPACE/python/gitlab-ci-python@6"
    inputs:
      image: "registry.hub.docker.com/library/python:3.12"
      ruff-enabled: true
      sbom-disabled: true
      package-enabled: true
      release-enabled: true
+73 −76
Original line number Diff line number Diff line
import argparse
import base64
from http.client import HTTPResponse
import json
import os
import re
import shutil
import ssl
from enum import Enum
from git import Remote, Repo
from logging import Logger
from pathlib import Path
import shutil
from typing import Optional, Union
from urllib.request import Request, urlretrieve, urlopen
from typing import Optional
from urllib.request import urlretrieve

from git import GitError, Repo
from gitlab import (
    Gitlab,
    GitlabCreateError,
@@ -21,10 +17,7 @@ from gitlab import (
    GitlabListError,
    GitlabUpdateError,
)
from gitlab.v4.objects import ProjectCommit
from gitlab.v4.objects import Group
from gitlab.v4.objects import Project
from gitlab.v4.objects import ProjectRelease
from gitlab.v4.objects import Group, Project, ProjectCommit

LOGGER = Logger(__name__)

@@ -173,7 +166,7 @@ class Synchronizer:
    #         == resp2.headers.get("content-length")
    #     )

    def get_or_create_group(self, group_path: str) -> Group:
    def get_or_create_group(self, group_path: str) -> Optional[Group]:
        if not group_path:
            # root path (emtpy string)
            return None
@@ -231,7 +224,7 @@ class Synchronizer:
            return
        dest_releases = dest_project.releases.list(all=True)
        for src_release in src_releases:
            tag_name = src_release.tag_name
            tag_name: str = src_release.tag_name
            dest_release = next(
                filter(
                    lambda rel: rel.tag_name == tag_name,
@@ -320,15 +313,13 @@ class Synchronizer:
            print(
                f"    - git repository: {AnsiColors.HGRAY}unchanged{AnsiColors.RESET} ({src_default_branch} on #{src_latest_commit.get_id()})"
            )
        else:
            return

        # Git sync is required
        repo_dir = self.work_dir / self.rel_path(src_project.path_with_namespace)
        shutil.rmtree(path=repo_dir, ignore_errors=True)

        src_repo_url: str = src_project.http_url_to_repo
            # print(
            #     f"... git clone source repository ({AnsiColors.HGREEN}{src_repo_url}{AnsiColors.RESET})"
            # )
        if self.src_client.private_token:
            # insert login/password in Git https url
            src_repo_url = src_repo_url.replace(
@@ -336,6 +327,7 @@ class Synchronizer:
            )

        # git clone --bare "$src_repo_url" "$repo_name"
        try:
            repo = Repo.clone_from(
                url=src_repo_url,
                to_path=repo_dir,
@@ -343,12 +335,16 @@ class Synchronizer:
                allow_unsafe_options=True,
                env={} if self.src_client.ssl_verify else {"GIT_SSL_NO_VERIFY": "1"},
            )
        except GitError as ge:
            print(
                f"    - source repo: git clone {AnsiColors.HRED}failed{AnsiColors.RESET}",
                ge,
            )
            self.handle_error(ge)
            return

        # if project already exists: unprotect default branch first
        if dest_latest_commit:
                # print(
                #     f"... unprotect {AnsiColors.HGREEN}{src_default_branch}{AnsiColors.RESET} branch (allow failure)"
                # )
            if not self.dry_run:
                try:
                    dest_project.protectedbranches.delete(src_default_branch)
@@ -363,11 +359,8 @@ class Synchronizer:
        dest_repo_url = (
            dest_project.http_url_to_repo
            if dest_project
                else f"https://gitlab.dummy/{dest_project_path}.git"
            else f"https://gitlab.dummy/{src_project.path_with_namespace}.git"
        )
            # print(
            #     f"... git push (force) destination repository ({AnsiColors.HGREEN}{dest_repo_url}{AnsiColors.RESET})"
            # )
        if self.dest_client.private_token:
            # insert login/password in Git https url
            # shellcheck disable=SC2001
@@ -376,6 +369,7 @@ class Synchronizer:
            )

        # git ${INSECURE:+-c http.sslVerify=false} push --force "$dest_repo_url" --tags "$src_default_branch"
        try:
            if not self.dry_run:
                dest = repo.create_remote("dest", dest_repo_url)
                dest.push(
@@ -389,11 +383,13 @@ class Synchronizer:
                        else {"GIT_SSL_NO_VERIFY": "1"}
                    ),
                ).raise_if_error()
        except GitError as ge:
            print(
                f"    - dest repo: git push --force {AnsiColors.HRED}failed{AnsiColors.RESET}",
                ge,
            )
            self.handle_error(ge)

            # after sync: protect default branch again
            # print(
            #     f"... protect {AnsiColors.HGREEN}{src_default_branch}{AnsiColors.RESET} branch"
            # )
        if not self.dry_run:
            try:
                dest_project.protectedbranches.create({"name": src_default_branch})
@@ -504,7 +500,7 @@ class Synchronizer:
        src_avatar_url = src_project.avatar_url
        src_web_url = src_project.web_url
        dest_avatar_url = dest_project.avatar_url if dest_project else None
        dest_web_url = dest_project.web_url
        dest_web_url = dest_project.web_url if dest_project else None
        if (
            src_avatar_url
            and dest_avatar_url
@@ -641,7 +637,8 @@ class Synchronizer:
            dest_avatar_url = dest_group.avatar_url if dest_group else None
            if (
                src_avatar_url
                and (dest_avatar_url == None or self.update_avatar)
                and dest_group
                and (dest_avatar_url is None or self.update_avatar)
                # and not self.look_same_resources(src_avatar_url, dest_avatar_url)
            ):
                try:
+85 −358

File changed.

Preview size limit exceeded, changes collapsed.

+17 −8
Original line number Diff line number Diff line
@@ -25,8 +25,7 @@ pytest = "^7.0.0"
pytest-cov = "^4.0.0"
pytest-env = "^0.8.0"
mypy = "^1.0.0"
pylint = "^2.17.5"
black = "^24.1.1"
ruff = "^0.4.1"

[tool.pytest.ini_options]
# this project uses "pytest" for unit testing
@@ -35,12 +34,22 @@ testpaths = [
    "tests",
]

[tool.black]
# this project uses "Black" as code formatter
# see: https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#usage
line-length = 88
target-version = ['py312']
include = '\.pyi?$'
[tool.ruff.lint]
extend-select = ["I"] # isort
ignore = ["F841"]

[tool.ruff.format]
# Like Black, use double quotes for strings.
quote-style = "double"

# Like Black, indent with spaces, rather than tabs.
indent-style = "space"

# Like Black, respect magic trailing commas.
skip-magic-trailing-comma = false

# Like Black, automatically detect the appropriate line ending.
line-ending = "auto"

[tool.mypy]
# this project uses "mypy" as a static type checker