Analyzing and Cleaning Your Jira Data Center Attachments (Python Tool)

There’s a deadline on the horizon. That big move from Jira Data Center to the Cloud is no longer a distant idea – it’s a project on your roadmap. You’ve audited your apps, planned the training, and everything seems under control.

Except for the 500-gigabyte gorilla in the room.

The one everyone quietly avoids discussing. It’s the decade-old archive of every file, log, screenshot, and design mockup your company has ever created, sitting silently in your Jira attachment library. To think you can migrate this digital behemoth “as-is” isn’t just optimistic; it’s one of the most costly and risky mistakes you can make.

The Diagnosis – Why Migrating Blind Is a Catastrophe

Before you can solve the problem, you have to see it. Blindly migrating your entire attachment library will sabotage your project in three silent ways:

  • The “Time Vampire” (Failed Migrations): Atlassian’s migration tools are powerful, but forcing them to move terabytes of data over the internet is a recipe for timeouts and multi-day failures. Every gigabyte of digital junk you try to move is another hour of stressful downtime you can’t afford.
  • The “Money Pit” (Paying for Junk): On-premise storage is cheap. Jira Cloud storage is not. Migrating 500 GB of attachments when your new Standard plan has a 250 GB limit means you are forced into an expensive, mandatory upgrade to the Premium plan from Day 1. You’ll be paying thousands extra each year just to host files from 2015.
  • The “Compliance Landmine” (Hidden Risks): That old attachment library is a graveyard of sensitive data—forgotten customer info, old API keys, confidential reports. Moving it to the cloud without an audit is a security and GDPR risk waiting to happen.

The only way to win is to audit and clean up before you migrate.

The Audit – Free “Pre-Migration Auditor” Tool

Manually checking thousands of projects is not an option. That’s why I built a free, open-source Python tool to do the heavy lifting for you.

Think of this tool as your Pre-Migration Auditor. It’s a simple, 100% read-only script that safely connects to your Data Center instance. It will not change or delete anything. Instead, it produces a single, beautiful HTML report that serves as your “battle plan,” revealing:

  • The true size of your attachment problem.
  • A data-driven list of “Frozen Dinosaur” files that are safe to archive.
  • A breakdown of your “heaviest” and “messiest” projects.

The Action Plan – A Phased Guide to a Clean Migration

So, you have your report. It might be showing hundreds of gigabytes of potential savings. Where do you begin? Don’t try to boil the ocean.

Propose Projects for Archival. The data in your report is your business case. Don’t just ask to archive a project; present a data-driven recommendation: “Project LEGACY is consuming 45 GB of attachment storage. Nobody has updated an issue in it for 3 years. I recommend we use Jira’s built-in Project Archival feature to safely preserve this data and dramatically reduce our migration load and future Cloud costs.”

The Future – How to Keep Your New Cloud Instance Clean

Congratulations! You’ve made a huge impact and de-risked your migration. But let’s be honest—that was a lot of manual work.

After you migrate, you don’t want to do this detective work ever again. You need an automated, 24/7 governance engine. That is exactly why I built Attachment Architect for Jira Cloud.

The free DC tool is a powerful one-time snapshot. The paid Cloud app is your live, continuous command center.

  • What if duplicate cleanup was automatic? The Cloud app has a Bulk Cleanup Center that lets you review and safely delete thousands of files in minutes.
  • What if you were alerted to ‘Dinosaurs’ proactively? The Heat Index dashboard in the Cloud app does this automatically, every single day.
  • What if you could prevent the mess before it starts? The Cloud app’s upcoming automated policies will let you set rules to block duplicates and enforce data retention.

You’ve done the hard work to prepare for your migration. Now, let’s make sure your new home in the Cloud stays clean, fast, and compliant from Day 1.

Get the Free Python Auditor on GitHub

See Attachment Architect for Jira Cloud

Favourite Filters Issue Count Performance problems in large instances (Jira)

As described in this Atlassian ticket there may be performance problems using Favourite Filters gadget in large Jira instances.

In our Jira instance (>2m issues, >10k users) these favfilters?showCounts=true requests where very expensive to CPU load.

In Atlassian ticket there is workaround provided how to turn off this feature in proxy level, but what to do if no proxy is used in front of Jira?

In our case we used Tuckey UrlRewriteFilter which is built in Jira by default. Open /jira_install_dir/atlassian-jira/WEB-INF/urlrewrite.xml and add this code before closing </urlrewrite> tag:

