Satis是静态包仓库生成器而非镜像站;其“发布”本质是Satis拉取Git仓库、解析tag、生成packages.json和ZIP包,需确保vcs仓库配置正确、tag符合语义化版本、项目配置指向Satis站点。

直接说结论:Satis 不是镜像站,而是静态包仓库生成器;发布私有包到 Satis 站点,本质是让 Satis 扫描你的 Git 仓库并生成 packages.json 和对应 ZIP 归档——不是「推送」,而是「拉取+生成」。
为什么 composer publish 不存在?
Satis 没有服务端 API,也不接受 HTTP 推送。它只是一个命令行工具,运行时会:
- 克隆你配置的 Git 仓库(支持
git@、https://、甚至本地路径) - 检出指定分支或标签(如
v1.2.0) - 读取其中的
composer.json,提取name、version、dist下载地址等元数据 - 打包源码为 ZIP(可选),写入
dist字段,并生成最终的packages.json
所以「发布」= 提交带正确 version 的 tag + 触发 Satis 构建。别在本地跑 composer install 后试图上传 vendor —— Satis 不认这个。
satis.json 中必须配对的两个关键字段
很多人卡在构建后包不出现,问题常出在这两处没对齐:
-
repositories里每个仓库的type必须是vcs(不是package或composer) - 每个
vcs仓库的url必须能被 Satis 主机直接git clone通(比如填git@gitlab.internal:php/my-utils.git,而非https://gitlab.internal/php/my-utils—— 后者可能因无凭据失败)
示例片段:
{
"repositories": [
{
"type": "vcs",
"url": "git@gitlab.internal:php/my-utils.git"
}
],
"require-all": true
}
注意:require-all 表示拉取所有 tagged 版本;若只想要特定包,改用 "require": { "mycompany/my-utils": "*" }。
Git Tag 命名必须匹配 Composer 版本约束
Satis 只识别符合语义化版本规范的 tag,且默认忽略 dev- 开头的分支(除非显式配置 branches)。常见踩坑点:
- 打了
1.2tag → 不生效(缺补零,应为1.2.0) - 打了
v1.2.0tag → 生效(v前缀被自动剥离) - 打了
release/1.2.0→ 不生效(非 tag,是分支名) -
composer.json里写"version": "1.2.0"→ 可以省略,Satis 优先从 tag 解析版本号
安全做法:打 tag 前删掉 composer.json 中的 version 字段,靠 Git tag 驱动版本,避免不一致。
构建后怎么让项目真正用上?
生成的 Satis 站点(比如 https://satis.internal)只是个静态文件目录,要让团队项目生效,必须在项目级或全局 composer.json 中声明仓库:
{
"repositories": [
{
"type": "composer",
"url": "https://satis.internal"
}
],
"require": {
"mycompany/my-utils": "^1.2"
}
}
关键细节:
-
type是composer(不是vcs),URL 指向 Satis 生成的packages.json所在根路径 - 首次使用前建议跑
composer clear-cache,否则 Composer 可能缓存旧的元数据 - 如果 Satis 站点启用了 HTTP Basic Auth,需提前执行
composer config http-basic.satis.internal username password
真正难的不是构建 Satis,而是确保 Git 权限、SSH 凭据、tag 规范、Composer 配置这四者严丝合缝——漏一环,包就「看不见」。









