galaxio-labs Operator Ecosystem
核心流程
gops mod创建模块维护器,用 GXL 编写维护器的 workflowgops sys创建系统维护器,组合多个模块维护器,用 GXL 编写 workflow- 系统维护器保存到配置管理库中,待发布到客户环境
- 在客户环境中,使用
gops prj创建维护工程,并加载系统维护器 - 在客户环境中,使用
gx执行维护器的 workflow - 保存维护工程到配置管理库中
GXL 文档的来源
gxl/ 下的页面大部分是 galaxy-flow 仓库 docs/gxl/ 的镜像,
单一真源在 galaxy-flow,请不要在这里直接改这些页面(改动会在下次同步时被覆盖)。
例外:gxl/example/*.md 是本仓库自有的运维向改写(补充“对应目录 / 运行方式 / 这个示例验证了什么”等),
不属于镜像,不会被同步覆盖。
同步与校验:
# 在 galaxy-flow 仓库执行同步(默认写入 ../operator-docs/src/gxl)
scripts/sync-gxl-docs.sh sync --dest <operator-docs>/src/gxl
# 只校验是否已同步
scripts/sync-gxl-docs.sh check --dest <operator-docs>/src/gxl
本仓库的 GXL docs sync check workflow 会每天定时、以及在 push / PR 时
用 galaxy-flow main 的 docs/gxl/ 校验上述镜像是否已同步。
新增镜像页面后,记得同时把条目加进 SUMMARY.md,否则该页不会出现在侧边栏。
目录约定
站点源(mdBook 的 src)在 src/,book.toml 留在仓库根:这样 .git/、.github/ 落在站点源之外,
不会被 mdBook 当作站点资源拷进 book/ 产物。theme/ 按 mdBook 约定放在 book.toml 同级。
上线前提:该 workflow 调用的是 galaxy-flow 仓库里的
scripts/sync-gxl-docs.sh。 在它并入 galaxy-flowmain之前,workflow 会给出 warning 并跳过校验(不会误报红)。
Changelog
文档更新 2026-09-30 —— 值变更表(gops sys diff / gops mod diff)
- 命令行工具:
cmd/gops.md新增「展示系统值变更」与「展示模块值变更」两节(列含义、未展开值比对、--json、localize末尾附带变更表);gops prj diff标注暂不提供;mod localize/sys localize补文件变更表(created/replaced,前后内容指纹比对);sys diff补 gxl 系统的模块分组([mod: <name>],values/<mod>/mod_value.yml)与--json新结构
文档更新 2026-09-28 —— 对齐 galaxy-ops 1.3.3 的 docker-compose 文件位置
- System 文档:
kind: docker-compose的 compose 文件默认从系统根移至sys/docker-compose.yaml,并补充查找顺序、compose 项目目录锚定系统根、旧布局仍兼容的说明;同步operator/sys/structure/directory.md、file-organization.md、naming-conventions.md、operator/sys/README.md、operator/sys/examples/docker-compose.md、operator/sys/troubleshooting/common-issues.md、operator/overview.md、operator/roadmap.md - 命令行工具:
cmd/gops.md的系统目录结构与.env消费说明改为sys/docker-compose.yaml
工程 2026-09-18 —— 站点源移入 src/,避免 .git 被拷进产物
book.toml的src由./改为src,站点内容(SUMMARY.md、README.md、CHANGELOG.md、cmd/、gxl/、operator/、config/、buildin.md、work.md、mermaid.min.js、favicon.svg)平移至src/- 原因:站点源为仓库根时,mdBook 会把
.git/(约 5.2MB,含 objects/refs)、.github/、.gitignore一并拷进book/产物(并且遍历.git时会撞上 git 临时 index 文件而偶发构建失败)。移入子目录后这些落在站点源之外 theme/保留在book.toml同级(mdBook 从 book root 取theme/,已实测确认);产物不再包含book.toml- galaxy-flow 的
scripts/sync-gxl-docs.sh默认--dest与GXL docs sync checkworkflow 同步改为src/gxl
页面风格 2026-09-18 —— 对齐 wp-docs 主题
- 移植 wp-docs 的 VitePress 风格 mdBook 主题:新增
theme/(site.css与上游一致;site.js裁掉 wp 专有的顶栏/中英切换/版本横幅,保留侧栏折叠、侧栏宽度持久化、本页目录、mermaid 主题联动),book.toml设default-theme/preferred-dark-theme并指向该目录 - favicon 改由
theme/favicon.svg提供;删除mermaid.css(其内容是一段报错文本,被误当样式表引用) mermaid.min.js改为按需懒加载(站内无 mermaid 图,原先每页白加载 2.9MB)- CI 固定 mdBook
0.5.2:主题依赖 0.5 的 DOM 结构
文档更新 2026-09-18 —— 对齐当前工具集与 galaxy-ops 实现
- 命令行工具:
cmd/gflow.md重写为cmd/gx.md(命令表按实机gx --help校正);移除gmod/gsys条目,gprj标注 legacy;cmd/gops.md按当前实现重写(ops-systems.yml已并入ops-prj.yml、sys localize参数、sys package/prj reimport/sys new --kind) - 维护器:
operator/sys/*补齐kind(gxl / docker-compose)分派、sys-model字段、GXL 与 docker-compose 两套目录结构、merged_vars.yml/sys_value.yml/.env与常见问题,并新增 docker-compose 示例;operator/mod/*与 README 同步gx名称 - 工程:
SUMMARY.md清掉指向不存在文件的条目并注册新页;book.toml移除非法字段multilingual(mdbook build恢复可用);并入galaxy-sec→galaxio-labs署名
Galaxy Flow v0.8.3 → v0.8.6
新增
- 日志重定向系统重构:改用管道(pipe)实现,改进处理机制与稳定性
- 逻辑表达式(
logic_exp):完整的解析与执行能力 gx.tar/gx.untar:原生压缩与解压缩能力
改进
- 成功状态处理逻辑重构、表达式逻辑更新、清理 taskvalue 中的日志
- 依赖更新(clap 等)、代码格式化与 clippy 修复、artifact 构建更新
- 新增读取文件日志功能
修复
- 模块路径错误、模块名称列表问题
- 通道与启用状态的关联问题
- 干运行参数未传递给子 gxl 的问题
从 v0.8.3 升级到 v0.8.6 向后兼容;建议试用新的日志重定向与逻辑表达式功能。
0.8.3
新增
- GXL 支持 数字、BOOL、数组、对象 数据类型
- 提供 defined 函数 - 检查变量是否已定义
- 提供 gx.shell 方便 shell 调用
- 支持 ${VAR:default} 变量定义默认值
- gprj update mod 或 gflow –update mod 支持更新项目依赖的 Mod
改进
- gx.read_file 读取内容到对象,便于后续处理
- winnow 升级 0.7
- 对于远程Mod的获取,去掉外部Git 依赖
- 修改外部依赖
0.7.0
新增
- 支持事务机制
- 支持 dryrun 机制(预览操作结果而不实际执行)
0.6.4
新增
gx.cmd支持 quiet(静默):自定义控制 cmd 的日志输出
0.6.2
新增
- 优化日志输出、增加日志重定向,支持捕获控制台标准日志输出
0.6.0
新增
- 生成任务报告(执行过程与结果详情)
- 支持 flow 上的 Task 注解
改进
- flow 编排语法由
:改为|
gflow-0.5.3
内置环境变量
GXL_PRJ_ROOT:最近定义的_gal/project.toml所在目录
extern mod 支持变量
extern mod head { path = "${GXL_START_ROOT}/_gal/"; }
0.5.2
内置环境变量
GXL_START_ROOT:GXL 启动处理的目录GXL_CUR_DIR:GXL 当前所在目录(调用gx.run时可能与GXL_START_ROOT不同)
命令行工具
当前(galaxio-labs operator ecosystem)提供的命令:
早期的
gflow、gmod、gsys、gprj已更名或合并:gflow→gx;gmod/gsys→gops mod/gops sys;gprj→gx init project。
gx 命令使用文档
gx是gflow的新名字(galaxy-flow的执行器 CLI)。本文档按当前gxCLI 编写。
概述
gx 用于运行 GXL 工作流,并提供运行环境 / 项目初始化与模块管理。它负责“执行”这一层:
galaxy-flow(gx):定义并执行工作流galaxy-ops(gops):组织与交付模块、系统、运维项目
基本用法
gx <COMMAND>
命令列表
| 命令 | 说明 |
|---|---|
gx run [FLOWS]... | 运行工作流(默认 ./_gal/work.gxl) |
gx adm [FLOWS]... | 运行管理流程(默认 ./_gal/adm.gxl) |
gx init env | 初始化本地 Galaxy 环境(~/.galaxy、网络访问控制等) |
gx init project [--repo URL] [--path SUBDIR] [--branch B] [--tag T] | 初始化项目(默认用本地模板;--path/--repo 走远程) |
gx mod update | 更新项目模块(依据本地 _gal 配置) |
gx doc [TOPIC] | 查看内置文档 |
gx check | 打印当前运行环境信息 |
gx self check|update|rollback | 自更新管理 |
参数说明
位置参数
FLOWS...:流程名称列表(用于gx run/gx adm)
选项参数
-e, --env <ENV>:环境名称(默认default)-d, --debug <DEBUG>:调试级别(默认0)-c, --conf <CONF>:GXL 配置文件路径(默认值由子命令决定)--log <LOG>:日志配置,例如--log cmd=debug,parse=info--cmd-arg <ARG>:传递给流程的命令行参数-q, --quiet:静默模式-h, --help/-V, --version
使用示例
# 运行默认工作流
gx run
# 运行指定流程
gx run conf ver
# 运行管理流程
gx adm package
# 指定环境与调试级别
gx adm -e dev -d 2 start
# 初始化项目(默认模板仓库)
gx init project --path <subdir>
# 更新模块 / 查看环境
gx mod update
gx check
目录约定
./_gal/work.gxl:工作流入口(gx run)./_gal/adm.gxl:管理流程入口(gx adm)./_gal/mods/:本地项目模块
注意:旧文档里的
./_rg/已改为./_gal/。
环境变量
RUST_LOG:Rust 日志级别- GXL 模块渠道等变量按具体工作流约定(例如模板里的
GXL_CHANNEL)
返回值
0:执行成功- 非
0:执行失败,返回错误码
常见问题
找不到配置文件
gx run / gx adm 默认读取当前目录下的 ./_gal/work.gxl / ./_gal/adm.gxl,请在项目根目录执行,或用 -c 指定配置文件。
权限问题
chmod +x gx
模块加载失败
检查网络连接与模块路径配置(_gal 中的 extern mod)。
与 gops 的关系
kind: gxl 的系统在 gops run start/stop/status/... 时委托外部执行器执行系统的管理流程;
kind: docker-compose 的系统不需要 gx,直接映射到本机 docker compose。
gops - Galaxy Operations System 系统操作管理工具
概述
gops 是 Galaxy Operations System 的核心命令行工具,用于管理系统配置、模块操作和系统设置。它提供了完整的系统管理功能,帮助开发者高效地管理 Galaxy 系统的各种组件和配置。
基本用法
显示版本信息
gops
# 输出示例:gops: 1.3.0
显示帮助信息
gops --help
gops <command> --help
gops <command> <subcommand> --help
命令结构
gops 采用三层命令结构:
gops [全局选项] <主命令> [子命令选项] <子命令>
主命令
gops prj- 部署管理命令gops mod- 模块管理命令gops sys- 系统管理命令(定义 / 交付 / 工件)gops run- 运行时运维命令(在环境里落地 / 运行)gops self- 自升级命令
全局选项
所有命令都支持以下全局选项:
调试选项
-d, --debug <LEVEL>- 调试级别(0-3)0: 关闭调试输出1: 基础调试信息2: 详细调试信息3: 跟踪调试信息
日志选项
--log <LOG>- 日志级别配置- 格式:
模块=级别,模块=级别 - 例如:
--log setting=debug,system=info
- 格式:
强制选项
-f, --force <LEVEL>- 强制更新级别0: 正常模式(默认)1: 跳过确认2: 覆盖文件3: 强制拉取
部署工程管理命令 (gops prj)
创建维护工程
gops prj new [OPTIONS]
选项:
-n, --name <NAME>- 工程配置名称(必填)-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置
功能:
- 创建指定名称的维护工程
- 初始化工程目录结构
- 生成必要的配置文件
示例:
# 创建名为 my-project 的工程
gops prj new --name my-project
# 创建工程并启用调试
gops prj new --name my-project --debug 2
导入系统到工程
gops prj import [OPTIONS]
选项:
-p, --path <PATH>- 系统导入路径(必填)-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置-f, --force <LEVEL>- 强制更新级别
功能:
- 从指定路径导入系统配置
- 将系统集成到当前工程
- 自动处理系统依赖关系
示例:
# 从指定路径导入系统
gops prj import --path /path/to/system
# 详细调试导入过程
gops prj import --path /path/to/system --debug 3
更新工程
gops prj update [OPTIONS]
选项:
-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置-f, --force <LEVEL>- 强制更新级别
功能:
- 更新工程中的系统引用
- 更新模块依赖关系
- 下载远程资源
示例:
# 正常更新工程
gops prj update
# 强制更新(覆盖文件)
gops prj update --force 2
# 详细调试更新过程
gops prj update --debug 3 --log update=debug
重新导入系统
gops prj reimport [OPTIONS]
选项:
-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置-f, --force <LEVEL>- 强制更新级别
功能:
- 按
ops-prj.yml记录的sys_models重新导入系统 - 保留
values/客户值(适用于“删除了已导入系统目录、但保留了 values/ + ops-prj.yml”的场景)
示例:
gops prj reimport
模块管理命令 (gops mod)
创建示例模块结构
gops mod example [OPTIONS]
选项:
-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置
功能:
- 创建完整的示例模块结构
- 包含示例配置和工作流
- 展示模块组织最佳实践
示例:
# 创建示例模块
gops mod example
# 创建示例模块并启用调试
gops mod example --debug 2
定义新模块操作符
gops mod new [OPTIONS]
选项:
-n, --name <NAME>- 模块名称(必填)- 支持字母数字、连字符和下划线
-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置
功能:
- 使用给定名称创建新模块规范
- 初始化模块目录结构
- 生成所有必要的配置文件
示例:
# 创建名为 my-module 的模块
gops mod new --name my-module
# 创建模块并启用调试
gops mod new --name my-module --debug 3
更新现有模块操作符
gops mod update [OPTIONS]
选项:
-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置-f, --force <LEVEL>- 强制更新级别
功能:
- 更新现有模块的配置
- 更新模块依赖关系或规范
- 支持强制更新模式
示例:
# 正常更新模块
gops mod update
# 强制更新模块
gops mod update --force 1
# 详细调试更新过程
gops mod update --debug 3 --log mod=debug
本地化模块配置
gops mod localize [OPTIONS]
选项:
-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置--value <PATH>- 包含环境特定值的 YAML/JSON 文件路径--default- 使用内置默认值而不是用户提供的 value.yml
功能:
- 基于环境特定值生成本地化配置文件
- 适配不同部署环境的需求
- 支持自定义值或默认值选择
- 渲染
spec/→local/后打印文件变更表(FILE | STATE,created/replaced):用前后内容指纹(sha256)比对,先清空local/再重建不会误报未变文件,删除不报;标头为<输出目录> ← <源模板>(如…/local ← sys/setting/warp-fusion),区分来源
示例:
# 使用默认值本地化
gops mod localize --default
# 使用自定义值文件本地化
gops mod localize --value prod-values.yml
# 使用自定义值文件并启用调试
gops mod localize --value dev-values.yml --debug 2
展示模块值变更
gops mod diff [--json]
只读比对「模块默认值」(mod/<model>/vars.yml,来源 mod-default)与生效值,按模型列出每个键的初始值 / 生效值 / 来源 / 可变性 / 变更状态。gops mod localize 结束时也会打印同一张表。
示例:
gops mod diff
gops mod diff --json
系统管理命令 (gops sys)
创建新的系统操作符
gops sys new [OPTIONS]
选项:
-n, --name <NAME>- 系统名称(必填)- 支持字母数字、连字符和下划线
--kind <KIND>- 部署类型:gxl(默认)或docker-compose;不指定时交互式选择
功能:
- 创建新的系统规范
- 初始化系统目录结构(
kind决定是否生成 GXL 骨架) gxl:交互式选择系统型号(测试环境下设TEST_MODE=1自动选择)docker-compose:无型号,只生成精简骨架
示例:
# 默认:GXL 系统(交互式选择型号)
gops sys new --name my-system
# 纯 docker-compose 系统
gops sys new --name gateway --kind docker-compose
# 在测试环境中创建系统
TEST_MODE=1 gops sys new --name test-system
更新系统配置
gops sys update [OPTIONS]
选项:
-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置-f, --force <LEVEL>- 强制更新级别
功能:
- 更新现有系统配置
- 更新系统规范或依赖关系
- 支持强制更新以不确认的情况下覆盖配置
示例:
# 正常更新系统
gops sys update
# 强制更新系统(跳过确认)
gops sys update --force 1
# 详细调试更新过程
gops sys update --debug 3 --log sys=debug
打包系统
gops sys package [OPTIONS]
选项:
-f, --force <LEVEL>- 强制更新级别--output <PATH>- 输出路径(默认:父目录下<name>-<version>.tar.gz)--full- 打当前目录全部(含制品与本地化产物,用于隔离网络交付;默认只打 git 入库文件)。旧名--no-git仍可用(隐藏别名)
功能:
- 先执行一次
update(解析变量、生成sys/merged_vars.yml),保证交付包可被gops prj import完整导入 - 再打包为
.tar.gz:默认只含 git 入库文件(git ls-files,等价git archive的“只含入库文件”,需在 git 仓库内运行),自然排除被.gitignore忽略的产物(sys/*/mods/、**/local、.env等);--full则打当前目录全部(含制品/本地化产物) - 两种模式都会排除
sys-prj.yml的ignore:节列出的路径;deliver.lock作为交付清单始终随包分发(不受ignore影响)
ignore 节(sys-prj.yml):列出打包时排除的路径模式(glob,相对系统根),即使 --full 也排除。匹配文件自身或其任一祖先目录——目录级模式(如 sys/*/mods)会排除整棵子树。模式锚定在根:裸名 mods 只匹配根级 mods,任意层级请用 **/mods;* 不跨 /,跨级用 **;前导 / 或 ./ 会被归一化(等价于不带)。
注意:模式过宽(如
*)会连sys/merged_vars.yml等一并排除;deliver.lock不受影响(始终随包)。
# sys-prj.yml
ignore:
- artifacts
- sys/*/mods
- '**/cache'
- .env
示例:
# 默认:只含入库文件(不含制品)
gops sys package
# 整目录打包(含制品 / 被忽略的产物,用于隔离网络)
gops sys package --full
gops sys package --output /tmp/gateway-0.1.0.tar.gz
为环境本地化系统配置
gops sys localize [OPTIONS]
选项:
-d, --debug <LEVEL>- 调试级别--log <LOG>- 日志配置--mod <MODULE>- 只处理指定模块--only- 只 localize,跳过 update(不解析/下载模块)
功能:
- 生成
.env:sys/merged_vars.yml默认值 ⊕values/sys_value.yml⊕values/value.yml - 两个值文件都是可选、可部分覆盖:只写需要修改的项,其余取系统默认值
- 默认先解析变量:
gops sys localize默认无条件先解析(等价于先跑一次gops sys update,含解析/下载模块),因此改完sys/setting/vars.yml一条命令即生效;--only跳过该步骤(用现有sys/merged_vars.yml,缺失时会明确报错)。 kind: docker-compose时,.env供 compose 消费(默认 compose 文件为sys/docker-compose.yaml,.env仍在系统根)
示例:
# 生成本地化配置(默认先解析变量,再写 .env)
gops sys localize
# 只 localize,不解析/下载(用现有 merged_vars.yml;缺失则报错)
gops sys localize --only
# 只处理某个模块
gops sys localize --mod gateway
值文件说明: values/sys_value.yml 由 sys update 首次生成,整份是注释模板——取消注释需要覆盖的项即可;values/value.yml 优先级更高(覆盖层优先:value.yml > sys_value.yml > 变量定义),适合入库的客户覆盖。
localize 渲染 sys setting 模板(src → dst)后,会打印文件变更表(FILE | STATE,created / replaced),用前后内容指纹(sha256)比对:清空输出树再重建不会把内容未变的文件误报为变更,删除不报。
改了
sys/setting/vars.yml而未重新 localize 时,gops sys check会输出[WARN]提示(仅比对.env看不到这层陈旧)。
展示系统值变更
gops sys diff [--json]
只读比对「系统默认值」(sys/merged_vars.yml 的 system: 段,来源 sys-defaults)与生效值(⊕ values/sys_value.yml(sys-setting) ⊕ values/value.yml(customer)),只列出被覆盖的键:
| 列 | 含义 |
|---|---|
KEY | 变量名 |
INITIAL | 初始层取值(- 表示初始层无此键) |
EFFECTIVE | 生效值 |
ORIGIN | 生效值来自哪一层 |
MUTABILITY | 生效值可变性(merged_vars.yml 不序列化可变性,故多为 module) |
STATE | same / changed / added / removed(表格只列非 same 行) |
比对用未展开值(${VAR} 展开前),避免伪变更。gops sys localize 结束时也会打印同一张表(无覆盖时打 [OK] 值无覆盖)。
对 gxl 系统(有 sys/mod_list.yml),sys localize 会逐模块消费 values/<mod>/mod_value.yml,故 sys diff / localize 还按模块分组呈现 [mod: <name>](初始层 = sys/<model>/mods/<mod>/vars.yml;生效层 ⊕ values/<mod>/value.yml ⊕ values/<mod>/mod_value.yml ⊕ 系统层)。模块内容未下载时给 [WARN](先 gops sys update)。
值文件键大小写不敏感(加载时归一化为大写)。--json 为 { "system": [...], "modules": [{ "module": …, "changes": [...] }], "files": [{ "target": …, "changes": [...] }] }(只含有变更的分组)。
文件覆盖层: 除值以外,sys diff 还会列出 sys/setting/<mod>/** 相对模块 <mod>/spec/** 的新增 / 替换(localize 把两者都渲染进 local/,即「setting 覆盖了模块默认的哪些文件」);纯路径 + 内容比对,不需渲染,也不依赖上次 localize 的磁盘状态。
示例:
gops sys diff
# [sys] 值变更 (1 项):
# KEY INITIAL EFFECTIVE ORIGIN MUTABILITY STATE
# NGINX_TAG 1.25-alpine 1.27-alpine customer module changed
# [mod: warp-parse] 值变更 (1 项):
# KEY INITIAL EFFECTIVE ORIGIN MUTABILITY STATE
# CPU 1000 2000 mod-setting module changed
gops sys diff --json
gops prj diff暂不提供(prj 视角即逐系统的sys表)。
运行时运维命令 (gops run)
在目标系统上执行标准运维动作(算子流契约)。按 sys/sys_model.yml 的 kind 分派:gxl 系统委托 gx run <cmd>(需 gx >= 0.13.0);docker-compose 系统映射到 docker compose 子命令(无需 gx)。
gops run download # 下载制品 compose: pull
gops run install # 安装组件 compose: create
gops run uninstall # 卸载组件 compose: down
gops run start # 启动服务 compose: up -d
gops run stop # 停止服务 compose: stop
gops run status # 查询状态 compose: ps
gops run diagnose # 诊断问题 compose: config(密钥掩码注入)
通用选项: --mod <MODULE>、-e, --env <ENV>(默认 default)、-d/--debug、--log。
与
gops sys(定义/交付/工件:new/update/localize/package/setting/check/diff)区分:gops run只管「在环境里落地/运行」。
示例:
gops run start --env default
gops run status --mod nginx
gops run diagnose # 校验并展示解析后的 compose(密钥以 ******** 掩码注入)
自升级命令 (gops self)
与 gx self 对齐,用于检查与升级 gops 自身。
查看状态
gops self status
输出当前版本、安装目录与最近一次自升级结果(state.last_remote_version / state.last_result / state.last_error)。
检查更新
# 默认 stable 通道
gops self check
# 指定通道
gops self check --channel alpha
# 机器可读输出(stdout 仅 JSON,不含版本横幅)
gops self check --channel alpha --json
升级
# 升级到通道最新版
gops self update --channel alpha
# 跳过交互确认
gops self update --channel alpha --yes
# 只演练,不实际安装
gops self update --channel alpha --dry-run
# 指定目标版本(与清单不一致时报错)
gops self update --channel alpha --to 2.1.0
# 已是最新时强制重装
gops self update --channel alpha --force
更新前会备份当前二进制;新版本 --version 健康检查失败会自动回滚。
回滚
# 回滚到最近一次备份
gops self rollback
# 指定备份 id(14 位时间戳)
gops self rollback --id 20260321123456
说明
- 制品清单来自
galaxio-labs/get的updates/gops通道,与inst-x.sh gops <channel>同一来源。 - 状态、锁与备份存放于
~/.galaxy/self_update/gops(与gx的同名目录隔离)。
环境变量
调试环境变量
TEST_MODE- 测试模式设置- 当设置为任意值时,启用测试环境行为
- 在
gops sys new中自动选择系统型号而不是交互式选择
模拟环境变量
MOCK_SUCCESS- 模拟成功状态- 用于测试环境中模拟成功的操作
- 通常与
TEST_MODE一起使用
配置文件结构
工程目录结构
my-project/
├── ops-prj.yml # 工程 manifest:name + work_envs + sys_models
├── version.txt
├── _gal/ # GXL 工程文件
├── values/ # 客户值目录
│ └── {system-name}/
│ ├── sys_value.yml # 值文件(只写需要覆盖的项)
│ └── value.yml # 额外覆盖层(可选)
└── {system-name}/ # 已导入的系统目录
└── values -> ../values/{system-name} # 符号链接(prj import/reimport 建立)
历史:原
ops-systems.yml已合并进ops-prj.yml;加载时会兼容合并旧文件,保存后写入单文件。
模块目录结构
my-module/
├── mod.yml # 模块配置文件
├── sys/ # 系统配置
├── workflow/ # 工作流配置
├── artifacts/ # 构建产物
├── config/ # 配置文件
└── settings/ # 模块设置
系统目录结构
my-system/
├── sys-prj.yml # 系统根配置
├── version.txt
├── _gal/ # GXL 工程文件(仅 kind: gxl)
├── values/ # 值文件目录
└── sys/
├── sys_model.yml # name / model / kind / vender
├── docker-compose.yaml # 系统级 compose 定义(${VAR} 占位)
├── mod_list.yml # 模块列表(GXL;可选)
├── merged_vars.yml # 聚合变量(sys update 生成,需入库)
├── workflows/ # GXL 工作流(可选)
└── setting/
├── list.yml # 可选
└── vars.yml # 系统设置变量定义(源)
纯 docker-compose 系统只保留 sys_model.yml、docker-compose.yaml 与 setting/vars.yml(详见 System 目录结构)。
最佳实践
工程管理
# 1. 创建新工程
gops prj new --name my-project
# 2. 导入系统到工程
gops prj import --path /path/to/system --force 1
# 3. 更新工程
gops prj update
# 4. 按 ops-prj.yml 重新导入并保留 values/
gops prj reimport
# 5. 客户差异写在 values/<system>/value.yml(只写要覆盖的项)
模块开发
# 1. 创建示例模块(学习结构)
gops mod example
# 2. 创建新模块
gops mod new --name my-module
# 3. 更新模块
gops mod update --force 2
# 4. 本地化模块配置
gops mod localize --value dev-values.yml
系统管理
# 1. 创建新系统
gops sys new --name my-system
# 2. 解析变量 / 初始化值文件
gops sys update --force 1
# 3. 本地化(生成 .env)
gops sys localize
调试技巧
# 启用详细调试
gops prj import --path /test --debug 3 --log all=debug
# 调试特定模块
gops mod update --debug 3 --log mod=debug
# 调试系统操作
gops sys update --debug 3 --log sys=debug
# 调试设置操作
gops sys setting --init --debug 2 --log setting=debug
故障排除
常见错误及解决方案
Q: 工程创建失败
错误:无法创建目录 "my-project"
解决:检查目录权限,或选择不同的名称
Q: 系统导入失败
错误:load project from ./path fail!
解决:检查路径是否正确,确保有适当的访问权限
gops prj import --path /path/to/system --debug 3
Q: 模块更新失败
错误:无法加载模块配置
解决:确保在正确的模块目录中执行命令
gops mod update --debug 3 --log mod=debug
Q: 系统创建卡在选择界面
解决:在测试环境中设置 TEST_MODE 环境变量
TEST_MODE=1 gops sys new --name test-system
Q: 设置命令在非交互模式下失败
解决:确保 sys/setting/ 目录存在,并在系统根目录执行
gops sys setting --init --debug 2
调试模式使用
# 基础调试
gops prj import --path /test --debug 1
# 详细调试
gops mod update --debug 2 --log mod=debug
# 跟踪级别调试
gops sys update --debug 3 --log sys=trace
# 跟踪级别调试(工程)
gops prj update --debug 3 --log all=debug
日志配置示例
# 调试特定模块
gops mod update --log mod=debug
# 调试多个模块
gops sys update --log sys=debug,net=info
# 设置不同级别
gops prj import --log import=debug,system=info,net=trace
# 调试所有内容
gops mod update --log all=debug
测试
项目包含完整的测试套件:
# 运行所有测试
cargo test
# 运行特定测试
cargo test test_gxops_run_success
# 运行测试并显示输出
cargo test -- --nocapture
# 在测试环境中运行
TEST_MODE=true cargo test
# 运行特定命令的测试
cargo test test_ia_setting_interactive
cargo test test_ia_setting_non_interactive
示例工作流
开发环境设置
# 1. 创建开发工程
gops prj new --name dev-project
# 2. 导入开发系统
gops prj import --path /path/to/dev-system --force 1
# 3. 更新工程依赖
gops prj update --debug 2
# 4. 写客户差异(项目值目录,只写要覆盖的项)
# dev-project/values/dev-system/value.yml
# 5. 创建开发模块
gops mod new --name dev-module
# 6. 本地化模块配置
gops mod localize --value dev-values.yml
生产环境部署
# 1. 创建生产工程
gops prj new --name prod-project
# 2. 导入生产系统(打包产物:.tar.gz 或 git/http 地址)
gops prj import --path /path/to/prod-system-0.1.0.tar.gz --force 3
# 3. 在项目值目录里写客户差异(只写需要覆盖的项)
# prod-project/values/prod-system/value.yml
# 4. 本地化生产配置(在系统目录内执行,自动使用项目值)
cd prod-system
gops sys localize
版本信息
当前版本:1.3.0
功能状态
| 命令 | 子命令 | 状态 | 说明 |
|---|---|---|---|
gops prj | new | ✅ 完成 | 创建维护工程 |
gops prj | import | ✅ 完成 | 导入系统到工程(打包产物) |
gops prj | update | ✅ 完成 | 更新工程 |
gops prj | reimport | ✅ 完成 | 按 ops-prj.yml 重新导入(保留 values/) |
gops mod | example | ✅ 完成 | 创建示例模块结构 |
gops mod | new | ✅ 完成 | 定义新模块操作符 |
gops mod | update | ✅ 完成 | 更新现有模块操作符 |
gops mod | localize | ✅ 完成 | 本地化模块配置 |
gops sys | new | ✅ 完成 | 创建系统(--kind gxl / docker-compose) |
gops sys | update | ✅ 完成 | 解析变量、初始化值文件 |
gops sys | package | ✅ 完成 | 先 update 再打包交付产物 |
gops sys | localize | ✅ 完成 | 生成 .env(--only 跳过 update) |
gops sys | setting | ✅ 完成 | 初始化系统设置 |
gops sys | download/install/start/stop/uninstall/status/diagnose | ✅ 完成 | 按 kind 分派(gxl→gx;docker-compose→docker compose) |
许可证
本项目采用 MIT 许可证 - 详见项目根目录的 LICENSE 文件
BUILDIN
Galaxy-Ops 文档
想先了解
gops的定位与独特价值,见 定位与价值。
gops <COMMAND>
一级命令:
gops mod:模块管理gops sys:系统管理gops prj:运维项目管理
对象模型
galaxy-ops 围绕三层对象工作:
Module -> System -> Project
Module:最小可复用运维单元System:由多个模块组合形成的系统定义Project:面向具体客户环境的交付项目
这三层分别对应当前 CLI 的三组命令:
gops mod ...gops sys ...gops prj ...
当前命令面
部署项目命令
gops prj new --name <name>
gops prj import --path <system-path>
gops prj update
gops prj reimport
gops prj reimport 按 ops-prj.yml 记录的 sys_models 重新导入系统,保留 values/ 客户值。
系统命令
# gops sys —— 定义 / 交付 / 工件
gops sys new --name <name> [--kind gxl|docker-compose]
gops sys update
gops sys package [--full]
gops sys localize [--mod <module>] [--only]
gops sys setting --init
gops sys check
# gops run —— 运行时运维(在环境里落地/运行)
gops run download [--mod <module>] [--env <env>]
gops run install [--mod <module>] [--env <env>]
gops run uninstall [--mod <module>] [--env <env>]
gops run start [--mod <module>] [--env <env>]
gops run stop [--mod <module>] [--env <env>]
gops run status [--mod <module>] [--env <env>]
gops run diagnose [--mod <module>] [--env <env>]
sys/sys_model.yml 的 kind 决定部署行为:gxl(默认)委托 gx 执行;docker-compose 直接映射到本机 docker compose。
模块命令
gops mod example
gops mod new --name <name>
gops mod update
gops mod localize [--value <file> | --default]
文档索引
- overview.md:
gops定位与独特价值(含对象模型 / 双后端分派图) - roadmap.md:按性价比排序的改进方向
- mod/README.md:模块对象说明与
gops mod使用方式 - mod/CONFIGURATION.md:模块配置与文件结构
- mod/DEVELOPMENT.md:模块开发与本地调试流程
- mod/REFERENCE.md:当前 CLI / 目录 / 概念参考
- mod/TROUBLESHOOTING.md:常见问题排查
- sys/README.md:系统对象说明与
gops sys使用方式 - sys/configuration/sys-model.md:
sys_model.yml字段与kind - sys/structure/directory.md:GXL / docker-compose 两种目录结构
- sys/examples/microservices.md:GXL 多模块系统示例
- sys/examples/docker-compose.md:纯 docker-compose 系统示例(含密钥与
.env) - sys/troubleshooting/common-issues.md:常见问题排查
对齐说明
本目录文档已经按当前 galaxy-ops 代码实现收敛为以下原则:
- 只使用
gops作为 CLI 入口 - 只描述当前代码里存在的命令和对象
- 文件树以真实生成结果为准
- 不再保留推断型 Rust API、旧命令名和过时的架构图
GOps 定位与价值
一句话定位
gops(galaxy-ops)不是执行引擎,而是运维能力的资产化 + 组合 + 交付层:
把“一套系统交付给 N 个客户“变成有对象模型、有版本、可审计的工程流程。 执行本身仍然交给
galaxy-flow(gx)或本机docker compose。
要解决的问题
这一节回答“为什么会有 gops“。这些问题最终都指向同一个主题:交付中“该共享的“与“该隔离的“没有被分层表达——能力、值、流程应沉淀到共享层,客户差异与运行形态应隔离到独立层;一旦混在一起,变更就会逃出版本与责任的闭环。
1. 客户环境的部署配置:时常修改、容易遗忘、后果严重
客户环境下的部署配置,是运维交付长期的重灾区:
- 时常修改:客户环境异构、需求会变(扩容、换证书、换域名、合规),配置天生是“活的“。
- 容易遗忘:修改发生在交付之后的现场,脱离产品版本库,没有“谁改了、改成了什么、相对默认差了多少“的记录。
- 后果严重:配置直接驱动运行时,一个错值就是生产事故,而且往往没有回滚点。
根因:配置的三种“脱节“
| 脱节 | 含义 |
|---|---|
| 时间脱节 | 配置在“交付之后、运行之中“被改,脱离了产品构建时刻 |
| 空间脱节 | 配置躺在客户环境中,脱离了产品的版本库 |
| 责任脱节 | 产品 / 实施 / 客户运维都可能改,却没人完整拥有 |
三种脱节合起来,就是“配置改动逃出了版本与责任闭环“。
GOps 的应对
| 症状 | 脱节 | GOps 机制 |
|---|---|---|
| 时常修改 | 时间 | 分层值文件(merged_vars 默认 ⊕ sys_value.yml ⊕ value.yml),高频改动被收敛进受控差异层 |
| 容易遗忘 | 空间 | sys_value.yml 注释模板、merged_vars.yml 入库、prj reimport 保留 values/ |
| 后果严重 | 责任 | 配置与密钥分离(${SEC_xxx} 运行时注入)、diagnose 预校验 + 掩码、打包产物版本化可回滚 |
一个关键设计:values/sys_value.yml 生成时为整份注释模板——“没写“等于“用系统默认值”。于是“复制了一份默认值却忘了改“这类经典事故从根上消失:要覆盖才写,且只写差异。
边界
GOps 提供的是“让配置回到版本与责任闭环“的结构,但它不包办全部:
- 它不强制你把
values/提交进 git——这仍是纪律(好在该提交的东西被压缩到极小、极明确); - 它不做漂移检测——有人绕过
gops直接改现场文件,不会告警; - 变更审计依赖 git 提供历史。
换句话说,它把“需要人管的东西“从“整个客户环境“缩小到“几个值文件 + 一次 commit“。
2. 模块被聚合进多个系统:默认要能用、集成要能改、部署还要能再改
一个模块(如 postgresql)会被多个系统复用,而它的运行配置需要同时满足三件事:
- 默认设定:模块自带一套能直接跑起来的默认值;
- 系统集成时可改写:被某个系统聚合时,集成者能按该系统需要改写;
- 部署时再次修改:到了客户现场,实施 / 客户还要能再改。
难点在于:把定制写进模块就会污染共享资产(又回到“每系统一份“的老路);而且三层改写必须有明确优先级,还要区分“哪些值允许被改、哪些不允许“。
根因:共享与定制的冲突 + 覆盖层级
- 模块是共享资产,被 N 个系统复用;但配置需求是每个系统 / 每个客户各异的。
- 改写点分布在三层,必须有单一、明确的优先级链。
- 并非所有值都该被改:有些是身份 / 常量(如
app_name),必须锁死。
GOps 的应对:变量 + 可变性 + 分层覆盖点
| 层级 | 拥有者 | 载体 | 作用 |
|---|---|---|---|
| 模块默认 | 模块定义者 | mod/<model>/vars.yml | 能直接运行的默认值 |
| 系统集成覆盖 | 系统集成者 | sys/setting/vars.yml → merge → sys/merged_vars.yml | 按系统需要改写 |
| 部署现场覆盖 | 实施 / 客户 | values/sys_value.yml、values/value.yml | 按客户环境再改 |
- 可变性(mutability):每个变量声明自己允许在哪些层被改——
Immutable/System/Module。定义者用它划定“允许被改写的边界“(例如app_name声明为不可变)。部署时的交互式设置只遍历可变项。 - 共享复用:模块以引用形式(
ModuleSpecRef:名称 + 地址 + 模型 + 开关)被多个系统聚合,可改名、可选不同ModelSTD,无需改动模块本体。
这样,同一模块的默认值只写一次,各系统 / 各客户的改写分别落在各自的层上,互不污染。
边界
- 覆盖优先级的细节由运行时(
orion-variate的变量合并)决定,以实际行为为准; - “哪些项该在系统层改、哪些该留给客户层“仍需约定,工具不强制。
3. 同一系统需要多种部署形态:二进制 / K8S / Docker Compose
同一套系统,可能既要在客户机上以二进制(裸机 / 进程)部署,又要上 Kubernetes,还要能跑 Docker Compose。
难点:三种形态实现差异极大(进程 vs 编排 vs 容器),几乎无法复用同一份部署脚本;如果每种形态各自维护一套交付(值文件、操作命令、打包流程),就等于三份并行的运维体系——问题 1 的“时常修改、容易遗忘“会被放大三倍。而客户差异(域名、端口、规格)本应与形态无关。
根因:形态差异外溢成了交付体系的分叉
- 形态的差异本是实现层的(怎么落地),却扩散到了交付层(值、命令、打包)。
- 本应“一份值 + 一套命令“跨越三种形态,实际却变成三套。
GOps 的应对:分层表达形态
| 部署形态 | GOps 表达 | 执行者 |
|---|---|---|
| 二进制(Host) | kind: gxl + ModelSTD(RunSPC=Host) | gx 执行模块的 host 工作流 |
| Kubernetes | kind: gxl + ModelSTD(RunSPC=K8S) | gx 执行模块的 k8s 工作流 |
| Docker Compose | kind: docker-compose(无 ModelSTD) | 本机 docker compose |
- 模块层承载“同一能力的多种落地形式“:同一模块可同时拥有 Host 与 K8S 的
mod/<model>/(不同RunSPC),各自的workflows/operators.gxl提供该形态的实现。 - 系统层选定形态:
ModelSTD(Host / K8S)+kind(gxl / compose)决定用哪种形态交付。 - 三形态共享交付面:同一套值模型、同一个命令面(
gops run start/stop/status/diagnose)、同一套打包 / 导入 / 保值流程。客户差异不随形态改变。
边界
- 一个
System绑定一个ModelSTD+kind,没有“一份系统自动产出三种形态“;切换形态意味着另一个系统对象(但复用同一批模块与值定义)。 - GOps 不做形态间的语义转换:不会把一份业务逻辑自动生成 host / k8s / compose 三份实现,各形态实现仍由模块作者分别编写;GOps 对齐的是对象、值、命令与交付流程,而非实现本身。
与开源机制的关系
“已经有 Helm / Ansible 了,为什么还要 GOps?”——先说结论:
开源机制解决的是“怎么覆盖“;GOps 想解决的是”谁来覆盖、覆盖了什么、以及别忘了“。前者是机制,后者是治理。
问题 2 拆成 7 个要求:R1 默认、R2 集成覆盖、R3 部署覆盖、R4 复用不 fork、R5 优先级链、R6 可变性、R7 记录保值。对照开源机制:
| 机制 | 复用 + 多层覆盖 | 优先级链 | 可变性声明 | 记录与保值 | 跨运行时 |
|---|---|---|---|---|---|
| Helm | ✅ chart 默认 + 覆盖 values | ✅ | ❌ | 🟡 升级可留用户 values | ❌ 绑 K8s |
| Kustomize | ✅ base + overlay | ✅ | ❌ | 🟡 靠 git | ❌ 绑 K8s |
| Ansible | ✅ role defaults + group/host vars | ✅ 20+ 级 | ❌ | ❌ | 🟡 通用但与执行耦合 |
| Terraform | ✅ module 变量 + tfvars | ✅ | ❌ | 🟡 state 非交付值 | ❌ 面向基础设施 |
| Nix modules | ✅ options + 覆盖 | ✅ | ✅ mkDefault/mkForce | 🟡 | ❌ 整机配置范式 |
| CUE / Jsonnet | ✅ 默认值 + 统一 | ✅ | 🟡 约束可禁覆盖 | ❌ | ❌ 是语言,不是交付系统 |
开源已解决得很好的:R1–R5(Helm 式分层 values、Ansible 式 role 复用)。GOps 的覆盖代数并不原创,本质与其同源。
开源至今的四个空白:
- 可变性 ≠ 所有权边界:开源工具把覆盖视为“谁在命令行传了什么“,没人把“产品 / 集成者 / 客户“表达成结构;Helm 里客户和集成者都只是传
-f,没有机制阻止客户覆盖集成者认为不可改的值。(只有 Nix 的mkDefault/mkForce把优先级做成了一等语义。) - 交付对象模型:没有“系统 → N 个客户项目、各自维护客户值“的对象层。
- 记录与保值:没有工具原生提供“实际使用的值落盘入库 + 升级保护客户值“。
- 跨运行时统一:Helm / Kustomize 绑 K8s、Terraform 绑基础设施、Nix 绑整机,没有一套对象与覆盖链能在 host / k8s / docker compose 间共享。
GOps 的位置(诚实版):
- 覆盖代数不是原创——可视为 Helm 式分层值 + Ansible 式复用的运维交付改写;
- 真正补的是空白 1–4:把覆盖嵌进
Module → System → Ops Project对象模型、用Immutable/System/Module把可变性变成声明式所有权边界、用merged_vars.yml+ 来源追踪做记录、用kind跨运行时统一; - 但它的可变性粒度比 Nix 粗(Nix 可对每个赋值定优先级并合并,GOps 按变量作用域分级),且闭环仍依赖 git 纪律。
有没有“满需求“的开源方案
把问题 1–3 合起来,“满需求“落在 6 个维度:
| 维度 | 含义 |
|---|---|
| D1 多层覆盖 | 默认 → 集成 → 部署三级覆盖 + 优先级链 + 复用不 fork |
| D2 可变性 / 所有权 | “某值不允许在某一层被改“作为声明 |
| D3 记录与保值 | 实际用了什么可复现;升级不覆盖客户值 |
| D4 密钥分离 | 密钥不落盘、运行时注入 |
| D5 多形态 | 同一能力支持二进制 / K8S / Compose |
| D6 交付对象模型 | 产品 → 系统 → 客户项目,含打包 / 导入闭环 |
主流方案对照:
| 方案 / 组合 | D1 | D2 | D3 | D4 | D5 | D6 |
|---|---|---|---|---|---|---|
| Helm + GitOps(Argo/Flux) + SOPS | ✅ | ❌ | 🟡 | ✅ | ❌ 仅 K8s | 🟡 |
| Ansible + Vault / AWX | 🟡 过程式 | ❌ | ❌ | ✅ | 🟡 | ❌ |
| Terraform / Pulumi | 🟡 | ❌ | 🟡 state | 🟡 | 🟡 provider | ❌ |
| Nix / Colmena | ✅ | ✅ mkForce | 🟡 | 🟡 | 🟡 host 强 | ❌ |
| Crossplane | 🟡 | ❌ | 🟡 | 🟡 | 🟡 k8s 原生 | ❌ |
| Dagger | ❌ | ❌ | ❌ | 🟡 | 🟡 runner | ❌ |
结论:
- 单一开源项目:没有满需求的。
- K8s 单形态下最接近满需求的是 GitOps 栈(Git + Helm/Kustomize + SOPS/Sealed-Secrets + Argo CD/Flux):D1/D3/D4 都做到,甚至靠 reconcile 有了漂移检测;但 D2 失守(无可变性声明)、D5 失守(只服务 K8s)。
- 能横跨三种形态的只有 Ansible / Terraform / Pulumi,但它们是过程式 / 状态式的,没有 D6 对象模型,D2/D3 基本空白,且配置与执行耦合。
- 跨形态没有开源方案同时满足:要么绑死 K8s,要么退化成过程式的 Ansible。
GOps 自己也不是“满需求“:
| D1 | D2 | D3 | D4 | D5 | D6 |
|---|---|---|---|---|---|
| ✅ | ✅(粒度粗) | 🟡 靠 git 纪律 | ✅ | 🟡 需分别实现 | ✅ |
它缺 GitOps 那种“强制以 Git 为真源 + 漂移检测 + 对账回滚“,也不做形态间自动转换。准确说法:开源里没有满需求,GOps 也没有;但它把“满需求“需要的维度装进了同一个对象模型,缺口集中在“强制入库 / 漂移检测 / 自动生成“。
GOps 与 GitOps 的差距
GOps 也依赖 Git,但 Git 在两边角色不同:
- GitOps:Git 是控制回路的输入——被常驻控制器持续读取、对账、收敛。
- GOps:Git 是版本化的载体——靠人 / CI 手动触发一次性动作。
一句话:GitOps 的 Git 驱动一个 loop,GOps 的 Git 只是仓库。
| 维度 | GitOps(Argo CD / Flux) | GOps |
|---|---|---|
| Git 角色 | 控制回路输入(活) | 协作 / 版本载体(存) |
| 真源 | Git 是唯一真源,现场必须服从 | 分层:默认来自系统产物,差异来自 values/,现场不强制收敛 |
| 执行方式 | 常驻 controller 持续 reconcile | CLI 手动 / CI 一次性触发 |
| 部署语义 | 声明式终态(幂等 converge) | 可重复过程(gx workflow,未必终态) |
| 漂移检测 | 核心能力(OutOfSync → 自愈) | 无 |
| 回滚 | revert commit → 自动回滚 | 重跑部署(人工) |
| 多形态 | 主流绑 K8s | 二进制 / K8S / Compose(kind) |
| 密钥 | 加密后仍进 Git(SOPS / Sealed-Secrets) | 不进 Git、不落盘,运行时注入 |
| 对象粒度 | manifest / release / overlay | Module / System / Ops Project |
三个本质差距:
- 有没有 reconcile loop:GitOps 有常驻控制器持续把现场拉回 Git;GOps 没有任何常驻组件,
gops run start跑完即止,不知道现场是否偏离默认值。 - 部署能否归约为声明式终态:GitOps 成立的前提是“期望状态可完整描述 + 幂等收敛“,这成立在容器 / 基础设施领域;二进制部署与 GXL 工作流走的是“可重复过程“,不假装是终态。
- 真源的权威性:GitOps 里现场是从属的,手改会被当 drift 冲掉;GOps 反而承认现场是权威之一——
prj reimport就是“重建系统、保留values/“。两者哲学相反。
为什么二进制 / GXL 难以 GitOps 化
GitOps 需要四个前提同时成立,二进制 / host / GXL 恰好逐条违反:
| 前提 | 含义 | 二进制 / Host / GXL |
|---|---|---|
| 终态可完整描述 | 期望状态是一个 spec | ❌ 安装 / 迁移是“过程 / 历史“(数据库迁移只能按序 apply) |
| 现实可观测 | 能读到实际状态并与期望 diff | ❌ host 没有统一的“部署了什么“状态接口,系统异构 |
| 操作幂等 | 可反复收敛而不产生副作用 | ❌ 启动 / 迁移 / 一次性初始化不幂等;GXL workflow 是“程序“ |
| 资源可抛弃 | 收敛 = 杀掉重建 | ❌ 客户机器是有状态资产(数据 / license / 硬件),强收敛危险 |
同样是部署,Docker Compose 可以而 host 不行:
| 前提 | Docker Compose | 二进制 / Host |
|---|---|---|
| 终态可完整描述 | ✅ compose.yml | ❌ 安装 / 迁移是过程 |
| 可观测 | ✅ docker compose ps | ❌ 无统一状态接口 |
| 幂等 | ✅ up -d 近似幂等 | ❌ 启动 / 迁移一次性 |
| 可抛弃 | ✅ 容器可重建 | ❌ 有状态资产 |
这也解释了为什么 GOps 的 docker-compose 形态最接近 GitOps——四个前提它占了三个半。
但并非“绝对不可能“:Puppet / Chef / Salt 证明了 host 收敛可行(装 agent + 状态模型 + 持续收敛),代价是 agent 重、OS 各异,且迁移 / 一次性步骤仍要退化成 exec / unless 这类逃逸阀。连 K8s 自己都得为非声明式步骤开逃逸阀(Helm hooks、Argo CD sync hooks、Job)——反过来说:凡是“过程“,GitOps 都得打补丁。
所以 GOps 的选择是取舍:既然四前提在二进制 / GXL 上凑不齐,就不去假装有终态收敛——部署 = 可重复的过程(GXL workflow),交给 gx;版本化的只是产物(tar.gz)+ 值(values/);它不承诺收敛,只承诺可复现与可追溯。代价是失去漂移检测与自动回滚,换来的是形态自由。
互补关系更准确:GitOps 管“收敛“,GOps 管“组织与交付“;GitOps 在单形态里做到极致,GOps 用放弃收敛换来覆盖不可收敛的世界。
独特价值
1. 三层对象模型:复用与客户差异物理隔离
Module → System → Ops Project 三层各司其职:
Module:最小可复用运维单元(变量 / 依赖 / 构件 / 工作流)。System:由模块组合出的交付单元。Ops Project:面向具体客户环境的运维项目。
同一个系统可以被多个客户项目导入,客户差异只落在 <project>/values/<system>/,不写死在系统定义里。
flowchart TD
M["Module 最小可复用单元"] --> S["System 组合交付单元"]
S --> P["Ops Project 客户现场"]
S -->|gops sys package| PKG["交付包 tar.gz"]
PKG -->|gops prj import| P
P -->|gops prj reimport 保留 values| P
关键机制:在项目内的系统目录执行 gops sys localize / sys update 时,会依据上层 ops-prj.yml 反向解析出该项目为该系统维护的值目录,而不是使用系统自带的 values/。产品定义与客户现场在磁盘结构上天然分离。
2. 执行中立:同一命令面,两种后端
sys/sys_model.yml 的 kind 决定行为,但操作员的命令是同一套:
flowchart LR
CMD["gops run start / stop / status / diagnose ..."] --> K{"sys_model.yml kind"}
K -->|gxl| GX["gx run -e ENV -d N cmd"]
K -->|docker-compose| DC["docker compose ..."]
GX --> WF["系统工作流 GXL"]
DC --> LOCAL["本机 docker compose"]
gops sys ... | gxl 后端 | docker-compose 后端 |
|---|---|---|
download | gx run download | docker compose pull |
install | gx run install | docker compose create |
start | gx run start | docker compose up -d |
stop | gx run stop | docker compose stop |
uninstall | gx run uninstall | docker compose down |
status | gx run status | docker compose ps |
diagnose | gx run diagnose | docker compose config |
价值点:纯声明式 compose 系统(完全不依赖 gx)与模块化 GXL 工作流系统共享同一套创建、变量、打包、本地化、交付流程。
3. 多模型模块(ModelSTD):一个模块,多目标平台
ModelSTD = CpuArch × OsCPE × RunSPC,例如 x86-ubt22-k8s、arm-mac14-host、x86-ubt22-host。gops mod new 一次生成全部目标模型目录,每个模型有独立的 vars.yml / spec/ / workflows/。
即“一份模块定义,按 CPU / OS / 运行空间派生多套实现“,而不是为每个平台维护一个独立仓库。
4. 值分层 + “只写差异” + 可审计
flowchart TD
MV["sys/merged_vars.yml 系统默认值"] --> ENV[".env"]
SV["values/sys_value.yml 注释模板"] --> ENV
UV["values/value.yml 客户覆盖"] --> ENV
ENV --> DC["sys/docker-compose.yaml 消费"]
SEC["~/.galaxy/sec_value.yml 密钥"] -->|运行时注入子进程环境| DC
.env = merged_vars 默认值 ⊕ values/sys_value.yml ⊕ values/value.ymlsys update生成的values/sys_value.yml是整份注释模板:保持注释即“空覆盖“,取消注释才生效,默认值不会被钉死。- 优先级明确:
value.yml(客户覆盖) >sys_value.yml(系统值) >merged_vars(默认)。 - 来源可追踪:本地化会写出实际使用的值,能回答“这个最终值是谁给的“。
5. 密钥作为一等公民:不落盘、运行时注入、诊断掩码
compose 里用 ${SEC_xxx} 占位;gops run start 运行时从 ~/.galaxy/sec_value.yml(或 ./.galaxy/sec_value.yml)读取,只注入 docker compose 子进程环境,不写 .env、不入库;gops run diagnose(docker compose config)注入的是掩码值 ********。
配置与敏感值在生命周期上被彻底分开,而不是仅靠 .gitignore 约定。
6. 交付闭环:打包 → 导入 → 重导入保值
gops sys package -> <name>-<version>.tar.gz(先 update 解析变量)
gops prj import -> 导入客户项目
gops prj reimport -> 按 ops-prj.yml 重建系统,保留 values/ 客户值
reimport 体现了核心主张:系统目录可被删除重建,但客户值永不丢失。产品升级与客户现场数据成为两个独立生命周期。
7. 单体 CLI,无历史包袱
一个 gops 二进制覆盖 mod / sys / prj,不存在 gmod / gsys 的历史分裂;文档以当前代码实现为唯一真源。
与常见工具的边界
| 工具 | 主要职责 | 与 GOps 的差异 |
|---|---|---|
| Ansible | 过程式配置与编排执行 | GOps 不执行;客户差异靠值文件而非 playbook 分支 |
| Helm | Kubernetes 包管理与模板 | GOps 跨 CPU / OS / 运行时,且含“系统 → 客户项目“对象层 |
| Terraform | 基础设施状态收敛 | GOps 不做状态收敛,面向运维交付资产 |
| docker compose | 单机声明式编排 | GOps 在其上加对象模型、打包、客户值、密钥、多模型 |
是 / 不是
是:运维能力的组织、配置、组合、交付;跨平台模块与系统的资产化;客户差异的集中管理。
不是:工作流执行引擎;配置管理 / 状态收敛工具。kind: gxl 系统的能力上限取决于 galaxy-flow / gx;kind: docker-compose 路径则把门槛降到“只要一台装了 docker 的机器“。
相关文档
GOps 改进方向
本文给出一份按“性价比“排序的改进清单。排序原则:高价值 ≠ 功能多,而是“把’靠人记住’的部分交给工具“。 因此优先做“把事后才发现变成事前就知道“的项,最后才考虑“再多一种后端 / 再多一套模板“。
“对应问题“一列指向 定位与价值 中的问题 1 / 2 / 3。每条都附现状证据,便于核对。
Tier 1:直接打痛点、代价低、收益高
| 改进点 | 对应问题 | 现状(代码证据) | 价值 |
|---|---|---|---|
① gops sys new --model <modelsdt>(非交互选型) | 采用前置 | ia_model_std() 只能交互;自动选型靠 TEST_MODE=1 这种 hack | 解锁 CI / 自动化,实现极小 |
② gops sys check 部署前校验 | 问题 1(后果严重) | sys localize 只导出 .env(export_env_file),不校验 sys/docker-compose.yaml 里的 ${VAR} 是否都有定义 | 把“上线才炸“提前到“localize 前报错“ |
| ③ 密钥缺失 fail-fast | 问题 1(容易遗忘) | run_compose_cmd 无脑 load_sec_dict() 注入,不校验被引用的 ${SEC_x} 是否存在 | 挡住“空密码静默上线“ |
④ gops sys diff | 问题 1(容易遗忘) | 有值来源追踪(_used.json),但没有“客户值 vs 系统默认“的差异视图 | 一眼看清“改了哪些、哪些还是默认“ |
这四条是同一主题:把“事后才发现“变成“事前就知道“——正是问题 1 的解药。
Tier 2:交付闭环与审计
| 改进点 | 对应问题 | 现状(代码证据) | 价值 |
|---|---|---|---|
| ⑤ 锁文件 / manifest | 问题 1、2(记录保值) | merged_vars.yml 已入库,但未记录系统版本 / 模块版本 / 值哈希 | “部署的是哪一版、用了什么值“可复现,回滚有依据 |
| ⑥ 轻量漂移报告 | 问题 1 | status / diagnose 不比对“值文件改动 vs 已生成的 .env“ | 报“值变了但没重新 localize“,不必做完整 reconcile |
⑦ values/ 提交检查(gops prj doctor 或 CI --check) | 问题 1 | 无,全靠 git 纪律(定位页「边界」已承认) | 把“靠纪律“补成“靠工具提醒“ |
⑤⑥⑦ 的共同作用:把“记录与保值“从靠纪律变成靠工具提醒。
Tier 3:战略级(大投入,决定上限)
| 改进点 | 对应问题 | 现状 | 价值 |
|---|---|---|---|
⑧ 多形态脚手架 gops sys export --form host / k8s / compose | 问题 3 | 一个 System 只绑一个 ModelSTD + kind | 降低“同能力写三遍“的成本,哪怕只生成骨架 + 提示 |
⑨ 可选收敛(仅 docker-compose / k8s 形态) | GitOps 缺口 | 无常驻对账组件 | 只在能声明终态的形态引入漂移检测 / 自愈,不放弃多形态 |
⑨ 是关键取舍:它补的正是 GOps 与 GitOps 的差距 里那块最短的板,同时不牺牲“覆盖不可收敛的世界“。
Tier 4:正确性 / 一致性小修(低价值但该修)
| 改进点 | 现状(代码证据) |
|---|---|
gops mod localize --value / --default 要么实现要么移除 | handle_localize 未读取这两个参数(声明未消费),文档已被迫标注“无效“ |
gops sys new 补 --debug / --log | SysNewArgs 没有 debug_log,与其他命令不一致 |
docker-compose 形态支持 --mod | run_compose_cmd 直接忽略并打印 note;可映射到 docker compose <service> |
清理 todo!() 死代码 | ModulesList::add_mod 为 todo!();若干注释、allow(dead_code) |
Tier 1 特性详述
下面把价值最高的四项(①–④)展开成可落地的设计:目标 / 现状证据 / 期望行为 / 代码落点 / 验收 / 成本。它们共享同一主题:把“事后才发现“变成“事前就知道“——也就是 问题 1 的解药。
约定:“现状证据“均以当前
galaxy-ops代码为准;“期望行为“是设计意图,落地前需再确认实现细节。
① gops sys new --model <modelsdt>:非交互选型
目标:让 sys new 能在 CI / 脚本中无人值守创建系统,不再只能靠人肉点菜单。
现状证据
app/gops/commands/sys_cmd.rs::SysCommandHandler::handle_new在kind = gxl分支调用Self::ia_model_std()?走交互选择。SysNewArgs只有name与kind,没有model;非交互只能靠TEST_MODE环境变量(ia_model_std/ia_kind内部特判)这种测试后门。
期望行为
SysNewArgs新增--model <modelsdt>(取值须属于ModelSTD::support(),如x86-ubt22-k8s)。- 给定
--model时跳过ia_model_std,直接SysOperator::make_new(&prj, name, model);未给定且非TEST_MODE时保持现有交互。 --model与--kind docker-compose互斥:compose 系统没有ModelSTD,组合出现时报错。--model非法时立即非 0 退出,并在 stderr 列出支持项。
代码落点
SysNewArgs加字段;handle_new中args.model()优先于ia_model_std()。- 顺带补
--debug / --log(即 Tier 4 那项),让configure_dfx_logging与其他命令一致。
验收
- 非 TTY 下
gops sys new --name demo --model x86-ubt22-k8s成功生成系统,无Select提示。 --model bogus退出码非 0,stderr 含支持列表。- 回归:无参数 + 真 TTY 时仍弹出交互选择。
成本 / 风险:S。低风险;注意 --model × --kind 的互斥校验。
② gops sys check:部署前变量校验
目标:在 localize 之后、start 之前,把“上线才炸“的未定义变量提前成一条明确报错。
现状证据
src/system/operator.rs::SysOperator::localize只把合并后的值无条件写入<sys>/.env(project::export_env_file(options.evaled_value(), env_path)),不校验sys/docker-compose.yaml里引用的${VAR}是否都有定义。- 缺失时
docker compose仅打印The "X" variable is not set. Defaulting to a blank string.然后带空值继续——正是“后果严重“的典型现场。
期望行为
- 新增只读命令
gops sys check:扫描系统内 compose 文件(sys/docker-compose.{yaml,yml}等)的插值占位- 形态:
${VAR}、${VAR:-default}、${VAR-default}、$VAR;带:-/-默认值的视为可选; - 其余必须在“合并值字典(∪ 生成的
.env)“中存在; - 输出缺失清单(
文件:行号 变量名),有缺失即非 0 退出。
- 形态:
- 同逻辑以软校验接入
sys localize(默认仅告警;--strict时失败),避免破坏既有流程。 kind: gxl系统跳过变量校验。
代码落点
- 直接复用
SysOperator::localize里已算出的options.evaled_value()(合并后的OriginDict),无需另建变量解析。 - 只需一个轻量 compose 插值扫描器(正则即可),与
src/project.rs::export_env_file同族。 - 与
diagnose(compose_subcommand→docker compose config)的区别:check是不依赖 docker 的静态校验,能在无 docker 的 CI 机器上运行。
验收
- 造一个引用
${UNDEFINED}的 compose:check非 0 并指名到该行;在values/sys_value.yml补上后check通过。 ${OPTIONAL:-1}不被判为缺失。
成本 / 风险:S–M。风险在 compose 插值语法细节($$ 转义、.env 与 shell 语义差异)——须对照官方文档,宁可漏报不可误报。
③ 密钥缺失 fail-fast
目标:挡住“空密码静默上线“。
现状证据
app/gops/commands/run_cmd.rs::RunCommandHandler::run_compose_cmd无脑orion_sec::load_sec_dict()后sec_env_pairs_for(cmd_name, &dict)全量注入子进程环境,不检查 compose 文件里实际引用的${SEC_xxx}是否都在sec_dict中。sec_env_pairs_for已知diagnose需要掩码(SECRET_MASK),说明“密钥注入“这一层已成型,只差一个“存在性“前置校验。
期望行为
- 启动前交集校验:扫描 compose 的
${SEC_*}占位,逐一确认存在于sec_dict;缺失则在真正启动之前报错,列出变量名与来源文件(不回显值)。 - 提示语指向
~/.galaxy/sec_value.yml(或./.galaxy/sec_value.yml)补键,但不得回显文件内容或密钥值。 diagnose保持只读可运行:缺密钥时仅告警(不阻断诊断)。
代码落点
- 与 ② 共用占位扫描器,仅筛选
SEC_前缀。 - 在
run_compose_cmd注入密钥之前插入ensure_secrets_present(compose_files, &sec_dict)即可。
验收
- compose 引用
${SEC_DB_PASSWORD}而sec_value.yml无该键:start非 0,且未真正执行docker compose up。 - 补键后
start正常;diagnose全程掩码。
成本 / 风险:S。风险:与 ② 共用扫描器,需保证只读、零副作用。
④ gops sys diff:客户值 vs 系统默认
目标:直打“容易遗忘“——一眼看清“改了哪些、哪些还是默认“。
现状证据
- 已有值来源追踪:本地化写出
_used.json(const_vars.rs::USED_JSON)与可读版.used_value.yml(USED_READABLE_FILE);src/project.rs::mix_used_value会把 used ⊕ mod ⊕ global 合并。 - 但没有“客户值 vs 系统默认“的差异视图;操作员只能肉眼比对
values/与sys/merged_vars.yml。
期望行为
gops sys diff [--format table|yaml] [--only-changed]:以sys/merged_vars.yml的system:段为基线,逐项对values/sys_value.yml⊕values/value.yml⊕ 实际.env做对比,标注:=未改(取默认)、!已覆盖、+客户新增键、-系统已删但客户仍写、~类型/格式变化;- 每项附来源层(优先级
value.yml>sys_value.yml>merged_vars)。
- 可选
--since <git-ref>:展示相对某提交的值变化(借 git 历史)。 - 纯读命令,不改任何文件。
代码落点
- 基线取
merged_vars.yml的system:段 + 模块默认;覆盖层取values/。 - 若当前合并(
mix_used_value)未保留“哪一层给的“信息,需要先让合并结果带上来源(不改变落盘格式)。
验收
- 默认值 + 一处覆盖:
diff仅把该一处标为!,其余标=。 - 删除一个客户键:显示
-(已回落默认),而非静默。
成本 / 风险:M。风险:需要“默认层“与“覆盖层“同时可见,可能触及值的合并表示(但不动落盘格式)。
后续(Tier 2 / 3)
⑤ 锁文件 / manifest、⑥ 轻量漂移报告、⑦ values/ 提交检查、⑧ 多形态脚手架、⑨ 可选收敛,留待下一轮展开。其中 ⑧ 的一部分已兑现:gops mod new 现已为 x86-ubt22-k8s 生成 Helm chart 脚手架(见 模块维护器)。
如果只做三件事
gops sys new --model—— 解锁 CI / 自动化,门槛最低。gops sys check部署前校验 —— 变量 + 密钥占位双校验,直打“后果严重“。gops sys diff—— 直打“容易遗忘“,且能作为对外卖点。
这三条合起来,正好把问题 1 的三个症状(时常修改 / 容易遗忘 / 后果严重)各自对应上一个可交付的功能,且都不动核心架构。
一个判断
按定位页的逻辑,高价值 ≠ 覆盖更多。所以 ①–⑦ 排在前面,把“再多一种部署后端““再写一套模板“这类排在最后——后者只会扩大覆盖,不会降低遗忘与事故。
说明:本文是改进建议,不是当前能力的描述;每条“现状“以现有代码为准,落地前需再次确认实现细节。
System Operator 指南
概述
在当前 galaxy-ops 实现里,系统通过 gops sys 管理,不存在独立的 gsys CLI。
System 是模块之上的组合层。它负责:
- 维护系统模型定义(含部署类型
kind) - 维护模块列表(GXL 类型)
- 维护系统级设置和值
- 生成
.env等本地化产物 - 提供下载、安装、启动、停止、状态、诊断等系统操作入口
当前命令
# gops sys —— 定义 / 交付 / 工件
gops sys new --name <name> [--kind gxl|docker-compose]
gops sys update [--force]
gops sys package [--force] [--output <path>] [--full]
gops sys localize [--mod <module>] [--only]
gops sys setting --init
gops sys check
# gops run —— 运行时运维(在环境里落地/运行)
gops run download [--mod <module>] [--env <env>]
gops run install [--mod <module>] [--env <env>]
gops run uninstall [--mod <module>] [--env <env>]
gops run start [--mod <module>] [--env <env>]
gops run stop [--mod <module>] [--env <env>]
gops run status [--mod <module>] [--env <env>]
gops run diagnose [--mod <module>] [--env <env>]
部署类型(kind)
sys/sys_model.yml 的 kind 字段决定 gops run 的行为(kind 缺省时按 gxl 处理,兼容 1.2.0 及更早的系统):
-
gxl:部署命令委托外部gx执行,要求sys/workflows/operators.gxl与可用的gx。映射为gx run -e <ENV> -d <N> [--cmd-arg <MOD>] <cmd>;gx取自$HOME/bin/gx,最低版本0.13.0。 -
docker-compose:部署命令直接映射到docker compose,无需gx(--mod参数会被忽略):gops sys ...docker compose ...downloadpullinstallcreatestartup -dstopstopuninstalldownstatuspsdiagnoseconfig
创建系统
gops sys new --name web-stack # 不指定 --kind:交互式选择部署类型,选 gxl 后再选择系统型号
gops sys new --name gateway --kind docker-compose # 纯 compose(无型号)
--kind 缺省时会在终端交互式选择部署类型(TEST_MODE 下直接按 gxl 处理);gxl 还需要再交互选择 ModelSTD。
两种类型生成的结构不同,见 目录结构。
关键文件
sys-prj.yml:系统对象根配置sys/sys_model.yml:系统模型定义(name/model(gxl 必填)/kind/vender)sys/mod_list.yml:模块列表(GXL;纯 compose 可省略)sys/setting/vars.yml:系统设置变量定义(源)sys/setting/list.yml:按模块的本地化列表(可选)sys/merged_vars.yml:聚合变量(sys update生成:模块变量 ⊕ 系统变量,需入库)sys/workflows/operators.gxl:系统级工作流(GXL)values/sys_value.yml:值文件(sys update生成注释模板,取消注释即覆盖)values/value.yml:额外覆盖层(适合入库的客户覆盖)sys/docker-compose.yaml:系统级 compose 定义(用${VAR}占位;放在系统根(旧布局)仍受支持).env:sys localize生成的非密钥配置(供 compose 消费)
值 / 本地化流程
gops sys update -> sys/merged_vars.yml(系统默认值)+ values/sys_value.yml(注释模板)
gops sys localize -> .env = merged_vars 默认值 ⊕ values/sys_value.yml ⊕ values/value.yml
两个值文件都是可选、可部分覆盖:只写需要修改的项,其余取系统默认值。保持注释模板原样时等价于空覆盖。
sys localize 默认总是先解析变量(等价于先跑一次 update,含解析/下载模块),再生成 .env;--only 跳过解析(用现有 sys/merged_vars.yml,缺失则明确报错)。
密钥
密钥不写入 .env:在 sys/docker-compose.yaml 里用 ${SEC_xxx} 占位,gops run start 运行时从 ~/.galaxy/sec_value.yml(或当前目录 ./.galaxy/sec_value.yml)读取并注入子进程环境(key 会归一化为大写并加 SEC_ 前缀)。gops run diagnose(docker compose config)只读校验,注入的是掩码值 ********。详见 galaxy-ops 仓库的 src/system/README.md。
常见流程
更新系统本地引用
gops sys update
gops sys update --force
本地化系统
gops sys localize # 默认先解析变量(等价于先 update),再生成 .env
gops sys localize --only # 只 localize,不解析/下载模块(用现有 merged_vars.yml)
gops sys localize --mod nginx
打包交付
gops sys package # 先 update 再打包 → ../<name>-<version>.tar.gz
初始化系统设置
gops sys setting --init
执行系统操作
gops run start --env default
gops run status --env default
与模块和项目的关系
gops mod new -> 创建模块
gops sys new -> 组合模块形成系统
gops prj new -> 创建运维项目
gops prj import -> 把系统导入项目
gops prj reimport -> 按 ops-prj.yml 重新导入(保留 values/)
gops prj update -> 同步项目本地引用
导入到运维项目后,项目值放在 <project>/values/<system>/。在项目内的系统目录执行 gops sys localize / gops sys update 时,会依据上层 ops-prj.yml 直接使用该项目值目录,不依赖 <sys>/values 符号链接是否完整。
现实边界
gxl系统的工作流执行仍依赖gxdocker-compose系统只依赖本机docker compose,不需要gx
sys_model.yml 说明
sys_model.yml 是 System 对象的核心定义文件,位于:
sys/sys_model.yml
字段
gxl 系统实际生成的内容(kind 为默认值 gxl 时会被省略,不写入文件):
name: web-stack # 系统名(必填)
model: arm-mac14-host # 目标型号(kind=gxl 必填;docker-compose 无型号)
vender: '' # 供应商标记(可选)
字段含义:
name:系统名(必填)kind:部署类型:gxl(默认)|docker-compose;gxl是默认值,序列化时省略model:目标型号(kind=gxl必填,写入文件;docker-compose无型号,字段省略)vender:供应商标记(可选)
纯 docker-compose 系统的实际内容示例:
name: gateway
kind: docker-compose
vender: ''
kind
kind 决定 gops sys 的行为:
kind | 说明 |
|---|---|
gxl(默认) | 模块式系统,部署命令委托外部 gx 执行 |
docker-compose | 声明式 compose 系统,部署命令直接映射到 docker compose(无需 gx) |
kind缺省时按gxl处理(兼容 1.2.0 及更早的系统)kind只在此文件里声明,不要写进sys-prj.yml
与其它文件的关系
sys/mod_list.yml:模块列表(仅gxl需要)sys/setting/vars.yml:系统设置变量定义(源)sys/merged_vars.yml:gops sys update解析出的聚合变量(需入库)
在流程中的作用
gops sys new会初始化它;--kind docker-compose会写入kind: docker-compose且不生成 GXL 骨架gops run的部署命令按kind分派gops prj import/prj reimport用它确定系统名与类型
如果要核对字段细节,优先以当前仓库代码和 gops sys new 的生成结果为准,而不是旧版文档示例。
System 示例:多模块系统
这里给出一个和当前实现一致的最小示例流程,用来说明 System 如何组合多个模块。
1. 创建模块
gops mod new --name gateway
gops mod new --name user-service
gops mod new --name postgres
2. 创建系统
gops sys new --name microservice-stack
cd microservice-stack
3. 维护系统模块列表
在 sys/mod_list.yml 中把需要的模块加入系统。
4. 初始化系统设置(可选)
gops sys setting --init
5. 解析变量并本地化
gops sys update # 解析变量 -> sys/merged_vars.yml,并生成 values/sys_value.yml(注释模板)
gops sys localize # 生成 .env(默认先解析变量,等价于先 update)
如果只想处理某个模块:
gops sys localize --mod gateway
值文件采用“只写差异”的风格:
# values/sys_value.yml —— 整份默认是注释,取消注释即覆盖
HTTP_PORT: 8081
也可以在同目录放 values/value.yml 作为额外覆盖层(优先级最高,适合入库的客户覆盖)。
6. 打包交付
gops sys package # -> ../microservice-stack-<version>.tar.gz
7. 在运维项目中使用(客户差异)
cd ..
gops prj new --name customer-a
cd customer-a
gops prj import --path ../microservice-stack-0.1.0.tar.gz
cd microservice-stack
gops sys localize # 值取自 <project>/values/microservice-stack/
8. 执行系统操作
gops run download --env default
gops run install --env default
gops run start --env default
gops run status --env default
说明
这个示例强调的是当前实现中的责任边界:
- 模块定义在
gops mod - 系统组合在
gops sys - 客户导入和交付在
gops prj
System 示例:纯 docker-compose 系统
纯 compose 系统不组合模块、不使用 GXL 工作流,gops sys 直接驱动本机 docker compose。
1. 创建系统
gops sys new --name gateway --kind docker-compose
cd gateway
生成的是精简结构(无 _gal/、mod_list.yml、workflows/、setting/list.yml),见 目录结构。
sys/sys_model.yml:
name: gateway
kind: docker-compose
vender: ''
2. 编写 compose 与变量定义
sys/docker-compose.yaml 用 Docker Compose 原生 ${VAR} 占位(sys new 会生成一份可修改的模板):
services:
app:
image: ${SERVICE_IMAGE}
ports:
- "${SERVICE_PORT}:80"
deploy:
replicas: ${REPLICAS}
compose 文件默认位于 sys/,也兼容放在系统根(旧布局)。无论文件在哪,compose 项目目录都锚定系统根,${VAR} 由系统根的 .env 注入。
非密钥变量在 sys/setting/vars.yml 的 system: 段声明(源定义,随系统版本化):
system:
- name: SERVICE_IMAGE
value: nginx:alpine
- name: SERVICE_PORT
value: 8080
- name: REPLICAS
value: 1
密钥不要写在这里:在 compose 里用 ${SEC_xxx} 占位,运行时由 gops run start 从 ~/.galaxy/sec_value.yml(或当前目录 ./.galaxy/sec_value.yml)注入(不落盘)。
services:
db:
environment:
POSTGRES_PASSWORD: ${SEC_POSTGRES_PASSWORD}
~/.galaxy/sec_value.yml(不在项目里、不入库):
postgres_password: "your-secret"
key 会归一化为大写并加 SEC_ 前缀:postgres_password → SEC_POSTGRES_PASSWORD。
3. 生成 .env
gops sys localize # 默认先解析变量(等价于先 update),再生成 .env
cat .env
规则:
.env = sys/merged_vars.yml 默认值 ⊕ values/sys_value.yml ⊕ values/value.yml
values/sys_value.yml是sys update生成的注释模板:取消注释要覆盖的项即可,其余取默认值。values/value.yml是更高优先级的覆盖层。
例如只想改端口与副本数:
# values/sys_value.yml
SERVICE_PORT: 9090
REPLICAS: 3
.env 只包含非密钥配置,随时可以用 docker compose config 校验。
4. 部署
kind: docker-compose 下,部署命令映射到 docker compose:
gops run diagnose # docker compose config(密钥以 ******** 掩码注入)
gops run download # docker compose pull
gops run install # docker compose create
gops run start # docker compose up -d(密钥注入子进程环境)
gops run status # docker compose ps
gops run stop # docker compose stop
gops run uninstall # docker compose down
kind: docker-compose 下 --mod 参数会被忽略(没有模块概念);--env 仍可传入。
5. 交付给客户(运维项目)
gops sys package # 先 update 再打包 -> ../gateway-<version>.tar.gz
cd ..
gops prj new --name customer-a
cd customer-a
gops prj import --path ../gateway-0.1.0.tar.gz
cd gateway
gops sys localize # 使用 <project>/values/gateway/ 下的客户值
gops run start
客户差异写在 <project>/values/gateway/(例如 value.yml)。在项目内的系统目录执行 gops sys localize / sys update 时,会依据上层 ops-prj.yml 直接使用该项目值目录。
System 目录结构
本文档以当前 gops sys new 的真实生成结果为准。系统有两种部署类型,目录结构不同。
GXL 系统(默认)
gops sys new --name <name>
<system-root>/
├── .gitignore
├── sys-prj.yml # 系统根配置
├── version.txt
├── _gal/ # GXL 工程目录
│ ├── adm.gxl
│ ├── project.toml
│ └── work.gxl
├── values/ # 值文件目录(本地化输入)
└── sys/
├── .gitignore
├── sys_model.yml # name / model / vender(kind 缺省 = gxl)
├── docker-compose.yaml # sys new 默认生成的 compose 定义(用 ${VAR} 占位)
├── mod_list.yml # 模块列表
├── workflows/
│ └── operators.gxl
└── setting/
├── list.yml
└── vars.yml
纯 docker-compose 系统
gops sys new --name <name> --kind docker-compose
<system-root>/
├── .gitignore
├── sys-prj.yml
├── version.txt
└── sys/
├── sys_model.yml # name / kind: docker-compose / vender
├── docker-compose.yaml # 系统级 compose 定义
└── setting/
└── vars.yml
compose 类型不生成 _gal/、values/、mod_list.yml、workflows/、setting/list.yml。
compose 文件默认位于 sys/,gops sys 按 sys/compose.{yaml,yml} → sys/docker-compose.{yaml,yml} → 系统根同名文件的顺序查找。无论文件在哪,compose 项目目录都锚定系统根(项目名 = 根目录名,相对挂载路径与 .env 均相对系统根)。把文件放在系统根(旧布局)仍受支持:此时 gops 不加 -f,交由 docker 自动发现(docker-compose.override.yml 自动合并、COMPOSE_FILE 环境变量继续生效);sys/ 布局下由 gops 显式合并 <sys>/<stem>.override.{yaml,yml}。
运行时生成的文件
gops sys update / gops sys localize 会在需要时补齐:
sys/merged_vars.yml:聚合变量(模块 ⊕ 系统),需入库values/sys_value.yml:值文件(注释模板;取消注释需要覆盖的项即可)values/setting/mod_value.yml:本地化辅助值文件.env:sys localize导出的非密钥配置(供 compose 消费)
可选文件
下列文件缺失时按空处理,纯 compose 系统可以完全不提供:
sys/mod_list.ymlsys/workflows/sys/setting/list.yml
现实说明
旧文档里常见的这些内容,不应再视为当前最小骨架的一部分:
sys/vars.ymlsys/<model>/mods/(由gops sys update生成,不是初始结构)test_res/- 独立
gsysCLI 生成目录
System 文件组织
系统围绕下面几类文件组织。其中 _gal/、mod_list.yml、workflows/、setting/list.yml 只属于 GXL 类型(见 目录结构)。
根目录文件
sys-prj.yml:系统根配置version.txt:版本标记.gitignore
_gal/(仅 GXL 系统)
adm.gxl:管理流程入口work.gxl:执行流程入口project.toml:GXL 工程配置
sys/
sys_model.yml:系统模型定义(name/model/kind/vender)docker-compose.yaml:系统级 compose 定义(sys new默认生成,用${VAR}占位;放在系统根(旧布局)仍受支持)mod_list.yml:模块列表定义(GXL;可选)merged_vars.yml:聚合变量(sys update生成,需入库)setting/list.yml:设置列表(可选)setting/vars.yml:设置变量定义(源)workflows/operators.gxl:系统操作工作流(GXL;可选)
values/(本地化输入)
sys_value.yml:值文件。sys update首次生成的是注释模板(可用变量全部以注释列出),取消注释需要覆盖的项即可;保持注释的项取系统默认值。value.yml:额外覆盖层,优先级最高(适合入库的客户覆盖)。setting/mod_value.yml、<mod>/mod_value.yml:本地化辅助值文件。
.env
gops sys localize 生成的非密钥配置(KEY=VALUE),供 docker compose 消费。密钥不写入 .env。compose 项目目录锚定系统根,因此 .env 位于系统根(而非默认的 sys/)。
文件职责与本地化
.env = sys/merged_vars.yml 默认值 ⊕ values/sys_value.yml ⊕ values/value.yml
后两者都是可选、可部分覆盖:只写需要修改的项,其余取系统默认值。
sys_model.yml:描述系统本身(含kind),属于系统对象定义层mod_list.yml:描述系统包含哪些模块,属于系统组合层setting/vars.yml/setting/list.yml:系统设置层merged_vars.yml:已解析的聚合变量(系统默认值的来源)operators.gxl:工作流层
当前 CLI 与文件关系
gops sys new:初始化文件骨架(按kind决定是否生成 GXL 骨架)gops sys update:解析变量 →sys/merged_vars.yml,并初始化values/gops sys package:先update再打包为<name>-<version>.tar.gzgops sys localize:按上述规则生成.envgops sys setting --init:初始化系统设置相关文件
不再使用的旧说法
SYS_BIN = "gsys"/MOD_BIN = "gmod"(GXL 模板中已改为"gops sys"/"gops mod")- “系统级 vars.yml 必然位于 sys/ 根目录”
- “sys/mods/ 是固定初始结构”(模块现在按目标模型分组到
sys/<model>/mods/<mod>/,由gops sys update生成) - “系统变量文件叫
sys/sys_vars.yml”(已重命名为merged_vars.yml,旧名仅作读取兼容)
System 命名约定
系统目录
系统通过下面命令创建:
gops sys new --name <name> [--kind gxl|docker-compose]
建议:
- 使用小写字母
- 单词之间使用连字符
- 避免空格和中文目录名
示例:
web-stackcustomer-edgedb-core
文件名
当前实现里关键文件名是固定的:
sys-prj.ymlsys/docker-compose.yamlsys_model.ymlmod_list.ymlmerged_vars.ymloperators.gxllist.ymlvars.ymlvalues/sys_value.yml、values/value.yml
这些名字最好不要随意改动,否则会影响 gops sys 的加载逻辑。
sys_vars.yml是merged_vars.yml的旧名(1.2.0 及更早),当前仅作读取兼容。
kind 取值
sys/sys_model.yml 的 kind 只使用这两个值(省略时按 gxl):
gxldocker-compose
模块名
系统命令里如果使用:
gops sys localize --mod <module>
gops run start --mod <module>
这里的 <module> 应与 mod_list.yml 中声明的模块名一致。
环境名
系统操作命令支持:
--env <env>
当前默认值是:
default
建议环境名保持简单稳定,例如:
defaultdevstagingprod
System 常见问题
1. gops sys new 卡在选择系统型号
原因:
kind: gxl的系统会交互选择ModelSTD
建议:
- 正常在交互终端选择
- 自动化测试场景可设置
TEST_MODE=1 - 不需要型号的纯 compose 系统用
gops sys new --kind docker-compose(不询问型号)
2. gops sys setting --init 没有生成预期文件
确认点:
- 当前目录必须是系统根目录
sys/setting/目录是否存在
3. gops sys localize 失败
常见原因与报错:
系统变量未解析:缺少 .../sys/merged_vars.yml→ 先执行gops sys update解析变量;或去掉--only,让localize自动先update。sys_model.yml缺失- 值文件内容不是合法 YAML (提示:全注释 / 空文件会被视为空覆盖,不会报错)
建议:
gops sys localize --debug 2
先打开调试输出定位是哪一层配置缺失。
4. 值文件写了却没生效
确认点:
values/sys_value.yml里对应的行已取消注释——sys update生成的是整份注释模板,保持注释等价于空覆盖- 优先级:
values/value.yml>values/sys_value.yml>sys/merged_vars.yml的系统默认值 - 在运维项目内执行时,值来自
<project>/values/<system>/(依据上层ops-prj.yml解析),而不是系统自带的<sys>/values
5. 日志出现 unexpanded variable in localize path 且本地化被跳过
原因:sys/setting/list.yml 里的路径模板引用了未设置的变量(常见是 ${GXL_PRJ_ROOT})。
说明:
GXL_PRJ_ROOT由gops进程启动时按当前目录向上查找_gal/project.toml设置一次- 路径里仍残留
${...}时会告警并跳过;不会再创建字面量${...}目录
建议:确认是在系统目录内执行,且该目录(或其上层)存在 _gal/project.toml。
6. download/install/start 等系统命令失败
分两种情况(由 sys/sys_model.yml 的 kind 决定):
kind: gxl:最终依赖系统工作流和gx- 先确认
sys/workflows/operators.gxl存在 - 再确认
gx可执行:gops使用$HOME/bin/gx,且要求版本 >=0.13.0 - 实际映射为
gx run -e <env> -d <debug> [--cmd-arg <mod>] <cmd>,检查--env与--mod传参
- 先确认
kind: docker-compose:直接调用本机docker compose- 确认
docker compose可用 - 确认
.env已生成(gops sys localize) --mod会被忽略(纯 compose 系统没有模块)
- 确认
7. docker compose 报变量未定义
确认点:
- 已执行
gops sys localize生成.env .env位于系统根;compose 文件默认在sys/(项目目录锚定系统根,${VAR}由系统根的.env注入)- 密钥类变量用
${SEC_xxx}占位,由gops run start从~/.galaxy/sec_value.yml注入;直接用docker compose up不会自动注入密钥
8. 文档和目录树不一致
处理原则:
- 以当前
gops sys new真实生成结果为准 - 以当前仓库代码为准
- 不再使用旧版
gsys文档作为依据
Module Operator 指南
概述
在当前 galaxy-ops 实现里,模块通过 gops mod 管理,不存在独立的 gmod CLI。
Module 是最小可复用运维单元。它负责沉淀:
- 模块变量
- 模块依赖
- 模块构件
- 模块工作流
- 模块本地化输出
模块本身不直接面向客户交付,它先被组合成 System,再由 Ops Project 导入和交付。
当前命令
gops mod example
gops mod new --name <name>
gops mod update
gops mod localize [--value <file> | --default]
典型工作流
1. 创建模块
gops mod new --name nginx
当前实现会在目标目录下生成类似结构:
nginx/
├── .gitignore
├── version.txt
├── mod-prj.yml
├── _gal/
│ ├── adm.gxl
│ ├── project.toml
│ └── work.gxl
└── mod/
├── arm-mac14-host/
│ ├── vars.yml
│ ├── _gal/work.gxl
│ ├── spec/
│ │ ├── artifact.yml
│ │ └── depends.yml
│ └── workflows/
│ └── operators.gxl
├── x86-ubt22-host/ # 结构同 arm-mac14-host
└── x86-ubt22-k8s/ # 结构同 arm-mac14-host
注意:
- 当前骨架一定会生成
mod-prj.yml - 当前骨架会按支持的
ModelSTD生成mod/<model>/...;gops mod new默认生成三个模型目录:arm-mac14-host、x86-ubt22-host、x86-ubt22-k8s - 每个
mod/<model>/下会直接生成vars.yml、spec/artifact.yml、spec/depends.yml、workflows/operators.gxl与_gal/work.gxl setting.yml不在gops mod new的初始骨架中(仅gops mod example会带);初始模板比较轻,后续通过 update / localize / 手工补充逐步完善
2. 更新模块本地引用
gops mod update
gops mod update --force 2
update 主要用于同步依赖、本地引用和相关生成内容。--force 支持不同强度的覆盖策略。
3. 本地化模块
gops mod localize
localize 会读取模块根目录下 values/<model>/ 里的值文件(sys_value.yml、mod_value.yml)生成本地化结果(mod/<model>/local/),用于后续系统组合或实际交付。
说明:
gops mod localize虽然声明了--value/--default参数,但当前实现并未消费它们,实际值来自values/<model>/。
模块在整体分层中的位置
gops mod -> 定义和维护模块
gops sys -> 组合模块形成系统
gops prj -> 导入系统形成具体交付项目
galaxy-flow -> 执行工作流
文档索引
Module Operator 开发流程
当前开发入口
模块开发从 gops mod 开始,而不是 gmod。
gops mod new --name <module-name>
推荐流程
1. 创建模块骨架
mkdir demo-work && cd demo-work
gops mod new --name postgresql
cd postgresql
2. 补齐模块模型内容
先检查 mod/ 下生成的模型目录(gops mod new 默认生成三个):
mod/
├── arm-mac14-host/
├── x86-ubt22-host/
└── x86-ubt22-k8s/
每个模型目录已包含以下文件,按需修改即可:
vars.ymlspec/artifact.ymlspec/depends.ymlworkflows/operators.gxl_gal/work.gxl
setting.yml 不在 gops mod new 的初始骨架中,需要自定义本地化行为时再手工补充。
3. 更新本地引用
gops mod update
需要强覆盖时:
gops mod update --force 2
4. 本地化验证
先准备好值文件(gops mod update 会在模块根生成 values/<model>/ 下的模板):
values/
└── x86-ubt22-k8s/
├── sys_value.yml
└── mod_value.yml
然后执行本地化:
gops mod localize
本地化会读取 values/<model>/ 生成 mod/<model>/local/。
--value/--default参数虽然可用,但当前gops mod localize实现并未消费它们;实际值始终来自values/<model>/。
5. 进入系统组合
模块完成后,通常不直接交付,而是继续:
gops sys new --name demo-system
把模块纳入系统对象中。
调试参数
当前模块命令统一支持调试参数:
gops mod new --name nginx --debug 1
gops mod update --debug 2 --log debug
gops mod localize --debug 3
现实边界
当前实现里,模块开发流程要注意几点:
gops mod new生成的是模板骨架,业务文件仍需按需修改localize依赖values/<model>/下的值文件和vars.yml变量定义,先补齐vars.yml再做本地化- 模块是系统的输入,不是交付终点
- 执行类工作流能力最终仍由
galaxy-flow/gx承担
Module Operator 配置说明
本文档只描述当前 galaxy-ops 代码中已经存在的模块配置对象和文件名。
核心文件
创建模块后,当前实现会生成这些关键文件:
<module-root>/
├── .gitignore
├── mod-prj.yml
├── version.txt
├── _gal/
│ ├── adm.gxl
│ ├── project.toml
│ └── work.gxl
└── mod/
└── <model>/
├── vars.yml
├── _gal/work.gxl
├── spec/
│ ├── artifact.yml
│ └── depends.yml
└── workflows/
└── operators.gxl
运行 gops mod update / gops mod localize 后,模块目录还会出现这些约定目录或文件:
mod/<model>/local/:gops mod localize生成的本地化输出mod/<model>/_used.json:gops mod localize生成的实际使用值values/<model>/sys_value.yml、values/<model>/mod_value.yml:值文件(注意在模块根values/下,不在mod/<model>/里)values/<model>/.used_value.yml:本地化时导出的可读值mod/<model>/setting.yml:本地化行为设置(可选;gops mod new不生成,gops mod example或手工补充时才有)
这些名字来自当前代码常量:
spec/artifact.ymldepends.ymlsetting.ymlvalues/workflows/local/
文件职责
mod-prj.yml
模块项目根配置。它是模块对象的入口配置文件,ModOperator::load / save 都围绕它工作。
_gal/adm.gxl
管理类工作流入口。
_gal/work.gxl
执行类工作流入口。
_gal/project.toml
当前生成模板里的 GXL 工程配置文件。
mod/<model>/vars.yml
某个 ModelSTD 下的模块变量定义。当前模块骨架至少会生成这个文件。
mod/<model>/spec/artifact.yml
模块构件定义,通常用于描述下载资源、源码包或依赖包。
mod/<model>/spec/depends.yml
模块依赖定义,用于组织本地依赖、仓库依赖或附加资源。
mod/<model>/setting.yml
模块本地化行为相关设置(可选,gops mod new 不生成)。
values/<model>/
模块值文件目录(位于模块根目录下,不是 mod/<model>/values/)。gops mod update 会在此生成 sys_value.yml 与 mod_value.yml,gops mod localize 会读取它们执行本地化。
mod/<model>/workflows/
模块工作流目录,通常放模块级 operators.gxl 等流程文件。
mod/<model>/local/
模块本地化结果或局部输出目录。
ModelSTD 目录
模块目录下按模型拆分。ModelSTD 当前支持三种组合(gops mod new 会全部生成):
arm-mac14-host(CpuArch::Arm+OsCPE::MAC14+RunSPC::Host)x86-ubt22-host(CpuArch::X86+OsCPE::UBT22+RunSPC::Host)x86-ubt22-k8s(CpuArch::X86+OsCPE::UBT22+RunSPC::K8S)
模型名由 ModelSTD 决定,表示 CPU / OS / 运行空间组合(来自 CpuArch / OsCPE / RunSPC 三个枚举)。
当前配置边界
当前代码里,模块配置的真实边界是:
- 模块根配置:
mod-prj.yml - 模型级配置:
mod/<model>/...(vars.yml/spec//workflows//_gal/work.gxl) - 值文件和本地化输出:模块根
values/<model>/与模型内mod/<model>/local/ - 工作流入口:
_gal/*.gxl与workflows/operators.gxl
不要再按旧文档理解为独立 gmod 工具或多套历史模板系统。
Module Operator 参考
CLI 参考
gops mod
gops mod <COMMAND>
子命令:
examplenewupdatelocalize
gops mod new
gops mod new --name <NAME> [--debug <0..3>] [--log <level>]
gops mod update
gops mod update [--debug <0..3>] [--log <level>] [--force <0..3>]
--force 当前含义:
0:正常1:跳过确认2:覆盖文件3:强制拉取
gops mod localize
gops mod localize [--value <file>] [--default]
注意:
--value/--default参数已声明,但当前实现未消费;实际值来自模块根values/<model>/下的值文件。
目录参考
最小模块骨架
gops mod new 按支持的 ModelSTD 生成三个模型目录(arm-mac14-host / x86-ubt22-host / x86-ubt22-k8s),每个模型结构相同:
<module>/
├── .gitignore
├── version.txt
├── mod-prj.yml
├── _gal/
│ ├── adm.gxl
│ ├── project.toml
│ └── work.gxl
└── mod/
└── <model>/
├── vars.yml
├── _gal/work.gxl
├── spec/
│ ├── artifact.yml
│ └── depends.yml
└── workflows/
└── operators.gxl
运行 / 本地化后新增
<module>/
├── values/
│ └── <model>/
│ ├── sys_value.yml
│ ├── mod_value.yml
│ └── .used_value.yml
└── mod/<model>/
├── local/ # gops mod localize 输出
├── _used.json # gops mod localize 生成
└── setting.yml # 可选,非 gops mod new 生成
代码参考
当前模块相关实现主要在这些文件:
app/gops/commands/mod_cmd.rssrc/module/operator.rssrc/module/spec.rssrc/module/model.rssrc/module/refs.rssrc/module/depend.rs
术语参考
Module:模块对象ModOperator:模块对象的代码实现入口ModelSTD:模型标识,描述 CPU / OS / 运行空间组合localize:根据变量和值文件生成本地结果update_local:同步本地依赖和引用
当前限制
下面这些内容不再视为当前实现的一部分:
- 独立
gmodCLI - 旧版多工具拆分说明
- 推断型 Rust API 文档
- 未在当前代码里出现的模板系统和扩展点
Module Operator 故障排除
1. gops mod new 创建后文件很少
现象:
- 每个
mod/<model>/下只有模板文件(vars.yml/spec//workflows/operators.gxl/_gal/work.gxl) - 没有
setting.yml,也没有values/
原因:
- 当前
mod new生成的是模板骨架,不是完整业务模板 setting.yml和values/不由mod new生成
处理:
- 按需修改
mod/<model>/下的模板文件 - 执行
gops mod update生成values/<model>/值文件模板 - 需要自定义本地化行为时再手工补充
setting.yml
2. gops mod localize 失败
常见原因:
vars.yml未定义完整- 模块根
values/<model>/下的sys_value.yml/mod_value.yml缺失或结构不匹配 - 尚未执行
gops mod update,导致值文件模板未生成
建议:
gops mod update
gops mod localize --debug 2
先生成 values/<model>/ 值文件,再用 --debug 2 定位问题。
注意:
gops mod localize声明的--value/--default目前未被实现消费,值始终来自values/<model>/。
3. gops mod update 覆盖了本地内容
原因:
- 使用了较强的
--force级别
建议:
- 默认先不用
--force - 必要时先试
--force 1 - 只有明确要覆盖时再用
--force 2或3
4. 模块目录模型不符合预期
现象:
mod/下生成的模型目录和预想的平台不同
原因:
- 当前模板和
ModelSTD支持集合由代码决定,不由文档静态列死
建议:
- 以生成结果为准
- 不要继续沿用旧文档里的目标平台列表
5. 工作流无法执行
现象:
- 模块骨架存在,但后续执行工作流失败
原因:
galaxy-ops负责组织和生成- 真正的工作流执行依赖
galaxy-flow/gx
建议:
- 先确认模块和系统对象已本地化成功
- 再检查
gx是否可执行、工作流入口是否存在
配置
📖 NetAccessCtrl 简约配置指南(非开发者版)
什么是 NetAccessCtrl?
NetAccessCtrl 是一个网络访问控制模块,可以在使用orino_variate 时自动将您的网络请求重定向到更快的镜像服务器,支持认证、超时设置和代理配置。它可以帮助您:
- 🚀 加速 GitHub、GitLab 等国外服务访问
- 🔐 安全管理认证信息
- ⏱️ 控制网络请求超时时间
- 🌐 配置代理服务器
- 📝 使用环境变量动态配置
快速开始
1. 创建配置文件
在您的项目根目录创建 net-accessor_ctrl.yaml 文件:
# 基础配置示例
enable: true
units:
- rules:
- pattern: "https://github.com/*"
target: "https://mirror.ghproxy.com/"
# 可选:添加认证信息
auth:
username: "your_username"
password: "your_token"
2. 常用场景配置
GitHub 加速访问
enable: true
units:
- rules:
- pattern: "https://github.com/*"
target: "https://mirror.ghproxy.com/"
- pattern: "https://raw.githubusercontent.com/*"
target: "https://raw.ghproxy.com/"
GitLab 镜像
enable: true
units:
- rules:
- pattern: "https://gitlab.com/*"
target: "https://gitlab-mirror.com/"
NPM 包管理器加速
enable: true
units:
- rules:
- pattern: "https://registry.npmjs.org/*"
target: "https://registry.npmmirror.com/"
3. 完整配置示例
enable: true
units:
# GitHub 配置
- rules:
- pattern: "https://github.com/*"
target: "https://ghproxy.com/"
- pattern: "https://raw.githubusercontent.com/*"
target: "https://raw.ghproxy.com/"
auth:
username: "${GITHUB_USER}"
password: "${GITHUB_TOKEN}"
timeout:
connect-timeout: 30
read-timeout: 60
total-timeout: 300
proxy:
url: "http://proxy.company.com:8080"
# 其他服务配置
- rules:
- pattern: "https://api.example.com/*"
target: "https://internal-api.example.com/"
配置参数说明
基本参数
enable:true或false,是否启用网络访问控制units: 配置单元列表,每个单元包含重定向规则和配置
单元配置 (units)
每个 unit 包含:
rules: 重定向规则列表auth: 可选的认证信息(用户名和密码)timeout: 可选的超时设置proxy: 可选的代理配置
规则配置 (rules)
每个 rule 包含:
pattern: 要匹配的URL模式(支持*通配符)target: 重定向的目标地址
环境变量支持
您可以使用环境变量来动态配置,避免硬编码敏感信息:
enable: true
units:
- rules:
- pattern: "https://${GITHUB_DOMAIN:github.com}/*"
target: "https://${MIRROR_DOMAIN:ghproxy.com}/"
auth:
username: "${GITHUB_USER}"
password: "${GITHUB_TOKEN}"
proxy:
url: "${PROXY_URL:http://proxy.default:8080}"
环境变量语法:
${VARIABLE_NAME}: 使用环境变量${VARIABLE_NAME:default_value}: 使用环境变量,如果不存在则使用默认值
使用方法
1. 设置环境变量(可选)
# Linux/Mac
export GITHUB_USER="your_username"
export GITHUB_TOKEN="your_token"
export PROXY_URL="http://proxy.company.com:8080"
# Windows
set GITHUB_USER=your_username
set GITHUB_TOKEN=your_token
set PROXY_URL=http://proxy.company.com:8080
2. 将配置文件放在正确位置
- 系统级配置:
/etc/net-access.yaml - 用户级配置:
~/.config/net-access.yaml - 项目级配置:
项目根目录/net-access.yaml
3. 验证配置
配置完成后,您可以通过以下方式验证是否生效:
# 测试 GitHub 访问
curl -I "https://github.com/user/repo/releases"
# 查看是否重定向到镜像服务器
常见问题
Q: 如何添加多个镜像服务器?
A: 在 units 中添加多个配置单元,系统会按顺序尝试:
enable: true
units:
# 第一个镜像
- rules:
- pattern: "https://github.com/*"
target: "https://mirror1.github.com/"
# 备用镜像
- rules:
- pattern: "https://github.com/*"
target: "https://mirror2.github.com/"
Q: 如何设置不同的超时时间?
A: 在 timeout 部分配置:
timeout:
connect-timeout: 30 # 连接超时(秒)
read-timeout: 60 # 读取超时(秒)
total-timeout: 300 # 总超时(秒)
Q: 如何处理认证?
A: 在 auth 部分配置用户名和密码,推荐使用环境变量:
auth:
username: "${YOUR_USERNAME}"
password: "${YOUR_PASSWORD}"
Q: 配置不生效怎么办?
A: 检查以下几点:
- 确保
enable: true - 检查配置文件路径是否正确
- 验证 YAML 语法是否正确
- 检查 URL 模式是否匹配
Q: 如何配置代理?
A: 在 proxy 部分配置:
proxy:
url: "http://proxy.example.com:8080"
Q: 支持哪些通配符?
A: 目前支持 * 通配符,可以匹配任意字符序列。例如:
https://github.com/*匹配所有 GitHub 地址https://raw.githubusercontent.com/*匹配所有 GitHub 原始文件地址
配置示例合集
常用镜像服务
GitHub 全家桶加速
enable: true
units:
- rules:
- pattern: "https://github.com/*"
target: "https://ghproxy.com/"
- pattern: "https://raw.githubusercontent.com/*"
target: "https://raw.ghproxy.com/"
- pattern: "https://gist.github.com/*"
target: "https://gist.ghproxy.com/"
Python 包管理器 (PyPI)
enable: true
units:
- rules:
- pattern: "https://pypi.org/*"
target: "https://pypi.doubanio.com/"
Docker 镜像加速
enable: true
units:
- rules:
- pattern: "https://registry-1.docker.io/*"
target: "https://dockerhub.azk8s.cn/"
RubyGems 加速
enable: true
units:
- rules:
- pattern: "https://rubygems.org/*"
target: "https://gems.ruby-china.com/"
企业内部配置
内部服务映射
enable: true
units:
- rules:
- pattern: "https://external-api.company.com/*"
target: "https://internal-api.company.com/"
auth:
username: "${INTERNAL_API_USER}"
password: "${INTERNAL_API_PASSWORD}"
timeout:
connect-timeout: 10
read-timeout: 30
total-timeout: 60
多环境配置
# 开发环境配置
enable: ${ENABLE_NET_ACCESS:true}
units:
- rules:
- pattern: "https://api.${ENV:dev}.company.com/*"
target: "http://localhost:8080/"
timeout:
connect-timeout: 5
read-timeout: 15
total-timeout: 30
故障排除
检查配置文件语法
使用在线 YAML 验证工具检查配置文件语法:
- 访问 https://www.yamllint.com/
- 粘贴您的配置文件内容
- 检查是否有语法错误
常见错误及解决方案
1. 配置文件不生效
症状: 配置修改后没有效果 解决方案:
- 检查配置文件路径是否正确
- 确认
enable: true - 重启应用程序
- 检查文件权限
2. 环境变量未生效
症状: 环境变量没有正确替换 解决方案:
- 确认环境变量已正确设置
- 检查环境变量名称是否正确
- 使用
echo $VARIABLE_NAME验证环境变量 - 重新启动终端或应用程序
3. 网络连接超时
症状: 请求经常超时 解决方案:
- 增加
timeout配置中的时间值 - 检查网络连接状态
- 尝试更换镜像服务器
4. 认证失败
症状: 401 或 403 错误 解决方案:
- 检查用户名和密码是否正确
- 确认认证信息是否有权限访问目标服务
- 检查 token 是否已过期
调试技巧
启用详细日志
如果应用程序支持日志,可以启用详细日志来查看重定向过程:
# 示例:启用调试日志
export RUST_LOG=debug
your_application
手动测试重定向
使用 curl 命令手动测试重定向是否工作:
# 测试重定向
curl -v "https://github.com/user/repo"
# 查看是否被重定向到镜像服务器
检查配置加载
如果可能,查看应用程序启动时的日志,确认配置文件是否正确加载。
最佳实践
安全性建议
- 使用环境变量: 避免在配置文件中硬编码敏感信息
- 设置文件权限: 确保配置文件只有授权用户可读
chmod 600 net-access.yaml - 定期更新认证信息: 定期更换密码和访问令牌
- 使用 HTTPS: 确保所有目标地址使用 HTTPS 协议
性能优化建议
- 规则排序: 将最常用的规则放在前面
- 合理设置超时: 根据网络环境调整超时时间
- 使用就近镜像: 选择地理位置较近的镜像服务器
- 避免过度重定向: 不要配置过多的重定向层级
维护建议
- 版本控制: 将配置文件纳入版本控制(排除敏感信息)
- 文档记录: 记录配置文件的用途和变更历史
- 定期测试: 定期测试配置是否仍然有效
- 备份配置: 保留配置文件的备份
获取帮助
如果遇到问题,可以通过以下方式获取帮助:
检查清单
在寻求帮助前,请先检查:
- 配置文件语法是否正确
- 环境变量是否正确设置
- 网络连接是否正常
- 认证信息是否有效
- 目标服务器是否可访问
常见资源
- YAML 语法验证: https://www.yamllint.com/
- 环境变量设置指南: 搜索 “环境变量设置 [您的操作系统]”
- 网络连接测试: 使用
ping和curl命令测试 - 镜像服务状态: 查看镜像服务的官方状态页面
联系支持
如果以上方法都无法解决问题,请联系技术支持并提供以下信息:
- 操作系统和版本
- 配置文件内容(去除敏感信息)
- 错误信息或日志
- 重现问题的步骤
附录
配置文件模板
基础模板
# NetAccessCtrl 基础配置模板
enable: true
units:
- rules:
- pattern: "https://example.com/*"
target: "https://mirror.example.com/"
完整模板
# NetAccessCtrl 完整配置模板
enable: true
units:
- rules:
- pattern: "https://service1.com/*"
target: "https://mirror1.service1.com/"
- pattern: "https://service2.com/*"
target: "https://mirror2.service2.com/"
auth:
username: "${SERVICE1_USER}"
password: "${SERVICE1_PASSWORD}"
timeout:
connect-timeout: 30
read-timeout: 60
total-timeout: 300
proxy:
url: "${PROXY_URL:http://proxy.default:8080}"
- rules:
- pattern: "https://another-service.com/*"
target: "https://internal.another-service.com/"
# 此单元无认证、超时和代理配置
常用镜像服务器列表
| 服务类型 | 原地址 | 推荐镜像地址 |
|---|---|---|
| GitHub | https://github.com/* | https://ghproxy.com/ |
| GitHub Raw | https://raw.githubusercontent.com/* | https://raw.ghproxy.com/ |
| PyPI | https://pypi.org/* | https://pypi.doubanio.com/ |
| NPM | https://registry.npmjs.org/* | https://registry.npmmirror.com/ |
| Docker Hub | https://registry-1.docker.io/* | https://dockerhub.azk8s.cn/ |
| RubyGems | https://rubygems.org/* | https://gems.ruby-china.com/ |
注意:镜像服务地址可能会发生变化,请以最新信息为准。
快速开始总结:
- 创建
net-access.yaml文件 - 复制相应场景的配置示例
- 设置环境变量(可选)
- 放置配置文件到正确位置
- 验证配置是否生效
祝您使用愉快!🎉
GXL 帮助(对齐当前实现)
1. 最小可运行示例
mod envs {
env default {
ROOT = "./";
}
}
mod main {
flow conf {
gx.echo(value: "hello galaxy flow");
}
}
2. 常用结构
2.1 模块与继承
mod base {
flow setup {
gx.echo(value: "setup");
}
}
mod main : base {
flow conf {
gx.echo(value: "conf");
}
}
2.2 环境与 gx.vars
mod envs {
env base {
gx.vars {
APP = "galaxy";
STAGE = "dev";
};
}
env default : base;
}
2.3 flow 编排
mod main {
flow prepare {
gx.echo(value: "prepare");
}
flow deploy {
gx.echo(value: "deploy");
}
flow @release | prepare | deploy {
gx.echo(value: "release");
}
}
2.4 函数与活动
mod sys {
fn echo_tag(tag = "INFO", *msg) {
gx.echo(value: "[${tag}] ${msg}");
}
activity copy {
src = "";
dst = "";
executer = "copy_act.sh";
}
}
mod main {
flow conf {
sys.echo_tag(msg: "start");
sys.copy(src: "a.txt", dst: "b.txt");
}
}
3. 控制流
3.1 if/else if/else
flow conf {
if defined(${DEPLOY}) && ${DEPLOY} == "true" {
gx.echo(value: "deploy");
} else if ${STAGE} == "test" {
gx.echo(value: "test");
} else {
gx.echo(value: "skip");
}
}
3.2 for
flow conf {
for ${CUR} in ${DATA} {
gx.echo(value: "item=${CUR}");
}
}
4. 内置能力写法
当前实现统一是函数调用形式:
gx.cmd(cmd: "echo hi");
gx.shell(shell: "./demo.sh", out_var: "OUT");
gx.read_file(file: "./var.yml", name: "DATA");
gx.tpl(tpl: "./tpls", dst: "./out", file: "./vars.json");
不要使用旧文档中的 gx.xxx { ... } 形式。
5. gx.patch_file 快速示例
gx.patch_file(
file: "./Cargo.toml",
action: "set",
marker: "version",
value: "0.12.3"
);
对应 marker 行:
version = "0.12.2" # @gxl:set(version)
更多参数见:docs/gxl/inner/patch_file.md
变量定义
1. 赋值
flow conf {
ONE = "one";
SYS_A = { MOD1: "A", MOD2: "B", MOD3: 1, MOD4: 2 };
SYS_B = ["C", "D"];
SYS_C = ${SYS_B[1]};
SYS_D = ${SYS_A.MOD1};
}
2. 数据类型
支持:
- 字符串:
"text"或r#"raw text"# - 布尔:
true/false - 数字:整数、浮点
- 对象:
{ KEY: VALUE, ... } - 列表:
[VALUE, VALUE, ...] - 变量引用:
${VAR}、${OBJ.KEY}、${ARR[0]}
3. 大小写规则
运行时变量键按不区分大小写处理(内部统一大写键)。
例如:
${SYS_A.MOD1}与${sys_a.mod1}读取同一个值。
4. 典型遍历
mod envs {
env default {
DATA_LIST = ["JAVA", "RUST", "PYTHON"];
DATA_OBJ = {
JAVA: { NAME: "JAVA", SCORE: 80 },
RUST: { NAME: "RUST", SCORE: 100 },
PYTHON: { NAME: "PYTHON", SCORE: 200 }
};
}
}
mod main {
flow list_do {
for ${CUR} in ${ENV_DATA_LIST} {
gx.echo(value: "CUR=${CUR}");
}
}
flow obj_do {
for ${CUR} in ${ENV_DATA_OBJ} {
gx.echo(value: "${CUR.NAME}:${CUR.SCORE}");
}
}
}
GXL 内置常量
以下常量由运行时自动注入到变量空间。
-
GXL_PRJ_ROOT- 从当前目录向上查找
_gal/project.toml所在目录。 - 找不到时值为
UNDEFIN。
- 从当前目录向上查找
-
GXL_GIT_BRANCH- 以
GXL_PRJ_ROOT(或当前启动目录)为起点探测 git 分支名。 - detached HEAD 或非 git 仓库时值为
UNDEFIN。
- 以
-
GXL_START_ROOT- 启动
gx时的工作目录。
- 启动
-
GXL_CUR_DIR- 当前执行目录;在
gx.run切换目录时可能与GXL_START_ROOT不同。
- 当前执行目录;在
-
GXL_CMD_ARG- CLI 透传参数(来自
--cmd-arg)。
- CLI 透传参数(来自
-
GXL_CMD_DRYRUN- CLI dryrun 标记。
-
GXL_CMD_MODUP- CLI 模块更新标记。
-
GXL_OS_SYS- 系统标识字符串(由架构/系统/主版本组合)。
GXL 语法(对齐当前代码)
本文档按当前解析器实现整理(src/parser/*)。
1. 顶层结构
GXL 文件由多个 mod 组成:
mod main {
env default {
ROOT = "./";
}
flow conf {
gx.echo(value: "hello");
}
}
也支持 extern mod(外部模块引用):
extern mod os,ssh { path = "./_gal/mods"; }
extern mod net { git = "https://example.com/repo.git", branch = "main"; }
2. 语法骨架
GxlFile = { ExternMod | Module } ;
ExternMod = "extern" "mod" ModNameList ModAddr ;
ModNameList = Name { "," Name } ;
ModAddr = "{" ( "path" "=" String
| "git" "=" String [ "," ("branch"|"channel") "=" String ] [ "," "tag" "=" String ] ) "}" ;
Module = [Annotation] "mod" Name [":" MixList] "{" { Prop | Env | Flow | Fun | Activity } "}" [";"] ;
Env = [Annotation] "env" Name [":" MixList] (";" | "{" { Prop | EnvStmt } "}" [";"]) ;
Flow = [Annotation] "flow" FlowHead (";" | Block [";"]) ;
Fun = "fn" Name "(" [FunParams] ")" (";" | Block [";"]) ;
Activity = "activity" Name "{" { FormalParam [","|";" ] } "}" ;
FlowHead = Name [":" FlowList [":" FlowList]]
| [FlowPipe "|"] "@" Name ["|" FlowPipe]
| Name ["|" FlowPipe] ;
FlowPipe = FlowRef { "|" FlowRef } ;
FlowList = FlowRef { "," FlowRef } ;
FlowRef = Name | Name "." Name | VarRef ;
MixList = MixItem { "," MixItem } ;
MixItem = Name | VarRef ;
Block = "{" { Prop | IfStmt | ForStmt | Builtin | Call | CmdBlock } "}" ;
IfStmt = "if" Expr Block { "else" "if" Expr Block } [ "else" Block ] ;
ForStmt = "for" VarRef "in" VarRef Block ;
CmdBlock = "```cmd" <raw text> "```" ;
Prop = Name "=" GxlObject (","|";") ;
GxlObject = VarRef | Scalar | List | Object ;
Object = "{" [ ObjItem {"," ObjItem} ] "}" ;
ObjItem = Name ":" ScalarOrNested ;
List = "[" [ ScalarOrNested {"," ScalarOrNested} ] "]" ;
Builtin = gx.xxx call syntax ;
Call = Path "(" [ActualParams] ")" [";"] ;
Annotation = "#[" AnnFun {"," AnnFun} "]" ;
3. Flow 头部支持形式
3.1 旧式(冒号)
flow test : pre1,pre2 : post1,post2 {
gx.echo(value: "run");
}
3.2 管道 + @ 指定主 flow
flow pre1 | pre2 | @test | post1 | post2 {
gx.echo(value: "run");
}
3.3 简写管道
flow test | post1 | post2 {
gx.echo(value: "run");
}
4. 参数与调用约定
所有内置能力统一使用调用形式:
gx.cmd(cmd: "echo hello");
gx.echo("hello"); // 等价,匿名参数映射到 default
说明:
- 调用参数分隔符是
,。 - 命名参数使用
:,如name: "v"。 - 很多能力支持
default(匿名首参数)写法。
5. 条件表达式
支持:
- 比较:
== != > >= < <= =*(=*为通配) - 逻辑:
&& || ! - 函数:
defined(${VAR})
示例:
if defined(${CUR.ENABLE}) && ${CUR.ENABLE} == true {
gx.echo(value: "enabled");
} else {
gx.echo(value: "disabled");
}
6. 目前块内可直接识别的内置能力
gx.cmdgx.shellgx.rungx.echogx.assertgx.vergx.read_filegx.read_cmdgx.read_stdingx.tplgx.targx.untargx.downloadgx.uploadgx.patch_file
补充:
gx.vars只在env块中使用。defined(...)是表达式函数,不是gx.defined命令。
GXL 示例索引(对齐当前 examples)
以下示例对应 galaxy-flow/examples/* 当前目录中的真实 work.gxl:
assert.md:断言、变量访问、auto_loaddryrun.md:#[dryrun(...)]fun.md:函数、参数、模块调用read.md:gx.read_file/gx.read_cmdshell.md:gx.shelltemplate.md:gx.tpl与cmd代码块transaction.md:#[transaction]/#[undo(...)]vars.md:对象、列表、for、if
说明:
- 这些页面只保留“当前示例在做什么”和“如何运行”。
- 语法规则请以
gxl/help.md、gxl/syntax.md和gxl/inner/*为准。
Assert 示例
对应目录:
galaxy-flow/examples/assert- 入口:
_gal/work.gxl - 常用 flow:
assert_main、assert_parent
这个示例主要验证三类能力:
gx.assert(...)的相等断言- 对象、数组与大小写不敏感变量访问
#[auto_load(entry/exit)]与模块 flow 组合
示例代码:
extern mod os { path= "../../_gal/mods"; }
mod base_env {
env _common {
gx.vars {
DOMAIN = "domain" ;
}
}
env cli : _common {
ROOT = "./";
}
env unit_test : _common {
ROOT = "./example";
}
}
mod envs : base_env {
#[usage(desp="default")]
env default : cli ;
env empty {}
env ut : unit_test ;
}
mod base{
mod_val = "1";
flow define {
base = "BASE";
}
#[auto_load(entry)]
flow base_into {
base_begin = "BASE_INTO";
}
#[auto_load(exit)]
flow base_exit {
base_end = "BASE_EXIT";
}
}
mod other {
flow def1 {
other_val = "OTHER_DEF";
}
flow def2{
other_val = "OTHER_DEF2";
}
}
mod main {
conf = "${ENV_ROOT}/conf" ;
#[auto_load(entry)]
flow __into | other.def1 {
other_val = "OTHER_DE1";
}
#[auto_load(exit)]
flow __exit | other.def2 ;
#[usage(desp="main")]
flow assert_main {
one= "one";
sys_a = { mod1 : "A", mod2 : "B" };
sys_b = [ "C", "D" ];
sys_c = ${SYS_B[1]} ;
sys_d = ${SYS_A.MOD1} ;
gx.assert ( value : "${MAIN_CONF}" , expect : "${ENV_ROOT}/conf" );
gx.assert ( value : "${OTHER_VAL}" , expect : "OTHER_DEF" );
gx.assert ( value : "${SYS_A.MOD1}" , expect : "A" );
gx.assert ( value : "${sys_a.mod1}" , expect : "A" );
gx.assert ( value : "${sys_b[0]}" , expect : "C" );
gx.assert ( value : "${sys_d}" , expect : "A" );
}
flow base.define | @assert_parent {
gx.assert ( value : "${MAIN_CONF}" , expect : "${ENV_ROOT}/conf" );
gx.assert ( value : "${BASE_MOD_VAL}" , expect : "1" );
gx.assert ( value : "${OTHER_VAL}" , expect : "OTHER_DEF" );
gx.assert ( value : "${BASE}" , expect : "BASE" );
gx.assert ( value : "${BASE_BEGIN}" , expect : "BASE_INTO" );
}
}
运行方式:
gx assert_main
gx assert_parent
Dryrun 示例
对应目录:
galaxy-flow/examples/dryrun- 入口:
_gal/work.gxl - 常用 flow:
start
这个示例演示:
#[dryrun(_step3)]在 dryrun 模式下替换目标 flow- 非 dryrun 时原 flow 继续执行,且断言失败
示例代码:
mod main {
env default {}
flow _step1 {
gx.echo ("step1");
}
#[dryrun(_step3)]
flow _step2 {
gx.echo ("step2");
gx.assert ( value : "true" , expect : "false" );
}
flow _step3 {
gx.echo ("dryrun setp2");
}
flow start | _step1 | _step2 ;
}
运行方式:
gx start --dryrun
gx start
Function 示例
对应目录:
galaxy-flow/examples/fun- 入口:
_gal/work.gxl - 常用 flow:
conf
这个示例演示:
fn定义与模块内调用- 默认参数与可变参数
- 函数中继续调用其他函数与
for
示例代码:
extern mod os { path = "../../_gal/mods"; }
mod sys {
fn echo( *value ) {
gx.echo ( "${value}");
}
fn echo_obj( *value , msg = "object") {
gx.echo ( "${value}:${msg}");
}
fn echo_list( *value , list_msg ) {
prefix = "galaxy";
sys.echo_obj("sys.echo_obj");
echo_obj("echo_obj");
for ${item} in ${list_msg} {
gx.echo ( "${prefix}-${value}-${item}");
}
}
}
运行方式:
gx conf
Read 示例
对应目录:
galaxy-flow/examples/read- 入口:
_gal/work.gxl - 常用 flow:
conf
这个示例演示:
gx.read_file(...)把 ini 文件读入变量空间gx.read_cmd(...)捕获命令输出- 读取命名对象后用
for遍历
示例代码:
extern mod os { path= "../../_gal/mods"; }
mod envs {
env _dev_local {
gx.read_file ( file : "./var.ini" );
}
env default : _dev_local ;
}
mod main {
flow conf {
gx.echo ( "${RUST}" );
gx.echo ( "${JAVA}" );
gx.assert ( value : "${JAVA}" , expect : "90" );
gx.read_cmd (
//fail!
//cmd : r#"git branch --show-current | sed -E "s/(feature|develop|ver-dev|release|master|issue)(\/\.*)?/_branch_\1/g" "# ,
//suc!
cmd : "git branch --show-current | sed -E 's/release/rls/g'" ,
name : "GIT_BRANCH" );
gx.echo ( "what:${GIT_BRANCH}" );
gx.read_file ( file : "./var2.ini" , name : "DATA");
for ${CUR} in ${DATA} {
gx.echo ( value : "${CUR}" );
}
}
}
运行方式:
gx conf
Shell 示例
对应目录:
galaxy-flow/examples/shell- 入口:
_gal/work.gxl - 常用 flow:
conf、do_obj
这个示例演示:
gx.shell(...)运行脚本并回填out_vararg_file的使用- 列表、对象遍历中重复执行 shell
示例代码:
extern mod os { path = "../../_gal/mods"; }
mod envs {
env _dev_local {}
env default : _dev_local;
}
mod main {
flow conf {
gx.read_file(file: "./var.yml", name: "VAR");
gx.echo("what:${VAR.MEMBER.JAVA}");
gx.shell(
arg_file: "./var.json",
shell: "./demo.sh",
out_var: "SYS_OUT");
gx.echo("what:${SYS_OUT}");
gx.read_file(file: "./var_list.yml", name: "DATA");
for ${CUR} in ${DATA.DEV_LANG} {
gx.shell(
shell: "./demo_ex.sh ${CUR}",
out_var: "SYS_OUT");
gx.echo("what:${SYS_OUT}");
}
gx.read_file(file: "./var_obj.yml", name: "DATA");
for ${CUR} in ${DATA} {
gx.shell(
shell: "./demo_ex.sh ${CUR.SYS.NAME}",
out_var: "SYS_OUT");
gx.echo("what:${SYS_OUT}");
}
}
flow do_obj {
gx.read_file(file: "./var_obj.yml", name: "DATA");
for ${CUR} in ${DATA} {
//gx.echo( "CUR:${CUR.SYS.NAME}" );
gx.shell(
shell: "./demo_ex.sh ${CUR.SYS.NAME}",
out_var: "SYS_OUT");
gx.echo("what:${SYS_OUT}");
}
}
}
运行方式:
gx conf
gx do_obj
Template 示例
对应目录:
galaxy-flow/examples/template- 入口:
_gal/work.gxl - 常用 flow:
conf
这个示例演示:
gx.tpl(...)渲染模板目录- 先用
gx.cmd(...)准备输出目录 cmd代码块的写法
示例代码:
extern mod os { path = "../../_gal/mods"; }
mod base_env {
env _common {
gx.vars {
DOMAIN = "domain";
SOCK_FILE = "socket";
GXL_PRJ_ROOT = "./";
}
}
env cli : _common {
ROOT = "./";
}
env unit_test : _common {
ROOT = "./example";
}
}
mod envs : base_env {
#[usage(desp = "default")]
env default : cli;
env empty {}
env ut : unit_test;
}
mod main {
conf = "${ENV_ROOT}/conf";
flow conf {
os.path(dst: "${MAIN_CONF}/used", keep: "true");
gx.tpl(
tpl: "${MAIN_CONF}/tpls/",
dst: "${MAIN_CONF}/used/",
file: "${MAIN_CONF}/value.json");
```cmd
echo "hello";
cp ./conf/value.json ./conf/used/back.json;
```
}
}
运行方式:
gx conf
Transaction 示例
对应目录:
galaxy-flow/examples/transaction- 入口:
_gal/work.gxl - 外部模块:
_gal/base.gxl - 常用 flow:
trans1、trans2
这个示例演示:
#[transaction]事务式 flow#[undo(...)]回滚 flow- 引入外部模块后的跨模块事务步骤
示例代码:
extern mod base { path = "./_gal/"; }
mod envs {
env default {};
}
mod main {
flow trans1 | step1 | step2 | base.base_step1 | step3;
flow trans2 | step1 | step3 | step2;
#[transaction, undo(_undo_step1)]
flow step1 {
gx.echo(" step1 ");
}
#[undo(_undo_step2)]
flow step2 {
gx.echo(" step2 ");
}
#[undo(_undo_step3)]
flow step3 {
gx.echo(" step3 ");
gx.assert(value: "true", expect: "false");
}
flow _undo_step1 {
gx.echo(" undo step1 ");
}
flow _undo_step2 {
gx.echo(" undo step2 ");
}
flow _undo_step3 {
gx.echo(" undo step3 ");
}
}
运行方式:
gx trans1
gx trans2
Vars 示例
对应目录:
galaxy-flow/examples/vars- 入口:
_gal/work.gxl - 常用 flow:
array_do、obj_do
这个示例演示:
- env 中定义列表与对象变量
for遍历数组和对象if条件判断与变量比较
示例代码:
mod envs {
env default {
data_list = [
"JAVA",
"RUST",
"PYTHON",
];
data_obj = {
JAVA: { NAME: "JAVA", SCORE: 80 },
RUST: { NAME: "RUST", SCORE: 100 },
PYTHON: { NAME: "PYTHON", SCORE: 200 },
};
}
}
mod main {
flow array_do {
for ${CUR} in ${ENV.DATA_LIST} {
gx.echo("CUR:${CUR}");
}
}
flow obj_do {
for ${CUR} in ${ENV.DATA_OBJ} {
gx.echo("CUR:${CUR.NAME} : ${CUR.SCORE}");
}
}
}
运行方式:
gx array_do
gx obj_do
GXL 内置能力总览(对齐当前实现)
以下为当前 block parser 直接支持的内置能力:
gx.assert:docs/gxl/inner/assert.mdgx.cmd:docs/gxl/inner/cmd.mdgx.echo:docs/gxl/inner/echo.mdgx.read_file / gx.read_cmd / gx.read_stdin:docs/gxl/inner/read.mdgx.vars(仅 env 内):docs/gxl/inner/vars.mdgx.tpl:docs/gxl/inner/tpl.mdgx.ver:docs/gxl/inner/ver.mdgx.run:docs/gxl/inner/run.mdgx.shell:docs/gxl/inner/shell.mdgx.tar / gx.untar:docs/gxl/inner/tar_untar.mdgx.download / gx.upload:docs/gxl/inner/download_upload.mdgx.patch_file:docs/gxl/inner/patch_file.md
表达式函数:
defined(${VAR}):docs/gxl/inner/defined.md
兼容别名说明:
- 解析器中部分能力存在
rg.xxx兼容解析入口,但在 block/env 语句分发层并未统一开放。 - 建议始终使用
gx.xxx。
未作为当前内置 block 能力接入:
gx.artifact(见docs/gxl/inner/artifact.md)
gx.artifact(当前未作为内置 block 能力接入)
当前 BlockAction 与 stc_blk 未直接识别 gx.artifact。
如果需要 artifact 流程,请通过外部模块/活动调用方式实现,例如:
os.artifact(file: "./target/a", dst: "./artifacts");
建议将该能力放在 _gal/mods 中以模块调用方式维护。
gx.assert
作用
断言比较,默认比较“相等应成立”。
语法
gx.assert(
value: "<实际值>",
expect: "<期望值>",
err: "<失败提示>",
result: "true|false"
);
参数:
value:实际值expect:期望值err:失败时消息(可选)result:"true"表示期望相等;"false"表示期望不相等
示例
gx.assert(value: "${ENV}", expect: "prod");
gx.assert(value: "${ENV}", expect: "prod", result: "false");
gx.cmd
作用
执行一条命令字符串。
语法
gx.cmd(
cmd: "<command>",
err: "<err var>",
suc: "<success message>",
ok_codes: "0,2",
sudo: "true|false",
log: "1|2|3",
silence: "true|false",
quiet: "true|false"
);
也支持匿名首参数:
gx.cmd("echo hello");
代码块命令
```cmd
cp a b
ls -al
```
示例
gx.cmd(cmd: "git branch --show-current");
gx.cmd("echo ${HOME}");
gx.cmd(cmd: "grep foo missing.txt", ok_codes: "0,1");
defined(…)
作用
条件表达式函数,判断变量是否已定义。
语法
if defined(${HOME}) {
gx.echo(value: "has home");
}
if !defined(${NO_SUCH_VAR}) {
gx.echo(value: "missing");
}
说明:
- 这是表达式函数,不是
gx.defined命令。
gx.download / gx.upload
gx.download
gx.download(
url: "https://example.com/a.txt",
local_file: "./temp/a.txt",
username: "user",
password: "pass"
);
gx.upload
gx.upload(
url: "https://example.com/upload",
local_file: "./temp/a.txt",
method: "put",
username: "user",
password: "pass"
);
说明:
local_file的父目录必须已存在。gx.download若local_file是目录,会按 URL 文件名落盘。
gx.echo
作用
输出一段文本到 stdout。
语法
gx.echo(value: "<text>");
也支持匿名首参数:
gx.echo("hello");
说明:
- 当前实现仅支持输出文本,不支持旧文档中的
file/export/inc参数。
gx.patch_file
作用
基于 marker 对文件做受控修改,支持:
setcomment_lineuncomment_linecomment_blockuncomment_block
语法
gx.patch_file(
file: "./Cargo.toml",
action: "set",
marker: "version",
value: "0.12.3",
strict: "true",
dry_run: "false",
backup: "false",
comment_prefix: "#"
);
参数:
file:目标文件(必填)action:操作类型(必填)marker(或id):marker id(必填)value:仅set需要strict:默认truedry_run:默认falsebackup:默认falsecomment_prefix(或comment):默认#
marker 约定
- set:
@gxl:set(<id>) - line:
@gxl:line(<id>) - block start:
@gxl:block(<id>) - block end:
@gxl:end(<id>)
兼容写法:
# @gxl:...#@gxl:...// @gxl:...//@gxl:...
strict 语义
strict=true 时,任何 marker 结构异常都失败,例如:
- marker 命中数不是 1
- block 嵌套
- 只有
end没有block - 缺少
end
comment_prefix 约束
comment_prefix不能为空字符串。
示例
1) set
version = "0.12.2" # @gxl:set(version)
gx.patch_file(
file: "./Cargo.toml",
action: "set",
marker: "version",
value: "\"0.12.3\""
);
2) comment/uncomment block
# @gxl:block(res_depend_test)
[features]
res_depend_test = []
# @gxl:end(res_depend_test)
gx.patch_file(file: "./Cargo.toml", action: "comment_block", marker: "res_depend_test");
gx.patch_file(file: "./Cargo.toml", action: "uncomment_block", marker: "res_depend_test");
3) line toggle
res_depend_test = [] # @gxl:line(res_depend_test)
gx.patch_file(file: "./Cargo.toml", action: "comment_line", marker: "res_depend_test");
gx.patch_file(file: "./Cargo.toml", action: "uncomment_line", marker: "res_depend_test");
gx.read_file / gx.read_cmd / gx.read_stdin
gx.read_file
读取配置文件到变量空间。
gx.read_file(
file: "./var.yml",
name: "DATA"
);
参数:
file(或匿名首参数)name:可选;不传时对象字段会并入全局变量entity:解析层接受,当前执行层未使用
格式支持:
inijsonyml
gx.read_cmd
执行命令并把 stdout 写入变量。
gx.read_cmd(
name: "BRANCH",
cmd: "git branch --show-current",
err: "ERR_MSG",
ok_codes: "0,1",
log: "1"
);
gx.read_stdin
从标准输入读取值。
gx.read_stdin(
prompt: "input your name:",
name: "USER_NAME"
);
gx.run
作用
在子目录中执行另一个 GXL 配置。
语法
gx.run(
local: "<run dir>",
conf: "<gxl file>",
env: "<env name>",
flow: "a,b,c",
isolate: "true|false"
);
参数:
local:运行目录conf:目标配置文件(默认./_gal/work.gxl)env:目标环境isolate:是否隔离变量空间flow:解析层可接受;当前执行层未实际覆盖 flow 列表(保留参数)
gx.shell
作用
执行 shell 命令/脚本,可加载参数文件,可回填输出变量。
语法
gx.shell(
shell: "<command or script>",
arg_file: "<json|yml|yaml|toml|ini>",
out_var: "<var name>",
err: "<err var>",
ok_codes: "0,2",
log: "1|2|3",
sudo: "true|false",
silence: "true|false"
);
也支持匿名首参数:
gx.shell("./demo.sh");
gx.tar / gx.untar
gx.tar
gx.tar(src: "./src", file: "./dist/src.tar.gz");
gx.untar
gx.untar(file: "./dist/src.tar.gz", dst: "./dist/unpack");
说明:
gx.untar解压前会处理目标路径(存在时清理)。
gx.tpl
作用
模板渲染(当前仅 handlebars 引擎)。
语法
gx.tpl(
tpl: "<模板文件或模板目录>",
dst: "<目标文件或目标目录>",
data: "<json string>",
file: "<json file>",
engine: "handlebars"
);
参数:
tpl:模板路径dst:输出路径data:内联 JSON 字符串(可选)file:JSON 数据文件(可选)engine:handlebars|helm(当前执行层仅支持handlebars)
示例
gx.tpl(
tpl: "./conf/tpls",
dst: "./conf/used",
file: "./conf/value.json"
);
gx.vars
作用
批量定义变量。
语法
env default {
gx.vars {
APP = "galaxy";
STAGE = "dev";
};
}
说明:
- 当前语法是
=赋值,支持;/,分隔。 gx.vars只在env中作为 env item 使用。
gx.ver
作用
读取并递增版本号(写回文件,并导出变量)。
语法
gx.ver(
file: "./version.txt",
inc: "build|bugfix|feature|main|null"
);
版本格式:
major.minor.patchmajor.minor.patch.build
说明:
- 默认导出变量为
VERSION。 export参数在当前解析层存在实现偏差,不建议使用。