How to sync worklogs from Jira Cloud to Jira Server (both use Tempo)

Originally asked by Andrew Hines on 10 June 2020 (original question)


Hi - I’m new to Exalate so please bear with me :wink:

We’re using both JIRA Cloud and JIRA Server. Most data is held on JIRA Server so we would like the Tempo time (worklogs) to be synced from Cloud back to Server so we can report on it in one place.

What’s most important is knowing the Hours, Issue Name, Account and User.

I have read the help documentation and set up a connection outbound from the Cloud end. Outgoing Sync has this code:

TempoWorkLogSync.send(
"OM72xP3i1IxEgUT4YR1dmAHNRXcOEw ", // that’s not my real key btw
replica,
issue,
httpClient,
nodeHelper
)

Incoming Sync is blank.

I don’t have a trigger. Triggers only seem to work for issues and sprints. So my trigger is blank.

At the Server end I have a blank Outgoing Sync and Incoming Sync simply states:

issue.workLogs = workLogHelper.mergeWorkLogs(issue, replica)

Nothing is syncing although the Connection is Active. No issues are under sync. Is this because I don’t have a trigger. How do I get it started for current and future worklogs ?

Many Thanks - AndySource: Jira Cloud (old community)


Answer by Andrew Hines on 26 June 2020

In fact Juan from your support desk gave us the mssing information needed to properly match Accounts.

Check out answer here : How to set Tempo account on Jira Server (old community)

Thanks to you and Juan for all assistance :wink:


Answer by Andrew Hines on 12 June 2020

Thank you Francis. I now have it syncing the Issues as well but I am having a problem specifying the user between the two systems.

I initially got error

Exalate failed to merge worklogs via workLogHelper.mergeWorklogs(issue, replica). User by email: is.origo.jira.tempo-plugin@connect.atlassian.com was not found. Please create user with this email.

If you don’t want to create that user, please use workLogHelper.mergeWorkLogs(issue, replica, { w -> w.author = /* get a user on your side via either of the methods in the nodeHelper e.g. nodeHelper.getUserByDisplayName() */ })

I understand this is because it hasn’t matched users properly. I’s like to match on email address and I first made my email address publicly visible on JIRA Cloud. Same result.

Then I also changed the inbound code on JIRA server as below:

issue.workLogs = workLogHelper.mergeWorkLogs(issue,replica, { w ->
w.author = nodeHelper.getUserByEmail(userMapping[w.author?.key]) ?: w.author
w.updateAuthor = nodeHelper.getUserByEmail(userMapping[w.updateAuthor?.key]) ?: w.updateAuthor
})

then I get error

Script error details: No such property: userMapping for class: Script196. Error line: Script196.groovy:9

What is the correct way to specify the user lookup by email on JIRA Server? Tempo is on both Cloud and Server if that’s relevant.

Many Thanks - Andy


Comments:

Francis Martens (Exalate) commented on 13 June 2020

You are almost there

a) You need to define a user mapping. Something like

def userMapping = [
     "foo@google.com" : "bar@facebook.com",
     "xyz@dropbox.com" : "wvu@bitcoin.com",
]

def targetMail = userMapping["xyz@dropbox.com"] 
// targetMail is "wvu@bitcoin.com"
    

But - make sure that the w.author?.key is provided.

You can test this by inspecting the remote issues tab on the issue or by throwing an exception in the incoming sync on the server

throw new Exception("The original author is ${w.author?.key}")

Whenever a new message is received from the cloud, an error will be raised with that content

Check for more information the troubleshooting article

Andrew Hines commented on 14 June 2020

Hi Francis …

Thank you. In fact I got it to work as follows :

On the source side (JIRA Cloud) I added a line to set the replica assignee

On the destination side (JIRA Server) I used the replica assignee email to getUserByEmail

That synced my Issue and I was initially very happy (old community)

Then I realised I still had a couple of issues - sorry

(1) The Account field doesn’t sync. Do you have any examples where the Account is copied across. We use this for project codes for Finance. I appreciate that it is a Tempo specific field - not native Jira.

(2) I realise that I’m wrong to search for the issue.assignee when attributing worklogs. It should be the person booking the time, not the owner of the Issue. What field should I have used ? We will have the same users (by email) on both systems.

Many Thanks for your help - Andy

Francis Martens (Exalate) commented on 14 June 2020

> The Account field doesn’t sync.

This is not supported in the TempoWorkLogSync. TempoWorkLogSync is meant to sync Tempo Worklogs and is provided as an example. The logic for accounts should be similar. Maybe someone else already made such logic

