【问题标题】:How to deploy multiple apps (monorepo) with Azure and NX如何使用 Azure 和 NX 部署多个应用程序 (monorepo)
【发布时间】:2020-09-17 02:12:25
【问题描述】:

我正在使用 NX 工具来管理具有多个应用程序的 monorepo,但我正在努力了解如何使用 Azure 进行部署和发布管道。

免责声明:我对 Azure 和 devops 很陌生。

我的理解是这样的: 我创建了一个管道(不是发布管道,如果有任何意义,只是一个“常规管道”)并插入一个 yml 到它。此外,管道链接到 Azure Repos 上的存储库,这意味着每次我推送到此存储库时,它都会触发管道并运行 yaml 命令。 在这个命令上,我运行 lint、测试和构建。

这是我能做到也能理解的,下面的就比较晦涩了

如果我在我可以调节的 master 上合并/合并,则构建作业应该创建一个工件。 现在我可以创建一个发布管道,它将在何时触发它链接到的回购将创建一个工件。然后,此发布管道可以将此工件发送到应用服务,该服务是应用所在的插槽。

好的,但我使用的是 monorepo,这意味着构建将生成多个应用程序,并且这些应用程序中的每一个都应部署到正确的应用程序服务。

经过一番研究,I found that 的总体思路是为每个应用创建一个发布管道。这些发布管道都链接到同一个 monorepo,但它们有一个过滤器,它是一个构建标签。 build 标签是在使用 yml 文件构建应用程序时添加的。

所以这些基本上是我对这一切的理解。现在是问题:

  1. 什么是构建标签,它存在于哪里?它是否以某种方式与工件相关联?
  2. 我们的想法是为每个工件创建一个构建标签,对吗?
  3. 我未能创建构建标签,我该怎么做?
  4. 压缩和发布工件的正确方法是什么?

    这是我正在使用的 yaml:

jobs:
  - job: Lint
    steps:
      - task: NodeTool@0
        inputs:
          versionSpec: '12.x'
        displayName: 'Install Node.js'
      - task: Npm@1
        displayName: 'Npm install'
      - pwsh: 'npm run nx affected -- --target=lint --parallel --base=origin/master --maxParallel=4'
        displayName: 'Running lint'

  - job: Test
    steps:
      - task: NodeTool@0
        inputs:
          versionSpec: '12.x'
        displayName: 'Install Node.js'
      - task: Npm@1
        displayName: 'npm install'
      - pwsh: 'npm run nx affected -- --target=test --parallel --code-coverage --base=origin/master --maxParallel=4'
        displayName: 'Running tests'

  - job: Build
    steps:
      - task: NodeTool@0
        inputs:
          versionSpec: '12.x'
        displayName: 'Install Node.js'
      - task: Npm@1
        displayName: 'npm install'
      - pwsh: 'npm run nx affected -- --target=build --parallel --base=origin/master --prod'
        displayName: 'Running build'
      - pwsh: |
          npm run nx affected:apps -- --base=HEAD~1  --head=HEAD | grep -E '( - )(\w|-|\d|_)+' | sed -E 's/ - /##vso[build.addbuildtag]/g'
        displayName: 'Adding build tags'

运行此程序时,测试、lint 和构建都在工作,但我认为它没有添加构建标签,这是日志:

好像什么都没有发生...如何正确添加标签并触发发布管道?

我还找到了这个 sn-p 来压缩和发布工件,但我不知道我是否可以使用它,因为在 monorepo 中我们应该 - 我认为 - 创建多个工件。

5) 所以最后一个问题是:我怎样才能创建多个工件,这甚至是一件好事吗?

非常感谢您的帮助,我知道这是一个很长很无聊的帖子,帮助菜鸟可能很无聊,但我坚持这个很长一段时间......

【问题讨论】:

  • 您好,您有机会尝试以下解决方案吗?效果如何?
  • 嗨,对不起,尽管信息量很大,但我没有花时间回答这篇文章。我自己找到了很多来回的解决方案,它看起来很像你的解决方案,除了第一部分,在我的解决方案中,我使用 vso.addBuildTags 在 yaml 文件中动态添加标签。我想找到一种解决方案来归档和发布受影响的应用程序,而不必为 yaml 中的每个应用程序手动执行它,我想循环访问受影响的应用程序变量并使用该循环的索引来找到正确的路径以便存档和发布。但看起来不可能。

标签: azure-devops monorepo


【解决方案1】:

1,您可以从 UI 页面(构建摘要页面,见下文)或使用 Rest api 为构建添加标签。它可用于在构建之间进行过滤。如果您的构建管道生成了多个工件,构建标签将无法过滤在一次构建中生成的工件。

2,因此您可以考虑如何为管道中的每个应用分离构建工件。

您可以使用Archive files task 压缩您的构建工件并使用publish build artifacts task 发布。

参见下面的 yaml 示例:我使用两个归档文件任务分别打包 app1 和 app2 的构建工件。并将压缩后的工件保存在文件夹 $(Build.ArtifactStagingDirectory) 中。 然后发布构建工件任务会将工件发布到 azure devops 云。 (发布管道将下载工件以部署到您的应用服务器)

