feature: cambio merge y tag para que el changelog se genere al crear un tag nuevo
This commit is contained in:
+69
-210
@@ -5,14 +5,57 @@ import sys
|
||||
import datetime
|
||||
import requests
|
||||
import locale
|
||||
from argparse import Namespace, ArgumentParser
|
||||
|
||||
from .git import Git
|
||||
from .io import *
|
||||
from git_flow import GitFlowError
|
||||
from git_flow.changelog import Changelog
|
||||
from git_flow.command.base import Command
|
||||
from git_flow.command.commit import CommitCommand
|
||||
from git_flow.command.init import InitCommand
|
||||
from git_flow.command.merge import MergeCommand
|
||||
from git_flow.command.new import NewCommand
|
||||
from git_flow.command.tag import TagCommand
|
||||
from git_flow.git import BUMP_VERSION, Git
|
||||
from git_flow.io import *
|
||||
|
||||
|
||||
REPOSITORY_TOKEN_PATH=".repository-token"
|
||||
LOCALE = 'es_AR.UTF-8'
|
||||
|
||||
class GitFlowCommand(Command):
|
||||
commands: tuple[Command, ...]
|
||||
|
||||
def __init__(self, *args: Command) -> None:
|
||||
self.commands = args
|
||||
|
||||
def name(self) -> str:
|
||||
return "git-flow"
|
||||
|
||||
def description(self) -> str:
|
||||
return """Git flow es un workflow automatizado siguiendo conventional commits, semver, y
|
||||
deploys aislados a distintos entornos."""
|
||||
|
||||
def setup_parser(self, parser: ArgumentParser) -> ArgumentParser:
|
||||
subparsers = parser.add_subparsers(title="comandos", dest="command", required=True)
|
||||
|
||||
for command in self.commands:
|
||||
subparser = subparsers.add_parser(command.name())
|
||||
command.setup_parser(subparser)
|
||||
|
||||
return parser
|
||||
|
||||
def get_parser(self) -> ArgumentParser:
|
||||
parser = ArgumentParser(self.name(), description=self.description())
|
||||
|
||||
return self.setup_parser(parser)
|
||||
|
||||
def run(self, args: Namespace = Namespace()):
|
||||
args = self.get_parser().parse_args()
|
||||
|
||||
for command in self.commands:
|
||||
if command.name() == args.command:
|
||||
return command.run(args)
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
@@ -20,6 +63,22 @@ def main():
|
||||
except locale.Error as e:
|
||||
print_warning(f"No se pudo configurar el locale '{LOCALE}': {e}")
|
||||
|
||||
command = GitFlowCommand(
|
||||
InitCommand(),
|
||||
NewCommand(),
|
||||
CommitCommand(),
|
||||
MergeCommand(),
|
||||
TagCommand(),
|
||||
)
|
||||
try:
|
||||
command.run()
|
||||
except GitFlowError as e:
|
||||
command.error(str(e))
|
||||
except Exception as e:
|
||||
command.error("Ocurrió un error inesperado: " + str(e))
|
||||
|
||||
return
|
||||
|
||||
args = sys.argv
|
||||
|
||||
if len(args) < 2:
|
||||
@@ -29,15 +88,7 @@ def main():
|
||||
command = args[1]
|
||||
|
||||
try:
|
||||
if command == "new":
|
||||
new_command()
|
||||
elif command == "init":
|
||||
init_command()
|
||||
elif command == "commit":
|
||||
commit_command()
|
||||
elif command == "merge":
|
||||
merge_command()
|
||||
elif command == "tag":
|
||||
if command == "tag":
|
||||
tag_command()
|
||||
elif command == "release":
|
||||
release_command()
|
||||
@@ -89,198 +140,6 @@ COMMIT_TYPES = [
|
||||
|
||||
DEFAULT_REMOTE = "origin"
|
||||
|
||||
def new_command():
|
||||
current_branch = ensure_right_branch()
|
||||
print_info("Se creará una nueva rama de trabajo sobre la rama actual.")
|
||||
print_info("Seleccione el tipo de cambio a realizar.")
|
||||
|
||||
branch_type = choose("Tipos de cambio", BRANCH_TYPES)
|
||||
branch = get_unique_branch_name(branch_type)
|
||||
|
||||
if confirm(f"Crear rama '{branch}' sobre rama '{current_branch}'"):
|
||||
Git("switch", branch, create=True).exec()
|
||||
else:
|
||||
raise RuntimeError("Abortando operación")
|
||||
|
||||
|
||||
def init_command():
|
||||
if not Git("rev-parse", is_inside_work_tree=True).code() == 0:
|
||||
print_warning("El directorio actual no es un repositorio.")
|
||||
|
||||
if not confirm("¿Desea inicializarlo?"):
|
||||
raise RuntimeError("Abortando operación")
|
||||
|
||||
Git("init").exec()
|
||||
|
||||
initialized = Git.flow_config("flow.initialized").without_checking().firstline()
|
||||
|
||||
if initialized == "true":
|
||||
print_error("El repositorio ya fue inicializado")
|
||||
return
|
||||
elif initialized != "":
|
||||
print_error("El valor de 'flow.initialized' ({initialized}) es inválido")
|
||||
return
|
||||
|
||||
print_info("Ingrese las ramas principales del repositorio separadas por espacio.")
|
||||
|
||||
branches = input("Ramas [dev main]: ").strip()
|
||||
branches = branches.split(" ") if len(branches) > 0 else ["dev", "main"]
|
||||
base = None
|
||||
|
||||
if confirm("¿Desea configurar un repositorio remoto?"):
|
||||
remote = DEFAULT_REMOTE
|
||||
remotes = Git("remote").lines()
|
||||
|
||||
if len(remotes) == 0:
|
||||
print("El repositorio no tiene ningún remoto.")
|
||||
|
||||
url = None
|
||||
|
||||
while url is None:
|
||||
url = input("Ingrese la URL del repositorio (https://github.com/user/repo.git): ").strip()
|
||||
|
||||
if len(url) == 0:
|
||||
print_error("Debe ingresar una URL")
|
||||
url = None
|
||||
elif len(remotes) == 1:
|
||||
remote = remotes[0]
|
||||
else:
|
||||
print("Tiene más de un remoto, seleccione el que desea utilizar.")
|
||||
remote = choose("Remotos: ", remotes)
|
||||
|
||||
Git.flow_config("flow.remote", remote).exec()
|
||||
|
||||
Git.flow_config("flow.branches", " ".join(branches)).exec()
|
||||
Git.flow_config("flow.initialized", "true").exec()
|
||||
Git("add", Git.FLOWCONFIG_FILE).exec()
|
||||
Git("commit", m="feature: initialize git-flow").exec()
|
||||
|
||||
existing_branches = Git.get_branches()
|
||||
|
||||
while base is None:
|
||||
default = Git("rev-parse", "HEAD", abbrev_ref=True).firstline()
|
||||
base = input(f"Ingrese la rama sobre la que desea crear las ramas principales [{default}]: ")
|
||||
|
||||
if not base:
|
||||
base = default
|
||||
elif base not in existing_branches:
|
||||
print_error("Debe ingresar una rama existente.")
|
||||
base = None
|
||||
|
||||
if confirm(f"¿Crear las ramas ingresadas sobre '{base}'?"):
|
||||
for branch in branches:
|
||||
if branch in existing_branches:
|
||||
continue
|
||||
|
||||
if base == "HEAD":
|
||||
Git("branch", branch).exec()
|
||||
else:
|
||||
Git("branch", branch, base).exec()
|
||||
|
||||
|
||||
def commit_command():
|
||||
ensure_initialized()
|
||||
branch = ensure_right_branch()
|
||||
status = Git.status()
|
||||
|
||||
if not status:
|
||||
print_error("No hay cambios para commitear.")
|
||||
return
|
||||
|
||||
files_in_index = []
|
||||
|
||||
for s in status:
|
||||
if s.worktree != "?" and s.worktree != " ":
|
||||
files_in_index.append(s.file)
|
||||
|
||||
if not files_in_index:
|
||||
print_warning("No hay cambios en el indice para commitear.")
|
||||
if confirm("¿Desea agregar la carpeta actual (`git add .`)?"):
|
||||
Git("add", ".").exec()
|
||||
else:
|
||||
print_error("Debe agregar algún cambio al indice para continuar.")
|
||||
return
|
||||
|
||||
commit_type = choose("Tipo de commit", COMMIT_TYPES)
|
||||
message = commit_type + ": " + get_commit_message()
|
||||
|
||||
if branch.startswith("wip/"):
|
||||
original_branch = branch.removeprefix("wip/")
|
||||
Git("commit", m=message).exec()
|
||||
|
||||
if commit_type != "wip":
|
||||
now = datetime.datetime.now()
|
||||
suffix = now.strftime("%Y-%m-%d_%H.%M.%S")
|
||||
Git("switch", original_branch).exec()
|
||||
Git("merge", branch, squash=True).exec()
|
||||
Git("commit", m=message).exec()
|
||||
Git("branch", branch, branch + "/" + suffix, move=True).exec()
|
||||
else:
|
||||
if commit_type == "wip":
|
||||
Git("switch", "wip/" + branch, create=True).exec()
|
||||
|
||||
Git("commit", m=message).exec()
|
||||
|
||||
|
||||
def merge_command():
|
||||
ensure_initialized()
|
||||
branch = ensure_right_branch()
|
||||
|
||||
if branch.startswith("wip/"):
|
||||
print_error("No se pueden mergear ramas de tipo 'wip'")
|
||||
return
|
||||
|
||||
(target, _) = get_branch_env_and_type(branch)
|
||||
status = Git.status()
|
||||
remote = Git.flow_config("flow.remote").firstline()
|
||||
|
||||
if status:
|
||||
not_empty = any(map(lambda s: s.index != " " or s.worktree != " ", status))
|
||||
|
||||
if not_empty:
|
||||
print_warning("Existen cambios en tu entorno de trabajo sin commitear.")
|
||||
|
||||
if not confirm("¿Desea continuar?", False):
|
||||
return
|
||||
|
||||
if remote:
|
||||
Git("switch", target).exec()
|
||||
Git("pull").exec()
|
||||
Git("switch", "-").exec()
|
||||
|
||||
commits = Git("log", target + "..", format="%s").lines()
|
||||
|
||||
if not commits:
|
||||
print_error("No hay cambios a mergear.")
|
||||
return
|
||||
|
||||
print("Cambios a mergear:")
|
||||
|
||||
for commit in commits:
|
||||
if commit != Git.BUMP_VERSION:
|
||||
print("- " + commit)
|
||||
|
||||
merge_conflicts = Git("merge", target, ff=False, commit=False).exec()
|
||||
|
||||
if merge_conflicts:
|
||||
Git("merge", abort=True).exec()
|
||||
print_error(f"La rama actual tiene conflictos con '{target}'. "
|
||||
"Se recomienda mergear la rama a la actual, resolver los conflictos, "
|
||||
"y ejecutar nuevamente este comando.")
|
||||
return
|
||||
|
||||
if remote:
|
||||
Git("push", remote, branch, set_upstream=True).exec()
|
||||
url = Git("remote", "get-url", remote).firstline()
|
||||
|
||||
if url is not None:
|
||||
[service, repository] = parse_url(url)
|
||||
create_pull_request(service, repository, branch, target)
|
||||
else:
|
||||
if confirm(f"Mergear rama '{target}' <= '{branch}'?"):
|
||||
Git("switch", target).exec()
|
||||
Git("merge", branch, ff=False).exec()
|
||||
|
||||
|
||||
def parse_url(url: str) -> list[str]:
|
||||
if "@" in url:
|
||||
@@ -406,8 +265,8 @@ def tag_command():
|
||||
|
||||
merged_commit = Git("show", "HEAD^2", patch=False, format="%H").firstline()
|
||||
if update_changelog(merged_commit, branch):
|
||||
Git("add", Git.CHANGELOG_FILE).exec()
|
||||
Git("commit", message=Git.BUMP_VERSION).exec()
|
||||
Git("add", Changelog.FILENAME).exec()
|
||||
Git("commit", message=BUMP_VERSION).exec()
|
||||
Git("push").exec()
|
||||
else:
|
||||
Git("tag", new_version, commit).exec()
|
||||
@@ -524,16 +383,16 @@ def get_unique_branch_name(branch_type):
|
||||
def update_changelog(branch: str, target: str):
|
||||
last_commit = Git("show", "HEAD", no_patch=True, format="%s").firstline()
|
||||
|
||||
if last_commit == Git.BUMP_VERSION:
|
||||
if last_commit == BUMP_VERSION:
|
||||
return False
|
||||
else:
|
||||
content = generate_changelog_entry(branch, target)
|
||||
|
||||
if os.path.isfile(Git.CHANGELOG_FILE):
|
||||
with open(Git.CHANGELOG_FILE, "r") as changelog:
|
||||
if os.path.isfile(Changelog.FILENAME):
|
||||
with open(Changelog.FILENAME, "r") as changelog:
|
||||
content = content + changelog.read()
|
||||
|
||||
with open(Git.CHANGELOG_FILE, "w") as changelog:
|
||||
with open(Changelog.FILENAME, "w") as changelog:
|
||||
changelog.write(content)
|
||||
|
||||
|
||||
@@ -569,7 +428,7 @@ def get_changelog_content_lines(branch: str, target: str):
|
||||
email = Git("show", commit, patch=False, format="%ae").firstline()
|
||||
username = email[:email.index('@')]
|
||||
|
||||
if message == Git.BUMP_VERSION:
|
||||
if message == BUMP_VERSION:
|
||||
continue
|
||||
|
||||
index = message.index(":")
|
||||
|
||||
Reference in New Issue
Block a user