Gestionando Feature Flags con LaunchDarkly en Pipelines CI/CD
Descubre cómo las feature flags pueden transformar tus despliegues. Este tutorial te guiará en la integración de LaunchDarkly en tus pipelines CI/CD para una gestión de funcionalidades dinámica, segura y controlada. Mejora la agilidad y reduce el riesgo en tus lanzamientos de software.
🚀 Introducción a las Feature Flags y CI/CD
En el mundo del desarrollo de software moderno, la velocidad y la seguridad son cruciales. Los equipos buscan constantemente formas de entregar valor a los usuarios de manera más rápida y con menos riesgo. Aquí es donde entran en juego dos conceptos poderosos: la Integración Continua/Entrega Continua (CI/CD) y las Feature Flags (también conocidas como feature toggles o interruptores de funcionalidad).
El CI/CD es una metodología que automatiza los pasos del desarrollo de software, desde la integración de código hasta el despliegue en producción. Su objetivo es asegurar que el software esté siempre en un estado desplegable y listo para ser lanzado.
Las Feature Flags, por otro lado, son una técnica que permite activar o desactivar funcionalidades específicas en tiempo de ejecución, sin necesidad de redeployar el código. Son esencialmente interruptores dentro de tu código que controlan qué partes del mismo son visibles o accesibles para diferentes grupos de usuarios o en diferentes entornos.
¿Por qué son tan importantes juntas? 🤔
La combinación de CI/CD y Feature Flags crea un ecosistema de entrega de software increíblemente potente. Mientras CI/CD te permite desplegar con frecuencia y confianza, las Feature Flags te otorgan un control granular sobre qué funcionalidades están activas y cuándo.
Este tutorial explorará cómo integrar LaunchDarkly, una plataforma líder en gestión de feature flags, con tus pipelines CI/CD para maximizar la agilidad, reducir el riesgo y habilitar nuevas estrategias de lanzamiento.
🎯 ¿Qué son las Feature Flags? Una inmersión profunda
Las feature flags son variables de configuración que se incrustan en el código de tu aplicación y que pueden ser controladas externamente. Imagina un interruptor if (feature_new_dashboard_enabled) en tu código. En lugar de tener que cambiar el código y redeployar para cambiar el valor de feature_new_dashboard_enabled, una plataforma de feature flags te permite hacerlo con un clic en una interfaz de usuario o a través de una API.
Tipos comunes de Feature Flags
Las feature flags no son un concepto único; vienen en varias formas, cada una con un propósito específico:
- Release Toggles: Las más comunes. Se usan para desacoplar el despliegue de código del lanzamiento de la funcionalidad. Permiten integrar código inacabado en la rama principal sin afectar a los usuarios. Una vez que la funcionalidad está lista y probada, la flag se activa.
- Experiment Toggles: Utilizadas para pruebas A/B, pruebas multivariante o para desplegar una funcionalidad a un pequeño porcentaje de usuarios y medir su impacto. Permiten una toma de decisiones basada en datos.
- Ops Toggles: Flags que controlan aspectos operativos del sistema, como la activación de un sistema de caché, un método de fallback o la desconexión de un servicio no esencial durante picos de carga. Ayudan a gestionar el rendimiento y la estabilidad.
- Permissioning Toggles: Permiten controlar el acceso a funcionalidades basadas en roles de usuario, planes de suscripción o licencias.
Ejemplo práctico de un Release Toggle
Imagina que estás desarrollando una nueva interfaz de usuario para una sección de tu aplicación. Puedes tener un release_toggle_new_ui que está false por defecto. A medida que los desarrolladores trabajan en la nueva UI, integran su código en la rama main sin que los usuarios finales la vean. Una vez que la nueva UI está completa, probada y lista, el equipo de producto puede activar la flag en producción. Si surge un problema, pueden desactivarla instantáneamente.
Beneficios de las Feature Flags ✨
La adopción de feature flags conlleva una serie de ventajas significativas:
- Despliegues sin miedo (Dark Launches): Despliega nuevas funcionalidades en producción, pero mantenlas ocultas para los usuarios hasta que estén completamente listas. Esto reduce el riesgo del despliegue en sí.
- Pruebas A/B y Experimentación: Dirige diferentes versiones de una funcionalidad a distintos grupos de usuarios para recopilar datos y tomar decisiones informadas.
- Kill Switches: Desactiva instantáneamente funcionalidades problemáticas en producción sin necesidad de revertir o redeployar.
- Rollbacks instantáneos: Si una nueva funcionalidad causa problemas, simplemente desactiva su flag en lugar de revertir un despliegue completo, que puede llevar tiempo y ser costoso.
- Lanzamientos progresivos (Canary Releases): Expón nuevas funcionalidades a un pequeño subconjunto de usuarios (por ejemplo, el 1% de tu tráfico) antes de un lanzamiento completo.
- Desarrollo continuo sin interrupciones: Los equipos pueden integrar código de características a medio terminar en la rama principal sin afectar a la versión en producción, facilitando la integración continua.
- Personalización de la experiencia del usuario: Ofrece diferentes funcionalidades o interfaces a usuarios basados en sus atributos (ubicación, plan de suscripción, comportamiento).
🛠️ Integrando LaunchDarkly en tu Flujo de CI/CD
LaunchDarkly es una plataforma robusta de gestión de feature flags que simplifica la creación, gestión y evaluación de tus flags. Ofrece SDKs para multitud de lenguajes y frameworks, una interfaz de usuario intuitiva y potentes capacidades de segmentación.
La integración de LaunchDarkly en tu pipeline CI/CD te permite automatizar la gestión de tus flags como parte de tu proceso de despliegue.
Conceptos clave de LaunchDarkly 📖
Antes de sumergirnos en la integración, repasemos algunos conceptos esenciales de LaunchDarkly:
- Flags: La unidad básica de control. Puedes definir flags booleanas, string, numéricas o JSON.
- Entornos: Representan tus diferentes entornos de desarrollo (dev, staging, production, etc.). Las flags se gestionan de forma independiente para cada entorno.
- Reglas de Segmentación: Permiten decidir quién ve qué versión de una flag. Puedes segmentar por atributos de usuario (ID, email, ubicación), porcentajes de tráfico, etc.
- SDKs: Bibliotecas cliente que integras en tu aplicación para evaluar el estado de las flags.
- API de LaunchDarkly: Permite la automatización y la integración con otras herramientas, incluyendo tu pipeline CI/CD.
Preparación del Entorno ⚙️
Para este tutorial, asumiremos que tienes un proyecto básico y un pipeline CI/CD configurado (por ejemplo, con GitLab CI, GitHub Actions, Jenkins, etc.). Los pasos son generales y aplicables a la mayoría de las plataformas.
- Crea una cuenta de LaunchDarkly: Si aún no tienes una, regístrate en LaunchDarkly.
- Configura un proyecto y entornos: Dentro de LaunchDarkly, crea un proyecto. Por defecto, tendrás entornos de
TestyProduction. Puedes añadir más (ej.Staging,Development) si es necesario. - Crea una Feature Flag: Para nuestro ejemplo, crearemos una flag booleana llamada
new-feature-enabled. Asegúrate de que tenga valores por defecto para cada entorno (ej.falseenProduction,trueenTest). - Obtén tus claves SDK: Necesitarás las claves
client-side(para aplicaciones frontend) oserver-side(para backends) para inicializar los SDKs de LaunchDarkly en tu aplicación. También necesitarás unpersonal access tokenpara interactuar con la API de LaunchDarkly desde tu pipeline CI/CD.
Integrando el SDK en tu aplicación
Primero, integra el SDK de LaunchDarkly en tu aplicación para que pueda evaluar las flags. Aquí hay un ejemplo básico en Python (para una aplicación de backend):
import launchdarkly_client
# Reemplaza con tu clave de SDK de LaunchDarkly para el entorno 'production'
LD_SDK_KEY = "sdk-xxxxxx"
# Inicializa el cliente de LaunchDarkly
ld_client = launchdarkly_client.LaunchDarklyClient(LD_SDK_KEY)
def get_user_context(user_id):
# Un 'context' representa al usuario o entidad para la que se evalúa la flag.
# Puedes añadir cualquier atributo para segmentación (ej. email, plan, país)
return {
"key": user_id,
"name": f"User {user_id}",
"custom": {
"plan": "premium"
}
}
def main():
user_context = get_user_context("john-doe")
# Evalúa la flag 'new-feature-enabled' para el contexto del usuario
is_new_feature_enabled = ld_client.variation("new-feature-enabled", user_context, False)
if is_new_feature_enabled:
print("🚀 ¡La nueva característica está activa para John Doe!")
# Código para la nueva característica
else:
print("🚫 La nueva característica NO está activa para John Doe.")
# Código para la característica antigua o comportamiento por defecto
# Cierra el cliente de LaunchDarkly al finalizar
ld_client.close()
if __name__ == "__main__":
main()
Para una aplicación frontend (por ejemplo, React), la lógica es similar pero se usa el SDK client-side y la clave client-side:
// React example (simplified)
import { withLDProvider } from 'launchdarkly-react-client-sdk';
// Reemplaza con tu clave de SDK de LaunchDarkly client-side
const LD_CLIENT_SIDE_ID = "xxxxxx";
const App = ({ flags }) => {
if (flags['new-feature-enabled']) {
return <div>🚀 ¡Bienvenido a la nueva interfaz!</div>;
} else {
return <div>🚫 Aquí está la interfaz clásica.</div>;
}
};
export default withLDProvider({
clientSideID: LD_CLIENT_SIDE_ID,
user: {
key: 'anonymous',
anonymous: true,
},
options: {
// ... otras opciones
},
})(App);
Este código simplemente lee el estado de la flag. El verdadero poder viene de cómo manipulamos estas flags desde nuestro CI/CD.
🔄 Automatizando la Gestión de Flags con CI/CD
Ahora, veamos cómo usar tu pipeline CI/CD para interactuar con LaunchDarkly. Esto puede incluir:
- Crear nuevas flags programáticamente.
- Modificar el estado de las flags (activar/desactivar).
- Realizar lanzamientos progresivos.
- Ejecutar pruebas en entornos específicos con flags activadas/desactivadas.
- Archivar flags antiguas.
Usaremos la API de LaunchDarkly para estas interacciones. Necesitarás un personal access token con los permisos adecuados.
1. Configuración de Credenciales en CI/CD
Antes de nada, guarda tu LaunchDarkly Personal Access Token como una variable secreta en tu sistema CI/CD. Por ejemplo:
- GitLab CI: Variables de entorno seguras en la configuración del proyecto/grupo.
- GitHub Actions: Secrets en la configuración del repositorio.
- Jenkins: Credenciales gestionadas.
Llamaremos a esta variable LD_ACCESS_TOKEN.
2. Ejemplo: Activar una Flag en un Entorno Específico tras un Despliegue Exitoso
Imagina que quieres que, después de un despliegue exitoso en staging, la flag new-feature-enabled se active para que el equipo de QA pueda probarla.
Aquí hay un ejemplo de cómo se vería un paso en GitHub Actions usando curl para interactuar con la API de LaunchDarkly. También puedes usar el CLI de LaunchDarkly o una librería cliente de API.
# .github/workflows/deploy.yml
name: Deploy to Staging and Enable Feature
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
environment: staging
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Deploy application to Staging
run: |
echo "Simulating application deployment to Staging..."
# Aquí irían los comandos reales de despliegue, por ejemplo:
# kubectl apply -f kubernetes/staging-deployment.yaml
# docker push my-app:staging
# ...
sleep 10 # Simula el tiempo de despliegue
echo "Deployment to Staging successful!"
- name: Enable 'new-feature-enabled' flag for Staging
env:
LD_ACCESS_TOKEN: ${{ secrets.LD_ACCESS_TOKEN }}
LD_PROJECT_KEY: 'my-project-key' # Reemplaza con la clave de tu proyecto LaunchDarkly
LD_ENVIRONMENT_KEY: 'staging' # La clave de tu entorno 'staging' en LaunchDarkly
FLAG_KEY: 'new-feature-enabled'
run: |
echo "Enabling feature flag '${FLAG_KEY}' in environment '${LD_ENVIRONMENT_KEY}'..."
curl -X PATCH "https://app.launchdarkly.com/api/v2/flags/${LD_PROJECT_KEY}/${FLAG_ENVIRONMENT_KEY}/${FLAG_KEY}" \
-H "Authorization: ${LD_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '[{"op": "replace", "path": "/environments/${LD_ENVIRONMENT_KEY}/on", "value": true}]'
echo "Feature flag '${FLAG_KEY}' enabled successfully in Staging."
Este paso del pipeline envía una solicitud PATCH a la API de LaunchDarkly para modificar el estado de la flag new-feature-enabled a true en el entorno staging. Una vez hecho esto, cualquier instancia de tu aplicación en staging que use el SDK de LaunchDarkly recibirá esta actualización (generalmente en milisegundos) y comenzará a mostrar la nueva funcionalidad.
3. Ejemplo: Deshabilitar una Flag si las Pruebas Fallan
Considera un escenario donde ejecutas pruebas automatizadas en staging y si alguna falla, quieres deshabilitar la nueva funcionalidad como medida de seguridad.
# .github/workflows/deploy.yml (continuación del job 'deploy')
- name: Run automated tests
run: |
echo "Running integration tests..."
# Aquí irían los comandos para ejecutar tus pruebas, por ejemplo:
# npm test
# pytest
sleep 15 # Simula el tiempo de ejecución de pruebas
# exit 1 # Descomentar para simular un fallo de prueba
echo "Integration tests passed."
- name: Disable 'new-feature-enabled' flag on test failure
if: failure() # Este paso solo se ejecuta si un paso anterior falló
env:
LD_ACCESS_TOKEN: ${{ secrets.LD_ACCESS_TOKEN }}
LD_PROJECT_KEY: 'my-project-key'
LD_ENVIRONMENT_KEY: 'staging'
FLAG_KEY: 'new-feature-enabled'
run: |
echo "Tests failed. Disabling feature flag '${FLAG_KEY}' in environment '${LD_ENVIRONMENT_KEY}'..."
curl -X PATCH "https://app.launchdarkly.com/api/v2/flags/${LD_PROJECT_KEY}/${LD_ENVIRONMENT_KEY}/${FLAG_KEY}" \
-H "Authorization: ${LD_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '[{"op": "replace", "path": "/environments/${LD_ENVIRONMENT_KEY}/on", "value": false}]'
echo "Feature flag '${FLAG_KEY}' disabled successfully in Staging due to test failure."
Con esta lógica, si el paso Run automated tests falla (es decir, sale con un código de error distinto de cero), el paso Disable 'new-feature-enabled' flag on test failure se ejecutará automáticamente para deshabilitar la flag. Esto es un ejemplo perfecto de cómo las feature flags pueden actuar como un kill switch automático integrado en tu flujo de CI/CD.
4. Lanzamientos Progresivos (Canary Releases) con CI/CD y LaunchDarkly
LaunchDarkly brilla especialmente en los lanzamientos progresivos. Puedes configurar reglas de segmentación para que una flag se active solo para un porcentaje de tus usuarios o para usuarios con atributos específicos. Tu pipeline puede ajustar estos porcentajes.
# .github/workflows/canary-release.yml
name: Canary Release of New Feature
on:
workflow_dispatch: # Permite activar manualmente este workflow
inputs:
percentage:
description: 'Percentage of users to enable the feature for (0-100)'
required: true
type: number
default: 10
jobs:
canary_release:
runs-on: ubuntu-latest
environment: production # Asegúrate de usar el entorno de producción
steps:
- name: Set Canary Release Percentage for 'new-feature-enabled'
env:
LD_ACCESS_TOKEN: ${{ secrets.LD_ACCESS_TOKEN }}
LD_PROJECT_KEY: 'my-project-key'
LD_ENVIRONMENT_KEY: 'production'
FLAG_KEY: 'new-feature-enabled'
CANARY_PERCENTAGE: ${{ github.event.inputs.percentage }}
run: |
echo "Setting canary release percentage for '${FLAG_KEY}' to ${CANARY_PERCENTAGE}% in environment '${LD_ENVIRONMENT_KEY}'..."
# Primero, asegúrate de que la flag esté 'on' para poder aplicar reglas de segmentación.
# Esto es un paso simplificado; en un escenario real, puedes querer mantener 'on' false por defecto
# y solo ajustar las reglas de segmentación.
curl -X PATCH "https://app.launchdarkly.com/api/v2/flags/${LD_PROJECT_KEY}/${LD_ENVIRONMENT_KEY}/${FLAG_KEY}" \
-H "Authorization: ${LD_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '[{"op": "replace", "path": "/environments/${LD_ENVIRONMENT_KEY}/on", "value": true}]'
# Ahora, modificamos las reglas de segmentación para el porcentaje.
# Esto es un ejemplo simplificado. La API de LaunchDarkly es más compleja para reglas.
# Idealmente, usarías el CLI de LaunchDarkly o su cliente Python para facilitar esto.
# Este ejemplo asume que ya existe una regla por defecto o que estamos estableciendo una nueva.
curl -X PATCH "https://app.launchdarkly.com/api/v2/flags/${LD_PROJECT_KEY}/${LD_ENVIRONMENT_KEY}/${FLAG_KEY}" \
-H "Authorization: ${LD_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '[{"op": "replace", "path": "/environments/${LD_ENVIRONMENT_KEY}/rules", "value": [
{"clauses": [], "rollout": {"variations": [
{"variation": 0, "weight": ${{ env.CANARY_PERCENTAGE }}},
{"variation": 1, "weight": ${{ 100 - env.CANARY_PERCENTAGE }}}
], "kind": "rollout"}}
]}]'
echo "Canary release for '${FLAG_KEY}' set to ${CANARY_PERCENTAGE}% successfully."
Con este pipeline, un ingeniero puede activar manualmente un workflow de lanzamiento canario y especificar el porcentaje de usuarios que verán la nueva funcionalidad, todo ello automatizado y rastreable en el CI/CD.
5. Gestión del Ciclo de Vida de las Flags (Flag Clean-up) 🧹
Las flags deben tener un ciclo de vida. Una vez que una funcionalidad ha sido completamente lanzada y se ha estabilizado, la flag asociada a menudo se vuelve redundante y puede eliminarse (o archivarse en LaunchDarkly). Esto previene la deuda técnica de flags.
Considera un paso en tu pipeline que archive flags obsoletas, quizás ejecutado de forma programada o manual:
# .github/workflows/flag-cleanup.yml
name: Archive Old Feature Flags
on:
schedule:
- cron: '0 0 * * MON' # Cada lunes a medianoche
workflow_dispatch:
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Archive old 'new-feature-enabled' flag
env:
LD_ACCESS_TOKEN: ${{ secrets.LD_ACCESS_TOKEN }}
LD_PROJECT_KEY: 'my-project-key'
LD_ENVIRONMENT_KEY: 'production'
FLAG_KEY_TO_ARCHIVE: 'old-feature-flag'
run: |
echo "Archiving feature flag '${FLAG_KEY_TO_ARCHIVE}' in environment '${LD_ENVIRONMENT_KEY}'..."
# Para archivar una flag, debes establecer su estado 'on' a false en todos los entornos
# y luego usar la operación de 'archive'. La API para archivar es un POST.
# Este es un ejemplo simplificado. La API real para archivar puede requerir más pasos.
# Es mejor usar el CLI para estas operaciones.
# Ejemplo con el CLI de LaunchDarkly (si lo tuvieras instalado en el runner)
# ld-cli flags archive --project ${LD_PROJECT_KEY} --flag ${FLAG_KEY_TO_ARCHIVE}
# Usando curl para una simulación (no es el método oficial de archivo)
curl -X PATCH "https://app.launchdarkly.com/api/v2/flags/${LD_PROJECT_KEY}/${LD_ENVIRONMENT_KEY}/${FLAG_KEY_TO_ARCHIVE}" \
-H "Authorization: ${LD_ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '[{"op": "replace", "path": "/environments/${LD_ENVIRONMENT_KEY}/on", "value": false}]'
sleep 5 # Pequeña espera
echo "Flag '${FLAG_KEY_TO_ARCHIVE}' marked for archiving. Consult LaunchDarkly UI for full archiving."
# LaunchDarkly tiene una operación de API /archive para flags, pero su uso directo puede ser complejo.
# El CLI o el SDK de automatización son preferibles.
📈 Estrategias Avanzadas y Mejores Prácticas
La integración de feature flags con CI/CD abre un abanico de posibilidades. Aquí te presento algunas estrategias avanzadas y mejores prácticas:
1. Feature Flag como parte del proceso de revisión de código
Cuando se introduce una nueva funcionalidad detrás de una flag, esta flag y su ciclo de vida deben ser parte de la revisión del código. ¿Es el nombre de la flag claro? ¿Están los tratamientos por defecto correctamente definidos? ¿Hay un plan para retirar la flag?
2. Contextos de usuario dinámicos
Enriquece tus contextos de usuario de LaunchDarkly con datos relevantes de tu aplicación (plan de suscripción, antigüedad del cliente, historial de compras, etc.). Esto permite una segmentación extremadamente granular y personalización avanzada.
3. Observabilidad de las Feature Flags
Integra LaunchDarkly con tus herramientas de monitoreo y logging. Saber cuándo se activa o desactiva una flag y cómo afecta al rendimiento o al comportamiento del usuario es fundamental. LaunchDarkly ofrece integraciones con herramientas como Datadog, New Relic, etc.
4. Pruebas Automatizadas con Flags
Tu suite de pruebas automatizadas debe considerar el estado de las flags. En tus entornos de pruebas, deberías ejecutar tests tanto con las flags activadas como desactivadas para asegurar que ambas ramas del código funcionan correctamente. Esto puede implicar ejecutar tus pipelines CI/CD múltiples veces con diferentes configuraciones de flags, o usar herramientas de testing que puedan manipular el contexto de las flags.
5. Documentación y Política de Flags
Establece una política clara sobre cómo se nombran las flags, quién es responsable de ellas, cuándo deben archivarse y cómo se comunican los cambios. Una wiki o una herramienta de gestión de proyectos puede ser útil para esto.
Tabla Comparativa: CI/CD sin Flags vs. CI/CD con LaunchDarkly y Flags
| Característica | CI/CD Tradicional (sin Flags) | CI/CD con LaunchDarkly y Feature Flags |
|---|---|---|
| --- | --- | --- |
| Riesgo de despliegue | Alto (despliegue de nuevas funcionalidades) | Bajo (funcionalidades ocultas por defecto) |
| Reversión de errores | Lento (requiere redeploy/rollback) | Instantáneo (desactivar flag) |
| --- | --- | --- |
| Lanzamientos | Binarios (todo o nada) | Progresivos (porcentaje, atributos) |
| Pruebas A/B | Difícil de implementar | Fácil de configurar y gestionar |
| --- | --- | --- |
| Integración de código | Más conflictos, ramas de características largas | Continuo, ramas cortas, trunk-based development |
| Control de funciones | Basado en código (redeploy) | Basado en configuración (tiempo de ejecución) |
| --- | --- | --- |
| Feedback temprano | Limitado hasta el lanzamiento completo | Se puede obtener feedback de grupos pequeños |
| Personalización | Limitada | Muy granular por usuario/contexto |
✅ Conclusión
La integración de LaunchDarkly y las feature flags en tus pipelines CI/CD no es solo una mejora incremental; es una transformación fundamental en cómo entregas software. Te permite moverte más rápido, con mayor seguridad y un control sin precedentes sobre tus funcionalidades.
Al automatizar la gestión de tus flags, pasas de una gestión manual y propensa a errores a un sistema robusto y programático que se alinea perfectamente con los principios de DevOps.
Te animo a explorar las posibilidades que esta combinación ofrece y a experimentar con los diferentes tipos de flags y estrategias de lanzamiento. La clave es empezar pequeño, integrar progresivamente y aprender de tus experiencias.
¡Feliz feature flagging!
Tutoriales relacionados
- Automatización Avanzada: Integrando Pruebas de Mutación en tu Pipeline CI/CDadvanced18 min
- Asegurando la Cadena de Suministro de Software en CI/CD con SLSA: Un Enfoque Integralintermediate15 min
- Implementando Blue/Green Deployments con Kubernetes y GitOps para CI/CD sin Downtimeintermediate20 min
- Asegurando Despliegues: Implementando Aprobaciones Manuales en Pipelines GitLab CI/CDintermediate15 min
- Optimización de Pipelines CI/CD con Build Caching Distribuido: Acelerando Tus Buildsintermediate15 min
Comentarios (0)
Aún no hay comentarios. ¡Sé el primero!