66import java .util .Objects ;
77import java .util .Optional ;
88
9+ import org .hibernate .infra .replicate .jira .JiraConfig ;
910import org .hibernate .infra .replicate .jira .service .jira .HandlerProjectContext ;
1011import org .hibernate .infra .replicate .jira .service .jira .client .JiraRestException ;
1112import org .hibernate .infra .replicate .jira .service .jira .model .rest .JiraFields ;
@@ -128,6 +129,24 @@ protected JiraIssue issueToCreate(JiraIssue sourceIssue) {
128129 destinationIssue .fields .assignee = JiraUser .unassigned (context .projectGroup ().users ().mappedPropertyName ());
129130 }
130131
132+ if (!isSubTaskIssue (sourceIssue .fields .issuetype ) && sourceIssue .fields .parent != null ) {
133+ if (isEpicIssue (sourceIssue .fields .parent .fields .issuetype )) {
134+ JiraConfig .IssueTypeValueMapping issueTypes = context .projectGroup ().issueTypes ();
135+ issueTypes .epicLinkKeyCustomFieldName ().ifPresent (epicLinkCustomFieldName -> destinationIssue .fields
136+ .properties ().put (epicLinkCustomFieldName , toDestinationKey (sourceIssue .fields .parent .key )));
137+ }
138+ }
139+ if (isEpicIssue (sourceIssue .fields .issuetype )) {
140+ // Try to set an epic label ... obviously it is a custom field >_< ...
141+ JiraConfig .IssueTypeValueMapping issueTypes = context .projectGroup ().issueTypes ();
142+ Object sourceEpicLabel = issueTypes .epicLinkSourceLabelCustomFieldName ()
143+ .map (sourceIssue .fields .properties ()::get ).orElse (sourceIssue .fields .summary );
144+
145+ issueTypes .epicLinkDestinationLabelCustomFieldName ()
146+ .ifPresent (epicLinkDestinationLabelCustomFieldName -> destinationIssue .fields .properties ()
147+ .put (epicLinkDestinationLabelCustomFieldName , sourceEpicLabel ));
148+ }
149+
131150 return destinationIssue ;
132151 }
133152
@@ -140,7 +159,10 @@ private Optional<JiraTransition> prepareTransition(JiraIssue sourceIssue) {
140159 }
141160
142161 protected Optional <JiraIssueLink > prepareParentLink (String destinationKey , JiraIssue sourceIssue ) {
143- if (sourceIssue .fields .parent != null ) {
162+ // we only add a link for sub-tasks (the ones that have a corresponding types).
163+ // Issues assigned to an epic, can also have a parent.
164+ // but for those we won't add an extra link:
165+ if (sourceIssue .fields .parent != null && isSubTaskIssue (sourceIssue .fields .issuetype )) {
144166 String parent = toDestinationKey (sourceIssue .fields .parent .key );
145167 // we don't really need it, but as usual we are making sure that the issue is
146168 // available downstream:
@@ -164,6 +186,20 @@ protected Optional<JiraIssueLink> prepareParentLink(String destinationKey, JiraI
164186 }
165187 }
166188
189+ private boolean isSubTaskIssue (JiraSimpleObject issueType ) {
190+ if (issueType == null ) {
191+ return false ;
192+ }
193+ return Boolean .parseBoolean (Objects .toString (issueType .properties ().get ("subtask" ), null ));
194+ }
195+
196+ private boolean isEpicIssue (JiraSimpleObject issueType ) {
197+ if (issueType == null ) {
198+ return false ;
199+ }
200+ return "epic" .equalsIgnoreCase (issueType .name );
201+ }
202+
167203 private String prepareDescriptionQuote (JiraIssue issue ) {
168204 URI issueUri = createJiraIssueUri (issue );
169205
0 commit comments