Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,5 @@ dmypy.json
# VSCode settings
.vscode

doc/_build
doc/_build
doc/source/api
14 changes: 0 additions & 14 deletions doc/source/_autoapi_templates/index.rst

This file was deleted.

5 changes: 4 additions & 1 deletion doc/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,20 @@
"version_match": get_version_match(__version__),
},
"check_switcher": False,
"ansys_sphinx_theme_autoapi": {
"project": project,
},
}

# Sphinx extensions
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.autosummary",
"autoapi.extension",
"sphinx_autodoc_typehints",
"numpydoc",
"sphinx.ext.intersphinx",
"sphinx_copybutton",
"ansys_sphinx_theme.extension.autoapi",
]

# Intersphinx mapping
Expand Down
2 changes: 1 addition & 1 deletion doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
:hidden:
:maxdepth: 3

autoapi/index
api/index
7 changes: 7 additions & 0 deletions src/ansys/tools/repo_sync/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,11 @@
# Ease import statements
# ------------------------------------------------------------------------------

from .constants import DEFAULT_BRANCH_NAME, DEFAULT_PULL_REQUEST_TITLE
from .repo_sync import synchronize

__all__ = [
"synchronize",
"DEFAULT_BRANCH_NAME",
"DEFAULT_PULL_REQUEST_TITLE",
]
29 changes: 23 additions & 6 deletions src/ansys/tools/repo_sync/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@
.. code::

repo-sync \
--token <token> \
--owner <organization-name> \
--repository <repository-name> \
--from-dir <path-to-dir-containing-files-to-sync> \
--to-dir <target-dir-for-sync> \
--include-manifest <path-to-manifest>
--token <token> \
--owner <organization-name> \
--repository <repository-name> \
--from-dir <path-to-dir-containing-files-to-sync> \
--to-dir <target-dir-for-sync> \
--include-manifest <path-to-manifest>

"""
import click

from .constants import DEFAULT_BRANCH_NAME, DEFAULT_PULL_REQUEST_TITLE
from .repo_sync import synchronize as _synchronize


Expand Down Expand Up @@ -99,6 +100,18 @@
default=False,
help="Generates a random branch name instead of the typical ``sync/file-sync``. Used for testing purposes mainly.",
)
@click.option(
"--target-branch-name",
type=str,
default=DEFAULT_BRANCH_NAME,
help=f"Name of the branch to create for the synchronization, by default it is '{DEFAULT_BRANCH_NAME}'.",
)
@click.option(
"--pull-request-title",
type=str,
default=DEFAULT_PULL_REQUEST_TITLE,
help=f"Title of the pull request created after synchronization, by default it is {DEFAULT_PULL_REQUEST_TITLE}",
)
def synchronize(
owner,
repository,
Expand All @@ -112,6 +125,8 @@ def synchronize(
dry_run,
skip_ci,
random_branch_name,
target_branch_name,
pull_request_title,
):
"""CLI command to execute the repository synchronization."""
_synchronize(
Expand All @@ -127,6 +142,8 @@ def synchronize(
dry_run=dry_run,
skip_ci=skip_ci,
random_branch_name=random_branch_name,
target_branch_name=target_branch_name,
pull_request_title=pull_request_title,
)


Expand Down
29 changes: 29 additions & 0 deletions src/ansys/tools/repo_sync/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates.
# SPDX-License-Identifier: MIT
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""Module containing constants for the repo sync tool."""

DEFAULT_BRANCH_NAME = "sync/file-sync"
"""Default branch name for the synchronization process."""

