diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml index 19ddeb1..0d4b8cb 100644 --- a/.github/workflows/build-dev.yml +++ b/.github/workflows/build-dev.yml @@ -26,9 +26,9 @@ jobs: - os: windows-latest python-version: "3.14" steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies diff --git a/.github/workflows/sonarqube.yml b/.github/workflows/sonarqube.yml index bea3f13..75355b7 100644 --- a/.github/workflows/sonarqube.yml +++ b/.github/workflows/sonarqube.yml @@ -10,11 +10,11 @@ jobs: name: SonarQube runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v6 with: python-version: 3.14 - name: Install dependencies @@ -27,6 +27,6 @@ jobs: coverage combine coverage xml - name: SonarQube Scan - uses: SonarSource/sonarqube-scan-action@v7.0.0 + uses: SonarSource/sonarqube-scan-action@a31c9398be7ace6bbfaf30c0bd5d415f843d45e9 env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/git_platforms_synchro.py b/git_platforms_synchro.py index a5e329e..590190b 100644 --- a/git_platforms_synchro.py +++ b/git_platforms_synchro.py @@ -41,7 +41,7 @@ def set_git_credentials(username: str, password: str): def git_clone(url: str, mirror: bool = False, disable_ssl_verify: bool = False, proxy: str = None) -> Repo: - if os.path.exists(TMP_REPO_GIT_DIRECTORY): + if os.path.exists(TMP_REPO_GIT_DIRECTORY) and len(os.listdir(TMP_REPO_GIT_DIRECTORY)): repo_cloned = Repo(TMP_REPO_GIT_DIRECTORY) origin_url = repo_cloned.remote('origin').url if repo_cloned.bare == mirror and origin_url == url: @@ -74,7 +74,7 @@ def configure_remote_to(repo: Repo, clone_url_to: str, proxy: str = '', ssl_veri def repo_mirror(create_repo: bool, dry_run: bool, clone_url_from: str, login_from: str, password_from: str, proxy_from: str, disable_ssl_verify_from: bool, git_to: GitClient, proxy_to: str, disable_ssl_verify_to: bool, org_to: str, repo: str, description: str = ''): if dry_run: - logger.info(' Dry-run mode, skipping repository creation and mirroring.') + logger.info(' Dry-run mode, skipping repository creation and mirroring.') return if create_repo: git_to.create_repo(org_to, repo, description) @@ -88,7 +88,7 @@ def repo_mirror(create_repo: bool, dry_run: bool, clone_url_from: str, login_fro def repo_tags_sync(args, clone_url_from: str, git_from: GitClient, git_to: GitClient, repo: str, branches_updated: int) -> bool: if args.dry_run: - logger.info(' Dry-run mode, skipping tags synchronization.') + logger.info(' Dry-run mode, skipping tags synchronization.') return False tags_commits_from = git_from.get_tags(args.from_org, repo) @@ -96,7 +96,7 @@ def repo_tags_sync(args, clone_url_from: str, git_from: GitClient, git_to: GitCl if branches_updated > 0 or set(tags_commits_from.keys()).issubset(set(tags_commits_to.keys())): return False - logger.info(' All branches already synchronized, do tags only...') + logger.info(' All branches already synchronized, do tags only...') set_git_credentials(git_from.get_login_or_token(), git_from.get_password()) repo_from_cloned = git_clone(url=clone_url_from, disable_ssl_verify=args.from_disable_ssl_verify, proxy=args.from_proxy) clone_url_to = git_to.get_repo_clone_url(args.to_org, repo) @@ -107,9 +107,9 @@ def repo_tags_sync(args, clone_url_from: str, git_from: GitClient, git_to: GitCl def repo_branch_sync(dry_run: bool, clone_url_from: str, login_from: str, password_from: str, proxy_from: str, disable_ssl_verify_from: bool, - git_to: GitClient, proxy_to: str, disable_ssl_verify_to: bool, org_to: str, repo: str, branch: str): + git_to: GitClient, proxy_to: str, disable_ssl_verify_to: bool, org_to: str, repo: str, branch: str, with_tags: bool): if dry_run: - logger.info(' Dry-run mode, skipping branch synchronization.') + logger.info(' Dry-run mode, skipping branch synchronization.') return set_git_credentials(login_from, password_from) repo_from_cloned = git_clone(url=clone_url_from, disable_ssl_verify=disable_ssl_verify_from, proxy=proxy_from) @@ -117,7 +117,7 @@ def repo_branch_sync(dry_run: bool, clone_url_from: str, login_from: str, passwo clone_url_to = git_to.get_repo_clone_url(org_to, repo) configure_remote_to(repo_from_cloned, clone_url_to, proxy_to, not disable_ssl_verify_to) set_git_credentials(git_to.get_login_or_token(), git_to.get_password()) - repo_from_cloned.remote(GIT_REMOTE_TO).push().raise_if_error() + repo_from_cloned.remote(GIT_REMOTE_TO).push(refspec=branch + ':' + branch, tags=with_tags).raise_if_error() def repo_branches_sync(args, branches_commits_from: dict, branches_commits_to: dict, @@ -132,18 +132,23 @@ def repo_branches_sync(args, branches_commits_from: dict, branches_commits_to: d branches_scanned = branches_updated = 0 for branch in input_parser.reduce(branches_commits_from.keys(), args.branches_include, args.branches_exclude): branches_scanned += 1 - logger.info(' Branch: %s', branch) + logger.info(' Branch: %s', branch) commit_from = branches_commits_from.get(branch, None) - logger.info(' Commit From: %s', commit_from) + logger.info(' Commit From: %s', commit_from) commit_to = branches_commits_to.get(branch, None) - logger.info(' Commit To : %s', commit_to) + logger.info(' Commit To : %s', commit_to) if commit_from == commit_to: - logger.info(' Already synchronized.') + logger.info(' Already synchronized.') continue - logger.info(' Synchronize branch...') + with_tags = False + with_tags_str = '' + if branches_updated == 0: + with_tags = True + with_tags_str = ' (with tags)' + logger.info(' Synchronize branch' + with_tags_str + '...') branches_updated += 1 repo_branch_sync(args.dry_run, clone_url_from, args.from_login, args.from_password, args.from_proxy, args.from_disable_ssl_verify, - git_to, args.to_proxy, args.to_disable_ssl_verify, args.to_org, repo, branch) + git_to, args.to_proxy, args.to_disable_ssl_verify, args.to_org, repo, branch, with_tags) return branches_scanned, branches_updated @@ -175,7 +180,7 @@ def main() -> int: # New repo to create and mirror if not git_to.has_repo(args.to_org, repo): - logger.info(' Repository does not exist on "to" plaform, create as mirror...') + logger.info(' Repository does not exist on "to" plaform, create as mirror...') total_repos_updated += 1 description = git_from.get_repo_description(args.from_org, repo) repo_mirror(True, args.dry_run, clone_url_from, args.from_login, args.from_password, args.from_proxy, args.from_disable_ssl_verify, @@ -185,13 +190,13 @@ def main() -> int: # Branches on "from", skip if no commits branches_commits_from = git_from.get_branches(args.from_org, repo) if len(branches_commits_from) == 0: - logger.info(' Repository has no branches on "from" platform, skipping.') + logger.info(' Repository has no branches on "from" platform, skipping.') continue # Branches on "to", mirror repo if empty branches_commits_to = git_to.get_branches(args.to_org, repo) if len(branches_commits_to) == 0: - logger.info(' Repository has no branches on "to" platform, synchronize as mirror...') + logger.info(' Repository has no branches on "to" platform, synchronize as mirror...') total_repos_updated += 1 repo_mirror( False, diff --git a/tests/test_git_platforms_synchro.py b/tests/test_git_platforms_synchro.py index 8b113c4..a9700ce 100644 --- a/tests/test_git_platforms_synchro.py +++ b/tests/test_git_platforms_synchro.py @@ -289,8 +289,9 @@ def test_from_github_to_gitea_sync_real(httpserver: HTTPServer, caplog: LogCaptu git_platforms_synchro.main() assert 'Reusing existing cloned repo ' + get_url_root(httpserver) + '/spring-projects/spring-petclinic.git' in caplog.text - assert 'Synchronize branch...' in caplog.text + assert 'Synchronize branch (with tags)...' in caplog.text assert 'The requested URL returned error: 542' in caplog.text + assert "['git', 'push', '--porcelain', '--tags', '--', 'sync-to', 'main:main'" in caplog.text def test_from_github_to_gitea_sync_dry_run(httpserver: HTTPServer, caplog: LogCaptureFixture): @@ -303,8 +304,8 @@ def test_from_github_to_gitea_sync_dry_run(httpserver: HTTPServer, caplog: LogCa with patch.object(sys, 'argv', get_test_args_github_to_gitea(httpserver) + ['--dry-run']): git_platforms_synchro.main() - assert 'Synchronize branch...' in caplog.text - assert ' Dry-run mode, skipping branch synchronization.' in caplog.text + assert 'Synchronize branch (with tags)...' in caplog.text + assert 'Dry-run mode, skipping branch synchronization.' in caplog.text def test_from_github_to_gitea_tags_only_real(httpserver: HTTPServer, caplog: LogCaptureFixture): @@ -359,7 +360,7 @@ def test_from_github_to_gitea_all_already_sync(httpserver: HTTPServer, caplog: L git_platforms_synchro.main() assert 'Already synchronized.' in caplog.text - assert 'Synchronize branch...' not in caplog.text + assert 'Synchronize branch' not in caplog.text assert 'All branches already synchronized, do tags only...' not in caplog.text assert 'Git Platforms Synchronization finished sucessfully. Repos updated: 0/1. Branches updated: 0/2' in caplog.text @@ -383,5 +384,5 @@ def test_from_github_to_gitea_tags_diff_sync(httpserver: HTTPServer, caplog: Log git_platforms_synchro.main() assert 'Already synchronized.' in caplog.text - assert 'Synchronize branch...' not in caplog.text + assert 'Synchronize branch' not in caplog.text assert 'All branches already synchronized, do tags only...' in caplog.text