13

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

  1. 查看$Build.SourceBranch
  2. version patch --force
  3. git push

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

4

3 回答 3

8

我添加了与问题中提到的相同的任务,并进行了一些小改动。
显然有一种方法可以跳过管道触发,请参见此处

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

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

这可以防止触发下一个构建。

提示:请记住授予“作者”(Azure DevOps 用户)权限(Bypass policies when pushing如果有)。

于 2019-10-11T21:04:58.297 回答
2

不要使用源代码库中的文件来跟踪当前/下一个版本。如果你这样做,我认为你不能轻易打破循环。

您可能能够在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-* 值来描述主要/次要值的质量:]

  1. (这并不是真正的任务,只是描述执行的开始:)作业开始。代码会自动从源代码库中提取到构建代理中。
  2. 使用您编写的实用程序命令行任务和代码或脚本,运行以查找具有与您使用的模式匹配的标记git describe --tags名的最新标记(见下文)。(我更喜欢这个顺序而不是调用,因为 npm 将只使用最新的标签,它可能不是版本号,这取决于您对分支的控制程度。)使用字符串或正则表达式操作来提取主要、次要、补丁,以及您可能拥有的任何 pre-* 值。这是我们将用来与 package.json 文件中的内容进行比较的先前版本。请注意,您可能必须按照这些说明运行 git 命令。将其保存到管道变量npm version from-git
  3. 使用您编写的实用程序命令行任务和代码或脚本,运行npm version以从 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. 使用您编写的实用程序命令行任务和代码或脚本,比较以前版本的主要、次要和前 * 值,以确定它们中的任何一个是否已更改。设置一个新的管道变量以反映它是否已更改。我将使用名称“restartVersionPatchNumber”,如果当前的主要、次要或前 * 值与以前版本的主要、次要或前 * 值不同,则为 true。

  5. npm 任务有条件地运行一个自定义命令:npm --no-git-tag-version version patch,它更新构建代理中的 package.json 但不提交更改,使您的工作区被修改(脏)(如果您使用自己的构建代理,这可能会导致后续构建出现问题而不是托管代理)。Task的条件表达式使用了一个自定义条件,该条件计算为我刚刚在上一步中设置的变量(“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. 利润

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

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


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


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

于 2019-10-11T05:56:49.177 回答
1

这是我在 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
于 2020-06-12T17:12:39.890 回答