如何使用 Azure Devops 管道增加 npm 包的版本

How to increase a version of an npm package using Azure Devops pipeline

管道由对 master 分支的新提交触发并发布包
目前,版本是手动设置的,我很乐意自动设置它。
我最初的想法是将以下任务添加到管道中:

  1. 结帐$Build.SourceBranch
  2. 运行 version patch --force
  3. git push

这行得通并且版本确实正确地增加了,问题是,它触发了另一个 运行 管道,它将再次增加,这将..你明白了,无限循环。
有更好的方法吗?

不要使用源代码库中的文件来跟踪 current/next 版本。如果你这样做,我认为你不会轻易打破循环。

您可以使用 运行ning npm --no-git-tag-version version 来增加构建代理中的 package.json 版本而无需提交,这样您就不会发生任何变化你将不得不推回原点。它应该只是改变 package.json 并让它变脏。

等到构建成功后。使用自定义脚本任务从 package.json 中提取版本,然后从 git reset --hard 中提取版本(没有理由保留构建服务器上已更改的任何内容)。虽然这将撤消 package.json 中的更改,但您现在可以在包含该版本的头部创建一个标签,然后执行 git push origin {tag-name} 不应在源上引入新的提交,然后重新提交触发您的管道。

实际上,我认为不会因为添加了标签就触发了管道,但老实说我还没有测试过。我很确定它不会。

管道中的任务顺序:

[给定一个源代码库,您确保在 package.json 中设置主要和次要版本以根据语义版本控制规则反映代码的当前状态,并始终保留补丁值设置为 0,并且,如果需要,使用 pre-* 值来描述 major/minor 值的质量:]

  1. (这不是真正的任务,只是描述执行的开始:)作业开始了。代码会自动从源代码库中提取到构建代理中。
  2. 使用您编写的实用程序命令行任务和代码或脚本,运行 git describe --tags 查找具有 标签名 匹配的最新标签您使用的模式(见下文)。 (我更喜欢这个序列而不是调用 npm version from-git 因为 npm 将只使用最新的标签,它可能不是版本号,具体取决于你对分支的控制程度。)使用字符串或正则表达式操作来提取major、minor、patch 以及您可能拥有的任何 pre-* 值。这是我们将用来与 package.json 文件中的内容进行比较的先前版本。请注意,您可能必须遵循 these instructions to run a git command. Save it to a pipeline variable.
  3. 使用您编写的实用程序命令行任务和代码或脚本,运行 npm version 获取当前 major/minor/pre 版本package.json 文件并将其保存到不同的管道变量。我正在使用 PowerShell Core,所以我的命令看起来像这样来创建一个 "currentPackageVersion" 管道变量:

    & npm.cmd version | ConvertFrom-Json | Select-Object -ExpandProperty {name-of-your-package} | Set-Variable -Name 'packageVersion' | Write-Output "#vso[task.setvariable variable=currentPackageVersion]$packageVersion"
    
  4. 使用您编写的实用命令行任务和代码或脚本,比较先前版本的主要、次要和 pre-* 值以确定它们中的任何一个是否已更改。设置一个新的管道变量来反映它是否已经改变。我将使用名称 "restartVersionPatchNumber",如果当前的 major、minor 或 pre-* 值与以前版本的 major、minor 或 pre-* 值不同,则该名称为真。

  5. npm 任务有条件地运行是一个自定义命令:npm --no-git-tag-version version patch,它更新package.json 在构建代理中但不提交更改,使您的工作区被修改(脏)(如果您使用自己的构建代理而不是托管代理,这可能会导致后续构建出现问题)。我在上一步中刚刚设置的 condition expression of the Task uses a custom condition that evaluates to the variable ("restartVersionPatchNumber")。请注意,如果此任务没有 运行,它应该只使用 package.json 文件中的版本值(当前版本现在位于 "currentPackageVersion" 管道变量中)。
  6. 使用您编写的实用命令行任务和代码或脚本,运行 npm version 提取 npm version 命令设置的新版本。将其保存到一个新的管道变量中;我将其命名为 "newVersionNumber".
  7. 常规构建任务 运行,生成工件并可能发布它们
  8. 使用实用程序命令行任务,运行 git reset --hard。由于下一步的缘故,即使您使用的是托管构建代理,您也需要执行此操作。
  9. 使用实用程序命令行任务,从保存的版本号 ("newVersionNumber") 创建一个变量,其中包含您想要采用。使用独特的模式,例如 "AzPipelineBuild-PipelineName-PackageVersion-1.0.0" 但使用您的版本而不是 1.0.0.
  10. 使用实用程序命令行任务,运行 git tag {*tagname*}。对于 PowerShell,语法为 & git.exe tag $env:newVersionNumber
  11. 使用实用程序命令行任务,运行 git push origin {*tagname*}
  12. 利润

您可以(也许应该)结合命令行步骤。正如您可能已经猜到的那样,我真的偏爱 PowerShell 任务 运行ning PowerShellCore (pwsh)。

作为作业工件创建的包将具有在构建中创建时的更新版本,并且它将与原始源代码存储库中现在的标签相匹配。


或者,使用外部源(Azure 函数等)或不同的(第二个)git 存储库,甚至是另一个与您的 CI 触发器无关的分支您仅用于跟踪内部版本号的项目,然后使用令牌替换任务在开始构建之前设置版本。我不太喜欢这个主意,但它会阻止重新触发新构建。


此外,您希望只使用该存储库构建一个包。接下来要做的是将该包发布到您的 Azure Artifacts 提要,或 npmjs.org 或任何地方。不要依赖将版本嵌入到原始源代码中;任何依赖于该包的东西都应该将它从你发布它的提要中拉出来,而不是依赖于它在构建步骤的早期使用新版本号构建。

我添加了与问题中提到的任务相同的任务,但稍作改动。
显然有一种方法可以跳过管道触发,请参阅 here

所以 npm version 任务看起来像这样:

version patch -m "Bump version to %s [skip ci]" --force

这会阻止触发下一个构建。

提示:请记住将 'author'(Azure DevOps 用户)权限授予 Bypass policies when pushing(如果有)。

这是我在 Powershell 中的实现,它是基于已接受答案的完整步骤。请注意,这也处理了一些 git 问题,例如此类方法附带的分离头。

steps:
- checkout: self
  persistCredentials: true
.
.
.
    - task: PowerShell@2
      displayName: 'Bump the version'
      inputs:
        targetType: 'inline'
        script: |
          $BranchName = "$(Build.SourceBranch)" -replace "refs/heads/"
          git checkout $BranchName
          git config --global user.email "anymail@anycompany.com"
          git config --global user.name "Your name"
          npm version prerelease -m "Auto increment pre-release version to %s [skip ci]" --force
          git push