Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

Commit

Permalink
changes to cli with new commands
Browse files Browse the repository at this point in the history
  • Loading branch information
kjaymiller committed Dec 11, 2023
1 parent e7c6d74 commit c833add
Showing 1 changed file with 152 additions and 90 deletions.
242 changes: 152 additions & 90 deletions tools/update_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@
import json
import itertools
from collections import defaultdict
# from rich import console

# Typer CLI Info
app = typer.Typer()
info_app = typer.Typer()
app.add_typer(info_app, name="info")
repos_app = typer.Typer()
app.add_typer(repos_app, name="repos")

# Configure Logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
file_handler = logging.FileHandler("update_info.log")
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
# Add the file handler to the logger
logger.addHandler(file_handler)

with open("cookiecutter.json") as f:
data = json.load(f)
Expand All @@ -23,7 +40,13 @@


def get_azure_combinations() -> Generator[tuple[str, str], None, None]:
"""Returns the base_keys and base_values for the combinations"""
"""
Returns the base_keys and base_values for the combinations
Yields:
tuple[str, str]: The base_keys and base_values for the combinations
Example: ("azure-flask-postgresql-azure-app-service", "Flask PostgreSQL Azure App Service")
"""
for framework, db_resource, host in combos:
base_keys = (
(f"azure-{framework[0]}/{db_resource[0]}/{host[0]}")
Expand All @@ -37,13 +60,15 @@ def get_azure_combinations() -> Generator[tuple[str, str], None, None]:
yield base_keys, base_values


app = typer.Typer()
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.FileHandler("update_info.log")

@app.command()
@info_app.command(name='list_repos')
def metadata_list():
"""
Creates a json file with the metadata for the combinations
TODO: #302 Allow passing in a file to update_repos to iterate
TODO: #303 Add a pattern that will allow for updating a subset of repos
TODO: #304 Create a list of patterns to exclude
"""
metadata_dict = defaultdict(list)

for framework, db_resource, host in combos:
Expand All @@ -60,90 +85,9 @@ def metadata_list():
with open("metadata.json", "w") as outfile:
json.dump(metadata_dict, outfile, indent=4)


@app.command()
def update_all_repos():
"""
Iterates through combinations:
- Creates a Placeholder Folder
- Attempts to pull the combination url
- Runs Cruft to update based on the path's cruft.json
- Creates pull request for the updates
"""

logger.debug("Creating Placeholder Folder")
base_path = pathlib.Path(f"update_repos/{random_cc_folder_prefix}")
base_path.mkdir(parents=True, exist_ok=True)

logger.debug("Cloning Repos and Running Cruft")
for base_key, base_values in get_azure_combinations():
base_file = base_key.replace("-", "_")
url = f"[email protected]:Azure-Samples/{base_key}.git"
cmd = ["git", "clone", url, base_file]
path = base_path.joinpath(base_file)

try:
subprocess.check_output(
cmd,
cwd=base_path,
)

except subprocess.CalledProcessError as e:
logger.warning(f"Could not to clone {url}: {e}. This is likely a non-existent repo.")
continue

branch_name = f"cruft/update"
subprocess.check_output(
["git", "checkout", "-b", branch_name],
text=True,
cwd=path,
)

cruft.update(
path, skip_apply_ask=True, extra_context={"python_version": "3.12"}
)

if not subprocess.check_output(
["git", "status", "--porcelain"],
text=True,
cwd=path,
):
logger.info(f"No changes for {base_file}, skipping.")
continue

if subprocess.check_output(
["ls -a" "**/*.rej"],
text=True,
cwd=path,
):
logger.error(f"Rejection files found for {base_file}!")
exit(1)

subprocess.check_output(
["git", "add", "."],
text=True,
cwd=path,
)
subprocess.check_output(
["git", "commit", "-m", "Cruft Update"],
text=True,
cwd=path,
)
subprocess.check_output(
["git", "push", "--set-upstream", "origin", branch_name],
text=True,
cwd=path,
)
subprocess.check_output(
["gh", "pr", "create", "--fill", "--reviewer", "kjaymiller,pamelafox"],
text=True,
cwd=path,
)


@app.command()
@info_app.command()
def update_readme():
"""Updates the README of cookiecutter-relecloud with the list of combinations"""
web_framework_values = defaultdict(list)

for framework, db_resource, host in combos:
Expand All @@ -168,6 +112,124 @@ def update_readme():

print(f"{len(list(combos))}: Total Combinations")

def create_base_folder():
"""Creates the base folder for the repo"""
base_path = pathlib.Path(f"update_repos/{random_cc_folder_prefix}")
base_path.mkdir(parents=True, exist_ok=True)
return base_path
# TODO: Get repos by pattern


def get_repos_by_pattern(pattern:str, repos: list[str]=list(get_azure_combinations())) -> list[str]:
"""
Returns a list of repos that match the provided pattern.
TODO: #305 Add Test
"""
pattern = re.compile(pattern)
matching_repos = [repo for repo in repos if pattern.match(repo)]
return matching_repos

def update_repo(repo:str, path: pathlib.Path, branch:str="cruft/update", **kwargs) -> None:
"""
Updates the repo with the provided name
Parameters:
repo (str): The name of the repo to update.
It should be the same as seen on GitHub.
path (pathlib.Path): The parent folder where the will be saved.
branch (str): The name of the branch to create and push to.
Defaults to cruft/update.
**kwargs: Additional keyword arguments to pass to cruft.update as
"""
# console = console.Console()
logger.debug("Creating Placeholder Folder")
url = f"[email protected]:Azure-Samples/{repo}.git"
path = path.joinpath(repo)

try:
subprocess.check_output(
["git", "clone", url],
cwd=path.parent,
)

except subprocess.CalledProcessError as e:
raise ValueError(f"Could not to clone {url}: {e}.\nThis is likely a non-existent repo.")

subprocess.check_output(
["git", "checkout", "-b", branch],
text=True,
cwd=path,
)

cruft.update(
path, skip_apply_ask=True, extra_context=kwargs,
)

if not subprocess.check_output(
["git", "status", "--porcelain"],
text=True,
cwd=path,
):
logger.info(f"No changes for {path}, skipping.")
return

if rejection_files:=list(pathlib.Path(path).rglob("*.rej")):
logger.error(f"Rejection files found for {path}!\nFiles: {'\n- '.join(rejection_files)}")
exit(1)

# Add the Changes and Create a PR
subprocess.check_output(
["git", "add", "."],
text=True,
cwd=path,
)
subprocess.check_output(
["git", "commit", "-m", "Cruft Update"],
text=True,
cwd=path,
)
subprocess.check_output(
["git", "push", "--set-upstream", "origin", branch],
text=True,
cwd=path,
)
subprocess.check_output(
["gh", "pr", "create", "--fill", "--reviewer", "kjaymiller,pamelafox"],
text=True,
cwd=path,
)

@repos_app.command(name="update-one")
def update_single_repo(repo:str, branch:str="cruft/update") -> None:
"""Clones a single repo and updates it using `cruft update`"""
logger.info(f)
return update_repo(repo=repo, path=create_base_folder(), branch=branch)

@repos_app.command(name="update-many")
def update_repos(pattern:str, branch:str="cruft/update") -> None:
"""Updates all repos that match the provided pattern"""
path = create_base_folder()
repos = get_repos_by_pattern(pattern)
for repo in repos:
update_repo(repo=repo, path=path, branch=branch)


@repos_app.command(name="update-all")
def update_all_repos(branch:str="cruft/update"):
"""
Iterates through combinations:
- Creates a Placeholder Folder
- Attempts to pull the combination url
- Runs Cruft to update based on the path's cruft.json
- Creates pull request for the updates
"""

path = create_base_folder()
for base_key,_ in get_azure_combinations():
update_repo(base_key, path, branch=branch)



if __name__ == "__main__":
app()

0 comments on commit c833add

Please sign in to comment.