El proyecto contoso-reservas ya existe, pero está vacío. El código de la web de reservas sigue donde estaba: en el portátil de Diego Salas, en una carpeta con control de versiones local que nadie más ve, y en una sucesión de ZIP en la bandeja de entrada de Marta. Esta lección elimina esa situación de raíz.
Azure Repos es el servicio de repositorios Git privados de Azure DevOps. Alojar código en un repositorio remoto es la parte fácil —eso lo hace cualquiera—; lo que de verdad transforma el trabajo del equipo es lo que se construye encima: una estrategia de ramificación que todos entienden, solicitudes de incorporación de cambios que convierten la revisión en conversación registrada, y directivas de rama que hacen que las reglas del equipo dejen de depender de que alguien se acuerde. Al terminar, la rama main de Contoso será, por construcción, siempre desplegable.
Contenido
- Git en lo imprescindible: confirmación, rama, fusión y rebase
- Crear el repositorio
contoso-reservasy clonarlo - Autenticación: Credential Manager, tokens y SSH
- Estrategias de ramificación y la que elige Contoso
- Solicitudes de incorporación de cambios
- Directivas de rama sobre
main - Revisores automáticos por ruta: el CODEOWNERS de Azure Repos
- Etiquetas y versionado semántico
.gitignorey el error de subir un secreto- Migrar el repositorio local conservando el historial
- Git LFS para los recursos gráficos pesados
- Comparación con GitHub Repos
- Errores Comunes y Consejos
- Ejercicios
- Conclusión
- Git en lo imprescindible: confirmación, rama, fusión y rebase
Esta no es una lección de Git, pero hay cuatro conceptos sin los cuales el resto no se entiende. Una confirmación (commit) es una instantánea completa del proyecto, identificada por un resumen criptográfico y que apunta a la confirmación anterior: la historia de un repositorio es una cadena de instantáneas, no una lista de diferencias. Una rama es solo un puntero móvil a una confirmación —crear una es escribir un fichero de 41 bytes—, y por eso el flujo de trabajo moderno crea y destruye ramas constantemente.
Fusión (merge) y rebase son dos formas de incorporar el trabajo de una rama a otra, y la diferencia importa:
| Fusión | Rebase | |
|---|---|---|
| Qué hace | Crea una confirmación nueva con dos padres | Reescribe las confirmaciones sobre otra base |
| Historia resultante | Ramificada, refleja lo que pasó de verdad | Lineal, más fácil de leer |
| Riesgo | Ninguno | Nunca sobre ramas ya compartidas |
| Uso típico en Contoso | Nunca a mano: lo hace la solicitud de cambios | Actualizar tu rama con main antes de pedir revisión |
git switch -c feature/1842-mapa-cabina # Crear rama desde main y situarse en ella
git commit -am "Anade el mapa de cabina con seleccion de asiento. AB#1842"
git fetch origin && git rebase origin/main # Reescribir mis confirmaciones sobre la punta de main
git add . && git rebase --continue # Tras resolver un conflicto: marcarlo y continuar
git push -u origin feature/1842-mapa-cabina # Publicar la rama en Azure ReposLa regla de oro del rebase: solo sobre tu rama personal y antes de que otros trabajen sobre ella. Rebasar main reescribe la historia de todo el mundo y es la forma más rápida de estropearle el día al equipo.
- Crear el repositorio
contoso-reservas y clonarlo
contoso-reservas y clonarloContoso crea cuatro repositorios en el proyecto, con el criterio «un artefacto desplegable, un repositorio»:
| Repositorio | Contenido | Se despliega en |
|---|---|---|
contoso-reservas |
La web pública | app-contoso-reservas-pro/dev |
contoso-api-disponibilidad |
La API de disponibilidad | app-contoso-api-disponibilidad-pro/dev |
contoso-modelos |
Biblioteca compartida de modelos de reserva | Paquete en el feed (05-05) |
contoso-infra |
Plantillas de Bicep de toda la plataforma | Recursos de Azure (05-06) |
# Crear los cuatro repositorios con la extension azure-devops de la CLI
for r in contoso-reservas contoso-api-disponibilidad contoso-modelos contoso-infra; do
az repos create --name "$r"
done
az repos list --query "[].{nombre:name, url:webUrl}" -o table
git clone https://[email protected]/contoso-airlines/contoso-reservas/_git/contoso-reservas
- Autenticación: Credential Manager, tokens y SSH
Hay tres formas de que tu Git local se autentique contra Azure Repos, y no son equivalentes:
| Método | Cómo funciona | Recomendación |
|---|---|---|
| Git Credential Manager | Abre el navegador, autentica con Entra ID (y MFA) y guarda un token de corta vida en el almacén de credenciales del sistema | La opción por defecto en portátiles de personas |
| Token de acceso personal (PAT) | Cadena generada a mano, con ámbitos y caducidad, que actúa como contraseña | Solo para automatismos que no admiten otra cosa |
| Claves SSH | Par de claves; la pública se registra en tu perfil | Buena para equipos Linux o quien prefiere no depender del navegador |
Git Credential Manager viene incluido con las instalaciones recientes de Git y respeta el acceso condicional y el MFA de 04-01: la sesión del portátil de Diego caduca cuando lo dice la política de Entra ID, no cuando a alguien se le ocurra. Los tokens de acceso personal son la fuente más común de incidentes de seguridad en Azure DevOps. Si tienes que usar uno: concédele solo los ámbitos necesarios (Code (read) para una herramienta que solo lee) y nunca Full access; ponle la caducidad más corta viable; guárdalo en kv-contoso-pro y no en un fichero de configuración; y ten presente que un PAT hereda todos los permisos de quien lo creó, así que el de un administrador es una llave maestra.
ssh-keygen -t ed25519 -C "[email protected]" # Generar el par de claves
ssh-add ~/.ssh/id_ed25519
cat ~/.ssh/id_ed25519.pub # La clave publica se pega en el perfil de Azure DevOps
# A partir de ahi se clona por SSH, sin contrasenas ni tokens
git clone [email protected]:v3/contoso-airlines/contoso-reservas/contoso-reservasPara los pipelines, ninguna de estas tres: usarán la federación de identidad de carga de trabajo de las conexiones de servicio de 05-01. La coherencia es la misma que en el módulo 4: si existe una forma de autenticarse sin secreto, es la que se usa.
- Estrategias de ramificación y la que elige Contoso
| Estrategia | Cómo funciona | Ventajas | Inconvenientes | Encaja con |
|---|---|---|---|---|
| GitFlow | Ramas develop, release/*, hotfix/*, feature/* y main |
Soporta varias versiones vivas a la vez | Complejo, fusiones largas, ralentiza la entrega | Software instalable con versiones mantenidas |
| GitHub Flow | main + ramas de característica; se despliega al fusionar |
Simple, ideal para despliegue continuo | Requiere pruebas automáticas sólidas | Servicios web con una sola versión viva |
| Rama de característica con Trunk-Based | main siempre desplegable + ramas de vida muy corta (1-2 días) |
Fusiones triviales, realimentación rápida, mejores métricas DORA | Exige disciplina y marcas de característica | Equipos que despliegan a diario |
| Trunk-Based puro | Todos confirman directamente en main |
Máxima velocidad de integración | Sin revisión previa; inviable con auditoría PCI DSS | Equipos muy maduros con pruebas exhaustivas |
Contoso elige rama de característica con Trunk-Based por tres razones concretas: solo hay una versión viva —la que está en Internet—, así que GitFlow resolvería un problema que Contoso no tiene cobrando su complejidad igualmente; la auditoría PCI DSS exige revisión de los cambios, lo que descarta el trunk-based puro sin solicitudes de cambio; y las ramas cortas atacan directamente su peor métrica DORA, el tiempo de entrega del cambio. Convención de nombres acordada: feature/<id>-<descripcion>, bugfix/<id>-<descripcion> y hotfix/<id>-<descripcion>, siempre con el identificador del elemento de trabajo por delante.
gitGraph
commit id: "v2.4.0"
branch feature/1842-mapa-cabina
commit id: "API mapa"
checkout main
branch bugfix/1855-asientos
commit id: "corrige recuento"
checkout main
merge bugfix/1855-asientos id: "PR 58"
checkout feature/1842-mapa-cabina
commit id: "rebase sobre main"
checkout main
merge feature/1842-mapa-cabina id: "PR 61" tag: "v2.5.0"
La regla que hace que esto funcione: una rama abierta más de dos días es una señal de alarma. Si el trabajo es mayor, se parte en incrementos fusionables en main sin activarse todavía, con las marcas de característica de 05-04.
- Solicitudes de incorporación de cambios
Una solicitud de incorporación de cambios (pull request) propone fusionar una rama en otra y abre una conversación sobre ella. Es el mecanismo central de calidad y, de paso, el registro documental que pedía el auditor en 05-01.
# Crear la solicitud desde la CLI, vinculando el elemento de trabajo
az repos pr create --repository contoso-reservas \
--source-branch feature/1842-mapa-cabina --target-branch main \
--title "Mapa de cabina con seleccion de asiento" \
--description "Implementa AB#1842. Incluye pruebas del recuento de asientos." \
--work-items 1842 --reviewers [email protected] \
--delete-source-branch true --squash true--delete-source-branch true borra la rama al completarse: sin ello, en seis meses habrá doscientas ramas muertas y nadie sabrá cuáles siguen vivas. --squash true se explica en el apartado siguiente.
Contoso define una plantilla de descripción en .azuredevops/pull_request_template.md, que Azure Repos precarga en cada solicitud nueva:
## Qué cambia y por qué
<!-- Contexto para quien revise: el problema, no solo la solucion -->
## Elemento de trabajo
AB#
## Cómo se ha probado
- [ ] Pruebas unitarias nuevas o actualizadas
- [ ] Probado en `app-contoso-reservas-dev`
## Riesgos y reversión
<!-- Que puede romperse y como se vuelve atras -->
## Lista de comprobación
- [ ] Sin secretos ni cadenas de conexión en el código
- [ ] Migraciones de base de datos compatibles hacia atrásCuatro prácticas separan una revisión útil de un trámite. Solicitudes pequeñas: por encima de 400 líneas la calidad de la revisión cae en picado y se aprueba por cansancio, mientras que una de 60 líneas recibe comentarios reales. Cambios sugeridos: Azure Repos permite proponer el texto exacto desde el comentario, y quien lo recibe lo aplica con un clic. Comentar el código, no a la persona: «esta consulta hace una llamada por asiento» en lugar de «has hecho un N+1». Y sobre todo, la conversación es documentación: cuando Marta pregunta «¿por qué 90 segundos de caché y no 300?» y Diego responde con el dato del proveedor de tarifas, esa respuesta queda asociada al cambio para siempre. Es la mejor documentación de arquitectura que existe, porque nadie tiene que acordarse de escribirla aparte.
- Directivas de rama sobre
main
mainAquí es donde el acuerdo verbal se convierte en regla aplicada. Una directiva de rama es una condición que debe cumplirse para poder completar una solicitud de incorporación de cambios. Contoso protege main con seis:
| Directiva | Configuración en Contoso | Qué previene |
|---|---|---|
| Número mínimo de revisores | 2, y no puede aprobar quien propone | Que un cambio entre sin ojos ajenos |
| Comprobar elementos de trabajo vinculados | Obligatorio | Cambios sin justificación rastreable |
| Comprobar resolución de comentarios | Todos resueltos | Objeciones que se ignoran en silencio |
| Compilación con validación | Pipeline de CI (05-03), obligatoria | Fusionar código que no compila o no pasa pruebas |
| Limitar tipos de fusión | Solo combinación en una confirmación (squash) | Historia de main ilegible |
| Revisores automáticos | Por ruta (apartado 7) | Que nadie con el contexto necesario se entere |
COMUN="--repository-id $REPO_ID --branch main --blocking true --enabled true"
# 1. Minimo de 2 revisores, sin autoaprobacion, reiniciando las
# aprobaciones si tras aprobar llegan confirmaciones nuevas
az repos policy approver-count create $COMUN \
--minimum-approver-count 2 --creator-vote-counts false \
--reset-on-source-push true --allow-downvotes false
# 2. Elemento de trabajo vinculado obligatorio (trazabilidad)
az repos policy work-item-linking create $COMUN
# 3. Todos los comentarios resueltos antes de completar
az repos policy comment-required create $COMUN
# 4. Compilacion con validacion: el pipeline de CI debe pasar,
# y su resultado caduca a las 12 horas (720 minutos)
az repos policy build create $COMUN \
--build-definition-id $ID_PIPELINE_CI \
--display-name "CI de Contoso Reservas" \
--valid-duration 720 --queue-on-source-update-only true
# 5. Solo se admite combinacion en una confirmacion (squash)
az repos policy merge-strategy create $COMUN --allow-squash true \
--allow-no-fast-forward false --allow-rebase false --allow-rebase-merge falseTres detalles que la gente pasa por alto. --reset-on-source-push true: si tras aprobar llegan confirmaciones nuevas, las aprobaciones se anulan —sin esto se puede aprobar un cambio de dos líneas y colar después quinientas—. --valid-duration 720: la compilación caduca a las 12 horas, lo que impide fusionar validado contra un main que ya era otra cosa. Y la combinación en una confirmación, que hace que cada solicitud aparezca en main como una única confirmación limpia: la historia pasa a ser la lista de cambios funcionales entregados, justo lo que quiere leer quien investiga una incidencia.
Las directivas se aplican también a los administradores, y esa es su gracia. Existe la opción de conceder «omitir directivas», y la respuesta correcta casi siempre es no concederla: si hace falta saltarse el proceso por una urgencia, es que el proceso está mal calibrado. Para las urgencias reales, Contoso mantiene ramas hotfix/* con su propia directiva de un solo revisor, pasando por el mismo pipeline.
- Revisores automáticos por ruta: el CODEOWNERS de Azure Repos
En GitHub, un fichero CODEOWNERS asigna propietarios por carpeta. Azure Repos hace lo mismo con la directiva de revisores automáticamente incluidos, configurada por ruta —no en un fichero del repositorio, sino en la propia directiva—:
# Infraestructura y pipelines: revision obligatoria de Contoso-Infraestructura
az repos policy required-reviewer create $COMUN \
--message "Cambios de infraestructura: revision de Contoso-Infraestructura" \
--required-reviewer-ids "Contoso-Infraestructura" \
--path-filter "/infra/*;/*.bicep;/azure-pipelines*.yml"
# Igual para el esquema de datos, con Contoso-DBA-Reservas y el filtro
# --path-filter "/src/Contoso.Reservas.Datos/Migraciones/*"Los grupos son los mismos del módulo 4, con lo que la gestión de personas sigue estando en un único sitio. El efecto práctico: Diego ya no puede cambiar el esquema de db-reservas sin que un DBA se entere, y no porque se lo hayan prohibido, sino porque la fusión no se completa.
- Etiquetas y versionado semántico
Una etiqueta (tag) marca una confirmación concreta con un nombre permanente. Es lo que permite responder a «qué código exacto es la versión 2.5.0 que está en producción».
Contoso usa versionado semántico MAYOR.MENOR.PARCHE:
| Parte | Cuándo sube | Ejemplo en Contoso |
|---|---|---|
| MAYOR | Cambio incompatible | La API de disponibilidad deja de aceptar el formato de fecha antiguo |
| MENOR | Funcionalidad nueva compatible | Se añade el mapa de cabina |
| PARCHE | Corrección compatible | Se arregla el recuento de asientos |
# Etiqueta anotada (con autor, fecha y mensaje) sobre la confirmacion actual
git tag -a v2.5.0 -m "Mapa de cabina y correccion del recuento de asientos"
git push origin v2.5.0 # Las etiquetas NO viajan con un git push normal
git show v2.5.0 --stat # Que confirmacion es exactamente la version desplegadaEn 05-05 el número de versión de los paquetes se generará automáticamente desde el pipeline, y en 05-04 la etiqueta se creará sola al desplegar en producción, de modo que la correspondencia entre etiqueta y entorno no dependa de que nadie la escriba a mano.
.gitignore y el error de subir un secreto
.gitignore y el error de subir un secretoEl fichero .gitignore indica qué no debe entrar nunca en el repositorio:
bin/
obj/
node_modules/
appsettings.Development.local.json # Configuracion local con secretos
.env
*.pfx # Claves privadas: jamas al repositorio
*.pem
.vs/Ahora el error grave. Diego confirma por accidente un appsettings.json con la cadena de conexión de sql-contoso-reservas-dev y la clave de la pasarela de pago. Lo descubre a los diez minutos y borra el fichero en la siguiente confirmación. El secreto sigue comprometido, porque la historia de Git es inmutable y cada confirmación conserva el contenido completo: cualquiera que haya clonado el repositorio —o cualquier copia de seguridad, o cualquier registro de compilación— tiene el valor. Borrarlo después no lo elimina, solo lo esconde de la vista superficial.
El procedimiento correcto, por orden estricto:
- Rotar el secreto inmediatamente. Es lo único que de verdad cierra el agujero: generar una clave nueva de la pasarela de pago, actualizarla en
kv-contoso-proy dejar la anterior sin valor. Todo lo demás es limpieza, no remedio. - Comprobar el uso. Revisar los registros de acceso del recurso por si la credencial se usó desde fuera; para esto sirven las alertas de Microsoft Defender for Cloud de 04-05.
- Limpiar la historia con
git filter-repo, coordinando un reclonado con todo el equipo. Es destructivo y disruptivo, y en repositorios grandes muchas veces no compensa. - Prevenir la reincidencia:
.gitignorecorrecto, revisión en la solicitud de cambios y detección automática.
Azure DevOps incluye detección de secretos que analiza las confirmaciones y avisa —y con GitHub Advanced Security for Azure DevOps, de pago, puede bloquear el envío antes de que el secreto entre—. Un gancho local o un paso de análisis en el pipeline detiene la mayoría de los casos restantes.
La solución de fondo ya la conoces del módulo 4: si no hay secretos, no se pueden filtrar. La aplicación de Contoso se autentica contra SQL y contra el almacenamiento con identidad administrada, y lo poco que sigue siendo secreto de verdad —pasarela-pago-clave, token-meteo— vive en kv-contoso-pro y se referencia con @Microsoft.KeyVault(...). El fichero de configuración del repositorio contiene nombres de recursos, nunca credenciales.
- Migrar el repositorio local conservando el historial
El repositorio de Diego tiene tres años de historia que no se pueden perder: es lo que permite saber por qué se escribió cada línea. La migración lo conserva todo:
cd ~/proyectos/contoso-reservas # El repositorio local existente de Diego
git remote add azure https://[email protected]/contoso-airlines/contoso-reservas/_git/contoso-reservas
git push azure --all # TODAS las ramas, con su historia intacta
git push azure --tags # TODAS las etiquetas
git log azure/main --oneline | wc -l # Comprobar que la historia llego completa
# Si el origen era otro servidor Git, la forma limpia es un clon espejo,
# que incluye todas las referencias y no solo las ramas locales:
git clone --mirror https://servidor-antiguo.contosoairlines.example/reservas.git
cd reservas.git && git push --mirror $URL_AZURE_REPOSAntes de dar la migración por buena, dos cosas: fijar main como rama predeterminada y dejar el repositorio antiguo en solo lectura. Si sigue aceptando envíos, aparecerán dos historias divergentes y alguien perderá trabajo.
- Git LFS para los recursos gráficos pesados
La web incluye imágenes de destinos, mapas de cabina en alta resolución y vídeos de cabecera: binarios de decenas de megabytes. Git guarda cada versión completa de cada binario para siempre, así que un mapa de 30 MB modificado veinte veces son 600 MB permanentes que todo el mundo se descarga al clonar. Git LFS (Large File Storage) sustituye el binario en la historia por un puntero de texto y guarda el contenido aparte, descargando solo la versión que necesitas:
git lfs install # Una vez por repositorio y maquina
git lfs track "*.psd" "*.mp4" "recursos/imagenes/**/*.png"
git add .gitattributes # El seguimiento se guarda ahi
git commit -m "Configura Git LFS para recursos graficos pesados"Dos advertencias: LFS hay que configurarlo antes de subir los binarios (hacerlo después exige reescribir la historia), y su almacenamiento consume la cuota facturable de Artifacts de la organización. Los recursos que la web sirve en producción viven en una cuenta de almacenamiento detrás de la CDN de 02-06; al repositorio solo va lo que forma parte del código fuente.
- Comparación con GitHub Repos
| Azure Repos | GitHub Repos | |
|---|---|---|
| Protección de rama | Directivas más granulares, con filtro por ruta y caducidad | Reglas de rama, más simples |
| Propietarios de código | Directiva de revisores por ruta | Fichero CODEOWNERS versionado |
| Revisión de código | Buena; cambios sugeridos | Excelente; el estándar del sector |
| Seguridad del código | Detección de secretos; Advanced Security de pago | Advanced Security más maduro; Dependabot |
| Ecosistema y comunidad | Interno | Enorme |
En la práctica, la experiencia de revisión de GitHub suele resultar más agradable, mientras que las directivas de Azure Repos son más granulares. Contoso se queda en Azure Repos por la integración con Boards y la trazabilidad que exige PCI DSS.
Errores Comunes y Consejos
- Ramas de larga duración. Una rama de tres semanas garantiza una fusión dolorosa. Si el trabajo es grande, se parte en incrementos fusionables y se oculta con marcas de característica.
- Rebasar una rama compartida. Reescribe la historia de todos. Rebase solo en tu rama y antes de que alguien más trabaje en ella.
- Solicitudes de cambio enormes y aprobaciones sin leer. A partir de 400 líneas la revisión es un trámite; y la directiva de dos revisores no vale nada si la segunda firma es automática. Mejor cinco solicitudes de 80 líneas y una revisión honesta.
- Creer que borrar la confirmación borra el secreto. No lo borra. Rotar siempre, y después limpiar.
- Conceder «omitir directivas» a los administradores. Convierte la protección en una sugerencia. Si hay urgencias, configura una directiva propia más laxa sobre
hotfix/*. - Subir binarios pesados sin LFS. El repositorio crece para siempre y el clonado se vuelve insoportable; y recuerda que LFS consume cuota facturable.
- Consejo: escribe mensajes de confirmación con un título breve en imperativo, un cuerpo que explique por qué —el qué ya se ve en el diff— y la referencia
AB#<id>. - Consejo: activa el borrado automático de la rama de origen al completar la solicitud y purga periódicamente las ramas sin actividad.
Ejercicios
Ejercicio 1: elegir y justificar la estrategia de ramificación
El equipo de Contoso Millas (centro-coste=CC-2077) mantiene un portal web y, además, una aplicación móvil cuya versión 3.2 sigue instalada en los teléfonos de los clientes y recibe correcciones mientras se desarrolla la 4.0.
- ¿Qué estrategia de ramificación le corresponde a cada uno de los dos productos, y por qué son distintas?
- Para el portal, define las directivas de rama que pondrías en
maincon su justificación. - ¿Cómo gestionarías una corrección urgente en el portal un sábado, sin saltarte el proceso?
Ejercicio 2: un secreto en el repositorio
Diego confirma y envía a main un fichero appsettings.json que contiene la clave de la pasarela de pago y la cadena de conexión de sql-contoso-reservas-pro. Se da cuenta veinte minutos después. Ya hay dos compañeros que han hecho git pull.
- Enumera las acciones en orden, indicando cuál cierra realmente el riesgo.
- ¿Por qué no basta con una confirmación que borre el fichero, ni con revertirla?
- ¿Qué tres medidas técnicas evitarían que vuelva a pasar, y qué decisión de arquitectura del módulo 4 lo hace casi imposible?
Ejercicio 3: directivas y revisores por ruta
Contoso quiere que: (a) nadie fusione en main sin dos aprobaciones y sin elemento de trabajo; (b) todo cambio bajo /src/Contoso.Reservas.Datos/Migraciones/ lo revise Contoso-DBA-Reservas; (c) la historia de main quede lineal; (d) una compilación aprobada hace tres días no sirva para fusionar hoy.
- Indica qué directiva concreta resuelve cada punto y escribe el comando de la CLI para (b).
- ¿Qué ocurre si Marta, que es administradora del proyecto, intenta fusionar sin cumplirlas?
Soluciones
Solución 1:
- Para el portal, rama de característica con Trunk-Based: una sola versión viva (la desplegada), despliegue frecuente y ramas de uno o dos días. Para la aplicación móvil, un flujo tipo GitFlow o al menos ramas
release/3.2yrelease/4.0de larga duración, porque hay dos versiones vivas simultáneamente: la instalada en los teléfonos, que sigue recibiendo parches, y la que se está desarrollando. La diferencia no es de gusto: en la web tú controlas qué versión ejecuta el cliente; en móvil, no. - Mínimo de 2 revisores sin autoaprobación y con reinicio al enviar cambios; elemento de trabajo vinculado (trazabilidad); comentarios resueltos; compilación con validación con caducidad de 12 horas; solo combinación en una confirmación; y revisores automáticos por ruta para infraestructura y esquema.
- Rama
hotfix/<id>-<descripcion>desdemain, con una directiva propia sobre el patrónhotfix/*que exija un solo revisor pero mantenga la compilación con validación y el elemento de trabajo. Pasa por el mismo pipeline y el mismo despliegue; lo único que se relaja es el número de ojos, no la automatización. Nunca conceder «omitir directivas».
Solución 2:
- (a) Rotar la clave de la pasarela de pago y cambiar la credencial de la base de datos —esto y solo esto cierra el riesgo—; actualizar el valor nuevo en
kv-contoso-pro. (b) Revisar los registros de acceso y las alertas de Defender for Cloud por si hubo uso indebido. (c) Añadir el fichero a.gitignorey eliminarlo del seguimiento. (d) Valorar reescribir la historia congit filter-repoy coordinar el reclonado, dado que el repositorio es privado y el equipo, pequeño. (e) Comunicarlo al responsable de seguridad: es un incidente, no un despiste. - Porque la historia de Git es inmutable y cada confirmación guarda el contenido completo: el valor sigue siendo recuperable en cualquier clon, copia de seguridad o registro de compilación. Una reversión añade una confirmación nueva, no elimina la anterior. Mientras la credencial siga siendo válida, sigue comprometida.
- Detección de secretos activada en el repositorio; un gancho de precommit o un paso de análisis en el pipeline de CI; y
.gitignorecompleto con revisión obligatoria de los ficheros de configuración en la solicitud de cambios. La decisión de arquitectura: autenticación con identidad administrada —sin cadena de conexión con contraseña que filtrar— y lo poco irreductible en Key Vault referenciado con@Microsoft.KeyVault(...). Si no hay secreto en el código, no hay secreto que subir.
Solución 3:
- (a)
approver-countcon--minimum-approver-count 2 --creator-vote-counts false, máswork-item-linking. (b)required-reviewercon su filtro de ruta y el grupo de Entra ID:az repos policy required-reviewer create --repository-id $REPO_ID --branch main --blocking true --enabled true --required-reviewer-ids "Contoso-DBA-Reservas" --path-filter "/src/Contoso.Reservas.Datos/Migraciones/*". (c)merge-strategypermitiendo solo--allow-squash true. (d)policy buildcon--valid-duration 720, que invalida las compilaciones de más de 12 horas. - No puede. Las directivas se aplican por igual a los administradores del proyecto salvo que se conceda explícitamente el permiso de omitir directivas, algo que Contoso no hace. Eso es justamente lo que convierte el acuerdo del equipo en una regla real y lo que satisface al auditor: no hay excepciones por cargo.
Conclusión
El código de Contoso Airlines ya no vive en un portátil ni viaja por correo. Has repasado lo imprescindible de Git —confirmación, rama, fusión y rebase, con la regla de no rebasar nunca ramas compartidas—, has creado los cuatro repositorios del proyecto y has migrado el repositorio local de Diego conservando sus tres años de historia, dejando el origen antiguo en solo lectura para que no aparezcan dos verdades. Sabes autenticarte con Git Credential Manager como opción por defecto, con SSH cuando conviene y con tokens de acceso personal solo cuando no hay alternativa, sabiendo que un PAT hereda todos los permisos de quien lo crea.
Has elegido conscientemente la estrategia de ramificación: rama de característica con Trunk-Based, con ramas de vida muy corta, porque Contoso tiene una sola versión viva, necesita revisión por PCI DSS y su métrica DORA más débil es el tiempo de entrega. Y has convertido el proceso de calidad en algo que no depende de la memoria de nadie: solicitudes de incorporación de cambios con plantilla, revisores y conversación registrada —que es, de paso, la mejor documentación de arquitectura que tendrá el equipo—, y directivas sobre main que exigen dos aprobaciones sin autoaprobación, elemento de trabajo vinculado, comentarios resueltos, compilación con validación vigente y combinación en una sola confirmación, con revisores automáticos por ruta que llevan cada cambio de esquema a Contoso-DBA-Reservas y cada plantilla a Contoso-Infraestructura. Sabes etiquetar con versionado semántico, mantener un .gitignore serio y, sobre todo, sabes que un secreto subido hay que rotarlo: borrar la confirmación no borra nada, y la solución de fondo sigue siendo la del módulo 4, no tener secretos que filtrar.
Queda un cabo suelto muy visible. La directiva más importante que has configurado —la compilación con validación— apunta a un pipeline que todavía no existe: hoy nadie comprueba que el código compila, que las pruebas pasan o que no se ha colado un fallo evidente antes de fusionar. En la próxima lección, Azure Pipelines: integración continua, construirás ese pipeline: agentes hospedados y autohospedados con sus costes reales, la anatomía de un azure-pipelines.yml explicada línea a línea, restauración, compilación, pruebas con publicación de resultados y cobertura, análisis estático, caché, plantillas reutilizables para no repetir el mismo YAML en cada servicio, y los secretos entrando desde Key Vault sin pasar jamás por el repositorio. Al terminarla, la regla «main siempre compila» dejará de ser una intención para ser un hecho verificado en cada cambio.
Curso de Azure
Módulo 1: Introducción a Azure
- ¿Qué es Azure?
- Modelos de servicio, regiones y zonas de disponibilidad
- Crear y configurar tu cuenta de Azure
- Recorrido por el portal de Azure
- Azure Resource Manager: suscripciones, grupos de recursos y etiquetas
- Azure CLI, PowerShell y Cloud Shell
Módulo 2: Servicios principales de Azure
- Máquinas virtuales de Azure
- Escalado y alta disponibilidad del cómputo
- Azure App Service
- Azure Storage: blobs, archivos, colas y tablas
- Redes en Azure: redes virtuales, subredes y NSG
- Conectividad híbrida y entrega global
Módulo 3: Bases de datos de Azure
- Elegir el servicio de datos adecuado
- Azure SQL Database
- Azure Cosmos DB
- Azure Database for MySQL
- Azure Database for PostgreSQL
- Analítica de datos: Data Lake, Data Factory y Synapse
Módulo 4: Seguridad en Azure
- Microsoft Entra ID y gestión de identidades
- RBAC e identidades administradas
- Azure Key Vault
- Protección DDoS y firewall de aplicaciones web
- Microsoft Defender for Cloud
- Gobernanza y cumplimiento con Azure Policy
Módulo 5: Azure DevOps
- Introducción a Azure DevOps
- Azure Repos
- Azure Pipelines: integración continua
- Despliegue continuo con entornos y aprobaciones
- Azure Artifacts
- Infraestructura como código con Bicep
Módulo 6: Servicios avanzados de Azure
- Contenedores en Azure: Container Registry y Container Apps
- Azure Kubernetes Service (AKS)
- Azure Functions
- Azure Logic Apps
- Mensajería y eventos: Service Bus, Event Grid y Event Hubs
- Servicios de IA de Azure
Módulo 7: Monitoreo y gestión
- Azure Monitor: métricas, alertas y paneles
- Log Analytics y consultas KQL
- Application Insights
- Azure Automation y runbooks
- Copias de seguridad y recuperación ante desastres
Módulo 8: Gestión y optimización de costos
- Calculadora de precios y estimación de costes
- Azure Cost Management: análisis, presupuestos y alertas
- Reservas, planes de ahorro y Azure Hybrid Benefit
- Azure Advisor
- Estrategias de optimización y cultura FinOps
