Zum Hauptinhalt springen
Diese Seite enthält in sich geschlossene Beispiele für environment.yaml für gängige Szenarien. Jedes Beispiel behandelt einen Aspekt — kombinieren Sie sie, um Ihre vollständige Konfiguration zu erstellen. Eine Einführung in die Syntax und die Konzepte von environment.yaml finden Sie unter Umgebungskonfiguration. Details zur Syntax finden Sie in der YAML-Referenz.
Secrets: In den Beispielen verweist $SECRET_NAME auf Secrets, die unter Settings → Secrets konfiguriert sind. Konfigurieren Sie diese, bevor Sie ein Beispiel verwenden. Jedes Beispiel enthält einen einklappbaren Abschnitt „Erforderliche Secrets“, der genau auflistet, welche Secrets eingerichtet werden müssen und welche Werte sie erwarten. Hinterlegen Sie Anmeldedaten niemals fest codiert in Ihrer environment.yaml.

Kurzreferenz: häufigste Setups

Die am häufigsten verwendeten Konfigurationen auf einen Blick. Die vollständige Liste finden Sie in den folgenden Abschnitten.
initialize: |
  npm install -g pnpm

maintenance: |
  pnpm install

knowledge:
  - name: lint
    contents: |
      Führen Sie `pnpm lint` aus, um Fehler zu prüfen.
  - name: test
    contents: |
      Führen Sie `pnpm test` für die gesamte Test-Suite aus.
initialize:
  - name: uv installieren
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  - name: Abhängigkeiten synchronisieren
    run: uv sync

knowledge:
  - name: lint
    contents: |
      Führen Sie `uv run ruff check .` für das Linting aus.
  - name: test
    contents: |
      Führen Sie `uv run pytest` für die gesamte Test-Suite aus.
initialize:
  - name: pnpm installieren
    run: npm install -g pnpm
  - name: uv installieren
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  - name: Frontend-Abhängigkeiten
    run: (cd frontend && pnpm install)
  - name: Backend-Abhängigkeiten
    run: (cd backend && uv sync)

