Cuando forkeé winfunc/opcode para armar opcode-lucho, di por hecho
que la parte aburrida ya estaba resuelta: el repo traía 5 workflows de GitHub Actions
(pr-check.yml, build-test.yml, build-linux.yml, build-macos.yml, release.yml), así que asumí que
solo tenía que empezar a abrir PRs y dejar que los checks hicieran su trabajo.
pr-check.yml falló en todos y cada uno de mis primeros PRs. Ninguna de las dos causas tenía que ver con mi
código.
Causa uno: dependencias de sistema que nunca se instalaban
El error era Package glib-2.0 was not found in the pkg-config search path. Tauri necesita dependencias de
sistema en Linux para compilar, y pr-check.yml nunca las instalaba en ubuntu-latest antes de correr
cargo check. La lista correcta de dependencias ya existía en build-test.yml, en el mismo repo —
simplemente nunca se había portado al workflow que corre en cada PR.
Causa dos: cargo check necesita un dist/index.html que tsc nunca genera
Con las dependencias de sistema resueltas, pr-check seguía en rojo. El script que corría era
bun run check, que en este repo significa tsc --noEmit && cargo check. El problema está en
web_server.rs: usa include_str! para embeber dist/index.html en el binario vía generate_context! de
Tauri. Ese archivo no existe hasta que se compila el frontend — y tsc --noEmit hace exactamente lo que
dice: tipa, pero no emite nada. cargo check fallaba buscando un archivo que nadie había construido todavía.
La solución fue correr bun run build antes de cargo check en el workflow, no después ni en paralelo.
Un tercer hallazgo, mientras arreglaba los dos anteriores
build-test.yml — el workflow que compila la app en las tres plataformas — nunca había corrido siquiera:
apuntaba a las ramas main/develop, que no existen en este fork (acá el flujo es rama por tarea → PR →
dev → master). No era un bug de configuración fina, era un workflow completo apuntando al vacío.
Con las dos causas de pr-check resueltas y las ramas de build-test corregidas, hoy pr-check pasa en
7m51s y build-test compila las tres plataformas sin intervención.
Lo que esto destapó: los checks en rojo no bloqueaban nada
Mientras investigaba por qué la CI nunca había estado en verde encontré algo peor: como no había protección de ramas, un PR se había mergeado alguna vez con los checks en rojo. La CI podía fallar todo lo que quisiera, que nada se lo impedía a nadie.
Puse rulesets en master y dev sin bypass para nadie, ni siquiera para mí como admin: exigen PR abierto y
el check bun run check en verde antes de poder mergear, y bloquean el force-push y el borrado de rama.
Probé que funcionaba empujando directo a master: lo rechazó con GH013.
Ahí apareció la vuelta de tuerca que no esperaba: los rulesets de protección no existen en GitHub Free para repos privados. El repo todavía estaba marcado como privado en ese momento, y la API respondía 403 con un mensaje directo: “Upgrade to GitHub Pro or make this repository public.” No hay forma de proteger una rama en un repo privado sin pagar. El orden quedó forzado al revés de lo que hubiera elegido a priori: primero hacer público el repo, recién después poder cerrar el agujero de la protección.
Forkear un codebase grande no es solo heredar código: es heredar también su infraestructura, con todas sus roturas silenciosas incluidas. Nadie te avisa — lo descubrís abriendo el primer PR.