Skip to main content
Vorlagen zum Kopieren und Einfügen für gängige Programmiersprachen und Anwendungsfälle. Jede Vorlage ist in sich abgeschlossen. Kombinieren Sie sie zu Ihrer vollständigen Konfiguration. Eine vollständige Aufschlüsselung aller Felder finden Sie in der Blueprint-Referenz.
Secrets: Vorlagen referenzieren Secrets über $SECRET_NAME. Konfigurieren Sie diese unter Settings > Secrets, bevor Sie eine Vorlage verwenden. Hinterlegen Sie Zugangsdaten niemals hartcodiert in Ihrem Blueprint.

Schnellstart

Minimale Blueprints für die gängigsten Setups. Kopieren Sie einen, fügen Sie ihn in den Blueprint-Editor ein, und Sie sind fertig.
initialize: |
  npm install -g pnpm

maintenance: |
  pnpm install

knowledge:
  - name: lint
    contents: |
      Führen Sie `pnpm lint` aus, um auf Fehler zu prüfen.
  - name: test
    contents: |
      Führen Sie `pnpm test` für die vollständige Testsuite aus.
initialize: |
  curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance: |
  uv sync

knowledge:
  - name: lint
    contents: |
      Führen Sie `uv run ruff check .` zum Linten aus.
  - name: test
    contents: |
      Führen Sie `uv run pytest` für die vollständige Testsuite aus.
initialize:
  - name: pnpm installieren
    run: npm install -g pnpm
  - name: Install uv
    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

Repository-Blueprints

Repo-spezifische Build-Schritte, Abhängigkeitsmanagement und Knowledge-Einträge. Lege diese unter Settings > Umgebungskonfiguration > [dein Repo] fest.

Python

Empfohlene Einrichtung für Python-Projekte, die uv für die Abhängigkeitsverwaltung verwenden.
initialize: |
  curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance: |
  uv sync

knowledge:
  - name: lint
    contents: |
      uv run ruff check .

      Auto-Fix:
      uv run ruff check --fix .

  - name: test
    contents: |
      uv run pytest

  - name: build
    contents: |
      uv run python -m build

Node.js

Standard-Node.js-Setup mit npm.
initialize: |
  nvm install 20
  nvm use 20

maintenance: |
  npm install

knowledge:
  - name: lint
    contents: |
      npx eslint .

  - name: test
    contents: |
      npm test

  - name: build
    contents: |
      npm run build
Verwenden Sie in maintenance npm install (nicht npm ci). Dadurch wird ein inkrementelles Update durchgeführt, während npm ci node_modules löscht und in jeder Sitzung alles von Grund auf neu installiert.

Go

Standard-Setup für Go mit Modulen.
initialize: |
  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

  go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest

maintenance: |
  go mod download

knowledge:
  - name: lint
    contents: |
      golangci-lint run

  - name: test
    contents: |
      go test ./...

  - name: build
    contents: |
      go build ./...

Java

Java-Einrichtung mit Gradle.
JDK 17 ist vorinstalliert im Basis-Image von Devin. Überspringen Sie die JDK-Installation, wenn das Standard-OpenJDK 17 ausreicht.
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: |
  ./gradlew dependencies

knowledge:
  - name: lint
    contents: |
      ./gradlew check

  - name: test
    contents: |
      ./gradlew test

  - name: build
    contents: |
      ./gradlew build

Ruby on Rails

Rails-Setup mit PostgreSQL.
initialize:
  - name: Install Ruby 3.3
    run: |
      sudo apt-get update -qq
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ruby-full libpq-dev postgresql-client

maintenance: |
  bundle install
  rails db:migrate

knowledge:
  - name: lint
    contents: |
      bundle exec rubocop

  - name: test
    contents: |
      bundle exec rspec

  - name: build
    contents: |
      rails assets:precompile

Rust

Standardmäßiges Rust-Setup mit Cargo.
Rust (über rustup) und Cargo sind im Basis-Image von Devin vorinstalliert. Überspringen Sie den Installationsschritt, wenn die standardmäßige stabile Toolchain ausreicht. Sie müssen nur die Abhängigkeiten abrufen.
initialize: |
  curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
  source ~/.cargo/env

maintenance: |
  cargo fetch

knowledge:
  - name: lint
    contents: |
      cargo clippy -- -D warnings

  - name: test
    contents: |
      cargo test

  - name: build
    contents: |
      cargo build --release