knowledge:
  - name: structure
    contents: |
      - `frontend/` — React-App (pnpm)
      - `backend/` — Python-API (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, verwaltet mit pnpm-Workspaces.
      - `packages/web` — Next.js-Frontend
      - `packages/api` — Express.js-Backend
      - `packages/shared` — Gemeinsame Hilfsfunktionen
  - name: test
    contents: |
      Führen Sie `pnpm test` im Stammverzeichnis für alle Pakete aus.
      Führen Sie `pnpm --filter web test` für ein bestimmtes Paket aus.

Wie die Schichten funktionieren

Umgebungskonfigurationen werden in Schichten angewendet. Jede Schicht baut auf der vorherigen auf:
1

Kontoweit (Enterprise)

Zertifikate, Proxy, DNS, VPN, Commit-Signierung, Gebietsschema, Ressourcenlimits, Git-Identität, APT-Mirrors. Gilt für alle Orgs und alle Repos.
2

Org-weit

Sprachlaufzeiten, Paketmanager-Registry-Konfiguration, Container-Registry, gemeinsame Tools. Gilt für alle Repos innerhalb der Org.
3

Repo-spezifisch

Build-Befehle, Abhängigkeitsinstallation, Test-/Lint-Befehle, projektspezifische Hinweise für Devin. Gilt für ein einzelnes Repo.
Kontoweite Konfigurationen werden zuerst angewendet, dann Org-weite und schließlich Repo-spezifische. Konfigurieren Sie jedes Beispiel im passenden Geltungsbereich unter Settings.

Modulreferenz

Verwenden Sie diese Tabelle, um das passende Beispiel für Ihre Anforderungen zu finden. Jedes Modul ist unabhängig — Sie können sie beliebig kombinieren.
ModulEbeneAbschnitt
CA-ZertifikateEnterpriseUnternehmens-CA-Zertifikat
Mehrere CA-ZertifikateEnterpriseMehrere CA-Zertifikate
HTTP/HTTPS-ProxyEnterpriseHTTP/HTTPS-Proxy
Authentifizierter ProxyEnterpriseAuthentifizierter Proxy
CA-Zertifikat + ProxyEnterpriseCA-Zertifikat + Proxy (kombiniert)
VPN (OpenVPN / WireGuard)EnterpriseVPN-Verbindung
Benutzerdefiniertes DNSEnterpriseBenutzerdefinierte DNS-Auflösung
GPG-Commit-SignierungEnterpriseGPG-Commit-Signierung
Git-Identität + SSH-SchlüsselEnterpriseGit-Identität und SSH-Schlüssel
SystempaketeEnterpriseSystempakete installieren
UmgebungsvariablenEnterpriseBenutzerdefinierte Umgebungsvariablen
Locale & ZeitzoneEnterpriseLocale und Zeitzone
RessourcenlimitsEnterpriseRessourcenlimits (ulimits)
APT-MirrorEnterpriseAPT-Mirror ersetzen
Java + MavenOrgJava + Maven mit einer privaten Registry
Java + GradleOrgJava + Gradle mit einer privaten Registry
Python + pip/uvOrgPython + pip/uv mit einer privaten Registry
Python + PoetryOrgPython + Poetry mit einer privaten Registry
Node.js + npm (scoped)OrgNode.js + npm mit einer privaten Registry für einen Geltungsbereich
Node.js + npm (vollständiger Mirror)OrgNode.js + npm mit einem vollständigen privaten Registry-Mirror
Node.js + pnpmOrgNode.js + pnpm mit einer privaten Registry
Node.js + YarnOrgNode.js + Yarn mit einer privaten Registry
GoOrgGo mit einem privaten Modul-Proxy
.NET + NuGetOrg.NET + NuGet mit einem privaten Feed
DockerOrgDocker mit einer privaten Container-Registry
Rust + CargoOrgRust + Cargo mit einer privaten Registry
Ruby + BundlerOrgRuby + Bundler mit einem privaten Gem-Server
PHP + ComposerOrgPHP + Composer mit einer privaten Registry
AWS CodeArtifactOrgAWS CodeArtifact-Token aktualisieren
Node.js-ProjektRepoStandard-Node.js-Projekt
Python-ProjektRepoStandard-Python-Projekt
Java-ProjektRepoStandard-Java-Projekt
Go-ProjektRepoStandard-Go-Projekt
Rust-ProjektRepoStandard-Rust-Projekt
MonorepoRepoMonorepo mit mehreren Services
Monorepo mit mehreren JDKsRepoMonorepo mit mehreren JDK-Versionen
Knowledge-EinträgeRepoUmfangreiche Knowledge-Einträge
Pre-commit-HooksRepoPre-commit-Hooks

Enterprise- / kontoweite Beispiele

Diese Beispiele konfigurieren Infrastruktur auf Maschinenebene, die für alle Orgs und Repos gilt. Legen Sie sie in Enterprise Settings (für kontoweite Konfigurationen) oder unter Settings > Environment > Organization-wide setup (für org-weite Konfigurationen) fest.

Unternehmens-CA-Zertifikat

Ihre Organisation verwendet eine private Zertifizierungsstelle für interne Dienste. Devin benötigt das Stammzertifikat, um über HTTPS interne Registries und Tools zu erreichen.
  • CORP_ROOT_CA_B64 — Base64-kodiertes PEM-Zertifikat von Ihrer Unternehmens-CA. Erzeugen Sie es mit: 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

Mehrere CA-Zertifikate

Einige Organisationen verwenden unterschiedliche CAs für verschiedene interne Dienste (z. B. eine für die Artefakt-Registry und eine andere für einen internen Git-Server).
  • CA_CERT_REGISTRY_B64 — Base64-kodiertes PEM-Zertifikat für die Artefakt-Registry-CA
  • CA_CERT_GIT_B64 — Base64-kodiertes PEM-Zertifikat für die Git-Server-CA
initialize:
  - name: Install corporate CA certificates
    run: |
      # Jedes Zertifikat dekodieren und installieren
      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: Zertifikate zu einem einzigen Bundle zusammenführen
      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

HTTP/HTTPS-Proxy

Ihre Organisation leitet ausgehenden Netzwerkverkehr über einen Unternehmens-Proxy.
  • CORP_HTTP_PROXY — HTTP-Proxy-URL (z. B. http://proxy.corp.internal:8080)
  • CORP_HTTPS_PROXY — HTTPS-Proxy-URL (z. B. http://proxy.corp.internal:8080)
  • CORP_NO_PROXY — Kommaseparierte Hosts, die den Proxy umgehen sollen (z. B. 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"
Setzen Sie CORP_NO_PROXY auf eine kommaseparierte Liste von Hosts, die den Proxy umgehen sollen, z. B. localhost,127.0.0.1,.corp.internal,10.0.0.0/8.

Proxy mit Authentifizierung

Wenn Ihr Proxy einen Benutzernamen und ein Passwort erfordert, geben Sie die Zugangsdaten in der Proxy-URL an.
  • PROXY_USER — Benutzername für die Proxy-Authentifizierung
  • PROXY_PASS — Passwort für die Proxy-Authentifizierung
  • PROXY_HOST — Proxy-Hostname (z. B. proxy.corp.internal)
  • PROXY_PORT — Proxy-Port (z. B. 8080)
  • CORP_NO_PROXY — Kommagetrennte Hosts, für die der Proxy umgangen wird
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"

CA-Zertifikat + Proxy (kombiniert)

Der gängigste Unternehmensstandard — installieren Sie ein unternehmenseigenes CA-Zertifikat und konfigurieren Sie einen systemweiten Proxy.
  • CORP_ROOT_CA_B64 — Base64-kodiertes PEM-Zertifikat von Ihrer unternehmenseigenen CA
  • CORP_HTTP_PROXY — HTTP-Proxy-URL
  • CORP_HTTPS_PROXY — HTTPS-Proxy-URL
  • CORP_NO_PROXY — Kommagetrennte Hosts, die den Proxy umgehen
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"

VPN-Verbindung

Ihre privaten Registries, Git-Server oder andere internen Dienste sind nur über VPN erreichbar. Dieses Modul muss vor anderen Modulen ausgeführt werden, die Netzwerkzugriff auf interne Ressourcen benötigen.
OpenVPN:
  • VPN_CONFIG_B64 — Base64-kodierte OpenVPN-Konfigurationsdatei (.ovpn). Generieren mit: cat corp.ovpn | base64 -w0
  • VPN_AUTH_USER (optional) — VPN-Nutzername, falls Ihr VPN eine Authentifizierung per Nutzername/Passwort erfordert
  • VPN_AUTH_PASS (optional) — VPN-Passwort
WireGuard:
  • WG_CONFIG_B64 — Base64-kodierte WireGuard-Konfigurationsdatei. Generieren mit: cat wg0.conf | base64 -w0
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

      # Schreibe die VPN-Konfiguration
      sudo mkdir -p /etc/openvpn/client
      echo "$VPN_CONFIG_B64" | base64 -d \
        | sudo tee /etc/openvpn/client/corp.conf > /dev/null

      # Falls das VPN eine Authentifizierung per Nutzername/Passwort erfordert
      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

      # Starte den VPN-Tunnel
      sudo systemctl daemon-reload
      sudo systemctl enable --now openvpn-client@corp

      # Warte, bis der Tunnel aufgebaut ist
      for i in $(seq 1 30); do
        if ip link show tun0 >/dev/null 2>&1; then break; fi
        sleep 1
      done
Weitere Details zur VPN-Einrichtung finden Sie unter VPN-Konfiguration.

Benutzerdefinierte DNS-Auflösung

Ihre internen Dienste verwenden private DNS-Namen, die nicht über öffentliches DNS beziehbar sind.
initialize:
  - name: Configure custom DNS resolution
    run: |
      # Add internal hostnames
      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

      # Optionally configure custom nameservers
      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

GPG-Commit-Signatur

Ihre Organisation verlangt, dass alle Git-Commits signiert sind.
  • GPG_PRIVATE_KEY_B64 — Base64-kodierter privater GPG-Schlüssel. Erstellen mit: gpg --export-secret-keys <key-id> | base64 -w0
initialize:
  - name: Prepare GPG and git signing config
    run: |
      # GPG ohne TTY betreiben
      echo 'export GPG_TTY=$(tty)' | sudo tee -a /etc/profile.d/gpg.sh > /dev/null

      # Git zum Signieren von Commits vorkonfigurieren (Schlüssel wird in maintenance importiert)
      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

      # Signing-Key-ID festlegen
      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-Identität und SSH-Schlüssel

Konfigurieren Sie die Git-Identität und SSH-Schlüssel für den Zugriff auf private Repositories per SSH.
  • GIT_USER_NAME — Name des Git-Autors (z. B. Devin AI)
  • GIT_USER_EMAIL — E-Mail-Adresse des Git-Autors (z. B. devin@company.com)
  • SSH_PRIVATE_KEY_B64 — Base64-kodierter privater SSH-Schlüssel. Generieren mit: cat ~/.ssh/id_ed25519 | base64 -w0
  • SSH_KNOWN_HOSTS_B64 — Base64-kodierte Known-Hosts-Einträge. Generieren mit: ssh-keyscan git.corp.internal | base64 -w0
  • SSH_CONFIG_B64 (optional) — Base64-kodierte SSH-Konfigurationsdatei für benutzerdefinierte Host-Aliase
initialize:
  - name: Prepare SSH directory and git identity
    run: |
      # Git-Identität festlegen
      git config --global user.name "$GIT_USER_NAME"
      git config --global user.email "$GIT_USER_EMAIL"

      # SSH-Verzeichnis vorbereiten
      mkdir -p ~/.ssh && chmod 700 ~/.ssh

      # git-lfs bei Bedarf aktivieren
      # git lfs install

maintenance:
  - name: Install SSH keys
    run: |
      # Privaten SSH-Schlüssel installieren (in maintenance, damit er bei jeder Sitzung neu geladen wird)
      echo "$SSH_PRIVATE_KEY_B64" | base64 -d > ~/.ssh/id_ed25519
      chmod 600 ~/.ssh/id_ed25519

      # Bekannte Hosts für den Git-Server hinzufügen
      echo "$SSH_KNOWN_HOSTS_B64" | base64 -d >> ~/.ssh/known_hosts

      # Optional eine benutzerdefinierte SSH-Konfiguration installieren
      if [ -n "${SSH_CONFIG_B64:-}" ]; then
        echo "$SSH_CONFIG_B64" | base64 -d > ~/.ssh/config
        chmod 600 ~/.ssh/config
      fi
Erzeugen Sie den Known-Hosts-Eintrag für Ihren Git-Server mit ssh-keyscan git.corp.internal | base64 -w0.

Systempakete installieren

Ihr Projekt benötigt Systempakete, die im standardmäßigen Devin-Image nicht enthalten sind (z. B. native Bibliotheken für die Bildverarbeitung oder PDF-Generierung).
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

Benutzerdefinierte Umgebungsvariablen

Legen Sie persistente Umgebungsvariablen fest, die in jeder Sitzung verfügbar sein sollen. Die empfohlene Vorgehensweise besteht darin, Zeilen im Format KEY=VALUE in die Datei $ENVRC zu schreiben. In $ENVRC geschriebene Variablen werden automatisch für alle nachfolgenden Schritte und die Devin-Sitzung exportiert (ähnlich wie GitHub Actions’ $GITHUB_ENV).
initialize:
  - name: Set custom environment variables
    run: |
      echo "CORPORATE_ENV=production" >> $ENVRC
      echo "DEFAULT_REGION=us-east-1" >> $ENVRC
      echo "MAX_RETRIES=3" >> $ENVRC
Sie können Umgebungsvariablen auch in Skripte in /etc/profile.d/ schreiben, damit sie systemweit verfügbar sind:
cat << 'ENVVARS' | sudo tee /etc/profile.d/custom-env.sh > /dev/null
export CORPORATE_ENV=production
export DEFAULT_REGION=us-east-1
ENVVARS
Beide Ansätze funktionieren. $ENVRC ist jedoch einfacher und wird für die meisten Fälle empfohlen.

Locale und Zeitzone

Standard-Basis-Images können fehlerhafte Locale-Einstellungen haben. Konfigurieren Sie Locale und Zeitzone, um Warnungen von Build-Tools, Java, Python und Git zu vermeiden.
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

      # Locale generieren und setzen
      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

      # Zeitzone setzen
      sudo timedatectl set-timezone UTC 2>/dev/null || \
        sudo ln -sfn /usr/share/zoneinfo/UTC /etc/localtime

Ressourcenlimits (ulimits)

Java-, Gradle- und Node.js-Builds stoßen häufig an das Standard-Limit von 1024 offenen Dateien. Erhöhen Sie es, um Build-Fehler zu vermeiden.
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

      # Auch das Kernel-Maximum setzen
      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

APT-Mirror ersetzen

In isolierten oder eingeschränkten Umgebungen ersetzen Sie die Standard-APT-Quellen von Ubuntu durch einen internen Mirror.
  • APT_MIRROR_URL — URL Ihres internen APT-Mirrors (z. B. https://artifactory.example.com/artifactory/ubuntu-remote)
initialize:
  - name: Replace APT sources with internal mirror
    run: |
      # Originale Quellen sichern
      sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak

      # Alle Ubuntu-Mirrors durch den internen Mirror ersetzen
      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

      # Drittanbieter-Quellen deaktivieren, die nicht erreichbar sind
      # sudo mv /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/disabled/ 2>/dev/null || true

      sudo apt-get update -qq
Gängige APT-Mirror-URL-Muster:
  • Artifactory: https://artifactory.example.com/artifactory/ubuntu-remote
  • Nexus: https://nexus.example.com/repository/ubuntu-proxy

Org-weite Beispiele

Diese Beispiele installieren Laufzeitumgebungen für Programmiersprachen und konfigurieren Paketmanager für die Verwendung privater Registries. Legen Sie sie unter Settings > Environment > Organization-wide setup fest.
Wenn Ihre private Registry eine Unternehmens-CA verwendet, stellen Sie sicher, dass das CA-Zertifikat zuerst auf Enterprise-Ebene installiert wird. Die unten stehende Konfiguration auf Org-Ebene setzt voraus, dass HTTPS-Vertrauen bereits eingerichtet ist.
Die Konfiguration von Anmeldedaten gehört in maintenance, nicht in initialize. Schritte, die Secrets (Registry-Passwörter, Auth-Token) in Konfigurationsdateien schreiben, sollten maintenance verwenden, damit die Anmeldedaten in jeder Sitzung frisch geladen werden. Die Secrets-Datei wird entfernt, bevor das Maschinen-Image gespeichert wird, sodass Konfigurationsdateien, die während initialize geschrieben werden, beim Start von Sitzungen keine gültigen Anmeldedaten haben.

Java + Maven mit privater Registry

Installieren Sie das JDK und konfigurieren Sie Maven so, dass die Auflösung aller Abhängigkeiten über Ihre private Registry erfolgt (z. B. Artifactory, Nexus).
JDK 17 ist auf Devins Basis-Image vorinstalliert. Überspringen Sie den unten stehenden Installationsschritt, wenn das Standard-OpenJDK 17 ausreicht — Sie benötigen dann nur die Maven-Installation und die Registry-Konfiguration.
  • MAVEN_REGISTRY_URL — URL Ihrer Maven-Registry (z. B. https://artifactory.example.com/artifactory/maven-virtual)
  • REGISTRY_USER — Benutzername für die Registry
  • REGISTRY_PASS — Passwort für die Registry oder API-Token
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
Gängige Registry-URL-Muster für 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 mit privater Registry

Installieren Sie das JDK und konfigurieren Sie Gradle so, dass alle Abhängigkeiten über Ihre private Registry bezogen werden.
JDK 17 ist auf Devins Basis-Image vorinstalliert. Überspringen Sie den Schritt zur JDK-Installation, wenn der Standard ausreicht.
  • GRADLE_REGISTRY_URL — URL Ihrer Gradle-/Maven-Registry
  • REGISTRY_USER — Registry-Benutzername
  • REGISTRY_PASS — Registry-Passwort oder API-Token
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 mit einer privaten Registry

Konfigurieren Sie pip und uv so, dass Pakete aus Ihrer privaten PyPI-Registry bezogen werden (z. B. Nexus, Artifactory).
  • PYPI_REGISTRY_HOST — Hostname Ihrer PyPI-Registry (z. B. artifactory.example.com/artifactory/api/pypi/pypi-virtual)
  • REGISTRY_USER — Registry-Nutzername
  • REGISTRY_PASS — Registry-Passwort oder API-Token
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 berücksichtigt pip.conf, kann aber auch explizit gesetzt werden
      echo "export UV_INDEX_URL=https://$REGISTRY_USER:$REGISTRY_PASS@${PYPI_REGISTRY_HOST}/simple" \
        | sudo tee /etc/profile.d/uv-registry.sh > /dev/null
Häufige Registry-URL-Muster für 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 mit privater Registry

Konfigurieren Sie Poetry so, dass es Pakete aus einer privaten PyPI-Registry bezieht.
  • PYPI_REGISTRY_HOST — Hostname Ihrer PyPI-Registry
  • REGISTRY_USER — Nutzername der Registry
  • REGISTRY_PASS — Passwort der Registry oder API-Token
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"

      # Private Registry optional als Standardquelle festlegen
      # poetry source add --priority=primary private "https://${PYPI_REGISTRY_HOST}/simple"

Node.js + npm mit einer privaten Registry für einen Geltungsbereich

Konfigurieren Sie npm so, dass Pakete in einem Geltungsbereich (z. B. @myorg/*) aus einer privaten Registry wie GitHub Packages bezogen werden, während öffentliche Pakete weiterhin aus der Standard-npm-Registry stammen.
  • GITHUB_PACKAGES_TOKEN — Personal Access Token oder GitHub App-Token mit read:packages-Geltungsbereich
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
Ersetzen Sie @myorg durch Ihren npm-Geltungsbereich. Gängige URLs für private Registries:
  • 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 mit einem vollständigen Spiegel Ihrer privaten Registry

Leiten Sie alle npm-Pakete über Ihre private Registry (nicht nur Pakete mit Geltungsbereich).
  • NPM_REGISTRY_URL — Vollständige URL Ihrer npm-Registry (z. B. https://artifactory.example.com/artifactory/api/npm/npm-virtual)
  • NPM_REGISTRY_HOST — Nur der Hostname, ohne Protokoll (z. B. artifactory.example.com)
  • REGISTRY_TOKEN — npm-Authentifizierungs-Token für die 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

Node.js + pnpm mit einer privaten Registry

Konfigurieren Sie pnpm so, dass Pakete aus einer privaten Registry bezogen werden.
pnpm ist im Basis-Image von Devin vorinstalliert. Sie können den Installationsschritt überspringen und nur die Registry konfigurieren.
  • NPM_REGISTRY_URL — Vollständige URL Ihrer npm-Registry
  • NPM_REGISTRY_HOST — Nur der Hostname, ohne Protokoll
  • REGISTRY_TOKEN — npm-Authentifizierungs-Token für die Registry
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 mit privater Registry

Konfigurieren Sie Yarn (Classic v1 oder Berry v2+) so, dass Pakete aus einer privaten Registry bezogen werden.
Yarn Classic (v1) ist auf Devins Basis-Image vorinstalliert. Überspringen Sie den Installationsschritt, wenn Sie nur v1 benötigen.
  • NPM_REGISTRY_URL — Vollständige URL Ihrer npm-/Yarn-Registry
  • REGISTRY_TOKEN — Auth-Token für die Registry (nur Berry)
initialize:
  - name: Yarn Classic installieren
    run: npm install -g yarn

maintenance:
  - name: Yarn für private Registry konfigurieren
    run: |
      yarn config set registry "$NPM_REGISTRY_URL"
      # Für Scoped Packages:
      # yarn config set @myorg:registry "https://npm.pkg.github.com"

Go mit einem privaten Modul-Proxy

Installieren Sie Go und konfigurieren Sie es so, dass Module über einen privaten Modul-Proxy bezogen werden (z. B. Athens, Artifactory oder einen GOPROXY-Endpunkt).
  • GO_PROXY_URL — URL Ihres Go-Modul-Proxys (z. B. https://athens.corp.internal)
  • GIT_TOKEN — Personal Access Token für private Git-Repos, die Go-Module hosten
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/"
Gängige Go-Proxy-URL-Muster:
  • Artifactory: https://artifactory.example.com/artifactory/go-virtual
  • Nexus: https://nexus.example.com/repository/go-proxy
  • Athens: https://athens.corp.internal

.NET + NuGet mit einem privaten Feed

Installieren Sie das .NET SDK und konfigurieren Sie NuGet so, dass Pakete aus einem privaten Feed bezogen werden (z. B. Azure Artifacts, Artifactory).
  • NUGET_FEED_URL — URL Ihres NuGet-Feeds (z. B. https://pkgs.dev.azure.com/org/project/_packaging/feed/nuget/v3/index.json)
  • REGISTRY_USER — Registry-Nutzername
  • REGISTRY_PASS — Registry-Passwort oder API-Token
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

      # Optionally disable the default nuget.org source
      # dotnet nuget disable source nuget.org
Gängige NuGet-Feed-URLs:
  • 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 mit einer privaten Container-Registry

Konfigurieren Sie Docker für die Authentifizierung bei einer privaten Container-Registry.
  • DOCKER_MIRROR_URL (optional) — URL Ihres Docker-Hub-Mirrors (z. B. https://mirror.corp.internal)
  • DOCKER_REGISTRY_URL — URL Ihrer privaten Container-Registry (z. B. registry.corp.internal:5000)
  • DOCKER_REGISTRY_USER — Registry-Benutzername
  • DOCKER_REGISTRY_PASS — Registry-Passwort oder API-Token
initialize:
  - name: Create Docker config directory
    run: sudo mkdir -p /etc/docker

maintenance:
  - name: Configure Docker for private registry
    run: |
      # Configure registry mirror (optional — routes Docker Hub pulls through your registry)
      cat << EOF | sudo tee /etc/docker/daemon.json > /dev/null
      {
        "registry-mirrors": ["$DOCKER_MIRROR_URL"]
      }
      EOF
      sudo systemctl restart docker || true

      # Log in to the private container registry
      echo "$DOCKER_REGISTRY_PASS" | docker login "$DOCKER_REGISTRY_URL" \
        --username "$DOCKER_REGISTRY_USER" \
        --password-stdin
Gängige URLs für Container-Registries:
  • 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 mit einer privaten Registry

Installieren Sie Rust und konfigurieren Sie Cargo so, dass es Crates aus einer privaten Registry bezieht.
Rust (über rustup) und Cargo sind im Basis-Image von Devin vorinstalliert. Überspringen Sie den Installationsschritt, wenn die stabile Standard-Toolchain ausreicht — Sie benötigen nur die Registry-Konfiguration.
  • CARGO_REGISTRY_INDEX — URL des Index der privaten Registry (z. B. sparse+https://cargo.corp.internal/api/v1/crates/)
  • CARGO_REGISTRY_TOKEN — Auth-Token für die private Registry
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
Wenn Sie nur eine private Registry hinzufügen möchten, ohne crates.io zu ersetzen, entfernen Sie die Abschnitte [source.crates-io] und [source.private] und verwenden Sie cargo install --registry private oder [dependencies] my-crate = { version = "1.0", registry = "private" } in Cargo.toml.

Ruby + Bundler mit einem privaten Gem-Server

Installieren Sie Ruby und konfigurieren Sie Bundler so, dass es Gems von einem privaten Gem-Server bezieht.
  • GEM_SERVER_URL — URL Ihres privaten Gem-Servers (z. B. https://artifactory.example.com/artifactory/api/gems/gems-virtual)
  • REGISTRY_USER — Benutzername für die Registry
  • REGISTRY_PASS — Passwort für die Registry oder API-Token
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"
Gängige URL-Muster für Gem-Server:
  • Artifactory: https://artifactory.example.com/artifactory/api/gems/gems-virtual
  • Nexus: https://nexus.example.com/repository/rubygems-proxy
  • Gemfury: https://gem.fury.io/<org>

Aktualisierung des AWS CodeArtifact-Tokens

AWS CodeArtifact-Tokens laufen nach 12 Stunden ab. Verwenden Sie maintenance, um das Token zu Beginn jeder Sitzung zu aktualisieren. Dieses Beispiel konfiguriert npm, pip und Maven für die Verwendung mit CodeArtifact.
awscli ist im Basis-Image von Devin vorinstalliert. Sie benötigen nur die Token-Aktualisierung und die Registry-Konfiguration.
  • AWS_ACCESS_KEY_ID und AWS_SECRET_ACCESS_KEY — IAM-Zugangsdaten mit den Berechtigungen codeartifact:GetAuthorizationToken und sts:GetServiceBearerToken
  • CA_DOMAIN — Ihr CodeArtifact-Domainname
  • CA_DOMAIN_OWNER — AWS-Konto-ID des Kontos, dem die Domain gehört
  • CA_REGION — AWS-Region (z. B. us-east-1)
  • CA_NPM_REPO, CA_PYPI_REPO, CA_MAVEN_REPO — Repository-Namen für jedes Ökosystem
maintenance:
  - name: Refresh CodeArtifact auth token
    run: |
      # Neues Token abrufen (gültig für 12 Stunden)
      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"

      # npm konfigurieren
      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"

      # pip konfigurieren
      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

      # Maven konfigurieren (optional)
      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 mit privater Registry

Installieren Sie PHP und konfigurieren Sie Composer so, dass Composer Pakete aus einer privaten Packagist- oder Satis-Registry bezieht.
  • COMPOSER_REGISTRY_URL — URL Ihrer privaten Composer-Registry (z. B. https://repo.packagist.com/<org>)
  • REGISTRY_USER — Benutzername für die Registry
  • REGISTRY_PASS — Passwort der Registry oder API-Token
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

      # Composer installieren
      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"

      # Bei der Registry authentifizieren
      composer config --global http-basic.$(echo "$COMPOSER_REGISTRY_URL" \
        | sed 's|https\?://||;s|/.*||') "$REGISTRY_USER" "$REGISTRY_PASS"

      # Standard-packagist.org optional deaktivieren
      # composer config --global repositories.packagist false
Gängige URL-Muster für Composer-Registries:
  • 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

Repository-spezifische Beispiele

Diese Beispiele konfigurieren Build-Schritte pro Repo, die Abhängigkeitsverwaltung und Knowledge-Einträge. Legen Sie sie unter Settings > Environment > [your repo] fest.

Standard-Node.js-Projekt

Ein typisches Node.js-Projekt mit Lint-, Test- und Build-Befehlen.
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.

Standard-Python-Projekt

Ein Python-Projekt, das uv zur Abhängigkeitsverwaltung verwendet.
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.

Standard Java-Projekt

Ein Java-Projekt, das Maven zur Abhängigkeitsverwaltung verwendet.
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.

Standard Go-Projekt

Ein Go-Projekt mit den üblichen Tools.
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.

Standard Rust-Projekt

Ein Rust-Projekt, das Cargo verwendet.
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 mit mehreren Services

Ein Monorepo mit separaten Frontend- und Backend-Services, die unterschiedliche Paketmanager verwenden.
initialize:
  - name: Install pnpm
    run: npm install -g pnpm
  - name: Install uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  - name: Frontend-Abhängigkeiten installieren
    run: (cd packages/frontend && pnpm install)
  - name: Backend-Abhängigkeiten installieren
    run: (cd packages/backend && uv sync)
  - name: Gemeinsame Bibliothek bauen
    run: (cd packages/shared && pnpm install && pnpm build)

knowledge:
  - name: structure
    contents: |
      Dies ist ein Monorepo mit drei Paketen:
      - `packages/frontend` — React-App (TypeScript, pnpm)
      - `packages/backend` — Python-API (FastAPI, uv)
      - `packages/shared` — Gemeinsame TypeScript-Hilfsprogramme (muss vor dem Frontend gebaut werden)
  - name: frontend
    contents: |
      Führe `cd packages/frontend && pnpm dev` aus, um den Entwicklungsserver zu starten.
      Führe `cd packages/frontend && pnpm lint` aus, um zu linten.
      Führe `cd packages/frontend && pnpm test` aus, um zu testen.
  - name: backend
    contents: |
      Führe `cd packages/backend && uv run uvicorn app.main:app --reload` aus, um die API zu starten.
      Führe `cd packages/backend && uv run ruff check .` aus, um zu linten.
      Führe `cd packages/backend && uv run pytest` aus, um zu testen.
Verwenden Sie Subshells (cd dir && command) anstelle von cd dir && command, damit das Arbeitsverzeichnis zwischen den Schritten jeweils zurückgesetzt wird.

Monorepo mit mehreren JDK-Versionen

Ein Java-Monorepo, in dem verschiedene Dienste unterschiedliche JDK-Versionen benötigen. Installiere beide JDKs bei der Einrichtung und verwende dann Knowledge-Einträge, um Devin mitzuteilen, welches JAVA_HOME für den jeweiligen Dienst verwendet werden soll.
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)

Pre-commit-Hooks

Wenn Ihr Projekt pre-commit-Hooks verwendet, installieren Sie sie in maintenance, damit sie in jeder Sitzung verfügbar sind.
initialize:
  - name: Install pre-commit
    run: pip install pre-commit

maintenance:
  - name: Install pre-commit hooks
    run: pre-commit install --install-hooks
Wenn das Projekt pre-commit bereits als Entwicklungsabhängigkeit enthält (z. B. in pyproject.toml), überspringe den Schritt initialize und verwende stattdessen in maintenance uv run pre-commit install --install-hooks oder pipx run pre-commit install --install-hooks.

Umfangreiche Knowledge-Einträge

Dokumentieren Sie die Architektur, Konventionen und Workflows Ihres Projekts in knowledge-Einträgen.
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/

Kombinierte Beispiele

Diese Beispiele zeigen, wie Konfigurationen auf Enterprise- und Org-Ebene zusammenwirken. In der Praxis würden Sie diese auf verschiedene Geltungsbereiche aufteilen — hier werden sie der Referenz halber zusammen gezeigt.

Vollständiger Enterprise-Stack

Eine vollständige Enterprise-Umgebung: unternehmenseigenes CA-Zertifikat, Proxy, Java (Maven), Python (pip/uv), Node.js (npm) und Docker — alles auf eine einzige Artifactory-Instanz konfiguriert.
Netzwerk & Vertrauen (kontoweit):
  • CORP_ROOT_CA_B64 — Base64-kodiertes unternehmenseigenes CA-Zertifikat
  • CORP_HTTP_PROXY — HTTP-Proxy-URL
  • CORP_HTTPS_PROXY — HTTPS-Proxy-URL
  • CORP_NO_PROXY — Hosts, die den Proxy umgehen
Registry-Anmeldedaten (organisationsweit):
  • ARTIFACTORY_USER — Artifactory-Benutzername
  • ARTIFACTORY_TOKEN — Artifactory-API-Token oder Passwort
  • ARTIFACTORY_MAVEN_URL — Maven-Repository-URL (z. B. https://artifactory.example.com/artifactory/maven-virtual)
  • ARTIFACTORY_PYPI_URL — PyPI-Repository-URL (z. B. https://user:token@artifactory.example.com/artifactory/api/pypi/pypi-virtual/simple)
  • ARTIFACTORY_NPM_URL — npm-Repository-URL (z. B. https://artifactory.example.com/artifactory/api/npm/npm-virtual)
  • ARTIFACTORY_DOCKER_URL — Docker-Registry-URL (z. B. artifactory.example.com)
Typischerweise würde dies auf drei Geltungsbereiche aufgeteilt:
  • Kontoweit (initialize): Zertifikat und Proxy
  • Organisationsweit (initialize): Installation von Sprachlaufzeitumgebungen
  • Organisationsweit (maintenance): Registry-Anmeldedaten (pro Sitzung aktualisiert)
Hier zur Referenz kombiniert dargestellt:
initialize:
  # ── Kontoübergreifend: Netzwerk und Vertrauen ──────────────────────────────────────

  - name: Unternehmens-CA-Zertifikat installieren
    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: Systemweiten Proxy konfigurieren
    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

  # ── Organisationsweit: Sprachlaufzeiten ──────────────────────────────────────────

  - name: JDK 17 + Maven installieren
    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: uv installieren
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  # ── Kontoübergreifend: Git-Proxy (wird jede Sitzung aktualisiert) ───────────────────

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

  # ── Organisationsweit: Registry-Anmeldedaten (werden jede Sitzung aktualisiert) ──────────────

  - name: Maven → Artifactory konfigurieren
    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: pip/uv → Artifactory PyPI konfigurieren
    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: npm → Artifactory konfigurieren
    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: Docker → Artifactory konfigurieren
    run: |
      echo "$ARTIFACTORY_TOKEN" | docker login "$ARTIFACTORY_DOCKER_URL" \
        --username "$ARTIFACTORY_USER" \
        --password-stdin
In diesem Beispiel verweisen alle Registries auf dieselbe Artifactory-Instanz, verwenden jedoch unterschiedliche URL-Pfade. Jedes Paket-Ökosystem hat sein eigenes Endpunktformat — Maven-, PyPI-, npm- und Docker-URLs unterscheiden sich selbst für dieselbe Registry.

Mehrere Sprachen mit unterschiedlichen Registries

Wenn verschiedene Sprachen verschiedene private Registries verwenden (z. B. Maven über Nexus, npm über GitHub Packages, Python über Artifactory).
  • NEXUS_MAVEN_URL — URL des Nexus-Maven-Repositorys
  • NEXUS_USER — Nexus-Benutzername
  • NEXUS_PASS — Nexus-Passwort
  • GITHUB_PACKAGES_TOKEN — GitHub Personal Access Token mit Geltungsbereich read:packages
  • ARTIFACTORY_USER — Artifactory-Benutzername
  • ARTIFACTORY_TOKEN — Artifactory-API-Token
  • GIT_TOKEN — Personal Access Token für private Go-Module
maintenance:
  # Maven → Nexus
  - name: Maven → Nexus konfigurieren
    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 (scoped)
  - name: npm → GitHub Packages konfigurieren
    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: pip → Artifactory konfigurieren
    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 → private Module über git
  - name: Private Go-Module konfigurieren
    run: |
      git config --global url."https://$GIT_TOKEN@github.com/myorg/".insteadOf "https://github.com/myorg/"

Air-Gap-Umgebung mit privaten Spiegelservern

In einer vollständig isolierten Air-Gap-Umgebung hat Devin keinen Zugriff auf öffentliche URLs. Alle Tools, Laufzeitumgebungen und Pakete müssen aus internen Spiegelservern stammen.
Zertifikate:
  • CORP_ROOT_CA_B64 — Base64-kodiertes Unternehmens-CA-Zertifikat
Zugriff auf Spiegelserver:
  • APT_MIRROR_URL — URL des internen Ubuntu-APT-Spiegelservers
  • MIRROR_USER — Benutzername für die Authentifizierung am Spiegelserver
  • MIRROR_PASS — Passwort für die Authentifizierung am Spiegelserver
  • JDK_TARBALL_URL — URL zum Herunterladen des JDK-Tarballs vom internen Spiegelserver
  • NODE_TARBALL_URL — URL zum Herunterladen des Node.js-Tarballs vom internen Spiegelserver
Paket-Registries:
  • INTERNAL_MAVEN_URL — URL der internen Maven-Registry
  • INTERNAL_NPM_URL — URL der internen npm-Registry
  • INTERNAL_PYPI_URL — URL der internen PyPI-Registry
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: |
      # JDK-Tarball aus internem Artefakt-Store herunterladen
      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
In Air-Gap-Umgebungen müssen alle Tools, die Devin benötigt (Laufzeitumgebungen für Programmiersprachen, CLI-Tools usw.), auf Ihren internen Mirror-Servern verfügbar sein. Öffentliche Registries und Downloadseiten sind nicht erreichbar.

VPN + Zertifikate + Proxy + Sprachen

Ein umfassendes Unternehmens-Setup, das VPN-Konnektivität mit Zertifikaten, Proxy und Unterstützung für mehrere Sprachen kombiniert. Dies ist die empfohlene Reihenfolge der Schritte.
VPN:
  • VPN_CONFIG_B64 — Base64-kodierte OpenVPN-Konfigurationsdatei
Netzwerk & trust:
  • CORP_ROOT_CA_B64 — Base64-kodiertes Zertifikat der Unternehmens-CA
  • CORP_HTTP_PROXY — HTTP-Proxy-URL
  • CORP_HTTPS_PROXY — HTTPS-Proxy-URL
  • CORP_NO_PROXY — Hosts, für die der Proxy umgangen wird
Registry-Anmeldedaten:
  • MAVEN_REGISTRY_URL — Maven-Registry-URL
  • NPM_REGISTRY_URL — npm-Registry-URL
  • PYPI_REGISTRY_HOST — PyPI-Registry-Hostname
  • REGISTRY_USER — Registry-Nutzername (für Maven und pip)
  • REGISTRY_PASS — Registry-Passwort (für Maven und pip)
  • REGISTRY_TOKEN — npm-Authentifizierungstoken
initialize:
  # 1. VPN — muss zuerst kommen, damit interne Ressourcen erreichbar sind
  - 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 — interne Hostnamen auflösen
  - 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. Zertifikate — internen CAs vertrauen
  - 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 — Datenverkehr über den Unternehmens-Proxy leiten
  - 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. Sprachlaufzeitumgebungen
  - 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
Die Reihenfolge ist bei initialize-Schritten wichtig. Zuerst muss VPN eingerichtet werden (damit interne Hosts erreichbar sind), dann DNS (damit Namen bezogen werden), dann Zertifikate (damit HTTPS funktioniert), dann der Proxy (damit der Datenverkehr korrekt geroutet wird) und schließlich Sprachlaufzeitumgebungen (die möglicherweise von internen Spiegelservern herunterladen).

Tipps zum Schreiben guter Konfigurationen

  • Testen Sie Befehle zuerst in einer Sitzung — führen Sie Befehle manuell in einer Devin-Sitzung aus, bevor Sie sie Ihrer Konfiguration hinzufügen. Das geht schneller, als auf einen vollständigen Build-Zyklus zu warten.
  • Verwenden Sie initialize für Tools, die nur einmal installiert werden, und maintenance für Abhängigkeiten — alles, was mehrere Minuten zur Installation braucht (Compiler, große Binärdateien, globale Tools), gehört in initialize. Schnelle Befehle zum Installieren von Abhängigkeiten (npm install, uv sync) gehören in maintenance.
  • Halten Sie maintenance-Befehle schnell — idealerweise dauern sie weniger als 2 Minuten. Sie werden zu Beginn jeder Sitzung ausgeführt.
  • Verwenden Sie $ENVRC für Umgebungsvariablen — schreiben Sie nicht in .bashrc oder .profile. $ENVRC ist der unterstützte Mechanismus, um Variablen über Schritte und Sitzungen hinweg festzulegen.
  • Geben Sie Ihren Schritten Namen — die Erweiterte Form mit name-Feldern erleichtert es deutlich, Fehler in Build-Logs zu erkennen.
  • Verwenden Sie Subshells für Monorepos(cd packages/foo && npm install) wird in einer Subshell ausgeführt, sodass nachfolgende Schritte nicht von der Verzeichnisänderung beeinflusst werden.
Weitere Informationen zu Syntax und Ausführungsdetails finden Sie in der YAML-Referenz. Hilfe bei fehlgeschlagenen Builds finden Sie unter Fehlerbehebung & FAQ.