Módulo 4: Secrets Environments And Identity
6. Ambientes de GitHub: `dev` y `prod`
Descripción
Un Environment de GitHub es un tercer mecanismo de control, distinto a todo lo que viste hasta ahora: no protege una credencial (eso ya lo hacen los Secrets, lección 3), y no reemplaza la necesidad de una credencial (eso es lo que hace OIDC, lecciones 4-5) — controla cuándo un job tiene permiso de correr, con una persona real de por medio si así se configura. Esta lección describe el mecanismo completo, con el camino de clics real de Settings → Environments. La parte de aprobación requerida es representativa —act, verificado, ignora por completo esta protección—, pero vas a probar tú mismo, con una corrida real de act, exactamente eso: que el job corre igual, sin esperar a nadie.
Conexión con el módulo
La lección 3 adelantó que un Secret puede vivir dentro de un Environment, con valores distintos para dev y prod. Esta lección construye el mecanismo completo del que esos Secrets forman parte: qué es un Environment, cómo se declara en un job, y su función más importante para el resto de esta guía — el required reviewers que el Módulo 5 va a necesitar cuando apply.yml corra terraform apply contra infraestructura real, no solo contra un plan de revisión.
Analogía: la caja fuerte de dos llaves
Piensa en un Environment con required reviewers como una caja fuerte que necesita dos llaves distintas, giradas a la vez, para abrirse — una persona sola, sin importar cuánto confíe en su propio criterio, físicamente no puede abrirla. El pipeline que quiere correr terraform apply contra prod es la primera llave: ya decidió que quiere actuar. La segunda llave es una persona designada —alguien que no sea quien escribió el cambio, en la configuración más estricta— que tiene que mirar específicamente ese cambio y girar su propia llave para que la puerta se abra. Ninguna de las dos llaves, por sí sola, hace nada.
Qué es un Environment: el camino de clics real
Como los Secrets de la lección 3, esto describe la interfaz real de github.com — configuración de plataforma, no un workflow, así que no hay YAML que act pueda interpretar para esta parte:
github.com/tu-usuario/andes-cargo-infra
└── Settings
└── Environments (menú lateral izquierdo)
└── [New environment]
Name: production
└── Configuration rules
├── Required reviewers
│ └── [+] Agregar personas o equipos
│ (el job se PAUSA aquí hasta que uno de
│ ellos apruebe, desde una notificación real)
├── Wait timer
│ └── minutos de espera obligatoria antes de correr
│ (incluso sin revisor, como salvaguarda de tiempo)
├── Deployment branches
│ └── restringe QUÉ ramas pueden desplegar a este
│ Environment (por ejemplo, solo `main`)
└── Environment secrets (lección 3)
└── valores visibles SOLO para jobs que declaren
este Environment
Un repositorio típico de esta guía tendría dos Environments: dev (sin required reviewers, para iterar rápido) y production (con required reviewers, para que ningún apply contra infraestructura real corra sin que una persona lo confirme activamente).
Cómo se declara en un job
jobs:
terraform-apply:
runs-on: ubuntu-latest
environment: production
steps:
- name: Terraform apply
run: terraform apply -auto-approve -input=false
La línea environment: production es toda la sintaxis que hace falta del lado del YAML — el resto del comportamiento (pausar, notificar a los revisores, esperar su aprobación) vive completamente en la configuración de Settings → Environments de arriba, no en el archivo. Esto es deliberado: el mismo apply.yml, sin cambiar una sola línea, se comporta distinto según cómo esté configurado el Environment al que apunta —sin required reviewers corre inmediatamente; con required reviewers, se pausa—.
La parte representativa, con la cita exacta
act ignora por completo el campo environment: de un job. Esto no es una suposición ni un comportamiento "probablemente así" — está confirmado contra un issue abierto del propio repositorio de act:
nektos/actissue #1714 — "Deployment Environments support" Estado: abierto, etiquetadoconfirmed/not-planned. El reporte original explica: "In GitHub action it is possible to specify an 'environment' key to discriminate between divergent secrets set" — y confirma queact, verificado, no procesa ese campo en absoluto: ni para diferenciar Secrets por ambiente, ni —la consecuencia directa que importa aquí— para aplicar ninguna protección de aprobación. El job corre exactamente igual que sienvironment:no existiera en el YAML.
confirmed/not-planned es la etiqueta más honesta que un mantenedor de código abierto puede poner en un issue: no es un error que alguien vaya a arreglar pronto — es una limitación reconocida, sin intención declarada de resolverla, porque implementar el modelo completo de Environments (incluida la espera de una aprobación humana real, con notificaciones, con una interfaz web) está fuera del propósito de una herramienta que ejecuta workflows localmente, sin ningún backend de usuarios ni notificaciones.
Pruébalo tú mismo: act corriendo un job de production sin pedir nada
Vas a confirmar esto con una corrida real, no solo con la cita de arriba. Sobre andes-cargo-infra/, crea un workflow deliberadamente simple, solo para esta prueba:
.github/workflows/environment-check.yml:
name: environment-check
on: workflow_dispatch
jobs:
deploy-to-production:
runs-on: ubuntu-latest
environment: production
steps:
- name: This step should only run after a human approves the "production" environment
run: echo "Job ran without waiting for any required reviewer."
Si este repositorio existiera en github.com real, con production configurado con al menos un required reviewer, disparar este workflow debería pausar el job en un estado "Waiting" hasta que alguien apruebe desde la interfaz web — el job ni siquiera empezaría a correr. Confírmalo con act:
act workflow_dispatch -j deploy-to-production
Qué esperar (salida literal, ejecutada para escribir esta lección):
[environment-check/deploy-to-production] ⭐ Run Set up job
[environment-check/deploy-to-production] 🚀 Start image=catthehacker/ubuntu:act-latest
[environment-check/deploy-to-production] ✅ Success - Set up job
[environment-check/deploy-to-production] ⭐ Run Main This step should only run after a human approves the "production" environment
[environment-check/deploy-to-production] | Job ran without waiting for any required reviewer.
[environment-check/deploy-to-production] ✅ Success - Main This step should only run after a human approves the "production" environment [55.2065ms]
[environment-check/deploy-to-production] ⭐ Run Complete job
[environment-check/deploy-to-production] ✅ Success - Complete job
[environment-check/deploy-to-production] 🏁 Job succeeded
El comando completo, de principio a fin, tardó 1.6 segundos. No hay ninguna pausa, ningún mensaje "Waiting for approval", ninguna interfaz que consultar — act ni siquiera reconoce que environment: production está declarado en el YAML. Esta es exactamente la confirmación práctica del issue citado arriba: act corre el job como si esa línea no existiera.
Por qué esto no es un defecto de esta guía, sino la frontera declarada
Que act ignore environment: no significa que el mecanismo de aprobación humana sea inútil ni que esta guía no pueda enseñarlo — significa, específicamente, que no se puede demostrar el bloqueo bajo act, solo describirlo con precisión, como hizo esta lección. La distinción importa: el Módulo 5 va a construir apply.yml con environment: production declarado exactamente así, siguiendo el patrón real — el YAML de esa lección va a ser 100% portable a un repositorio real de GitHub, donde sí funcionaría el bloqueo. Lo único que no puedes hacer, dentro de esta guía, es ver ese bloqueo ocurrir con tus propios ojos — para eso, el Módulo 8, lección 5, apunta a la opción (nunca obligatoria) de crear un repositorio real de GitHub.
Errores comunes
Concluir que, como act lo ignora, environment: no sirve para nada en el resto de esta guía (de alcance). Qué pasa: alguien, después de ver que el job corrió sin pausa, decide que declarar environment: production en apply.yml (Módulo 5) es innecesario, ya que "de todas formas act no lo respeta". Cómo detectarlo: si tu razonamiento es "no sirve aquí, así que no lo declaro". Cómo corregirlo: declarar environment: production en apply.yml sigue siendo correcto y necesario, precisamente porque ese mismo archivo es el que correría, sin ningún cambio, en un repositorio real — donde environment: sí bloquearía el job hasta la aprobación. Omitirlo "porque aquí no hace nada" produciría un apply.yml incompleto que fallaría en aplicar el control real el día que se use en producción.
Confundir required reviewers con branches: del disparador (de sintaxis). Qué pasa: alguien intenta lograr el mismo efecto de "solo aplica con revisión" restringiendo on: push: branches: [main], sin declarar ningún environment:. Por qué pasa: ambos mecanismos suenan a "control de qué puede correr". Cómo detectarlo: si tu único control de despliegue es un filtro de rama, sin ninguna aprobación humana explícita en el medio. Cómo corregirlo: branches: (Módulo 2, lección 3) controla qué evento dispara el workflow — no involucra a ninguna persona revisando en el momento. required reviewers de un Environment es un control completamente distinto: pausa el job, ya disparado, hasta que alguien apruebe activamente. El primero es un filtro automático; el segundo es una intervención humana en tiempo real. apply.yml, en el Módulo 5, va a usar ambos a la vez, cada uno resolviendo un problema distinto.
Ejercicios
Ejercicio 1 — Reproduce la prueba con dev en vez de production. Cambia environment: production a environment: dev en environment-check.yml y vuelve a correr act workflow_dispatch -j deploy-to-production. ¿Cambia algo en el comportamiento? ¿Debería, según lo que aprendiste en esta lección?
Ver solución
No debería cambiar nada, y no cambia: act ignora el campo environment: sin importar qué valor tenga —dev, production, o cualquier nombre inventado—, porque simplemente no lo procesa en absoluto (issue #1714). La única diferencia real entre dev y production, en un repositorio real de GitHub, estaría en cómo cada uno esté configurado en Settings → Environments —si dev no tiene required reviewers y production sí—, no en el nombre del Environment en sí mismo.
Ejercicio 2 — Explica la diferencia entre "confirmed" y "not-planned" en la etiqueta del issue. El issue #1714 está etiquetado confirmed/not-planned. Explica, en tus propias palabras, qué comunica cada mitad de esa etiqueta por separado.
Ver solución
confirmed significa que los mantenedores del proyecto reconocen que el comportamiento reportado es real —no es un malentendido del usuario ni algo que ya esté resuelto—. not-planned significa que, reconociendo que es real, no hay intención declarada de implementarlo como una función futura del proyecto. Juntas, las dos etiquetas comunican exactamente el nivel de honestidad que esta lección necesita: no es un bug que vaya a desaparecer en la próxima versión de act, es una limitación de diseño reconocida y permanente, la base sólida para etiquetar esta parte de la guía como representativa con confianza, no como "todavía no verificado".
Ejercicio 3 — Diseña el Environment de prod para Andes Cargo. Sin escribir YAML todavía (eso es el Módulo 5), describe en prosa qué reglas de configuración le pondrías al Environment production de andes-cargo-infra/ si este repositorio fuera real, usando al menos tres de las cuatro reglas mencionadas en el camino de clics de esta lección.
Ver solución
Una configuración razonable: required reviewers con al menos una persona distinta de quien escribió el cambio (para que ningún autor apruebe su propio apply contra producción); deployment branches restringido únicamente a main (para que ninguna rama de feature, ni siquiera por error, pueda disparar un despliegue a producción); y environment secrets con las credenciales reales de la cuenta de producción de Andes Cargo, completamente separadas de las que usaría el Environment dev — de forma que un error en la configuración de dev nunca pueda exponer accidentalmente una credencial de producción.
Resumen y siguiente paso
En esta lección viste qué es un Environment de GitHub, el camino de clics real para configurarlo (Settings → Environments, required reviewers, wait timer, deployment branches), y cómo se declara en un job (environment: <nombre>). Confirmaste, con una corrida real de act —no solo con la cita del issue—, que act ignora por completo esta protección: el job corrió en 1.6 segundos, sin pausa, sin esperar ninguna aprobación. Y entendiste por qué esto no invalida el mecanismo para el resto de esta guía: apply.yml, en el Módulo 5, sigue declarando environment: production porque ese YAML tiene que ser portable a un repositorio real, donde el bloqueo sí ocurriría.
Antes de avanzar deberías poder: trazar el camino de clics completo para crear un Environment con required reviewers; explicar, con la cita exacta, por qué act ignora environment:; y explicar por qué declarar environment: sigue siendo correcto aunque act no lo respete.
Con esto se cierra la parte conceptual y representativa de este módulo. Las lecciones 7 y 8 vuelven a terreno completamente ejecutado: vas a migrar el ci.yml real de Andes Cargo para que use Secrets en vez de credenciales escritas en el archivo, con salida real de act confirmando cada paso.
Recursos
- GitHub Docs — Using environments for deployment — documentación oficial completa de Environments, incluidos
required reviewers,wait timerydeployment branches. - nektos/act issue #1714 — la fuente exacta de la cita de esta lección:
actignoraenvironment:, confirmado ynot-planned. - nektosact.com — User Guide — documentación de
act workflow_dispatch, usada en el experimento de esta lección.