用于单仓库的黑客式语义发布
这是一个概念验证项目,它包装了semantic-release以适用于单仓库。
这个包应该能够正常工作,但可能不够稳定,不适合用于重要的生产环境,因为它高度依赖于semantic-release的工作方式(所以在semantic-release的未来版本中可能会出现问题或过时)。
semantic-release最好的特点之一是可以忘记版本号。但在单仓库中,对于本地依赖(在同一个单仓库中被引用为dependencies
、devDependencies
或peerDependencies
的包)仍然需要大量的版本号管理。然而,在multi-semantic-release中,本地依赖的版本号会在发布时被写入package.json
。这意味着不再需要硬编码版本号(我们建议在您的仓库代码中直接使用*
星号)。
yarn add multi-semantic-release --dev npm i multi-semantic-release -D
multi-semantic-release [选项] npx multi-semantic-release [选项]
发布的配置与semantic-release配置相同,即在package.json
的release
键下或任何类型的.releaserc
文件中设置,如.yaml
、.json
。
但在multi-semantic-release中,这种配置可以在全局(在您的顶级目录中)或每个包(在该单独包的目录中)中完成。如果您同时设置了两者,则每个包的设置将覆盖全局设置。
multi-semantic-release不支持任何命令行参数(这是不可能的,除非复制semantic-release的文件,而我一直在尽量避免这样做)。
multi-semantic-release自动检测以下包管理器的工作空间中的包:
确保在您的package.json
项目文件中有一个workspaces
属性。在那里,您可以设置一个包列表,这些包可能会在msr过程中被处理,也可以忽略其他包。例如,假设您的项目有4个包(即a、b、c和d),您只想处理a和d(忽略b和c)。您可以在package.json
文件中设置以下结构:
{ "name": "msr-test-yarn", "author": "Dave Houlbrooke <dave@shax.com", "version": "0.0.0-semantically-released", "private": true, "license": "0BSD", "engines": { "node": ">=8.3" }, "workspaces": [ "packages/*", "!packages/b/**", "!packages/c/**" ], "release": { "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator" ], "noCi": true } }
确保在项目根目录的pnpm-workspace.yaml
中有一个packages
属性。在那里,您可以设置一个包列表,这些包可能会在msr过程中被处理,也可以忽略其他包。例如,假设您的项目有4个包(即a、b、c和d),您只想处理a和d(忽略b和c)。您可以在pnpm-workspace.yaml
文件中设置以下结构:
packages: - 'packages/**' - '!packages/b/**' - '!packages/c/**'
注意,包版本中的workspace:
前缀目前还不支持。issues/85
确保在您的package.json
项目文件中有一个bolt.workspaces
属性。在那里,您可以设置一个包列表,这些包可能会在msr过程中被处理,也可以忽略其他包。例如,假设您的项目有4个包(即a、b、c和d),您只想处理a和d(忽略b和c)。您可以在package.json
文件中设置以下结构:
{ "name": "msr-test-bolt", "author": "Dave Houlbrooke <dave@shax.com", "version": "0.0.0-semantically-released", "private": true, "license": "0BSD", "engines": { "node": ">=8.3" }, "bolt": { "workspaces": [ "packages/*", "!packages/b/**", "!packages/c/**" ] }, "release": { "plugins": [ "@semantic-release/commit-analyzer", "@semantic-release/release-notes-generator" ], "noCi": true } }
有几个调整可以使msr适应一些特殊情况:
标志 | 类型 | 描述 | 默认值 |
---|---|---|---|
--sequential-init | 布尔值 | 避免假设的并发初始化冲突 | false |
--debug | 布尔值 | 输出调试信息 | false |
--first-parent | 布尔值 | 仅对当前分支应用提交过滤 | false |
--deps.bump | 字符串 | 定义依赖版本更新规则。<ul><li>override — 用下一个版本替换任何先前版本</li><li>satisfy — 检查下一个包版本是否符合其当前引用。如果匹配(* 匹配任何版本,1.1.0 匹配1.1.x ,1.5.0 匹配^1.0.0 等),则不会触发发布;如果不匹配,则应用override 策略;inherit 将尝试遵循当前声明的版本/范围。~1.0.0 + minor 变为~1.1.0 ,1.x + major 变为2.x ,但1.x + minor 仍为1.x ,因此不会发布,等等。</li><li>ignore 阻止MSR更新依赖</li></ul> 实验性功能 | override |
--deps.release | 字符串 | 如果任何依赖项发生更改,定义依赖包的发布类型。<ul><li>patch 、minor 、major — 严格声明更新任何依赖时发生的发布类型;</li><li>inherit — 将更新的依赖中"最高"的发布类型应用于包。<br/>例如,如果任何依赖有破坏性变更,major 发布将应用于链上的所有依赖项。</li></ul> 实验性功能 | patch |
--deps.prefix | 字符串 | 如果--deps.bump 设置为override ,可选择附加到下一个版本的前缀。支持的值:^ | ~ | '' (空字符串) | '' (空字符串) |
--dry-run | 布尔值 | 演练模式 | false |
--ignore-packages | 字符串 | 在升级过程中要忽略的包列表(附加到package.json工作区中已存在的包) | null |
--ignore-private-packages | 布尔值 | 忽略私有包 | false |
示例:
$ multi-semantic-release --debug
$ multi-semantic-release --deps.bump=satisfy --deps.release=patch
$ multi-semantic-release --ignore-packages=packages/a/**,packages/b/**
你还可以将CLI的--ignore-packages
选项与package.json
的workspaces
属性中每个包内的!
操作符结合使用。尽管你可以使用CLI忽略选项,但不能使用它来设置要发布的包 - 也就是说,你仍需要在package.json
中设置workspaces
属性。
⚠️ 请注意,allowUnknownFlags
已启用,因此其余标志将作为options
参数传递给所有包的内部semrel
调用。
multi-semantic-release默认导出一个multirelease()
方法,该方法接受以下参数:
packages
包含package.json
文件字符串路径的数组options
包含默认semantic-release配置选项的对象multirelease()
返回一个描述多重发布结果的对象数组( 对应传入的packages
数组)。
const multirelease = require("multi-semantic-release"); multirelease([ `${__dirname}/packages/my-pkg-1/package.json`, `${__dirname}/packages/my-pkg-2/package.json`, ]);
Multi-semantic release似乎与许多CI/CD系统兼容。至少我们确定了三个,以下是配置示例:
发布monorepo时,你可能会遇到npm ERR! code ETARGET
错误。这是因为npm version
在MSR尚未更新的未来依赖版本上创建了重新验证更新。
最简单的解决方法是在.npmrc中设置workspaces-update为false,或手动运行npm config set workspaces-update false
发布monorepo时,你可能会遇到EINVALIDNPMTOKEN
错误。包越多,出错的机会就越大,很遗憾。
INVALIDNPMTOKEN 无效的npm令牌。 在NPM_TOKEN环境变量中配置的npm令牌(https://github.com/semantic-release/npm/blob/master/README.md#npm-registry-authentication)必须是有效的令牌(https://docs.npmjs.com/getting-started/working_with_tokens),允许发布到注册表https://registry.npmjs.org/。
不要急于更改你的令牌。_也许_这与你的注册表上的npm whoami
请求限流有关(仅是假设:https://github.com/semantic-release/npm/pull/416)。此时你可以:
这个错误似乎与并发的git调用有关(issues/24)。或者可能不是。
无论如何,我们添加了一个特殊的--sequental-init
标志来对这些调用进行排队。
只要按照支持的包管理器之一的工作区功能配置工作区,就会自动查找包。
我知道Lerna现在是最知名的工具,但未来似乎很明显它将被Yarn和NPM的功能直接替代。如果你现在(2019年1月)使用Yarn工作区,那么发布是Lerna_真正_需要的唯一剩余功能(尽管如果Yarn添加并行脚本执行会很好)。因此,使用multi-semantic-release意味着你可能可以完全从项目中移除Lerna。
其他支持monorepo的semantic-release包通过迭代进入每个包并运行semantic-release
命令来工作。这在概念上很简单,但不幸的是不可行,因为:
一个关键要求是优雅地处理本地依赖版本号。multi-semantic-release执行以下操作:
patch
升级package.json
文件(覆盖任何现有值)上述意味着,可能如果有人在多重发布_期间_(在所有依赖都以其下一个版本发布之前)升级依赖并从NPM拉取包,那么他们的npm install
将失败(如果他们几分钟后再次尝试,就会成功)。权衡之下,我认为保持原子正确性更重要(假设项目提交了它们的锁文件,这种情况应该相当罕见)。
这是multi-semantic-release最棘手的部分,也是最可能破坏依赖的部分。我预计这将在未来引起维护问题。在理想情况下,semantic-release将内置对monorepo的支持(使得这个包变得不必要)。
我最终集成的方式是为semantic-release创建一个自定义的"内联插件",并将其作为唯一的插件传递给semanticRelease()
。然后,这个插件调用任何其他配置的插件来检索并可能修改响应。
该插件同时启动所有发布,然后在不同点暂停它们(使用 Promises),以允许多发布中的其他包赶上进度。这主要是为了在发布任何包之前确定所有包的版本号。这使我们能够对本地依赖项已升级的发布进行"补丁"升级,并在每个 package.json
中准确写入本地依赖项的版本。
内联插件执行以下操作:
context.commits
替换为仅限于该文件夹的提交列表plugins.analyzeCommits()
获取下一个发布类型(例如来自 @semantic-release/commit-analyzer)patch
plugins.generateNotes()
获取发布说明(例如来自 @semantic-release/release-notes-generator)package.json
的 dependencies
、devDependencies
、peerDependencies
中为本地依赖项写入正确的版本git push
,多个同时发布会失败,因为 Git 引用未锁定 — semantic-release 应该使用 execa.sync()
使 Git 操作具有原子性)与 semantic release 的集成相当不完善 — 以下是这个包难以维护的原因简要总结:
@semantic-release/commit-analyzer
使用前过滤 context.commits
对象(使其只列出相应目录的提交)。context.commits
非常困难!我最终通过创建一个内联插件并通过 options.plugins
将其传递给 semanticRelease()
来实现plugins.analyzeCommits()
并覆盖 context.commits
— 参见 createInlinePluginCreator.jsdependencies
指向内部包),这一步还会在它们中任何一个升级时进行 patch
升级。.releaserc
和每个目录的单个包覆盖)。git tag
异步执行而陷入奇怪的状态execa()
的调用应该替换为 execa.sync()
以确保 Git 的内部状态是原子的。Synchronizer
是其中的精髓。它对于使 标签和提交发布阶段严格按顺序进行至关重要。事件发射器允许:
发布始终使用 my-pkg-1@1.0.1
格式的 tagFormat
作为 Git 标签,并始终覆盖 semantic-release 配置中设置的任何 gitTag
。
我个人可以看到这个选项在协调 semantic-release 方面的潜力(例如,使两个具有相同标签的包始终同时升级和发布)。不幸的是,由于 semantic-release 中可用的集成点,在发布时阻止第二个包创建重复标签(导致错误)实际上是不可能的。
要使 tagFormat
选项按预期工作,需要进行以下操作:
v1.0.0
将具有与 Lerna 的固定模式相同的效果(所有更改的 monorepo 包同时发布)欢迎提出任何类型的问题:错误、功能请求或问题。 你随时可以提出 PR。只需 fork 这个仓库,编写一些代码,添加一些测试,然后推送你的更改。 欢迎任何反馈。
AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI小说写作助手,一站式润色、改写、扩写
蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮 助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等, 都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅 助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支 持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。