Skip to content

Commit

Permalink
Jira Epic Mapping: Add flexibility to epic issue type (#9666)
Browse files Browse the repository at this point in the history
* Jira Epic Mapping: Add flexibility to epic issue type

* Update unit tests

* Missed a test
  • Loading branch information
Maffooch authored Mar 5, 2024
1 parent ba63ec5 commit b493f7e
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 8 deletions.
18 changes: 18 additions & 0 deletions dojo/db_migrations/0204_jira_project_epic_issue_type_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.1.13 on 2024-03-01 20:39

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('dojo', '0203_alter_finding_options_finding_epss_percentile_and_more'),
]

operations = [
migrations.AddField(
model_name='jira_project',
name='epic_issue_type_name',
field=models.CharField(default='Epic', blank=True, help_text='The name of the of structure that represents an Epic', max_length=64),
),
]
15 changes: 10 additions & 5 deletions dojo/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2709,7 +2709,7 @@ class JIRAProjectForm(forms.ModelForm):
class Meta:
model = JIRA_Project
exclude = ['product', 'engagement']
fields = ['inherit_from_product', 'jira_instance', 'project_key', 'issue_template_dir', 'component', 'custom_fields', 'jira_labels', 'default_assignee', 'add_vulnerability_id_to_jira_label', 'push_all_issues', 'enable_engagement_epic_mapping', 'push_notes', 'product_jira_sla_notification', 'risk_acceptance_expiration_notification']
fields = ['inherit_from_product', 'jira_instance', 'project_key', 'issue_template_dir', 'epic_issue_type_name', 'component', 'custom_fields', 'jira_labels', 'default_assignee', 'add_vulnerability_id_to_jira_label', 'push_all_issues', 'enable_engagement_epic_mapping', 'push_notes', 'product_jira_sla_notification', 'risk_acceptance_expiration_notification']

def __init__(self, *args, **kwargs):
from dojo.jira_link import helper as jira_helper
Expand Down Expand Up @@ -2742,6 +2742,7 @@ def __init__(self, *args, **kwargs):
self.fields['jira_instance'].disabled = False
self.fields['project_key'].disabled = False
self.fields['issue_template_dir'].disabled = False
self.fields['epic_issue_type_name'].disabled = False
self.fields['component'].disabled = False
self.fields['custom_fields'].disabled = False
self.fields['default_assignee'].disabled = False
Expand All @@ -2765,6 +2766,7 @@ def __init__(self, *args, **kwargs):
self.initial['jira_instance'] = jira_project_product.jira_instance.id if jira_project_product.jira_instance else None
self.initial['project_key'] = jira_project_product.project_key
self.initial['issue_template_dir'] = jira_project_product.issue_template_dir
self.initial['epic_issue_type_name'] = jira_project_product.epic_issue_type_name
self.initial['component'] = jira_project_product.component
self.initial['custom_fields'] = jira_project_product.custom_fields
self.initial['default_assignee'] = jira_project_product.default_assignee
Expand All @@ -2779,6 +2781,7 @@ def __init__(self, *args, **kwargs):
self.fields['jira_instance'].disabled = True
self.fields['project_key'].disabled = True
self.fields['issue_template_dir'].disabled = True
self.fields['epic_issue_type_name'].disabled = True
self.fields['component'].disabled = True
self.fields['custom_fields'].disabled = True
self.fields['default_assignee'].disabled = True
Expand All @@ -2798,6 +2801,7 @@ def __init__(self, *args, **kwargs):
if self.instance.id:
self.fields['jira_instance'].required = True
self.fields['project_key'].required = True
self.fields['epic_issue_type_name'].required = True

def clean(self):
logger.debug('validating jira project form')
Expand All @@ -2807,17 +2811,18 @@ def clean(self):
if not self.cleaned_data.get('inherit_from_product', False):
jira_instance = self.cleaned_data.get('jira_instance')
project_key = self.cleaned_data.get('project_key')
epic_issue_type_name = self.cleaned_data.get('epic_issue_type_name')

if project_key and jira_instance:
if project_key and jira_instance and epic_issue_type_name:
return cleaned_data

if not project_key and not jira_instance:
if not project_key and not jira_instance and not epic_issue_type_name:
return cleaned_data

if self.target == 'engagement':
raise ValidationError('JIRA Project needs a JIRA Instance and JIRA Project Key, or choose to inherit settings from product')
raise ValidationError('JIRA Project needs a JIRA Instance, JIRA Project Key, and Epic issue type name, or choose to inherit settings from product')
else:
raise ValidationError('JIRA Project needs a JIRA Instance and JIRA Project Key, leave empty to have no JIRA integration setup')
raise ValidationError('JIRA Project needs a JIRA Instance, JIRA Project Key, and Epic issue type name, leave empty to have no JIRA integration setup')


