在 Microsoft Team Foundation Server (TFS) 2018 和更低版本中,生成和发布管道被称为“定义”,运行被称为“生成”,服务连接被称为“服务终结点”,阶段被称为“环境”,而作业被称为“阶段” 。
每次成功生成后,可以自动将数据库更新部署到Azure SQL数据库。
DACPAC
部署数据库的最简单方法是创建
数据层包或 DACPAC
。 DACPAC 可用于打包和部署架构更改和数据。 可以在 Visual Studio 中使用
SQL 数据库项目
创建 DACPAC。
若要将 DACPAC 部署到Azure SQL数据库,请将以下代码片段添加到 azure-pipelines.yml 文件。
- task: SqlAzureDacpacDeployment@1
displayName: Execute Azure SQL : DacpacTask
inputs:
azureSubscription: '<Azure service connection>'
ServerName: '<Database server name>'
DatabaseName: '<Database name>'
SqlUsername: '<SQL user name>'
SqlPassword: '<SQL user password>'
DacpacFile: '<Location of Dacpac file in $(Build.SourcesDirectory) after compilation>'
TFS 不支持 YAML。
使用Azure SQL数据库部署任务时,另请参阅身份验证信息。
SQL 脚本
也可以使用 SQL 脚本来部署数据库,而不是使用 DACPAC。 下面是创建空数据库的 SQL 脚本的简单示例。
USE [main]
IF NOT EXISTS (SELECT name FROM main.sys.databases WHERE name = N'DatabaseExample')
CREATE DATABASE [DatabaseExample]
若要在管道中运行 SQL 脚本,需要Azure PowerShell脚本在 Azure 中创建和删除防火墙规则。 如果没有防火墙规则,Azure Pipelines 代理无法与Azure SQL数据库通信。
以下 PowerShell 脚本创建防火墙规则。 可以将此脚本 SetAzureFirewallRule.ps1
签入存储库。
[CmdletBinding(DefaultParameterSetName = 'None')]
param
[String] [Parameter(Mandatory = $true)] $ServerName,
[String] [Parameter(Mandatory = $true)] $ResourceGroupName,
[String] $FirewallRuleName = "AzureWebAppFirewall"
$agentIP = (New-Object net.webclient).downloadstring("https://api.ipify.org")
New-AzSqlServerFirewallRule -ResourceGroupName $ResourceGroupName -ServerName $ServerName -FirewallRuleName $FirewallRuleName -StartIPAddress $agentIp -EndIPAddress $agentIP
[CmdletBinding(DefaultParameterSetName = 'None')]
param
[String] [Parameter(Mandatory = $true)] $ServerName,
[String] [Parameter(Mandatory = $true)] $ResourceGroupName,
[String] $FirewallRuleName = "AzureWebAppFirewall"
$ErrorActionPreference = 'Stop'
function New-AzureSQLServerFirewallRule {
$agentIP = (New-Object net.webclient).downloadstring("https://api.ipify.org")
New-AzureSqlDatabaseServerFirewallRule -StartIPAddress $agentIp -EndIPAddress $agentIp -FirewallRuleName $FirewallRuleName -ServerName $ServerName -ResourceGroupName $ResourceGroupName
function Update-AzureSQLServerFirewallRule{
$agentIP= (New-Object net.webclient).downloadstring("https://api.ipify.org")
Set-AzureSqlDatabaseServerFirewallRule -StartIPAddress $agentIp -EndIPAddress $agentIp -FirewallRuleName $FirewallRuleName -ServerName $ServerName -ResourceGroupName $ResourceGroupName
if ((Get-AzureSqlDatabaseServerFirewallRule -ServerName $ServerName -FirewallRuleName $FirewallRuleName -ResourceGroupName $ResourceGroupName -ErrorAction SilentlyContinue) -eq $null)
New-AzureSQLServerFirewallRule
Update-AzureSQLServerFirewallRule
以下 PowerShell 脚本删除防火墙规则。 可以在存储库中签入此脚本 RemoveAzureFirewallRule.ps1
。
[CmdletBinding(DefaultParameterSetName = 'None')]
param
[String] [Parameter(Mandatory = $true)] $ServerName,
[String] [Parameter(Mandatory = $true)] $ResourceGroupName,
[String] $FirewallRuleName = "AzureWebAppFirewall"
Remove-AzSqlServerFirewallRule -ServerName $ServerName -FirewallRuleName $FirewallRuleName -ResourceGroupName $ResourceGroupName
[CmdletBinding(DefaultParameterSetName = 'None')]
param
[String] [Parameter(Mandatory = $true)] $ServerName,
[String] [Parameter(Mandatory = $true)] $ResourceGroupName,
[String] $FirewallRuleName = "AzureWebAppFirewall"
$ErrorActionPreference = 'Stop'
if ((Get-AzureSqlDatabaseServerFirewallRule -ServerName $ServerName -FirewallRuleName $FirewallRuleName -ResourceGroupName $ResourceGroupName -ErrorAction SilentlyContinue))
Remove-AzureSqlDatabaseServerFirewallRule -FirewallRuleName $FirewallRuleName -ServerName $ServerName -ResourceGroupName $ResourceGroupName
将以下内容添加到 azure-pipelines.yml 文件以运行 SQL 脚本。
variables:
AzureSubscription: '<Azure service connection>'
ServerName: '<Database server name>'
ServerFqdn: '<SQL Database FQDN>'
DatabaseName: '<Database name>'
AdminUser: '<SQL user name>'
AdminPassword: '<SQL user password>'
SQLFile: '<Location of SQL file in $(Build.SourcesDirectory)>'
steps:
- task: AzurePowerShell@5
displayName: Azure PowerShell script: FilePath
inputs:
azureSubscription: '$(AzureSubscription)'
ScriptPath: '$(Build.SourcesDirectory)\scripts\SetAzureFirewallRule.ps1'
ScriptArguments: '-ServerName $(ServerName) -ResourceGroupName $(ResourceGroupName)'
azurePowerShellVersion: LatestVersion
- task: CmdLine@2
displayName: Run Sqlcmd
inputs:
filename: Sqlcmd
arguments: '-S $(ServerFqdn) -U $(AdminUser) -P $(AdminPassword) -d $(DatabaseName) -i $(SQLFile)'
- task: AzurePowerShell@5
displayName: Azure PowerShell script: FilePath
inputs:
azureSubscription: '$(AzureSubscription)'
ScriptPath: '$(Build.SourcesDirectory)\scripts\RemoveAzureFirewallRule.ps1'
ScriptArguments: '-ServerName $(ServerName) -ResourceGroupName $(ResourceGroupName)'
azurePowerShellVersion: LatestVersion
TFS 不支持 YAML。
设置生成管道时,请确保用于部署数据库的 SQL 脚本和用于配置防火墙规则的Azure PowerShell脚本是生成项目的一部分。
设置发布管道时,请选择“ 从空进程开始”,链接生成中的项目,然后使用以下任务:
首先,使用Azure PowerShell任务在 Azure 中添加防火墙规则,以允许 Azure Pipelines 代理连接到Azure SQL数据库。 该脚本需要一个参数 - 创建的 SQL Server 的名称。
其次,使用 命令行 任务使用 SQLCMD 工具运行 SQL 脚本。 -S {database-server-name}.database.windows.net -U {username}@{database-server-name} -P {password} -d {database-name} -i {SQL file}
例如,当 SQL 脚本来自项目源时,{SQL 文件} 将采用以下形式: $(System.DefaultWorkingDirectory)/contoso-repo/DatabaseExample.sql
第三,使用另一个Azure PowerShell任务删除 Azure 中的防火墙规则。
Azure 服务连接
Azure SQL数据库部署任务是将数据库部署到 Azure 的主要机制。 此任务与其他内置 Azure 任务一样,需要 Azure 服务连接作为输入。 Azure 服务连接存储从 Azure Pipelines 或 TFS 连接到 Azure 的凭据。
开始执行此任务的最简单方法是以拥有 Azure DevOps 组织和 Azure 订阅的用户身份登录。
在这种情况下,无需手动创建服务连接。
否则,若要了解如何创建 Azure 服务连接,请参阅 创建 Azure 服务连接。
若要了解如何创建 Azure 服务连接,请参阅 创建 Azure 服务连接。
有条件地部署
可以选择仅将某些版本部署到 Azure 数据库。
以下示例演示如何使用步骤条件仅部署源自主分支的生成。
- task: SqlAzureDacpacDeployment@1
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
inputs:
azureSubscription: '<Azure service connection>'
ServerName: '<Database server name>'
DatabaseName: '<Database name>'
SqlUsername: '<SQL user name>'
SqlPassword: '<SQL user password>'
DacpacFile: '<Location of Dacpac file in $(Build.SourcesDirectory) after compilation>'
若要了解有关条件的详细信息,请参阅 指定条件。
TFS 不支持 YAML。
更多 SQL 操作
SQL Azure Dacpac 部署可能不支持要执行的所有 SQL Server 操作。 在这些情况下,只需使用 PowerShell 或命令行脚本来运行所需的命令。
本部分介绍调用 SqlPackage.exe工具的一些常见用例。
作为运行此工具的先决条件,必须使用自承载代理并在代理上安装该工具。
如果从安装 SQLPackage 的文件夹执行 SQLPackage ,则必须为路径 &
加上前缀,并将其包装在双引号中。
<Path of SQLPackage.exe> <Arguments to SQLPackage.exe>
可以使用以下任一 SQL 脚本,具体取决于要执行的操作
从实时 SQL Server 或Microsoft Azure SQL 数据库创建数据库快照 (.dacpac) 文件。
命令语法:
SqlPackage.exe /TargetFile:"<Target location of dacpac file>" /Action:Extract
/SourceServerName:"<ServerName>.database.windows.net"
/SourceDatabaseName:"<DatabaseName>" /SourceUser:"<Username>" /SourcePassword:"<Password>"
SqlPackage.exe /action:Extract /tf:"<Target location of dacpac file>"
/SourceConnectionString:"Data Source=ServerName;Initial Catalog=DatabaseName;Integrated Security=SSPI;Persist Security Info=False;"
SqlPackage.exe /TargetFile:"C:\temp\test.dacpac" /Action:Extract /SourceServerName:"DemoSqlServer.database.windows.net"
/SourceDatabaseName:"Testdb" /SourceUser:"ajay" /SourcePassword:"SQLPassword"
sqlpackage.exe /Action:Extract /?
增量更新数据库架构以便匹配源 .dacpac 文件的架构。 如果服务器上不存在数据库,则发布操作将创建它。 否则,将更新现有数据库。
命令语法:
SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:Publish /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password> "
SqlPackage.exe /SourceFile:"E:\dacpac\ajyadb.dacpac" /Action:Publish /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb4" /TargetUser:"ajay" /TargetPassword:"SQLPassword"
sqlpackage.exe /Action:Publish /?
将实时数据库(包括数据库架构和用户数据)从SQL Server或Microsoft Azure SQL 数据库导出到 BACPAC 包 (.bacpac 文件) 。
命令语法:
SqlPackage.exe /TargetFile:"<Target location for bacpac file>" /Action:Export /SourceServerName:"<ServerName>.database.windows.net"
/SourceDatabaseName:"<DatabaseName>" /SourceUser:"<Username>" /SourcePassword:"<Password>"
SqlPackage.exe /TargetFile:"C:\temp\test.bacpac" /Action:Export /SourceServerName:"DemoSqlServer.database.windows.net"
/SourceDatabaseName:"Testdb" /SourceUser:"ajay" /SourcePassword:"SQLPassword"
sqlpackage.exe /Action:Export /?
将 BACPAC 包中的架构和表数据导入到SQL Server或Microsoft Azure SQL 数据库实例中的新用户数据库中。
命令语法:
SqlPackage.exe /SourceFile:"<Bacpac file location>" /Action:Import /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>"
SqlPackage.exe /SourceFile:"C:\temp\test.bacpac" /Action:Import /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword"
sqlpackage.exe /Action:Import /?
DeployReport
创建将由发布操作完成的更改的 XML 报表。
命令语法:
SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:DeployReport /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output XML file path for deploy report>"
SqlPackage.exe /SourceFile:"E: \dacpac\ajyadb.dacpac" /Action:DeployReport /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\deployReport.xml"
sqlpackage.exe /Action:DeployReport /?
DriftReport
创建自注册数据库注册以来已对其做出的更改的 XML 报表。
命令语法:
SqlPackage.exe /Action:DriftReport /TargetServerName:"<ServerName>.database.windows.net" /TargetDatabaseName:"<DatabaseName>"
/TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output XML file path for drift report>"
SqlPackage.exe /Action:DriftReport /TargetServerName:"DemoSqlServer.database.windows.net" /TargetDatabaseName:"Testdb"
/TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\driftReport.xml"
sqlpackage.exe /Action:DriftReport /?
创建 Transact-SQL 增量更新脚本,该脚本可更新目标的架构以匹配源的架构。
命令语法:
SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:Script /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output SQL script file path>"
SqlPackage.exe /Action:Script /SourceFile:"E:\dacpac\ajyadb.dacpac" /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\test.sql"
/Variables:StagingDatabase="Staging DB Variable value"
sqlpackage.exe /Action:Script /?