DEFAULT_PULL_REQUEST_TITLE = "sync: file sync performed by ansys-tools-repo-sync"
"""Default title for the pull request created during synchronization."""
41 changes: 25 additions & 16 deletions src/ansys/tools/repo_sync/repo_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""Module containing the sync tool implementation."""

from fnmatch import filter
import os
import re
Expand All @@ -30,6 +32,8 @@
from git import Repo
from github import Auth, Github, GithubException

from .constants import DEFAULT_BRANCH_NAME, DEFAULT_PULL_REQUEST_TITLE


def include_patterns(*patterns):
"""Include listed patterns in ``copytree()``.
Expand Down Expand Up @@ -148,6 +152,8 @@ def synchronize(
dry_run: bool = False,
skip_ci: bool = False,
random_branch_name: bool = False,
target_branch_name: str = DEFAULT_BRANCH_NAME,
pull_request_title: str = DEFAULT_PULL_REQUEST_TITLE,
) -> Union[str, None]:
"""Synchronize a folder to a remote repository.

Expand Down Expand Up @@ -178,23 +184,24 @@ def synchronize(
skip_ci : bool, optional
Whether to add a ``[skip ci]`` prefix to the commit message or not. By default ``False``.
random_branch_name : bool, optional
For testing purposes - generates a random suffix for the branch name ``sync/file-sync``.
For testing purposes - generates a random suffix for the branch name.
target_branch_name : str, optional
Name of the branch to create for the synchronization, by default it is 'sync/file-sync'.
pull_request_title : str, optional
Title of the pull request created after synchronization, by default it is
'sync: file sync performed by ansys-tools-repo-sync'.

Returns
-------
Union[str, None]
Pull request URL. In case of dry-run or no files modified, ``None`` is returned.

"""
# New branch name and PR title
new_branch_name = "sync/file-sync"
pr_title = "sync: file sync performed by ansys-tools-repo-sync"

# If requested, add random suffix
if random_branch_name:
from secrets import token_urlsafe

new_branch_name = f"{new_branch_name}-{token_urlsafe(16)}"
target_branch_name = f"{target_branch_name}-{token_urlsafe(16)}"

# Authenticate with GitHub
g = Github(auth=Auth.Token(token))
Expand Down Expand Up @@ -240,18 +247,20 @@ def synchronize(
dirs_exist_ok=True,
)

print(f">>> Checking out new branch '{new_branch_name}' from '{branch_checked_out}'...")
print(f">>> Checking out new branch '{target_branch_name}' from '{branch_checked_out}'...")
repo = Repo(repo_path)
try:
# Commit changes to a new branch
repo.git.checkout(branch_checked_out)
repo.git.checkout("-b", new_branch_name)
print(f">>> Committing changes to branch '{new_branch_name}'...")
repo.git.checkout("-b", target_branch_name)
print(f">>> Committing changes to branch '{target_branch_name}'...")
repo.git.add("--all")
repo.index.commit(f"{'[skip ci] ' if skip_ci else ''}sync: add changes from local folder")

# Get a list of the files modified
output = repo.git.diff("--compact-summary", f"{branch_checked_out}", f"{new_branch_name}")
output = repo.git.diff(
"--compact-summary", f"{branch_checked_out}", f"{target_branch_name}"
)

# If output is empty, avoid creating PR
if not output:
Expand All @@ -264,17 +273,17 @@ def synchronize(
pull_request = None
if not dry_run:
# Push changes to remote repositories
print(f">>> Force-pushing branch '{new_branch_name}' remotely...")
repo.git.push("--force", "origin", new_branch_name)
print(f">>> Force-pushing branch '{target_branch_name}' remotely...")
repo.git.push("--force", "origin", target_branch_name)

# Create a pull request
try:
print(f">>> Creating pull request from '{new_branch_name}'...")
print(f">>> Creating pull request from '{target_branch_name}'...")
pull_request = pygithub_repo.create_pull(
title=pr_title,
title=pull_request_title,
body="Please review and merge these changes.",
base=branch_checked_out,
head=new_branch_name,
head=target_branch_name,
)
except GithubException as err:
if err.args[0] == 422 or err.data["message"] == "Validation Failed":
Expand All @@ -286,7 +295,7 @@ def synchronize(
# Find the associated PR (must be opened...)
associated_pull_request = None
for pr in prs:
if pr.head.ref == new_branch_name:
if pr.head.ref == target_branch_name:
associated_pull_request = pr
break

Expand Down
Loading