@@ -13,6 +13,9 @@ use warnings;
1313
1414use base qw( Bugzilla::Extension) ;
1515
16+ use Bugzilla::Bug;
17+ use Bugzilla::BugUrl;
18+ use Bugzilla::Extension::JiraWebhookSync::JiraBugMap;
1619use Bugzilla::Logging;
1720use Bugzilla::Util qw( trim) ;
1821
@@ -21,6 +24,27 @@ use List::Util qw(uniq);
2124use Mojo::URL;
2225use Mojo::Util qw( dumper) ;
2326
27+ # Creates/updates database schema for the extension
28+ sub db_schema_abstract_schema {
29+ my ($self , $args ) = @_ ;
30+ $args -> {schema }-> {jira_bug_map } = {
31+ FIELDS => [
32+ id => {TYPE => ' MEDIUMSERIAL' , NOTNULL => 1, PRIMARYKEY => 1,},
33+ bug_id => {
34+ TYPE => ' INT3' ,
35+ NOTNULL => 1,
36+ REFERENCES => {TABLE => ' bugs' , COLUMN => ' bug_id' , DELETE => ' CASCADE' ,}
37+ },
38+ jira_id => {TYPE => ' VARCHAR(255)' , NOTNULL => 1,},
39+ jira_project_key => {TYPE => ' VARCHAR(100)' , NOTNULL => 1,},
40+ ],
41+ INDEXES => [
42+ jira_bug_map_bug_id_idx => {FIELDS => [' bug_id' , ' jira_id' ], TYPE => ' UNIQUE' ,},
43+ jira_bug_map_project_idx => [' jira_project_key' ],
44+ ],
45+ };
46+ }
47+
2448# Adds the JiraWebhookSync configuration panel to the admin interface.
2549# This hook allows administrators to configure Jira webhook synchronization settings.
2650sub config_add_panels {
@@ -29,9 +53,46 @@ sub config_add_panels {
2953 $modules -> {JiraWebhookSync } = ' Bugzilla::Extension::JiraWebhookSync::Config' ;
3054}
3155
32- # Modifies webhook payload before sending by adding configured whiteboard tags.
56+ # Intercepts see_also additions to check if they should be stored in the mapping table
57+ # instead of as regular see_also links. This is used to work around JBI design choices
58+ # that require the see_also value to not exist to prevent duplicate jira tickets.
59+ sub bug_start_of_update {
60+ my ($self , $args ) = @_ ;
61+ my $new_bug = $args -> {bug };
62+
63+ foreach my $see_also (@{$new_bug -> see_also}) {
64+
65+ # Check if this see_also URL corresponds to a Jira ticket
66+ my ($jira_id , $project_key )
67+ = Bugzilla::Extension::JiraWebhookSync::JiraBugMap-> extract_jira_info(
68+ $see_also -> name);
69+
70+ next unless $jira_id && $project_key ;
71+
72+ INFO(" Intercepting see_also for Jira ticket: $jira_id (project: $project_key )" );
73+
74+ # Add the jira id and project key to the jira_bug_map table unless it already exists
75+ my $existing_map
76+ = Bugzilla::Extension::JiraWebhookSync::JiraBugMap-> get_by_bug_id($new_bug -> id);
77+ if (!$existing_map ) {
78+ INFO(' Creating new Jira mapping for bug ' . $new_bug -> id);
79+ Bugzilla::Extension::JiraWebhookSync::JiraBugMap-> create({
80+ bug_id => $new_bug -> id,
81+ jira_id => $jira_id ,
82+ jira_project_key => $project_key ,
83+ });
84+ }
85+
86+ # Remove the see_also entry from the new bug object
87+ $new_bug -> remove_see_also($see_also );
88+ }
89+ }
90+
91+ # Modifies webhook payload before sending by adding configured whiteboard tags
92+ # and see_also values from the mapping table.
3393# Checks if the bug's product/component matches any configuration rules and
3494# automatically adds the corresponding whiteboard tag to the payload if matched.
95+ # Also checks if there's a Jira mapping for this bug and adds the Jira URL to see_also.
3596sub webhook_before_send {
3697 my ($self , $args ) = @_ ;
3798 my $webhook = $args -> {webhook };
@@ -45,6 +106,34 @@ sub webhook_before_send {
45106 my $uri = Mojo::URL-> new($webhook -> url);
46107 return if $uri -> host ne $hostname ;
47108
109+ # Get the bug object from the payload
110+ my $bug_id = $payload -> {bug }-> {id };
111+
112+ INFO(" Processing webhook for bug $bug_id to Jira host $hostname " );
113+
114+ # Check if there's a Jira mapping for this bug
115+ my $jira_map
116+ = Bugzilla::Extension::JiraWebhookSync::JiraBugMap-> get_by_bug_id($bug_id );
117+
118+ if ($jira_map ) {
119+
120+ # Construct the Jira URL from the mapping
121+ my $jira_url = " https://$hostname /browse/" . $jira_map -> jira_id;
122+
123+ INFO(" Adding Jira see_also to webhook payload: $jira_url " );
124+
125+ # Add the Jira URL to the see_also array in the payload
126+ if (!exists $payload -> {bug }-> {see_also }) {
127+ $payload -> {bug }-> {see_also } = [];
128+ }
129+
130+ # Only add if not already present
131+ my %existing_see_also = map { $_ => 1 } @{$payload -> {bug }-> {see_also }};
132+ if (!$existing_see_also {$jira_url }) {
133+ push @{$payload -> {bug }-> {see_also }}, $jira_url ;
134+ }
135+ }
136+
48137 # Make copy of the current whiteboard value
49138 my $whiteboard = $payload -> {bug }-> {whiteboard };
50139
@@ -60,8 +149,7 @@ sub webhook_before_send {
60149 }
61150 }
62151
63- $payload -> {bug }-> {whiteboard }
64- = _add_whiteboard_tags($whiteboard , \@new_tags );
152+ $payload -> {bug }-> {whiteboard } = _add_whiteboard_tags($whiteboard , \@new_tags );
65153}
66154
67155# Adds a whiteboard tag to the whiteboard string if it doesn't already exist.
@@ -78,7 +166,7 @@ sub _add_whiteboard_tags {
78166 $whiteboard .= " [$new_tag ]" ; # Append new tag to the end
79167 }
80168
81- return trim($whiteboard ); # Trim whitespace before returning
169+ return trim($whiteboard ); # Trim whitespace before returning
82170}
83171
84172# Checks if a bug matches the criteria defined in a rule.
0 commit comments