X-Git-Url: https://defaria.com/gitweb/?a=blobdiff_plain;f=audience%2FJIRA%2Flib%2FJIRAUtils.pm;fp=audience%2FJIRA%2Flib%2FJIRAUtils.pm;h=0000000000000000000000000000000000000000;hb=8b59f0654d6cedeb6564480ee69acdcf0988e9ff;hp=a60e01c2037acbb9b2058ab40fcc45ddcb7d721b;hpb=63fec67e965a0aa304ec9c0daebbc7ccae283cf2;p=clearscm.git diff --git a/audience/JIRA/lib/JIRAUtils.pm b/audience/JIRA/lib/JIRAUtils.pm deleted file mode 100644 index a60e01c..0000000 --- a/audience/JIRA/lib/JIRAUtils.pm +++ /dev/null @@ -1,655 +0,0 @@ -=pod - -=head1 NAME $RCSfile: JIRAUtils.pm,v $ - -Some shared functions dealing with JIRA - -=head1 VERSION - -=over - -=item Author - -Andrew DeFaria - -=item Revision - -$Revision: 1.0 $ - -=item Created - -Fri Mar 12 10:17:44 PST 2004 - -=item Modified - -$Date: 2013/05/30 15:48:06 $ - -=back - -=head1 ROUTINES - -The following routines are exported: - -=cut - -package JIRAUtils; - -use strict; -use warnings; - -use base 'Exporter'; - -use FindBin; -use Display; -use Carp; -use DBI; - -use JIRA::REST; -use BugzillaUtils; - -our ($jira, %opts); - -our @EXPORT = qw ( - addJIRAComment - addDescription - Connect2JIRA - findIssue - getIssue - getIssueLinks - getIssueLinkTypes - getRemoteLinks - updateIssueWatchers - linkIssues - addRemoteLink - getRemoteLink - removeRemoteLink - getRemoteLinkByBugID - promoteBug2JIRAIssue - findRemoteLinkByBugID -); - -my (@issueLinkTypes, %total, %cache, $jiradb); - -sub _checkDBError ($;$) { - my ($msg, $statement) = @_; - - $statement //= 'Unknown'; - - $main::log->err ('JIRA database not opened!', 1) unless $jiradb; - - my $dberr = $jiradb->err; - my $dberrmsg = $jiradb->errstr; - - $dberr ||= 0; - $dberrmsg ||= 'Success'; - - my $message = ''; - - if ($dberr) { - my $function = (caller (1)) [3]; - - $message = "$function: $msg\nError #$dberr: $dberrmsg\n" - . "SQL Statement: $statement"; - } # if - - $main::log->err ($message, 1) if $dberr; - - return; -} # _checkDBError - -sub openJIRADB (;$$$$) { - my ($dbhost, $dbname, $dbuser, $dbpass) = @_; - - $dbhost //= $main::opts{jiradbhost}; - $dbname //= 'jiradb'; - $dbuser //= 'adefaria'; - $dbpass //= 'reader'; - - $main::log->msg ("Connecting to JIRA ($dbuser\@$dbhost)..."); - - $jiradb = DBI->connect ( - "DBI:mysql:$dbname:$dbhost", - $dbuser, - $dbpass, { - PrintError => 0, - RaiseError => 1, - }, - ); - - _checkDBError "Unable to open $dbname ($dbuser\@$dbhost)"; - - return $jiradb; -} # openJIRADB - -sub Connect2JIRA (;$$$) { - my ($username, $password, $server) = @_; - - my %opts; - - $opts{username} = $username || 'jira-admin'; - $opts{password} = $password || $ENV{PASSWORD} || 'jira-admin'; - $opts{server} = $server || $ENV{JIRA_SERVER} || 'jira-dev:8081'; - $opts{URL} = "http://$opts{server}/rest/api/latest"; - - $main::log->msg ("Connecting to JIRA ($opts{username}\@$opts{server})"); - - $jira = JIRA::REST->new ($opts{URL}, $opts{username}, $opts{password}); - - # Store username as we might need it (see updateIssueWatchers) - $jira->{username} = $opts{username}; - - return $jira; -} # Connect2JIRA - -sub addDescription ($$) { - my ($issue, $description) = @_; - - if ($main::opts{exec}) { - eval {$jira->PUT ("/issue/$issue", undef, {fields => {description => $description}})}; - - if ($@) { - return "Unable to add description\n$@"; - } else { - return 'Description added'; - } # if - } # if -} # addDescription - -sub addJIRAComment ($$) { - my ($issue, $comment) = @_; - - if ($main::opts{exec}) { - eval {$jira->POST ("/issue/$issue/comment", undef, { body => $comment })}; - - if ($@) { - return "Unable to add comment\n$@"; - } else { - return 'Comment added'; - } # if - } else { - return "Would have added comments to $issue"; - } # if -} # addJIRAComment - -sub findIssue ($%) { - my ($bugid, %bugmap) = @_; - -=pod - # Check the cache... - if ($cache{$bugid}) { - if ($cache{$bugid} =~ /^\d+/) { - # We have a cache hit but the contents here are a bugid. This means we had - # searched for the corresponding JIRA issue for this bug before and came - # up empty handed. In this situtaion we really have: - return "Unable to find a JIRA issue for Bug $bugid"; - } else { - return $cache{$bugid}; - } # if - } # if -=cut - my $issue; - - my %query = ( - jql => "\"Bugzilla Bug Number\" ~ $bugid", - fields => [ 'key' ], - ); - - eval {$issue = $jira->GET ("/search/", \%query)}; - - my $issueID = $issue->{issues}[0]{key}; - - if (@{$issue->{issues}} > 2) { - $main::log->err ("Found more than 2 issues for Bug ID $bugid"); - - return "Found more than 2 issues for Bug ID $bugid"; - } elsif (@{$issue->{issues}} == 2) { - my ($issueNum0, $issueNum1); - - if ($issue->{issues}[0]{key} =~ /(\d+)/) { - $issueNum0 = $1; - } # if - - if ($issue->{issues}[1]{key} =~ /(\d+)/) { - $issueNum1 = $1; - } # if - - if ($issueNum0 < $issueNum1) { - $issueID = $issue->{issues}[1]{key}; - } # if - - # Let's mark them as clones. See if this clone link already exists... - my $alreadyCloned; - - for (getIssueLinks ($issueID, 'Cloners')) { - my $inwardIssue = $_->{inwardIssue}{key} || ''; - my $outwardIssue = $_->{outwardIssue}{key} || ''; - - if ("RDBNK-$issueNum0" eq $inwardIssue || - "RDBNK-$issueNum0" eq $outwardIssue || - "RDBNK-$issueNum1" eq $inwardIssue || - "RDBNK-$issueNum1" eq $outwardIssue) { - $alreadyCloned = 1; - - last; - } # if - } # for - - unless ($alreadyCloned) { - my $result = linkIssues ("RDBNK-$issueNum0", 'Cloners', "RDBNK-$issueNum1"); - - return $result if $result =~ /Unable to/; - - $main::log->msg ($result); - } # unless - } # if - - if ($issueID) { - $main::log->msg ("Found JIRA issue $issueID for Bug $bugid"); - - #$cache{$bugid} = $issueID; - - #return $cache{$bugid}; - return $issueID; - } else { - my $status = $bugmap{$bugid} ? 'Future JIRA Issue' - : "Unable to find a JIRA issue for Bug $bugid"; - - # Here we put this bugid into the cache but instead of a the JIRA issue - # id we put the bugid. This will stop us from adding up multiple hits on - # this bugid. - #$cache{$bugid} = $bugid; - - return $status; - } # if -} # findJIRA - -sub getIssue ($;@) { - my ($issue, @fields) = @_; - - my $fields = @fields ? "?fields=" . join ',', @fields : ''; - - return $jira->GET ("/issue/$issue$fields"); -} # getIssue - -sub getIssueLinkTypes () { - my $issueLinkTypes = $jira->GET ('/issueLinkType/'); - - map {push @issueLinkTypes, $_->{name}} @{$issueLinkTypes->{issueLinkTypes}}; - - return @issueLinkTypes -} # getIssueLinkTypes - -sub linkIssues ($$$) { - my ($from, $type, $to) = @_; - - unless (@issueLinkTypes) { - getIssueLinkTypes; - } # unless - - unless (grep {$type eq $_} @issueLinkTypes) { - $main::log->err ("Type $type is not a valid issue link type\nValid types include:\n" - . join "\n\t", @issueLinkTypes); - - return "Unable to $type link $from -> $to"; - } # unless - - my %link = ( - inwardIssue => { - key => $from, - }, - type => { - name => $type, - }, - outwardIssue => { - key => $to, - }, - comment => { - body => "Link ported as part of the migration from Bugzilla: $from <-> $to", - }, - ); - - $main::total{'IssueLinks Added'}++; - - if ($main::opts{exec}) { - eval {$jira->POST ("/issueLink", undef, \%link)}; - - if ($@) { - return "Unable to $type link $from -> $to\n$@"; - } else { - return "Made $type link $from -> $to"; - } # if - } else { - return "Would have $type linked $from -> $to"; - } # if -} # linkIssue - -sub getRemoteLink ($;$) { - my ($jiraIssue, $id) = @_; - - $id //= ''; - - my $result; - - eval {$result = $jira->GET ("/issue/$jiraIssue/remotelink/$id")}; - - return if $@; - - my %remoteLinks; - - if (ref $result eq 'ARRAY') { - map {$remoteLinks{$_->{id}} = $_->{object}{title}} @$result; - } else { - $remoteLinks{$result->{id}} = $result->{object}{title}; - } # if - - return \%remoteLinks; -} # getRemoteLink - -sub getRemoteLinks (;$) { - my ($bugid) = @_; - - $jiradb = openJIRADB unless $jiradb; - - my $statement = 'select url from remotelink'; - - $statement .= " where url like 'http://bugs%'"; - $statement .= " and url like '%$bugid'" if $bugid; - $statement .= " group by issueid desc"; - - my $sth = $jiradb->prepare ($statement); - - _checkDBError 'Unable to prepare statement', $statement; - - $sth->execute; - - _checkDBError 'Unable to execute statement', $statement; - - my %bugids; - - while (my $record = $sth->fetchrow_array) { - if ($record =~ /(\d+)$/) { - $bugids{$1} = 1; - } # if - } # while - - return keys %bugids; -} # getRemoteLinks - -sub findRemoteLinkByBugID (;$) { - my ($bugid) = @_; - - my $condition = 'where issueid = jiraissue.id and jiraissue.project = project.id'; - - if ($bugid) { - $condition .= " and remotelink.url like '%id=$bugid'"; - } # unless - - $jiradb = openJIRADB unless $jiradb; - - my $statement = <<"END"; -select - remotelink.id, - concat (project.pkey, '-', issuenum) as issue, - relationship -from - remotelink, - jiraissue, - project -$condition -END - - my $sth = $jiradb->prepare ($statement); - - _checkDBError 'Unable to prepare statement', $statement; - - $sth->execute; - - _checkDBError 'Unable to execute statement', $statement; - - my @records; - - while (my $row = $sth->fetchrow_hashref) { - $row->{bugid} = $bugid; - - push @records, $row; - } # while - - return \@records; -} # findRemoteLinkByBugID - -sub promoteBug2JIRAIssue ($$$$) { - my ($bugid, $jirafrom, $jirato, $relationship) = @_; - - my $result = linkIssues $jirafrom, $relationship, $jirato; - - return $result if $result =~ /Unable to link/; - - $main::log->msg ($result . " (BugID $bugid)"); - - for (@{findRemoteLinkByBugID $bugid}) { - my %record = %$_; - - $result = removeRemoteLink ($record{issue}, $record{id}); - - # We may not care if we couldn't remove this link because it may have been - # removed by a prior pass. - return $result if $result =~ /Unable to remove link/; - - $main::log->msg ($result) unless $result eq ''; - } # for - - return $result; -} # promoteBug2JIRAIssue - -sub addRemoteLink ($$$) { - my ($bugid, $relationship, $jiraIssue) = @_; - - my $bug = getBug $bugid; - - # Check to see if this Bug ID already exists on this JIRA Issue, otherwise - # JIRA will duplicate it! - my $remoteLinks = getRemoteLink $jiraIssue; - - for (keys %$remoteLinks) { - if ($remoteLinks->{$_} =~ /Bug (\d+)/) { - return "Bug $bugid is already linked to $jiraIssue" if $bugid == $1; - } # if - } # for - - # Note this globalid thing is NOT working! ALl I see is null in the database - my %remoteLink = ( -# globalid => "system=http://bugs.audience.com/show_bug.cgi?id=$bugid", -# application => { -# type => 'Bugzilla', -# name => 'Bugzilla', -# }, - relationship => $relationship, - object => { - url => "http://bugs.audience.com/show_bug.cgi?id=$bugid", - title => "Bug $bugid", - summary => $bug->{short_desc}, - icon => { - url16x16 => 'http://bugs.audience.local/favicon.png', - title => 'Bugzilla Bug', - }, - }, - ); - - $main::total{'RemoteLink Added'}++; - - if ($main::opts{exec}) { - eval {$jira->POST ("/issue/$jiraIssue/remotelink", undef, \%remoteLink)}; - - return $@; - } else { - return "Would have linked $bugid -> $jiraIssue"; - } # if -} # addRemoteLink - -sub removeRemoteLink ($;$) { - my ($jiraIssue, $id) = @_; - - $id //= ''; - - my $remoteLinks = getRemoteLink ($jiraIssue, $id); - - for (keys %$remoteLinks) { - my $result; - - $main::total{'RemoteLink Removed'}++; - - if ($main::opts{exec}) { - eval {$result = $jira->DELETE ("/issue/$jiraIssue/remotelink/$_")}; - - if ($@) { - return "Unable to remove remotelink $jiraIssue ($id)\n$@" if $@; - } else { - my $bugid; - - if ($remoteLinks->{$_} =~ /(\d+)/) { - return "Removed remote link $jiraIssue (Bug ID $1)"; - } # if - } # if - - $main::total{'Remote Links Removed'}++; - } else { - if ($remoteLinks->{$_} =~ /(\d+)/) { - return "Would have removed remote link $jiraIssue (Bug ID $1)"; - } # if - } # if - } # for -} # removeRemoteLink - -sub getIssueLinks ($;$) { - my ($issue, $type) = @_; - - my @links = getIssue ($issue, ('issuelinks')); - - my @issueLinks; - - for (@{$links[0]->{fields}{issuelinks}}) { - my %issueLink = %$_; - - next if ($type && $type ne $issueLink{type}{name}); - - push @issueLinks, \%issueLink; - } - - return @issueLinks; -} # getIssueLinks - -sub updateIssueWatchers ($%) { - my ($issue, %watchers) = @_; - - my $existingWatchers; - - eval {$existingWatchers = $jira->GET ("/issue/$issue/watchers")}; - - return "Unable to get issue $issue\n$@" if $@; - - for (@{$existingWatchers->{watchers}}) { - # Cleanup: Remove the current user from the watchers list. - # If he's on the list then remove him. - if ($_->{name} eq $jira->{username}) { - $jira->DELETE ("/issue/$issue/watchers?username=$_->{name}"); - - $total{"Admins destroyed"}++; - } # if - - # Delete any matching watchers - delete $watchers{lc ($_->{name})} if $watchers{lc ($_->{name})}; - } # for - - return '' if keys %watchers == 0; - - my $issueUpdated; - - for (keys %watchers) { - if ($main::opts{exec}) { - eval {$jira->POST ("/issue/$issue/watchers", undef, $_)}; - - if ($@) { - $main::log->warn ("Unable to add user $_ as a watcher to JIRA Issue $issue"); - - $main::total{'Watchers skipped'}++; - } else { - $issueUpdated = 1; - - $main::total{'Watchers added'}++; - } # if - } else { - $main::log->msg ("Would have added user $_ as a watcher to JIRA Issue $issue"); - - $main::total{'Watchers that would have been added'}++; - } # if - } # for - - $main::total{'Issues updated'}++ if $issueUpdated; - - return ''; -} # updateIssueWatchers - -=pod - -I'm pretty sure I'm not using this routine anymore and I don't think it works. -If you wish to reserect this then please test. - -sub updateWatchers ($%) { - my ($issue, %watchers) = @_; - - my $existingWatchers; - - eval {$existingWatchers = $jira->GET ("/issue/$issue/watchers")}; - - if ($@) { - error "Unable to get issue $issue"; - - $main::total{'Missing JIRA Issues'}++; - - return; - } # if - - for (@{$existingWatchers->{watchers}}) { - # Cleanup: Mike Admin Cogan was added as a watcher for each issue imported. - # If he's on the list then remove him. - if ($_->{name} eq 'mcoganAdmin') { - $jira->DELETE ("/issue/$issue/watchers?username=$_->{name}"); - - $main::total{"mcoganAdmin's destroyed"}++; - } # if - - # Delete any matching watchers - delete $watchers{$_->{name}} if $watchers{$_->{name}}; - } # for - - return if keys %watchers == 0; - - my $issueUpdated; - - for (keys %watchers) { - if ($main::opts{exec}) { - eval {$jira->POST ("/issue/$issue/watchers", undef, $_)}; - - if ($@) { - error "Unable to add user $_ as a watcher to JIRA Issue $issue"; - - $main::total{'Watchers skipped'}++; - } else { - $main::total{'Watchers added'}++; - - $issueUpdated = 1; - } # if - } else { - $main::log->msg ("Would have added user $_ as a watcher to JIRA Issue $issue"); - - $main::total{'Watchers that would have been added'}++; - } # if - } # for - - $main::total{'Issues updated'}++ if $issueUpdated; - - return; -} # updateWatchers -=cut - -1;