管理声明性代理的环境和版本

随着声明性代理的成熟,需要将其部署到多个环境(开发、过渡和生产),并最终运行并行版本,以便在不中断现有用户的情况下试用新功能。 为每个环境和版本组合维护一组单独的清单文件不会缩放。

Microsoft 365 代理工具包同时满足要求、目标环境和代理版本,其机制相同:环境文件。 通过为每个部署目标定义一个 .env.* 文件并在 ${{VAR_NAME}} 清单、声明性代理文件和 中使用占位符, m365agents.yml可以使用单个命令预配任何环境或版本,atk provision --env <target>而无需复制单个文件。

两个轴,一个系统

声明性代理的环境管理有两个维度:

  • 目标环境:部署到不同租户或应用注册的相同代理-开发、过渡、生产或特定于客户的租户。
  • 代理版本:并行运行的同一代理的多个变体,例如,v1 稳定版、v2 预览版或实验分支。

这两个维度的处理方式相同。 为每个部署目标定义一个环境文件,以及 ${{VAR_NAME}} 清单中的占位符、声明性代理文件,并在 m365agents.yml 预配时解析。

模型目标环境

大多数团队至少部署到两个环境(开发和生产),并且许多团队在它们之间添加了过渡环境。 在 env/ 文件夹中为每个环境创建一个文件:

env/
├── .env.dev
├── .env.dev.user
├── .env.staging
├── .env.staging.user
├── .env.prod
└── .env.prod.user

每个文件使用特定于环境的值定义相同的变量名称:

# env/.env.staging
TEAMS_APP_ID=33333333-3333-3333-3333-333333333333
AAD_CLIENT_ID=44444444-4444-4444-4444-444444444444
API_BASE_URL=https://api-staging.contoso.com
SHAREPOINT_SITE_URL=https://contoso.sharepoint.com/sites/hr-staging
AGENT_DISPLAY_NAME=HR Onboarding Buddy (Staging)
TEAMSFX_ENV=staging

提示

在非生产租户的代理显示名称中包括环境名称。 例如,“HR Onboarding Buddy (Staging) ”可让测试人员立即清楚他们使用的是哪个版本,这有助于避免在报告问题时出现混淆。

若要面向不同的环境,请将 标志 --env 传递给每个 Agents Toolkit 命令:

atk provision --env staging
atk deploy --env staging
atk publish --env staging

为多个版本建模

代理版本遵循与目标环境相同的模式。 每个版本都是具有其自己的环境文件的部署目标。 若要在同一生产租户中部署版本 2 (v2) 代理以及版本 1 (v1) 代理,请添加环境 prod-v2

env/
├── .env.dev
├── .env.staging
├── .env.prod          # v1, the stable one
├── .env.prod-v2       # v2, running side by side
└── ...corresponding .user files

提供 .env.prod-v2 唯一的 Teams 应用 ID,以便两个代理可以共存于同一租户中:

# env/.env.prod-v2
TEAMS_APP_ID=55555555-5555-5555-5555-555555555555
AAD_CLIENT_ID=22222222-2222-2222-2222-222222222222
API_BASE_URL=https://api.contoso.com
SHAREPOINT_SITE_URL=https://contoso.sharepoint.com/sites/hr
AGENT_DISPLAY_NAME=HR Onboarding Buddy (Preview)
AGENT_VERSION=2.0.0
TEAMSFX_ENV=prod-v2

将清单中的变量用于不同版本之间的任何值:

{
  "$schema": "https://developer.microsoft.com/json-schemas/teams/v1.24/MicrosoftTeams.schema.json",
  "manifestVersion": "1.24",
  "id": "${{TEAMS_APP_ID}}",
  "version": "${{AGENT_VERSION}}",
  "name": {
    "short": "${{AGENT_DISPLAY_NAME}}",
    "full": "${{AGENT_DISPLAY_NAME}} - Contoso"
  },
  "developer": {
    "name": "Contoso",
    "websiteUrl": "${{API_BASE_URL}}"
  },
  "copilotAgents": {
    "declarativeAgents": [
      {
        "id": "declarativeAgent",
        "file": "declarativeAgent.json"
      }
    ]
  }
}

结果是一个清单文件,该文件在同一租户中生成两个不同的可安装应用。 收到预览版安装的用户请参阅 v2;所有其他用户都保留在 v1 上。

注意

Teams 应用 ID 是此模式的关键。 平台将具有不同 ID 的应用视为单独的安装,无论它们共享多少代码。 这种分离还允许对代理角色进行 A/B 测试,而不会影响生产用户。

