私有包发版后镜像源不识别,因composer镜像源仅同步packagist.org上已注册并启用自动更新的公开包;未注册、未授权或内网gitlab私有包需用satis搭建内网静态源,并禁用packagist.org fallback。

私有包发版后镜像源不识别?先确认它是不是“镜像源能管的包”
Composer 镜像源(如阿里云、腾讯云)只同步 packagist.org 上公开注册的包,**不会自动抓取你 Git 仓库里刚 push 的 tag 或新分支**。你本地 git tag v1.2.0 && git push --tags 完,镜像站根本不知道这回事——它只认 Packagist 的 webhook 或爬虫触发。所以第一反应不应该是“怎么推”,而是:“这个包有没有在 packagist.org 上 register 并启用 auto-update?”
常见误判场景:
- 你在 GitHub 创建了
myorg/my-private-sdk,但没去 packagist.org 提交注册,镜像源自然找不到 - 你注册了,但没在 Packagist 页面点「Enable auto-updating」,也没配 GitHub webhook,那么即使打 tag,Packagist 不会更新元数据,镜像源也就无法同步
- 你用的是纯内网 GitLab,且没搭
satis或packagist-mirror,那任何公网镜像源都跟你没关系——它们压根连不到你的服务器
想让私有包被 Composer 正确识别,必须走标准注册+元数据生成流程
如果你的私有包要进公网镜像(比如让团队成员 composer require myorg/my-private-sdk 成功),唯一合规路径是:注册到 Packagist → 启用自动更新 → 等镜像源同步。过程要点:
工作流任务拆解与模型编排技能。使用场景:(1) 收到复杂工作任务需要拆解为可执行步骤,(2) 需要为不同步骤选择最合适的模型,(3) 需要跟踪工作流进度和模型使用情况,(4) 长时间任务卡住需要问题诊断和解决方案。
- 包名必须符合
vendor/name格式,不能含下划线或大写字母;myorg/my_private_sdk是非法的,会卡在 Packagist 提交校验 - GitHub 仓库需公开(或至少对 Packagist OAuth 授权可见),私有仓库即使配了 token,部分镜像源也不支持拉取
- 提交后,Packagist 会生成
https://packagist.org/p/myorg/my-private-sdk.json,国内镜像源靠轮询这个地址来判断是否要更新 - 阿里云镜像通常 5–10 分钟同步一次该 JSON;若超过 30 分钟还没生效,去 镜像状态页 查同步时间戳,再比对
curl -I https://mirrors.aliyun.com/composer/p/myorg/my-private-sdk.json是否返回 200
内网私有包别硬塞公网镜像,用 satis 构建静态源才是正解
真正需要同步私有包的场景,几乎都在局域网——比如公司 GitLab 上的 internal/payment-sdk。这时强行往阿里云镜像里“塞”不仅无效,还会引发权限和网络策略问题。正确做法是用 satis 在内网搭一个静态 Composer 源:
-
satis.json中"repositories"必须显式列出每个私有仓库,且"type": "vcs"不能省:{"type": "vcs", "url": "https://gitlab.internal/internal/payment-sdk"} -
"require-all": true必须设为true,否则只同步你当前项目composer.json里写死的版本,新 tag 或 dev 分支不会入库 -
"archive"块必须完整,否则 CI 构建时 fallback 到git clone,而内网往往禁用 git 协议:"archive": {"directory": "dist", "format": "zip", "skip-dev": true} - 生成完后,把
web/目录扔到 Nginx 下,确保能直接curl https://satis.internal/packages.json返回 JSON —— 这个 URL 才是你项目composer.json里"repositories"应该填的值
项目里声明私有源时,packagist.org fallback 必须关掉
哪怕你已配好内网 satis 源,只要 composer.json 里没禁用官方源,Composer 在找不到包时仍会默默 fallback 到 packagist.org,导致超时或报错 Could not find package。必须显式屏蔽:
- 写法必须是独立对象:
"repositories": [<br> {"packagist.org": false},<br> {"type": "composer", "url": "https://satis.internal/"}<br>] -
{"packagist.org": false}不能合并进下一项,也不能写成"packagist": false—— 键名必须严格匹配 - 删掉
vendor/和composer.lock再跑composer install --no-cache -v,终端输出里应看到请求的是https://satis.internal/packages.json,而不是packagist.org
最常被忽略的一点:satis 构建生成的 packages.json 必须能被所有机器直接 HTTP GET 到,不是“放对目录”就行,还要检查 Nginx 是否允许跨域、是否拦截了 .json 后缀、SSL 证书是否被客户端信任——这些细节一出错,就表现为“配置写了,但 composer install 仍卡住”。










