How can I copy the last attachment from a Jira issue to another?

Sadek Joma'a October 22, 2015

Hi,

I have a workflow where in each step a file is attached to the issue. At the end I want to copy the LAST attached file only from this issue to another issue. How can I do that?

to be more clear: I know how to copy A file, but I don't know how to copy the LAST one only.

I have tried to do that with JJUPIN SIL, but I could not because SIL stores the attachments in alphabetical order and does not store any date-time info about them. So you can not determine which file was attached last. (I have discovered that by testing only. So, please correct if I am mistaken!)

Any help would be appreciated.

6 answers

1 accepted

1 vote
Answer accepted
eric anier
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 22, 2015

Hi Sadek,

You may use the sql() routine of JJUPIN to directly query the attachment table FILEATTACHMENT and sort it by created.

 

Regards,

Sadek Joma'a October 22, 2015

Hi Eric, Thanks for the suggested solution. I think this should work for me. But I have faced one problem: finding the datasource JNDI name that I should use. I am using my Jira server (6.4.9) with MySQL DB and I don't know from where should I get the datasource JNDI name. Can you help me with that. can I use the datasource name stated in the dbconfig.xml file. The content of the file is as follows: <?xml version="1.0" encoding="UTF-8" ?> <jira-database-config> <name>defaultDS</name> <delegator-name>default</delegator-name> <database-type>mysql</database-type> <jdbc-datasource> <url>jdbc:mysql://localhost:3306/jiradb?useUnicode=true&characterEncoding=UTF8&sessionVariables=storage_engine=InnoDB</url> <driver-class>com.mysql.jdbc.Driver</driver-class> <username>jirauser</username> <password>jirapass</password> <pool-min-size>20</pool-min-size> <pool-max-size>20</pool-max-size> <pool-max-wait>30000</pool-max-wait> <validation-query>select 1</validation-query> <min-evictable-idle-time-millis>60000</min-evictable-idle-time-millis> <time-between-eviction-runs-millis>300000</time-between-eviction-runs-millis> <pool-max-idle>20</pool-max-idle> <pool-remove-abandoned>true</pool-remove-abandoned> <pool-remove-abandoned-timeout>300</pool-remove-abandoned-timeout> <pool-test-while-idle>true</pool-test-while-idle> <validation-query-timeout>3</validation-query-timeout> </jdbc-datasource> </jira-database-config> or I must add a datasource in context.xml as instructed in the documentation of SIL ? Many thanks, Sadek

eric anier
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 22, 2015

Hi Sadek, Yes you have to define it on context.html

Sadek Joma'a October 23, 2015

Ok. I have added the following code to context.xml: <Resource name="JiraDBsql" auth="Container" type="javax.sql.DataSource" username="jiradbuser" password="jiradbpass" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://127.0.0.1:3306/jiradb" /> and now it DOES work. I will try the attachment manipulations I need now. :) Thanks for the help and for the great plug in.

Sadek Joma'a October 26, 2015

I have used this to re-order the attachments successfully. Moreover, I have just learned from Alexandra Topoloaga from Kepler-Rominfo that you can use the same method to re-name the attached files. Simply edit the FILENAME field of the fileattachment table and the file name is changed. I mean there is no need to edit anything on the hard disk of the server !

4 votes
Kristian Walker _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
October 27, 2015

Hi Sadek,

I have enclosed a Script Runner solution below of how you can copy the previous attachment from an issue over to another issue.

This code can be edited if needed to automatically specify the issue key of the issue that the attachment should be copied to.

import com.atlassian.jira.component.ComponentAccessor
import org.apache.log4j.Category
import com.atlassian.jira.issue.Issue;

def Category log = Category.getInstance("com.onresolve.jira.groovy.PostFunction");
log.setLevel(org.apache.log4j.Level.DEBUG);

// Get the current issue key
Issue issueKey = issue
def id = issueKey.getId()

// Get the current logged in user
def user = ComponentAccessor.getJiraAuthenticationContext().getUser().name

// Get a manager to handle the copying of attachments
def attachmentManager = ComponentAccessor.getAttachmentManager()

// Get the default attachment path from its manager 
def attachmentPathManager = ComponentAccessor.getAttachmentPathManager().attachmentPath.toString()

// Get the current date
def today = new Date()

