1
0
-1

Hi.


We're using Exalate to synchronise issues across our cloud based instances of Jira and GitHub.


Is it possible to set the value of an issue variable field (i.e. input side) from within the outgoing sync processor during sychronisation?  That is to say, update a source-side field during the course of a source-side initiated sync?


I've attempted this within one of our of outgoing scripts and whilst it doesn't lead to an error, or affect synchronisation, neither does the source side field get updated. I'm left wondering whether this simply isn't possible or if there's a particular way of doing it other than a simple assignment.


For example:

// **outgoing sync processor script**


// usual mapping of source to destination(replica) fields in an outgoing script
replica.description = issue.description
replica.labels = issue.labels
replica.comments = issue.comments


// but in addition, attempt to update a field of the source issue during the same outgoing process
issue.customFields."CF Name" = <insert appropriate value for custom field>


This question is related to one previously asked here but in which the matter of whether this action is fundamentally possible or not, rather than being the best approach to that particular use-case, didn't get answered (imho).

Update local field when local issue execute sync



Thanks,
Glenn

    CommentAdd your comment...

    2 answers

    1.  
      1
      0
      -1

      Actually looking for something similar (going to be posting the question soon) regarding last sync time. But for the question of modifying the issue during an outgoing sync, the server method I've used previously is:


      import com.atlassian.jira.component.ComponentAccessor;
      import com.atlassian.jira.issue.ModifiedValue
      import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
      import com.atlassian.jira.issue.Issue
      def issueMgr = ComponentAccessor.getIssueManager()
      def customFieldManager = ComponentAccessor.getCustomFieldManager()
      Issue curIssue = issueMgr.getIssueObject(issue.id as Long)
      def cf = customFieldManager.getCustomFieldObjectsByName("WhateverYourFieldIsNamed")[0]
      def changeHolder = new DefaultIssueChangeHolder()
      curIssue.setCustomFieldValue(cf,valueOfFieldYouWant)
      cf.updateValue(null, curIssue, new ModifiedValue(curIssue.getCustomFieldValue(cf), currentTime),changeHolder)



      And for cloud you use a REST call as below:

      def url = "yourcloudURL.atlassian.net"
      def fullUrl = url + '/rest/api/3/issue/'+issue.key
      def userAuth = "Basic XXXXXX" //replace with user auth string for user you want to act. Easiest way I've found to get this is in Postman enter username and password into basic authentication then check headers for Authorization's value.
      
      def message = '{"fields": {"customfield_XXXX":"'+currentTime+'"}}' //replace the Xs with the customfield number (found by hovering over the edit button in Custom Fields settings)
      def get = new URL(fullUrl).openConnection();
      get.setRequestMethod("PUT")
      get.setDoOutput(true)
      get.setRequestProperty("Authorization",userAuth)
      get.setRequestProperty("Content-Type","application/json")
      get.setRequestProperty("X-ExperimentalApi","opt-in") //needed for some, but not this, endpoint
      get.setRequestProperty("Accept","application/json")
      get.getOutputStream().write(message.getBytes("UTF-8"));
      def getRC = get.getResponseCode(); // the response code from the REST call
      if (getRC.equals(204)) { //success
      	return true
      }

      There is risk that it might just trigger another sync, but it didn't seem to constantly do so when I was trying it (maybe it knows to ignore that type of change?)

      1. Francis Martens (Exalate)

        Updating the local issue in an outgoing sync is currently not supported for the reason you indicated.
        We can see the value of having it in the product. 

      CommentAdd your comment...
    2.  
      1
      0
      -1

      Did you try to use this instead:


      issue.customFields."CF Name"?.value = *** your value ***


      Anyway if that doesn't work, you can using Atlassian API (CustomFieldManager and IssueManager) to do so.

      1. Glenn Bullingham

        Hello Yaakov,


        Thank you for your reply.  I've been able to revisit this task today and can confirm that the approach I might expect to work, that is to say, the first example you gave (i.e. issue.customFields."CF Name"?.value = *** your value ***) does not work.  As with my own previous attempts, whilst it does not lead to an exception or an error being raised during synchronisation, neither does it cause the target custom field to be updated.  I able able the read the same custom field's value elsewhere within the same outgoing sync script, it just seems that it cannot be written.


        Please would you mind directing me towards either documentation on, or an example of the use of,  CustomFieldManager etc. within the outgoing sync script, as per your alternative suggestion?  I found this pertaining to Jira on-premise but I can't even update the script by adding just the initial import (import com.atlassian.jira.component.ComponentAccessor) without receiving a "Cannot publish changes" error.

        Thanks,

        Glenn

      2. Yaakov Shamii

        Hi Glenn,

        Can you post the error you receive?


      3. Glenn Bullingham

        Sure, no problem.  

      4. Glenn Bullingham

        Sorry to pester but does anyone have an answer or solution for this please?  If this isn't the correct way to go about the task in hand, that's fine.  But I would really like to know how to identify, from the Jira side using a JQL query (so that it can be used within boards, gadgets etc.), which side of the synchronization occurred last.  i.e. I'd like an easy way to identify at any point in time all the issues under synchronisation which were last updated by a user in GitHub, rather than directly in Jira.


        Thanks,

        Glenn

      5. Yaakov Shamii

        Glenn, I believe you have another error in your data filter rather than the import (as they seem correct, and I used them before).

        Jonathon's answer seem legit, and if you don't want to trigger the sync again you can update a custom field without history (but it won't send update mails to the customer in that case).

        If you still encounter problems, please share the logs with us, I couldn't understand from the picture what is the actual problem.

        Goodluck 

      6. Glenn Bullingham

        Thank you both for your input.  However there must be something fundamental that I am missing.  Whilst I appreciate that my scripting skills aren't infallible, I currently have a fully functional outgoing script set on my Jira cloud connector.  If I so much as add just the opening line from Jonathon's example to it at line 1, i.e. the first import statement


        import com.atlassian.jira.component.ComponentAccessor;

        ,then I'm unable to apply the change to the Data Filter script, as per the screenshot above.  Should I be able to do this?  That is, is this functionality available in the Jira Cloud version, or do you have it working only with Jira Server on-premise?

      7. Yaakov Shamii

        As far as I know, Atlassian's javadoc is not compatible in the cloud instance, so you can't use ComponentAccessor or managers and so on. Please use Jira's rest api to update the origin issue custom fields.

      8. Glenn Bullingham

        Yaakov Shamii Thank you.  I'd completely missed Jonathon's delineation of using REST for cloud use-cases.

      CommentAdd your comment...