> Worklog attribution

Check the details in following document

https://docs.idalko.com/exalate/x/DgBL

In line 9 in the code example above - change replica.assignee.email into w.author?.email

This should be sufficient

Let me know how it goes

Andrew Hines commented on 15 June 2020

Hi Francis - Thanks so much for your help. It is very much appreciated. Using w.author?.email worked and now my worklogs sync from Cloud to Server with the correct user. That’s the basics of what I was trying to do.

So now my biggest sticking point is the Account field. I believe that it’s not part of the worklog itself but is linked to it - is that right ? Is there any function I can use which will set the Account for a Tempo worklog in JIRA Server. I know the custom field names at either end but I don’t know how to set them when I do the workLogHelper.mergeWorkLogs.

Also if this is something that would warrant a commercial discussion rather than me floundering around you providing free help then please say so. We are on an Exalate trial but will iminently be going to a paid subscription so happy to have a chat …

Francis Martens (Exalate) commented on 15 June 2020

This needs to be developed. We got a lot on our stack atm, so it is not in our plans.

Can you have a look if no one else did it?

Andrew Hines commented on 17 June 2020

Hi Francis … thanks for your help. It seems I also have a great team working for me. One of my colleagues came up with the following solution :

Outbound from JIRA Cloud:

Inbound in JIRA Server :

This works when we test it with a new Issue and then log time to it. the Account gets synced with the Issue and worklogs inherit that Account.

Cue … happy dancing around the room … (old community)

When we update the Connection to sync our live JSD Cloud back to a custom Jira Server project we get one of two errors…

Most errors are the first one.

Any pointers ? Do we need the same workflow and transitions on both sides ?

Thanks - Andy

Francis Martens (Exalate) commented on 18 June 2020

What version of Jira and exalate do you have?

Francis Martens (Exalate) commented on 18 June 2020

Good to know about the Tempo Account - kudos to your colleague

Andrew Hines commented on 19 June 2020

Hi Francis -

JIRA Cloud uses Exalate v5.0.44 (Core v5.0.52)

JIRA Server (v8.2.3) uses v4.7.9-j8

Are they all good ?

Francis Martens (Exalate) commented on 19 June 2020

Looks like.

If you retry the errors - what gives?

Andrew Hines commented on 19 June 2020

Hi Francis - I get the same error. Here’s the details:

We have gone back to syncing a very basic project - absolutely standard workflow.

We’ve updated the receiving script as follows :

If we comment out line 12 then it syncs and we can see that the value being passed in replica.customFields.“Account” is :

Experimentation confirms that this is the Description of the Account and not the Key.

If we uncomment line 12 then it fails with the above error.

Any suggestions - or resources you can point us to ?

Thanks - Andy

Andrew Hines commented on 21 June 2020

Hi - I’m now trying to code a fixed value to the customfield that is used by the Account but I’m not getting the syntax right.

I could use this as a workaround for now …

On our JIRA Server customfield 16030 holds the account details. I’m seeing this via a REST API call

If I try to set this field though then it fails. I’m using :

issue.customFields.“16030”.value = [self: “https://cds.vixtechnology.com/rest/tempo-accounts/1/account/220”, id: 220, key: “OVERHEAD”, name: “OVERHEAD”]

How would I express this properly ? If I try it on a different custom field then it works but it shows as one long string.

So clearly I am getting the syntax wrong and not expressing it as 4 element associative array. I assume this is why it’s not able to be set.

Hopefully this is just my lack of understanding … any ideas ?

Many Thanks - Andy

Answer by Francis Martens (Exalate) on 10 June 2020

Welcome to the Exalate, and thanks for asking the question.

The way that Exalate works is documented in the synchronization process, but it boils down to

  1. An issue gets updated on Jira A
  2. Exalate turns the issue into a message using the outgoing sync processor
  3. Exalate sends the message to Jira B
  4. The exalate on Jira B receives the message
  5. The message is applied to the related issue (the twin as we call it) using the incoming sync processor

To be able to sync worklogs, you need to have the issue - containing these worklogs - to be under sync.
Else Exalate will not know to what issue the worklogs need to be added at the receiving end.
We tweaked the documentation a bit so that it is hopefully more clear (here)

Triggers are not necessary as you can also Exalate manually. But most customers are configuring a trigger.


Comments:

Andrew Hines commented on 12 June 2020

Thanks Francis - see my follow up question. Is that OK or should I post it as a new one ?

Francis Martens (Exalate) commented on 13 June 2020

that’s ok

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.