{"id":39220,"date":"2020-05-14T06:00:35","date_gmt":"2020-05-14T13:00:35","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/premier-developer\/?p=39220"},"modified":"2020-04-28T14:25:13","modified_gmt":"2020-04-28T21:25:13","slug":"using-azure-devops-pipelines-with-redgate-to-automate-oracle-database-deployments","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/premier-developer\/using-azure-devops-pipelines-with-redgate-to-automate-oracle-database-deployments\/","title":{"rendered":"Using Azure DevOps Pipelines with Redgate to Automate Oracle Database Deployments"},"content":{"rendered":"<p>Application Development Manager <a href=\"https:\/\/www.linkedin.com\/in\/jafar-jaffery-5664883\/\">Jafar Jaffery<\/a> demonstrates using DevOps build and release pipelines to streamline development changes to your Oracle databases.<\/p>\n<hr \/>\n<p>In this post, I will cover a basic end to end-to-end example of taking a local Oracle database, setting up a project in a Git repository and using a Continuous Integration \/ Continuous Delivery (CI\/CD) pipeline to take your database changes from code through to production. I will use <a href=\"https:\/\/azure.microsoft.com\/services\/devops\/\">Azure DevOps<\/a> as the foundation for my CI\/CD pipeline, and will use Redgate Tools (<a href=\"https:\/\/www.red-gate.com\/products\/oracle-development\/source-control-for-oracle\/\">Source Control for Oracle<\/a> \/ <a href=\"https:\/\/www.red-gate.com\/products\/oracle-development\/schema-compare-for-oracle\/\">Schema Compare for Oracle<\/a>) to perform the build &amp; release steps. Database development and deployment in Oracle is an involved effort with many moving parts, and using the products previously mentioned helps streamline the process.<\/p>\n<p>Below is a diagram of the pipeline that this post will cover. We won&#8217;t cover topics like unit testing or restoring data from other environment as part of the pipeline, but instead focus on the core components needed to get started with database deployments with Oracle databases. The process will start by committing changes to source control, which will kick off the build &amp; publish artifact steps. Once that completes, our changes will be deployed first to a testing environment, and upon approval be promoted to a production environment. This can be extended to have as many environments as needed, but for simplicity we will stick to these two environments.<\/p>\n<p><img decoding=\"async\" width=\"708\" height=\"274\" class=\"wp-image-39222\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image.png 708w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-300x116.png 300w\" sizes=\"(max-width: 708px) 100vw, 708px\" \/><\/p>\n<h2>Build Server \/ Agent Pool<\/h2>\n<p>In order to perform build and release tasks for an Oracle database, we will need to have a build server that has the requisite components. To achieve this, I started with Windows Server 2019. Additional components you&#8217;ll need to add are Oracle Client (I used the <a href=\"https:\/\/www.oracle.com\/database\/technologies\/oracle18c-windows-180000-downloads.html\">18c Client<\/a> for Windows for my setup), and Redgate Schema Compare for Oracle. Once the build server is setup, you&#8217;ll also need to create a new agent pool using <a href=\"https:\/\/docs.microsoft.com\/azure\/devops\/pipelines\/agents\/pools-queues?view=azure-devops&amp;tabs=yaml%2Cbrowser\">these steps<\/a>, and add a virtual machine as a new <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/devops\/pipelines\/agents\/v2-windows?view=azure-devops\">self-hosted agent<\/a> to that agent pool. We will refer to this agent pool as &#8220;Oracle Pipelines&#8221; for our example, and will later use this agent pool to perform our build and release steps.<\/p>\n<h2>Source Control<\/h2>\n<p><img decoding=\"async\" width=\"171\" height=\"118\" class=\"wp-image-39223\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-1.png\" \/><\/p>\n<p>For the source code, we will be using two different source control systems. The first one will be setup with an Azure DevOps Git repository (we&#8217;ll call it &#8220;OracleSandbox&#8221;) as our main repository for database code. It will also be used to initiate our CI Pipeline when a change is committed. The other will be Source Control for Oracle, which will be used to synchronize changes between local databases and our main Azure DevOps repository. Source Control for Oracle lets developers make changes directly in the database without having to manually script changes &amp; organize them into a database folder structure. It also facilitates developer collaboration during database development.<\/p>\n<p>To create a new source control project, follow the steps shown <a href=\"https:\/\/documentation.red-gate.com\/soco\/setting-up\/creating-a-new-source-control-project\">here<\/a> on the Redgate site. Redgate also has a series of <a href=\"https:\/\/www.red-gate.com\/hub\/university\/courses\/source-control-for-oracle\/source-control-for-oracle\">getting started videos<\/a> that cover a variety of source control topics like creating a new project, branching with Git, and conflict resolution. Once setup, the Git repository should look something like this:<\/p>\n<p><img decoding=\"async\" width=\"413\" height=\"471\" class=\"wp-image-39224\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-2.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-2.png 413w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-2-263x300.png 263w\" sizes=\"(max-width: 413px) 100vw, 413px\" \/><\/p>\n<h2>CI Pipeline<\/h2>\n<p><img decoding=\"async\" width=\"274\" height=\"140\" class=\"wp-image-39225\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-3.png\" \/><\/p>\n<p>The build pipeline will perform the following tasks:<\/p>\n<ol>\n<li>Validate the source schema in our Git repository.<\/li>\n<li>Package the project files into an artifact. In this case it will be a .zip file, but it could also be a NuGet package or some other type as well.<\/li>\n<li>Publish the artifact.<\/li>\n<\/ol>\n<p>In this example, I&#8217;ve created the build pipeline using the classic editor, and started with an &#8220;Empty Job&#8221;. You you can do this using YAML pipelines as well. For more information on pipelines, you can start with <a href=\"https:\/\/docs.microsoft.com\/azure\/devops\/pipelines\/get-started\/pipelines-get-started?view=azure-devops\">this doc<\/a> as well as this <a href=\"https:\/\/docs.microsoft.com\/azure\/devops\/pipelines\/create-first-pipeline?view=azure-devops&amp;tabs=net%2Cclassic%2Cbrowser%2Ctfs-2018-2\">guide<\/a>. As a note, set the Agent Pool to the one created earlier, namely &#8220;Oracle Pipelines&#8221;.<\/p>\n<p><img decoding=\"async\" width=\"1300\" height=\"611\" class=\"wp-image-39227\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-5.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-5.png 1300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-5-300x141.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-5-1024x481.png 1024w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-5-768x361.png 768w\" sizes=\"(max-width: 1300px) 100vw, 1300px\" \/><\/p>\n<p>The validation script uses SQLPlus &amp; Redgate Schema Compare for Oracle to create a new temporary schema from the definition in our Git repository, and then removes that schema. This is done to ensure the schema definition in our Git repository is valid. As a reference, here is the PowerShell script I&#8217;m using for this:<\/p>\n<pre class=\"prettyprint\"># this script creates a target DB using the source schema (to validate it works), and then deletes that target schema\r\nparam (\r\n   $schemaCompareExePath,\u00a0\u00a0# location of Redgate SCO EXE\r\n   $sourceSchemaName, # source schema name from source control\r\n   $sourceSchemaRelativePath,\u00a0\u00a0# relative path of schema from source control root folder\r\n   $targetSchemaName, # target schema name to be created for validation purposes\r\n   $buildLocalPath, # local path where build files will be located\r\n   $sqlPlusConnStr, # connection string for SQL Plus commands\r\n   # connection \/ creds for Redgate Schema Compare\r\n   $tnsName,\r\n   $userName,\r\n   $password\r\n)\r\n$ErrorActionPreference = \"Stop\"\r\n$createQuery = \"CREATE USER $targetSchemaName IDENTIFIED by null; GRANT \"\"DBA\"\" TO $targetSchemaName; ALTER USER $targetSchemaName DEFAULT ROLE \"\"DBA\"\";\"\r\n\r\n# Create empty schema for validation\r\n$createQuery | sqlplus $sqlPlusConnStr | Out-Host\r\n\r\n# Deploy changes using Redgate Schema Compare for Oracle\r\nWrite-Warning \"Upgrading $targetSchemaName\"\r\n\r\ntry {\r\n   &amp; $schemaCompareExePath -source \"$buildLocalPath\\$sourceSchemaRelativePath{$sourceSchemaName}\" -target \"$userName\/$password@$tnsName{$targetSchemaName}\" AS SYSDBA -deploy | Out-Host\r\n\r\n   # Logging the Schema Compare exit code and path to artifacts\r\n   Write-Output \"Schema Compare for Oracle exited with code $lastExitCode\"\r\n}\r\nfinally {\r\n   # drop the validation schema created\r\n   $dropQuery = \"DROP USER $targetSchemaName CASCADE;\"\r\n   $dropQuery | sqlplus $sqlPlusConnStr | Out-Host\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h2><img decoding=\"async\" width=\"256\" height=\"201\" class=\"wp-image-39229\" style=\"font-size: 1rem;\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-7.png\" \/>CD Pipeline<\/h2>\n<p>The release pipeline will perform the following tasks:<\/p>\n<ol>\n<li>Unzip\/unpack the artifact contents.<\/li>\n<li>Deploy the changes using Redgate Schema Compare, wrapped in PowerShell in this example.<\/li>\n<\/ol>\n<p>For information on how to create release pipelines, view the Microsoft documentation <a href=\"https:\/\/docs.microsoft.com\/azure\/devops\/pipelines\/release\/?view=azure-devops\">here<\/a>. Here are the things you need to set up in your pipeline:<\/p>\n<p><img decoding=\"async\" width=\"1275\" height=\"593\" class=\"wp-image-39230\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-8.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-8.png 1275w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-8-300x140.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-8-1024x476.png 1024w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-8-768x357.png 768w\" sizes=\"(max-width: 1275px) 100vw, 1275px\" \/><\/p>\n<p><strong>Note<\/strong>: be sure to set the Agent Pool (in the Agent Job) to the one created earlier, namely &#8220;Oracle Pipelines&#8221; &#8212; as shown here:<\/p>\n<p><img decoding=\"async\" width=\"970\" height=\"610\" class=\"wp-image-39232\" src=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-10.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-10.png 970w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-10-300x189.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/05\/word-image-10-768x483.png 768w\" sizes=\"(max-width: 970px) 100vw, 970px\" \/><\/p>\n<p>Here is the PowerShell script I&#8217;m using for the release DB deployment:<\/p>\n<pre class=\"prettyprint\">param (\r\n   $schemaCompareExePath,\u00a0\u00a0# location of Redgate SCO EXE\r\n   $sourceSchemaName, # source schema name from source control\r\n   $sourceSchemaRelativePath,\u00a0\u00a0# relative path of schema from source control root folder\r\n   $releaseLocalPath, # local path where build files will be located\r\n   $targetSchemaName, # target schema name to be created for validation purposes\r\n   # connection \/ creds for Redgate Schema Compare\r\n   $tnsName,\r\n   $userName,\r\n   $password\r\n)\r\n\r\n# perform deployment with Redgate Schema Compare\r\n&amp; \"$schemaCompareExePath\" \/source:\"$releaseLocalPath\\$sourceSchemaRelativePath{$sourceSchemaName}\" \/target:\"$userName\/$password@$tnsName{$targetSchemaName}\" AS SYSDBA \/deploy\r\nWrite-Output \"Schema Compare for Oracle exited with code $lastExitCode\"\r\n\r\n# exit code of 61 (differences in source\/target schemas) is not actually an error, but ends up being treated like one -- so adding logic to ignore that\r\nIf ($lastExitCode = 61) {\r\n   exit 0\r\n}<\/pre>\n<p>&nbsp;<\/p>\n<h2>Closing Thoughts<\/h2>\n<p>As mentioned earlier, the pipeline described in this post is not meant to be a comprehensive one. Rather, it is intended to be a starting point for automating your Oracle deployments. For additional considerations in your Oracle database DevOps process, Redgate has a good whitepaper <a href=\"http:\/\/assets.red-gate.com\/products\/oracle-development\/deployment-suite-for-oracle\/database-devops-with-deployment-suite-for-oracle.pdf\">here<\/a>.<\/p>\n<p>Below are some additional references for your consideration:<\/p>\n<ul>\n<li>Schema Compare for Oracle 5 &#8211; Using the command line\n<a href=\"https:\/\/documentation.red-gate.com\/sco\/using-the-command-line\">https:\/\/documentation.red-gate.com\/sco\/using-the-command-line<\/a><\/li>\n<li>Permissions required to use Schema Compare for Oracle\n<a href=\"https:\/\/documentation.red-gate.com\/sco\/requirements\/permissions-required-to-use-schema-compare-for-oracle\">https:\/\/documentation.red-gate.com\/sco\/requirements\/permissions-required-to-use-schema-compare-for-oracle<\/a><\/li>\n<li>Database build &#8211; Database DevOps for Oracle &#8211; Product Documentation\n<a href=\"https:\/\/documentation.red-gate.com\/ddfo\/automated-build-and-test\/database-build\">https:\/\/documentation.red-gate.com\/ddfo\/automated-build-and-test\/database-build<\/a><\/li>\n<li>Deployments &#8211; Database DevOps for Oracle &#8211; Product Documentation\n<a href=\"https:\/\/documentation.red-gate.com\/ddfo\/release-management\/deployments\">https:\/\/documentation.red-gate.com\/ddfo\/release-management\/deployments<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post, I will cover a basic end to end-to-end example of taking a local Oracle database, setting up a project in a Git repository and using a Continuous Integration \/ Continuous Delivery (CI\/CD) pipeline to take your database changes from code through to production.<\/p>\n","protected":false},"author":582,"featured_media":37933,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[8,22,1],"tags":[40,21,3],"class_list":["post-39220","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-data","category-devops","category-permierdev","tag-development","tag-devops","tag-team"],"acf":[],"blog_post_summary":"<p>In this post, I will cover a basic end to end-to-end example of taking a local Oracle database, setting up a project in a Git repository and using a Continuous Integration \/ Continuous Delivery (CI\/CD) pipeline to take your database changes from code through to production.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/39220","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/users\/582"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/comments?post=39220"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/39220\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media\/37933"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media?parent=39220"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/categories?post=39220"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/tags?post=39220"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}