> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 场景：ACME Corp 的成长路径

> 了解蓝图配置如何从单个代码仓库，演进到具有共享依赖的多代码仓库应用，再发展为多组织企业。

蓝图分为三个层级——代码仓库、组织和企业——最常见的问题是：*这应该放在哪一层？*

本页将通过一家虚构公司 **ACME Corp** 的三个成长阶段来回答这个问题。每个阶段都只会引入一个新问题，而这个问题都会由上一个层级来解决。请直接跳转到最符合你公司情况的阶段。

| 阶段                                                                       | ACME 的情况                     | 他们配置的内容              |
| ------------------------------------------------------------------------ | ---------------------------- | -------------------- |
| [1. 一个代码仓库](#stage-1-one-repository)                                     | 单个 Rails 应用，一个团队             | 一个代码仓库蓝图             |
| [2. 多个代码仓库，共享依赖](#stage-2-several-repositories-with-shared-dependencies) | 五个代码仓库、一个共享的开发 CLI，以及相互依赖的服务 | 一个组织蓝图，加上每个代码仓库各一个蓝图 |
| [3. 多个组织](#stage-3-multiple-organizations-the-enterprise-blueprint)      | 多个团队，每个团队都有自己的组织，另外还有一个安全团队  | 一个企业蓝图，加上各组织蓝图       |

<Info>
  先给出一个经验法则：**代码仓库蓝图用于安装项目依赖，组织蓝图用于安装多个代码仓库共享的内容，而企业蓝图用于安装每个组织都必须具备的内容。** 各层级采用叠加方式，并按自上而下的顺序运行：企业 → 组织 → 克隆代码仓库 → 代码仓库。
</Info>

***

<div id="stage-1-one-repository">
  ## 第 1 阶段：一个代码仓库
</div>

ACME 有一个产品：`acme-web`，这是一个使用 Postgres 和 Redis 的 Rails 应用程序。两个工程师，共用一个代码仓库。此时还没有任何需要共享的内容，所以**所有内容都放在代码仓库蓝图中**。

他们在 **设置 > 环境 > 蓝图 > 添加** 中添加这个代码仓库，打开其编辑器，并编写：

```yaml acme-web (repository blueprint) theme={null}
initialize:
  - name: Install Ruby 3.3
    uses: github.com/ruby/setup-ruby@v1
    with:
      ruby-version: "3.3"

  - name: Install Postgres and Redis
    run: |
      sudo apt-get update -qq
      sudo apt-get install -y postgresql redis-server libpq-dev
      sudo systemctl enable --now postgresql redis-server
      sudo -u postgres createuser -s "$USER"

maintenance:
  - name: Install gems and prepare the database
    run: |
      bundle install
      bin/rails db:prepare

knowledge:
  - name: lint
    contents: bundle exec rubocop
  - name: test
    contents: bundle exec rspec
  - name: startup
    contents: bin/rails server -p 3000
```

这就是全部配置。保存后会触发一次构建，此后每个会话启动时都会自动安装好 Ruby、启动 Postgres、装好 gems，并完成数据库迁移。

**为什么还不使用组织蓝图？** 只服务于一个代码仓库的组织蓝图只是徒增一层间接。等到第二个代码仓库也需要同样配置时再使用。

<Tip>
  ACME 不是手动编写这些内容的。他们只需让 Devin *"为这个代码仓库设置你的环境"*，审查建议卡片，然后点击 **批准**。请参阅[快速开始](/zh/onboard-devin/environment/blueprints#getting-started)。
</Tip>

***

<div id="stage-2-several-repositories-with-shared-dependencies">
  ## 第 2 阶段：多个共享依赖的代码仓库
</div>

两年后，ACME 有五个代码仓库：

| 代码仓库            | 说明                                                                                                            |
| --------------- | ------------------------------------------------------------------------------------------------------------- |
| `acme-devtools` | 一个 CLI (`acme`) ，用于启动容器、串联各项服务，并提供本地主机名 (`acme.local`、`portal.acme.local`) 。它还负责内部文档搜索 (`acme docs:search`) 。 |
| `acme-web`      | 主应用程序。大多数功能都在这里开发。                                                                                            |
| `acme-portal`   | 面向客户的门户。它会调用 `acme-web`。                                                                                      |
| `acme-sso`      | 身份验证服务。两个应用程序都依赖它。                                                                                            |
| `acme-events`   | 事件消费者。                                                                                                        |

这是一个很有代表性的场景，因为这些代码仓库**并不是彼此独立的**：如果没有安装 `acme-devtools`，且 `acme-sso` 没有运行，那么在 `acme-portal` 里就无法开展任何有意义的工作。这就引出了两个问题。

<div id="one-blueprint-per-application-or-just-one-for-the-development-cli">
  ### “每个应用程序一个蓝图，还是只为开发 CLI 配一个蓝图？”
</div>

**两者都需要——用途不同。** Devin 会构建**一个快照**，其中包含**所有**已配置的代码仓库，所以这不是非此即彼的选择：

* 将**全部五个代码仓库**添加到环境中，这样它们都会被克隆到快照中。
* 将**跨代码仓库共享的 setup**统一放在**组织蓝图**中：语言运行时环境、Docker、本地主机名，以及内部 registry 的凭据。
* 为每个代码仓库分别提供自己的**代码仓库蓝图**，用于管理各自的依赖，以及各自的 `knowledge` 条目 (lint、test 和 startup 命令) 。

下面说明为什么你不应该把所有内容都塞进 `acme-devtools` 蓝图：代码仓库蓝图会在所有代码仓库都克隆完成后运行，但其中的步骤会**在对应代码仓库的目录中**执行，而且其中的 `knowledge` 条目只有在 Devin 处理该代码仓库时才会加载。如果由 `acme-devtools` 安装所有内容，那么在 `acme-portal` 中工作的会话将看不到任何 portal 的 lint 和 test 命令；而且只要 `acme-devtools` 的某个步骤失败，其他四个代码仓库表面上看起来正常，实际上却无法使用。

<div id="the-organization-blueprint">
  ### 组织蓝图
</div>

```yaml Organization-wide setup theme={null}
initialize:
  - name: Install Ruby 3.3
    uses: github.com/ruby/setup-ruby@v1
    with:
      ruby-version: "3.3"

  - name: Install Node.js 20
    uses: github.com/actions/setup-node@v4
    with:
      node-version: "20"

  - name: Install Docker and Compose
    run: |
      curl -fsSL https://get.docker.com | sh
      sudo usermod -aG docker "$USER"

  - name: Local hostnames for the development CLI
    run: |
      for host in acme.local portal.acme.local sso.acme.local; do
        grep -q " $host$" /etc/hosts \
          || echo "127.0.0.1 $host" | sudo tee -a /etc/hosts > /dev/null
      done

maintenance:
  - name: Authenticate to the internal registry
    run: |
      bundle config set --global https://gems.acme.internal "$ACME_REGISTRY_TOKEN"
      npm config set //npm.acme.internal/:_authToken "$ACME_REGISTRY_TOKEN"

post-build:
  - name: Verify the stack comes up
    run: |
      acme up --detach
      acme status
      acme down
```

有三点需要注意：

1. **`initialize` 与 `maintenance`。** Docker、运行时和主机名属于一次性的系统设置，因此应放在 `initialize` 中。注册表凭据应在每次定期构建时刷新，因此应放在 `maintenance` 中。

   这里特意没有包含 `acme` CLI 本身。它位于 `acme-devtools` 中，而组织级步骤会在**任何代码仓库被克隆之前**运行，因此它需要通过该代码仓库自己的蓝图来安装 (如下所示) 。该安装会在构建期间执行，并保留到快照中，这样其他所有代码仓库之后都可以使用它。
2. **`post-build` 是多代码仓库设置的核心价值所在。** 它会在*每个*代码仓库都完成克隆和设置后运行，因此只有在这里，你才能验证整个技术栈能否一起正常启动。非零退出码会导致构建失败，因此你会在构建阶段就发现损坏的技术栈，而不是在会话进行到一半时才发现。参见 [`post-build`](/zh/onboard-devin/environment/blueprint-reference#post-build)。
3. \*\*secrets 应归属于组织，\*\*而不是每个代码仓库。组织蓝图的 **Secrets** 选项卡中的一个 `ACME_REGISTRY_TOKEN` 就可以供每个代码仓库的 `bundle install` 和 `npm install` 使用。

<Warning>
  **顺序陷阱：**组织级 `initialize` 和 `maintenance` 都会在代码仓库被克隆**之前**运行 (参见[构建顺序](/zh/onboard-devin/environment/blueprints#how-builds-work)) 。任何需要已检出源代码的内容——例如位于你的某个代码仓库*内部*的 CLI——都必须放在该代码仓库自己的蓝图中，或放在 `post-build` 中，而不能放在组织级 `maintenance` 中。只有当你可以从已发布的制品 (例如 tarball、package 或 container image) 安装它时，才应将其保留在组织这一层级。
</Warning>

<div id="the-repository-blueprints">
  ### 代码仓库蓝图
</div>

每个代码仓库蓝图都很精简，因为所有共享内容都已现成可用：

```yaml acme-devtools (repository blueprint) theme={null}
initialize: |
  ./bin/install            # 将 `acme` 添加到整个快照的 PATH 中

maintenance: |
  acme docs:index          # 每次构建时刷新内部文档索引

knowledge:
  - name: cli
    contents: |
      `acme` manages every local service. Common commands:
        acme up <service>     start a service and its dependencies
        acme status           list running services
        acme docs:search <q>  search internal ACME engineering documentation
      Prefer `acme docs:search` over guessing at conventions.
```

```yaml acme-portal (repository blueprint) theme={null}
maintenance: |
  npm install

knowledge:
  - name: lint
    contents: npm run lint
  - name: test
    contents: npm test
  - name: startup
    contents: |
      The portal needs SSO running first:
        acme up sso
        acme up portal
      Then visit https://portal.acme.local
```

`acme-web`、`acme-sso` 和 `acme-events` 的结构相同：各自都有一个用于安装自身依赖的 `maintenance` 步骤，以及针对各自 lint、测试和启动命令的 `knowledge` 条目。

<Tip>
  **将 `acme-devtools` 排在代码仓库列表第一位**。代码仓库蓝图会按 Settings 中显示的顺序运行，因此，提供共享 CLI 的代码仓库应先于调用它的代码仓库完成设置。
</Tip>

<Info>
  **Knowledge 按代码仓库隔离。** 配置了五个代码仓库后，在 `acme-portal` 中工作的会话只能看到该 portal 的 Knowledge 条目，以及组织和企业级 Knowledge——看不到 `acme-web` 的条目。因此，每个代码仓库都应有自己的蓝图，即使它的 `maintenance` 部分只有一行。
</Info>

<Tip>
  由于 `acme` CLI 已经知道如何运行所有内容，这些蓝图中最有价值的部分是 **`knowledge`** 部分：它会告诉 Devin 该调用哪个 CLI 命令。如果你们有内部文档搜索，也可以将它指向那里。
</Tip>

<div id="if-your-services-live-in-a-monorepo-instead">
  ### 如果你的服务位于 monorepo 中
</div>

思路是一样的，只是下沉一个层级：使用 [工作区](/zh/onboard-devin/environment/workspaces)，在单个代码仓库内为每个包提供各自作用域内的设置和 Knowledge，而不是为每个代码仓库分别使用一个蓝图。

***

<div id="stage-3-multiple-organizations-the-enterprise-blueprint">
  ## 第 3 阶段：多个组织——企业蓝图
</div>

ACME 现在有 400 名工程师。Platform、Payments 和 Data 各自都有自己的 Devin **组织**，拥有各自独立的代码仓库、成员和快照。安全团队提出了一些适用于所有组织的要求：

* 所有流量都必须通过企业代理，并使用内部证书颁发机构。
* 所有软件包都必须来自 Artifactory，绝不能来自公共仓库。
* 每个环境都必须安装公司的依赖项扫描和密钥扫描工具。
* 全公司统一使用 Python 3.12 和 Node.js 20，没有任何例外。

这些内容都不应该放在组织蓝图里，因为那样就必须**复制到每个组织**，而且只要有一个团队忘记更新，就会立刻出现偏差。这正是**企业蓝图**的作用：它作为基础环境，在整个企业中每个组织的构建里最先运行。

```yaml Devin's base environment (enterprise blueprint) theme={null}
initialize:
  - name: Corporate certificate authority and proxy
    run: |
      sudo cp "$FILE_ACME_CA_CERT" /usr/local/share/ca-certificates/acme-ca.crt
      sudo update-ca-certificates
      cat <<'EOF' >> ~/.bashrc
      export HTTPS_PROXY=http://proxy.acme.internal:8080
      export NO_PROXY=localhost,127.0.0.1,.acme.internal
      export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/acme-ca.crt
      export REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
      EOF

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

  - name: Security tooling
    run: |
      pip install bandit safety
      curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh

maintenance:
  - name: Point every package manager at Artifactory
    run: |
      pip config set global.index-url \
        "https://devin:$ARTIFACTORY_TOKEN@artifactory.acme.internal/api/pypi/pypi/simple/"
      npm config set registry https://artifactory.acme.internal/api/npm/npm/
      npm config set //artifactory.acme.internal/api/npm/npm/:_authToken "$ARTIFACTORY_TOKEN"

knowledge:
  - name: security-policy
    contents: |
      All dependencies must resolve through artifactory.acme.internal.
      Never add a public registry to a lockfile or a CI configuration.
```

`ARTIFACTORY_TOKEN` 是一个**企业级 secret**，只需在 **设置 > Devin 的基础环境 > Secrets** 中定义一次，即可在所有组织的每次 build 和每个 session 中使用。该证书是一个文件附件，会以 `$FILE_ACME_CA_CERT` 的形式提供给 build。

<div id="what-each-tier-owns-now">
  ### 现在各层级分别负责什么
</div>

| Tier           | Owner    | ACME example                                               |
| -------------- | -------- | ---------------------------------------------------------- |
| **Enterprise** | 安全和平台管理员 | 证书颁发机构、代理、Artifactory、Python 3.12、扫描器、一个共享令牌               |
| **组织**         | 各团队的管理员  | Payments：Docker、`acme` CLI，以及团队主机名。Data：Spark 和 JDK 17。    |
| **代码仓库**       | 代码仓库负责人  | `bundle install`、`npm install`，以及 lint、测试和启动相关 `knowledge` |

第 2 阶段中的 Payments 组织蓝图会继续工作，**完全无需更改**。只是因为企业层级已经完成了这些工作，它不再需要安装 Python 或配置软件包仓库。Data 组织蓝图会安装 Spark 和 JDK，而 Payments 根本不会看到这些。代码仓库蓝图保持不变。

<div id="operating-it">
  ### 如何运作
</div>

* **将 Python 从 3.12 升级到 3.13** 只需改动一行，再进行一次[企业范围重建](/zh/enterprise/environment-management/overview#enterprise-wide-rebuilds)，变更就会级联到所有组织。
* **当某个团队需要不同的凭据时**——例如，Data 组织有自己的 Artifactory 域——该团队只需定义一个同名的组织 secret，即可**覆盖**企业 secret。
* **若要在各组织中逐步 rollout 此变更**，请参阅[迁移你的企业](/zh/enterprise/environment-management/rollout)。

***

<div id="deciding-where-something-goes">
  ## 决定某项内容该放在哪里
</div>

按顺序往下看。第一个回答“是”的，就是答案：

<Steps>
  <Step title="公司里的每个组织都需要它吗？">
    → **企业蓝图。** 证书、代理、内部注册表、指定的运行时、安全工具，以及公司范围内的 secrets。
  </Step>

  <Step title="这个组织里有两个或更多代码仓库需要它吗？">
    → **组织蓝图。** Docker、共享的开发 CLI、本地主机名、跨代码仓库的服务编排，以及注册表凭据。在 `post-build` 中验证组装好的整套环境。
  </Step>

  <Step title="是否只有这个代码仓库需要它？">
    → **代码仓库蓝图。** 依赖安装、迁移，以及与其 lint、test 和启动命令相关的 `knowledge` 条目。
  </Step>

  <Step title="它是事实信息，而不是要运行的命令吗？">
    → **`knowledge`**，放在它适用的层级。它永远不会被执行；它会被加载到 Devin 上下文中。
  </Step>
</Steps>

这样可以避免的常见错误：

* **把所有内容都放到某一个代码仓库的蓝图里。** 其他代码仓库就拿不到 knowledge 条目，而且只要有一个步骤出问题，整个设置看起来都会不健康。
* **在每个代码仓库里重复配置共享工具。** 如果两个代码仓库安装了同一个全局工具的不同版本，最后运行的那个会覆盖前面的。应改为把这个工具放到组织蓝图中。
* **跳过跨代码仓库验证。** 如果你的代码仓库只有配合起来才能正常工作，那么 `post-build` 是唯一能在会话开始前 (而不是进行中) 证明这一点的地方。

<div id="related-pages">
  ## 相关页面
</div>

* [声明式配置](/zh/onboard-devin/environment/blueprints) — 构建顺序、快照和故障排查
* [蓝图参考](/zh/onboard-devin/environment/blueprint-reference) — 所有字段说明，包括 `post-build` 和 `clone`
* [模板库](/zh/onboard-devin/environment/templates) — 可按语言和注册表直接复制使用的蓝图
* [工作区和 monorepo](/zh/onboard-devin/environment/workspaces) — monorepo 场景下对应第 2 阶段的内容
* [企业环境概览](/zh/enterprise/environment-management/overview) — 第 3 阶段的完整详解
