Enumeración y gestión de incidencias
Obtenga, cree, etiquete y cierre incidencias mediante programación.
Enumeración y gestión de incidencias es una lección gratuita de AI Agents en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Agents, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Agents incluye 4 lecciones en total.
Obtener incidencias de un repositorio
Utilice repo.get_issues() para enumerar las incidencias. De forma predeterminada, devuelve las incidencias abiertas; pase state='closed' o state='all' para obtener otros estados. El resultado es un PaginatedList; recórralo para procesar cada incidencia.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Open issues (default)
open_issues = repo.get_issues(state='open')
print(f'Open issues: {open_issues.totalCount}')
# Process first 20
for issue in open_issues[:20]:
print(f'#{issue.number}: {issue.title}')
print(f' Labels: {[l.name for l in issue.labels]}')
print(f' Assignee: {issue.assignee.login if issue.assignee else None}')
print(f' Created: {issue.created_at.date()}')Filtrar incidencias
get_issues() admite varios parámetros de filtrado: state, labels, assignee, milestone, since y sort. Combínelos para obtener exactamente las incidencias que su agente debe procesar.
import datetime
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Issues with the 'bug' label, sorted by newest
bug_issues = repo.get_issues(
state='open',
labels=['bug'],
sort='created',
direction='desc'
)
# Issues updated in the last 7 days
cutoff = datetime.datetime.now() - datetime.timedelta(days=7)
recent_issues = repo.get_issues(
state='open',
since=cutoff
)
# Issues assigned to a specific user
my_issues = repo.get_issues(
state='open',
assignee='username'
)
print(f'Bug issues: {bug_issues.totalCount}')
print(f'Recent issues: {recent_issues.totalCount}')Acceder a las propiedades de una incidencia
Cada objeto Issue tiene propiedades detalladas: número, título, cuerpo, etiquetas, personas asignadas, hito, estado, número de comentarios y marcas de tiempo. Acceda a ellas como atributos de Python. El cuerpo es texto Markdown sin procesar.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
issue = repo.get_issue(42) # get by number
print(f'Number: #{issue.number}')
print(f'Title: {issue.title}')
print(f'State: {issue.state}') # 'open' or 'closed'
print(f'Author: {issue.user.login}')
print(f'Body length: {len(issue.body or "")}')
print(f'Labels: {[l.name for l in issue.labels]}')
print(f'Assignees: {[a.login for a in issue.assignees]}')
print(f'Milestone: {issue.milestone.title if issue.milestone else None}')
print(f'Comments: {issue.comments}')
print(f'Reactions: {issue.get_reactions().totalCount}')
print(f'URL: {issue.html_url}')Crear incidencias nuevas
Utilice repo.create_issue() para crear una incidencia nueva mediante programación. El único campo obligatorio es title. Añada body (Markdown), labels (deben existir previamente), assignees (nombres de usuario de GitHub) y milestone (objeto de hito).
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# Create a bug report
bug_body = (
'## Bug Report\n\n'
'**Observed:** Login fails with 500 error\n'
'**Expected:** Successful login\n'
'**Steps to reproduce:**\n'
'1. Navigate to /login\n'
'2. Enter valid credentials\n'
'3. Click Submit\n\n'
'**Environment:** Production, v2.3.1'
)
issue = repo.create_issue(
title='Login endpoint returns 500 for valid credentials',
body=bug_body,
labels=['bug', 'priority:high'],
assignees=['alice'], # must be repo collaborators
)
print(f'Created issue #{issue.number}: {issue.html_url}')Editar (actualizar) incidencias
Utilice issue.edit() para actualizar cualquier propiedad de una incidencia existente. Puede cambiar el título, el cuerpo, el estado, las etiquetas, las personas asignadas o el hito en una sola llamada. Pase únicamente los campos que desea cambiar; los demás se conservarán.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
issue = repo.get_issue(42)
# Update title and add new labels
issue.edit(
title='[URGENT] Login endpoint returns 500',
labels=['bug', 'priority:critical', 'needs-hotfix']
)
# Close the issue
issue.edit(state='closed')
print(f'Issue #{issue.number} closed')
# Reopen it
issue.edit(state='open')
# Assign to a user
from github import NamedUser
issue.edit(assignees=['bob', 'carol'])
# Update the body
issue.edit(body=issue.body + '\n\n**Update:** Hotfix deployed to production.')Gestionar etiquetas
Las etiquetas organizan las incidencias. Obtenga todas las etiquetas del repositorio con repo.get_labels(), cree otras nuevas con repo.create_label() y añada o quite etiquetas de una incidencia con issue.add_to_labels() e issue.remove_from_labels().
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
# List all labels
for label in repo.get_labels():
print(f'{label.name}: #{label.color}')
# Create a new label if it doesn't exist
existing_names = {l.name for l in repo.get_labels()}
if 'agent-reviewed' not in existing_names:
repo.create_label(
name='agent-reviewed',
color='0075ca', # hex without #
description='Reviewed by AI agent'
)
print('Created label: agent-reviewed')
# Add a label to an issue
issue = repo.get_issue(42)
issue.add_to_labels('agent-reviewed')
# Remove a label
issue.remove_from_labels('needs-triage')Leer los comentarios de una incidencia
Utilice issue.get_comments() para recuperar todos los comentarios de una incidencia. Cada comentario tiene un autor (user.login), texto y marcas de tiempo. Recórralos en orden para ver el historial de la conversación.
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
issue = repo.get_issue(42)
# Get all comments
comments = list(issue.get_comments())
print(f'Comments on #{issue.number}: {len(comments)}')
for comment in comments:
print(f'\n{comment.user.login} ({comment.created_at.date()}):')
print(comment.body[:200])
# Get only recent comments
for comment in issue.get_comments(since=cutoff):
print(f'Recent: {comment.user.login}: {comment.body[:100]}')Añadir comentarios a las incidencias
Utilice issue.create_comment(body) para publicar un comentario. El cuerpo admite Markdown. Los comentarios del agente deben identificarse claramente como automatizados; incluya el encabezado «🤖 Análisis automatizado» para establecer las expectativas.
from github import Github
import os
import datetime
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
issue = repo.get_issue(42)
# Add an agent comment with clear attribution
agent_comment = (
'**Automated Analysis** (via code-review agent)\n\n'
'---\n'
f'**Issue classified as:** Critical Bug\n'
f'**Suggested priority:** P0\n'
f'**Suggested assignee:** @backend-team\n\n'
'**Analysis:**\n'
'The login 500 error matches pattern #12 in our known issues database.\n'
'Likely cause: database connection pool exhaustion during peak traffic.\n\n'
'**Suggested fix:** Increase pool size in `db_config.py` or add circuit breaker.\n\n'
f'_Generated at {datetime.datetime.now().strftime("%Y-%m-%d %H:%M UTC")}_'
)
comment = issue.create_comment(agent_comment)
print(f'Comment added: {comment.html_url}')Agente de triaje masivo de incidencias
Un agente de triaje procesa automáticamente las incidencias nuevas: lee el título y el cuerpo, las clasifica mediante un LLM, añade las etiquetas correspondientes, las asigna al equipo adecuado y publica un comentario inicial. Esto ahorra a los ingenieros horas de trabajo manual de triaje.
import anthropic
import json
import os
from github import Github
g = Github(token=os.environ['GITHUB_TOKEN'])
client = anthropic.Anthropic(api_key=os.environ['ANTHROPIC_API_KEY'])
def triage_issue(repo, issue):
prompt = (
'Classify this GitHub issue. Return JSON only:\n'
'{"type": "bug|feature|question|docs", '
'"priority": "critical|high|medium|low", '
'"team": "backend|frontend|infra|ml", '
'"summary": "one sentence"}\n\n'
f'Title: {issue.title}\n'
f'Body: {(issue.body or "")[:1000]}'
)
response = client.messages.create(
model='claude-opus-4-5',
max_tokens=200,
messages=[{'role': 'user', 'content': prompt}]
)
try:
return json.loads(response.content[0].text)
except json.JSONDecodeError:
return {'type': 'question', 'priority': 'medium', 'team': 'backend', 'summary': 'Needs manual review'}Aplicar los resultados del triaje a las incidencias
Aplique a la incidencia la clasificación del triaje del LLM: establezca las etiquetas según el tipo y la prioridad, asígnela al responsable adecuado del equipo y publique un comentario de triaje. Lleve un registro de las incidencias que ya se han sometido a triaje mediante una etiqueta personalizada para evitar procesarlas de nuevo.
TEAM_ASSIGNEES = {
'backend': 'alice',
'frontend': 'bob',
'infra': 'carol',
'ml': 'dave'
}
def apply_triage(repo, issue, classification):
issue_type = classification.get('type', 'question')
priority = classification.get('priority', 'medium')
team = classification.get('team', 'backend')
summary = classification.get('summary', '')
# Apply labels
labels_to_add = [f'type:{issue_type}', f'priority:{priority}', 'agent-triaged']
issue.edit(labels=labels_to_add)
# Assign to team lead
assignee = TEAM_ASSIGNEES.get(team, 'alice')
issue.edit(assignees=[assignee])
# Post triage comment
comment = (
f'**Automated Triage**\n\n'
f'Type: `{issue_type}` | Priority: `{priority}` | Team: `{team}`\n'
f'Summary: {summary}\n\n'
f'Assigned to @{assignee} for follow-up.'
)
issue.create_comment(comment)
print(f'Triaged #{issue.number}: {issue_type}/{priority} -> {assignee}')
# --- demo: minimal stand-in for a GitHub Issue object ---
class _FakeIssue:
number = 501
def edit(self, **kwargs):
print(f'[github] issue.edit({kwargs})')
def create_comment(self, body):
print(f'[github] comment posted:\n{body}')
classification = {'type': 'bug', 'priority': 'high', 'team': 'backend',
'summary': 'Login fails with 500 when email has a plus sign'}
apply_triage('coddy-agents', _FakeIssue(), classification)
Cerrar automáticamente las incidencias obsoletas
La gestión de incidencias obsoletas es una automatización habitual: busque incidencias abiertas sin actividad durante N días, publique un comentario de advertencia y ciérrelas si no llega ninguna respuesta durante un periodo de gracia. Utilice issue.updated_at para comprobar la actividad y issue.edit(state='closed') para cerrarlas.
import datetime
from github import Github
import os
g = Github(token=os.environ['GITHUB_TOKEN'])
repo = g.get_repo('myorg/myrepo')
STALE_DAYS = 90
GRACE_DAYS = 14
now = datetime.datetime.utcnow()
stale_cutoff = now - datetime.timedelta(days=STALE_DAYS)
for issue in repo.get_issues(state='open'):
last_updated = issue.updated_at.replace(tzinfo=None)
if last_updated > stale_cutoff:
continue
# Check if stale warning already posted
comments = list(issue.get_comments())
stale_warned = any('stale' in c.body.lower() for c in comments)
if not stale_warned:
issue.create_comment(
'This issue has been inactive for 90 days. '
'It will be closed in 14 days unless there is activity.'
)
issue.add_to_labels('stale')
print(f'Stale warning: #{issue.number}')Comprobación rápida: issue.edit() frente a create_issue()
Compruebe su comprensión de la gestión de incidencias de GitHub.
Resumen de la gestión de incidencias
Ahora su agente puede gestionar incidencias de GitHub de principio a fin:
- repo.get_issues(state, labels, assignee, since): filtrar y enumerar incidencias
- repo.get_issue(number): obtener una incidencia específica por número
- repo.create_issue(title, body, labels, assignees): abrir una incidencia nueva
- issue.edit(state, title, labels, assignees): actualizar cualquier campo
- issue.create_comment(body): añadir un comentario Markdown
- repo.create_label() / issue.add_to_labels(): gestionar etiquetas
- Identifique siempre claramente los comentarios del agente para distinguirlos de la actividad humana
- Utilice etiquetas
'agent-triaged'para evitar volver a procesar las incidencias
Preguntas frecuentes
¿La lección «Enumeración y gestión de incidencias» es gratis?
Sí — el texto completo de «Enumeración y gestión de incidencias» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Agents, actualiza a CoddyKit PRO. El curso de AI Agents incluye 4 lecciones en total.
¿Qué aprenderé en «Enumeración y gestión de incidencias»?
Obtenga, cree, etiquete y cierre incidencias mediante programación. Practicas AI Agents con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Agents?
No se requiere experiencia previa. AI Agents en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «Enumeración y gestión de incidencias»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Agents?
Sí. Cada lección de AI Agents incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Introducción a GitHub REST API
- Enumeración y gestión de incidencias
- Comentarios automatizados en revisiones de PR
- Historial de commits y análisis de diferencias