mcpField
P
provisioning-with-comtrya

provisioning-with-comtrya

github.com/zenobi-us云与 DevOps6844 次安装今天更新
代码仓库

关于 provisioning-with-comtrya

此技能介绍如何使用 Comtrya 为 macOS、Linux 和 Windows 设计并应用配置清单,涵盖系统差异、依赖顺序和权限控制。它强调在团队推广前先验证、试运行并进行试点。

主要功能

  1. 01按配置职责组织清单
  2. 02指定操作系统和包管理器变体
  3. 03显式声明操作依赖
  4. 04限制权限提升
  5. 05推广前先验证、试运行和试点

适用场景

  1. 01跨操作系统配置开发机器
  2. 02为团队共享点文件和系统设置
  3. 03在团队设备应用前测试配置清单

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/zenobi-us/dotfiles --skill provisioning-with-comtrya

安装后在 Claude Code 中输入/provisioning-with-comtrya确认已加载。

附带文件references/action-reference.md

详细介绍

使用 Comtrya 进行配置

概述

Comtrya 是一款声明式系统配置工具(YAML/TOML),可在 macOS、Linux 和 Windows 上以幂等方式应用配置。核心原则:清单描述期望状态;可重复应用,且不会产生副作用。

关键要点: 配置系统需要分层思考(OS 检测、包管理器、权限级别、依赖顺序、回滚安全性)。

重要: 文件操作(file.link、file.copy、directory.copy)要求源文件位于相对于清单的 files/ 子目录中。这样可以避免 Comtrya 将配置文件解析为清单。

适用场景

  • 设计适用于多种 OS 的配置方案(开发团队、CI/CD、个人设备)
  • 构建能够处理 OS 差异的清单
  • 管理包管理器冲突
  • 同时设置点文件和系统配置
  • 大范围应用前测试更改
  • 安全处理权限提升

多 OS 清单结构

使用变体检测 OS

使用 where 条件来指定特定的 OS、架构或运行时条件:

actions:
  - action: package.install
    name: neovim
    variants:
      - where: os.name == "linux"
        provider: apt
      - where: os.name == "macos"
        provider: brew
      - where: os.name == "windows"
        provider: winget

更简单的方式: 让 comtrya 自动检测默认包管理器(Linux 上为 apt,macOS 上为 brew,Windows 上为 winget):

- action: package.install
  name: git
按职责组织(团队安全)

按职责拆分清单,而非按 OS 拆分:

manifests/
  base.yml          # Cross-platform: git, dotfiles, shell config
  dev-tools.yml     # Dev dependencies with OS variants
  system.yml        # OS-specific: systemd units, defaults, prefs

应用多个清单:

comtrya apply --manifest base.yml --manifest dev-tools.yml

原因: 使用不同 OS 的团队可以共享基础配置,同时覆盖特定工具层。

包管理器安全性

防止冲突

Comtrya 具有幂等性且仅添加内容——package.install 不会卸载或降级软件包。核心行为:

  • 如果软件包已安装:跳过(无操作)
  • 如果同一软件包使用不同的提供方:分别保留
  • 如果使用相同的包管理器:以单个声明为准

团队策略: 记录每种 OS 使用的包管理器:

  • “Linux 团队:仅使用 apt”
  • “macOS 团队:主要使用 brew,GUI 应用使用 homebrew-cask”
  • “例外情况记录在清单注释中”
覆盖默认提供方

团队成员需要使用非标准提供方时(例如,Linux 上使用 nix):

- action: package.install
  name: rust
  provider: nix
  where: user.username == "zenobius"

或者创建团队变体:

- action: package.install
  name: rust
  variants:
    - where: user.username == "zenobius"
      provider: nix
    - provider: apt  # default fallback

依赖排序

Comtrya 不会自动排列操作顺序——请显式声明依赖项:

actions:
  - action: group.add
    group_name: docker
    id: docker_group

  - action: package.install
    name: docker
    depends_on: ["docker_group"]  # Wait for group creation

  - action: command.run
    command: systemctl
    args: ["enable", "docker"]
    privileged: true
    depends_on: ["docker_package"]