Monorepos

Monorepo mit einem Node.js-Frontend und einem Python-Backend. Jedes Teilprojekt erhält eigene Knowledge-Einträge.
initialize:
  - name: Install pnpm
    run: npm install -g pnpm
  - name: Install uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

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

knowledge:
  - name: structure
    contents: |
      Dies ist ein Monorepo mit drei Packages:
      - `packages/frontend` — React-App (TypeScript, pnpm)
      - `packages/backend` — Python-API (FastAPI, uv)
      - `packages/shared` — Gemeinsame TypeScript-Utilities (muss vor dem Frontend gebaut werden)
  - name: frontend
    contents: |
      Führe `cd packages/frontend && pnpm dev` aus, um den Dev-Server 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.
Verwende Subshells (cd dir && command) anstelle von cd dir && command, damit das Arbeitsverzeichnis zwischen den Schritten zurückgesetzt wird.

Private Paket-Registries

Konfigurieren Sie Paketmanager so, dass sie Abhängigkeiten aus privaten Registries beziehen. Konfigurieren Sie dies unter Settings > Umgebungskonfiguration > Org-wide setup (oder pro Repo, wenn es nur für ein Repo benötigt wird).
Die Konfiguration von Zugangsdaten gehört in maintenance, nicht in initialize. Schritte, die Secrets (Registry-Passwörter, Auth-Token) in Konfigurationsdateien schreiben, sollten maintenance verwenden, damit Zugangsdaten in jeder Sitzung neu geladen werden. Secrets werden entfernt, bevor der Snapshot gespeichert wird. Daher enthalten Konfigurationsdateien, die während initialize geschrieben werden, beim Start von Sitzungen keine gültigen Zugangsdaten.
Wenn Ihre private Registry eine Unternehmens-CA verwendet, stellen Sie sicher, dass das CA-Zertifikat zuerst auf Enterprise-Ebene installiert ist. Die folgende Konfiguration setzt voraus, dass das Vertrauen in HTTPS bereits hergestellt ist.

Node.js-Registries

