Plantillas listas para copiar y pegar para lenguajes habituales, registros privados e infraestructura Enterprise.
Plantillas listas para copiar y pegar para lenguajes y casos de uso habituales. Cada plantilla es autosuficiente. Combínalas para crear tu configuración completa.Para ver un desglose completo de cada campo, consulta la referencia de plantillas.
Secretos: Las plantillas hacen referencia a los secretos mediante $SECRET_NAME. Configúralos en Settings > Secrets antes de usar una plantilla. Nunca incrustes credenciales directamente en tu plantilla.
Plantillas mínimas para las configuraciones más habituales. Copia uno, pégalo en el editor de plantillas y listo.
Proyecto Node.js
initialize: | npm install -g pnpmmaintenance: | pnpm installknowledge: - name: lint contents: | Ejecuta `pnpm lint` para comprobar si hay errores. - name: test contents: | Ejecuta `pnpm test` para la suite completa.
Proyecto Python
initialize: | curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: | uv syncknowledge: - name: lint contents: | Ejecuta `uv run ruff check .` para hacer linting. - name: test contents: | Ejecuta `uv run pytest` para la suite completa.
Full-stack (Node + Python)
initialize: - name: Instalar pnpm run: npm install -g pnpm - name: Install uv run: curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: - name: Dependencias del frontend run: (cd frontend && pnpm install) - name: Dependencias del backend run: (cd backend && uv sync)knowledge: - name: structure contents: | - `frontend/` — app de React (pnpm) - `backend/` — API de Python (uv) - name: test contents: | Frontend: cd frontend && pnpm test Backend: cd backend && uv run pytest
Pasos de compilación para cada repositorio, gestión de dependencias y entradas de Knowledge. Configúralos en Settings > Configuración de Environment > [tu repo].
initialize: | nvm install 20 nvm use 20maintenance: | npm installknowledge: - name: lint contents: | npx eslint . - name: test contents: | npm test - name: build contents: | npm run build
Usa npm install (no npm ci) en maintenance. Realiza una actualización incremental, mientras que npm ci elimina node_modules y reinstala todo desde cero en cada sesión.
Rust (mediante rustup) y Cargo vienen preinstalados en la imagen base de Devin. Omite el paso de instalación si la cadena de herramientas estable predeterminada es suficiente. Solo necesitas descargar las dependencias.
Monorepo con un frontend en Node.js y un backend en Python. Cada subproyecto tiene sus propias entradas de Knowledge.
initialize: - name: Instalar pnpm run: npm install -g pnpm - name: Install uv run: curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: - name: Instalar dependencias del frontend run: (cd packages/frontend && pnpm install) - name: Instalar dependencias del backend run: (cd packages/backend && uv sync) - name: Compilar la biblioteca compartida run: (cd packages/shared && pnpm install && pnpm build)knowledge: - name: structure contents: | Este es un monorepo con tres paquetes: - `packages/frontend` — Aplicación de React (TypeScript, pnpm) - `packages/backend` — API en Python (FastAPI, uv) - `packages/shared` — Utilidades compartidas de TypeScript (deben compilarse antes que el frontend) - name: frontend contents: | Ejecuta `cd packages/frontend && pnpm dev` para iniciar el servidor de desarrollo. Ejecuta `cd packages/frontend && pnpm lint` para ejecutar el linter. Ejecuta `cd packages/frontend && pnpm test` para ejecutar las pruebas. - name: backend contents: | Ejecuta `cd packages/backend && uv run uvicorn app.main:app --reload` para iniciar la API. Ejecuta `cd packages/backend && uv run ruff check .` para ejecutar el linter. Ejecuta `cd packages/backend && uv run pytest` para ejecutar las pruebas.
Usa subshells (cd dir && command) en lugar de cd dir && command para que el directorio de trabajo se restablezca entre pasos.
Monorepo de Java en el que distintos servicios requieren distintas versiones de JDK. Instala ambos JDK durante la configuración y luego usa entradas de knowledge para indicarle a Devin qué JAVA_HOME debe usar para cada servicio.
Configura los gestores de paquetes para resolver dependencias desde registros privados. Configúralos en Settings > Configuración de Environment > configuración de la organización (o por repositorio si solo un repositorio lo necesita).
La configuración de credenciales corresponde a maintenance, no a initialize. Los pasos que escriben secretos (contraseñas del registro, tokens de autenticación) en archivos de configuración deben usar maintenance para que las credenciales se
vuelvan a cargar en cada sesión. Los secretos se eliminan antes de guardar la instantánea, por lo que los archivos de configuración escritos durante initialize no tendrán credenciales válidas cuando se inicien las sesiones.
Si tu registro privado usa una CA corporativa, asegúrate de que el certificado de CA esté instalado primero a nivel de Enterprise. La siguiente configuración asume que la confianza en HTTPS ya
está establecida.
Configura npm para resolver paquetes con ámbito (p. ej., @myorg/*) desde un registro privado, mientras que los paquetes públicos se siguen obteniendo del registro predeterminado de npm.
Secretos requeridos
- GITHUB_PACKAGES_TOKEN — Personal Access Token o token de GitHub App con ámbito read:packages
maintenance: - name: Configure npm scoped registry run: | npm config set @myorg:registry https://npm.pkg.github.com npm config set //npm.pkg.github.com/:_authToken $GITHUB_PACKAGES_TOKEN
Sustituye @myorg por tu ámbito de npm. URLs habituales de registros privados:
Redirige todos los paquetes de npm a través de tu registro privado (no solo los paquetes con ámbito).
Secretos requeridos
NPM_REGISTRY_URL — URL completa de tu registro de npm (p. ej., https://artifactory.example.com/artifactory/api/npm/npm-virtual) - NPM_REGISTRY_HOST — Solo el hostname, sin protocolo (p. ej.,
artifactory.example.com) - REGISTRY_TOKEN — token de autenticación de npm para el registro
maintenance: - name: Configure npm to use private registry run: | npm config set registry $NPM_REGISTRY_URL npm config set //${NPM_REGISTRY_HOST}/:_authToken $REGISTRY_TOKEN npm config set strict-ssl true
Configura pnpm para resolver paquetes desde un registro privado.
Secretos requeridos
NPM_REGISTRY_URL — URL completa de tu registro de npm - NPM_REGISTRY_HOST — Solo el hostname, sin protocolo - REGISTRY_TOKEN — token de autenticación de npm para el registro
initialize: - name: Install pnpm run: npm install -g pnpmmaintenance: - name: Configure pnpm for private registry run: | pnpm config set registry $NPM_REGISTRY_URL pnpm config set //${NPM_REGISTRY_HOST}/:_authToken $REGISTRY_TOKEN
Configura Yarn (Classic v1 o Berry v2+) para resolver paquetes desde un registro privado.
Secretos requeridos
- NPM_REGISTRY_URL — URL completa de tu registro de npm/Yarn - REGISTRY_TOKEN — token de autenticación para el registro (solo Berry)
Yarn Classic (v1):
initialize: - name: Install Yarn Classic run: npm install -g yarnmaintenance: - name: Configure Yarn for private registry run: | yarn config set registry "$NPM_REGISTRY_URL" # Para paquetes con ámbito: # yarn config set @myorg:registry "https://npm.pkg.github.com"
Yarn Berry (v2+):
maintenance: - name: Configure Yarn Berry for private registry run: | yarn config set npmRegistryServer "$NPM_REGISTRY_URL" yarn config set npmAuthToken "$REGISTRY_TOKEN" # Para paquetes con ámbito: # yarn config set npmScopes.myorg.npmRegistryServer "https://npm.pkg.github.com" # yarn config set npmScopes.myorg.npmAuthToken "$GITHUB_PACKAGES_TOKEN"
Configura pip y uv para resolver paquetes desde tu registro privado de PyPI (p. ej., Nexus, Artifactory).
Secretos requeridos
PYPI_REGISTRY_URL — URL completa de tu índice de PyPI, incluidas las credenciales si son necesarias (p. ej., https://user:token@nexus.example.com/repository/pypi-proxy/simple)
Configura Poetry para resolver paquetes desde un registro privado de PyPI.
Secretos requeridos
POETRY_REGISTRY_URL — URL completa de tu registro compatible con PyPI - REGISTRY_USER — nombre de usuario del registro - REGISTRY_PASS — contraseña del registro o token de API
Instala el JDK y configura Maven para redirigir toda la resolución de dependencias a través de tu registro privado (p. ej., Artifactory, Nexus).
JDK 17 está preinstalado en la imagen base de Devin. Omite el paso de instalación si el OpenJDK 17 predeterminado es suficiente. Solo necesitas instalar Maven y configurar el registro.
Secretos requeridos
MAVEN_REGISTRY_URL — URL de tu registro de Maven (p. ej., https://artifactory.example.com/artifactory/maven-virtual) - REGISTRY_USER — Nombre de usuario del registro - REGISTRY_PASS — Contraseña del registro o
token de API
Instala el JDK y configura Gradle para resolver todas las dependencias a través de tu registro privado.
JDK 17 viene preinstalado en la imagen base de Devin. Omite el paso de instalación del JDK si el predeterminado es suficiente.
Secretos requeridos
- GRADLE_REGISTRY_URL — URL de tu registro de Gradle/Maven - REGISTRY_USER — Nombre de usuario del registro - REGISTRY_PASS — Contraseña del registro o token de API
Instala Go y configúralo para resolver módulos mediante un proxy privado de módulos (p. ej., Athens, Artifactory o un endpoint de GOPROXY).
Secretos requeridos
GO_PROXY_URL — URL de tu proxy de módulos de Go (p. ej., https://athens.corp.internal) - GIT_TOKEN — token de acceso personal para repositorios de Git privados que alojan módulos de Go
initialize: - name: Install Go run: | GO_VERSION=1.23.5 ARCH=$(dpkg --print-architecture) curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz" \ | sudo tar -xz -C /usr/local echo 'export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"' \ | sudo tee /etc/profile.d/golang.sh > /dev/null - name: Configure Go for private modules run: | cat << 'GOENV' | sudo tee /etc/profile.d/go-private.sh > /dev/null export GOPROXY="$GO_PROXY_URL,direct" export GONOSUMCHECK="corp.internal/*,github.com/myorg/*" export GOPRIVATE="corp.internal/*,github.com/myorg/*" GOENVmaintenance: - name: Authenticate Go private modules run: | git config --global url."https://$GIT_TOKEN@github.com/myorg/".insteadOf "https://github.com/myorg/"
Configura Docker para descargar desde un registro privado de contenedores.
Secretos requeridos
DOCKER_MIRROR_URL(opcional) — URL de tu mirror de Docker Hub (p. ej., https://mirror.corp.internal) - DOCKER_REGISTRY_URL — URL de tu registro privado de contenedores (p. ej.,
registry.corp.internal:5000) - DOCKER_REGISTRY_USER — Nombre de usuario del registro - DOCKER_REGISTRY_PASS — Contraseña del registro o token de API
initialize: - name: Create Docker config directory run: sudo mkdir -p /etc/dockermaintenance: - name: Configure Docker for private registry run: | # Configurar el mirror del registro (opcional — enruta las descargas de Docker Hub a través de tu registro) cat << EOF | sudo tee /etc/docker/daemon.json > /dev/null { "registry-mirrors": ["$DOCKER_MIRROR_URL"] } EOF sudo systemctl restart docker || true # Iniciar sesión en el registro de contenedores privado echo "$DOCKER_REGISTRY_PASS" | docker login "$DOCKER_REGISTRY_URL" \ --username "$DOCKER_REGISTRY_USER" \ --password-stdin
Configura Cargo para resolver crates desde un registro privado.
Rust (a través de rustup) y Cargo vienen preinstalados en la imagen base de Devin. Omite el paso de instalación si el toolchain estable predeterminado es suficiente. Solo necesitas configurar el registro.
Secretos requeridos
CARGO_REGISTRY_INDEX — URL del índice del registro privado (p. ej., sparse+https://cargo.corp.internal/api/v1/crates/) - CARGO_REGISTRY_TOKEN — Token de autenticación para el registro privado
Si solo necesitas agregar un registro privado sin sustituir crates.io, elimina las secciones [source.crates-io] y [source.private] y usa cargo install --registry private o [dependencies] my-crate = { version = "1.0", registry = "private" } en Cargo.toml.
Ruby / Bundler
Instala Ruby y configura Bundler para resolver las gemas desde un servidor privado de gemas.
Secretos requeridos
GEM_SERVER_URL — URL de tu servidor privado de gemas (p. ej., https://artifactory.example.com/artifactory/api/gems/gems-virtual) - REGISTRY_USER — Nombre de usuario del registro - REGISTRY_PASS — Contraseña o token de API del registro
initialize: - name: Install Ruby run: | sudo apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ruby-fullmaintenance: - name: Configure Bundler for private gem server run: | bundle config set mirror.https://rubygems.org "$GEM_SERVER_URL" bundle config set "$GEM_SERVER_URL" "$REGISTRY_USER:$REGISTRY_PASS"
Patrones de URL habituales para servidores de gemas:
Los tokens de AWS CodeArtifact caducan al cabo de 12 horas. Usa maintenance para renovar el token al inicio de cada sesión. Este ejemplo configura npm, pip y Maven para usar CodeArtifact.
awscli viene preinstalado en la imagen base de Devin. Solo necesitas renovar el token y configurar el registro.
Secretos requeridos
AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY — credenciales de IAM con los permisos codeartifact:GetAuthorizationToken y sts:GetServiceBearerToken - CA_DOMAIN — nombre de tu dominio de CodeArtifact
CA_DOMAIN_OWNER — ID de la cuenta de AWS propietaria del dominio - CA_REGION — región de AWS (p. ej., us-east-1) - CA_NPM_REPO, CA_PYPI_REPO, CA_MAVEN_REPO — nombres de los repositorios de cada ecosistema
Infraestructura a nivel de máquina que se aplica a todas las organizaciones y repositorios. Configúrala en Settings > entorno base de Devin (a nivel Enterprise) o Settings > Configuración de Environment > configuración de la organización (a nivel de organización).
Certificado de autoridad de certificación corporativa
Tu organización usa una autoridad certificadora privada para los servicios internos. Devin necesita el certificado raíz para conectarse a los repositorios y herramientas internos mediante HTTPS.
Secretos requeridos
- CORP_ROOT_CA_B64 — Certificado PEM codificado en Base64 de tu CA corporativa. Genéralo con: cat corp-root-ca.crt | base64 -w0
Si tu organización usa múltiples certificados de CA (p. ej., CAs separadas para distintos servicios internos).
Secretos requeridos
- CORP_ROOT_CA_B64 — certificado de CA principal codificado en Base64 - CORP_INTERMEDIATE_CA_B64 — certificado de CA intermedio codificado en Base64
initialize: - name: Install corporate CA certificates run: | echo "$CORP_ROOT_CA_B64" | base64 -d \ | sudo tee /usr/local/share/ca-certificates/corp-root-ca.crt > /dev/null echo "$CORP_INTERMEDIATE_CA_B64" | base64 -d \ | sudo tee /usr/local/share/ca-certificates/corp-intermediate-ca.crt > /dev/null sudo update-ca-certificates # Crear un paquete combinado para herramientas que necesitan un único archivo CA cat /usr/local/share/ca-certificates/corp-*.crt \ | sudo tee /usr/local/share/ca-certificates/corp-bundle.crt > /dev/null echo 'export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/corp-bundle.crt' \ | sudo tee /etc/profile.d/node-ca.sh > /dev/null
Proxy HTTP/HTTPS
Dirige todo el tráfico de red a través de un proxy corporativo.
Secretos requeridos
CORP_HTTP_PROXY — URL del proxy HTTP (p. ej., http://proxy.corp.example.com:8080) - CORP_HTTPS_PROXY — URL del proxy HTTPS - CORP_NO_PROXY — Lista de hosts separados por comas para omitir el proxy (p. ej.,
localhost,127.0.0.1,.corp.example.com)
Si tu proxy corporativo requiere autenticación con nombre de usuario y contraseña.
Secretos requeridos
PROXY_USER — Nombre de usuario del proxy - PROXY_PASS — Contraseña del proxy - PROXY_HOST — Host y puerto del proxy (p. ej., proxy.corp.example.com:8080) - CORP_NO_PROXY — Hosts que deben omitir el proxy
Configuración combinada para entornos que necesitan tanto una CA corporativa como un proxy. Esto es habitual en entornos empresariales donde los servicios internos usan certificados privados y todo el tráfico debe pasar por un proxy.
Secretos requeridos
CORP_ROOT_CA_B64 — Certificado de CA corporativa codificado en Base64 - CORP_HTTP_PROXY, CORP_HTTPS_PROXY — URL del proxy - CORP_NO_PROXY — Hosts que deben omitir el proxy
Solo se puede acceder a tus registros privados, servidores Git u otros servicios internos a través de una VPN. Debe ejecutarse antes que otros módulos que necesiten acceso de red a recursos internos.
Secretos requeridos
OpenVPN:
VPN_CONFIG_B64 — Archivo de configuración de OpenVPN codificado en Base64 (.ovpn). Genéralo con: cat corp.ovpn | base64 -w0
VPN_AUTH_USER(opcional) — Nombre de usuario de la VPN, si tu VPN requiere autenticación con nombre de usuario y contraseña
VPN_AUTH_PASS(opcional) — Contraseña de la VPN
WireGuard:
WG_CONFIG_B64 — Archivo de configuración de WireGuard codificado en Base64. Genéralo con: cat wg0.conf | base64 -w0
OpenVPN:
initialize: - name: Install and configure OpenVPN run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openvpn # Escribir la configuración de VPN sudo mkdir -p /etc/openvpn/client echo "$VPN_CONFIG_B64" | base64 -d \ | sudo tee /etc/openvpn/client/corp.conf > /dev/null # Si la VPN requiere autenticación con usuario/contraseña if [ -n "${VPN_AUTH_USER:-}" ] && [ -n "${VPN_AUTH_PASS:-}" ]; then printf '%s\n%s\n' "$VPN_AUTH_USER" "$VPN_AUTH_PASS" \ | sudo tee /etc/openvpn/client/auth.txt > /dev/null sudo chmod 600 /etc/openvpn/client/auth.txt echo "auth-user-pass /etc/openvpn/client/auth.txt" \ | sudo tee -a /etc/openvpn/client/corp.conf > /dev/null fi # Iniciar el túnel VPN sudo systemctl daemon-reload sudo systemctl enable --now openvpn-client@corp # Esperar a que el túnel se establezca for i in $(seq 1 30); do if ip link show tun0 >/dev/null 2>&1; then break; fi sleep 1 done
Tu organización requiere que todos los commits de Git estén firmados y quieres que GitHub marque los commits de Devin como Verified.
Secretos requeridos
GPG_PRIVATE_KEY_B64 — Clave privada de GPG codificada en Base64. Genérala con: gpg --export-secret-keys <key-id> | base64 -w0
GIT_USER_NAME — Nombre del autor de Git (p. ej., Devin AI)
GIT_USER_EMAIL — Correo electrónico del autor de Git. Debe coincidir con un UID de la clave GPG; de lo contrario, GitHub no verificará la firma.
Sube también la clave pública correspondiente a la cuenta de GitHub cuyas credenciales usa Devin para hacer push (en GitHub Settings > SSH and GPG keys). GitHub solo marca los commits como Verified cuando la clave pública de firma está registrada en la cuenta que creó el commit.
initialize: - name: Prepare GPG and git signing config run: | # Permitir que GPG funcione sin una TTY echo 'export GPG_TTY=$(tty)' | sudo tee -a /etc/profile.d/gpg.sh > /dev/nullmaintenance: - name: Import GPG key and configure git signing run: | echo "$GPG_PRIVATE_KEY_B64" | base64 -d | gpg --batch --import 2>/dev/null KEY_ID=$(gpg --list-secret-keys --keyid-format long 2>/dev/null \ | grep sec | head -1 | awk '{print $2}' | cut -d'/' -f2) git config --global user.signingkey "$KEY_ID" git config --global commit.gpgsign true git config --global tag.gpgsign true git config --global gpg.program gpg
Identidad de Git y claves SSH
Configura la identidad de Git y las claves SSH de Devin para acceder a servidores Git privados.
Secretos requeridos
GIT_USER_NAME — Nombre del autor de Git - GIT_USER_EMAIL — Correo electrónico del autor de Git - SSH_PRIVATE_KEY_B64 — Clave privada SSH codificada en Base64. Genérala con: cat ~/.ssh/id_ed25519 | base64 -w0 -
SSH_KNOWN_HOSTS_B64 — Entradas de hosts conocidos codificadas en Base64. Genéralas con: ssh-keyscan git.corp.internal | base64 -w0 - SSH_CONFIG_B64(opcional) — Archivo de configuración SSH codificado en Base64
initialize: - name: Configure git identity run: | git config --global user.name "$GIT_USER_NAME" git config --global user.email "$GIT_USER_EMAIL" # Preparar el directorio SSH mkdir -p ~/.ssh && chmod 700 ~/.sshmaintenance: - name: Install SSH keys run: | # Instalar la clave privada SSH (en maintenance para que se vuelva a cargar en cada sesión) echo "$SSH_PRIVATE_KEY_B64" | base64 -d > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 # Agregar hosts conocidos para tu servidor Git echo "$SSH_KNOWN_HOSTS_B64" | base64 -d >> ~/.ssh/known_hosts # Instalar opcionalmente una configuración SSH personalizada if [ -n "${SSH_CONFIG_B64:-}" ]; then echo "$SSH_CONFIG_B64" | base64 -d > ~/.ssh/config chmod 600 ~/.ssh/config fi
Genera la entrada de hosts conocidos para tu servidor Git con ssh-keyscan git.corp.internal | base64 -w0.
Instale paquetes del sistema que no estén en la imagen predeterminada de Devin (p. ej., bibliotecas nativas para el procesamiento de imágenes o la generación de PDF).
Establece variables de entorno persistentes que deben estar disponibles en cada sesión.La forma recomendada es escribir líneas KEY=VALUE en el archivo $ENVRC. Las variables escritas en $ENVRC se exportan automáticamente para todos los pasos posteriores y para la sesión de Devin (de forma similar a $GITHUB_ENV de GitHub Actions).
Ambos métodos funcionan. $ENVRC es más sencillo y se recomienda en la mayoría de los casos.
Configuración regional y zona horaria
Las imágenes base predeterminadas pueden tener la configuración regional mal configurada. Configure la configuración regional y la zona horaria para evitar advertencias de las herramientas de compilación, Java, Python y Git.
initialize: - name: Configure locale and timezone run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq locales # Generar y establecer la configuración regional sudo sed -i 's/^# *en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen sudo locale-gen sudo update-locale LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 cat << 'LOCALE' | sudo tee /etc/profile.d/locale.sh > /dev/null export LANG="en_US.UTF-8" export LC_ALL="en_US.UTF-8" LOCALE # Establecer la zona horaria sudo timedatectl set-timezone UTC 2>/dev/null || \ sudo ln -sfn /usr/share/zoneinfo/UTC /etc/localtime
Límites de recursos (ulimits)
Las compilaciones de Java, Gradle y Node.js suelen alcanzar el límite predeterminado de 1024 archivos abiertos. Auméntelo para evitar fallos de compilación.
initialize: - name: Raise resource limits run: | cat << 'LIMITS' | sudo tee /etc/security/limits.d/99-devin.conf > /dev/null * soft nofile 65536 * hard nofile 65536 * soft nproc 65536 * hard nproc 65536 LIMITS # También establecer el máximo del kernel echo "fs.file-max = 65536" | sudo tee /etc/sysctl.d/99-devin-filemax.conf > /dev/null sudo sysctl -p /etc/sysctl.d/99-devin-filemax.conf 2>/dev/null || true
Reemplazo del mirror de APT
En entornos aislados o restringidos, sustituye los repositorios APT predeterminados de Ubuntu por un mirror interno.
Secretos requeridos
- APT_MIRROR_URL — URL de tu mirror interno de APT (p. ej., https://artifactory.example.com/artifactory/ubuntu-remote)
initialize: - name: Replace APT sources with internal mirror run: | # Hacer copia de seguridad de las fuentes originales sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak # Reemplazar todos los mirrors de Ubuntu con tu mirror interno sudo sed -i "s|http://archive.ubuntu.com/ubuntu|$APT_MIRROR_URL|g" /etc/apt/sources.list sudo sed -i "s|http://security.ubuntu.com/ubuntu|$APT_MIRROR_URL|g" /etc/apt/sources.list sudo apt-get update -qq
direnv ya viene integrado en el shell de Devin, por lo que las variables de .envrc se cargan automáticamente. No necesitas hacer source manualmente.
Para las variables de entorno sensibles (API keys, tokens, contraseñas de bases de datos), usa secretos del repositorio en lugar de archivos .envrc. Los secretos del repositorio se almacenan de forma segura y se inyectan durante la sesión. Nunca aparecen en tu blueprint ni en tu instantánea.
Cambio de versión de Node según el repositorio
Usa nvm (preinstalado) para cambiar la versión de Node.js de cada repositorio mediante .nvmrc.
nvm use lee el archivo .nvmrc de la raíz del repositorio. Asegúrate de que tu repositorio incluya ese archivo (p. ej., con 20).
Autenticación en el navegador (Playwright)
Devin proporciona un navegador Chrome con un endpoint de CDP en localhost:29229durante las sesiones. Usa scripts de Playwright para automatizar el inicio de sesión en el navegador.
El navegador solo está disponible durante las sesiones, no en las compilaciones de instantánea. Instala Playwright en initialize y mantén los scripts de inicio de sesión en tu repositorio.
initialize: | pip install playwright playwright install chromiummaintenance: | npm installknowledge: - name: browser-auth contents: | This project requires browser authentication. Run the login script before interacting with the app: python scripts/login.py Devin's Chrome browser is accessible via CDP at: http://localhost:29229
Script de ejemplo para iniciar sesión (scripts/login.py):
from playwright.sync_api import sync_playwrightimport oswith sync_playwright() as p: browser = p.chromium.connect_over_cdp("http://localhost:29229") context = browser.contexts[0] page = context.pages[0] if context.pages else context.new_page() page.goto("https://internal-tool.example.com/login") page.fill("#username", os.environ["TOOL_USERNAME"]) page.fill("#password", os.environ["TOOL_PASSWORD"]) page.click('button[type="submit"]') page.wait_for_url("**/dashboard")
Guarda las credenciales de inicio de sesión como secretos, no en el código fuente. Para mantener la autenticación a largo plazo, confirma los scripts de inicio de sesión en .agents/skills/ para que Devin pueda autenticarse de nuevo automáticamente.
Herramientas personalizadas del sistema y PATH
Instala paquetes del sistema, binarios personalizados y configura la variable PATH en initialize.
Devin permite ejecutar GitHub Actions basadas en Node.js directamente en blueprints. Esto es útil para instalar versiones específicas de herramientas mediante las mismas acciones que usa tu CI.
Acciones como setup-node y setup-python modifican PATH y las variables de entorno. Los binarios instalados por una acción están disponibles en todos los pasos posteriores y en maintenance. Solo se admiten las GitHub Actions basadas en Node.js. Las acciones compuestas y basadas en Docker no son compatibles.
No necesitas GitHub Actions para la configuración básica de herramientas. Los comandos directos de shell (nvm install 20, curl ... | sh, apt-get install) funcionan igual de bien y suelen ser más sencillos. Las GitHub Actions resultan más útiles cuando quieres reproducir exactamente tu configuración de CI o necesitas la comodidad de acciones como setup-java, que gestionan múltiples distribuciones.
Estos ejemplos muestran cómo se combinan las configuraciones de Enterprise y a nivel de org. En la práctica, se dividirían entre distintos ámbitos. Se muestran juntas aquí como referencia.
Stack empresarial completo (Artifactory)
Un Environment empresarial completo: certificado CA corporativo, proxy, Java (Maven), Python (pip/uv), Node.js (npm) y Docker, todos apuntando a una única instancia de Artifactory.
Secretos requeridos
Red y confianza (para toda la cuenta):
CORP_ROOT_CA_B64 — certificado de la CA corporativa codificado en Base64
CORP_HTTP_PROXY — URL del proxy HTTP
CORP_HTTPS_PROXY — URL del proxy HTTPS
CORP_NO_PROXY — hosts que deben omitir el proxy
Credenciales del registro (para toda la organización):
ARTIFACTORY_USER — nombre de usuario de Artifactory
ARTIFACTORY_TOKEN — token de API o contraseña de Artifactory
ARTIFACTORY_MAVEN_URL — URL del repositorio de Maven (p. ej., https://artifactory.example.com/artifactory/maven-virtual)
ARTIFACTORY_PYPI_URL — URL del repositorio de PyPI (p. ej., https://user:token@artifactory.example.com/artifactory/api/pypi/pypi-virtual/simple)
ARTIFACTORY_NPM_URL — URL del repositorio de npm (p. ej., https://artifactory.example.com/artifactory/api/npm/npm-virtual)
ARTIFACTORY_DOCKER_URL — URL del registro de Docker (p. ej., artifactory.example.com)
Esto normalmente se dividiría en tres ámbitos:
Para toda la cuenta (initialize): Certificado y proxy
En toda la organización (initialize): Instalación del entorno de ejecución del lenguaje
Para toda la organización (maintenance): Credenciales del registro (se actualizan en cada sesión)
Se muestra aquí de forma combinada como referencia:
initialize: # ── Para toda la cuenta: red y confianza ────────────────────────────────────── - name: Install corporate CA certificate run: | echo "$CORP_ROOT_CA_B64" | base64 -d \ | sudo tee /usr/local/share/ca-certificates/corp-root-ca.crt > /dev/null sudo update-ca-certificates echo 'export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/corp-root-ca.crt' \ | sudo tee /etc/profile.d/node-ca.sh > /dev/null - name: Configure system-wide proxy run: | cat << 'PROXY' | sudo tee /etc/profile.d/proxy.sh > /dev/null export http_proxy="$CORP_HTTP_PROXY" export https_proxy="$CORP_HTTPS_PROXY" export no_proxy="$CORP_NO_PROXY" export HTTP_PROXY="$CORP_HTTP_PROXY" export HTTPS_PROXY="$CORP_HTTPS_PROXY" export NO_PROXY="$CORP_NO_PROXY" PROXY source /etc/profile.d/proxy.sh # ── Para toda la organización: entornos de ejecución ────────────────────────────────────────── - name: Install JDK 17 + Maven run: | sudo apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-17-jdk-headless echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' \ | sudo tee /etc/profile.d/java.sh > /dev/null MAVEN_VERSION=3.9.9 curl -fsSL "https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \ | sudo tar -xz -C /opt sudo ln -sf /opt/apache-maven-${MAVEN_VERSION}/bin/mvn /usr/local/bin/mvn - name: Install uv run: curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: # ── Para toda la cuenta: proxy de git (se actualiza en cada sesión) ─────────────────── - name: Configure git proxy run: | git config --global http.proxy "$CORP_HTTP_PROXY" git config --global https.proxy "$CORP_HTTPS_PROXY" # ── Para toda la organización: credenciales de registro (se actualizan en cada sesión) ────────────── - name: Configure Maven → Artifactory run: | mkdir -p ~/.m2 cat > ~/.m2/settings.xml << EOF <settings> <mirrors> <mirror> <id>artifactory</id> <mirrorOf>*</mirrorOf> <url>$ARTIFACTORY_MAVEN_URL</url> </mirror> </mirrors> <servers> <server> <id>artifactory</id> <username>$ARTIFACTORY_USER</username> <password>$ARTIFACTORY_TOKEN</password> </server> </servers> </settings> EOF - name: Configure pip/uv → Artifactory PyPI run: | mkdir -p ~/.config/pip cat > ~/.config/pip/pip.conf << EOF [global] index-url = $ARTIFACTORY_PYPI_URL trusted-host = $(echo "$ARTIFACTORY_PYPI_URL" | sed 's|https\?://||;s|/.*||') EOF echo "export UV_INDEX_URL=$ARTIFACTORY_PYPI_URL" \ | sudo tee /etc/profile.d/uv-registry.sh > /dev/null - name: Configure npm → Artifactory run: | npm config set registry "$ARTIFACTORY_NPM_URL" REGISTRY_HOST=$(echo "$ARTIFACTORY_NPM_URL" | sed 's|https\?://||;s|/.*||') npm config set "//${REGISTRY_HOST}/:_authToken" "$ARTIFACTORY_TOKEN" - name: Configure Docker → Artifactory run: | echo "$ARTIFACTORY_TOKEN" | docker login "$ARTIFACTORY_DOCKER_URL" \ --username "$ARTIFACTORY_USER" \ --password-stdin
En este ejemplo, todos los registries apuntan a la misma instancia de Artifactory, pero usan rutas de URL diferentes. Cada ecosistema de paquetes tiene su propio formato de endpoint. Las URL de Maven, PyPI, npm y Docker son diferentes incluso para el mismo registry.
Varios lenguajes con distintos repositorios
Cuando distintos lenguajes usan diferentes repositorios privados (p. ej., Maven desde Nexus, npm desde GitHub Packages, Python desde Artifactory).
Secretos requeridos
NEXUS_MAVEN_URL — URL del repositorio Maven de Nexus - NEXUS_USER — nombre de usuario de Nexus - NEXUS_PASS — contraseña de Nexus - GITHUB_PACKAGES_TOKEN — token de acceso personal de GitHub con el ámbito read:packages -
ARTIFACTORY_USER — nombre de usuario de Artifactory - ARTIFACTORY_TOKEN — token de API de Artifactory - GIT_TOKEN — token de acceso personal para módulos privados de Go
En un entorno completamente aislado de la red, Devin no puede acceder a ninguna URL pública. Todas las herramientas, los entornos de ejecución y los paquetes deben provenir de mirrors internos.
Secretos requeridos
Certificados:
CORP_ROOT_CA_B64 — Certificado de CA corporativa codificado en Base64
Acceso al mirror:
APT_MIRROR_URL — URL del mirror interno de Ubuntu APT
MIRROR_USER — Nombre de usuario para autenticarse en el mirror
MIRROR_PASS — Contraseña para autenticarse en el mirror
JDK_TARBALL_URL — URL para descargar el archivo tar del JDK desde el mirror interno
NODE_TARBALL_URL — URL para descargar el archivo tar de Node.js desde el mirror interno
Registros de paquetes:
INTERNAL_MAVEN_URL — URL del registro interno de Maven
INTERNAL_NPM_URL — URL del registro interno de npm
INTERNAL_PYPI_URL — URL del registro interno de PyPI
En entornos aislados de la red, todas las herramientas que Devin necesita (entornos de ejecución, herramientas de CLI, etc.) deben estar disponibles en tus repositorios espejo internos. No se puede acceder a los repositorios públicos ni a los sitios de descarga.
VPN + certificados + proxy + lenguajes
Una configuración empresarial completa que combina conectividad VPN con certificados, proxy y compatibilidad con varios idiomas. Este es el orden de operaciones recomendado.
Secretos requeridos
VPN:
VPN_CONFIG_B64 — Archivo de configuración de OpenVPN codificado en Base64
Red y confianza:
CORP_ROOT_CA_B64 — Certificado de la CA corporativa codificado en Base64
CORP_HTTP_PROXY — URL del proxy HTTP
CORP_HTTPS_PROXY — URL del proxy HTTPS
CORP_NO_PROXY — Hosts excluidos del proxy
Credenciales del registro:
MAVEN_REGISTRY_URL — URL del registro de Maven
NPM_REGISTRY_URL — URL del registro de npm
PYPI_REGISTRY_HOST — Nombre de host del registro de PyPI
REGISTRY_USER — Nombre de usuario del registro (para Maven y pip)
REGISTRY_PASS — Contraseña del registro (para Maven y pip)
REGISTRY_TOKEN — Token de autenticación de npm
initialize: # 1. VPN — debe ir primero para que los recursos internos sean accesibles - name: Establish VPN connection run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openvpn sudo mkdir -p /etc/openvpn/client echo "$VPN_CONFIG_B64" | base64 -d \ | sudo tee /etc/openvpn/client/corp.conf > /dev/null sudo systemctl daemon-reload sudo systemctl enable --now openvpn-client@corp for i in $(seq 1 30); do if ip link show tun0 >/dev/null 2>&1; then break; fi sleep 1 done # 2. DNS — resolver nombres de host internos - name: Configure DNS run: | sudo mkdir -p /etc/systemd/resolved.conf.d cat << 'DNS' | sudo tee /etc/systemd/resolved.conf.d/corp.conf > /dev/null [Resolve] DNS=10.0.0.53 Domains=corp.internal DNS sudo systemctl restart systemd-resolved || true # 3. Certificados — confiar en las CAs internas - name: Install CA certificate run: | echo "$CORP_ROOT_CA_B64" | base64 -d \ | sudo tee /usr/local/share/ca-certificates/corp-root-ca.crt > /dev/null sudo update-ca-certificates echo 'export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/corp-root-ca.crt' \ | sudo tee /etc/profile.d/node-ca.sh > /dev/null # 4. Proxy — enrutar el tráfico a través del proxy corporativo - name: Configure proxy run: | cat << 'PROXY' | sudo tee /etc/profile.d/proxy.sh > /dev/null export http_proxy="$CORP_HTTP_PROXY" export https_proxy="$CORP_HTTPS_PROXY" export no_proxy="$CORP_NO_PROXY" export HTTP_PROXY="$CORP_HTTP_PROXY" export HTTPS_PROXY="$CORP_HTTPS_PROXY" export NO_PROXY="$CORP_NO_PROXY" PROXY source /etc/profile.d/proxy.sh # 5. Entornos de ejecución - name: Install JDK 17 run: | sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-17-jdk-headless echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' \ | sudo tee /etc/profile.d/java.sh > /dev/null - name: Install Node.js tooling run: npm install -g pnpm - name: Install uv run: curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: - name: Configure git proxy run: | git config --global http.proxy "$CORP_HTTP_PROXY" git config --global https.proxy "$CORP_HTTPS_PROXY" - name: Configure Maven run: | mkdir -p ~/.m2 cat > ~/.m2/settings.xml << EOF <settings> <mirrors> <mirror> <id>corp</id> <mirrorOf>*</mirrorOf> <url>$MAVEN_REGISTRY_URL</url> </mirror> </mirrors> <servers> <server> <id>corp</id> <username>$REGISTRY_USER</username> <password>$REGISTRY_PASS</password> </server> </servers> </settings> EOF - name: Configure npm run: | npm config set registry "$NPM_REGISTRY_URL" NPM_HOST=$(echo "$NPM_REGISTRY_URL" | sed 's|https\?://||;s|/.*||') npm config set "//${NPM_HOST}/:_authToken" "$REGISTRY_TOKEN" - name: Configure pip/uv run: | mkdir -p ~/.config/pip cat > ~/.config/pip/pip.conf << EOF [global] index-url = https://$REGISTRY_USER:$REGISTRY_PASS@${PYPI_REGISTRY_HOST}/simple EOF echo "export UV_INDEX_URL=https://$REGISTRY_USER:$REGISTRY_PASS@${PYPI_REGISTRY_HOST}/simple" \ | sudo tee /etc/profile.d/uv-registry.sh > /dev/null
El orden de los pasos de initialize es importante. La VPN debe ir primero (para que los hosts internos sean accesibles), luego el DNS (para que los nombres se resuelvan), después los certificados (para que HTTPS funcione), luego el proxy (para que el tráfico se enrute correctamente) y, por último, los entornos de ejecución, que pueden descargarse desde mirrors internos).
Prueba primero los comandos en una sesión. Ejecuta los comandos manualmente en una sesión de Devin antes de agregarlos a tu plantilla. Es más rápido que esperar un ciclo completo de compilación.
Usa initialize para herramientas que se instalan una sola vez y maintenance para dependencias. Todo lo que tarde varios minutos en instalarse (compiladores, binarios grandes, herramientas globales) debe ir en initialize. Los comandos rápidos de dependencias (npm install, uv sync) van en maintenance.
Haz que los comandos de maintenance sean rápidos. Procura que tarden menos de 2 minutos. Se ejecutan al inicio de cada sesión.
Usa $ENVRC para las variables de entorno. No escribas en .bashrc ni en .profile. $ENVRC es el mecanismo compatible para establecer variables entre pasos y sesiones.
Pon nombre a tus pasos. La forma expandida con campos name hace que los fallos en los registros de compilación sean mucho más fáciles de identificar.
Usa subshells para monorepos.(cd packages/foo && npm install) se ejecuta en una subshell para que los pasos posteriores no se vean afectados por el cambio de directorio.
Usa npm install, no npm ci.npm ci elimina node_modules y reinstala todo desde cero en cada sesión, lo que lo hace lento para maintenance.
Usa secretos del repo para los valores sensibles. Configúralos en Settings > Secrets con ámbito de repo, en lugar de incluirlos directamente en las plantillas.