public/Update-JiraSql.ps1
<#
.SYNOPSIS Update a Jira SQL database with data from a Jira Cloud instance .DESCRIPTION Executes the necessary steps to update a SQL datastore of Jira data from a Jira Cloud instance A PowerJira Session must be opened with Open-JiraSession before calling this method .PARAMETER RefreshType Indicates whether to do a Full or Differential refresh. Use values from Get-JiraRefreshTypes .PARAMETER ProjectKeys Supply this parameter in order to limit the refresh to a specified set of projects. Without this parameter, the method will update all projects .PARAMETER Obfuscate Supply this parameter to obfuscate issue information in sensitive projects Issue Summary and Description will be replaced the with the string [Obfuscated] .PARAMETER SqlInstance The connection string for the SQL instance where the data will be updated .PARAMETER SqlDatabase The name of the database to perform updates in .PARAMETER SyncDeployments Use this switch to sync deployment information from third-party providers. https://developer.atlassian.com/cloud/jira/software/modules/deployment/ .EXAMPLE Open-JiraSession @jiraConnectionDetails Update-Jira -RefreshType (Get-JiraRefreshTypes).Full -SqlInstance localhost -SqlDatabase Jira Close-JiraSession Performs a full refresh of all Jira projects on a local sql database .EXAMPLE Open-JiraSession @jiraConnectionDetails $Params = @{ RefreshType = (Get-JiraRefreshTypes).Differential ProjectKeys = @("PROJKEY","MJPK","KEY3") SqlInstance = "my.remote.sql.server,1234" SqlDatabase = "Jira" } Update-Jira @Params Close-JiraSession Performs a differential refresh of 3 Jira projects on a remote Sql Server #> function Update-JiraSql { [CmdletBinding()] param ( # Refresh type [Parameter(Mandatory, Position=0)] [ValidateSet("F","D")] [string] $RefreshType, # Keys of specific projects to pull [Parameter(Position=1)] [string[]] $ProjectKeys, # Keys of projects to be obfuscated [Parameter(Position=2)] [string[]] $Obfuscate, # The sql instance to update data in [Parameter(Mandatory,Position=3)] [string] $SqlInstance, # The sql database to update data in [Parameter(Mandatory,Position=4)] [string] $SqlDatabase, # Synchronization options to override the defaults [Parameter()] [hashtable] $SyncOptions ) begin { Write-Verbose "Beginning Jira data update on $SqlInstance in database $SqlDatabase" #################################################### # CONFIGURATION # #################################################### #configure the database targets $sqlSplat = @{ SqlInstance = $SqlInstance SqlDatabase = $SqlDatabase } #setup the sync options $options = Get-DefaultJiraSyncOptions if ($SyncOptions) { $options = Merge-Hashtable -Source $SyncOptions -Target $options } #################################################### # GET PREVIOUS BATCH INFO / CLEAR PREVIOUS BATCH # #################################################### $RefreshTypes = Get-JiraRefreshTypes if ($RefreshType -eq $RefreshTypes.Full) { Clear-JiraRefresh @sqlSplat $lastRefreshStamp = 0 $lastRefreshDate = (Get-Date '1970-01-01') } else { $lastRefresh = Get-LastJiraRefresh @sqlSplat $lastRefreshStamp = $lastRefresh.Refresh_Start_Unix $lastRefreshDate = $lastRefresh.Refresh_Start } #################################################### # BEGIN THE REFRESH BATCH # #################################################### Clear-JiraStaging @sqlSplat $refreshId = Start-JiraRefresh -RefreshType $RefreshType @sqlSplat } process { #################################################### # REFRESH STEP 0 - CONFIGURE # #################################################### # define a convenient hash for splatting the basic refresh arguments $refreshSplat = @{ RefreshId = $refreshId } + $sqlSplat #################################################### # REFRESH STEP 1 - NO CONTEXT DATA # #################################################### # these are mostly lookup tables if ($options.ProjectCategories) { Update-JiraProjectCategories @refreshSplat } else { Write-Verbose "Skipping Project Categories" } if ($options.StatusCategories) { Update-JiraStatusCategories @refreshSplat } else { Write-Verbose "Skipping Status Categories" } if ($options.Statuses) { Update-JiraStatuses @refreshSplat } else { Write-Verbose "Skipping Statuses" } if ($options.Resolutions) { Update-JiraResolutions @refreshSplat } else { Write-Verbose "Skipping Resolutions" } if ($options.Priorities) { Update-JiraPriorities @refreshSplat } else { Write-Verbose "Skipping Priorities" } if ($options.IssueLinkTypes) { Update-JiraIssueLinkTypes @refreshSplat } else { Write-Verbose "Skipping Issue Link Types" } if ($options.Users) { Update-JiraUsers @refreshSplat } else { Write-Verbose "Skipping Users" } #################################################### # REFRESH STEP 2 - PROJECTS # #################################################### if ($options.Projects) { # update projects, and in the process get a full project key list if necessary $refreshProjectKeys = Update-JiraProjects -ProjectKeys $ProjectKeys @refreshSplat | ForEach-Object { $_.Project_Key } } else { $refreshProjectKeys = $ProjectKeys Write-Verbose "Skipping Projects" } #################################################### # REFRESH STEP 3 - PROJECT TAXONS # #################################################### if ($options.Projects) { # next do the updates where the only context is the list of projects Update-JiraVersions -ProjectKeys $refreshProjectKeys @refreshSplat Update-JiraComponents -ProjectKeys $refreshProjectKeys @refreshSplat } else { Write-Verbose "Skipping Project Taxons" } #################################################### # REFRESH STEP 4 - WORKLOGS # #################################################### if ($options.Worklogs) { # worklogs are refreshed based on the last unix timestamp of a refresh # need to both update changed / new worklogs, and remove any that have been deleted Update-JiraWorklogs -LastRefreshUnix $lastRefreshStamp @refreshSplat Remove-JiraWorklogs -LastRefreshUnix $lastRefreshStamp @sqlSplat } else { Write-Verbose "Skipping Worklogs" } #################################################### # REFRESH STEP 5 - ISSUES # #################################################### if ($options.Issues) { # issues are retrieved using jql crafted from the date of last refresh and optionally a project key list # first format the date stamp and create the updated date clause $jqlUpdateDate = (Get-Date $lastRefreshDate -format "yyyy-MM-dd HH:mm") $updateJql = "updatedDate >= '$jqlUpdateDate'" # if we're refreshing a specific list of projects, create the clause; otherwise, don't add a project clause $projectJql = if($null -eq $ProjectKeys -or $ProjectKeys.Count -eq 0) { "" } else { " AND Project in (" + ($refreshProjectKeys -join ",") + ")" } # update issues with the crafted JQL Update-JiraIssues -Jql ($updateJql + $projectJql) -Obfuscate $Obfuscate -SyncDeployments:$options.Deployments @refreshSplat #if we're doing a diff refresh, pull down ALL issue IDs for the listed projects, in order to detect deleted issues $deleteRetrieveSuccess = $false if ($RefreshType -eq (Get-JiraRefreshTypes).Differential) { # use the project list if we're doing a list, otherwise use a "true = true" type clause to get everything $deleteRetrieveSuccess = if ($null -eq $ProjectKeys) { Update-JiraDeletedIssues -Jql "project is not EMPTY" @sqlSplat } else { Update-JiraDeletedIssues -Jql $projectJql @sqlSplat } } } else { Write-Verbose "Skipping Issues" } #################################################### # REFRESH STEP 6 - SYNC STAGING TO LIVE TABLES # #################################################### #determine if deletes should be synced $syncDelete = $deleteRetrieveSuccess -and ($RefreshType -eq $RefreshTypes.Differential) #perform the sync Sync-JiraStaging -SyncDeleted $syncDelete @sqlSplat } end { #################################################### # RECORD BATCH END # #################################################### Stop-JiraRefresh @refreshSplat Write-Verbose "Jira update completed!" } } |