diff --git a/README.md b/README.md index 4687d0a..ff21126 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,9 @@ The task needs special configuration in `exportimportconfig.py` (see sample in * `PORTFOLIO_EPIC_LABEL`: (porfolio epic mode) for an issue to be considered a porfolio epic, this label must be attached to it * `PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_NAME`: (porfolio epic mode) only issues that are linked to the portfolio epic with this link name are migrated * `PORTFOLIO_EPIC_SUB_EPIC_TARGET_LINK_NAME`: (porfolio epic mode) the link name to use in target JIRA to link issues to portfolio epics +* `PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_DIRECTION`: 'outwardIssue' or 'inwardIssue'. Choose which direction search is done +* `PORTFOLIO_EPIC_SUB_EPIC_TARGET_LINK_SWAP`: 'True' or 'False' Optionally swap direction to destination, if it is logically opposite. + * `STATUS_TRANSITIONS`: map of source JIRA statuses to list of workflow transition names in target JIRA that result in equivalent status, `None` for no transition * `STATUS_TRANSITIONS_ISSUETYPE`: issuetype specific map of source JIRA statuses to list of workflow transition names in target JIRA that result in equivalent status, `None` for no transition. If an issuetype is not in this list, the default `STATUS_TRANSITIONS` are used. * `RESOLUTION_MAP`: map source JIRA resolutions to target resolutions, only used when a `WithResolution` transition is used in `STATUS_TRANSITIONS` diff --git a/exportimportconfig-sample.py b/exportimportconfig-sample.py index 9074ef4..8140948 100644 --- a/exportimportconfig-sample.py +++ b/exportimportconfig-sample.py @@ -102,7 +102,8 @@ PORTFOLIO_EPIC_LABEL = 'porfolio-epic' PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_NAME = 'sub-epic' PORTFOLIO_EPIC_SUB_EPIC_TARGET_LINK_NAME = 'sub-epic' - +PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_DIRECTION = 'outwardIssue' # or inwardIssue +PORTFOLIO_EPIC_SUB_EPIC_TARGET_LINK_SWAP = 'True' # ...or False, swapping direction CUSTOM_FIELD_FOR_SOURCE_JIRA_ISSUE_KEY = ('Text 1', 'customfield_10132') CUSTOM_FIELD = ('customfield_11086', {'value': 'Custom value'}) diff --git a/lib/export_import.py b/lib/export_import.py index 58197a8..dae9a9c 100644 --- a/lib/export_import.py +++ b/lib/export_import.py @@ -101,12 +101,33 @@ def _map_sub_epics(source_jira, dest_jira, source_issue, dest_issue, conf, resul print('with sub-epics:') # Get all linked sub-epics and import them recursively. for linked_issue in source_issue.fields.issuelinks: - if linked_issue.type.name == conf.PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_NAME and hasattr(linked_issue, 'outwardIssue'): - sub_epic = linked_issue.outwardIssue - new_sub_epic = _map_issue(source_jira, dest_jira, sub_epic, conf, result, None, True) + if linked_issue.type.name == conf.PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_NAME and \ + hasattr(linked_issue, conf.PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_DIRECTION): + if conf.PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_DIRECTION == "inwardIssue": + sub_epic = linked_issue.inwardIssue + else: + sub_epic = linked_issue.outwardIssue + # Test if sub_epic already exists. Use that or create a new + # Search always returns an iterator, but it may be empty + # It then throws StopIteration, instead of giving us issue + try: + new_sub_epic = next(_already_imported(conf, dest_jira, sub_epic)) + print('Issue', sub_epic, 'has already been imported, link only...') + except StopIteration: + new_sub_epic = _map_issue(source_jira, dest_jira, sub_epic, conf, result, None, True) + # Always create link, no matter if it was existing issue or new + # If SWAP, change direction + # If searched outwardIssue, or if searched inward, but SWAP is true + inIssue = dest_issue.key + outIssue = new_sub_epic.key + # If searched inwardIssue and no SWAP, or if searched outward, but SWAP is true + if (conf.PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_DIRECTION == 'inwardIssue' and not conf.PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_SWAP ) or \ + (conf.PORTFOLIO_EPIC_SUB_EPIC_SOURCE_LINK_DIRECTION == 'outwardIssue' and conf.PORTFOLIO_EPIC_SUB_EPIC_TARGET_LINK_SWAP): + outIssue = dest_issue.key + inIssue = new_sub_epic.key + dest_jira.create_issue_link(type=conf.PORTFOLIO_EPIC_SUB_EPIC_TARGET_LINK_NAME, - inwardIssue=dest_issue.key, - outwardIssue=new_sub_epic.key) + inwardIssue= inIssue, outwardIssue= outIssue ) # TODO: add portfolio epic label to target print('Sub-epics of', source_issue.key, 'done.')