Tarefa de implantação do banco de dados SQL do Azure

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Você pode implantar automaticamente suas atualizações de banco de dados em um banco de dados SQL do Azure após cada build bem-sucedido.

DACPAC

A maneira mais simples de implantar um banco de dados é criar um pacote da camada de dados ou DACPAC. OS DACPACs podem ser usados para empacotar e implantar dados e alterações de esquema. Você pode criar um DACPAC usando o projeto de banco de dados SQL no Visual Studio.

Para implantar um DACPAC em um banco de dados SQL do Azure, adicione o trecho de código a seguir ao arquivo 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>'

Confira também informações de autenticação ao usar a tarefa implantação de banco de dados SQL do Azure.

Scripts SQL

Em vez de usar um DACPAC, você também pode usar scripts SQL para implantar seu banco de dados. Aqui está um exemplo simples de um script SQL que cria um banco de dados vazio.

  USE [main]
  GO
  IF NOT EXISTS (SELECT name FROM main.sys.databases WHERE name = N'DatabaseExample')
  CREATE DATABASE [DatabaseExample]
  GO

Para executar scripts SQL como parte de um pipeline, você precisará de scripts do Azure PowerShell para criar e remover regras de firewall no Azure. Sem as regras de firewall, o agente do Azure Pipelines não pode se comunicar com o Banco de Dados SQL do Azure.

O script do PowerShell a seguir cria regras de firewall. Você pode marcar nesse script como SetAzureFirewallRule.ps1 no repositório.

ARM

