Skip to content

Instantly share code, notes, and snippets.

@SyNeto
Created September 11, 2025 03:17
Show Gist options
  • Select an option

  • Save SyNeto/5b68471b63b3141f70ee1590ab5dc75b to your computer and use it in GitHub Desktop.

Select an option

Save SyNeto/5b68471b63b3141f70ee1590ab5dc75b to your computer and use it in GitHub Desktop.
Gistly: Flujos de Actualización de Gists - Discovery Document

Gist Update Flows - Discovery Document

Este documento define los flujos de actualización de gists para la funcionalidad gist update propuesta para Gistly.

Tabla de Contenidos

Resumen Ejecutivo

La funcionalidad gist update permitirá modificar gists existentes, agregando, actualizando o eliminando archivos. GitHub Gists maneja automáticamente el versionado, creando una nueva revisión en el historial cada vez que se actualiza.

Comando Propuesto

gist update GIST_ID [FILES...] [OPTIONS]

API de GitHub Gists

Endpoint de Actualización

PATCH /gists/{gist_id}
Authorization: token {github_token}
Content-Type: application/json

{
  "description": "Nueva descripción (opcional)",
  "files": {
    "archivo1.py": {
      "content": "nuevo contenido"
    },
    "archivo2.md": {
      "filename": "nuevo_nombre.md",
      "content": "contenido actualizado"
    },
    "archivo_a_borrar.txt": null
  }
}

Comportamiento del API

  1. Archivos no mencionados: Permanecen sin cambios
  2. Archivos nuevos: Se agregan al gist
  3. Archivos existentes: Se actualizan con nuevo contenido
  4. Archivos con null: Se eliminan del gist
  5. Versionado: GitHub crea automáticamente una nueva revisión

Escenarios de Actualización

Escenario 1: Agregar Archivo Nuevo

graph TD
    A[gist update abc123 nuevo_archivo.py] --> B{¿Archivo existe en gist?}
    B -->|No| C[Agregar archivo al gist]
    C --> D[Crear nueva revisión]
    D --> E[Gist actualizado]
Loading

Ejemplo:

# Gist actual: [main.py, README.md]
gist update abc123def456 utils.py

# Resultado: [main.py, README.md, utils.py]
# Nueva revisión creada automáticamente

Escenario 2: Actualizar Archivo Existente

graph TD
    A[gist update abc123 main.py] --> B{¿Archivo existe en gist?}
    B -->|Sí| C[Comparar contenido]
    C --> D{¿Contenido diferente?}
    D -->|Sí| E[Actualizar archivo]
    D -->|No| F[Sin cambios]
    E --> G[Crear nueva revisión]
    F --> H[Gist sin modificar]
Loading

Ejemplo:

# Gist actual: [main.py, README.md]
gist update abc123def456 main.py  # main.py modificado localmente

# Resultado: [main.py (nueva versión), README.md]
# Nueva revisión creada

Escenario 3: Múltiples Archivos (Mixto)

graph TD
    A[gist update abc123 main.py utils.py config.json] --> B[Analizar cada archivo]
    B --> C[main.py: Existe - Actualizar]
    B --> D[utils.py: No existe - Agregar]
    B --> E[config.json: Existe - Actualizar]
    C --> F[Construir payload API]
    D --> F
    E --> F
    F --> G[Enviar PATCH request]
    G --> H[Nueva revisión con todos los cambios]
Loading

Ejemplo:

# Gist actual: [main.py, README.md]
gist update abc123def456 main.py utils.py helpers.py

# Análisis:
# - main.py: existe → actualizar
# - utils.py: no existe → agregar
# - helpers.py: no existe → agregar

# Resultado: [main.py (actualizado), README.md, utils.py (nuevo), helpers.py (nuevo)]

Flujos Detallados

Flujo Principal de Actualización

sequenceDiagram
    participant Usuario
    participant CLI
    participant GistManager
    participant GitHub API
    participant LocalFiles

    Usuario->>CLI: gist update abc123 file1.py file2.md
    CLI->>GistManager: update_gist(gist_id, files)
    
    Note over GistManager: Validación inicial
    GistManager->>GitHub API: GET /gists/{gist_id}
    GitHub API-->>GistManager: Gist actual + metadatos
    
    Note over GistManager: Procesamiento de archivos
    loop Para cada archivo local
        GistManager->>LocalFiles: Leer contenido
        LocalFiles-->>GistManager: Contenido del archivo
        
        alt Archivo existe en gist
            Note over GistManager: Comparar contenido
            alt Contenido diferente
                Note over GistManager: Marcar para actualización
            else Contenido igual
                Note over GistManager: Skip (sin cambios)
            end
        else Archivo no existe
            Note over GistManager: Marcar para adición
        end
    end
    
    Note over GistManager: Construir payload
    GistManager->>GitHub API: PATCH /gists/{gist_id}
    GitHub API-->>GistManager: Gist actualizado
    GistManager-->>CLI: Resultado
    CLI-->>Usuario: Confirmación + URL
Loading

Flujo de Validaciones

graph TD
    A[Iniciar update] --> B{¿Gist ID válido?}
    B -->|No| C[Error: Gist no encontrado]
    B -->|Sí| D{¿Token tiene permisos?}
    D -->|No| E[Error: Sin permisos]
    D -->|Sí| F{¿Archivos locales existen?}
    F -->|No| G[Error: Archivo no encontrado]
    F -->|Sí| H{¿Al menos un cambio?}
    H -->|No| I[Warning: Sin cambios]
    H -->|Sí| J[Proceder con update]
    
    C --> Z[Salir con error]
    E --> Z
    G --> Z
    I --> Y[Salir sin cambios]
    J --> K[Update exitoso]