重要: 如果没有 depends_on,docker 软件包会在用户组创建之前安装,导致静默失败。

权限提升模式

使用权限提升

对于需要提升权限的操作,请使用 privileged: true:

- action: command.run
  command: systemctl
  args: ["enable", "nginx"]
  privileged: true
  where: os.name == "linux"

或者使用 sudo comtrya apply 运行整个清单。

安全性:尽量减少权限提升

尽可能避免提升权限:

# ❌ Avoid: Privileged command for user config
- action: command.run
  command: tee
  args: ["~/.config/app/config.json"]
  privileged: true

# ✅ Better: User-owned file without privileges
- action: file.copy
  from: app-config.json
  to: ~/.config/app/config.json

应用前:试运行和验证

请勿跳过本节。验证是不可妥协的要求。

在任何团队成员的设备上应用清单之前,必须进行验证。这不是最佳实践,而是硬性要求。跳过验证会导致每位受影响用户需要花费 1–4 小时进行恢复。验证总共需要 15–30 分钟。

强制验证流程(必须按顺序完成):

1. 语法验证(关卡:必须通过)

检查清单语法中是否存在拼写错误和解析错误:

comtrya validate manifest.yml

关卡: 继续之前修复所有错误。如果验证失败,请勿继续。

2. 在测试设备上试运行(关卡:检查输出)

预览所有更改,但不实际应用:

comtrya apply --dry-run --manifest manifest.yml

关卡: 仔细检查输出。如果有任何操作出乎意料(使用了错误的包管理器、路径异常、缺少依赖项),请先排查问题再继续。

3. 让一名团队成员参与试点(关卡:获得批准)

将清单应用到一名志愿团队成员的实际设备上(不是虚拟机):

# Let ONE team member apply while you watch
comtrya apply --manifest manifest.yml

关卡: 确认对方的系统未受影响。扩大部署范围前,必须获得试点用户的明确确认。

4. 部署到团队(仅在通过 Gate 3 后)

试点成功后,部署到团队的其他成员。


为什么不能跳过验证:

  • **仅进行语法验证并不够。**它可以发现拼写错误,却无法发现逻辑错误(例如,操作系统对应的包管理器错误、缺少 depends_on)。
  • **在你的机器上试运行 ≠ 在团队成员的机器上试运行。**每种操作系统、包管理器和用户配置都不一样。
  • **你的配置不具有代表性。**必须先让一位团队成员在其实际环境中进行测试。在部署期间测试 = 一片混乱。
  • **跳过此流程会导致:**清单损坏、软件包安装到错误位置、缺少依赖项、系统状态无法恢复。
  • **跳过验证的代价:**每位受影响的团队成员需要手动恢复 1–4 小时。
  • **验证的代价:**总计 15–30 分钟。

这不是可选事项。请遵循各个关卡。

回滚与恢复(仅限紧急情况)

回滚仅用于紧急情况——成本高且容易出错。通过验证来预防,成本要低得多。

Comtrya 清单描述的是期望状态,而非状态变更。恢复需要:

  1. 手动移除更改或
  2. 编写反向操作(package.remove、file.delete)
  3. 对清单进行版本控制以跟踪更改

紧急回滚示例:

# Only if troubleshooting a broken manifest on live system
# AFTER validation failed: this is a failure mode
actions:
  - action: package.remove
    name: broken-package
  - action: command.run
    cmd: "rm ~/.config/broken-app"

**恢复成本:**每位受影响的用户需要 1–4 小时。

**预防成本:**应用更改前进行验证,耗时 15–30 分钟。

Recover.yml 并不能替代验证——它是灭火器。不要依赖灭火器;火灾发生后再使用,而不是用它来替代预防。

常见模式

符号链接配置文件
# Single file symlink (from files/ directory)
- action: file.link
  from: nvim/init.lua
  to: ~/.config/nvim/init.lua

# Walk directory and symlink all files
- action: file.link
  source: shell-configs
  target: ~/.config/shell
  walk_dir: true
下载并安装二进制文件
- action: file.download
  from: https://example.com/tool.tar.gz
  to: /tmp/tool.tar.gz

- action: file.unarchive
  from: /tmp/tool.tar.gz
  to: /usr/local/bin/

