在Azure DevOps(VSTS)中在发布阶段之间共享文件

10
总体情况:我们使用Azure DevOps发布流程(目前我们在设计师中创建步骤,而不是YAML管道)。我们需要发布到3个具有不同数据库的环境。发布过程的一部分是从DACPAC文件中部署数据库。由于使用SqlPackage.exe直接发布到数据库不够透明(您无法看到和审查实际的SQL脚本),因此我们想要分成两个阶段进行发布:
  1. 从DACPAC创建SQL脚本并审核
  2. 经过批准后,从之前生成的脚本运行应用程序和数据库部署。
问题:如何在各个阶段之间共享SQL脚本文件,并进行审核。这些阶段可能会在不同的代理上触发。 我尝试过的内容:
  1. 将脚本发布为构建工件 - 这不起作用,因为要生成脚本,我需要连接到数据库,而连接到生产数据库不应该是构建过程的一部分。
  2. 将Artifact发布到Azure Pipelines作为发布步骤 - 它没有允许在发布时执行,只能在构建时执行。
  3. 将Artifact发布到文件共享 - 我不确定这究竟是如何工作的,文档也不是很好。此外,在我们的基础设施中设置常规的Windows文件共享可能会很困难,我宁愿避免这种方法。
还有其他建议吗?

可能会感兴趣的内容:https://github.com/MicrosoftDocs/azure-devops-docs/issues/5703 - J.G.Sebring
2个回答

2

虽然您不能使用管道工件,但是您可以使用包管理中的通用程序包来发布任意文件以供以后检索。只需将文件内容转储到管道日志中,这是允许人们检查它的最简单的方法。

您还可以创建一个带有占位符的文件作为构建工件,并在每个阶段中合并来自管道变量的最终设置,这样您就可以将它们保留为构建工件。这是我倾向于处理此类文件的方式。听起来这对于您生成的SQL文件不适用。

或者,如果“查看并批准”环节很重要,您可以生成它并将其写入日志,将其上传到通用程序包管理中。然后在阶段结束时请求批准。在下一个阶段中,您可以从通用程序包管理中下载脚本,或者在执行之前使用完全相同的任务配置重新生成它。


1
我被告知,“发布管道工件”的未来版本很可能会实现我们所有人想要的情景。 - jessehouwing
感谢您的建议,我们最终通过将脚本发送到SFTP服务器来解决问题,这样我们就可以访问和审核它,然后在第二阶段下载脚本并运行。但理想情况下是要发布构件。 - Mateusz Moska
1
是的,通用软件包管理将允许类似的操作。在从SFTP检索脚本后,您是否检查其sha值?否则,您可能会使用与生成的不同的脚本。在您的情况下,安全性似乎很重要 ;)。 - jessehouwing
再次感谢您的想法 :) 您是正确的,我们应该检查SHA校验和,目前我们还没有这样做。 - Mateusz Moska

0
Azure DevOps现在允许下载之前阶段作为工件发布的文件。
在我分享的代码中,我实现了带有数据库更改的SQL模式生成,然后发布这些更改(经过批准)。一些备注:
  • 如果更改会导致数据丢失,这种方法将不起作用。
  • sqlpackage 的路径仅在安装了 Visual Studio 2019(例如在 windows-2019 映像中)时才正确。
  • 我通过组变量传递了以下变量(有关如何创建组变量的更多信息,请单击此处):
    • targetDBConnectionString
    • servername
    • databasename
    • adminlogin
    • adminPassword
  • 我已经在ApplyChanges阶段添加了一个approval(在Pipelines菜单中选择environments,然后选择ApplyChanges环境,最后从右上角的三个点按钮中选择approvals and checks)。这样,在手动批准之前,不会将更改应用于数据库。

stages:
- stage: 'Build'
  displayName: 'Build the web application'
  jobs: 

  (...)

  - job: BuildDacpac
    pool:
      vmImage: 'windows-2019'
    steps:
    - task: DotNetCoreCLI@2
      displayName: 'Build the database project'
      inputs:
        command: 'custom'
        custom: 'build'
        projects: 'FQDN\For\The\DB\Project\DBProjectName.sqlproj'
    - task: CopyFiles@2
      displayName: 'Copy dacpac file to a staging directory'
      inputs:
        contents: |
          FQDN\For\The\DB\Project\bin\**\*.dacpac
        targetFolder: '$(Build.StagingDirectory)'
    - task: PublishBuildArtifacts@1
      displayName: 'Publish build artifact'
      inputs:
        pathToPublish: '$(Build.ArtifactStagingDirectory)'
        artifactName: dropDacpac
      condition: succeededOrFailed()

- stage: VerifyScript
      displayName: 'Script database schema changes'
      dependsOn: 
        - Build
      jobs:
      - deployment: VerifyScript
        pool:
          vmImage: 'windows-2019'
        variables:
        - group: 'Timeline CV - Release'
        environment: 'scriptverification'
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: dropDacpac
                patterns: '**/*'

          - task: CmdLine@2
            displayName: 'Generate schema changes script'
            inputs:
              script: |
                "c:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions\Microsoft\SQLDB\DAC\140\sqlpackage.exe"    ^
                /action:script ^
                /diagnostics:true ^
                /sourcefile:$(Pipeline.Workspace)\dropDacpac\path\to\the\dacpacFile\package.dacpac    ^
                /targetConnectionString:$(targetDBConnectionString) ^
                /outputpath:$(Build.StagingDirectory)\changesScript.sql

          - task: PublishPipelineArtifact@1
            inputs:
              targetPath: '$(Build.StagingDirectory)'
              artifactName: dropSqlSchemaChangesScript
            condition: succeededOrFailed()

          - task: PowerShell@2
            displayName: Show Auto Generated SQL Script
            inputs: 
              targetType: 'inline'
              script: | 
                Write-Host "Auto Generated SQL Update Script:"
                Get-Content $(Build.StagingDirectory)\changesScript.sql | foreach {Write-Output      $_}

- stage: ApplyChanges
  displayName: 'Apply database schema changes'
  dependsOn: VerifyScript
  jobs:
  - deployment: ApplyChanges
    pool:
      vmImage: 'windows-2019'
    variables:
    - group: 'Timeline CV - Release'
    environment: 'applyChanges'
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: dropSqlSchemaChangesScript
          - task: SqlDacpacDeploymentOnMachineGroup@0
            displayName: 'Deploy SQL schema changes script'
            inputs:
              taskType: 'sqlQuery'
              sqlFile: '$(Pipeline.Workspace)\dropSqlSchemaChangesScript\changesScript.sql'
              targetMethod: 'server'
              authScheme: 'sqlServerAuthentication'
              serverName: '$(servername)'
              databaseName: '$(databasename)'
              sqlUsername: '$(adminlogin)'
              sqlPassword: '$(adminPassword)'

这个能在发布管道中使用吗?在我的发布管道中,$(Build.ArtifactStagingDirectory)没有设置。 - Saurabh Nanda
你尝试过在发布管道(经典视图)中使用下载管道工件任务吗?我相信这是可能的。请查看此链接:https://learn.microsoft.com/en-us/azure/devops/pipelines/artifacts/pipeline-artifacts?view=azure-devops&tabs=classic - ccoutinho
我收到了以下错误信息:“无法从发布环境上传到管道工件。” - Saurabh Nanda
看起来你的问题是上传/发布构件,而不是下载它。如果在你的使用情况下有意义,我建议你创建一个构建流水线,最后发布构件。然后,当构建流水线中发布构件时,你正在处理的发布流水线将被触发。 - ccoutinho

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接