Blueprints prontos para copiar e colar para linguagens comuns, registros privados e infraestrutura Enterprise.
Blueprints prontos para copiar e colar para linguagens e casos de uso comuns. Cada template é independente. Combine-os para montar sua configuração completa.Para ver uma descrição completa de cada campo, consulte a referência de blueprints.
Segredos: Os templates fazem referência a segredos usando $SECRET_NAME. Configure-os em Configurações → Secrets antes de usar um template. Nunca inclua credenciais diretamente no seu blueprint.
Blueprints mínimos para as configurações mais comuns. Copie um, cole no editor de blueprints e pronto.
Projeto em Node.js
initialize: | npm install -g pnpmmaintenance: | pnpm installknowledge: - name: lint contents: | Execute `pnpm lint` para verificar erros. - name: test contents: | Execute `pnpm test` para o conjunto completo de testes.
Projeto em Python
initialize: | curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: | uv syncknowledge: - name: lint contents: | Execute `uv run ruff check .` para rodar o lint. - name: test contents: | Execute `uv run pytest` para o conjunto completo de testes.
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: Dependências do frontend run: (cd frontend && pnpm install) - name: Dependências do backend run: (cd backend && uv sync)knowledge: - name: structure contents: | - `frontend/` — app React (pnpm) - `backend/` — API em Python (uv) - name: test contents: | Frontend: cd frontend && pnpm test Backend: cd backend && uv run pytest
Etapas de build por repositório, gerenciamento de dependências e entradas do Knowledge. Defina isso em Configurações > Configuração de ambiente > [seu repositório].
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
Use npm install (não npm ci) em maintenance. Ele faz uma atualização incremental, enquanto npm ci exclui node_modules e reinstala tudo do zero a cada sessão.
Rust (via rustup) e Cargo já vêm pré-instalados na imagem base do Devin. Pule a etapa de instalação se a toolchain estável padrão for suficiente. Você só precisa baixar as dependências.
Monorepo com frontend em Node.js e backend em Python. Cada subprojeto recebe suas próprias entradas no Knowledge.
initialize: - name: Instalar pnpm run: npm install -g pnpm - name: Instalar uv run: curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: - name: Instalar dependências do frontend run: (cd packages/frontend && pnpm install) - name: Instalar dependências do backend run: (cd packages/backend && uv sync) - name: Build da biblioteca compartilhada run: (cd packages/shared && pnpm install && pnpm build)knowledge: - name: structure contents: | Este é um monorepo com três pacotes: - `packages/frontend` — app React (TypeScript, pnpm) - `packages/backend` — API Python (FastAPI, uv) - `packages/shared` — utilitários TypeScript compartilhados (o build deve ser feito antes do frontend) - name: frontend contents: | Execute `cd packages/frontend && pnpm dev` para iniciar o servidor de desenvolvimento. Execute `cd packages/frontend && pnpm lint` para rodar o lint. Execute `cd packages/frontend && pnpm test` para testar. - name: backend contents: | Execute `cd packages/backend && uv run uvicorn app.main:app --reload` para iniciar a API. Execute `cd packages/backend && uv run ruff check .` para rodar o lint. Execute `cd packages/backend && uv run pytest` para testar.
Use subshells (cd dir && command) em vez de cd dir && command, para que o diretório de trabalho seja redefinido entre as etapas.
Um monorepo Java em que serviços diferentes exigem versões diferentes do JDK. Instale ambos os JDKs na configuração inicial e depois use entradas de knowledge para informar ao Devin qual JAVA_HOME usar para cada serviço.
initialize: - name: Instalar JDK 17 (primário) 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 - name: Instalar JDK 11 (serviço legado) run: | sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-11-jdk-headlessmaintenance: - name: Aquecer caches de dependências run: | export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 (cd services/api && ./gradlew dependencies --refresh-dependencies) export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 (cd services/legacy && ./gradlew dependencies --refresh-dependencies)knowledge: - name: build_api contents: | Faça o build do serviço de API (JDK 17): JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 \ cd services/api && ./gradlew clean build - name: build_legacy contents: | Faça o build do serviço legado (JDK 11): JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 \ cd services/legacy && ./gradlew clean build - name: test_all contents: | Execute os testes de todos os serviços: JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 \ (cd services/api && ./gradlew test) JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 \ (cd services/legacy && ./gradlew test)
Configure os gerenciadores de pacotes para resolver dependências usando registros privados. Defina isso em Configurações > Configuração do ambiente > configuração em nível da organização (ou por repositório, se apenas um repositório precisar disso).
A configuração de credenciais deve ser feita em maintenance, não em initialize. Etapas que gravam segredos (senhas de registro, tokens de autenticação) em arquivos de configuração devem usar maintenance para que as credenciais sejam
carregadas novamente em cada sessão. Os segredos são removidos antes de o snapshot ser salvo, portanto os arquivos de configuração gravados durante initialize não terão credenciais válidas quando as sessões começarem.
Se o seu registro privado usa uma CA corporativa, primeiro verifique se o certificado de CA está instalado no nível Enterprise. A configuração abaixo pressupõe que a confiança em HTTPS
já foi estabelecida.
Configure o npm para resolver pacotes com escopo (por exemplo, @myorg/*) a partir de um registro privado, enquanto os pacotes públicos continuam vindo do registro padrão do npm.
Segredos necessários
- GITHUB_PACKAGES_TOKEN — Token de acesso pessoal ou token do GitHub App com o escopo 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
Substitua @myorg pelo seu escopo do npm. URLs comuns de registros privados:
Direcione todos os pacotes npm pelo seu registro privado (não apenas os pacotes com escopo).
Segredos necessários
NPM_REGISTRY_URL — URL completa do seu registro npm (por exemplo, https://artifactory.example.com/artifactory/api/npm/npm-virtual) - NPM_REGISTRY_HOST — Apenas o hostname, sem protocolo (por exemplo,
artifactory.example.com) - REGISTRY_TOKEN — Token de autenticação do npm para o 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
Configure o pnpm para resolver pacotes a partir de um registro privado.
Segredos necessários
NPM_REGISTRY_URL — URL completa do seu registro npm - NPM_REGISTRY_HOST — Apenas o hostname, sem protocolo - REGISTRY_TOKEN — Token de autenticação do npm para o 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
Configure o Yarn (Classic v1 ou Berry v2+) para resolver pacotes a partir de um registro privado.
Segredos necessários
- NPM_REGISTRY_URL — URL completa do seu registro npm/Yarn - REGISTRY_TOKEN — Token de autenticação para o registro (apenas no 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 pacotes com escopo: # 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 pacotes com escopo: # yarn config set npmScopes.myorg.npmRegistryServer "https://npm.pkg.github.com" # yarn config set npmScopes.myorg.npmAuthToken "$GITHUB_PACKAGES_TOKEN"
Configure o pip e o uv para resolver pacotes do seu registro PyPI privado (por exemplo, Nexus, Artifactory).
Segredos necessários
PYPI_REGISTRY_URL — URL completa do seu índice PyPI, incluindo credenciais, se necessário (por exemplo, https://user:token@nexus.example.com/repository/pypi-proxy/simple)
Configure o Poetry para resolver pacotes de um registro PyPI privado.
Segredos necessários
POETRY_REGISTRY_URL — URL completa do seu registro compatível com PyPI - REGISTRY_USER — Nome de usuário do registro - REGISTRY_PASS — Senha do registro ou token de API
Instale o JDK e configure o Maven para usar seu registro privado como espelho para toda a resolução de dependências (por exemplo, Artifactory, Nexus).
O JDK 17 vem pré-instalado na imagem base do Devin. Pule a etapa de instalação se o OpenJDK 17 padrão for suficiente. Você só precisa instalar o Maven e configurar o registro.
Segredos necessários
MAVEN_REGISTRY_URL — URL do seu registro Maven (por exemplo, https://artifactory.example.com/artifactory/maven-virtual) - REGISTRY_USER — Nome de usuário do registro - REGISTRY_PASS — Senha do registro ou
token de API
Instale o JDK e configure o Gradle para resolver todas as dependências por meio do seu registro privado.
O JDK 17 vem pré-instalado na imagem base do Devin. Pule a etapa de instalação do JDK se a configuração padrão for suficiente.
Segredos necessários
- GRADLE_REGISTRY_URL — URL do seu registro Gradle/Maven - REGISTRY_USER — Nome de usuário do registro - REGISTRY_PASS — Senha do registro ou token de API
Instale o Go e configure-o para resolver módulos por meio de um proxy privado de módulos (por exemplo, Athens, Artifactory ou um endpoint do GOPROXY).
Segredos necessários
GO_PROXY_URL — URL do seu proxy de módulos Go (por exemplo, https://athens.corp.internal) - GIT_TOKEN — Token de acesso pessoal para repositórios Git privados que hospedam módulos 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/"
Configure o Docker para baixar imagens de um registro privado de contêineres.
Segredos necessários
DOCKER_MIRROR_URL(opcional) — URL do seu espelho do Docker Hub (por exemplo, https://mirror.corp.internal) - DOCKER_REGISTRY_URL — URL do seu registro privado de contêineres (por exemplo,
registry.corp.internal:5000) - DOCKER_REGISTRY_USER — Nome de usuário do registro - DOCKER_REGISTRY_PASS — Senha do registro ou token de API
initialize: - name: Create Docker config directory run: sudo mkdir -p /etc/dockermaintenance: - name: Configure Docker for private registry run: | # Configurar mirror de registro (opcional — roteia pulls do Docker Hub pelo seu registro) cat << EOF | sudo tee /etc/docker/daemon.json > /dev/null { "registry-mirrors": ["$DOCKER_MIRROR_URL"] } EOF sudo systemctl restart docker || true # Fazer login no registro privado de contêineres echo "$DOCKER_REGISTRY_PASS" | docker login "$DOCKER_REGISTRY_URL" \ --username "$DOCKER_REGISTRY_USER" \ --password-stdin
Configure o Cargo para resolver crates a partir de um registro privado.
Rust (via rustup) e Cargo vêm pré-instalados na imagem base do Devin. Pule a etapa de instalação se o toolchain estável padrão for suficiente. Você só precisa da configuração do registro.
Segredos necessários
CARGO_REGISTRY_INDEX — URL do índice do registro privado (por exemplo, sparse+https://cargo.corp.internal/api/v1/crates/) - CARGO_REGISTRY_TOKEN — token de autenticação para o registro privado
Se você só precisa adicionar um registro privado sem substituir o crates.io, remova as seções [source.crates-io] e [source.private] e use cargo install --registry private ou [dependencies] my-crate = { version = "1.0", registry = "private" } no Cargo.toml.
Ruby / Bundler
Instale o Ruby e configure o Bundler para resolver gems a partir de um servidor privado de gems.
Segredos necessários
GEM_SERVER_URL — URL do seu servidor privado de gems (por exemplo, https://artifactory.example.com/artifactory/api/gems/gems-virtual) - REGISTRY_USER — nome de usuário do registro - REGISTRY_PASS — senha do registro
ou token de API
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"
Os tokens do AWS CodeArtifact expiram após 12 horas. Use maintenance para renovar o token no início de cada sessão. Este exemplo configura npm, pip e Maven para usar o CodeArtifact.
awscli vem pré-instalado na imagem base do Devin. Você só precisa renovar o token e configurar o registro.
Segredos necessários
AWS_ACCESS_KEY_ID e AWS_SECRET_ACCESS_KEY — credenciais do IAM com as permissões codeartifact:GetAuthorizationToken e sts:GetServiceBearerToken - CA_DOMAIN — Nome do seu domínio do CodeArtifact
name - CA_DOMAIN_OWNER — ID da conta AWS proprietária do domínio - CA_REGION — Região da AWS (por exemplo, us-east-1) - CA_NPM_REPO, CA_PYPI_REPO, CA_MAVEN_REPO — Nomes dos repositórios para cada ecossistema
Infraestrutura no nível da máquina que se aplica a todas as org e repositórios. Configure isso em Configurações > ambiente base do Devin (para toda a Enterprise) ou em Configurações > Configuração do ambiente > Configuração no nível da organização (no nível da organização).
Sua organização usa uma autoridade certificadora privada para serviços internos. Devin precisa do certificado raiz para acessar registros e ferramentas internos via HTTPS.
Segredos necessários
- CORP_ROOT_CA_B64 — certificado PEM codificado em Base64 da sua CA corporativa. Gere com: cat corp-root-ca.crt | base64 -w0
Se a sua organização usar vários certificados de CA (por exemplo, CAs separadas para diferentes serviços internos).
Segredos necessários
- CORP_ROOT_CA_B64 — certificado de CA principal codificado em Base64 - CORP_INTERMEDIATE_CA_B64 — certificado de CA intermediário codificado em 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 # Cria um pacote combinado para ferramentas que precisam de um único arquivo de 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
Encaminhe todo o tráfego de rede por meio de um proxy corporativo.
Segredos necessários
CORP_HTTP_PROXY — URL do proxy HTTP (por exemplo, http://proxy.corp.example.com:8080) - CORP_HTTPS_PROXY — URL do proxy HTTPS - CORP_NO_PROXY — Lista de hosts separados por vírgula que devem ignorar o proxy (por exemplo,
localhost,127.0.0.1,.corp.example.com)
Se o seu proxy corporativo exigir autenticação com nome de usuário e senha.
Segredos necessários
PROXY_USER — Nome de usuário do proxy - PROXY_PASS — Senha do proxy - PROXY_HOST — Host e porta do proxy (por exemplo, proxy.corp.example.com:8080) - CORP_NO_PROXY — Hosts que devem ignorar o proxy
Configuração combinada para ambientes que exigem tanto uma CA corporativa quanto um proxy. Isso é comum em ambientes corporativos em que serviços internos usam certificados privados e todo o tráfego precisa passar por um proxy.
Segredos necessários
CORP_ROOT_CA_B64 — certificado de CA corporativa codificado em Base64 - CORP_HTTP_PROXY, CORP_HTTPS_PROXY — URLs do proxy - CORP_NO_PROXY — Hosts que ignoram o proxy
Seus registros privados, servidores Git ou outros serviços internos só podem ser acessados por VPN. Isso precisa ser executado antes de outros módulos que exigem acesso de rede a recursos internos.
Segredos necessários
OpenVPN:
VPN_CONFIG_B64 — Arquivo de configuração do OpenVPN (.ovpn) codificado em Base64. Gere com: cat corp.ovpn | base64 -w0
VPN_AUTH_USER(opcional) — Nome de usuário da VPN, caso sua VPN exija autenticação com nome de usuário e senha
VPN_AUTH_PASS(opcional) — Senha da VPN
WireGuard:
WG_CONFIG_B64 — Arquivo de configuração do WireGuard codificado em Base64. Gere com: 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 # Escrever a configuração da VPN sudo mkdir -p /etc/openvpn/client echo "$VPN_CONFIG_B64" | base64 -d \ | sudo tee /etc/openvpn/client/corp.conf > /dev/null # Se a VPN exigir autenticação por usuário/senha 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 o túnel VPN sudo systemctl daemon-reload sudo systemctl enable --now openvpn-client@corp # Aguardar o túnel ser estabelecido for i in $(seq 1 30); do if ip link show tun0 >/dev/null 2>&1; then break; fi sleep 1 done
GIT_USER_NAME — Nome do autor no Git (por exemplo, Devin AI)
GIT_USER_EMAIL — Email do autor no Git. Deve corresponder a um UID da chave GPG; caso contrário, o GitHub não verificará a assinatura.
Além disso, importe a chave pública correspondente para a conta do GitHub cujas credenciais o Devin usa para fazer push (em Configurações do GitHub > SSH and GPG keys). O GitHub só marca commits como Verified quando a chave pública usada na assinatura está registrada na conta que criou o commit.
initialize: - name: Prepare GPG and git signing config run: | # Permitir que o GPG funcione sem um 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
Identidade do Git e chaves SSH
Configure a identidade do Git e as chaves SSH do Devin para acessar servidores Git privados.
Segredos necessários
GIT_USER_NAME — Nome do autor no Git - GIT_USER_EMAIL — Email do autor no Git - SSH_PRIVATE_KEY_B64 — Chave privada SSH codificada em Base64. Gere com: cat ~/.ssh/id_ed25519 | base64 -w0 -
SSH_KNOWN_HOSTS_B64 — Entradas de hosts conhecidos codificadas em Base64. Gere com: ssh-keyscan git.corp.internal | base64 -w0 - SSH_CONFIG_B64(opcional) — Arquivo de configuração SSH codificado em Base64
initialize: - name: Configure git identity run: | git config --global user.name "$GIT_USER_NAME" git config --global user.email "$GIT_USER_EMAIL" # Preparar o diretório SSH mkdir -p ~/.ssh && chmod 700 ~/.sshmaintenance: - name: Install SSH keys run: | # Instalar a chave privada SSH (em maintenance para que seja recarregada a cada sessão) echo "$SSH_PRIVATE_KEY_B64" | base64 -d > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 # Adicionar hosts conhecidos para seu servidor Git echo "$SSH_KNOWN_HOSTS_B64" | base64 -d >> ~/.ssh/known_hosts # Opcionalmente, instalar uma configuração SSH personalizada if [ -n "${SSH_CONFIG_B64:-}" ]; then echo "$SSH_CONFIG_B64" | base64 -d > ~/.ssh/config chmod 600 ~/.ssh/config fi
Gere a entrada de hosts conhecidos para seu servidor Git com ssh-keyscan git.corp.internal | base64 -w0.
Instale pacotes no nível do sistema que não estão na imagem padrão do Devin (por exemplo, bibliotecas nativas para processamento de imagens ou geração de PDF).
Defina variáveis de ambiente persistentes que devem estar disponíveis em todas as sessões.A abordagem recomendada é gravar linhas KEY=VALUE no arquivo $ENVRC. As variáveis gravadas em $ENVRC são exportadas automaticamente para todas as etapas seguintes e para a sessão do Devin (semelhante ao $GITHUB_ENV do GitHub Actions).
As duas abordagens funcionam. $ENVRC é mais simples e recomendado na maioria dos casos.
Localidade e fuso horário
As imagens base padrão podem ter configurações de localidade incorretas. Configure a localidade e o fuso horário para evitar avisos de ferramentas de build, Java, Python e Git.
Builds em Java, Gradle e Node.js frequentemente esbarram no limite padrão de 1024 arquivos abertos. Aumente esse limite para evitar falhas de build.
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 # Também define o máximo do 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
Substituição do mirror do APT
Em ambientes sem conexão com a internet ou restritos, substitua as fontes APT padrão do Ubuntu por um espelho interno.
Segredos necessários
- APT_MIRROR_URL — URL do seu espelho APT interno (por exemplo, https://artifactory.example.com/artifactory/ubuntu-remote)
initialize: - name: Replace APT sources with internal mirror run: | # Fazer backup das fontes originais sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak # Substituir todos os mirrors do Ubuntu pelo 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
O direnv já vem integrado ao shell do Devin, então as variáveis de .envrc são carregadas automaticamente. Não é preciso executar source manualmente.
Para variáveis de ambiente sensíveis (chaves de API, tokens, senhas de banco de dados), use segredos do repositório em vez de arquivos .envrc. Os segredos do repositório são armazenados com segurança e injetados durante a sessão. Eles nunca aparecem no seu blueprint nem no snapshot.
Troca de versão do Node por repositório
Use o nvm (pré-instalado) para alternar entre versões do Node.js em cada repositório via .nvmrc.
nvm use lê o .nvmrc na raiz do repo. Certifique-se de que seu repositório tenha esse arquivo (por exemplo, com 20).
Autenticação via navegador (Playwright)
O Devin fornece um navegador Chrome com um endpoint CDP em localhost:29229durante as sessões. Use scripts do Playwright para automatizar o login no navegador.
O navegador só está disponível durante as sessões, não em builds do snapshot. Instale o Playwright em initialize e mantenha os scripts de login no seu repositório.
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
Exemplo de script de login (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")
Armazene as credenciais de login como segredos, não no código-fonte. Para autenticação de longo prazo, faça commit dos scripts de login em .agents/skills/ para que o Devin possa se reautenticar automaticamente.
Ferramentas personalizadas do sistema e PATH
Instale pacotes do sistema, binários personalizados e configure o PATH em initialize.
Devin oferece suporte à execução de GitHub Actions baseadas em Node.js diretamente em blueprints. Isso é útil para instalar versões específicas de ferramentas usando as mesmas actions usadas pela sua CI.
Ações como setup-node e setup-python alteram o PATH e as variáveis de ambiente. Os binários instalados por uma ação ficam disponíveis em todas as etapas seguintes e em maintenance. Apenas
GitHub Actions baseadas em Node.js são compatíveis. Ações compostas e baseadas em Docker não são.
Você não precisa de GitHub Actions para a configuração básica de ferramentas. Comandos shell diretos (nvm install 20, curl ... | sh, apt-get install) funcionam tão bem quanto e geralmente são mais simples. GitHub Actions são mais úteis quando você quer replicar exatamente sua configuração de CI ou precisa da praticidade de ações como setup-java, que lidam com várias distribuições.
Estes exemplos mostram como as configurações do Enterprise e no nível da organização se combinam. Na prática, você as dividiria entre diferentes escopos. Elas são apresentadas juntas aqui como referência.
Stack Enterprise completo (Artifactory)
Um ambiente Enterprise completo: certificado de CA corporativo, proxy, Java (Maven), Python (pip/uv), Node.js (npm) e Docker, todos apontando para uma única instância do Artifactory.
Segredos necessários
Rede e confiança (nível da conta):
CORP_ROOT_CA_B64 — certificado de CA corporativa codificado em Base64
CORP_HTTP_PROXY — URL do proxy HTTP
CORP_HTTPS_PROXY — URL do proxy HTTPS
CORP_NO_PROXY — hosts que devem ignorar o proxy
Credenciais do registro (nível da organização):
ARTIFACTORY_USER — nome de usuário do Artifactory
ARTIFACTORY_TOKEN — token de API ou senha do Artifactory
ARTIFACTORY_MAVEN_URL — URL do repositório Maven (por exemplo, https://artifactory.example.com/artifactory/maven-virtual)
ARTIFACTORY_PYPI_URL — URL do repositório PyPI (por exemplo, https://user:token@artifactory.example.com/artifactory/api/pypi/pypi-virtual/simple)
ARTIFACTORY_NPM_URL — URL do repositório npm (por exemplo, https://artifactory.example.com/artifactory/api/npm/npm-virtual)
ARTIFACTORY_DOCKER_URL — URL do registro do Docker (por exemplo, artifactory.example.com)
Isso normalmente seria dividido em três escopos:
Nível da conta (initialize): Certificado e proxy
Nível da organização (initialize): Instalação de runtimes de linguagem
No nível da organização (maintenance): Credenciais do registro (atualizadas a cada sessão)
Neste exemplo, todos os registros apontam para a mesma instância do Artifactory, mas usam caminhos de URL diferentes. Cada ecossistema de pacotes tem seu próprio formato de endpoint. As URLs de Maven, PyPI, npm e Docker são diferentes entre si, mesmo no mesmo registro.
Multilíngue com diferentes registros
Quando diferentes linguagens usam registros privados diferentes (por exemplo, Maven no Nexus, npm no GitHub Packages, Python no Artifactory).
Segredos necessários
NEXUS_MAVEN_URL — URL do repositório Maven no Nexus - NEXUS_USER — nome de usuário do Nexus - NEXUS_PASS — senha do Nexus - GITHUB_PACKAGES_TOKEN — token de acesso pessoal do GitHub com escopo read:packages -
ARTIFACTORY_USER — nome de usuário do Artifactory - ARTIFACTORY_TOKEN — token de API do Artifactory - GIT_TOKEN — token de acesso pessoal para módulos privados do Go
Em ambientes isolados da internet, todas as ferramentas de que o Devin precisa (runtimes de linguagem, ferramentas de CLI etc.) devem estar disponíveis nos seus mirrors internos. Registros públicos e sites de download não podem ser acessados.
VPN + certificados + proxy + linguagens
Uma configuração Enterprise completa que combina conectividade VPN com certificados, proxy e suporte a múltiplos idiomas. Esta é a ordem de operações recomendada.
Segredos necessários
VPN:
VPN_CONFIG_B64 — arquivo de configuração do OpenVPN codificado em Base64
Rede & confiança:
CORP_ROOT_CA_B64 — certificado de CA corporativa codificado em Base64
CORP_HTTP_PROXY — URL do proxy HTTP
CORP_HTTPS_PROXY — URL do proxy HTTPS
CORP_NO_PROXY — hosts que devem ignorar o proxy
Credenciais do registro:
MAVEN_REGISTRY_URL — URL do registro do Maven
NPM_REGISTRY_URL — URL do registro do npm
PYPI_REGISTRY_HOST — hostname do registro do PyPI
REGISTRY_USER — nome de usuário do registro (para Maven e pip)
REGISTRY_PASS — senha do registro (para Maven e pip)
REGISTRY_TOKEN — token de autenticação do npm
initialize: # 1. VPN — deve vir primeiro para que os recursos internos sejam acessíveis - 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 — resolve hostnames 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 nas 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 — rotear o tráfego pelo 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. Runtimes de linguagem - 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
A ordem das etapas de initialize importa. A VPN deve vir primeiro (para que os hosts internos fiquem acessíveis), depois o DNS (para que os nomes sejam resolvidos), depois os certificados (para que o HTTPS funcione), depois o proxy (para que o tráfego seja roteado corretamente) e, por fim, os runtimes de linguagem (que podem fazer download de mirrors internos).
Teste os comandos primeiro em uma sessão. Execute os comandos manualmente em uma sessão do Devin antes de adicioná-los ao blueprint. Isso é mais rápido do que esperar um ciclo completo de build.
Use initialize para ferramentas instaladas uma única vez e maintenance para dependências. Tudo o que leva minutos para instalar (compiladores, binários grandes, ferramentas globais) deve ficar em initialize. Comandos rápidos de dependência (npm install, uv sync) entram em maintenance.
Mantenha os comandos de maintenance rápidos. Procure ficar abaixo de 2 minutos. Eles são executados no início de cada sessão.
Use $ENVRC para variáveis de ambiente. Não escreva em .bashrc nem em .profile. $ENVRC é o mecanismo suportado para definir variáveis entre etapas e sessões.
Dê nomes às suas etapas. A forma expandida com campos name facilita muito identificar falhas nos logs de build.
Use subshells para monorepos.(cd packages/foo && npm install) é executado em um subshell, então as etapas seguintes não são afetadas pela mudança de diretório.
Use npm install, não npm ci.npm ci apaga node_modules e reinstala tudo do zero em cada sessão, o que é lento para maintenance.
Use secrets do repositório para valores sensíveis. Configure-os em Configurações → Secrets com escopo de repositório, em vez de embuti-los nos blueprints.