<rule enabled="true">
    <name>Disables Favourite Filters Issue Count</name>
    <condition type="parameter" name="showCounts" operator="equal">true</condition>
    <from>^/rest/gadget/1.0/favfilters</from>
    <to type="permanent-redirect">/rest/gadget/1.0/favfilters?showCounts=false</to>
</rule>

After Jira restart users will see “UNDEFINED” result if they turn on Issue Count functionality.

Rename attachments in Jira using Groovy

While Atlassian is “GATHERING INTEREST” to implement file renaming feature in Jira, it is possible to rename attachments using Groovy.

If you use JMWE, Scriptrunner, etc.  in Jira, you can use following Groovy script:

import org.ofbiz.core.entity.GenericValue
import com.atlassian.jira.ofbiz.OfBizDelegator
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.attachment.Attachment

def attachmentManager = ComponentAccessor.getAttachmentManager()

OfBizDelegator delegator = ComponentAccessor.getComponentOfType(OfBizDelegator.class)
issue.get("attachment")?.each {
  for(GenericValue attachment : delegator.findByField("FileAttachment", "id", it.id)){ 
      attachment.setString("filename", "no_klienta_"+it.filename)
      attachment.store()
  } 
}

 

Update Jira issues from MS Excel spreadsheet using Powershell script (updated: 13.05.2019.)

I have created Powershell script which allows to set values in Jira issues using data from MS Excel spreadsheet.

Script is based on following Powershell modules:

Usage:

  1. Set Jira server address in “update_issues.ps1” file.
  2. Update data in “data_for_issues.xlsx”
  3. Set custom field configuration according to your needs in “update_issues.ps1”
  4. Launch “update_issues.bat”, enter your Jira credentials and wait for script to complete.
  5. Log file is created next to “update_issues.ps1” file.

Download (updated: 13.05.2019.): update_issues_PS_script_V2.zip

update_issues.ps1 (updated: 13.05.2019.):

$ErrorActionPreference="SilentlyContinue"
Stop-Transcript | out-null
$ErrorActionPreference = "Continue"
Start-Transcript -path .\script\update_issues.log -append

Import-Module .\script\JiraPS
Import-Module .\script\PSExcel

####### Define some variables below ########

#Excel data file
$path = ".\data_for_issues.xlsx"

#Jira adresss
Set-JiraConfigServer -Server "https://jira-server.com"

############################################

$issues = new-object System.Collections.ArrayList

foreach ($field in (Import-XLSX -Path $path -RowStart 1))
 
{
    $issues.add($field) | out-null
}

$issuesfull = @()

foreach ($issue in $issues | Where { $_.key -and $_.key.Trim() })
{
    $i++
    $issuesfull += ($issue.key)
}

Write-Host "Pieteikumi: " $issuesfull  -ForegroundColor yellow
Write-Host "Dati tiks rakstīti" $i "pieteikumos. Tiklīdz ievadīsies lietotāja datus, tā sāksies datu rakstīšana." -ForegroundColor green
Write-Host "--------------------------------------" -ForegroundColor green

$cred = Get-Credential

foreach ($issue in $issues | Where { $_.key -and $_.key.Trim() })
{
    write-host "`n"
    $a++
    Write-Host "Izpildes statuss: " $a "/" $i -ForegroundColor gray
    Write-Host "Raksta datus pieteikumā: " $issue.key -ForegroundColor green
    Write-Host "Investīciju gads: " $issue.ig
    Write-Host "Projekta uzsākšanas gads: " $issue.pug
    Write-Host "Ranga datums: " $issue.rd.ToString('yyyy-MM-dd')
    Write-Host "Ranga vieta: " $issue.vr

## Custom field configuration

    $fields = @{
        customfield_11758 = @{
            value = [string]$issue.ig
        }
        customfield_12031 = @{
            value = [string]$issue.pug
        }
        customfield_24240 = $issue.rd.ToString('yyyy-MM-dd')
        customfield_24241 = [int]$issue.vr
    }

    Try
    {
        Set-JiraIssue -Issue $issue.key -Fields $fields -Credential $cred
        Write-Host "Dati ierakstīti pieteikumā: " $issue.key -ForegroundColor green
    }
    Catch
    {
        $ErrorMessage = $_.Exception.Message
        $FailedItem = $_.Exception.ItemName
        Write-Host "Error: $ErrorMessage" -ForegroundColor red
    }
    
}

Write-Host -NoNewLine "Datu rakstīšana pieteikumos beigusies. Nospiediet jebkuru taustiņu, lai izietu..." -ForegroundColor yellow
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');
Stop-Transcript