Loading

Casos Edge y Validaciones

Casos Especiales

1. Archivo con mismo contenido

# Si el archivo local tiene el mismo contenido que en el gist
gist update abc123 main.py  # Sin cambios reales

# Comportamiento: 
# - Detectar que no hay cambios
# - Mostrar warning: "No changes detected for main.py"
# - No hacer request al API si no hay cambios en ningún archivo

2. Gist con archivos que no están localmente

# Gist actual: [main.py, README.md, config.json]
gist update abc123 main.py  # Solo actualizar main.py

# Comportamiento:
# - README.md y config.json permanecen sin cambios
# - Solo main.py se actualiza
# - Otros archivos no se tocan

3. Archivos con nombres problemáticos

# GitHub no permite archivos que empiecen con "gistfile"
gist update abc123 gistfile1.txt

# Comportamiento:
# - Validar nombre antes de enviar
# - Error: "Invalid filename: 'gistfile1.txt'. Filenames cannot start with 'gistfile'"

Validaciones Requeridas

graph LR
    A[Archivo local] --> B{Existe localmente?}
    B -->|No| C[Error: File not found]
    B -->|Sí| D{Nombre válido?}
    D -->|No| E[Error: Invalid filename]
    D -->|Sí| F{Es archivo de texto?}
    F -->|No| G[Error: Binary files not supported]
    F -->|Sí| H{Tamaño < 1MB?}
    H -->|No| I[Error: File too large]
    H -->|Sí| J[Archivo válido]
Loading

Propuesta de Implementación

1. Estructura del Comando CLI

@main.command()
@click.argument('gist_id', required=True)
@click.argument('files', nargs=-1, type=click.Path(exists=True))
@click.option('--description', '-d', help='Update gist description')
@click.option('--add', multiple=True, type=click.Path(exists=True), 
              help='Explicitly add new files')
@click.option('--remove', multiple=True, 
              help='Remove files from gist (by filename)')
@click.option('--dry-run', is_flag=True, 
              help='Show what would be changed without making changes')
@click.option('--force', is_flag=True, 
              help='Skip confirmation prompts')
def update(gist_id, files, description, add, remove, dry_run, force):
    """Update an existing gist
    
    GIST_ID: The ID or URL of the gist to update
    FILES: Local files to add or update in the gist
    
    Examples:
    
        gist update abc123def456 main.py utils.py
        gist update abc123def456 --add new_file.py --remove old_file.py
        gist update abc123def456 --description "Updated version"
        gist update abc123def456 *.py --dry-run
    """

2. Método Core en GistManager

def update_gist(self, gist_id: str, files: Dict[str, str] = None, 
                description: str = None, files_to_remove: List[str] = None) -> Dict:
    """
    Update an existing gist
    
    Args:
        gist_id: GitHub gist ID
        files: Dict of filename -> content for files to add/update
        description: New description (optional)
        files_to_remove: List of filenames to remove from gist
        
    Returns:
        Dict: Updated gist information
        
    Raises:
        Exception: If gist not found, permission denied, or update fails
    """

3. Flujo de Procesamiento

def _prepare_update_payload(self, current_gist: Dict, 
                          new_files: Dict[str, str],
                          files_to_remove: List[str],
                          description: str = None) -> Dict:
    """
    Prepare the payload for PATCH request
    
    Logic:
    1. Start with empty files dict
    2. For each new file:
       - If exists in gist and content different: add to update
       - If not exists in gist: add as new
       - If exists and content same: skip
    3. For each file to remove: set to null
    4. Only include files that have changes
    """

4. Casos de Uso Extendidos

# Casos básicos
gist update abc123 main.py                    # Actualizar un archivo
gist update abc123 main.py utils.py          # Actualizar múltiples archivos
gist update abc123 --description "New desc"  # Solo cambiar descripción

# Casos avanzados
gist update abc123 *.py --dry-run            # Preview de cambios
gist update abc123 --add new.py --remove old.py  # Operaciones explícitas
gist update abc123 main.py --force          # Sin confirmación

# Con URL en lugar de ID
gist update https://gist.github.com/user/abc123def456 main.py

5. Output Esperado

$ gist update abc123def456 main.py utils.py config.json

Analyzing gist abc123def456...
✓ Gist found: "My Python Project" (3 files)

Changes to be made:
  📝 main.py (modified)
  ➕ utils.py (new file)
  📝 config.json (modified)

Continue with update? [y/N]: y

Updating gist...
✅ Gist updated successfully!

🔗 URL: https://gist.github.com/user/abc123def456
📊 Revision: 4 → 5 (new revision created)
📁 Files: 3 → 4 files total

Beneficios de esta Implementación

  1. Intuitivo: El comportamiento es predecible y lógico
  2. Eficiente: Solo envía cambios reales al API
  3. Seguro: Validaciones extensas antes de modificar
  4. Flexible: Soporte para múltiples casos de uso
  5. Versionado automático: GitHub maneja las revisiones transparentemente

Próximos Pasos

  1. Implementar get_gist() para obtener gist actual
  2. Implementar update_gist() con lógica de comparación
  3. Agregar comando CLI update
  4. Crear tests comprehensivos para todos los escenarios
  5. Documentar casos edge y limitaciones

Este documento será actualizado conforme se implementen y validen los flujos descritos.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment