composer如何自定义版本发布格式_composer项目版本管理实践

composer.json 里写 1.2.3-custom.1 会直接报错,不是配置没生效,而是根本解析失败——Composer 的版本解析器严格遵循 SemVer 2.0,这个字符串连“版本”都算不上。

为什么 1.2.3-custom.1 会被拒绝

错误信息通常是:Invalid version string "1.2.3-custom.1"。这不是 Composer 故意设限,而是它调用的 ComposerSemverVersionParser 在底层就拒绝了该格式:预发布标识符(-custom.1)中,点号后接数字再跟点号,违反了 SemVer 对 identifier 的定义——必须是字母开头、后续只允许字母、数字和连字符,且不能以点号结尾或连续出现点号。

真正被接受的预发布格式只有:

1.2.3-alpha、1.2.3-beta.2、1.2.3-rc.11.2.3-dev(但注意:Packagist 不将其视为预发布版本,而是开发分支别名)1.2.3-hotfix(合法,因 hotfix 是纯字母,无点号)

而这些全都不等价于 custom.1:后者含非法结构,连 tokenization 都过不了。

想发定制版,别改 version 字段,改 dist 源

如果你要发布一个内部 patch 版本(比如修复客户紧急问题),又不想动原包源码、也不愿污染 Packagist 的公开版本流,正确做法是绕过版本解析,直接指定分发源:

在你的项目 composer.json 中,为该依赖显式声明 dist 字段,例如:{ "require": { "vendor/package": "1.2.3" }, "repositories": [ { "type": "package", "package": { "name": "vendor/package", "version": "1.2.3-custom.1", "dist": { "url": "https://internal.example.com/package-1.2.3-custom.1.zip", "type": "zip" }, "autoload": { "psr-4": { "Vendor\Package\": "src/" } } } } ]}

这样 Composer 完全跳过 Packagist 元数据校验,只认你给的 URL 和 version 字符串——version 这里可以任意写(包括 1.2.3-custom.1),只要保证 dist.url 可访问、压缩包结构正确即可。

关键点:这种写法不依赖 Packagist,也不需要打 Git tag风险点:version 字符串仅作本地标识,无法被其他项目通过 require 直接引用,必须复制整段 repositories 配置

想让别人也能装 alpha/beta 版,tag 名和 stability 必须配对

如果你控制的是被依赖方(即自己发包),要让下游用户能 composer require vendor/name:v1.0.0-beta.1,必须同时满足:

Git 仓库打了带 v 前缀的 tag:v1.0.0-beta.1(不是 1.0.0-beta.1)Packagist 已收录该仓库,且成功抓取到这个 tag下游项目未全局锁定 stability:默认 minimum-stability 是 stable,所以必须显式指定完整 tag 名,或临时放宽限制

常见翻车点:

打 tag 时漏了 v,导致 Packagist 当成 dev 分支处理,composer show vendor/name 里压根不显示该版本用户执行 composer require vendor/name:1.0.0-beta.1(缺 v),Composer 会尝试匹配分支别名而非 tag,最终失败在根项目设 "minimum-stability": "beta" 后忘了加 "prefer-stable": true,结果所有依赖都倾向拉 beta 版,引发兼容性雪崩

打 tag 推送后 Packagist 没反应?先查 webhook 和 tag 可见性

提交仓库 URL 到 Packagist 后,新 tag 不自动出现,90% 是因为同步链路断了。不要立刻重提包,先检查两件事:

GitHub 页面上打开 “Releases”,确认 v1.0.0 是否可见、是否指向正确的 commit(不是灰色的 “Draft”)进入 GitHub 仓库 Settings → Webhooks,看是否有 Packagist 的回调地址(类似 https://packagist.org/api/github?username=xxx),且状态为 “Active”,最近一次 delivery 是 success

如果 webhook 失效(常见于长期无活动后被 GitHub 自动禁用),手动点 Packagist 包页的 “Update” 能救急,但只是单次补丁;长期必须重装 Packagist App 并授权 “Repository permissions → Contents & Metadata”。

最隐蔽的坑:你本地 git tag v1.0.0 了,但忘了 git push origin v1.0.0 或 git push –tags —— 远程根本没有这个 tag,Packagist 再勤快也抓不到东西。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。