- task: ArchiveFiles@2
      inputs:
        rootFolderOrFile: $(system.defaultworkingdirectory)/app1/dist
        archiveType: 'zip'
        archiveFile: '$(Build.ArtifactStagingDirectory)/app1/dist1.zip'
        includeRootFolder: false
      enabled: true
    - task: ArchiveFiles@2
      inputs:
        rootFolderOrFile: $(system.defaultworkingdirectory)/app2/dist
        archiveType: 'zip'
        archiveFile: '$(Build.ArtifactStagingDirectory)/app2/dist2.zip'
        includeRootFolder: false
      enabled: true


    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: $(Build.ArtifactStagingDirectory)/
        artifactName: build

3,然后您可以在发布管道中使用多个阶段并使用Azure App Service Deploy task。下面的例子:

在第一阶段添加Azure App Service Deploy task并将包设置为$(System.DefaultWorkingDirectory)/**/app1/dist1.zip以部署app1。在第二阶段将其设置为 $(System.DefaultWorkingDirectory)/**/app2/dist2.zip 以部署 app2。

在 monorepo 中部署多个应用的​​另一种解决方法是创建多个构建/发布管道,每个应用一个。并在构建管道中使用path filter 让构建管道仅在相应应用更新时触发。

trigger:
  paths:
    include:
    - root/app1/*

希望以上有所帮助!

【讨论】:

    【解决方案2】:

    @levi Lu-MSFT 的回答帮助了我很多,基本上我们就是这样做的,但他们并没有真正提供完整的 yaml 代码。

    我们设置发布管道的方式是每个应用程序一个发布管道,查看发布触发器的构建标签。我们目前将所有应用程序捆绑在一个工件中,因此缺点是当触发应用程序的主分支时,发布过程将下载所有应用程序。

    我动态添加构建标签的方式是从这个 nx 命令开始的: npx nx affected:apps --base=origin/main --plain 它会打印出已更改的应用程序列表。从那里,我遍历应用程序并动态创建构建标签。

    这里我有两个工作,一个在 PR 上运行,一个在主分支上运行。

    trigger:
      branches:
        include:
          - main
    pool:
      name: My-Pool
      demands: Agent.OS -equals Windows_NT
    
    jobs:
      - job: NX_AFFECTED_PR
        pool:
          name: WBOmega-Pool
          demands: Agent.OS -equals Windows_NT
        condition: eq(variables['Build.Reason'], 'PullRequest')
        steps:
          - task: Npm@1
            displayName: 'npm install'
            inputs:
              command: 'install'
              verbose: true
    
          - powershell: |
              npx nx affected:apps --base=origin/main --plain | Tee-Object -Variable output
    
              [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
              foreach ($appName in ($output -replace '\s+', ' ').Split()) {
                      Write-Host "this is the app-name: $appName"
                      if($appName.Trim() -eq ""){
                        Write-Host "App name is blank"
                      } else {
                        $url="https://dev.azure.com/YOUR_ORG/$(System.TeamProject)/_apis/build/builds/$(build.buildid)/tags/" + $appName + "?api-version=6.0"
                        Write-Host $url
                        $result = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Put
                      }
              }
            name: set_build_tags
          - powershell: |
              npx nx affected --target=build --base=origin/main --parallel --max-parallel=3
            name: build
          - powershell: |
              npx nx affected --target=lint --base=origin/main --parallel --max-parallel=3
            name: lint
          - powershell: |
              npx nx affected --target=test --base=origin/main --parallel --max-parallel=3
            name: test
    
      - job: NX_AFFECTED_MAIN
        pool:
          name: My-Pool
          demands: Agent.OS -equals Windows_NT
        condition: ne(variables['Build.Reason'], 'PullRequest')
        steps:
          - checkout: self
            persistCredentials: true
          - powershell: |
              npx nx affected:apps --base=HEAD~1 --plain | Tee-Object -Variable output
              [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
              foreach ($appName in ($output -replace '\s+', ' ').Split()) {
                      Write-Host "this is the app-name: $appName"
                      if($appName.Trim() -eq ""){
                        Write-Host "App name is blank"
                      } else {
                        $url="https://dev.azure.com/YOUR_ORG/$(System.TeamProject)/_apis/build/builds/$(build.buildid)/tags/" + $appName + "?api-version=6.0"
                        Write-Host $url
                        $result = Invoke-RestMethod -Uri $url -Headers @{Authorization = "Bearer $(System.AccessToken)"} -Method Put
                      }
              }
            name: set_build_tags
          - powershell: |
              npx nx affected --target=build --base=HEAD~1 --parallel --max-parallel=3
            name: build
          - powershell: |
              npx nx affected --target=lint --base=HEAD~1 --parallel --max-parallel=3
            name: lint
          - powershell: |
              npx nx affected --target=test --base=HEAD~1 --parallel --max-parallel=3
            name: test
          - task: CopyFiles@2
            displayName: 'Copy Files to: $(build.artifactstagingdirectory)\apps\'
            inputs:
              SourceFolder: '$(Build.SourcesDirectory)\dist\apps\'
              TargetFolder: '$(build.artifactstagingdirectory)\apps\'
              CleanTargetFolder: true
              OverWrite: true
    
          - task: PublishBuildArtifacts@1
            displayName: 'Publish Artifact'
            inputs:
              PathtoPublish: '$(Build.ArtifactStagingDirectory)\apps'
              ArtifactName: 'Apps'
    
    

    【讨论】:

      猜你喜欢
      • 2023-01-03
      • 2019-07-02
      • 2019-07-20
      • 1970-01-01
      • 2021-08-22
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      • 2021-04-23
      相关资源
      最近更新 更多