对代理定义本身进行分支

当版本差异超出了变量值 (例如,不同的指令、新功能或一组不同的插件) 时,可以使用两个选项来分支代理定义本身。

选项 A:保留单个 declarativeAgent.json 值,并将变量用于不同的值。 当差异很小(例如不同的说明段落或不同的 SharePoint 网站 URL)时,此方法非常有效。

选项 B:为每个版本维护单独的声明性代理文件,并通过 Teams 应用清单中的变量引用该文件:

{
  "copilotAgents": {
    "declarativeAgents": [
      {
        "id": "declarativeAgent",
        "file": "declarativeAgent.${{AGENT_VARIANT}}.json"
      }
    ]
  }
}

在 中 m365agents.yml,将包步骤配置为包含在 ${{TEAMSFX_ENV}} 输出项目名称中,以便每个环境生成不同的 zip 文件:

provision:
  - uses: teamsApp/zipAppPackage
    with:
      manifestPath: ./appPackage/manifest.json
      outputZipPath: ./appPackage/build/appPackage.${{TEAMSFX_ENV}}.zip
      outputFolder: ./appPackage/build

当 时 AGENT_VARIANT=v1,生成解析为 declarativeAgent.v1.json。 当 时 AGENT_VARIANT=v2,它会解析为 declarativeAgent.v2.json。 这两个文件都存储在存储库中,并像任何其他源文件一样在拉取请求中查看,不需要任何功能标志。

由于输出 zip 路径包含 ${{TEAMSFX_ENV}},因此每个环境都会生成一个唯一命名的项目。 例如, appPackage.prod.zipappPackage.prod-v2.zip 是独立写入的 ./appPackage/build/ ,并且永远不会相互覆盖。

使用 CI/CD 自动执行部署

若要跨所有环境缩放此模式,请在 GitHub Actions 或 Azure DevOps 中使用矩阵从单个工作流预配每个环境:

strategy:
  matrix:
    include:
      - target: dev
        secret_name: AAD_SECRET_DEV
      - target: staging
        secret_name: AAD_SECRET_STAGING
      - target: prod
        secret_name: AAD_SECRET_PROD
      - target: prod-v2
        secret_name: AAD_SECRET_PROD_V2
steps:
  - uses: actions/checkout@v4
  - run: npm install -g @microsoft/m365agentstoolkit-cli
  - run: atk provision --env ${{ matrix.target }}
    env:
      SECRET_AAD_CLIENT_SECRET: ${{ secrets[matrix.secret_name] }}
  - run: atk deploy --env ${{ matrix.target }}

每个矩阵作业加载正确的 .env.* 文件,并从显式映射的 GitHub 机密中检索其机密。 需要显式映射,因为 GitHub 机密名称仅允许使用大写字母、数字和下划线 (例如,目标名称(如) prod-v2 不能直接用作) 的机密名称。 使用此配置,将从过渡到生产的更改提升成为工作流触发器,而不是手动步骤。

警告

不要在 中 .env.prod存储生产机密。 用于 .env.prod.user 本地开发和用于管道运行的 CI/CD 机密存储。 .user确保文件已.gitignore由 排除,并且从不提交。 CI/CD 管道应在运行时注入 SECRET_* 变量。

命名约定

对环境文件使用以下命名约定。

模式 说明
.env.<target> 租户或阶段:开发、过渡、生产
.env.<target>-<variant> 目标中的版本或分支:prod-v2、prod-experimental
.env.<target>.user 该目标的机密,从未提交
.env.local 在预配) 期间自动生成的项目根 (代理工具包配置

此约定使 env/ 文件夹成为自记录。 任何团队成员都可以确定存在哪些环境以及每个环境的目标。

此方法的好处

从每个环境一个清单迁移到包含多个环境文件的一个存储库会更改团队的工作方式:

  • 无需重复代码的并行版本:将 v1 和 v2 部署到同一生产租户,以便进行实际用户试点,而无需分支代码库。
  • 单命令升级:传递 --env prod 是完整的升级步骤。 无需文件编辑或手动合并步骤。
  • 跨环境一致的 CI/CD:单个工作流以相同的步骤处理每个环境,从而消除开发和生产之间的配置偏差。
  • 简化的载入:新团队成员可以通过填写 .env.dev.user开始。 无需更改清单。
  • 可审核部署:每个环境都有一个事实来源文件。 比较 和 prod-v2 之间的prod更改是两个文件的差异。

此方法将目标环境和代理版本视为部署目标,在整个过程中使用相同的工具和约定。