Pular para o conteúdo principal
Esta página fornece exemplos autônomos de environment.yaml para cenários comuns. Cada exemplo cobre uma necessidade — combine-os para montar sua configuração completa. Para uma introdução à sintaxe e aos conceitos de environment.yaml, consulte Configuração de ambiente. Para detalhes da sintaxe, consulte a Referência de YAML.
Secrets: Os exemplos referenciam secrets por meio de $SECRET_NAME. Configure-os em Configurações → Secrets antes de usar um exemplo. Cada exemplo inclui uma seção recolhível “segredo necessário” listando exatamente quais secrets configurar e quais valores eles devem ter. Nunca inclua credenciais diretamente no seu environment.yaml.

Referência rápida: configurações mais comuns

As configurações mais usadas em um só lugar. Para ver a lista completa, consulte as seções abaixo.
initialize: |
  npm install -g pnpm

maintenance: |
  pnpm install

knowledge:
  - name: lint
    contents: |
      Execute `pnpm lint` para verificar se há erros.
  - name: test
    contents: |
      Execute `pnpm test` para rodar a suíte completa.
initialize:
  - name: Instalar uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  - name: Sincronizar dependências
    run: uv sync

knowledge:
  - name: lint
    contents: |
      Execute `uv run ruff check .` para rodar o lint.
  - name: test
    contents: |
      Execute `uv run pytest` para rodar a suíte completa.
initialize:
  - name: Instalar pnpm
    run: npm install -g pnpm
  - name: Instalar uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  - 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 Python (uv)
  - name: test
    contents: |
      Frontend: cd frontend && pnpm test
      Backend: cd backend && uv run pytest
initialize: |
  npm install -g pnpm

maintenance: |
  pnpm install

knowledge:
  - name: structure
    contents: |
      Monorepo gerenciado com pnpm workspaces.
      - `packages/web` — frontend em Next.js
      - `packages/api` — backend em Express.js
      - `packages/shared` — utilitários compartilhados
  - name: test
    contents: |
      Execute `pnpm test` a partir da raiz para todos os packages.
      Execute `pnpm --filter web test` para um package específico.

Como as camadas funcionam

As configurações de ambiente são aplicadas em camadas. Cada camada se baseia na anterior:
1

Nível da conta (Enterprise)

Certificados, proxy, DNS, VPN, assinatura de commit, localidade, limites de recursos, identidade do git, espelhos do APT. Aplica-se a todas as org e todos os repositórios.
2

Nível da org

Runtimes de linguagem, configuração do registro do gerenciador de pacotes, registro de contêineres, ferramentas compartilhadas. Aplica-se a todos os repositórios da org.
3

Específico do repositório

Comandos de build, instalação de dependências, comandos de teste/lint, notas específicas do projeto para o Devin. Aplica-se a um único repositório.
O nível da conta é executado primeiro, depois o nível da org e, em seguida, o específico do repositório. Configure cada exemplo no escopo apropriado em Configurações.

Referência dos módulos

Use esta tabela para encontrar o exemplo mais adequado às suas necessidades. Cada módulo é independente — combine-os livremente.
MóduloCamadaSeção
Certificados de CAEnterpriseCertificado de CA corporativo
Múltiplos certificados de CAEnterpriseMúltiplos certificados de CA
Proxy HTTP/HTTPSEnterpriseProxy HTTP/HTTPS
Proxy autenticadoEnterpriseProxy autenticado
Certificado de CA + proxyEnterpriseCertificado de CA + proxy (combinado)
VPN (OpenVPN / WireGuard)EnterpriseConexão VPN
DNS personalizadoEnterpriseResolução de DNS personalizada
Assinatura de commit com GPGEnterpriseAssinatura de commit com GPG
Identidade do Git + chaves SSHEnterpriseIdentidade do Git e chaves SSH
Pacotes do sistemaEnterpriseInstalar pacotes do sistema
Variáveis de ambienteEnterpriseVariáveis de ambiente personalizadas
Localidade e fuso horárioEnterpriseLocalidade e fuso horário
Limites de recursosEnterpriseLimites de recursos (ulimits)
Espelho APTEnterpriseSubstituição do espelho APT
Java + MavenOrgJava + Maven com um registro privado
Java + GradleOrgJava + Gradle com um registro privado
Python + pip/uvOrgPython + pip/uv com um registro privado
Python + PoetryOrgPython + Poetry com um registro privado
Node.js + npm (scoped)OrgNode.js + npm com um registro privado scoped
Node.js + npm (espelho completo)OrgNode.js + npm com um espelho completo de registro privado
Node.js + pnpmOrgNode.js + pnpm com um registro privado
Node.js + YarnOrgNode.js + Yarn com um registro privado
GoOrgGo com um proxy de módulos privado
.NET + NuGetOrg.NET + NuGet com um feed privado
DockerOrgDocker com um registro privado de contêineres
Rust + CargoOrgRust + Cargo com um registro privado
Ruby + BundlerOrgRuby + Bundler com um servidor privado de gems
PHP + ComposerOrgPHP + Composer com um registro privado
AWS CodeArtifactOrgRenovação de token do AWS CodeArtifact
Projeto Node.jsRepoProjeto Node.js padrão
Projeto PythonRepoProjeto Python padrão
Projeto JavaRepoProjeto Java padrão
Projeto GoRepoProjeto Go padrão
Projeto RustRepoProjeto Rust padrão
MonorepoRepoMonorepo com vários serviços
Monorepo com múltiplos JDKsRepoMonorepo com várias versões de JDK
Entradas de KnowledgeRepoEntradas avançadas de Knowledge
Hooks de pre-commitRepoHooks de pre-commit

Exemplos de Enterprise / nível da conta

Estes exemplos configuram a infraestrutura no nível da máquina, aplicável a todas as org e repositórios. Defina-os em Configurações do Enterprise (para nível da conta) ou Configurações > Ambiente > Configuração em nível da organização (para nível da organização).

Certificado de CA corporativo