[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

Clássico

[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 -RuleName $FirewallRuleName -ServerName $ServerName
}

function Update-AzureSQLServerFirewallRule{
  $agentIP= (New-Object net.webclient).downloadstring("https://api.ipify.org")
  Set-AzureSqlDatabaseServerFirewallRule -StartIPAddress $agentIp -EndIPAddress $agentIp -RuleName $FirewallRuleName -ServerName $ServerName
}

if ((Get-AzureSqlDatabaseServerFirewallRule -ServerName $ServerName -RuleName $FirewallRuleName -ErrorAction SilentlyContinue) -eq $null)
{
  New-AzureSQLServerFirewallRule
}
else
{
  Update-AzureSQLServerFirewallRule
}

O script do PowerShell a seguir remove as regras de firewall. Você pode marcar nesse script como RemoveAzureFirewallRule.ps1 no repositório.

ARM

[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

Clássico

[CmdletBinding(DefaultParameterSetName = 'None')]
param
(
  [String] [Parameter(Mandatory = $true)] $ServerName,
  [String] [Parameter(Mandatory = $true)] $ResourceGroupName,
  [String] $FirewallRuleName = "AzureWebAppFirewall"
)

$ErrorActionPreference = 'Stop'

if ((Get-AzureSqlDatabaseServerFirewallRule -ServerName $ServerName -RuleName $FirewallRuleName -ErrorAction SilentlyContinue))
{
  Remove-AzureSqlDatabaseServerFirewallRule -RuleName $FirewallRuleName -ServerName $ServerName
}

Adicione o seguinte ao arquivo azure-pipelines.yml para executar um script SQL.

variables:
  AzureSubscription: '<SERVICE_CONNECTION_NAME>'
  ResourceGroupName: '<RESOURCE_GROUP_NAME>'
  ServerName: '<DATABASE_SERVER_NAME>'
  ServerFqdn: '<DATABASE_FQDN>'
  DatabaseName: '<DATABASE_NAME>'
  AdminUser: '<DATABASE_USERNAME>'
  AdminPassword: '<DATABASE_PASSWORD>'
  SQLFile: '<LOCATION_OF_SQL_FILE_IN_$(Build.SourcesDirectory)>'

steps:
- task: AzurePowerShell@5
  displayName: 'Azure PowerShell script'
  inputs:
    azureSubscription: '$(AzureSubscription)'
    ScriptType: filePath
    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'
  inputs:
    azureSubscription: '$(AzureSubscription)'
    ScriptType: filePath
    ScriptPath: '$(Build.SourcesDirectory)\scripts\RemoveAzureFirewallRule.ps1'
    ScriptArguments: '-ServerName $(ServerName) -ResourceGroupName $(ResourceGroupName)'
    azurePowerShellVersion: LatestVersion

Conexão de serviço do Azure

A tarefa Implantação de Banco de Dados SQL do Azure é o mecanismo principal para implantar um banco de dados no Azure. Essa tarefa, assim como acontece com outras tarefas internas do Azure, requer uma conexão de serviço do Azure como entrada. A conexão de serviço do Azure armazena as credenciais para se conectar do Azure Pipelines com o Azure.

A maneira mais fácil de começar com essa tarefa é estar conectado como um usuário que detém a organização do Azure DevOps e a assinatura do Azure. Nesse caso, você não precisará criar manualmente a conexão de serviço. Caso contrário, para saber como criar uma conexão de serviço do Azure, confira Criar uma conexão de serviço do Azure.

Para saber como criar uma conexão de serviço do Azure, confira Criar uma conexão de serviço do Azure.

Implantando condicionalmente

Você pode optar por implantar apenas determinadas compilações no banco de dados do Azure.

Para fazer isso no YAML, você pode usar uma destas técnicas:

  • Isole as etapas de implantação em um trabalho separado e adicione uma condição a esse trabalho.
  • Adicione uma condição à etapa.

O exemplo a seguir mostra como usar condições de etapa para implantar somente builds originados da ramificação principal.

- 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>'

Para saber mais sobre condições, confira Especificar condições.

Mais ações do SQL

Implantação do Dacpac do SQL Azure pode não dar suporte a todas as ações do SQL Server que você deseja executar. Nesses casos, você pode simplesmente usar o PowerShell ou scripts de linha de comando para executar os comandos necessários. Esta seção mostra alguns dos casos de uso comuns para invocar a ferramenta SqlPackage.exe. Como pré-requisito para executar essa ferramenta, você deve usar um agente auto-hospedado e ter a ferramenta instalada em seu agente.

Observação

Se você executar o SQLPackage na pasta em que ele está instalado, deverá prefixar o caminho com & e encapsulá-lo entre aspas duplas.

Sintaxe básica

<Path of SQLPackage.exe> <Arguments to SQLPackage.exe>

Você pode usar qualquer um dos scripts SQL a seguir, dependendo da ação que deseja executar

Extract

Cria um arquivo (.dacpac) de instantâneo de um banco de dados do SQL Server dinâmico ou do Banco de Dados SQL do Microsoft Azure.

Sintaxe de comando:

SqlPackage.exe /TargetFile:"<Target location of dacpac file>" /Action:Extract
/SourceServerName:"<ServerName>.database.windows.net"
/SourceDatabaseName:"<DatabaseName>" /SourceUser:"<Username>" /SourcePassword:"<Password>"

ou

SqlPackage.exe /action:Extract /tf:"<Target location of dacpac file>"
/SourceConnectionString:"Data Source=ServerName;Initial Catalog=DatabaseName;Integrated Security=SSPI;Persist Security Info=False;"

Exemplo:

SqlPackage.exe /TargetFile:"C:\temp\test.dacpac" /Action:Extract /SourceServerName:"DemoSqlServer.database.windows.net"
 /SourceDatabaseName:"Testdb" /SourceUser:"ajay" /SourcePassword:"SQLPassword"

Ajuda:

sqlpackage.exe /Action:Extract /?

Publicação

atualiza um esquema de banco de dados incrementalmente para que corresponda ao esquema de um arquivo .dacpac de origem. Se o banco de dados não existir no servidor, a operação de publicação o criará. Caso contrário, será atualizado um banco de dados existente.

Sintaxe de comando:

SqlPackage.exe /SourceFile:"<Dacpac file location>" /Action:Publish /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password> "

Exemplo:

SqlPackage.exe /SourceFile:"E:\dacpac\ajyadb.dacpac" /Action:Publish /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb4" /TargetUser:"ajay" /TargetPassword:"SQLPassword"

Ajuda:

sqlpackage.exe /Action:Publish /?

Exportação

exporta um banco de dados dinâmico – incluindo o esquema e os dados de usuário do banco de dados – do SQL Server ou do Banco de Dados SQL do Microsoft Azure para um pacote BACPAC (arquivo .bacpac).

Sintaxe de comando:

SqlPackage.exe /TargetFile:"<Target location for bacpac file>" /Action:Export /SourceServerName:"<ServerName>.database.windows.net"
/SourceDatabaseName:"<DatabaseName>" /SourceUser:"<Username>" /SourcePassword:"<Password>"

Exemplo:

SqlPackage.exe /TargetFile:"C:\temp\test.bacpac" /Action:Export /SourceServerName:"DemoSqlServer.database.windows.net"
/SourceDatabaseName:"Testdb" /SourceUser:"ajay" /SourcePassword:"SQLPassword"

Ajuda:

sqlpackage.exe /Action:Export /?

Importar

importa os dados de esquema e tabela de um pacote BACPAC para um novo banco de dados do usuário em uma instância do SQL Server ou do Banco de Dados SQL do Microsoft Azure.

Sintaxe de comando:

SqlPackage.exe /SourceFile:"<Bacpac file location>" /Action:Import /TargetServerName:"<ServerName>.database.windows.net"
/TargetDatabaseName:"<DatabaseName>" /TargetUser:"<Username>" /TargetPassword:"<Password>"

Exemplo:

SqlPackage.exe /SourceFile:"C:\temp\test.bacpac" /Action:Import /TargetServerName:"DemoSqlServer.database.windows.net"
/TargetDatabaseName:"Testdb" /TargetUser:"ajay" /TargetPassword:"SQLPassword"

Ajuda:

sqlpackage.exe /Action:Import /?

DeployReport

cria um relatório XML das alterações que teriam sido feitas por uma ação de publicação.

Sintaxe de comando:

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>"

Exemplo:

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" 

Ajuda:

sqlpackage.exe /Action:DeployReport /?

DriftReport

cria um relatório XML das alterações que teriam sido feitas a um banco de dados registrado desde o último registro.

Sintaxe de comando:

SqlPackage.exe /Action:DriftReport /TargetServerName:"<ServerName>.database.windows.net" /TargetDatabaseName:"<DatabaseName>"
/TargetUser:"<Username>" /TargetPassword:"<Password>" /OutputPath:"<Output XML file path for drift report>"

Exemplo:

SqlPackage.exe /Action:DriftReport /TargetServerName:"DemoSqlServer.database.windows.net" /TargetDatabaseName:"Testdb"
/TargetUser:"ajay" /TargetPassword:"SQLPassword" /OutputPath:"C:\temp\driftReport.xml"

Ajuda:

sqlpackage.exe /Action:DriftReport /?

Script

cria um script de atualização incremental Transact-SQL que atualiza o esquema de um destino para que corresponda ao esquema de origem.

Sintaxe de comando:

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>"

Exemplo:

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"

Ajuda:

sqlpackage.exe /Action:Script /?