本页提供了一些可独立使用的 environment.yaml 示例,适用于常见场景。每个示例都涵盖一个配置点——将它们组合起来即可构建完整配置。
如需了解 environment.yaml 语法和相关概念,请参阅环境配置 。如需语法细节,请参阅 YAML 参考 。
Secrets: 示例通过 $SECRET_NAME 引用 secrets。请先在设置 → Secrets 中配置这些 secrets,再使用示例。每个示例都包含一个可折叠的 “必需的 secrets” 部分,明确列出需要设置哪些 secrets 以及它们应填写的值。切勿在你的 environment.yaml 中硬编码凭据。
将最常用的配置汇总在一处。完整列表请参见下方各节。
initialize : |
npm install -g pnpm
maintenance : |
pnpm install
knowledge :
- name : lint
contents : |
运行 `pnpm lint` 检查错误。
- name : test
contents : |
运行 `pnpm test` 执行完整测试套件。
initialize :
- name : Install uv
run : curl -LsSf https://astral.sh/uv/install.sh | sh
maintenance :
- name : 同步依赖
run : uv sync
knowledge :
- name : lint
contents : |
运行 `uv run ruff check .` 执行 lint 检查。
- name : test
contents : |
运行 `uv run pytest` 执行完整测试套件。
initialize :
- name : 安装 pnpm
run : npm install -g pnpm
- name : Install uv
run : curl -LsSf https://astral.sh/uv/install.sh | sh
maintenance :
- name : 前端依赖
run : (cd frontend && pnpm install)
- name : 后端依赖
run : (cd backend && uv sync)
knowledge :
- name : structure
contents : |
- `frontend/` — React 应用(pnpm)
- `backend/` — Python API(uv)
- name : test
contents : |
前端:cd frontend && pnpm test
后端:cd backend && uv run pytest
initialize : |
npm install -g pnpm
maintenance : |
pnpm install
knowledge :
- name : structure
contents : |
使用 pnpm workspaces 管理的 Monorepo。
- `packages/web` — Next.js 前端
- `packages/api` — Express.js 后端
- `packages/shared` — 共享工具
- name : test
contents : |
在根目录运行 `pnpm test`,测试所有软件包。
运行 `pnpm --filter web test` 可测试特定软件包。
环境配置按层应用。每一层都建立在前一层之上:
账户级(Enterprise)
证书、代理、DNS、VPN、提交签名、区域设置、资源限制、Git 身份、APT 镜像源。
适用于所有组织 和所有仓库 。
组织级
语言运行时、包管理器注册表配置、容器注册表、共享工具。
适用于组织内的所有仓库 。
仓库级
构建命令、依赖安装、测试/lint 命令、针对 Devin 的项目专属说明。
适用于单个仓库 。
账户级最先运行,然后是组织级,最后是仓库级。请在Settings 中按相应作用域配置每个示例。
使用下表,根据你的需求找到合适的示例。各模块彼此独立,可自由组合。
这些示例用于配置适用于所有组织和仓库的机器级基础设施。在 Enterprise Settings (用于账户级) 或 Settings > Environment > Organization-wide setup (用于组织级) 中进行设置。
你的组织为内部服务使用私有证书颁发机构。Devin 需要根证书,才能通过 HTTPS 访问内部注册表和工具。
CORP_ROOT_CA_B64 — 来自企业 CA 的 base64 编码 PEM 证书。生成方式: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
# 让 Node.js 信任企业 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
有些组织会为不同的内部服务使用不同的 CA (例如,一个用于制品仓库,另一个用于内部 Git 服务器) 。
CA_CERT_REGISTRY_B64 — 制品仓库 CA 的 Base64 编码 PEM 证书
CA_CERT_GIT_B64 — Git 服务器 CA 的 Base64 编码 PEM 证书
initialize :
- name : 安装企业 CA 证书
run : |
# 解码并安装每个证书
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:将证书合并为单个包
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
你的组织通过企业代理转发出站流量。
CORP_HTTP_PROXY — HTTP 代理 URL (例如:http://proxy.corp.internal:8080)
CORP_HTTPS_PROXY — HTTPS 代理 URL (例如:http://proxy.corp.internal:8080)
CORP_NO_PROXY — 以逗号分隔的主机列表,用于指定应绕过代理的主机 (例如: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"
将 CORP_NO_PROXY 设置为以逗号分隔的主机列表,用于指定应绕过代理的主机,例如 localhost,127.0.0.1,.corp.internal,10.0.0.0/8。
如果你的代理需要用户名和密码,请将凭据嵌入代理 URL 中。
PROXY_USER — 代理身份验证用户名
PROXY_PASS — 代理身份验证密码
PROXY_HOST — 代理主机名 (例如 proxy.corp.internal)
PROXY_PORT — 代理端口 (例如 8080)
CORP_NO_PROXY — 用逗号分隔的无需通过代理的主机
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 证书并配置全系统代理。
CORP_ROOT_CA_B64 — 来自你的企业 CA 的 Base64 编码 PEM 证书
CORP_HTTP_PROXY — HTTP 代理 URL
CORP_HTTPS_PROXY — HTTPS 代理 URL
CORP_NO_PROXY — 以逗号分隔的主机列表,这些主机将绕过代理
initialize :
- name : Install corporate CA certificate
run : |
echo "$CORP_ROOT_CA_B64" | base64 -d \
| sudo tee /usr/local/share/ca-certificates/corp-root-ca.crt > /dev/null
sudo update-ca-certificates
echo 'export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/corp-root-ca.crt' \
| sudo tee /etc/profile.d/node-ca.sh > /dev/null
- name : Configure system-wide proxy
run : |
cat << 'PROXY' | sudo tee /etc/profile.d/proxy.sh > /dev/null
export http_proxy="$CORP_HTTP_PROXY"
export https_proxy="$CORP_HTTPS_PROXY"
export no_proxy="$CORP_NO_PROXY"
export HTTP_PROXY="$CORP_HTTP_PROXY"
export HTTPS_PROXY="$CORP_HTTPS_PROXY"
export NO_PROXY="$CORP_NO_PROXY"
PROXY
source /etc/profile.d/proxy.sh
maintenance :
- name : Configure git proxy
run : |
git config --global http.proxy "$CORP_HTTP_PROXY"
git config --global https.proxy "$CORP_HTTPS_PROXY"
你的私有注册表、Git 服务器或其他内部服务只能通过 VPN 访问。必须先运行此模块,然后再运行其他需要访问内部资源网络的模块。
OpenVPN:
VPN_CONFIG_B64 — Base64 编码的 OpenVPN 配置文件 (.ovpn) 。生成命令:cat corp.ovpn | base64 -w0
VPN_AUTH_USER (可选) — VPN 用户名 (如果你的 VPN 需要用户名/密码身份验证)
VPN_AUTH_PASS (可选) — VPN 密码
WireGuard:
WG_CONFIG_B64 — Base64 编码的 WireGuard 配置文件。生成命令:cat wg0.conf | base64 -w0
initialize :
- name : 安装并配置 OpenVPN
run : |
sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openvpn
# 写入 VPN 配置
sudo mkdir -p /etc/openvpn/client
echo "$VPN_CONFIG_B64" | base64 -d \
| sudo tee /etc/openvpn/client/corp.conf > /dev/null
# 如果 VPN 需要用户名/密码身份验证
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 隧道
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
initialize :
- name : 安装并配置 WireGuard
run : |
sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq wireguard-tools
# 写入 WireGuard 配置
echo "$WG_CONFIG_B64" | base64 -d \
| sudo tee /etc/wireguard/wg0.conf > /dev/null
sudo chmod 600 /etc/wireguard/wg0.conf
# 启动隧道
sudo systemctl enable --now wg-quick@wg0
你的内部服务使用私有 DNS 名称,而这些名称无法通过公共 DNS 解析。
initialize :
- name : Configure custom DNS resolution
run : |
# 添加内部主机名
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
# 可选:配置自定义名称服务器
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
你的组织要求所有 Git 提交均已签名。
GPG_PRIVATE_KEY_B64 — Base64 编码的 GPG 私钥。生成方式:gpg --export-secret-keys <key-id> | base64 -w0
initialize :
- name : Prepare GPG and git signing config
run : |
# 允许 GPG 在没有 TTY 的情况下工作
echo 'export GPG_TTY=$(tty)' | sudo tee -a /etc/profile.d/gpg.sh > /dev/null
# 预配置 git 以签署提交(密钥在 maintenance 中导入)
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
# 设置签名密钥 ID
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 用户身份信息和 SSH 密钥,以便通过 SSH 访问私有仓库。
GIT_USER_NAME — Git 提交作者名称 (例如:Devin AI)
GIT_USER_EMAIL — Git 提交作者邮箱 (例如:devin@company.com)
SSH_PRIVATE_KEY_B64 — Base64 编码的 SSH 私钥。使用以下命令生成:cat ~/.ssh/id_ed25519 | base64 -w0
SSH_KNOWN_HOSTS_B64 — Base64 编码的 known hosts 内容。使用以下命令生成:ssh-keyscan git.corp.internal | base64 -w0
SSH_CONFIG_B64 (可选) — 用于自定义主机别名的 Base64 编码 SSH 配置文件
initialize :
- name : Prepare SSH directory and git identity
run : |
# 设置 git 身份信息
git config --global user.name "$GIT_USER_NAME"
git config --global user.email "$GIT_USER_EMAIL"
# 准备 SSH 目录
mkdir -p ~/.ssh && chmod 700 ~/.ssh
# 如需启用 git-lfs
# git lfs install
maintenance :
- name : Install SSH keys
run : |
# 安装 SSH 私钥(置于 maintenance 中,以便每次会话时重新加载)
echo "$SSH_PRIVATE_KEY_B64" | base64 -d > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
# 为你的 Git 服务器添加已知主机
echo "$SSH_KNOWN_HOSTS_B64" | base64 -d >> ~/.ssh/known_hosts
# 可选:安装自定义 SSH 配置文件
if [ -n "${SSH_CONFIG_B64:-}" ]; then
echo "$SSH_CONFIG_B64" | base64 -d > ~/.ssh/config
chmod 600 ~/.ssh/config
fi
使用 ssh-keyscan git.corp.internal | base64 -w0 为你的 Git 服务器生成 known_hosts 条目。
你的项目需要默认 Devin 镜像中不包含的系统级软件包 (例如,用于图像处理或生成 PDF 的原生库) 。
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
设置在每个会话中都可用的持久环境变量。
推荐的方法是将 KEY=VALUE 行写入 $ENVRC 文件。写入 $ENVRC 的变量会自动导出,并在后续所有步骤以及 Devin 会话中可用 (类似于 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
你也可以将环境变量写入 /etc/profile.d/ 下的脚本中,以便在系统范围内生效: cat << 'ENVVARS' | sudo tee /etc/profile.d/custom-env.sh > /dev/null
export CORPORATE_ENV=production
export DEFAULT_REGION=us-east-1
ENVVARS
这两种方法都可以。$ENVRC 更简单,且在大多数情况下更推荐使用。
默认基础镜像的区域设置可能配置不正确。请配置区域设置和时区,以避免构建工具、Java、Python 和 Git 发出警告。
initialize :
- name : Configure locale and timezone
run : |
sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq locales
# 生成并设置语言环境
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
# 设置时区
sudo timedatectl set-timezone UTC 2>/dev/null || \
sudo ln -sfn /usr/share/zoneinfo/UTC /etc/localtime
Java、Gradle 和 Node.js 构建经常会触及默认的 1024 个打开文件数限制。请提高该限制,以避免构建失败。
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
# 同时设置内核最大值
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
在隔离网络或受限环境中,使用内部 mirror 替换默认的 Ubuntu APT 软件源。
APT_MIRROR_URL — 你的内部 APT mirror 的 URL (例如:https://artifactory.example.com/artifactory/ubuntu-remote)
initialize :
- name : Replace APT sources with internal mirror
run : |
# 备份原始源
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
# 将所有 Ubuntu 镜像替换为内部镜像
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 mv /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/disabled/ 2>/dev/null || true
sudo apt-get update -qq
常见的 APT 镜像 URL 格式:
Artifactory: https://artifactory.example.com/artifactory/ubuntu-remote
Nexus: https://nexus.example.com/repository/ubuntu-proxy
这些示例会安装语言运行时,并将包管理器配置为使用私有注册表。请在 Settings > Environment > Organization-wide setup 中进行设置。
如果你的私有注册表使用企业 CA,请先确保已在 Enterprise 级别安装 CA 证书 。以下组织级配置默认已建立 HTTPS 信任。
凭据配置应放在 maintenance 中,而不是 initialize 中。 将 secrets (注册表密码、身份验证令牌) 写入配置文件的步骤应使用 maintenance,这样凭据才会在每次会话时重新加载。在保存机器镜像之前,secrets 文件会被移除,因此在 initialize 期间写入的配置文件在会话开始时将不包含有效凭据。
安装 JDK,并配置 Maven,使所有依赖解析都通过你的私有制品库进行 (例如 Artifactory、Nexus) 。
JDK 17 已预装 在 Devin 的基础镜像中。如果默认的 OpenJDK 17 已足够,则跳过下面的安装步骤——你只需安装 Maven 并配置仓库。
MAVEN_REGISTRY_URL — 你的 Maven 仓库的 URL (例如 https://artifactory.example.com/artifactory/maven-virtual)
REGISTRY_USER — 仓库用户名
REGISTRY_PASS — 仓库密码或 API 令牌
initialize :
- name : Install JDK 17
run : |
sudo apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-17-jdk-headless
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' \
| sudo tee /etc/profile.d/java.sh > /dev/null
- name : Install Maven
run : |
MAVEN_VERSION=3.9.9
curl -fsSL "https://archive.apache.org/dist/maven/maven-3/${MAVEN_VERSION}/binaries/apache-maven-${MAVEN_VERSION}-bin.tar.gz" \
| sudo tar -xz -C /opt
sudo ln -sf /opt/apache-maven-${MAVEN_VERSION}/bin/mvn /usr/local/bin/mvn
maintenance :
- name : Configure Maven for private registry
run : |
mkdir -p ~/.m2
cat > ~/.m2/settings.xml << EOF
<settings>
<mirrors>
<mirror>
<id>private-registry</id>
<mirrorOf>*</mirrorOf>
<url>$MAVEN_REGISTRY_URL</url>
</mirror>
</mirrors>
<servers>
<server>
<id>private-registry</id>
<username>$REGISTRY_USER</username>
<password>$REGISTRY_PASS</password>
</server>
</servers>
</settings>
EOF
Maven 常见仓库 URL 格式:
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>
安装 JDK,并配置 Gradle 通过你的私有仓库解析所有依赖项。
JDK 17 已预装 在 Devin 的基础镜像中。如果默认配置已足够,可以跳过 JDK 安装步骤。
GRADLE_REGISTRY_URL — 你的 Gradle/Maven 仓库 URL
REGISTRY_USER — 仓库用户名
REGISTRY_PASS — 仓库密码或 API 令牌
initialize :
- name : Install JDK 17
run : |
sudo apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-17-jdk-headless
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' \
| sudo tee /etc/profile.d/java.sh > /dev/null
- name : Install Gradle
run : |
GRADLE_VERSION=8.12
curl -fsSL "https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip" \
-o /tmp/gradle.zip
sudo unzip -qo /tmp/gradle.zip -d /opt
sudo ln -sf /opt/gradle-${GRADLE_VERSION}/bin/gradle /usr/local/bin/gradle
rm /tmp/gradle.zip
maintenance :
- name : Configure Gradle for private registry
run : |
mkdir -p ~/.gradle
cat > ~/.gradle/init.gradle << EOF
allprojects {
repositories {
maven {
url "$GRADLE_REGISTRY_URL"
credentials {
username = "$REGISTRY_USER"
password = "$REGISTRY_PASS"
}
allowInsecureProtocol = false
}
}
}
EOF
配置 pip 和 uv,使其从你的私有 PyPI 仓库 (例如 Nexus、Artifactory) 获取软件包。
PYPI_REGISTRY_HOST — 你的 PyPI 仓库的主机名 (例如 artifactory.example.com/artifactory/api/pypi/pypi-virtual)
REGISTRY_USER — 仓库用户名
REGISTRY_PASS — 仓库密码或 API 令牌
initialize :
- name : Install uv
run : curl -LsSf https://astral.sh/uv/install.sh | sh
maintenance :
- name : Configure pip for private registry
run : |
mkdir -p ~/.config/pip
cat > ~/.config/pip/pip.conf << EOF
[global]
index-url = https://$REGISTRY_USER:$REGISTRY_PASS@${PYPI_REGISTRY_HOST}/simple
trusted-host = ${PYPI_REGISTRY_HOST}
EOF
- name : Configure uv for private registry
run : |
# uv 会遵循 pip.conf,但你也可以显式设置
echo "export UV_INDEX_URL=https://$REGISTRY_USER:$REGISTRY_PASS@${PYPI_REGISTRY_HOST}/simple" \
| sudo tee /etc/profile.d/uv-registry.sh > /dev/null
PyPI 常见的软件包仓库 URL 模式:
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
将 Poetry 配置为从私有 PyPI 注册表解析软件包。
PYPI_REGISTRY_HOST — 你的 PyPI 注册表主机名
REGISTRY_USER — 注册表用户名
REGISTRY_PASS — 注册表密码或 API 令牌
initialize :
- name : Install Poetry
run : curl -sSL https://install.python-poetry.org | python3 -
maintenance :
- name : Configure Poetry for private registry
run : |
poetry config repositories.private "https://${PYPI_REGISTRY_HOST}/simple"
poetry config http-basic.private "$REGISTRY_USER" "$REGISTRY_PASS"
# 可选:将私有注册表设置为默认源
# poetry source add --priority=primary private "https://${PYPI_REGISTRY_HOST}/simple"
通过带作用域的私有注册表使用 Node.js + npm
配置 npm,使其从 GitHub Packages 等私有注册表中解析带作用域的软件包 (例如 @myorg/*) ,同时公共软件包仍然来自默认的 npm 注册表。
GITHUB_PACKAGES_TOKEN — 具有 read:packages 作用域的 Personal Access Token 或 GitHub App 令牌
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
将 @myorg 替换为你的 npm 作用域。常见的私有 registry URL:
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 配合完整私有注册表镜像
让所有 npm 软件包都通过你的私有注册表 (而不只是作用域软件包) 。
NPM_REGISTRY_URL — 你的 npm 注册表的完整 URL (例如:https://artifactory.example.com/artifactory/api/npm/npm-virtual)
NPM_REGISTRY_HOST — 仅主机名,不包含协议 (例如:artifactory.example.com)
REGISTRY_TOKEN — 该注册表的 npm 身份验证令牌
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
将 pnpm 配置为从私有注册表解析软件包。
pnpm 已在 Devin 的基础镜像中预装 。你可以跳过安装步骤,只配置注册表即可。
NPM_REGISTRY_URL — 你的 npm 注册表完整 URL
NPM_REGISTRY_HOST — 仅主机名,不含协议
REGISTRY_TOKEN — 该注册表的 npm 身份验证令牌
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
配置 Yarn (Classic v1 或 Berry v2+) ,使其从私有注册表解析软件包。
Yarn Classic (v1) 已预装 在 Devin 的基础镜像中。如果你只需要 v1,请跳过安装步骤。
NPM_REGISTRY_URL — 你的 npm/Yarn 注册表的完整 URL
REGISTRY_TOKEN — 注册表的身份验证令牌 (仅 Berry 需要)
Yarn Classic (v1)
Yarn Berry (v2+)
initialize :
- name : Install Yarn Classic
run : npm install -g yarn
maintenance :
- name : Configure Yarn for private registry
run : |
yarn config set registry "$NPM_REGISTRY_URL"
# 对于带作用域的软件包:
# yarn config set @myorg:registry "https://npm.pkg.github.com"
maintenance :
- name : Configure Yarn Berry for private registry
run : |
yarn config set npmRegistryServer "$NPM_REGISTRY_URL"
yarn config set npmAuthToken "$REGISTRY_TOKEN"
# 对于带作用域的软件包:
# yarn config set npmScopes.myorg.npmRegistryServer "https://npm.pkg.github.com"
# yarn config set npmScopes.myorg.npmAuthToken "$GITHUB_PACKAGES_TOKEN"
安装 Go 并将其配置为通过私有模块代理 (例如 Athens、Artifactory 或 GOPROXY 端点) 解析模块。
GO_PROXY_URL — 你的 Go 模块代理的 URL (例如 https://athens.corp.internal)
GIT_TOKEN — 用于访问托管 Go 模块的私有 Git 仓库的 Personal access token
initialize :
- name : 安装 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 : 为私有模块配置 Go
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 : 验证 Go 私有模块身份
run : |
git config --global url."https://$GIT_TOKEN@github.com/myorg/".insteadOf "https://github.com/myorg/"
常见的 Go 代理 URL 格式:
Artifactory: https://artifactory.example.com/artifactory/go-virtual
Nexus: https://nexus.example.com/repository/go-proxy
Athens: https://athens.corp.internal
安装 .NET SDK,并配置 NuGet,使其从私有源 (例如 Azure Artifacts、Artifactory) 解析软件包。
NUGET_FEED_URL — 你的 NuGet 源 URL (例如 https://pkgs.dev.azure.com/org/project/_packaging/feed/nuget/v3/index.json)
REGISTRY_USER — Registry 用户名
REGISTRY_PASS — Registry 密码或 API 令牌
initialize :
- name : Install .NET SDK
run : |
curl -fsSL https://dot.net/v1/dotnet-install.sh -o /tmp/dotnet-install.sh
chmod +x /tmp/dotnet-install.sh
sudo /tmp/dotnet-install.sh --channel 8.0 --install-dir /usr/local/dotnet
echo 'export DOTNET_ROOT=/usr/local/dotnet' \
| sudo tee /etc/profile.d/dotnet.sh > /dev/null
echo 'export PATH="$DOTNET_ROOT:$DOTNET_ROOT/tools:$PATH"' \
| sudo tee -a /etc/profile.d/dotnet.sh > /dev/null
rm /tmp/dotnet-install.sh
maintenance :
- name : Configure NuGet for private feed
run : |
dotnet nuget add source "$NUGET_FEED_URL" \
--name private-feed \
--username "$REGISTRY_USER" \
--password "$REGISTRY_PASS" \
--store-password-in-clear-text
# 可选:禁用默认的 nuget.org 源
# dotnet nuget disable source nuget.org
常见的 NuGet 源 URL:
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,使其能够向私有容器镜像仓库进行身份验证。
DOCKER_MIRROR_URL (可选) — 你的 Docker Hub 镜像 URL (例如,https://mirror.corp.internal)
DOCKER_REGISTRY_URL — 你的私有容器注册表 URL (例如,registry.corp.internal:5000)
DOCKER_REGISTRY_USER — 注册表用户名
DOCKER_REGISTRY_PASS — 注册表密码或 API 令牌
initialize :
- name : Create Docker config directory
run : sudo mkdir -p /etc/docker
maintenance :
- name : Configure Docker for private registry
run : |
# 配置镜像仓库镜像(可选 — 通过你的镜像仓库转发 Docker Hub 拉取请求)
cat << EOF | sudo tee /etc/docker/daemon.json > /dev/null
{
"registry-mirrors": ["$DOCKER_MIRROR_URL"]
}
EOF
sudo systemctl restart docker || true
# 登录私有容器镜像仓库
echo "$DOCKER_REGISTRY_PASS" | docker login "$DOCKER_REGISTRY_URL" \
--username "$DOCKER_REGISTRY_USER" \
--password-stdin
常见的容器注册表 URL:
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,使其从私有注册表解析 crate。
Rust (通过 rustup) 和 Cargo 已预装 在 Devin 的基础镜像中。如果默认的稳定工具链已足够,请跳过安装步骤——你只需要配置注册表。
CARGO_REGISTRY_INDEX — 私有注册表索引的 URL (例如:sparse+https://cargo.corp.internal/api/v1/crates/)
CARGO_REGISTRY_TOKEN — 用于私有注册表的身份验证令牌
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
如果你只需要添加 私有注册表,而不替换 crates.io,请移除 [source.crates-io] 和 [source.private] 部分,并使用 cargo install --registry private,或者在 Cargo.toml 中使用 [dependencies] my-crate = { version = "1.0", registry = "private" }。
Ruby + Bundler 使用私有 gem 服务器
安装 Ruby 并配置 Bundler,使其从私有 gem 服务器解析 gem 依赖。
GEM_SERVER_URL — 你的私有 gem 服务器的 URL (例如,https://artifactory.example.com/artifactory/api/gems/gems-virtual)
REGISTRY_USER — Registry 用户名
REGISTRY_PASS — Registry 密码或 API 令牌
initialize :
- name : Install Ruby
run : |
sudo apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ruby-full
maintenance :
- name : Configure Bundler for private gem server
run : |
bundle config set mirror.https://rubygems.org "$GEM_SERVER_URL"
bundle config set "$GEM_SERVER_URL" "$REGISTRY_USER:$REGISTRY_PASS"
常见的 gem 服务器 URL 格式:
Artifactory: https://artifactory.example.com/artifactory/api/gems/gems-virtual
Nexus: https://nexus.example.com/repository/rubygems-proxy
Gemfury: https://gem.fury.io/<org>
AWS CodeArtifact 令牌会在 12 小时后过期。使用 maintenance 在每次会话开始时刷新令牌。此示例会将 npm、pip 和 Maven 配置为使用 CodeArtifact。
awscli 已预装 在 Devin 的基础镜像中。你只需要配置令牌刷新和 registry。
AWS_ACCESS_KEY_ID 和 AWS_SECRET_ACCESS_KEY — 具有 codeartifact:GetAuthorizationToken 和 sts:GetServiceBearerToken 权限的 IAM 凭据
CA_DOMAIN — 你的 CodeArtifact 域名
CA_DOMAIN_OWNER — 拥有该域的 AWS 账户 ID
CA_REGION — AWS 区域 (例如 us-east-1)
CA_NPM_REPO, CA_PYPI_REPO, CA_MAVEN_REPO — 各生态的代码仓库名称
maintenance :
- name : Refresh CodeArtifact auth token
run : |
# 获取新令牌(有效期 12 小时)
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
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
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(可选)
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 使用私有 registry
安装 PHP,并配置 Composer,使其从私有 Packagist 或 Satis registry 解析软件包。
COMPOSER_REGISTRY_URL — 你的私有 Composer registry 的 URL (例如:https://repo.packagist.com/<org>)
REGISTRY_USER — registry 用户名
REGISTRY_PASS — registry 密码或 API 令牌
initialize :
- name : Install PHP and Composer
run : |
sudo apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \
php-cli php-mbstring php-xml php-curl unzip
# 安装 Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
maintenance :
- name : Configure Composer for private registry
run : |
composer config --global repositories.private \
composer "$COMPOSER_REGISTRY_URL"
# 向 registry 进行身份验证
composer config --global http-basic.$(echo "$COMPOSER_REGISTRY_URL" \
| sed 's|https\?://||;s|/.*||') "$REGISTRY_USER" "$REGISTRY_PASS"
# 可选:禁用默认的 packagist.org
# composer config --global repositories.packagist false
常见 Composer registry URL 模式:
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
这些示例用于配置各个仓库的构建步骤、依赖管理和 Knowledge 条目。你可以在 Settings > Environment > [your repo] 中进行设置。
一个典型的 Node.js 项目,带有 lint、test 和 build 命令。
initialize : |
npm install -g pnpm
maintenance : |
pnpm install
knowledge :
- name : lint
contents : |
Run `pnpm lint` to check for errors.
Run `pnpm lint --fix` to auto-fix.
- name : test
contents : |
Run `pnpm test` for the full test suite.
Run `pnpm test -- --watch` during development.
- name : build
contents : |
Run `pnpm build` to create a production build.
Output goes to the `dist/` directory.
一个使用 uv 管理依赖项的 Python 项目。
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.
使用 Maven 进行依赖管理的 Java 项目。
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.
使用标准工具链的 Go 项目。
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.
使用 Cargo 的 Rust 项目。
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。
initialize :
- name : Install pnpm
run : npm install -g pnpm
- name : Install uv
run : curl -LsSf https://astral.sh/uv/install.sh | sh
maintenance :
- name : Install frontend dependencies
run : (cd packages/frontend && pnpm install)
- name : Install backend dependencies
run : (cd packages/backend && uv sync)
- name : Build shared library
run : (cd packages/shared && pnpm install && pnpm build)
knowledge :
- name : structure
contents : |
This is a monorepo with three packages:
- `packages/frontend` — React app (TypeScript, pnpm)
- `packages/backend` — Python API (FastAPI, uv)
- `packages/shared` — Shared TypeScript utilities (must be built before frontend)
- name : frontend
contents : |
Run `cd packages/frontend && pnpm dev` to start the dev server.
Run `cd packages/frontend && pnpm lint` to lint.
Run `cd packages/frontend && pnpm test` to test.
- name : backend
contents : |
Run `cd packages/backend && uv run uvicorn app.main:app --reload` to start the API.
Run `cd packages/backend && uv run ruff check .` to lint.
Run `cd packages/backend && uv run pytest` to test.
使用子 Shell (cd dir && command),而不要使用 cd dir && command,这样每个步骤之间都会重置工作目录。
在一个 Java monorepo 中,不同服务需要不同的 JDK 版本。先在设置时安装这两个 JDK,然后使用 Knowledge 条目告诉 Devin 每个服务应使用哪个 JAVA_HOME。
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 钩子,请在 maintenance 中安装它们,以便在每次会话中都能直接使用。
initialize :
- name : Install pre-commit
run : pip install pre-commit
maintenance :
- name : Install pre-commit hooks
run : pre-commit install --install-hooks
如果项目已将 pre-commit 设为开发依赖 (例如在 pyproject.toml 中) ,请跳过 initialize 步骤,改为在 maintenance 中运行 uv run pre-commit install --install-hooks 或 pipx run pre-commit install --install-hooks。
在 knowledge 条目中记录你项目的架构、约定和工作流程。
knowledge :
- name : architecture
contents : |
This is a microservices application:
- `api-gateway/` — Express.js reverse proxy (port 3000)
- `auth-service/` — JWT authentication service (port 3001)
- `user-service/` — User CRUD service (port 3002)
- `shared/` — Shared protobuf definitions and utilities
Services communicate via gRPC. The API gateway is the only public-facing service.
- name : conventions
contents : |
- All API responses use the `{ data, error, meta }` envelope format
- Database migrations are in `migrations/` and run with `npm run migrate`
- Environment-specific config is in `config/{env}.json`
- Feature flags are managed via LaunchDarkly (SDK key in $LD_SDK_KEY)
- name : testing
contents : |
Unit tests: `npm test`
Integration tests: `npm run test:integration` (requires Docker for Postgres)
E2E tests: `npm run test:e2e` (requires all services running)
Coverage report: `npm run test:coverage` (must be > 80% for CI to pass)
- name : deployment
contents : |
CI/CD runs on GitHub Actions. Merges to `main` auto-deploy to staging.
Production deploys require a manual approval step in the Actions UI.
Docker images are pushed to ECR: 123456789.dkr.ecr.us-east-1.amazonaws.com/
这些示例展示了企业级和组织级配置如何组合。实际使用中,你通常会将这些内容拆分到不同的作用域中——此处将它们一并展示,以供参考。
一个完整的企业环境:企业 CA 证书、代理、Java (Maven) 、Python (pip/uv) 、Node.js (npm) 和 Docker——均指向同一个 Artifactory 实例。
网络与信任 (账户级) :
CORP_ROOT_CA_B64 — Base64 编码的企业 CA 证书
CORP_HTTP_PROXY — HTTP 代理 URL
CORP_HTTPS_PROXY — HTTPS 代理 URL
CORP_NO_PROXY — 不经过代理的主机
注册表凭据 (组织级) :
ARTIFACTORY_USER — Artifactory 用户名
ARTIFACTORY_TOKEN — Artifactory API 令牌或密码
ARTIFACTORY_MAVEN_URL — Maven 仓库 URL (例如:https://artifactory.example.com/artifactory/maven-virtual)
ARTIFACTORY_PYPI_URL — PyPI 仓库 URL (例如:https://user:token@artifactory.example.com/artifactory/api/pypi/pypi-virtual/simple)
ARTIFACTORY_NPM_URL — npm 仓库 URL (例如:https://artifactory.example.com/artifactory/api/npm/npm-virtual)
ARTIFACTORY_DOCKER_URL — Docker registry URL (例如:artifactory.example.com)
这通常会拆分为三个作用域:
账户级 (initialize) : 证书和代理
组织级 (initialize) : 语言运行时的安装
组织级 (maintenance) : 注册表凭据 (每次会话都会刷新)
此处将它们合并展示,供参考:
initialize :
# ── 账户范围:网络与信任 ──────────────────────────────────────
- name : 安装企业 CA 证书
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 : 配置系统级代理
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
# ── 组织范围:语言运行时 ──────────────────────────────────────────
- name : 安装 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 : 安装 uv
run : curl -LsSf https://astral.sh/uv/install.sh | sh
maintenance :
# ── 账户范围:git 代理(每次会话刷新)───────────────────
- name : 配置 git 代理
run : |
git config --global http.proxy "$CORP_HTTP_PROXY"
git config --global https.proxy "$CORP_HTTPS_PROXY"
# ── 组织范围:镜像仓库凭据(每次会话刷新)──────────────
- name : 配置 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 : 配置 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 : 配置 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 : 配置 Docker → Artifactory
run : |
echo "$ARTIFACTORY_TOKEN" | docker login "$ARTIFACTORY_DOCKER_URL" \
--username "$ARTIFACTORY_USER" \
--password-stdin
在此示例中,所有注册表都指向同一个 Artifactory 实例,但使用不同的 URL 路径。每种包生态系统都有各自的端点格式——即使是同一个注册表,Maven、PyPI、npm 和 Docker 的 URL 也都不同。
当不同语言使用不同的私有注册表时 (例如:Maven 使用 Nexus,npm 使用 GitHub Packages,Python 使用 Artifactory) 。
NEXUS_MAVEN_URL — Nexus Maven 仓库 URL
NEXUS_USER — Nexus 用户名
NEXUS_PASS — Nexus 密码
GITHUB_PACKAGES_TOKEN — 具有 read:packages 作用域的 GitHub 个人访问令牌
ARTIFACTORY_USER — Artifactory 用户名
ARTIFACTORY_TOKEN — Artifactory API 令牌
GIT_TOKEN — 用于 Go 私有模块的个人访问令牌
maintenance :
# Maven → Nexus
- name : 配置 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(作用域限定)
- name : 配置 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 : 配置 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 → 通过 git 使用私有模块
- name : 配置 Go 私有模块
run : |
git config --global url."https://$GIT_TOKEN@github.com/myorg/".insteadOf "https://github.com/myorg/"
在完全气隙的环境中,Devin 无法访问任何公共 URL。所有工具、运行时和软件包都必须来自内部镜像。
证书:
CORP_ROOT_CA_B64 — Base64 编码的企业 CA 证书
镜像访问:
APT_MIRROR_URL — 内部 Ubuntu APT 镜像 URL
MIRROR_USER — 镜像身份验证用户名
MIRROR_PASS — 镜像身份验证密码
JDK_TARBALL_URL — 从内部镜像下载 JDK tarball 的 URL
NODE_TARBALL_URL — 从内部镜像下载 Node.js tarball 的 URL
软件包注册表:
INTERNAL_MAVEN_URL — 内部 Maven 注册表 URL
INTERNAL_NPM_URL — 内部 npm 注册表 URL
INTERNAL_PYPI_URL — 内部 PyPI 注册表 URL
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 压缩包
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
在物理隔离环境中,Devin 所需的所有工具 (语言运行时、CLI 工具等) 都必须可通过你的内部镜像源获取。公共注册表和下载站点无法访问。
一个全面的企业级配置,将 VPN 连接与证书、代理和多语言支持结合起来。这是推荐的操作顺序。
VPN:
VPN_CONFIG_B64 — Base64 编码的 OpenVPN 配置文件
Network & trust:
CORP_ROOT_CA_B64 — Base64 编码的企业 CA 证书
CORP_HTTP_PROXY — HTTP 代理 URL
CORP_HTTPS_PROXY — HTTPS 代理 URL
CORP_NO_PROXY — 绕过代理的主机
注册表凭据:
MAVEN_REGISTRY_URL — Maven 注册表 URL
NPM_REGISTRY_URL — npm 注册表 URL
PYPI_REGISTRY_HOST — PyPI 注册表主机名
REGISTRY_USER — 注册表用户名 (用于 Maven 和 pip)
REGISTRY_PASS — 注册表密码 (用于 Maven 和 pip)
REGISTRY_TOKEN — npm 身份验证令牌
initialize :
# 1. VPN — 必须首先执行,以确保内部资源可访问
- 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 — 解析内部主机名
- 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. 证书 — 信任内部 CA
- 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. 代理 — 通过企业代理路由流量
- name : Configure proxy
run : |
cat << 'PROXY' | sudo tee /etc/profile.d/proxy.sh > /dev/null
export http_proxy="$CORP_HTTP_PROXY"
export https_proxy="$CORP_HTTPS_PROXY"
export no_proxy="$CORP_NO_PROXY"
export HTTP_PROXY="$CORP_HTTP_PROXY"
export HTTPS_PROXY="$CORP_HTTPS_PROXY"
export NO_PROXY="$CORP_NO_PROXY"
PROXY
source /etc/profile.d/proxy.sh
# 5. language runtimes
- name : Install JDK 17
run : |
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq openjdk-17-jdk-headless
echo 'export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64' \
| sudo tee /etc/profile.d/java.sh > /dev/null
- name : Install Node.js tooling
run : npm install -g pnpm
- name : Install uv
run : curl -LsSf https://astral.sh/uv/install.sh | 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
initialize 步骤的顺序很重要。 必须先配置 VPN (这样才能访问内部主机) ,然后是 DNS (这样名称才能解析) ,接着是证书 (这样 HTTPS 才能正常工作) ,然后是代理 (这样流量才能正确路由) ,最后是语言运行时 (它们可能需要从内部镜像源下载) 。
先在会话中测试命令 — 在将命令添加到配置之前,先在 Devin 会话中手动运行。这比等待完整的构建周期更快。
一次性安装的工具用 initialize,依赖项用 maintenance — 任何安装需要几分钟的内容 (编译器、大型二进制文件、全局工具) 都应放在 initialize 中。快速的依赖命令 (npm install、uv sync) 应放在 maintenance 中。
保持 maintenance 命令执行迅速 — 尽量控制在 2 分钟以内。这些命令会在每次会话开始时运行。
使用 $ENVRC 管理环境变量 — 不要写入 .bashrc 或 .profile。$ENVRC 是在各个步骤和会话之间设置变量的受支持方式。
为步骤命名 — 使用带有 name 字段的展开形式后,构建日志中的失败会更容易定位。
在 monorepo 中使用子 Shell — (cd packages/foo && npm install) 会在子 Shell 中运行,因此后续步骤不会受到目录切换的影响。
有关语法和执行细节的更多信息,请参阅 YAML 参考 。有关构建失败的故障排查,请参阅 故障排查与常见问题 。