Sua organização usa uma autoridade certificadora privada para serviços internos. O Devin precisa do certificado raiz para acessar registros e ferramentas internas por HTTPS.
  • CORP_ROOT_CA_B64 — Certificado PEM codificado em base64 da sua CA corporativa. Gere com: cat corp-root-ca.crt | base64 -w0
initialize:
  - 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

      # Let Node.js trust the corporate CA
      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

Múltiplos certificados de CA

Algumas organizações têm CAs separadas para diferentes serviços internos (por exemplo, uma para o registro de artefatos e outra para um servidor Git interno).
  • CA_CERT_REGISTRY_B64 — Certificado PEM codificado em Base64 para a CA do registro de artefatos
  • CA_CERT_GIT_B64 — Certificado PEM codificado em Base64 para a CA do servidor Git
initialize:
  - name: Install corporate CA certificates
    run: |
      # Decode and install each certificate
      echo "$CA_CERT_REGISTRY_B64" | base64 -d \
        | sudo tee /usr/local/share/ca-certificates/registry-ca.crt > /dev/null
      echo "$CA_CERT_GIT_B64" | base64 -d \
        | sudo tee /usr/local/share/ca-certificates/git-ca.crt > /dev/null

      sudo update-ca-certificates

      # Node.js: combine certs into a single bundle
      cat /usr/local/share/ca-certificates/registry-ca.crt \
          /usr/local/share/ca-certificates/git-ca.crt \
        > /tmp/corp-ca-bundle.crt
      echo "export NODE_EXTRA_CA_CERTS=/tmp/corp-ca-bundle.crt" \
        | sudo tee /etc/profile.d/node-ca.sh > /dev/null

Proxy HTTP/HTTPS