// Get the last attachments file properties needed by the attachment manager to copy it.

def fileName = issueKey.attachments.last()?.filename.toString()
def fileType = issueKey.attachments.last()?.mimetype.toString()

// Construct the key of the next Subtask
def currentIssue = issue.toString()

// Extract the project key from the issue
def projectKey = currentIssue.replaceAll("[^A-Z]", "").toString();

// Get the ID that jira has used to store the last attachment
def fileId = issueKey.attachments.last()?.id

// Construct the file path of the attachment to copy
def path = attachmentPathManager + "/" + projectKey + "/" + currentIssue + "/" + fileId + "/"

// Construct a pointer to the file that will be copied
File filePath = new File(path.toString())

// Specify the issue to copy the attachment to here. This could be defined in code.
Issue subIssue = ComponentAccessor.getIssueManager().getIssueObject("KDP-100")

// If there is a previous attachment
if (fileName != null) {
// Attach the file to the new issue
    attachmentManager.createAttachmentCopySourceFile(filePath, fileName, fileType, user, subIssue, null, today)
}

 

I hope this helps

 

Kristian

Sadek Joma'a October 27, 2015

Thank you Kristian. This a big effort you have made here. I am sure it will be helpful for me and others. Sadek

Kristian Walker _Adaptavist_
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
October 27, 2015

You are welcome Sadek. Please let me know if helps you to solve your issue. Kristian

Mete Erzincanli November 5, 2018

Kristian,

attachments.last() 

doesn't take the latest attachment since the list is sorted alphabetically.

0 votes
Isaac_Philip April 11, 2017

The best would be to use the attachmentManager.copyAttachments method to achieve this task.

attachmentManager.copyAttachments()

0 votes
Manojkumar V October 4, 2016

Hi Sadek,

I have a similar requirement to copy the attachments in one issue to other issue. As you have mentioned "I know how to copy a file" Could you please tell how did you achieve this with SIL. I just want to copy all the attachments in an issue.

0 votes
MClementCH July 13, 2016

As I use a similiar function with SIL (JJupin) I wrote the following function which I share with you. Todo would be a better error handling and there's currently no way I know to remove the directory created in "SIL tmp"; the files get deleted after attaching to target issue:

function copyAttachments(string sourceKey, string targetKey)
{
    const string _targetPath = replace(silEnv("sil.home"), "\\", "/") + "/../tmp/" + sourceKey;
    string [] _attachmentList;
    
    // unique array of attachments
    for(string attachment in sourceKey.attachments) {
        _attachmentList = arrayAddElementIfNotExist(_attachmentList, attachment);
    }
    
    for(string attachment in _attachmentList) {
        string [] filePaths = getAttachmentPath(sourceKey, attachment);
        if(arraySize(filePaths) &gt; 1) {
            for(int i=0; i &lt; arraySize(filePaths); i++) {
                string sourceFilePath = replace(filePaths[i], "\\", "/");
                string targetFile = replace(attachment, ".", "_" + (i+1) + ".");
                string targetFilePath = _targetPath + "/" + targetFile;
                if(createDirectory(_targetPath)) {
                    fileCopy(sourceFilePath, targetFilePath);
                    attachFile(targetFilePath, targetKey);
                    deleteFile(targetFilePath);
                }
            }
        }
        else {
            string sourceFilePath = replace(filePaths[0], "\\", "/");
            string targetFile = attachment;
            string targetFilePath = _targetPath + "/" + targetFile;
            if(createDirectory(_targetPath)) {
                fileCopy(sourceFilePath, targetFilePath);
                attachFile(targetFilePath, targetKey);
                deleteFile(targetFilePath);
            }
        }
    }
    return;
}
copyAttachments("SPIKS-70", "SPIKS-71");
return "OK";
0 votes
MClementCH July 12, 2016

With SIL (in JJuping or BlitzActions) you may iterate through the attachments of an issue and get the file path therefore...

 

string temp = "";
for(string attachment in attachments) {
    string [] filePaths = getAttachmentPath(key, attachment);
    for (string fileName in filePaths) {
        temp = temp + "--- " + attachment + " -&gt; " + fileName;
    }
}
return isNull(temp) ? "Sorry, no attachments in " + key : temp;

Suggest an answer

Log in or Sign up to answer