Lineamientos de desarrollo para este repositorio. Son de cumplimiento obligatorio
para cualquier cambio que entre a main.
Usamos un GitFlow simplificado, sin rama develop:
maines la única rama base y protegida. Nunca se hace commit ni push directo amain.- Todo cambio se desarrolla en una rama corta creada a partir de
main. - Todo cambio entra a
mainexclusivamente vía Pull Request, con code review antes de mergear. GitHub no exige approval de terceros (equipo pequeño / maintainer único), pero el PR y la resolución de hilos del review sí son obligatorios. - La rama se elimina después de mergear.
git switch main
git pull --ff-only
git switch -c feature/mi-cambio # crear rama desde main
# ... trabajo + commits ...
git push -u origin feature/mi-cambio
gh pr create # abre el PR usando el template del repoPara llevar varias features a la vez no uses
git switch: cada una va en su propio worktree, con su dev-server y sus puertos. Ver §8.
2. Nombres de rama — Conventional Branch
Formato: <tipo>/<descripción-en-kebab-case>. Solo minúsculas, números y guiones
(sin guiones al inicio/fin ni consecutivos). Opcionalmente incluye el issue.
| Prefijo | Uso |
|---|---|
feature/ |
nueva funcionalidad |
bugfix/ |
corrección de bug (no urgente) |
hotfix/ |
corrección urgente en producción |
release/ |
preparación de una versión |
chore/ |
tooling, dependencias, configuración |
docs/ |
solo documentación |
test/ |
solo pruebas |
Ejemplos: feature/exportar-malla-xlsx, bugfix/slug-duplicado, feature/issue-42-login-microsoft.
3. Mensajes de commit — Conventional Commits 1.0.0
Formato:
<tipo>[scope opcional]: <descripción en imperativo, minúscula>
[cuerpo opcional]
[footer(s) opcional(es)]
Tipos: feat, fix, refactor, perf, style, docs, test, build, ci, chore.
feat:→ incrementa MINORfix:→ incrementa PATCH- Breaking change → incrementa MAJOR: agrega
!tras el tipo/scope (feat(api)!: ...) o un footerBREAKING CHANGE: <descripción>.
Ejemplos:
feat(docs): sirve el Docusaurus en /docs/ en vez de /docs/docs/
fix(paginas): evita slug duplicado al actualizar
chore(deps): actualiza @docusaurus/* a 3.9.2
refactor(api)!: renombra el endpoint de páginas públicas
BREAKING CHANGE: /paginas ahora responde bajo /public/paginas
El scope sugerido corresponde al paquete o área: web, api, docs, calendario,
labs, avances, paginas, deps, etc.
4. Versionado y changelog — SemVer 2.0.0
Las versiones son MAJOR.MINOR.PATCH y se derivan de los commits (ver arriba).
- Se registran en
CHANGELOG.mdsiguiendo el estilo Keep a Changelog. - Cada release se etiqueta con un tag
vX.Y.Zenmain. - Acumula los cambios visibles bajo
## [Unreleased]mientras se desarrolla; al liberar, muévelos a una sección con la versión y la fecha.
El code review se realiza una vez finalizada la rama, antes de mergear (no durante).
-
Nada de comentarios generales. Selecciona la porción específica del código y deja el comentario inline sobre esa línea/rango.
-
Cada comentario sigue Conventional Comments:
<label> [decoración]: <mensaje>Labels:
praise,nitpick,suggestion,issue,todo,question,thought,chore,note. Decoraciones:(blocking),(non-blocking),(if-minor).Ejemplos:
suggestion (non-blocking): extrae esto a un helper reutilizableissue (blocking): este slug puede colisionar; falta validar unicidadquestion: ¿por qué useMasterKey aquí?
-
Resolver dentro del mismo PR. Atiende el máximo posible de comentarios en el propio PR; una vez atendido cada hilo, se resuelve/cierra (no se dejan hilos abiertos).
-
Se mergea solo cuando: se hizo el code review, no quedan hilos sin resolver (GitHub lo bloquea vía required conversation resolution), y CI/tests pasan. No se exige approval formal de terceros mientras haya un único maintainer.
Autenticación: si
ghvive detrás de 1Password, resuelve el token una vez:export GH_TOKEN="$(gh auth token)".
# Comentario inline sobre una línea específica de un archivo del PR
gh api repos/{owner}/{repo}/pulls/{number}/comments \
-f body='suggestion (non-blocking): extrae a un helper' \
-f commit_id="$(gh pr view {number} --json headRefOid -q .headRefOid)" \
-f path='packages/api/src/controllers/paginas.controller.ts' \
-F line=42 -f side=RIGHT
# Resolver un hilo de review (GraphQL) una vez atendido
gh api graphql -f query='mutation($id:ID!){resolveReviewThread(input:{threadId:$id}){thread{isResolved}}}' \
-f id='<THREAD_ID>'En este repo también existe el comando /code-review --comment, que publica los
hallazgos como comentarios inline del PR automáticamente.
- El título del PR sigue Conventional Commits (igual que los commits).
- La descripción usa el PR template del repo.
- Enlaza los issues que cierra (
Closes #123). - Un PR = un cambio coherente. Evita PRs que mezclan features no relacionadas.
yarn test # pruebas (Vitest) — desde la RAÍZ del repo
cd packages/web && npx tsc --noEmit # type-check del web
yarn build # build completo si afecta el outputCuando hay más de un frente vivo (dos US, una feature y un hotfix, un PR en
review mientras empiezas el siguiente), cada uno va en su propio git worktree:
una copia física del árbol de trabajo en otra carpeta, compartiendo el mismo
.git. No es un git clone — el historial no se duplica.
Lo que aporta es simultaneidad: varias copias abiertas a la vez, cada una con
su yarn dev, sin git stash ni cambiar de rama a media tarea. Si solo trabajas
una cosa, una rama normal basta.
| # | Paso | Comando |
|---|---|---|
| 1 | Crear worktree + rama desde main al día |
wt new feature/mi-cambio |
| 2 | Levantar el dev-server del worktree | yarn dev (dentro) o wt dev feature/mi-cambio |
| 3 | Trabajar y commitear (Conventional Commits) | git commit |
| 4 | Pruebas manuales sobre ESE servidor, y correcciones | — |
| 5 | Verificación de §7 y push | git push -u origin feature/mi-cambio |
| 6 | Abrir PR con el template | gh pr create |
| 7 | Code review de §5 y resolución de hilos | — |
| 8 | Merge del PR | gh pr merge |
| 9 | Cerrar worktree, borrar rama y sincronizar | wt done feature/mi-cambio + git pull en el principal |
El worktree no se cierra antes del merge: los pasos 4 y 7 pueden devolverte a
él para correcciones. wt done se niega a borrar una rama sin mergear, y solo
tira la carpeta si no hay cambios sin guardar (--force para forzar).
Vive en tools/wt.zsh. Instalación, una vez:
echo 'source ~/ITESM/TC2005B/Calendario/tc2005b.github.io/tools/wt.zsh' >> ~/.zshrcwt new <spec> [--base <ref>] [--no-install] # worktree + rama + bootstrap + cd
wt ls # worktrees vivos y su puerto web
wt cd <spec> | wt path <spec> # navegar
wt dev <spec> # yarn dev en ese worktree
wt done <spec> [--force] # cerrar y borrar la ramaEl <spec> es el nombre de la rama. Sin prefijo de Conventional Branch se asume
feature/. Los worktrees se crean fuera del repo, en ../.worktrees/<spec>,
para que Vite y tsc no vean una copia del árbol dentro del árbol.
Si la rama ya existe, wt new la adopta en vez de crearla — sirve para
retomar una rama, revisar el PR de otro, o mover a un worktree trabajo que empezó
en el checkout principal. Como una rama solo puede estar checkouteada en un sitio
a la vez, primero hay que salir de ella (git switch main).
Lo que git ignora (node_modules, .env) no se copia al worktree; de eso se
encarga el bootstrap de wt new, que además le asigna un par de puertos propio:
- Busca el primer desplazamiento libre sobre los del checkout principal
(web
5173, api3006) → el primer worktree usa5174/3007, el segundo5175/3008, etc. - "Libre" es ni escuchando ahora ni reservado por otro worktree: se leen los
.env.localde todos, así que dos worktrees creados en frío tampoco chocan. - Escribe
packages/api/.env(conPORTySERVER_URLreescritos) ypackages/web/.env.local(VITE_PORT,VITE_API_PORT, quevite.config.tslee para el server y el proxy).
Por eso dentro de un worktree basta yarn dev: los puertos ya están en su sitio.
El dev-server usa strictPort, así que si un puerto estuviera tomado falla en
vez de saltar al siguiente y quedarse proxeando al API de otra rama.
⚠️ Todos los worktrees comparten la BD de PRODUCCIÓN, igual que el checkout principal (verCLAUDE.md). Aislar el puerto no aísla los datos: las pruebas manuales de un worktree escriben en la misma base que las de otro.