Blueprint pronti da copiare e incollare per linguaggi comuni, registri privati e infrastruttura Enterprise.
Blueprint pronti da copiare e incollare per linguaggi e casi d’uso comuni. Ogni template è autonomo. Combinali per comporre la configurazione completa.Per una panoramica completa di ogni campo, consulta il riferimento dei blueprint.
Secrets: I template fanno riferimento ai secret tramite $SECRET_NAME. Configurali in Settings > Secrets prima di usare un template. Non inserire mai credenziali in chiaro nel blueprint.
Blueprint essenziali per le configurazioni più comuni. Copiane uno, incollalo nell’editor dei blueprint e il gioco è fatto.
Progetto Node.js
initialize: | npm install -g pnpmmaintenance: | pnpm installknowledge: - name: lint contents: | Esegui `pnpm lint` per verificare eventuali errori. - name: test contents: | Esegui `pnpm test` per la suite completa.
Progetto Python
initialize: | curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: | uv syncknowledge: - name: lint contents: | Esegui `uv run ruff check .` per il linting. - name: test contents: | Esegui `uv run pytest` per la suite completa.
Passaggi di build per ciascun repo, gestione delle dipendenze e voci di Knowledge. Configurali in Settings > Configurazione dell’ambiente > [il tuo repo].
initialize: | nvm install 20 nvm use 20maintenance: | npm installknowledge: - name: lint contents: | npx eslint . - name: test contents: | npm test - name: build contents: | npm run build
Usa npm install (non npm ci) in maintenance. Esegue un aggiornamento incrementale, mentre npm ci elimina node_modules e reinstalla tutto da zero a ogni sessione.
Rust (tramite rustup) e Cargo sono preinstallati nell’immagine di base di Devin. Salta il passaggio di installazione se la toolchain stabile predefinita è sufficiente. Devi solo scaricare le dipendenze.
Monorepo con frontend Node.js e backend Python. Ogni sottoprogetto ha le proprie voci di Knowledge.
initialize: - name: Install pnpm run: npm install -g pnpm - name: Install uv run: curl -LsSf https://astral.sh/uv/install.sh | shmaintenance: - 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: | Questo è un monorepo con tre package: - `packages/frontend` — app React (TypeScript, pnpm) - `packages/backend` — API Python (FastAPI, uv) - `packages/shared` — utilità TypeScript condivise (da buildare prima del frontend) - name: frontend contents: | Esegui `cd packages/frontend && pnpm dev` per avviare il server di sviluppo. Esegui `cd packages/frontend && pnpm lint` per eseguire il lint. Esegui `cd packages/frontend && pnpm test` per eseguire i test. - name: backend contents: | Esegui `cd packages/backend && uv run uvicorn app.main:app --reload` per avviare l'API. Esegui `cd packages/backend && uv run ruff check .` per eseguire il lint. Esegui `cd packages/backend && uv run pytest` per eseguire i test.
Usa le subshell (cd dir && command) invece di cd dir && command, così la directory di lavoro viene reimpostata tra un passaggio e l’altro.
Un monorepo Java in cui servizi diversi richiedono versioni diverse del JDK. Installa entrambi i JDK durante la configurazione, poi usa le voci di knowledge per indicare a Devin quale JAVA_HOME usare per ciascun servizio.
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-headlessmaintenance: - 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: | Esegui la build del servizio API (JDK 17): JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 \ cd services/api && ./gradlew clean build - name: build_legacy contents: | Esegui la build del servizio legacy (JDK 11): JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 \ cd services/legacy && ./gradlew clean build - name: test_all contents: | Esegui i test per tutti i servizi: 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)
Configura i gestori di pacchetti per risolvere le dipendenze tramite registry privati. Impostali in Settings > Configurazione dell’ambiente > Configurazione a livello di org (oppure a livello di repo, se serve solo per una repo).
La configurazione delle credenziali deve stare in maintenance, non in initialize. I passaggi che scrivono segreti (password del registry, auth token) nei file di configurazione devono usare maintenance, in modo che le credenziali vengano
ricaricate a ogni sessione. I segreti vengono rimossi prima che lo snapshot venga salvato, quindi i file di configurazione scritti durante initialize non avranno credenziali valide all’avvio delle sessioni.
Se il tuo registry privato usa una CA aziendale, assicurati prima che il certificato CA sia installato a livello Enterprise. La configurazione seguente presuppone che l’attendibilità HTTPS sia
già configurata.
Configura npm per risolvere i pacchetti con ambito (ad es. @myorg/*) da un registry privato, mentre i pacchetti pubblici continuano a provenire dal registry npm predefinito.
Segreti richiesti
- GITHUB_PACKAGES_TOKEN — Token di accesso personale o token GitHub App con ambito 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
Sostituisci @myorg con il tuo scope npm. URL comuni dei registry privati:
Instrada tutti i pacchetti npm attraverso il tuo registry privato (non solo i pacchetti con ambito).
Segreti richiesti
NPM_REGISTRY_URL — URL completo del tuo registry npm (ad es. https://artifactory.example.com/artifactory/api/npm/npm-virtual) - NPM_REGISTRY_HOST — Solo hostname, senza protocollo (ad es.
artifactory.example.com) - REGISTRY_TOKEN — Token di autenticazione npm per il registry
maintenance: - name: Configure npm to use private registry run: | npm config set registry $NPM_REGISTRY_URL npm config set //${NPM_REGISTRY_HOST}/:_authToken $REGISTRY_TOKEN npm config set strict-ssl true
Configura pnpm per risolvere i pacchetti da un registry privato.
Segreti richiesti
NPM_REGISTRY_URL — URL completo del tuo registry npm - NPM_REGISTRY_HOST — Solo hostname, senza protocollo - REGISTRY_TOKEN — Token di autenticazione npm per il registry
initialize: - name: Install pnpm run: npm install -g pnpmmaintenance: - name: Configure pnpm for private registry run: | pnpm config set registry $NPM_REGISTRY_URL pnpm config set //${NPM_REGISTRY_HOST}/:_authToken $REGISTRY_TOKEN
Configura Yarn (Classic v1 o Berry v2+) per risolvere i pacchetti da un registry privato.
Segreti richiesti
- NPM_REGISTRY_URL — URL completo del tuo registry npm/Yarn - REGISTRY_TOKEN — Token di autenticazione per il registry (solo Berry)
Yarn Classic (v1):
initialize: - name: Install Yarn Classic run: npm install -g yarnmaintenance: - name: Configure Yarn for private registry run: | yarn config set registry "$NPM_REGISTRY_URL" # Per i pacchetti con ambito: # 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" # Per i pacchetti con ambito: # yarn config set npmScopes.myorg.npmRegistryServer "https://npm.pkg.github.com" # yarn config set npmScopes.myorg.npmAuthToken "$GITHUB_PACKAGES_TOKEN"
Configura pip e uv per recuperare i pacchetti dal tuo registry PyPI privato (ad es. Nexus, Artifactory).
Segreti richiesti
PYPI_REGISTRY_URL — URL completo del tuo indice PyPI, incluse le credenziali se richieste (ad es. https://user:token@nexus.example.com/repository/pypi-proxy/simple)
Configura Poetry per recuperare i pacchetti da un registry PyPI privato.
Segreti richiesti
POETRY_REGISTRY_URL — URL completo del tuo registry compatibile con PyPI - REGISTRY_USER — Nome utente del registry - REGISTRY_PASS — Password del registry o token API
Installa il JDK e configura Maven in modo che tutta la risoluzione delle dipendenze passi attraverso il tuo registry privato (ad es., Artifactory, Nexus).
JDK 17 è preinstallato nell’immagine di base di Devin. Salta il passaggio di installazione se l’OpenJDK 17 predefinito è sufficiente. Ti servono solo l’installazione di Maven e la configurazione del registry.
Segreti richiesti
MAVEN_REGISTRY_URL — URL del tuo registry Maven (ad es., https://artifactory.example.com/artifactory/maven-virtual) - REGISTRY_USER — Nome utente del registry - REGISTRY_PASS — Password del registry o
token API
Installa il JDK e configura Gradle per risolvere tutte le dipendenze tramite il tuo registry privato.
JDK 17 è preinstallato nell’immagine di base di Devin. Salta il passaggio di installazione del JDK se la versione predefinita è sufficiente.
Segreti richiesti
- GRADLE_REGISTRY_URL — URL del tuo registry Gradle/Maven - REGISTRY_USER — Nome utente del registry - REGISTRY_PASS — Password del registry o token API
Installa Go e configuralo per risolvere i moduli tramite un proxy privato per i moduli (ad es. Athens, Artifactory o un endpoint GOPROXY).
Segreti richiesti
GO_PROXY_URL — URL del tuo proxy per i moduli Go (ad es. https://athens.corp.internal) - GIT_TOKEN — token di accesso personale per repo Git private che ospitano moduli Go
initialize: - name: Install Go run: | GO_VERSION=1.23.5 ARCH=$(dpkg --print-architecture) curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz" \ | sudo tar -xz -C /usr/local echo 'export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"' \ | sudo tee /etc/profile.d/golang.sh > /dev/null - name: Configure Go for private modules run: | cat << 'GOENV' | sudo tee /etc/profile.d/go-private.sh > /dev/null export GOPROXY="$GO_PROXY_URL,direct" export GONOSUMCHECK="corp.internal/*,github.com/myorg/*" export GOPRIVATE="corp.internal/*,github.com/myorg/*" GOENVmaintenance: - name: Authenticate Go private modules run: | git config --global url."https://$GIT_TOKEN@github.com/myorg/".insteadOf "https://github.com/myorg/"
Configura Docker per scaricare da un registry di container privato.
Segreti richiesti
DOCKER_MIRROR_URL(facoltativo) — URL del mirror Docker Hub (ad es., https://mirror.corp.internal) - DOCKER_REGISTRY_URL — URL del tuo registry di container privato (ad es.,
registry.corp.internal:5000) - DOCKER_REGISTRY_USER — Nome utente del registry - DOCKER_REGISTRY_PASS — Password del registry o token API
initialize: - name: Create Docker config directory run: sudo mkdir -p /etc/dockermaintenance: - name: Configure Docker for private registry run: | # Configura il mirror del registry (opzionale — instrada i pull di Docker Hub attraverso il tuo registry) cat << EOF | sudo tee /etc/docker/daemon.json > /dev/null { "registry-mirrors": ["$DOCKER_MIRROR_URL"] } EOF sudo systemctl restart docker || true # Accedi al container registry privato echo "$DOCKER_REGISTRY_PASS" | docker login "$DOCKER_REGISTRY_URL" \ --username "$DOCKER_REGISTRY_USER" \ --password-stdin
Configura Cargo in modo che risolva i crate da un registry privato.
Rust (tramite rustup) e Cargo sono già preinstallati nell’immagine di base di Devin. Salta il passaggio di installazione se la toolchain stabile predefinita è sufficiente. È necessaria solo la configurazione del registry.
Segreti richiesti
CARGO_REGISTRY_INDEX — URL dell’indice del registry privato (ad es. sparse+https://cargo.corp.internal/api/v1/crates/) - CARGO_REGISTRY_TOKEN — token di autenticazione per il registry privato
Se devi solo aggiungere un registry privato senza sostituire crates.io, rimuovi le sezioni [source.crates-io] e [source.private] e usa cargo install --registry private oppure [dependencies] my-crate = { version = "1.0", registry = "private" } in Cargo.toml.
Ruby / Bundler
Installa Ruby e configura Bundler per risolvere le dipendenze gem da un server Gem privato.
Segreti richiesti
GEM_SERVER_URL — URL del tuo server Gem privato (ad es., https://artifactory.example.com/artifactory/api/gems/gems-virtual) - REGISTRY_USER — Nome utente del registry - REGISTRY_PASS — Password del registry
o token 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"
I token AWS CodeArtifact scadono dopo 12 ore. Usa maintenance per aggiornare il token all’inizio di ogni sessione. Questo esempio configura npm, pip e Maven per usare CodeArtifact.
awscli è preinstallato nell’immagine di base di Devin. Devi solo configurare l’aggiornamento del token e il registry.
Segreti richiesti
AWS_ACCESS_KEY_ID e AWS_SECRET_ACCESS_KEY — credenziali IAM con le autorizzazioni codeartifact:GetAuthorizationToken e sts:GetServiceBearerToken - CA_DOMAIN — Nome del dominio
CodeArtifact - CA_DOMAIN_OWNER — ID dell’account AWS proprietario del dominio - CA_REGION — Regione AWS (ad es., us-east-1) - CA_NPM_REPO, CA_PYPI_REPO, CA_MAVEN_REPO — Nomi dei repository per ciascun ecosistema
Infrastruttura a livello di macchina valida per tutte le org e repo. Impostala in Settings > ambiente di base di Devin (a livello di Enterprise) oppure in Settings > configurazione dell’ambiente > configurazione a livello di org (a livello di org).
La tua organizzazione utilizza un’autorità di certificazione privata per i servizi interni. Devin richiede il certificato radice per accedere ai registry interni e agli strumenti tramite HTTPS.
Segreti richiesti
- CORP_ROOT_CA_B64 — certificato PEM codificato in Base64 della tua CA aziendale. Genera con: cat corp-root-ca.crt | base64 -w0
Se la tua organizzazione utilizza più certificati CA (ad es. CA distinte per diversi servizi interni).
Segreti richiesti
- CORP_ROOT_CA_B64 — certificato CA principale codificato in Base64 - CORP_INTERMEDIATE_CA_B64 — certificato CA intermedio codificato in 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 # Crea un bundle combinato per gli strumenti che richiedono un singolo file 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
Instrada tutto il traffico di rete tramite un proxy aziendale.
Segreti richiesti
CORP_HTTP_PROXY — URL del proxy HTTP (ad es. http://proxy.corp.example.com:8080) - CORP_HTTPS_PROXY — URL del proxy HTTPS - CORP_NO_PROXY — elenco di host, separati da virgole, da escludere dal proxy (ad es.
localhost,127.0.0.1,.corp.example.com)
Se il proxy aziendale richiede l’autenticazione tramite nome utente/password.
Segreti richiesti
PROXY_USER — Nome utente del proxy - PROXY_PASS — Password del proxy - PROXY_HOST — hostname e porta del proxy (ad es. proxy.corp.example.com:8080) - CORP_NO_PROXY — host da escludere dal proxy
Configurazione combinata per ambienti che richiedono sia una CA aziendale sia un proxy. Questa configurazione è comune negli ambienti enterprise in cui i servizi interni usano certificati privati e tutto il traffico deve passare tramite un proxy.
Segreti richiesti
CORP_ROOT_CA_B64 — certificato CA aziendale codificato in Base64 - CORP_HTTP_PROXY, CORP_HTTPS_PROXY — URL del proxy - CORP_NO_PROXY — host da escludere dal proxy
I tuoi registry privati, i server Git o altri servizi interni sono raggiungibili solo tramite VPN. Questo modulo deve essere eseguito prima degli altri moduli che richiedono l’accesso di rete alle risorse interne.
Segreti richiesti
OpenVPN:
VPN_CONFIG_B64 — file di configurazione OpenVPN (.ovpn) codificato in Base64. Genera con: cat corp.ovpn | base64 -w0
VPN_AUTH_USER(facoltativo) — nome utente VPN, se la VPN richiede l’autenticazione con nome utente/password
VPN_AUTH_PASS(facoltativo) — password VPN
WireGuard:
WG_CONFIG_B64 — file di configurazione WireGuard codificato in Base64. Genera con: cat wg0.conf | base64 -w0
OpenVPN:
initialize: - name: Install and configure OpenVPN run: | sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openvpn # Scrivi la configurazione VPN sudo mkdir -p /etc/openvpn/client echo "$VPN_CONFIG_B64" | base64 -d \ | sudo tee /etc/openvpn/client/corp.conf > /dev/null # Se la VPN richiede autenticazione con username/password 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 # Avvia il tunnel VPN sudo systemctl daemon-reload sudo systemctl enable --now openvpn-client@corp # Attendi che il tunnel sia attivo for i in $(seq 1 30); do if ip link show tun0 >/dev/null 2>&1; then break; fi sleep 1 done
La tua organizzazione richiede che tutti i commit Git siano firmati e vuoi che GitHub contrassegni i commit di Devin come Verified.
Segreti richiesti
GPG_PRIVATE_KEY_B64 — chiave privata GPG codificata in Base64. Genera con: gpg --export-secret-keys <key-id> | base64 -w0
GIT_USER_NAME — nome autore Git (ad es. Devin AI)
GIT_USER_EMAIL — email autore Git. Deve corrispondere a un UID della chiave GPG, altrimenti GitHub non verificherà la firma.
Carica anche la chiave pubblica corrispondente nell’account GitHub le cui credenziali Devin usa per eseguire il push (in GitHub Settings > SSH and GPG keys). GitHub contrassegna i commit come Verified solo quando la chiave pubblica usata per la firma è registrata nell’account autore del commit.
initialize: - name: Prepare GPG and git signing config run: | # Consenti a GPG di funzionare senza un 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
Identità Git e chiavi SSH
Configura l’identità Git e le chiavi SSH di Devin per accedere a server Git privati.
Segreti richiesti
GIT_USER_NAME — nome autore Git - GIT_USER_EMAIL — email autore Git - SSH_PRIVATE_KEY_B64 — chiave privata SSH codificata in Base64. Genera con: cat ~/.ssh/id_ed25519 | base64 -w0 -
SSH_KNOWN_HOSTS_B64 — voci known_hosts codificate in Base64. Genera con: ssh-keyscan git.corp.internal | base64 -w0 - SSH_CONFIG_B64(facoltativo) — file di configurazione SSH codificato in Base64
initialize: - name: Configure git identity run: | git config --global user.name "$GIT_USER_NAME" git config --global user.email "$GIT_USER_EMAIL" # Prepara la directory SSH mkdir -p ~/.ssh && chmod 700 ~/.sshmaintenance: - name: Install SSH keys run: | # Installa la chiave privata SSH (in maintenance così viene ricaricata a ogni sessione) echo "$SSH_PRIVATE_KEY_B64" | base64 -d > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 # Aggiungi i known hosts per il tuo server Git echo "$SSH_KNOWN_HOSTS_B64" | base64 -d >> ~/.ssh/known_hosts # Installa facoltativamente una configurazione SSH personalizzata if [ -n "${SSH_CONFIG_B64:-}" ]; then echo "$SSH_CONFIG_B64" | base64 -d > ~/.ssh/config chmod 600 ~/.ssh/config fi
Genera la voce known_hosts per il tuo server Git con ssh-keyscan git.corp.internal | base64 -w0.
Installa pacchetti di sistema che non sono presenti nell’immagine Devin predefinita (ad es. librerie native per l’elaborazione delle immagini o la generazione di PDF).
Imposta variabili d’ambiente persistenti da rendere disponibili in ogni sessione.L’approccio consigliato è scrivere righe KEY=VALUE nel file $ENVRC. Le variabili scritte in $ENVRC vengono esportate automaticamente per tutti i passaggi successivi e per la sessione di Devin (in modo analogo a $GITHUB_ENV di GitHub Actions).
Entrambi gli approcci funzionano. $ENVRC è più semplice ed è consigliato nella maggior parte dei casi.
Impostazioni locali e fuso orario
Le immagini di base predefinite potrebbero avere impostazioni del locale non corrette. Configura il locale e il fuso orario per evitare avvisi da strumenti di 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 # Genera e imposta il 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 # Imposta il fuso orario sudo timedatectl set-timezone UTC 2>/dev/null || \ sudo ln -sfn /usr/share/zoneinfo/UTC /etc/localtime
Limiti di risorse (ulimits)
Le build Java, Gradle e Node.js raggiungono spesso il limite predefinito di 1024 file aperti. Aumentalo per evitare errori di 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 # Imposta anche il massimo del kernel echo "fs.file-max = 65536" | sudo tee /etc/sysctl.d/99-devin-filemax.conf > /dev/null sudo sysctl -p /etc/sysctl.d/99-devin-filemax.conf 2>/dev/null || true
Sostituzione del mirror di APT
In ambienti air-gapped o soggetti a restrizioni, sostituisci i repository APT predefiniti di Ubuntu con un mirror interno.
Segreti richiesti
- APT_MIRROR_URL — URL del tuo mirror APT interno (ad es. https://artifactory.example.com/artifactory/ubuntu-remote)
initialize: - name: Replace APT sources with internal mirror run: | # Backup delle sorgenti originali sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak # Sostituisci tutti i mirror Ubuntu con il mirror interno sudo sed -i "s|http://archive.ubuntu.com/ubuntu|$APT_MIRROR_URL|g" /etc/apt/sources.list sudo sed -i "s|http://security.ubuntu.com/ubuntu|$APT_MIRROR_URL|g" /etc/apt/sources.list sudo apt-get update -qq
direnv è già configurato nella shell di Devin, quindi le variabili di .envrc vengono caricate automaticamente. Non serve eseguire il source manualmente.
Per le variabili d’ambiente sensibili (API key, token, password del database), usa i segreti del repo invece dei file .envrc. I segreti del repo sono archiviati in modo sicuro e vengono iniettati all’avvio della sessione. Non compaiono mai nel blueprint o nello snapshot.
Cambio della versione di Node per singola repo
Usa nvm (preinstallato) per cambiare versione di Node.js per ciascun repository tramite .nvmrc.
nvm use legge .nvmrc dalla directory radice della repo. Assicurati che il repository ne abbia uno (ad es., contenente 20).
Autenticazione nel browser (Playwright)
Devin mette a disposizione un browser Chrome con un endpoint CDP su localhost:29229durante le sessioni. Usa script Playwright per automatizzare il login nel browser.
Il browser è disponibile solo durante le sessioni, non nelle build snapshot. Installa Playwright in initialize e conserva gli script di login nella tua repo.
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
Esempio di script di accesso (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")
Conserva le credenziali di accesso come secrets, non nel codice sorgente. Per un’autenticazione a lungo termine, esegui il commit degli script di accesso in .agents/skills/ in modo che Devin possa riautenticarsi automaticamente.
Strumenti di sistema personalizzati e PATH
Installa pacchetti di sistema, binari personalizzati e configura il PATH in initialize.
Devin supporta l’esecuzione diretta nei blueprint di GitHub Actions basate su Node.js. Questo è utile per installare versioni specifiche degli strumenti tramite le stesse azioni usate dalla tua CI.
Azioni come setup-node e setup-python modificano il PATH e le variabili d’ambiente. I binari installati da un’azione sono disponibili in tutti i passaggi successivi e in maintenance. Sono supportate solo le GitHub Actions basate su Node.js. Le azioni composite e quelle basate su Docker non sono supportate.
Non servono GitHub Actions per la configurazione di base degli strumenti. I comandi shell diretti (nvm install 20, curl ... | sh, apt-get install) funzionano altrettanto bene e spesso sono più semplici. Le GitHub Actions sono particolarmente utili quando vuoi replicare esattamente la configurazione della tua CI o sfruttare la comodità di azioni come setup-java, che gestiscono più distribuzioni.
Questi esempi mostrano come si combinano le configurazioni Enterprise e quelle a livello di org. In pratica, le divideresti tra diversi ambiti. Qui sono riunite a scopo di riferimento.
Stack Enterprise completo (Artifactory)
Un ambiente enterprise completo: certificato CA aziendale, proxy, Java (Maven), Python (pip/uv), Node.js (npm) e Docker, tutti puntati a una singola istanza di Artifactory.
Segreti richiesti
Rete e attendibilità (per l’intero account):
CORP_ROOT_CA_B64 — certificato CA aziendale codificato in Base64
CORP_HTTP_PROXY — URL del proxy HTTP
CORP_HTTPS_PROXY — URL del proxy HTTPS
CORP_NO_PROXY — host da escludere dal proxy
Credenziali del registry (per l’intera org):
ARTIFACTORY_USER — nome utente Artifactory
ARTIFACTORY_TOKEN — token API o password di Artifactory
ARTIFACTORY_MAVEN_URL — URL del repository Maven (ad es., https://artifactory.example.com/artifactory/maven-virtual)
ARTIFACTORY_PYPI_URL — URL del repository PyPI (ad es., https://user:token@artifactory.example.com/artifactory/api/pypi/pypi-virtual/simple)
ARTIFACTORY_NPM_URL — URL del repository npm (ad es., https://artifactory.example.com/artifactory/api/npm/npm-virtual)
ARTIFACTORY_DOCKER_URL — URL del registry Docker (ad es., artifactory.example.com)
In genere questo verrebbe suddiviso in tre ambiti:
A livello di account (initialize): Certificato e proxy
Org-wide (initialize): Installazione del runtime del linguaggio
A livello di org (maintenance): credenziali del registry (aggiornate a ogni sessione)
In questo esempio, tutti i registry puntano alla stessa istanza di Artifactory, ma utilizzano percorsi URL diversi. Ogni ecosistema di pacchetti ha il proprio formato di endpoint. Gli URL di Maven, PyPI, npm e Docker sono tutti diversi, anche per lo stesso registry.
Multilingua con registry diversi
Quando linguaggi diversi usano registri privati differenti (ad es. Maven da Nexus, npm da GitHub Packages, Python da Artifactory).
Segreti richiesti
NEXUS_MAVEN_URL — URL del repository Maven di Nexus - NEXUS_USER — nome utente di Nexus - NEXUS_PASS — password di Nexus - GITHUB_PACKAGES_TOKEN — token di accesso personale GitHub con ambito read:packages -
ARTIFACTORY_USER — nome utente di Artifactory - ARTIFACTORY_TOKEN — token API di Artifactory - GIT_TOKEN — token di accesso personale per i moduli Go privati
In un ambiente completamente air-gapped, Devin non può accedere ad alcun URL pubblico. Tutti gli strumenti, i runtime e i pacchetti devono provenire da mirror interni.
Segreti richiesti
Certificati:
CORP_ROOT_CA_B64 — certificato CA aziendale codificato in Base64
Accesso ai mirror:
APT_MIRROR_URL — URL del mirror APT interno di Ubuntu
MIRROR_USER — nome utente per l’autenticazione al mirror
MIRROR_PASS — password per l’autenticazione al mirror
JDK_TARBALL_URL — URL da cui scaricare il tarball JDK dal mirror interno
NODE_TARBALL_URL — URL da cui scaricare il tarball Node.js dal mirror interno
Registry dei pacchetti:
INTERNAL_MAVEN_URL — URL del registry Maven interno
Negli ambienti air-gapped, tutti gli strumenti necessari a Devin (runtime dei linguaggi di programmazione, strumenti CLI, ecc.) devono essere disponibili sui vostri mirror interni. I registry pubblici e i siti di download non sono raggiungibili.
VPN + certificati + proxy + linguaggi
Una configurazione Enterprise completa che combina connettività VPN con certificati, proxy e supporto multilingua. Questo è l’ordine delle operazioni consigliato.
Segreti richiesti
VPN:
VPN_CONFIG_B64 — file di configurazione OpenVPN codificato in Base64
Rete & attendibilità:
CORP_ROOT_CA_B64 — certificato CA aziendale codificato in Base64
CORP_HTTP_PROXY — URL del proxy HTTP
CORP_HTTPS_PROXY — URL del proxy HTTPS
CORP_NO_PROXY — host da escludere dal proxy
Credenziali del registry:
MAVEN_REGISTRY_URL — URL del registry Maven
NPM_REGISTRY_URL — URL del registry npm
PYPI_REGISTRY_HOST — hostname del registry PyPI
REGISTRY_USER — nome utente del registry (per Maven e pip)
REGISTRY_PASS — password del registry (per Maven e pip)
REGISTRY_TOKEN — token di autenticazione per npm
initialize: # 1. VPN — deve essere il primo affinché le risorse interne siano raggiungibili - 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 — risolve gli hostname interni - 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. Certificati — attendibilità delle CA interne - 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 — instrada il traffico attraverso il proxy aziendale - 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. Language runtimes - 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
L’ordine dei passaggi initialize è importante. La VPN deve venire per prima (in modo che gli host interni siano raggiungibili), poi il DNS (in modo che i nomi vengano risolti), poi i certificati (in modo che HTTPS funzioni), poi il proxy (in modo che il traffico venga instradato correttamente) e infine i runtime dei linguaggi (che potrebbero scaricare da mirror interni).
Prova prima i comandi in una sessione. Esegui i comandi manualmente in una sessione di Devin prima di aggiungerli al blueprint. È più veloce che aspettare un ciclo di build completo.
Usa initialize per gli strumenti da installare una sola volta, maintenance per le dipendenze. Tutto ciò che richiede minuti per essere installato (compilatori, binari di grandi dimensioni, strumenti globali) va in initialize. I comandi rapidi per le dipendenze (npm install, uv sync) vanno in maintenance.
Mantieni rapidi i comandi maintenance. Cerca di restare sotto i 2 minuti. Vengono eseguiti all’inizio di ogni sessione.
Usa $ENVRC per le variabili d’ambiente. Non scrivere in .bashrc o .profile. $ENVRC è il meccanismo supportato per impostare variabili tra passaggi e sessioni.
Assegna un nome ai passaggi. La forma estesa con i campi name rende molto più semplice individuare gli errori nei log di build.
Usa le subshell per i monorepo.(cd packages/foo && npm install) viene eseguito in una subshell, così i passaggi successivi non risentono del cambio di directory.
Usa npm install, non npm ci.npm ci elimina node_modules e reinstalla tutto da zero a ogni sessione, rallentando maintenance.
Usa i secrets del repo per i valori sensibili. Configurali in Settings > Secrets con ambito repo invece di inserirli direttamente nei blueprint.