- action: file.remove
  target: /tmp/tool.tar.gz
将 Git 仓库作为配置的一部分
- action: git.clone
  repo_url: "https://github.com/user/dotfiles.git"
  directory: ~/dotfiles

- action: file.link
  from: dotfiles/zshrc
  to: ~/.zshrc
用户和组管理(需要特权)
- action: group.add
  group_name: dev

- action: user.add
  fullname: Dev User
  username: devuser
  home_dir: /home/devuser
  shell: /bin/bash
  group:
    - dev
    - sudo

版本兼容性说明

Comtrya 版本之间可能存在以下差异:

  • 可用操作(较新版本会添加功能)
  • where 子句语法
  • 特权处理方式

**最佳实践:**在 CI/CD 或团队文档中固定 comtrya 版本:

COMTRYA_VERSION=0.3.0
curl -fsSL https://get.comtrya.dev | INSTALL_VERSION=$COMTRYA_VERSION sh

快速参考:操作(v0.9.2)

文件与目录操作
操作必需可选说明
file.copyfrom、totemplate、chmod、owned_by_user/group从 files/ 目录复制文件
file.linkfrom、towalk_dir、source、target为 files/ 目录中的文件创建符号链接
file.downloadfrom/source、to/targetowned_by_user/group从 URL 下载
file.removetarget-移除文件
file.chownpath、user、group-更改所有权
file.unarchivefrom、toforce解压 tar.gz
directory.copyfrom、to-从 files/ 目录复制目录

重要:file.link、file.copy、directory.copy 要求源文件位于 files/ 子目录中。

软件包操作
操作必需可选说明
package.installname 或 listprovider、repository、file安装软件包
package.repositoryname(url)key、provider添加软件包仓库

提供程序:apt、brew、pacman、yay、paru、pkg、pkgin、winget、xbps、zypper、macports、dnf、snapcraft

其他操作
操作必需可选说明
command.run(或 cmd.run)commandargs、dir、privileged、env执行命令
git.clonerepo_url、directory-克隆仓库(v0.9.1+)
user.addfullname、home_dir、usernameshell、group创建用户
user.groupusername、group-将用户添加到组
group.addgroup_name-创建组
binary.githubname、directory、repository、version-下载 GitHub 二进制文件
macos.defaultdomain、key、kind、value-设置 macOS 默认值
上下文变量
变量示例描述
{{ user.home_dir }}/home/zenobius主目录
{{ user.config_dir }}/home/zenobius/.config配置目录
{{ user.username }}zenobius用户名
{{ os.name }}linux, macos, windows操作系统名称

常见错误(危险信号)

❌ 禁止:未满足以下条件就应用于任何团队机器:

  • 语法验证通过
  • 已在你的测试机器上完成并审核试运行
  • 一名志愿团队成员已先行成功试用

后果: 每位受影响用户需要 1–4 小时恢复。跳过这些步骤就会发生。

✅ 必须: 语法检查通过 → 试运行通过 → 一人试用通过 → 推广至团队。总耗时:15–30 分钟。结果:系统无故障。


❌ 混用包管理器而不记录: 会造成隐性冲突或效率低下。

✅ 解决方法: 在清单注释中按操作系统记录团队策略。


❌ 未试运行就应用于生产环境: 会破坏现有配置。

✅ 解决方法: 始终先运行 --dry-run,在一台机器上测试,然后再推广。


❌ 假定自定义命令具有幂等性: 某些脚本无法安全重复执行。

✅ 解决方法: 为非幂等命令添加保护措施(检查是否已执行)。


❌ 不加限制地提升权限: 过度使用 sudo 会带来安全风险。

✅ 解决方法: 尽量减少 sudo;改用 file.create 创建用户配置。

实际效果

应用此模式后的结果:

  • 多操作系统团队的配置时间:2 小时 → 20 分钟(经过验证的清单)
  • 因缺少依赖项导致的隐性故障:每次推广 7 次 → 0 次(明确使用 depends_on)
  • 包管理器冲突:每月 3 次 → 0 次(记录策略)
  • 从故障清单中恢复:手动清理 → 脚本化回滚

评论

支持 Markdown