class GITHUBFindingForm(forms.Form):
Expand Down
2 changes: 1 addition & 1 deletion dojo/jira_link/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -1223,7 +1223,7 @@ def add_epic(engagement, **kwargs):
'summary': epic_name,
'description': epic_name,
'issuetype': {
'name': 'Epic'
'name': getattr(jira_project, "epic_issue_type_name", "Epic"),
},
get_epic_name_field_name(jira_instance): epic_name,
}
Expand Down
1 change: 1 addition & 0 deletions dojo/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3890,6 +3890,7 @@ class JIRA_Project(models.Model):
help_text=_("Automatically maintain parity with JIRA. Always create and update JIRA tickets for findings in this Product."))
enable_engagement_epic_mapping = models.BooleanField(default=False,
blank=True)
epic_issue_type_name = models.CharField(max_length=64, blank=True, default="Epic", help_text=_("The name of the of structure that represents an Epic"))
push_notes = models.BooleanField(default=False, blank=True)
product_jira_sla_notification = models.BooleanField(default=False, blank=True, verbose_name=_("Send SLA notifications as comment?"))
risk_acceptance_expiration_notification = models.BooleanField(default=False, blank=True, verbose_name=_("Send Risk Acceptance expiration notifications as comment?"))
Expand Down
10 changes: 8 additions & 2 deletions unittests/dojo_test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ def get_new_product_with_jira_project_data(self):
'jira-project-form-project_key': 'IFFFNEW',
'jira-project-form-jira_instance': 2,
'jira-project-form-enable_engagement_epic_mapping': 'on',
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-push_notes': 'on',
'jira-project-form-product_jira_sla_notification': 'on',
'jira-project-form-custom_fields': 'null',
Expand All @@ -170,7 +171,9 @@ def get_new_product_without_jira_project_data(self):
'name': 'new product',
'description': 'new description',
'prod_type': 1,
'sla_configuration': 1
'sla_configuration': 1,
# A value is set by default by the model, so we need to add it here as well
'jira-project-form-epic_issue_type_name': 'Epic',
# 'project_key': 'IFFF',
# 'jira_instance': 2,
# 'enable_engagement_epic_mapping': 'on',
Expand All @@ -186,6 +189,7 @@ def get_product_with_jira_project_data(self, product):
'jira-project-form-project_key': 'IFFF',
'jira-project-form-jira_instance': 2,
'jira-project-form-enable_engagement_epic_mapping': 'on',
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-push_notes': 'on',
'jira-project-form-product_jira_sla_notification': 'on',
'jira-project-form-custom_fields': 'null',
Expand All @@ -201,6 +205,7 @@ def get_product_with_jira_project_data2(self, product):
'jira-project-form-project_key': 'IFFF2',
'jira-project-form-jira_instance': 2,
'jira-project-form-enable_engagement_epic_mapping': 'on',
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-push_notes': 'on',
'jira-project-form-product_jira_sla_notification': 'on',
'jira-project-form-custom_fields': 'null',
Expand All @@ -214,7 +219,8 @@ def get_product_with_empty_jira_project_data(self, product):
'description': product.description,
'prod_type': product.prod_type.id,
'sla_configuration': 1,

# A value is set by default by the model, so we need to add it here as well
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-custom_fields': 'null',
# 'project_key': 'IFFF',
# 'jira_instance': 2,
Expand Down
8 changes: 8 additions & 0 deletions unittests/test_jira_config_engagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def get_new_engagement_with_jira_project_data(self):
# 'jira-project-form-inherit_from_product': 'on', # absence = False in html forms
'jira-project-form-jira_instance': 2,
'jira-project-form-project_key': 'IUNSEC',
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-product_jira_sla_notification': 'on',
'jira-project-form-custom_fields': 'null',
}
Expand All @@ -40,6 +41,7 @@ def get_new_engagement_with_jira_project_data_and_epic_mapping(self):
# 'jira-project-form-inherit_from_product': 'on', # absence = False in html forms
'jira-project-form-jira_instance': 2,
'jira-project-form-project_key': 'IUNSEC',
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-product_jira_sla_notification': 'on',
'jira-project-form-enable_engagement_epic_mapping': 'on',
'jira-epic-form-push_to_jira': 'on',
Expand All @@ -56,6 +58,8 @@ def get_new_engagement_without_jira_project_data(self):
'target_end': '2070-12-04',
'status': 'Not Started',
'jira-project-form-inherit_from_product': 'on',
# A value is set by default by the model, so we need to add it here as well
'jira-project-form-epic_issue_type_name': 'Epic',
# 'project_key': 'IFFF',
# 'jira_instance': 2,
# 'enable_engagement_epic_mapping': 'on',
Expand All @@ -75,6 +79,7 @@ def get_engagement_with_jira_project_data(self, engagement):
# 'jira-project-form-inherit_from_product': 'on', # absence = False in html forms
'jira-project-form-jira_instance': 2,
'jira-project-form-project_key': 'ISEC',
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-product_jira_sla_notification': 'on',
'jira-project-form-custom_fields': 'null',
}
Expand All @@ -91,6 +96,7 @@ def get_engagement_with_jira_project_data2(self, engagement):
# 'jira-project-form-inherit_from_product': 'on', # absence = False in html forms
'jira-project-form-jira_instance': 2,
'jira-project-form-project_key': 'ISEC2',
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-product_jira_sla_notification': 'on',
'jira-project-form-custom_fields': 'null',
}
Expand All @@ -105,6 +111,8 @@ def get_engagement_with_empty_jira_project_data(self, engagement):
'target_end': '2070-12-04',
'status': 'Not Started',
'jira-project-form-inherit_from_product': 'on',
# A value is set by default by the model, so we need to add it here as well
'jira-project-form-epic_issue_type_name': 'Epic',
# 'project_key': 'IFFF',
# 'jira_instance': 2,
# 'enable_engagement_epic_mapping': 'on',
Expand Down
1 change: 1 addition & 0 deletions unittests/test_jira_config_engagement_epic.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def get_new_engagement_with_jira_project_data_and_epic_mapping(self):
'status': 'Not Started',
'jira-project-form-jira_instance': 2,
'jira-project-form-project_key': 'NTEST',
'jira-project-form-epic_issue_type_name': 'Epic',
'jira-project-form-product_jira_sla_notification': 'on',
'jira-project-form-enable_engagement_epic_mapping': 'on',
'jira-epic-form-push_to_jira': 'on',
Expand Down

0 comments on commit b493f7e

Please sign in to comment.