Compare commits

...
30 Commits
Author SHA1 Message Date
gitea-actions b8fff9e77a chore: bump version and update CHANGELOG.md [skip ci] 2026-09-15 19:53:13 +00:00
jt f6a7f1a987 Merge pull request 'bugfix: include group path in repo for gitlab support' (#17) from bugfix/gitlab-include-group-path into main
Publish to PyPI / Publish-to-PyPI (push) Successful in 44s
Reviewed-on: #17
2026-09-15 19:52:35 +00:00
Jonathan Teran 3e448544f0 bugfix: include group path in repo for gitlab support 2026-09-15 16:50:45 -03:00
jt 75a77201d4 Merge pull request 'docs: actualizar README con secciones por remoto y ejemplos de pipeline' (#16) from worktree-kind-watching-hearth into main
Publish to PyPI / Publish-to-PyPI (push) Failing after 29s
Reviewed-on: #16
2026-09-14 04:03:06 +00:00
jtandClaude Sonnet 5 e8c0c0b777 docs: actualizar README con secciones por remoto y ejemplos de pipeline
Documenta como generar tokens de acceso para Github, Gitlab, Bitbucket y
Gitea, y agrega ejemplos de pipeline para taggeo automatico en cada uno.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 23:18:47 -03:00
gitea-actions d4dc694db6 chore: bump version and update CHANGELOG.md [skip ci] 2026-09-14 00:23:39 +00:00
jt 9120698900 Merge pull request 'refactor: remove release prompts' (#15) from refactor/remove-release-prompts into main
Publish to PyPI / Publish-to-PyPI (push) Successful in 17s
Reviewed-on: #15
2026-09-14 00:23:28 +00:00
jt c035a8867e refactor: cambiar incremento de commits refactor y perf 2026-09-13 21:22:41 -03:00
jt 0c31c747ff refactor: eliminar preguntas innecesarias de release y merge 2026-09-13 21:22:14 -03:00
gitea-actions 12ce68d954 chore: bump version and update CHANGELOG.md [skip ci] 2026-09-13 23:56:52 +00:00
jt 29eacfdc4d Merge pull request 'feature: add gitlab remote support' (#14) from feature/gitlab-remote-support into main
Publish to PyPI / Publish-to-PyPI (push) Successful in 2m40s
Reviewed-on: #14
2026-09-13 23:54:15 +00:00
jt 748d4201cc feature: add gitlab remote support 2026-09-13 20:48:49 -03:00
gitea-actions 94a219ed82 chore: bump version and update CHANGELOG.md [skip ci] 2026-07-31 15:25:28 +00:00
jt 3f3650360a Merge pull request 'Feature/parse git remote url with library' (#12) from feature/parse-git-remote-url-with-library into main
Publish to PyPI / Publish-to-PyPI (push) Successful in 55s
Reviewed-on: #12
2026-07-31 15:24:35 +00:00
Jonathan Teran 11a48a922c style: format with ruff 2026-07-31 12:22:39 -03:00
Jonathan Teran f4adb431db feature: parse git remote url with giturlparse 2026-07-31 12:22:14 -03:00
gitea-actions 8f1a60cc06 chore: bump version and update CHANGELOG.md [skip ci] 2026-07-29 14:56:49 +00:00
jt fcc8114c8e Merge pull request 'bugfix: change checkout version to v7' (#11) from feature/change-flow-settings-in-local-config into main
Publish to PyPI / Publish-to-PyPI (push) Successful in 16s
Reviewed-on: #11
2026-07-29 14:56:38 +00:00
Jonathan Teran Carballo c58c4cea96 bugfix: change checkout version to v7 2026-07-29 11:55:54 -03:00
jt 7fbf499278 Merge pull request 'bugfix: move git fetch to separate line' (#10) from feature/change-flow-settings-in-local-config into main
Publish to PyPI / Publish-to-PyPI (push) Failing after 8s
Reviewed-on: #10
2026-07-29 14:49:33 +00:00
Jonathan Teran Carballo 64fc890cb7 bugfix: move git fetch to separate line 2026-07-29 11:49:25 -03:00
gitea-actions 7199249f75 chore: bump version and update CHANGELOG.md [skip ci] 2026-07-29 14:47:56 +00:00
jt 7efaf367e5 Merge pull request 'bugfix: change actions/checkout to v4 and add step to fetch tags' (#9) from feature/change-flow-settings-in-local-config into main
Publish to PyPI / Publish-to-PyPI (push) Failing after 17s
Reviewed-on: #9
2026-07-29 14:47:38 +00:00
Jonathan Teran Carballo dc79ffa399 bugfix: change actions/checkout to v4 and add step to fetch tags 2026-07-29 11:47:00 -03:00
jt 31513a3e3a Merge pull request 'bugfix: change actions/checkout version' (#8) from feature/change-flow-settings-in-local-config into main
Publish to PyPI / Publish-to-PyPI (push) Failing after 19s
Reviewed-on: #8
2026-07-29 14:45:20 +00:00
Jonathan Teran Carballo c45f065e77 bugfix: change actions/checkout version 2026-07-29 11:45:12 -03:00
jt 7f7dd7b538 Merge pull request 'bugfix: add fetch-tags: true' (#7) from feature/change-flow-settings-in-local-config into main
Publish to PyPI / Publish-to-PyPI (push) Failing after 14s
Reviewed-on: #7
2026-07-29 14:41:06 +00:00
Jonathan Teran Carballo adcb53156a bugfix: add fetch-tags: true 2026-07-29 11:40:54 -03:00
jt 5ca817c796 Merge pull request 'bugfix: remove checkout parameters' (#6) from feature/change-flow-settings-in-local-config into main
Publish to PyPI / Publish-to-PyPI (push) Failing after 14s
Reviewed-on: #6
2026-07-29 14:35:04 +00:00
Jonathan Teran Carballo 2be9b50ac4 bugfix: remove checkout parameters 2026-07-29 11:34:43 -03:00
12 changed files with 331 additions and 83 deletions
+1 -8
View File
@@ -8,11 +8,10 @@ jobs:
Publish-to-PyPI:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true
- name: Configure git
run: |
@@ -28,12 +27,6 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v8.3.2
- name: Count commits
run: |
echo "Commit count: $(git rev-list --count main)"
echo "Tags available:"
git tag
- name: Bump version
run: |
uv run git-flow tag --token="${{ secrets.GITEA_TOKEN }}"
+54
View File
@@ -1,3 +1,57 @@
## v1.20.2 - 2026-09-15
- **bugfix**: include group path in repo for gitlab support [[jteran](mailto:jteran@renatre.org.ar)] (3e44854)
---
## v1.20.1 - 2026-09-14
- **refactor**: cambiar incremento de commits refactor y perf [[jonathan.nerat](mailto:jonathan.nerat@gmail.com)] (c035a88)
- **refactor**: eliminar preguntas innecesarias de release y merge [[jonathan.nerat](mailto:jonathan.nerat@gmail.com)] (0c31c74)
---
## v1.20.0 - 2026-09-13
- **feature**: add gitlab remote support [[jonathan.nerat](mailto:jonathan.nerat@gmail.com)] (748d420)
---
## v1.19.0 - 2026-07-31
- **style**: format with ruff [[jteran](mailto:jteran@renatre.org.ar)] (11a48a9)
- **feature**: parse git remote url with giturlparse [[jteran](mailto:jteran@renatre.org.ar)] (f4adb43)
---
## v1.18.0 - 2026-07-29
- **bugfix**: change checkout version to v7 [[jteran](mailto:jteran@renatre.org.ar)] (c58c4ce)
- **bugfix**: move git fetch to separate line [[jteran](mailto:jteran@renatre.org.ar)] (64fc890)
- **bugfix**: change actions/checkout to v4 and add step to fetch tags [[jteran](mailto:jteran@renatre.org.ar)] (dc79ffa)
- **bugfix**: change actions/checkout version [[jteran](mailto:jteran@renatre.org.ar)] (c45f065)
- **bugfix**: add fetch-tags: true [[jteran](mailto:jteran@renatre.org.ar)] (adcb531)
- **bugfix**: remove checkout parameters [[jteran](mailto:jteran@renatre.org.ar)] (2be9b50)
- **feature**: show commit count and list tags on workflow [[jteran](mailto:jteran@renatre.org.ar)] (f05582b)
---
## v0.1.0-main - 2026-07-29
- **bugfix**: change actions/checkout to v4 and add step to fetch tags [[jteran](mailto:jteran@renatre.org.ar)] (dc79ffa)
- **bugfix**: change actions/checkout version [[jteran](mailto:jteran@renatre.org.ar)] (c45f065)
- **bugfix**: add fetch-tags: true [[jteran](mailto:jteran@renatre.org.ar)] (adcb531)
- **bugfix**: remove checkout parameters [[jteran](mailto:jteran@renatre.org.ar)] (2be9b50)
- **feature**: show commit count and list tags on workflow [[jteran](mailto:jteran@renatre.org.ar)] (f05582b)
---
## v0.1.0-main - 2026-07-29
- **feature**: show commit count and list tags on workflow [[jteran](mailto:jteran@renatre.org.ar)] (f05582b)
+152 -11
View File
@@ -15,7 +15,7 @@ carpeta local, y lo instalamos:
```sh
cd ~/Downloads
git clone git@bitbucket.org:sushi2717/git-flow.git
git clone ssh://git@git.jonathanteran.dev:59169/jt/git-flow.git
cd git-flow
pipx install .
```
@@ -49,24 +49,27 @@ El comando solicitará 2 opciones:
- [x] Bitbucket
- [x] Github
- [x] Gitea
- [x] Gitlab
La configuración del remoto requiere tener un Access Token para poder crear los PRs automáticamente.
El mismo se puede crear desde el repositorio al que se quiere dar acceso: *"Repository settings" >
"Access Tokens" > "Create access token"*. El token necesita permiso para *Write* en *Pull Requests*.
La configuración del remoto requiere tener un Access Token para poder crear los PRs y tags
automáticamente. Ver la sección [Remotos soportados](#remotos-soportados) para las instrucciones
de cómo generar el token en cada proveedor.
Luego se debe guardar el token dentro del repositorio a configurar, en el archivo
Una vez generado, el token se debe guardar dentro del repositorio a configurar, en el archivo
`.repository-token`. De no especificarse, los merges y tags se harán de forma local.
## Utilización
Git Flow cuenta con 5 comandos principales para guiar el workflow (ver `git-flow <command> -h` para
Git Flow cuenta con los siguientes comandos para guiar el workflow (ver `git-flow <command> -h` para
más información):
- `init`: Inicializa el repositorio para utilizar git-flow (ramas principales y remoto).
- `new`: Crea una nueva rama siguiendo CB.
- `commit`: Crea un commit siguiendo CC.
- `merge`: Mergea la rama actual a una de las ramas principales.
- `tag`: Crea un tag sobre el ultimo merge siguiendo SemVer.
- `release`: Prepara la rama actual para pasarse al siguiente entorno configurado
- `release`: Prepara la rama actual para pasarse al siguiente entorno configurado.
- `branch`: Lista las ramas del repositorio, agrupadas por entorno objetivo.
El workflow para el cual se penso la herramienta es el siguiente:
@@ -85,9 +88,147 @@ El workflow para el cual se penso la herramienta es el siguiente:
`feature/my-new-feature`, se crea la rama `release/test/feature/my-new-feature` sobre `test` que
tiene los cambios de la rama original.
En cualquier momento se puede usar `git-flow branch` para ver en qué entorno está cada rama, y cuáles
están todavía en progreso (`wip/`) o descartadas (`trash/`).
## Remotos soportados
Cada remoto necesita un Access Token con permisos para crear Pull/Merge Requests y tags. El token se
guarda en el archivo `.repository-token` en la raíz del repositorio (una única línea con el valor del
token), o se pasa por parámetro con `--token=<TOKEN>` al comando `git-flow tag` (útil para no
commitear el token y usarlo solo desde un pipeline mediante una variable secreta).
### Github
1. Ir a *Settings* del repositorio (o de la organización) > *Developer settings* > *Personal access
tokens* > *Fine-grained tokens* > *Generate new token*.
2. Seleccionar el repositorio sobre el que se va a usar `git-flow`.
3. En *Repository permissions*, otorgar:
- **Contents**: Read and write (necesario para crear tags).
- **Pull requests**: Read and write (necesario para crear PRs).
4. Generar el token y guardarlo en `.repository-token`.
Ejemplo de pipeline (GitHub Actions) para taggear automáticamente en cada push a una rama principal:
```yaml
# .github/workflows/tag.yml
name: Tag and publish
on:
push:
branches: [main]
jobs:
tag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: astral-sh/setup-uv@v3
- run: uv run git-flow tag --token=${{ secrets.GIT_FLOW_TOKEN }}
- run: uv build
- run: uv publish --token=${{ secrets.PYPI_TOKEN }}
```
### Gitlab
1. Ir a *Settings* > *Access Tokens* del proyecto (o *Group access tokens* si se quiere usar a nivel
grupo).
2. Crear un token con rol **Developer** o superior, y los scopes:
- **api** (o al menos `write_repository` para tags y `api` para Merge Requests).
3. Generar el token y guardarlo en `.repository-token`.
Ejemplo de pipeline (GitLab CI) para taggear automáticamente en cada push a una rama principal:
```yaml
# .gitlab-ci.yml
tag:
image: python:3.14
rules:
- if: $CI_COMMIT_BRANCH == "main"
script:
- pip install uv
- uv run git-flow tag --token=$GIT_FLOW_TOKEN
- uv build
- uv publish --token=$PYPI_TOKEN
```
El token debe guardarse como variable protegida y enmascarada (`GIT_FLOW_TOKEN`) en *Settings* >
*CI/CD* > *Variables*.
### Bitbucket
1. Ir a *Repository settings* > *Access Tokens* > *Create access token* (o *Workspace settings* >
*Access Tokens* para un token a nivel workspace).
2. Otorgar permiso de **Write** en *Pull requests* y *Repositories* (necesario para crear tags).
3. Generar el token y guardarlo en `.repository-token`.
Este mismo repositorio usa Git Flow para el taggeo automático usando Bitbucket Pipelines, se puede
ver el archivo `bitbucket-pipelines.yml` como ejemplo:
```yaml
# bitbucket-pipelines.yml
image: python:3.14
pipelines:
branches:
'main':
- step:
name: "Tag and publish package"
caches:
- pip
script:
- pip install uv
- uv run git-flow tag --token=$BEARER
- uv build
- uv publish --token=$PYPI_TOKEN
```
El token se configura como variable segura del repositorio (`BEARER`) en *Repository settings* >
*Repository variables*.
### Gitea
1. Ir a *Settings* del usuario (o de la organización) > *Applications* > *Manage Access Tokens* >
*Generate New Token*.
2. Otorgar permiso de escritura sobre:
- **repository** (necesario para crear tags).
- **issue** (necesario para crear PRs, ya que Gitea expone los PRs bajo el mismo scope).
3. Generar el token y guardarlo en `.repository-token`.
Ejemplo de pipeline (Gitea Actions) para taggear automáticamente en cada push a una rama principal:
```yaml
# .gitea/workflows/tag.yml
name: Tag and publish
on:
push:
branches: [main]
jobs:
tag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: astral-sh/setup-uv@v3
- run: uv run git-flow tag --token=${{ secrets.GIT_FLOW_TOKEN }}
- run: uv build
- run: uv publish --token=${{ secrets.PYPI_TOKEN }}
```
## Taggeo automático por pipeline
Éste repositorio utiliza Git Flow para el taggeo automático usando pipelines, se puede ver el
archivo `bitbucket-pipelines.yml` como ejemplo. El comando `git-flow tag` soporta el pasaje del
token mediante la opción `--token=<TOKEN>`. Ver la sección [Configuración](#configuracion) para las
instrucciones de como generar este token. El mismo necesita scope `write:repository:bitbucket`.
En todos los casos, `git-flow tag` detecta que se está ejecutando desde un pipeline (no encuentra
`.repository-token` en el repositorio) y usa el token pasado por `--token=<TOKEN>` tanto para crear
el tag en el remoto como para pushear el commit del `CHANGELOG.md` generado, en vez de crear el tag
únicamente en forma local como sucede al ejecutarlo manualmente sin remoto configurado.
+1 -1
View File
@@ -8,7 +8,7 @@ description = "Git workflow automation to follow best practices when working wit
dynamic = ["version"]
requires-python = ">= 3.14"
dependencies = [
"requests", "typer", "rich", "questionary"
"requests", "typer", "rich", "questionary", "giturlparse"
]
authors = [
{name = "Alan Facundo Biglieri", email = "abiglieri@renatre.org.ar"},
+6 -5
View File
@@ -36,16 +36,17 @@ COMMIT_TYPE_INCREMENT = {
"feature": SEMVER_MINOR,
"bugfix": SEMVER_PATCH,
"hotfix": SEMVER_PATCH,
"refactor": SEMVER_SKIP,
"perf": SEMVER_SKIP,
"refactor": SEMVER_PATCH,
"perf": SEMVER_PATCH,
"docs": SEMVER_SKIP,
"style": SEMVER_SKIP,
"test": SEMVER_SKIP,
}
SUPPORTED_REMOTE_APIS = [
"bitbucket.org",
"github.com",
SUPPORTED_REMOTE_URL_SCHEMAS = [
"ssh",
"http",
"https"
]
REPOSITORY_TOKEN_FILENAME = ".repository-token"
+4
View File
@@ -11,6 +11,7 @@ from git_flow.remote.base import RemoteAPI
from git_flow.remote.bitbucket import BitbucketRemoteAPI
from git_flow.remote.github import GithubRemoteAPI
from git_flow.remote.gitea import GiteaRemoteAPI
from git_flow.remote.gitlab import GitlabRemoteAPI
from git_flow.io import *
from os.path import isfile
@@ -123,6 +124,9 @@ def get_remote_api(token: str) -> RemoteAPI:
if remote_type == "gitea":
remote_schema = "https://" if schema == "ssh://" else schema
return GiteaRemoteAPI(remote_schema + host, repository, token)
elif remote_type == "gitlab":
remote_schema = "https://" if schema == "ssh://" else schema
return GitlabRemoteAPI(remote_schema + host, repository, token)
elif remote_type == "bitbucket":
return BitbucketRemoteAPI(repository, token)
elif remote_type == "github":
+1 -1
View File
@@ -101,7 +101,7 @@ uno nuevo.""",
remote = base.io_choice("Remoto", remotes)
remote_type = base.io_choice(
"Tipo de remoto:", ["bitbucket", "github", "gitea"]
"Tipo de remoto:", ["bitbucket", "github", "gitea", "gitlab"]
)
return (remote, remote_type)
-4
View File
@@ -119,10 +119,6 @@ def create_pull_request(token: str, branch: str, target: str):
base.io_success(message, "Rama creada")
if base.io_confirm("¿Desea cambiar a la rama objetivo y bajar los cambios?"):
Git("switch", target).exec(print="Cambiando a rama objetivo")
Git("pull").exec(print="Obteniendo cambios")
def _get_pr_title_from_branch(branch: str) -> str:
if branch in base.environments:
+6 -36
View File
@@ -1,16 +1,14 @@
from typing import Optional
import typer
import git_flow.command.base as base
from git_flow import COMMIT_TYPES, GitFlowError
from git_flow import GitFlowError
from git_flow.git import Git
app = typer.Typer()
@app.command()
def release(group: Optional[str] = None):
def release():
"""Realiza el merge de la rama, o crea el PR para hacerlo si tiene un remoto configurado"""
base.ensure_initialized()
@@ -44,45 +42,17 @@ def release(group: Optional[str] = None):
for commit in commits:
print("- " + commit)
grouping = group is not None
if not group:
if base.io_confirm("¿Desea agrupar este release con otra rama?", False):
grouping = True
group = base.io_choice(
"Grupo release: ", Git.get_branches("release/" + next_env + "/")
)
else:
group = next_env
if has_remote and Git.get_tracking_branch(group):
Git("switch", group).exec(print="Cambiando a la rama objetivo")
if has_remote and Git.get_tracking_branch(next_env):
Git("switch", next_env).exec(print="Cambiando a la rama objetivo")
Git("pull").exec(print="Sincronizando cambios la rama objetivo")
Git("switch", "-").exec(print="Volviendo a la rama original")
if len(commits) > 1 and base.io_confirm(
f"¿Desea reemplazar los {len(commits)} commits de la rama por uno solo?", False
):
base.io_info("Debe ingresar el mensaje del commit a crear.")
message = base.get_commit_message(COMMIT_TYPES[:-1])
Git("switch", next_branch, create=True).exec(print="Creando rama release")
Git("switch", next_branch, fork_point, create=True).exec(
print="Creando rama release en base"
)
Git("merge", branch, squash=True).exec(print="Squasheando commits en uno solo")
Git("commit", m=message).exec(print="Creando commit único")
else:
Git("switch", next_branch, create=True).exec(print="Creando rama release")
status = Git("rebase", fork_point, next_branch, onto=group).code(
status = Git("rebase", fork_point, next_branch, onto=next_env).code(
print="Moviendo cambios hacia el siguiente ambiente"
)
if status:
Git("rebase", abort=True).exec(print="Deshaciendo cambios por conflictos")
raise GitFlowError("Error al realizar pasaje de cambios a rama objetivo")
elif grouping:
Git("switch", group).exec(print="Cambiando a rama objetivo")
Git("merge", next_branch, ff_only=True).exec(
print="Mergeando cambios de la nueva rama"
)
+36 -17
View File
@@ -1,6 +1,8 @@
from abc import ABC, abstractmethod
from git_flow import SUPPORTED_REMOTE_APIS, GitFlowError
import giturlparse
from git_flow import SUPPORTED_REMOTE_URL_SCHEMAS, GitFlowError
from git_flow.git import Git
@@ -11,25 +13,42 @@ class RemoteAPI(ABC):
@staticmethod
def parse(remote: str):
"""Soportamos 3 tipos de URL: http, https y ssh. Si no se especifica el esquema, asumimos ssh:
Ejemplos:
- http://gitea/user/repo
- https://gitea.com/user/repo.git
- git@bitbucket.org:user/repo
- git.mygiteainstance.com:user/repo.git
- ssh://git@git.mygiteainstance.com:1234/user/repo.git
"""
url = Git("remote", "get-url", remote).firstline()
if url.startswith("git@"):
at_pos = url.index("@")
colon_pos = url.index(":")
schema = "ssh://"
host = url[at_pos+1:colon_pos]
repository = url[colon_pos+1:]
elif url.startswith("http://") or url.startswith("https://"):
start_pos = url.index("://") + 3
uri_start = url.index("/", start_pos)
schema = url[:start_pos]
host = url[start_pos:uri_start]
repository = url[uri_start+1:]
else:
parsed_url = giturlparse.parse(url) # Validamos que la URL sea válida
if not parsed_url.valid:
raise GitFlowError(f"La URL del remoto {remote} es inválida: {url}")
repository = repository.removesuffix(".git")
return [schema, host, repository]
if not parsed_url.protocol in SUPPORTED_REMOTE_URL_SCHEMAS:
raise GitFlowError(
f"La URL del remoto {remote} no tiene un esquema soportado: {url}"
)
# Cuando el host es seteado por pipeline puede ser "http://gitea/OWNER/REPO", en ese caso
# la libreria parsea OWNER="" y REPO="OWNER/REPO"
# En GitLab, los proyectos pueden estar dentro de grupos y subgrupos (ej:
# owner/grupo/subgrupo/repo), que la libreria expone por separado en groups_path
repository = (
"/".join(
filter(
None,
[parsed_url.owner, parsed_url.groups_path, parsed_url.repo],
)
)
.removeprefix("/")
.removesuffix(".git")
)
return [parsed_url.protocol + "://", parsed_url.host, repository]
@abstractmethod
def create_pull_request(
@@ -38,7 +57,7 @@ class RemoteAPI(ABC):
destination: str,
title: str | None = None,
description: str | None = None,
close_source_branch: bool = True
close_source_branch: bool = True,
) -> str:
pass
+59
View File
@@ -0,0 +1,59 @@
from urllib.parse import quote
import requests
from git_flow import GitFlowError
from git_flow.remote.base import RemoteAPI
class GitlabRemoteAPI(RemoteAPI):
def __init__(self, base_url: str, repository: str, token: str) -> None:
super().__init__(repository, token)
self.base_url = base_url
def create_pull_request(
self,
source: str,
destination: str,
title: str | None = None,
description: str | None = None,
close_source_branch: bool = True
) -> str:
response = requests.post(
self.get_endpoint("/merge_requests"),
headers=self.get_headers(),
json={
"title": title,
"description": description,
"source_branch": source,
"target_branch": destination,
"remove_source_branch": close_source_branch,
},
)
if response.ok:
return "PR creado exitosamente: " + response.json()["web_url"]
else:
raise GitFlowError("Ocurrió un error al crear el PR: " + response.text)
def create_tag(self, tag: str, commit: str) -> str:
response = requests.post(
self.get_endpoint("/repository/tags"),
headers=self.get_headers(),
json={"tag_name": tag, "ref": commit},
)
if response.ok:
return "Tag creado exitosamente: " + tag
else:
raise GitFlowError("Ocurrió un error al crear el tag: " + response.text)
def get_endpoint(self, resource: str) -> str:
project_id = quote(self.repository, safe="")
return f"{self.base_url}/api/v4/projects/{project_id}{resource}"
def get_headers(self):
return {
"Accept": "application/json",
"Content-Type": "application/json",
"PRIVATE-TOKEN": self.token,
}
Generated
+11
View File
@@ -70,6 +70,7 @@ wheels = [
name = "git-flow-envs"
source = { editable = "." }
dependencies = [
{ name = "giturlparse" },
{ name = "questionary" },
{ name = "requests" },
{ name = "rich" },
@@ -78,12 +79,22 @@ dependencies = [
[package.metadata]
requires-dist = [
{ name = "giturlparse" },
{ name = "questionary" },
{ name = "requests" },
{ name = "rich" },
{ name = "typer" },
]
[[package]]
name = "giturlparse"
version = "0.15.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/8c/8a/b70b84cc78f9059d627f09560c81a11e8f046570d220a24e169489cad6c9/giturlparse-0.15.0.tar.gz", hash = "sha256:9af3f1fd5c4a0cac94ddb283593635005646393ee0debbe330d1bdff8866bf2c", size = 16138, upload-time = "2026-06-16T07:28:56.021Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/96/147a2771ab655b9353781fb2f95c94eaf1d8576dccc991c1a61d0d355067/giturlparse-0.15.0-py2.py3-none-any.whl", hash = "sha256:76d2e6983b037356ab99b30683e533ac3db96409b68e2163a20fc3aff6446f10", size = 16683, upload-time = "2026-06-16T07:28:55.184Z" },
]
[[package]]
name = "idna"
version = "3.11"