Konfigurieren Sie npm so, dass Packages mit Scope (z. B. @myorg/*) aus einer privaten Registry bezogen werden, während öffentliche Packages weiterhin aus der Standard-npm-Registry kommen.
- GITHUB_PACKAGES_TOKEN — Personal Access Token oder GitHub-App-Token mit dem Geltungsbereich 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
Ersetzen Sie @myorg durch Ihren npm-Scope. Gängige private Registry-URLs:
  • 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>

Python-Registries

Konfigurieren Sie pip und uv so, dass sie Pakete aus Ihrer privaten PyPI-Registry beziehen (z. B. Nexus, Artifactory).
  • PYPI_REGISTRY_URL — Vollständige URL Ihres PyPI-Index, einschließlich Anmeldedaten, falls erforderlich (z. B. https://user:token@nexus.example.com/repository/pypi-proxy/simple)
maintenance:
  - name: Configure pip/uv for private registry
    run: |
      mkdir -p ~/.config/pip
      cat > ~/.config/pip/pip.conf << EOF
      [global]
      index-url = $PYPI_REGISTRY_URL
      EOF

      echo "export UV_INDEX_URL=$PYPI_REGISTRY_URL" \
        | sudo tee /etc/profile.d/uv-registry.sh > /dev/null
Gängige URL-Muster für PyPI-Registries:
  • Artifactory: https://artifactory.example.com/artifactory/api/pypi/pypi-virtual/simple
  • Nexus: https://nexus.example.com/repository/pypi-proxy/simple
  • AWS CodeArtifact: https://aws:TOKEN@domain-owner.d.codeartifact.region.amazonaws.com/pypi/repo/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

JVM-Registries

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 Installationsschritt, wenn das Standard-OpenJDK 17 ausreicht. Sie benötigen nur die Maven-Installation und die Konfiguration der Registry.
  • MAVEN_REGISTRY_URL — URL Ihrer Maven-Registry (z. B. https://artifactory.example.com/artifactory/maven-virtual) - REGISTRY_USER — Registry-Nutzername - 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 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>

Weitere Registries

Installieren Sie Go und konfigurieren Sie es so, dass es Module über einen privaten Modul-Proxy bezieht (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 bereitstellen
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 URL-Schemata für Go-Proxys:
  • Artifactory: https://artifactory.example.com/artifactory/go-virtual
  • Nexus: https://nexus.example.com/repository/go-proxy
  • Athens: https://athens.corp.internal
Konfigurieren Sie NuGet so, dass Pakete aus einem privaten Feed bezogen werden können.
- NUGET_SOURCE_URL — URL Ihres NuGet-Feeds - NUGET_API_KEY — API key oder PAT für den Feed
initialize:
  - name: Install .NET SDK
    run: |
      curl -fsSL https://dot.net/v1/dotnet-install.sh | bash -s -- --channel 8.0
      echo 'export PATH="$HOME/.dotnet:$PATH"' \
        | sudo tee /etc/profile.d/dotnet.sh > /dev/null

maintenance:
  - name: Configure NuGet for private feed
    run: |
      dotnet nuget add source "$NUGET_SOURCE_URL" \
        --name private \
        --username any \
        --password "$NUGET_API_KEY" \
        --store-password-in-clear-text 2>/dev/null || \
      dotnet nuget update source private \
        --source "$NUGET_SOURCE_URL" \
        --username any \
        --password "$NUGET_API_KEY" \
        --store-password-in-clear-text
Konfigurieren Sie Docker so, dass Images aus einer privaten Container-Registry abgerufen werden.
  • 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-Nutzername - 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: |
      # Registry-Mirror konfigurieren (optional — leitet Docker-Hub-Pulls über Ihre Registry)
      cat << EOF | sudo tee /etc/docker/daemon.json > /dev/null
      {
        "registry-mirrors": ["$DOCKER_MIRROR_URL"]
      }
      EOF
      sudo systemctl restart docker || true

      # Bei der privaten Container-Registry anmelden
      echo "$DOCKER_REGISTRY_PASS" | docker login "$DOCKER_REGISTRY_URL" \
        --username "$DOCKER_REGISTRY_USER" \
        --password-stdin
Gängige Container-Registry-URLs:
  • 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
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 Konfiguration der Registry.
  • CARGO_REGISTRY_INDEX — URL des Index einer 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.
Installieren Sie Ruby und konfigurieren Sie Bundler zum Beziehen von Gems von einem privaten Gem-Server.
  • GEM_SERVER_URL — URL Ihres privaten Gem-Servers (z. B. https://artifactory.example.com/artifactory/api/gems/gems-virtual) - REGISTRY_USER — Registry-Nutzername - REGISTRY_PASS — Registry- Passwort 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-Schemata 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>
Installieren Sie PHP und konfigurieren Sie Composer so, dass Pakete aus einer privaten Packagist- oder Satis-Registry bezogen werden.
  • COMPOSER_REGISTRY_URL — URL Ihrer privaten Composer-Registry (z. B. https://repo.packagist.com/<org>)
  • REGISTRY_USER — Registry-Nutzername
  • REGISTRY_PASS — Registry-Passwort 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"

      # Mit der Registry authentifizieren
      composer config --global http-basic.$(echo "$COMPOSER_REGISTRY_URL" \
        | sed 's|https\?://||;s|/.*||') "$REGISTRY_USER" "$REGISTRY_PASS"
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
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-Anmeldedaten mit den Berechtigungen codeartifact:GetAuthorizationToken und sts:GetServiceBearerToken - CA_DOMAIN — Name Ihrer CodeArtifact-Domain Domainname - CA_DOMAIN_OWNER — AWS-Konto-ID, dem die Domain gehört - CA_REGION — AWS-Region (z. B. us-east-1) - CA_NPM_REPO, CA_PYPI_REPO, CA_MAVEN_REPO — Reponamen 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

Enterprise-Infrastruktur

Infrastruktur auf Maschinenebene, die für alle Orgs und Repos gilt. Legen Sie diese in Settings > Devin’s base environment (unternehmensweit) oder Settings > Umgebungskonfiguration > Org-wide setup (org-weit) fest.

Netzwerk und Konnektivität

Ihre Organisation verwendet eine private Zertifizierungsstelle für interne Dienste. Devin benötigt das Stammzertifikat, um interne Registries und Tools über HTTPS zu erreichen.
- CORP_ROOT_CA_B64 — Base64-kodiertes PEM-Zertifikat von der CA Ihres Unternehmens. erzeugen 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
      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
Wenn Ihre Organisation mehrere CA-Zertifikate verwendet (z. B. separate CAs für unterschiedliche interne Dienste).
- CORP_ROOT_CA_B64 — Base64-codiertes primäres CA-Zertifikat - CORP_INTERMEDIATE_CA_B64 — Base64-codiertes Zwischenzertifikat
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

      # Kombiniertes Bundle für Tools erstellen, die eine einzelne CA-Datei benötigen
      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
Leiten Sie den gesamten Netzwerkverkehr über einen Unternehmensproxy.
  • CORP_HTTP_PROXY — HTTP-Proxy-URL (z. B. http://proxy.corp.example.com:8080) - CORP_HTTPS_PROXY — HTTPS-Proxy-URL - CORP_NO_PROXY — kommagetrennte Liste der Hosts, die den Proxy umgehen sollen (z. B. localhost,127.0.0.1,.corp.example.com)
initialize:
  - 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"

      # npm-Proxy konfigurieren
      npm config set proxy "$CORP_HTTP_PROXY"
      npm config set https-proxy "$CORP_HTTPS_PROXY"
Wenn Ihr Unternehmens-Proxy eine Authentifizierung per Nutzername/Passwort erfordert.
  • PROXY_USER — Proxy-Nutzername - PROXY_PASS — Proxy-Passwort - PROXY_HOST — Proxy-Hostname und -Port (z. B. proxy.corp.example.com:8080) - CORP_NO_PROXY — Hosts, für die der Proxy umgangen werden soll
initialize:
  - name: Configure authenticated proxy
    run: |
      PROXY_URL="http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}"

      cat << PROXY | sudo tee /etc/profile.d/proxy.sh > /dev/null
      export http_proxy="$PROXY_URL"
      export https_proxy="$PROXY_URL"
      export no_proxy="$CORP_NO_PROXY"
      export HTTP_PROXY="$PROXY_URL"
      export HTTPS_PROXY="$PROXY_URL"
      export NO_PROXY="$CORP_NO_PROXY"
      PROXY
      source /etc/profile.d/proxy.sh

maintenance:
  - name: Configure git for authenticated proxy
    run: |
      PROXY_URL="http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}"
      git config --global http.proxy "$PROXY_URL"
      git config --global https.proxy "$PROXY_URL"
Kombinierte Einrichtung für Umgebungen, die sowohl eine Unternehmens-CA als auch einen Proxy benötigen. Das ist in Unternehmensumgebungen üblich, in denen interne Dienste private Zertifikate verwenden und der gesamte Datenverkehr über einen Proxy geleitet werden muss.
  • CORP_ROOT_CA_B64 — Base64-kodiertes Unternehmens-CA-Zertifikat - CORP_HTTP_PROXY, CORP_HTTPS_PROXY — Proxy-URLs - CORP_NO_PROXY — 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"
Ihre privaten Registries, Git-Server oder anderen internen Dienste sind nur über ein 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). Erzeugen 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. Erzeugen mit: 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

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

      # Falls VPN Nutzername/Passwort-Authentifizierung 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

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

      # Warten, bis der Tunnel aktiv ist
      for i in $(seq 1 30); do
        if ip link show tun0 >/dev/null 2>&1; then break; fi
        sleep 1
      done
WireGuard:
initialize:
  - name: Install and configure WireGuard
    run: |
      sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq wireguard-tools

      # WireGuard-Konfiguration schreiben
      echo "$WG_CONFIG_B64" | base64 -d \
        | sudo tee /etc/wireguard/wg0.conf > /dev/null
      sudo chmod 600 /etc/wireguard/wg0.conf

      # Tunnel starten
      sudo systemctl enable --now wg-quick@wg0
Weitere Informationen zur VPN-Einrichtung finden Sie unter VPN-Konfiguration.
Ihre internen Dienste verwenden private DNS-Namen, die über öffentliches DNS nicht aufgelöst werden können.
initialize:
  - name: Configure custom DNS resolution
    run: |
      # Interne Hostnamen hinzufügen
      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

      # Optional benutzerdefinierte Nameserver konfigurieren
      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

Identität und Sicherheit

Ihre Organisation verlangt, dass alle Git-Commits signiert sind, und Sie möchten, dass GitHub Devins Commits als Verified kennzeichnet.
  • GPG_PRIVATE_KEY_B64 — Base64-kodierter privater GPG-Schlüssel. Erzeugen mit: gpg --export-secret-keys <key-id> | base64 -w0
  • GIT_USER_NAME — Name des Git-Autors (z. B. Devin AI)
  • GIT_USER_EMAIL — E-Mail-Adresse des Git-Autors. Muss mit einer UID im GPG-Schlüssel übereinstimmen, sonst verifiziert GitHub die Signatur nicht.
Laden Sie außerdem den zugehörigen öffentlichen Schlüssel in das GitHub-Konto hoch, dessen Anmeldedaten Devin zum Pushen verwendet (unter GitHub Settings > SSH and GPG keys). GitHub kennzeichnet Commits nur dann als Verified, wenn der öffentliche Signaturschlüssel für das Konto registriert ist, das den Commit erstellt hat.
initialize:
  - name: Prepare GPG and git signing config
    run: |
      # GPG die Ausführung ohne TTY ermöglichen
      echo 'export GPG_TTY=$(tty)' | sudo tee -a /etc/profile.d/gpg.sh > /dev/null

maintenance:
  - 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
Konfigurieren Sie Devins Git-Identität und SSH-Schlüssel für den Zugriff auf private Git-Server.
  • GIT_USER_NAME — Name des Git-Autors - GIT_USER_EMAIL — E-Mail-Adresse des Git-Autors - SSH_PRIVATE_KEY_B64 — Base64-kodierter privater SSH-Schlüssel. Erzeugen mit: cat ~/.ssh/id_ed25519 | base64 -w0 - SSH_KNOWN_HOSTS_B64 — Base64-kodierte Known-Hosts-Einträge. Erzeugen mit: ssh-keyscan git.corp.internal | base64 -w0 - SSH_CONFIG_B64 (optional) — Base64-kodierte SSH-Konfigurationsdatei
initialize:
  - name: Configure git identity
    run: |
      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

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

      # Known Hosts für Ihren 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.

Systemkonfiguration

Installieren Sie Systempakete, die im Standard-Image von Devin 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
Legen Sie persistente Umgebungsvariablen fest, die in jeder Sitzung verfügbar sein sollen.Es wird empfohlen, 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 bei $GITHUB_ENV in GitHub Actions’).
initialize:
  - name: Benutzerdefinierte Umgebungsvariablen festlegen
    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 unter /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 in den meisten Fällen empfohlen.
Standard-Basis-Images können fehlerhafte Locale-Einstellungen aufweisen. Konfigurieren Sie Locale und Zeitzone, um Warnungen durch 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 festlegen
      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 festlegen
      sudo timedatectl set-timezone UTC 2>/dev/null || \
        sudo ln -sfn /usr/share/zoneinfo/UTC /etc/localtime
Java-, Gradle- und Node.js-Builds stoßen häufig an das Standardlimit 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
In Air-Gap- oder eingeschränkten Umgebungen ersetzen Sie die Standard-Ubuntu-APT-Quellen 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

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

Fortgeschrittene Nutzungsmuster

Devins Basisumgebung enthält direnv. Verwenden Sie initialize, um .envrc-Dateien zu erstellen. Direnv lädt sie automatisch.
initialize: |
  cat <<'EOF' > .envrc
  export DATABASE_URL=postgresql://localhost:5432/myapp_dev
  export REDIS_URL=redis://localhost:6379
  export APP_ENV=development
  EOF

maintenance: |
  direnv allow .
direnv ist in Devins Shell bereits eingebunden, sodass .envrc-Variablen automatisch geladen werden. Ein manuelles Sourcing ist nicht nötig.
Für vertrauliche Umgebungsvariablen (API-Schlüssel, Tokens, Datenbankpasswörter) sollten Sie statt .envrc-Dateien Repo-Secrets verwenden. Repo-Secrets werden sicher gespeichert und beim Start der Sitzung eingebunden. Sie erscheinen niemals in Ihrem Blueprint oder Snapshot.
Verwenden Sie das vorinstallierte nvm, um Node.js-Versionen pro Repository über .nvmrc zu wechseln.
initialize: |
  nvm install 18
  nvm install 20
  nvm install 22

maintenance: |
  nvm use
nvm use liest die .nvmrc aus dem Stammverzeichnis des Repo. Stellen Sie sicher, dass Ihr Repository eine solche Datei enthält (z. B. mit 20 als Inhalt).
Devin stellt während Sitzungen einen Chrome-Browser mit einem CDP-Endpunkt unter localhost:29229 bereit. Verwenden Sie Playwright-Skripte, um browserbasierte Anmeldungen zu automatisieren.
Der Browser ist nur während Sitzungen verfügbar, nicht in Snapshot-Builds. Installieren Sie Playwright in initialize und legen Sie die Anmeldeskripte in Ihrem Repo ab.
initialize: |
  pip install playwright
  playwright install chromium

maintenance: |
  npm install

knowledge:
  - 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
Beispielskript für die Anmeldung (scripts/login.py):
from playwright.sync_api import sync_playwright
import os

with 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")
Speichern Sie Zugangsdaten als Secrets, nicht im Quellcode. Für eine dauerhafte Authentifizierung committen Sie Login-Skripte in .agents/skills/, damit Devin sich automatisch erneut authentifizieren kann.
Installieren Sie Systempakete, benutzerdefinierte Binärdateien und konfigurieren Sie den PATH in initialize.
initialize:
  - name: Install system packages
    run: |
      apt-get update
      apt-get install -y \
        jq \
        ripgrep \
        fd-find \
        protobuf-compiler \
        libssl-dev

  - name: Install custom CLI tool
    run: |
      curl -L https://github.com/example/tool/releases/download/v1.0/tool-linux-amd64 \
        -o /usr/local/bin/mytool
      chmod +x /usr/local/bin/mytool

  - name: Add custom bin directory to PATH
    run: |
      mkdir -p ~/bin
      echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc

knowledge:
  - name: tools
    contents: |
      Custom tools available:
      - mytool: installed at /usr/local/bin/mytool
      - Additional binaries can be placed in ~/bin
Devin unterstützt das direkte Ausführen von Node.js-basierten GitHub Actions in Blueprints. Das ist nützlich, um bestimmte Tool-Versionen über dieselben Actions zu installieren, die auch in Ihrer CI verwendet werden.
initialize:
  - name: "Install Node.js 20"
    uses: github.com/actions/setup-node@v4
    with:
      node-version: "20"

  - name: "Install Python 3.12"
    uses: github.com/actions/setup-python@v5
    with:
      python-version: "3.12"

  - name: "Install Go 1.22"
    uses: github.com/actions/setup-go@v5
    with:
      go-version: "1.22"

  - name: "Install Java 21"
    uses: github.com/actions/setup-java@v4
    with:
      java-version: "21"
      distribution: "temurin"

  - name: "Install Gradle"
    uses: github.com/gradle/actions/setup-gradle@v4

  - name: "Install Ruby 3.3"
    uses: github.com/ruby/setup-ruby@v1
    with:
      ruby-version: "3.3"

  - name: "Install additional tools"
    run: |
      pip install uv
      npm install -g pnpm turbo
      go install golang.org/x/tools/gopls@latest

maintenance: |
  echo "All runtimes are available:"
  node --version
  python --version
  go version
  java --version
Actions wie setup-node und setup-python ändern PATH und Umgebungsvariablen. Von einer Action installierte Binärdateien sind in allen nachfolgenden Schritten und in maintenance verfügbar. Nur Node.js-basierte GitHub Actions werden unterstützt. Composite- und Docker-basierte Actions werden nicht unterstützt.
Für die grundlegende Einrichtung von Tools benötigen Sie keine GitHub Actions. Direkte Shell-Befehle (nvm install 20, curl ... | sh, apt-get install) funktionieren genauso gut und sind oft einfacher. GitHub Actions sind besonders nützlich, wenn Sie Ihr CI-Setup exakt nachbilden möchten oder den Komfort von Actions wie setup-java nutzen wollen, die mehrere Distributionen unterstützen.

Full-Stack-Beispiele

Diese Beispiele zeigen, wie Konfigurationen auf Enterprise- und Org-Ebene zusammenwirken. In der Praxis würden Sie diese auf verschiedene Geltungsbereiche aufteilen. Sie sind hier der Übersicht halber zusammen dargestellt.
Eine vollständige Unternehmensumgebung: Unternehmens-CA-Zertifikat, Proxy, Java (Maven), Python (pip/uv), Node.js (npm) und Docker – alles auf eine einzige Artifactory-Instanz ausgerichtet.
Netzwerk & Vertrauenseinstellungen (kontoweit):
  • CORP_ROOT_CA_B64 — Base64-kodiertes Unternehmens-CA-Zertifikat
  • CORP_HTTP_PROXY — HTTP-Proxy-URL
  • CORP_HTTPS_PROXY — HTTPS-Proxy-URL
  • CORP_NO_PROXY — Hosts, die den Proxy umgehen sollen
Registry-Anmeldedaten (organisationsweit):
  • ARTIFACTORY_USER — Artifactory-Nutzername
  • 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)
Dies würde typischerweise auf drei Geltungsbereiche verteilt:
  • Kontoweit (initialize): Zertifikat und Proxy
  • Organisationsweit (initialize): Installationen von Laufzeitumgebungen für Programmiersprachen
  • Organisationsweit (maintenance): Registry-Zugangsdaten (werden bei jeder Sitzung erneuert)
Hier zur Übersicht zusammengefasst:
initialize:
  # ── Kontoweit: Netzwerk und Vertrauen ────────────────────────────────────

  - 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

  # ── Organisationsweit: Language Runtimes ─────────────────────────────────

  - name: Install JDK 17 + Maven
    run: |
      sudo apt-get update -qq
      sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-17-jdk-headless
      echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' \
        | sudo tee /etc/profile.d/java.sh > /dev/null

      MAVEN_VERSION=3.9.9
      curl -fsSL "https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \
        | sudo tar -xz -C /opt
      sudo ln -sf /opt/apache-maven-${MAVEN_VERSION}/bin/mvn /usr/local/bin/mvn

  - name: Install uv
    run: curl -LsSf https://astral.sh/uv/install.sh | sh

maintenance:
  # ── Kontoweit: Git-Proxy (wird jede Sitzung aktualisiert) ──────────────

  - name: Configure git proxy
    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: Configure Maven → Artifactory
    run: |
      mkdir -p ~/.m2
      cat > ~/.m2/settings.xml << EOF
      <settings>
        <mirrors>
          <mirror>
            <id>artifactory</id>
            <mirrorOf>*</mirrorOf>
            <url>$ARTIFACTORY_MAVEN_URL</url>
          </mirror>
        </mirrors>
        <servers>
          <server>
            <id>artifactory</id>
            <username>$ARTIFACTORY_USER</username>
            <password>$ARTIFACTORY_TOKEN</password>
          </server>
        </servers>
      </settings>
      EOF

  - name: Configure pip/uv → Artifactory PyPI
    run: |
      mkdir -p ~/.config/pip
      cat > ~/.config/pip/pip.conf << EOF
      [global]
      index-url = $ARTIFACTORY_PYPI_URL
      trusted-host = $(echo "$ARTIFACTORY_PYPI_URL" | sed 's|https\?://||;s|/.*||')
      EOF

      echo "export UV_INDEX_URL=$ARTIFACTORY_PYPI_URL" \
        | sudo tee /etc/profile.d/uv-registry.sh > /dev/null

  - name: Configure npm → Artifactory
    run: |
      npm config set registry "$ARTIFACTORY_NPM_URL"
      REGISTRY_HOST=$(echo "$ARTIFACTORY_NPM_URL" | sed 's|https\?://||;s|/.*||')
      npm config set "//${REGISTRY_HOST}/:_authToken" "$ARTIFACTORY_TOKEN"

  - name: Configure Docker → Artifactory
    run: |
      echo "$ARTIFACTORY_TOKEN" | docker login "$ARTIFACTORY_DOCKER_URL" \
        --username "$ARTIFACTORY_USER" \
        --password-stdin
In diesem Beispiel verweisen alle Registries auf dieselbe Artifactory-Instanz, verwenden jedoch unterschiedliche URL-Pfade. Jedes Paket-Ökosystem verwendet ein eigenes Endpunktformat. Maven-, PyPI-, npm- und Docker-URLs unterscheiden sich selbst bei derselben Registry.
Wenn verschiedene Sprachen unterschiedliche 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-Nutzername - NEXUS_PASS — Nexus-Passwort - GITHUB_PACKAGES_TOKEN — GitHub Personal Access Token mit dem Geltungsbereich read:packages - ARTIFACTORY_USER — Artifactory-Nutzername - ARTIFACTORY_TOKEN — Artifactory-API-Token - GIT_TOKEN — Personal Access Token für private Go-Module
maintenance:
  # Maven → Nexus
  - name: Configure Maven → Nexus
    run: |
      mkdir -p ~/.m2
      cat > ~/.m2/settings.xml << EOF
      <settings>
        <mirrors>
          <mirror>
            <id>nexus</id>
            <mirrorOf>*</mirrorOf>
            <url>$NEXUS_MAVEN_URL</url>
          </mirror>
        </mirrors>
        <servers>
          <server>
            <id>nexus</id>
            <username>$NEXUS_USER</username>
            <password>$NEXUS_PASS</password>
          </server>
        </servers>
      </settings>
      EOF

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

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

  # Go → private Module via git
  - name: Configure Go private modules
    run: |
      git config --global url."https://$GIT_TOKEN@github.com/myorg/".insteadOf "https://github.com/myorg/"
In einer vollständig air-gapped Umgebung kann Devin keine öffentlichen URLs erreichen. Alle Tools, Laufzeitumgebungen und Pakete müssen aus internen Mirrorn stammen.
Zertifikate:
  • CORP_ROOT_CA_B64 — Base64-kodiertes Unternehmens-CA-Zertifikat
Mirror-Zugriff:
  • APT_MIRROR_URL — URL des internen Ubuntu-APT-Mirrors
  • MIRROR_USER — Nutzername für die Authentifizierung am Mirror
  • MIRROR_PASS — Passwort für die Authentifizierung am Mirror
  • JDK_TARBALL_URL — URL zum Herunterladen des JDK-Tarballs vom internen Mirror
  • NODE_TARBALL_URL — URL zum Herunterladen des Node.js-Tarballs vom internen Mirror
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, CLI-Tools usw.), auf Ihren internen Mirrors verfügbar sein. Öffentliche Registries und Downloadseiten sind nicht erreichbar.
Ein umfassendes Enterprise-Setup, das VPN-Konnektivität mit Zertifikaten, Proxy und Mehrsprachigkeitsunterstützung kombiniert. Dies ist die empfohlene Vorgehensreihenfolge.
VPN:
  • VPN_CONFIG_B64 — Base64-kodierte OpenVPN-Konfigurationsdatei
Netzwerk & Vertrauenseinstellungen:
  • CORP_ROOT_CA_B64 — Base64-kodiertes Unternehmens-CA-Zertifikat
  • CORP_HTTP_PROXY — HTTP-Proxy-URL
  • CORP_HTTPS_PROXY — HTTPS-Proxy-URL
  • CORP_NO_PROXY — Hosts, die den Proxy umgehen
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-Auth-Token
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 das VPN eingerichtet werden (damit interne Hosts erreichbar sind), dann DNS (damit Namen aufgelöst werden können), dann Zertifikate (damit HTTPS funktioniert), dann der Proxy (damit der Datenverkehr korrekt weitergeleitet wird) und schließlich Laufzeitumgebungen für Programmiersprachen (die möglicherweise aus internen Mirrors herunterladen).

Tipps zum Schreiben guter Blueprints

  • Teste Befehle zuerst in einer Sitzung. Führe Befehle manuell in einer Devin-Sitzung aus, bevor du sie deinem Blueprint hinzufügst. Das geht schneller, als auf einen vollständigen Build-Zyklus zu warten.
  • Verwende initialize für Tools, die nur einmal installiert werden, und maintenance für Abhängigkeiten. Alles, was mehrere Minuten für die Installation braucht (Compiler, große Binärdateien, globale Tools), gehört in initialize. Schnelle Befehle für Abhängigkeiten (npm install, uv sync) gehören in maintenance.
  • Halte maintenance-Befehle schnell. Sie sollten nach Möglichkeit in unter 2 Minuten laufen. Diese Befehle werden zu Beginn jeder Sitzung ausgeführt.
  • Verwende $ENVRC für Umgebungsvariablen. Schreibe nicht in .bashrc oder .profile. $ENVRC ist der unterstützte Mechanismus, um Variablen schritt- und sitzungsübergreifend zu setzen.
  • Gib deinen Schritten Namen. Die erweiterte Form mit name-Feldern macht Fehler in Build-Logs deutlich leichter auffindbar.
  • Verwende Subshells für Monorepos. (cd packages/foo && npm install) läuft in einer Subshell, sodass nachfolgende Schritte nicht von der Verzeichnisänderung betroffen sind.
  • Verwende npm install, nicht npm ci. npm ci löscht node_modules und installiert in jeder Sitzung alles von Grund auf neu, was für maintenance zu langsam ist.
  • Verwende Repo-Secrets für sensible Werte. Konfiguriere sie unter Settings > Secrets im Geltungsbereich des Repos, statt sie fest in Blueprints zu hinterlegen.
Details zur Syntax findest du in der Blueprint-Referenz. Hilfe zur Behebung von Build-Fehlern findest du unter Deklarative Konfiguration > Fehlerbehebung.