我已经工作了四年来为xash3d-fwgs开发了一个WebAssembly端口。这是开源的GoldSource引擎,可以在浏览器中运行Counter Strike 1.6和Half-Life Deathmatch,包括客户端和服务器。
如果你想看看而不是读取,那么有人为其开发了一个前端:https://x8bitrain.github.io/webXash/。这是x8bitrain的工作,而不是我的工作,你需要从你的Steam安装中提供自己的游戏文件,它不会带来任何资产。
端口本身是有趣的部分,而不是本文的重点。本文是关于发布它,这导致了一个我已经四年了没有意识到它是一个相同问题的问题。
什么repo实际上是
它变成了:
- 引擎,C编译到wasm通过emscripten,发布到npm为
xash3d-fwgs - 半生命周期游戏逻辑,同样的交易,
hlsdk-portable - cs 1.6客户端,基于这些,
cs16-client cs-web-server,一个docker镜像,包含一个可玩的cs服务器和web客户端hl-web-server,这是相同的镜像,但cs内容被移除并用半生命周期默认值代替-metpamx两者的变体,包含metamod-p和amx mod x
所以:C,javascript,typescript,go,以及一个docker镜像堆栈。每一个都有一个版本。每一个都依赖于repo中的另一个包。
发布日
顺序是强制的。你不能发布客户端之前引擎。半生命周期镜像从
FROM cs-web-server:1.4.2
所以它甚至不能开始构建,直到cs镜像被推送。不是构建,而是推送。
我在寻找一个工具。这就是它崩溃的地方。
每个monorepo工具都做什么
它们都可以构建并发布所有内容。lerna,changesets,nx,turborepo,所有这些。并且这是正确的,针对npm。一个npm包可以在本地工作空间中构建之前被构建,因此构建整个图表,然后推送它是更快更安全的。
但是对于docker镜像来说,它是完全不可能的。"构建所有内容"意味着我的半生命周期构建在cs推送之前运行,并且每次都会失败,因为它需要的标签不存在。
我需要的是这个顺序规则成为包的属性,而不是工具的属性。npm消费者可以在构建之前等待发布。docker消费者不能。没有工具可以做到这一点,因为大多数这些工具只处理一个生态系统的图表,并且从未需要。
我承认我花了多长时间
我之前遇到过这个问题。在2022年,我在写一个关于CI/CD工具的毕业论文,尝试用gitlab ci和lerna来构建一些类似的事情。
lerna给你图表和版本,并且它很好地处理了这两者。但是它无法发布任何不是npm的包。这不是"它很难",函数根本不存在。所以我在一边计算正确的版本,另一边写了一个ci脚本来推送包,并且工具从未推送任何包。手动将数字从一个半边传输到另一个半边。
所以我尝试用nx来构建发布层。最小的可用的原型已经有了1000多行typescript代码,并且其中没有一个是我的项目。这就是它不再是"配置一个工具"而是"编写一个工具"的时刻,我还没有准备好说出来,所以我放下它,继续工作。
然后四年后端口给了我相同的图表,但是我现在关心的是发布一个我实际关心的东西。
当它崩溃时会发生什么
步骤四中的某个步骤失败了。三个npm包已经发布,cs镜像被推送,半生命周期镜像在一个坏的引擎配置上失败了。
一个注册中心可以告诉你[email protected]存在。但是它无法告诉你这个构建还欠你两个镜像。没有工具可以解决这个问题。lerna的恢复方法是问npm已经存在的包,但这是一个生态系统的问题,而不是一个docker标签和github发布的问题。
所以你需要在ci日志中重新构建发布的包,这听起来很糟糕。
所以我写了一个原型
不是一个工具,最初是一个原型,来找出这个想法是否正确还是我只是被困在这里四年了。它通过了几个docker镜像发布的顺序,顺序保持了,恢复也保持了。
这个原型变成了dispat。单个二进制文件,MIT许可, 没有守护进程, 没有状态文件, 没有托管。
两个想法,两个都来自上述两个问题。
一个,是否一个消费者等待一个构建或一个发布是设置。isBuildWaitingPublish在空间中。npm空间:关闭,消费者可以早早地构建,所有内容都重叠。docker空间:开启,消费者的构建不会在其提供者的docker push返回之前开始。我的四级链顺序正确地工作了,没有粘合剂,图表中的不相关分支仍然并行。
二,"它已发布"的记录是git标签,仅在发布成功后写入。所以没有状态来恢复,没有注册中心来询问。计划是一个纯函数,它的历史,图表和配置的函数。重新运行计算相同的计划,仅执行没有标签的部分。半生命周期镜像在坏的标签上失败了,下一次运行时它会被恢复到它最初欠有的版本。三个npm包已经发布的包不会出现在计划中。恢复只是重新运行dispat。
版本来自惯用提交,所以feat(cs16-client):是一个小版本,fix(engine)^^:是一个修补版本,它会传播到下游的包。日志和github发布从相同的提交中衍生出来。一个包就是一个文件夹,一个阶段就是一个shell命令,这就是为什么C,go,typescript和docker可以在一个图表中一起工作的原因。
现在发布日是:
$ dispat
并且它会发布npm包,然后镜像,镜像从镜像构建的镜像,按照顺序,图表允许并行,带有日志,标签和github发布。
它也发布了自己,这感觉像是唯一的诚实测试。它的1.0.0版本是一次运行,合并了11个包:cli与6个交叉编译的二进制文件,5个go模块,4个容器镜像和文档站点,每个包都有自己的版本,标签,日志和发布。
它的缺点
- 它需要惯用提交。没有办法绕过它,版本必须来自某个地方
- 它不会构建任何内容。emscripten,docker,go build,所有这些仍然是你的命令。它运行它们并停止如果它们失败
- 它不是一个任务运行器,没有缓存。它工作出改变了的git和跳过其他部分,缓存中的内容仍然在你的构建步骤中工作
- 它无法在不同的仓库之间顺序发布包,只能在一个检出中。有一个git子模块模式可以实现这一点,但它是一个真正的折扣
如果你的仓库是一个游戏和一个部署脚本,你不需要这个,我不会伪造它。如果它是一个游戏,日志,服务器,启动器,两个库,并且所有这些都有应该对齐的版本,那就是我所处的位置,dispat就是它的结果。
评论 (0)