Sua organização roteia o tráfego de saída por meio de um proxy corporativo.
  • CORP_HTTP_PROXY — URL do proxy HTTP (por exemplo, http://proxy.corp.internal:8080)
  • CORP_HTTPS_PROXY — URL do proxy HTTPS (por exemplo, http://proxy.corp.internal:8080)
  • CORP_NO_PROXY — Hosts separados por vírgulas que devem ignorar o proxy (por exemplo, localhost,127.0.0.1,.corp.internal,10.0.0.0/8)
initialize:
  - name: Configure system-wide HTTP/HTTPS 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

maintenance:
  - name: Configure git proxy
    run: |
      git config --global http.proxy "$CORP_HTTP_PROXY"
      git config --global https.proxy "$CORP_HTTPS_PROXY"
Defina CORP_NO_PROXY como uma lista de hosts separada por vírgulas que não devem passar pelo proxy, como localhost,127.0.0.1,.corp.internal,10.0.0.0/8.

Proxy autenticado

Se o seu proxy exigir nome de usuário e senha, inclua as credenciais na URL do proxy.
  • PROXY_USER — Nome de usuário para autenticação do proxy
  • PROXY_PASS — Senha para autenticação do proxy
  • PROXY_HOST — Nome do host do proxy (por exemplo, proxy.corp.internal)
  • PROXY_PORT — Porta do proxy (por exemplo, 8080)
  • CORP_NO_PROXY — Hosts separados por vírgula para os quais o proxy deve ser ignorado
initialize:
  - name: Configure authenticated HTTP/HTTPS proxy
    run: |
      cat << 'PROXY' | sudo tee /etc/profile.d/proxy.sh > /dev/null
      export http_proxy="http://$PROXY_USER:$PROXY_PASS@$PROXY_HOST:$PROXY_PORT"
      export https_proxy="http://$PROXY_USER:$PROXY_PASS@$PROXY_HOST:$PROXY_PORT"
      export no_proxy="$CORP_NO_PROXY"
      export HTTP_PROXY="$http_proxy"
      export HTTPS_PROXY="$https_proxy"
      export NO_PROXY="$CORP_NO_PROXY"
      PROXY
      source /etc/profile.d/proxy.sh

maintenance:
  - name: Configure git proxy
    run: |
      git config --global http.proxy "http://$PROXY_USER:$PROXY_PASS@$PROXY_HOST:$PROXY_PORT"
      git config --global https.proxy "http://$PROXY_USER:$PROXY_PASS@$PROXY_HOST:$PROXY_PORT"

Certificado de CA + proxy (combinado)

A configuração de base mais comum no Enterprise — instalar um certificado de CA corporativo e configurar um proxy para todo o sistema.
  • CORP_ROOT_CA_B64 — Certificado PEM codificado em Base64 da sua CA corporativa
  • CORP_HTTP_PROXY — URL do proxy HTTP
  • CORP_HTTPS_PROXY — URL do proxy HTTPS
  • CORP_NO_PROXY — Hosts separados por vírgula para ignorar o proxy
initialize:
  - 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

maintenance:
  - name: Configure git proxy
    run: |
      git config --global http.proxy "$CORP_HTTP_PROXY"
      git config --global https.proxy "$CORP_HTTPS_PROXY"

Conexão VPN

Seus registries privados, servidores Git ou outros serviços internos só ficam acessíveis via VPN. Isso deve ser executado antes dos outros módulos que precisam de acesso de rede a recursos internos.
OpenVPN:
  • VPN_CONFIG_B64 — Arquivo de configuração do OpenVPN codificado em Base64 (.ovpn). Gere com: cat corp.ovpn | base64 -w0
  • VPN_AUTH_USER (opcional) — Nome de usuário da VPN, se sua VPN exigir 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
initialize:
  - name: Instalar e configurar o OpenVPN
    run: |
      sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openvpn

      # Grava 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 com nome de usuário e 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

      # Inicia o túnel VPN
      sudo systemctl daemon-reload
      sudo systemctl enable --now openvpn-client@corp

      # Aguarda o túnel subir
      for i in $(seq 1 30); do
        if ip link show tun0 >/dev/null 2>&1; then break; fi
        sleep 1
      done
Para mais detalhes sobre a configuração da VPN, consulte Configuração de VPN.

Resolução de DNS personalizada

Seus serviços internos usam nomes de DNS privados que não podem ser resolvidos por DNS público.
initialize:
  - name: Configure custom DNS resolution
    run: |
      # Adicionar hostnames internos
      cat << 'HOSTS' | sudo tee -a /etc/hosts > /dev/null
      10.0.1.50  nexus.corp.internal
      10.0.1.51  git.corp.internal
      10.0.1.52  artifactory.corp.internal
      HOSTS

      # Opcionalmente, configurar servidores de nomes personalizados
      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 10.0.0.54
      Domains=corp.internal
      DNS
      sudo systemctl restart systemd-resolved || true

Assinatura de commits com GPG

Sua organização exige que todos os commits do Git sejam assinados.
  • GPG_PRIVATE_KEY_B64 — chave privada do GPG codificada em Base64. Gere com: gpg --export-secret-keys <key-id> | base64 -w0
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/null

      # Pré-configurar o git para assinar commits (chave importada na manutenção)
      git config --global commit.gpgsign true
      git config --global tag.gpgsign true

maintenance:
  - name: Import GPG signing key
    run: |
      echo "$GPG_PRIVATE_KEY_B64" | base64 -d | gpg --batch --import

      # Definir o ID da chave de assinatura
      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"

Identidade do Git e chaves SSH

Configure a identidade do usuário do Git e as chaves SSH para acessar repositórios privados por SSH.
  • GIT_USER_NAME — Nome do autor no Git (ex.: Devin AI)
  • GIT_USER_EMAIL — E-mail do autor no Git (ex.: devin@company.com)
  • SSH_PRIVATE_KEY_B64 — Chave privada SSH codificada em Base64. Gere com: cat ~/.ssh/id_ed25519 | base64 -w0
  • SSH_KNOWN_HOSTS_B64 — known_hosts codificado em Base64. Gere com: ssh-keyscan git.corp.internal | base64 -w0
  • SSH_CONFIG_B64 (opcional) — Arquivo de configuração SSH codificado em Base64 para aliases de host personalizados
initialize:
  - name: Prepare SSH directory and git identity
    run: |
      # Definir identidade do git
      git config --global user.name "$GIT_USER_NAME"
      git config --global user.email "$GIT_USER_EMAIL"

      # Preparar diretório SSH
      mkdir -p ~/.ssh && chmod 700 ~/.ssh

      # Ativar git-lfs se necessário
      # git lfs install

maintenance:
  - name: Install SSH keys
    run: |
      # Instalar chave privada SSH (em manutenção para ser recarregada a cada sessão)
      echo "$SSH_PRIVATE_KEY_B64" | base64 -d > ~/.ssh/id_ed25519
      chmod 600 ~/.ssh/id_ed25519

      # Adicionar hosts conhecidos para o 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 do seu servidor Git com ssh-keyscan git.corp.internal | base64 -w0.

Instalar pacotes do sistema

Seu projeto precisa de pacotes de sistema que não estão incluídos na imagem padrão do Devin (por exemplo, bibliotecas nativas para processamento de imagens ou geração de PDFs).
initialize:
  - name: Install system packages
    run: |
      sudo apt-get update -qq
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
        libpq-dev \
        libmagickwand-dev \
        poppler-utils \
        ffmpeg

Variáveis de ambiente personalizadas

Defina variáveis de ambiente persistentes que devem estar disponíveis em cada sessão. A abordagem recomendada é adicionar linhas KEY=VALUE ao arquivo $ENVRC. As variáveis adicionadas ao $ENVRC são exportadas automaticamente para todas as etapas subsequentes e para a sessão do Devin (semelhante ao $GITHUB_ENV do GitHub Actions).
initialize:
  - name: Set custom environment variables
    run: |
      echo "CORPORATE_ENV=production" >> $ENVRC
      echo "DEFAULT_REGION=us-east-1" >> $ENVRC
      echo "MAX_RETRIES=3" >> $ENVRC
Você também pode gravar variáveis de ambiente em scripts de /etc/profile.d/ para que fiquem disponíveis em todo o sistema:
cat << 'ENVVARS' | sudo tee /etc/profile.d/custom-env.sh > /dev/null
export CORPORATE_ENV=production
export DEFAULT_REGION=us-east-1
ENVVARS
As duas abordagens funcionam. $ENVRC é mais simples e recomendado na maioria dos casos.

Locale e fuso horário

Imagens base padrão podem ter configurações de locale incorretas. Configure o locale e o fuso horário para evitar avisos de ferramentas de build, Java, Python e 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

      # Gerar e definir o locale
      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

      # Definir fuso horário
      sudo timedatectl set-timezone UTC 2>/dev/null || \
        sudo ln -sfn /usr/share/zoneinfo/UTC /etc/localtime

Limites de recursos (ulimits)

Builds de 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 espelho APT

Em ambientes isolados da internet ou restritos, substitua os repositórios APT padrão do Ubuntu por um espelho interno.
  • 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

      # Desativar fontes de terceiros que não serão acessíveis
      # sudo mv /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/disabled/ 2>/dev/null || true

      sudo apt-get update -qq
Padrões comuns de URL para espelhos APT:
  • Artifactory: https://artifactory.example.com/artifactory/ubuntu-remote
  • Nexus: https://nexus.example.com/repository/ubuntu-proxy

Exemplos em nível da organização

Estes exemplos instalam runtimes de linguagem e configuram gerenciadores de pacotes para usar registros privados. Defina-os em Configurações > Ambiente > Configuração em nível da organização.
Se o seu registro privado usar uma CA corporativa, certifique-se de que o certificado de CA esteja instalado primeiro no nível enterprise. A configuração no nível da organização abaixo pressupõe que a confiança em HTTPS já tenha sido estabelecida.
A configuração de credenciais deve ficar em maintenance, não em initialize. Etapas que gravam secrets (senhas de registro, tokens de autenticação) em arquivos de configuração devem usar maintenance para que as credenciais sejam recarregadas a cada sessão. O arquivo de secrets é removido antes que a imagem da máquina seja salva, portanto os arquivos de configuração gravados durante initialize não terão credenciais válidas quando as sessões forem iniciadas.

Java + Maven com um repositório privado

Instale o JDK e configure o Maven para espelhar toda a resolução de dependências por meio do seu repositório privado (por exemplo, Artifactory, Nexus).
O JDK 17 vem pré-instalado na imagem base do Devin. Pule a etapa de instalação abaixo se o OpenJDK 17 padrão for suficiente — você só precisa instalar o Maven e configurar o registro.
  • 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
initialize:
  - name: Install JDK 17
    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: Install Maven
    run: |
      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

maintenance:
  - name: Configure Maven for private registry
    run: |
      mkdir -p ~/.m2
      cat > ~/.m2/settings.xml << EOF
      <settings>
        <mirrors>
          <mirror>
            <id>private-registry</id>
            <mirrorOf>*</mirrorOf>
            <url>$MAVEN_REGISTRY_URL</url>
          </mirror>
        </mirrors>
        <servers>
          <server>
            <id>private-registry</id>
            <username>$REGISTRY_USER</username>
            <password>$REGISTRY_PASS</password>
          </server>
        </servers>
      </settings>
      EOF
Padrões comuns de URL de repositório para Maven:
  • Artifactory: https://artifactory.example.com/artifactory/maven-virtual
  • Nexus: https://nexus.example.com/repository/maven-public
  • Azure Artifacts: https://pkgs.dev.azure.com/org/project/_packaging/feed/maven/v1
  • GitHub Packages: https://maven.pkg.github.com
  • GitLab: https://gitlab.example.com/api/v4/groups/<group-id>/-/packages/maven
  • AWS CodeArtifact: https://<domain>.d.codeartifact.<region>.amazonaws.com/maven/<repo>

Java + Gradle com um repositório privado

Instale o JDK e configure o Gradle para resolver todas as dependências por meio do seu repositório 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.
  • 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
initialize:
  - name: Install JDK 17
    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: Install Gradle
    run: |
      GRADLE_VERSION=8.12
      curl -fsSL "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" \
        -o /tmp/gradle.zip
      sudo unzip -qo /tmp/gradle.zip -d /opt
      sudo ln -sf /opt/gradle-${GRADLE_VERSION}/bin/gradle /usr/local/bin/gradle
      rm /tmp/gradle.zip

maintenance:
  - name: Configure Gradle for private registry
    run: |
      mkdir -p ~/.gradle
      cat > ~/.gradle/init.gradle << EOF
      allprojects {
          repositories {
              maven {
                  url "$GRADLE_REGISTRY_URL"
                  credentials {
                      username = "$REGISTRY_USER"
                      password = "$REGISTRY_PASS"
                  }
                  allowInsecureProtocol = false
              }
          }
      }
      EOF

Python + pip/uv com um repositório privado

Configure o pip e o uv para obter pacotes do seu repositório privado do PyPI (por exemplo, Nexus, Artifactory).
  • PYPI_REGISTRY_HOST — Nome do host do seu registro PyPI (por exemplo, artifactory.example.com/artifactory/api/pypi/pypi-virtual)
  • REGISTRY_USER — Nome de usuário do registro
  • REGISTRY_PASS — Senha do registro ou token de API
initialize:
  - name: Install uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  - name: Configure pip for private registry
    run: |
      mkdir -p ~/.config/pip
      cat > ~/.config/pip/pip.conf << EOF
      [global]
      index-url = https://$REGISTRY_USER:$REGISTRY_PASS@${PYPI_REGISTRY_HOST}/simple
      trusted-host = ${PYPI_REGISTRY_HOST}
      EOF

  - name: Configure uv for private registry
    run: |
      # uv respeita o pip.conf, mas você também pode definir explicitamente
      echo "export UV_INDEX_URL=https://$REGISTRY_USER:$REGISTRY_PASS@${PYPI_REGISTRY_HOST}/simple" \
        | sudo tee /etc/profile.d/uv-registry.sh > /dev/null
Padrões comuns de URL de registro do PyPI:
  • Artifactory: https://artifactory.example.com/artifactory/api/pypi/pypi-virtual/simple
  • Nexus: https://nexus.example.com/repository/pypi-group/simple
  • Azure Artifacts: https://pkgs.dev.azure.com/org/project/_packaging/feed/pypi/simple/
  • GitLab: https://gitlab.example.com/api/v4/groups/<group-id>/-/packages/pypi/simple
  • AWS CodeArtifact: https://<domain>.d.codeartifact.<region>.amazonaws.com/pypi/<repo>/simple

Python + Poetry com um registro privado

Configure o Poetry para resolver pacotes usando um registro PyPI privado.
  • PYPI_REGISTRY_HOST — Nome do host do seu registro PyPI
  • REGISTRY_USER — Nome de usuário do registro
  • REGISTRY_PASS — Senha do registro ou token de API
initialize:
  - name: Install Poetry
    run: curl -sSL https://install.python-poetry.org | python3 -

maintenance:
  - name: Configure Poetry for private registry
    run: |
      poetry config repositories.private "https://${PYPI_REGISTRY_HOST}/simple"
      poetry config http-basic.private "$REGISTRY_USER" "$REGISTRY_PASS"

      # Opcionalmente, defina o registro privado como fonte padrão
      # poetry source add --priority=primary private "https://${PYPI_REGISTRY_HOST}/simple"

Node.js + npm com um registro privado para um escopo

Configure o npm para resolver pacotes com escopo (por exemplo, @myorg/*) a partir de um registro privado, como o GitHub Packages, enquanto os pacotes públicos continuam vindo do registro padrão do npm.
  • GITHUB_PACKAGES_TOKEN — token de acesso pessoal ou token do GitHub App com 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:
  • GitHub Packages: https://npm.pkg.github.com
  • Artifactory: https://artifactory.example.com/artifactory/api/npm/npm-virtual
  • Nexus: https://nexus.example.com/repository/npm-group
  • GitLab: https://gitlab.example.com/api/v4/packages/npm
  • AWS CodeArtifact: https://<domain>.d.codeartifact.<region>.amazonaws.com/npm/<repo>

Node.js + npm com espelho completo de registro privado

Faça com que todos os pacotes do npm passem pelo seu registro privado (não apenas os pacotes com escopo).
  • 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 nome do host, 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

Node.js + pnpm com um registro privado

Configure o pnpm para resolver pacotes de um registro privado.
pnpm vem pré-instalado na imagem base do Devin. Você pode pular a etapa de instalação e apenas configurar o registro.
  • NPM_REGISTRY_URL — URL completa do seu registro npm
  • NPM_REGISTRY_HOST — Somente o nome do host, sem protocolo
  • REGISTRY_TOKEN — token de autenticação do npm para o registro
initialize:
  - name: Install pnpm
    run: npm install -g pnpm

maintenance:
  - name: Configure pnpm for private registry
    run: |
      pnpm config set registry $NPM_REGISTRY_URL
      pnpm config set //${NPM_REGISTRY_HOST}/:_authToken $REGISTRY_TOKEN

Node.js + Yarn com um registro privado

Configure o Yarn (Classic v1 ou Berry v2+) para resolver pacotes de um registro privado.
Yarn Classic (v1) vem pré-instalado na imagem base do Devin. Pule a etapa de instalação se você só precisar da v1.
  • NPM_REGISTRY_URL — URL completa do seu registro npm/Yarn
  • REGISTRY_TOKEN — Token de autenticação para o registro (apenas Berry)
initialize:
  - name: Instalar Yarn Classic
    run: npm install -g yarn

maintenance:
  - name: Configurar Yarn para registro privado
    run: |
      yarn config set registry "$NPM_REGISTRY_URL"
      # Para pacotes com escopo:
      # yarn config set @myorg:registry "https://npm.pkg.github.com"

Use um proxy privado de módulos do Go

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 GOPROXY).
  • GO_PROXY_URL — URL do seu proxy de módulos do Go (por exemplo, https://athens.corp.internal)
  • GIT_TOKEN — Token de acesso pessoal para repositórios Git privados que hospedam módulos do 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/*"
      GOENV

maintenance:
  - name: Authenticate Go private modules
    run: |
      git config --global url."https://$GIT_TOKEN@github.com/myorg/".insteadOf "https://github.com/myorg/"
Padrões comuns de URLs de proxy do Go:
  • Artifactory: https://artifactory.example.com/artifactory/go-virtual
  • Nexus: https://nexus.example.com/repository/go-proxy
  • Athens: https://athens.corp.internal

.NET + NuGet com um feed privado

Instale o SDK do .NET e configure o NuGet para resolver pacotes de um feed privado (por exemplo, Azure Artifacts, Artifactory).
  • NUGET_FEED_URL — URL do seu feed do NuGet (por exemplo, https://pkgs.dev.azure.com/org/project/_packaging/feed/nuget/v3/index.json)
  • REGISTRY_USER — Nome de usuário do registro
  • REGISTRY_PASS — Senha do registro ou token de API
initialize:
  - name: Install .NET SDK
    run: |
      curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh
      chmod +x /tmp/dotnet-install.sh
      sudo /tmp/dotnet-install.sh --channel 8.0 --install-dir /usr/local/dotnet
      echo 'export DOTNET_ROOT=/usr/local/dotnet' \
        | sudo tee /etc/profile.d/dotnet.sh > /dev/null
      echo 'export PATH="$DOTNET_ROOT:$DOTNET_ROOT/tools:$PATH"' \
        | sudo tee -a /etc/profile.d/dotnet.sh > /dev/null
      rm /tmp/dotnet-install.sh

maintenance:
  - name: Configure NuGet for private feed
    run: |
      dotnet nuget add source "$NUGET_FEED_URL" \
        --name private-feed \
        --username "$REGISTRY_USER" \
        --password "$REGISTRY_PASS" \
        --store-password-in-clear-text

      # Opcionalmente, desabilite a fonte padrão nuget.org
      # dotnet nuget disable source nuget.org
URLs comuns de feeds do NuGet:
  • Azure Artifacts: https://pkgs.dev.azure.com/org/project/_packaging/feed/nuget/v3/index.json
  • Artifactory: https://artifactory.example.com/artifactory/api/nuget/v3/nuget-virtual
  • GitHub Packages: https://nuget.pkg.github.com/myorg/index.json
  • Nexus: https://nexus.example.com/repository/nuget-hosted/index.json

Docker com um registro privado de contêineres

Configure o Docker para autenticar em um registro privado de contêineres.
  • DOCKER_MIRROR_URL (opcional) — URL do 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/docker

maintenance:
  - name: Configure Docker for private registry
    run: |
      # Configurar espelho 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 de contêiner privado
      echo "$DOCKER_REGISTRY_PASS" | docker login "$DOCKER_REGISTRY_URL" \
        --username "$DOCKER_REGISTRY_USER" \
        --password-stdin
URLs comuns de registros de contêineres:
  • Amazon ECR: <account-id>.dkr.ecr.<region>.amazonaws.com
  • Azure Container Registry: <name>.azurecr.io
  • Google Artifact Registry: <region>-docker.pkg.dev
  • GitHub Container Registry: ghcr.io
  • GitLab Container Registry: registry.gitlab.example.com
  • Nexus: https://nexus.example.com:8443
  • JFrog: <name>.jfrog.io

Rust + Cargo com um registro privado

Instale o Rust e configure o Cargo para resolver crates 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.
  • 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
initialize:
  - name: Install Rust
    run: |
      curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
        | sh -s -- -y --default-toolchain stable
      echo 'source "$HOME/.cargo/env"' \
        | sudo tee /etc/profile.d/rust.sh > /dev/null

maintenance:
  - name: Configure Cargo for private registry
    run: |
      mkdir -p ~/.cargo
      cat > ~/.cargo/config.toml << EOF
      [registries.private]
      index = "$CARGO_REGISTRY_INDEX"
      token = "$CARGO_REGISTRY_TOKEN"

      [source.crates-io]
      replace-with = "private"

      [source.private]
      registry = "$CARGO_REGISTRY_INDEX"
      EOF
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 com um servidor privado de gems

Instale o Ruby e configure o Bundler para resolver gems de um servidor privado de gems.
  • 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-full

maintenance:
  - 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"
Padrões comuns de URL para servidores de gems:
  • Artifactory: https://artifactory.example.com/artifactory/api/gems/gems-virtual
  • Nexus: https://nexus.example.com/repository/rubygems-proxy
  • Gemfury: https://gem.fury.io/<org>

Renovação do token do AWS CodeArtifact

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 da renovação do token e da configuração do registro.
  • 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
  • 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 de cada ecossistema
maintenance:
  - name: Refresh CodeArtifact auth token
    run: |
      # Obter um token novo (válido por 12 horas)
      export CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token \
        --domain $CA_DOMAIN \
        --domain-owner $CA_DOMAIN_OWNER \
        --region $CA_REGION \
        --query authorizationToken \
        --output text)

      CA_ENDPOINT="https://${CA_DOMAIN}-${CA_DOMAIN_OWNER}.d.codeartifact.${CA_REGION}.amazonaws.com"

      # Configurar npm
      npm config set registry "${CA_ENDPOINT}/npm/${CA_NPM_REPO}/"
      npm config set "//${CA_DOMAIN}-${CA_DOMAIN_OWNER}.d.codeartifact.${CA_REGION}.amazonaws.com/npm/${CA_NPM_REPO}/:_authToken" "$CODEARTIFACT_AUTH_TOKEN"

      # Configurar pip
      mkdir -p ~/.config/pip
      cat > ~/.config/pip/pip.conf << EOF
      [global]
      index-url = https://aws:${CODEARTIFACT_AUTH_TOKEN}@${CA_DOMAIN}-${CA_DOMAIN_OWNER}.d.codeartifact.${CA_REGION}.amazonaws.com/pypi/${CA_PYPI_REPO}/simple/
      EOF

      # Configurar Maven (opcional)
      mkdir -p ~/.m2
      cat > ~/.m2/settings.xml << EOF
      <settings>
        <servers>
          <server>
            <id>codeartifact</id>
            <username>aws</username>
            <password>${CODEARTIFACT_AUTH_TOKEN}</password>
          </server>
        </servers>
        <mirrors>
          <mirror>
            <id>codeartifact</id>
            <mirrorOf>*</mirrorOf>
            <url>${CA_ENDPOINT}/maven/${CA_MAVEN_REPO}/</url>
          </mirror>
        </mirrors>
      </settings>
      EOF

PHP + Composer com registro privado

Instale o PHP e configure o Composer para resolver pacotes de um registro privado do Packagist ou Satis.
  • COMPOSER_REGISTRY_URL — URL do seu registro privado do Composer (por exemplo, https://repo.packagist.com/<org>)
  • REGISTRY_USER — Nome de usuário do registro
  • REGISTRY_PASS — Senha do registro ou token de API
initialize:
  - name: Install PHP and Composer
    run: |
      sudo apt-get update -qq
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
        php-cli php-mbstring php-xml php-curl unzip

      # Instalar o Composer
      curl -sS https://getcomposer.org/installer | php
      sudo mv composer.phar /usr/local/bin/composer

maintenance:
  - name: Configure Composer for private registry
    run: |
      composer config --global repositories.private \
        composer "$COMPOSER_REGISTRY_URL"

      # Autenticar no registro
      composer config --global http-basic.$(echo "$COMPOSER_REGISTRY_URL" \
        | sed 's|https\?://||;s|/.*||') "$REGISTRY_USER" "$REGISTRY_PASS"

      # Opcionalmente, desabilitar o packagist.org padrão
      # composer config --global repositories.packagist false
Padrões comuns de URL de registro do Composer:
  • Artifactory: https://artifactory.example.com/artifactory/api/composer/packagist-virtual
  • Nexus: https://nexus.example.com/repository/packagist-proxy
  • Private Packagist: https://repo.packagist.com/<org>
  • Satis: https://satis.corp.internal

Exemplos específicos por repositório

Estes exemplos configuram etapas de build por repositório, gerenciamento de dependências e entradas no Knowledge. Defina-os em Configurações > Ambiente > [seu repositório].

Projeto padrão em Node.js

Um projeto típico em Node.js com comandos de lint, teste e build.
initialize: |
  npm install -g pnpm

maintenance: |
  pnpm install

knowledge:
  - name: lint
    contents: |
      Run `pnpm lint` to check for errors.
      Run `pnpm lint --fix` to auto-fix.
  - name: test
    contents: |
      Run `pnpm test` for the full test suite.
      Run `pnpm test -- --watch` during development.
  - name: build
    contents: |
      Run `pnpm build` to create a production build.
      Output goes to the `dist/` directory.

Projeto padrão em Python

Um projeto em Python que usa o uv para gerenciamento de dependências.
initialize:
  - name: Install uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  - name: Sync dependencies
    run: uv sync

knowledge:
  - name: lint
    contents: |
      Run `uv run ruff check .` to lint.
      Run `uv run ruff format .` to format.
  - name: test
    contents: |
      Run `uv run pytest` for the full test suite.
      Run `uv run pytest -x` to stop on first failure.

projeto padrão em Java

Um projeto Java que usa Maven para gerenciar dependências.
maintenance:
  - name: Resolve dependencies
    run: mvn dependency:resolve -U -q

knowledge:
  - name: build
    contents: |
      Run `mvn clean package` to build.
      Run `mvn clean package -DskipTests` to build without tests.
  - name: test
    contents: |
      Run `mvn test` for unit tests.
      Run `mvn verify` for integration tests.
  - name: lint
    contents: |
      Run `mvn checkstyle:check` for style checks.
      Run `mvn spotbugs:check` for bug detection.

projeto padrão em Go

Um projeto Go com ferramentas padrão.
maintenance:
  - name: Download dependencies
    run: go mod download

knowledge:
  - name: build
    contents: |
      Run `go build ./...` to build all packages.
      Run `go build -o bin/app ./cmd/app` to build the main binary.
  - name: test
    contents: |
      Run `go test ./...` for all tests.
      Run `go test -race ./...` to include race detection.
      Run `go test -v ./pkg/... -run TestSpecific` for a specific test.
  - name: lint
    contents: |
      Run `golangci-lint run` for linting (if installed).
      Run `go vet ./...` for basic static analysis.

Projeto padrão em Rust

Um projeto em Rust usando Cargo.
maintenance:
  - name: Fetch dependencies
    run: cargo fetch

knowledge:
  - name: build
    contents: |
      Run `cargo build` for a debug build.
      Run `cargo build --release` for a release build.
  - name: test
    contents: |
      Run `cargo test` for all tests.
      Run `cargo test -- --test-threads=1` for sequential execution.
  - name: lint
    contents: |
      Run `cargo clippy -- -D warnings` for lint checks.
      Run `cargo fmt --check` to verify formatting.

Monorepo com vários serviços

Um monorepo com serviços de frontend e backend separados, que usam gerenciadores de pacotes diferentes.
initialize:
  - name: Install pnpm
    run: npm install -g pnpm
  - name: Install uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  - name: Install frontend dependencies
    run: (cd packages/frontend && pnpm install)
  - name: Install backend dependencies
    run: (cd packages/backend && uv sync)
  - name: Build shared library
    run: (cd packages/shared && pnpm install && pnpm build)

knowledge:
  - name: structure
    contents: |
      This is a monorepo with three packages:
      - `packages/frontend` — React app (TypeScript, pnpm)
      - `packages/backend` — Python API (FastAPI, uv)
      - `packages/shared` — Shared TypeScript utilities (must be built before frontend)
  - name: frontend
    contents: |
      Run `cd packages/frontend && pnpm dev` to start the dev server.
      Run `cd packages/frontend && pnpm lint` to lint.
      Run `cd packages/frontend && pnpm test` to test.
  - name: backend
    contents: |
      Run `cd packages/backend && uv run uvicorn app.main:app --reload` to start the API.
      Run `cd packages/backend && uv run ruff check .` to lint.
      Run `cd packages/backend && uv run pytest` to test.
Use subshells (cd dir && command) em vez de cd dir && command para que o diretório de trabalho seja restaurado entre as etapas.

Monorepo com várias versões do JDK

Um monorepo Java em que serviços diferentes exigem versões diferentes do JDK. Instale ambos os JDKs durante a configuração e, em seguida, use entradas de Knowledge para informar ao Devin qual JAVA_HOME deve ser usado em cada serviço.
initialize:
  - name: Install JDK 17 (primary)
    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: Install JDK 11 (legacy service)
    run: |
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-11-jdk-headless

maintenance:
  - name: Warm dependency caches
    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: |
      Build the API service (JDK 17):
        JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 \
        cd services/api && ./gradlew clean build
  - name: build_legacy
    contents: |
      Build the legacy service (JDK 11):
        JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 \
        cd services/legacy && ./gradlew clean build
  - name: test_all
    contents: |
      Run tests for all services:
        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)

Hooks pré-commit

Se o seu projeto usa hooks do pre-commit, instale-os em maintenance para que fiquem prontos em todas as sessões.
initialize:
  - name: Install pre-commit
    run: pip install pre-commit

maintenance:
  - name: Install pre-commit hooks
    run: pre-commit install --install-hooks
Se o projeto já tiver pre-commit como dependência de desenvolvimento (por exemplo, em pyproject.toml), pule a etapa initialize e use uv run pre-commit install --install-hooks ou pipx run pre-commit install --install-hooks na etapa maintenance.

Entradas avançadas de knowledge

Documente a arquitetura, as convenções e os fluxos de trabalho do seu projeto em entradas knowledge.
knowledge:
  - name: architecture
    contents: |
      This is a microservices application:
      - `api-gateway/` — Express.js reverse proxy (port 3000)
      - `auth-service/` — JWT authentication service (port 3001)
      - `user-service/` — User CRUD service (port 3002)
      - `shared/` — Shared protobuf definitions and utilities

      Services communicate via gRPC. The API gateway is the only public-facing service.

  - name: conventions
    contents: |
      - All API responses use the `{ data, error, meta }` envelope format
      - Database migrations are in `migrations/` and run with `npm run migrate`
      - Environment-specific config is in `config/{env}.json`
      - Feature flags are managed via LaunchDarkly (SDK key in $LD_SDK_KEY)

  - name: testing
    contents: |
      Unit tests: `npm test`
      Integration tests: `npm run test:integration` (requires Docker for Postgres)
      E2E tests: `npm run test:e2e` (requires all services running)

      Coverage report: `npm run test:coverage` (must be > 80% for CI to pass)

  - name: deployment
    contents: |
      CI/CD runs on GitHub Actions. Merges to `main` auto-deploy to staging.
      Production deploys require a manual approval step in the Actions UI.
      Docker images are pushed to ECR: 123456789.dkr.ecr.us-east-1.amazonaws.com/

Exemplos combinados

Estes exemplos mostram como as configurações do Enterprise e no nível da organização se combinam. Na prática, isso seria dividido entre escopos — aqui, eles são mostrados juntos como referência.

Stack Enterprise completa

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.
Rede e confiança (nível da conta):
  • CORP_ROOT_CA_B64 — Certificado de CA corporativo 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 de 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 Docker (por exemplo, artifactory.example.com)
Normalmente, isso 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
  • Nível da organização (maintenance): Credenciais de registro (atualizadas a cada sessão)
Mostrado aqui de forma combinada como referência:
initialize:
  # ── Em toda a conta: rede e confiança ────────────────────────────────────

  - name: Instalar certificado CA corporativo
    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: Configurar proxy em todo o sistema
    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

  # ── Em toda a organização: runtimes de linguagem ─────────────────────────

  - name: Instalar 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: Instalar uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  # ── Em toda a conta: proxy git (atualizado a cada sessão) ──────────────

  - name: Configurar proxy git
    run: |
      git config --global http.proxy "$CORP_HTTP_PROXY"
      git config --global https.proxy "$CORP_HTTPS_PROXY"

  # ── Em toda a organização: credenciais de registro (atualizadas a cada sessão) ──

  - name: Configurar 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: Configurar 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: Configurar 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: Configurar Docker → Artifactory
    run: |
      echo "$ARTIFACTORY_TOKEN" | docker login "$ARTIFACTORY_DOCKER_URL" \
        --username "$ARTIFACTORY_USER" \
        --password-stdin
Neste exemplo, todos os registries 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 registry.

Várias linguagens com registries diferentes

Quando linguagens diferentes usam registries privados distintos (por exemplo, Maven do Nexus, npm do GitHub Packages e Python do Artifactory).
  • NEXUS_MAVEN_URL — URL do repositório Maven do 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
maintenance:
  # Maven → Nexus
  - name: Configurar Maven → Nexus
    run: |
      mkdir -p ~/.m2
      cat > ~/.m2/settings.xml << EOF
      <settings>
        <mirrors>
          <mirror>
            <id>nexus</id>
            <mirrorOf>*</mirrorOf>
            <url>$NEXUS_MAVEN_URL</url>
          </mirror>
        </mirrors>
        <servers>
          <server>
            <id>nexus</id>
            <username>$NEXUS_USER</username>
            <password>$NEXUS_PASS</password>
          </server>
        </servers>
      </settings>
      EOF

  # npm → GitHub Packages (com escopo)
  - name: Configurar npm → GitHub Packages
    run: |
      npm config set @myorg:registry https://npm.pkg.github.com
      npm config set //npm.pkg.github.com/:_authToken $GITHUB_PACKAGES_TOKEN

  # Python → Artifactory
  - name: Configurar pip → Artifactory
    run: |
      mkdir -p ~/.config/pip
      cat > ~/.config/pip/pip.conf << EOF
      [global]
      index-url = https://$ARTIFACTORY_USER:$ARTIFACTORY_TOKEN@artifactory.example.com/artifactory/api/pypi/pypi-virtual/simple
      EOF

  # Go → módulos privados via git
  - name: Configurar módulos privados do Go
    run: |
      git config --global url."https://$GIT_TOKEN@github.com/myorg/".insteadOf "https://github.com/myorg/"

Ambiente air-gapped com espelhos privados

Em um ambiente totalmente air-gapped, o Devin não pode acessar nenhuma URL pública. Todas as ferramentas, runtimes e pacotes devem vir de espelhos internos.
Certificados:
  • CORP_ROOT_CA_B64 — certificado de CA corporativa codificado em Base64
Acesso ao espelho:
  • APT_MIRROR_URL — URL do espelho APT interno do Ubuntu
  • MIRROR_USER — nome de usuário para autenticação no espelho
  • MIRROR_PASS — senha para autenticação no espelho
  • JDK_TARBALL_URL — URL para baixar o tarball do JDK do espelho interno
  • NODE_TARBALL_URL — URL para baixar o tarball do Node.js do espelho interno
Registros de pacotes:
  • INTERNAL_MAVEN_URL — URL do registro interno do Maven
  • INTERNAL_NPM_URL — URL do registro interno do npm
  • INTERNAL_PYPI_URL — URL do registro interno do PyPI
initialize:
  - 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

  - name: Replace apt sources with internal mirror
    run: |
      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

  - name: Install JDK from internal mirror
    run: |
      # Baixar o tarball do JDK do repositório de artefatos interno
      curl -fsSL -u "$MIRROR_USER:$MIRROR_PASS" "$JDK_TARBALL_URL" \
        | sudo tar -xz -C /usr/local
      sudo ln -sf /usr/local/jdk-17.*/bin/java /usr/local/bin/java
      sudo ln -sf /usr/local/jdk-17.*/bin/javac /usr/local/bin/javac
      echo "export JAVA_HOME=$(ls -d /usr/local/jdk-17.*)" \
        | sudo tee /etc/profile.d/java.sh > /dev/null

  - name: Install Node.js from internal mirror
    run: |
      curl -fsSL -u "$MIRROR_USER:$MIRROR_PASS" "$NODE_TARBALL_URL" \
        | sudo tar -xz -C /usr/local --strip-components=1

maintenance:
  - name: Configure all package managers for internal registry
    run: |
      # Maven
      mkdir -p ~/.m2
      cat > ~/.m2/settings.xml << EOF
      <settings>
        <mirrors>
          <mirror>
            <id>internal</id>
            <mirrorOf>*</mirrorOf>
            <url>$INTERNAL_MAVEN_URL</url>
          </mirror>
        </mirrors>
        <servers>
          <server>
            <id>internal</id>
            <username>$MIRROR_USER</username>
            <password>$MIRROR_PASS</password>
          </server>
        </servers>
      </settings>
      EOF

      # npm
      npm config set registry "$INTERNAL_NPM_URL"

      # pip
      mkdir -p ~/.config/pip
      cat > ~/.config/pip/pip.conf << EOF
      [global]
      index-url = $INTERNAL_PYPI_URL
      EOF
Em ambientes sem conexão com a internet, todas as ferramentas de que Devin precisa (runtimes de linguagem, ferramentas de CLI etc.) devem estar disponíveis nos seus espelhos internos. Registries públicos e sites de download são inacessíveis.

VPN + certificados + proxy + idiomas

Uma configuração corporativa abrangente que combina conectividade VPN com certificados, proxy e suporte a vários idiomas. Esta é a ordem recomendada de operações.
VPN:
  • VPN_CONFIG_B64 — arquivo de configuração do OpenVPN codificado em Base64
Rede e 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 — nome do host 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 — resolver nomes 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 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 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. Runtime 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 | sh

maintenance:
  - 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 possam ser 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 baixar de espelhos internos).

Dicas para escrever boas configurações

  • Teste os comandos primeiro em uma sessão — execute os comandos manualmente em uma sessão do Devin antes de adicioná-los à sua configuração. 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) devem ir em maintenance.
  • Mantenha os comandos de maintenance rápidos — procure mantê-los 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 compatível 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 uma subshell para que as etapas seguintes não sejam afetadas pela mudança de diretório.
Para mais detalhes sobre sintaxe e execução, consulte a Referência de YAML. Para solucionar falhas de build, consulte Solução de problemas e FAQ.