On 2012-09-26 21:32, Christopher Brooks wrote:
Hi,

I've seen a bunch of +1's on list but no one has updated the wiki page
of tasks in order to help make this a reality.  +1 means you support
the proposal both in spirit and in contribution, so please, if you
really want this add  your name next to a deliverable here:

http://opencast.jira.com/wiki/display/MH/Switching+to+Git

And get to work on it; we won't be able to switch to git without these
tasks finished (and potentially more).

Chris

I'm not the right person to solve this problem, but I'll try to explain how we have done the jira-git integration at UiB.

The svntogit script that we run on jenkins (https://github.com/uib/jenkins-svn2git) takes care of both tags and branches automatically. (The jira branches looks a bit funny in git though)

Mapping from jira to git is done by cgit-commit-filter (relies on cgit, but can probably be solved by other commit filters as well) which transforms commit messages that has refs to a jira case to an url

#!/usr/bin/perl -p

s,(?:https://(?:jira\.uib\.no/(?:jira/)?browse/)?(J[A-Z]+-\d+),<a 
href="https://jira.uib.no/browse/$1";>$1</a>,g;

and from git to jira we use a jira-gitbot (attached) based on
http://confluence.atlassian.com/display/JIRAEXT/JIRA+Command+Line+Interface

our repo:
https://github.com/uib/matterhorn

Last: About the branch mapping; why does each ticket need to be a branch, isn’t that just making a big mess? I'm not very experienced with svn so bare with me if this a silly question :)
--

Olav Bringedal

Seksjon for integrasjon og applikasjonsutvikling
IT-Avdelingen UIB
#!/opt/perl/bin/perl -w

# This script will read RSS commit feeds and then post comments in
# Jira where an issue-ID is mentioned.

use strict;
use LWP::UserAgent;
use XML::Simple qw(XMLin);
use DBI;

our $PROGNAME = "gitbot-watch";
our $VERSION = "0.01";

my @FEEDS = (
    # Insert any feeds you want to watch here
    # git.uib.no/cgit master feeds are automatically picked up by code (below)

    #"http://git.uib.no/cgit/site/www.uib.no.git/atom/?h=JEW-25";,
);

my @CGIT_ROOTS = (
    "http://git.uib.no/cgit/";,
);

# This should be a version of the Jira command line interface script
# configured to login as 'gitbot'.
# http://confluence.atlassian.com/display/JIRAEXT/JIRA+Command+Line+Interface
my $JIRA_GITBOT = "$ENV{HOME}/bin/jira-gitbot";

use Getopt::Long qw(GetOptions);
GetOptions(\my %opt,
    'dry-run',
    'catch-up',
    'list-feeds',
    'verbose',
) or usage();
usage() if @ARGV;

my $ua = LWP::UserAgent->new(
    agent => "$PROGNAME/$VERSION ",
    keep_alive => 1,
    show_progress => -t,
);

# pick up the cgit feeds
for my $cgit_root (@CGIT_ROOTS) {
    my $res = $ua->get($cgit_root);
    next unless $res->is_success;
    next unless $res->content_type eq "text/html";
    require HTML::LinkExtor;
    my $p = HTML::LinkExtor->new(undef, $res->base);
    $p->parse($res->decoded_content)->eof;
    my %seen;
    for ($p->links) {
        my($tag, %attr) = @$_;
        next unless $tag eq "a";
        my $href = $attr{href};
        next unless $href;
        next unless $href && $href =~ m,\.git/\z,;
        next if $seen{$href}++;
        push(@FEEDS, $href . "atom/");
    }
}

if ($opt{"list-feeds"}) {
    print "$_\n" for @FEEDS;
    exit;
}

my $dbh = setup_db("var/$PROGNAME.db");

my $JIRA_ISSUE_ID_re = do {
    my $projects = join("|", sort +jira_projects());
    die "Can't lookup projects in Jira [$projects]" unless $projects =~ /JEW/;
    qr/\b((?:$projects)-\d+)/;
};

for my $feed (@FEEDS) {
    my $res = $ua->get($feed);
    unless ($res->is_success) {
        next;
    }
    unless ($res->content_type =~ /\bxml\b/) {
        print "  ==> unrecognized content type '" . $res->content_type . "'\n";
        next;
    }

    my $feed_info = XMLin($res->decoded_content,
        ForceArray => ['item', 'entry'],
        KeyAttr => [],
        KeepRoot => 1,
    );
    if ($feed_info->{rss}{version}) {
        my @items = reverse @{$feed_info->{rss}{channel}{item}};
        process_rssitem($_) for @items;
    }
    elsif (($feed_info->{feed}{xmlns} || "") eq "http://www.w3.org/2005/Atom";) {
        my @items = reverse @{delete $feed_info->{feed}{entry}};
        #use Data::Dump; dd $feed_info;
        for my $item (@items) {
            # convert to RSS form
            $item->{guid} = $feed . "#" . $item->{id};
            my $link = $item->{atom_link} = $item->{link};
            $item->{link} = $link->{href};
            process_rssitem($item);
        }
    }
    else {
        print "  ==> doesn't look like an RSS feed\n";
        next;
    }
}

sub process_rssitem {
    my $item = shift;
    #use Data::Dump; dd $item;

    my $guid = $item->{guid} || $item->{link} || return;
    my $link = $item->{link} || $item->{guid} || return;
    my $text = $item->{title};
    $text .= "\n$item->{description}" if $item->{description};
    $text .= "\n" unless $text =~ /\n\z/;

    # We did not get redirected to https when running this service
    # from void; so in order to keep the guids compatible drop the 's'.
    $guid =~ s,^(http)s(://git\.uib\.no),$1$2,;

    if (already_processed($guid)) {
        print "Already processed: $guid\n" if $opt{verbose};
        return;
    }

    if ($link =~ /\bvoid\.uib\.no\/bazaar\//) {
        # description just repeats most of the text in the title; clean it up
        $text =~ s/^(\S+: \d+: ).*\n/$1/;
    }

    my @ids = $text =~ /$JIRA_ISSUE_ID_re/g;
    if (@ids) {
        print "$guid: @ids\n";
        for my $id (@ids) {
            my $comment = "$text$link";
            $comment =~ s/^((?:\S+: \d+: )?)\Q$id\E:?\s+/$1/;
            jira_add_comment($id, $comment);
        }
    }
    remember_processed($guid, @ids) unless $opt{"dry-run"};
}

sub jira_projects {
    my @projects;
    for (split(/^/, jira("getProjectList"))) {
        push(@projects, $1) if /([A-Z]+), \d+./;
    }
    return @projects;
}

sub jira_add_comment {
    my($issue, $comment) = @_;
    if ($opt{"dry-run"} || $opt{"catch-up"}) {
        print "addComment to $issue skipped\n";
        return;
    }
    return jira("addComment", "--issue", $issue, "--comment", $comment);
}

sub jira {
    my($action, @args) = @_;
    my @cmd = ($JIRA_GITBOT, "--action", $action, @args);
    #print "@cmd\n";
    my $pid = open(my $fh, "-|");
    die unless defined $pid;
    unless ($pid) {
        # kid
        exec(@cmd);
        exit 1;
    }
    my $output = do { local $/; <$fh> };
    die "Can't wait for $pid: $!" unless $pid == waitpid $pid, 0;
    die "jira exits with $?" if $?;
    return $output;
}

sub setup_db {
    my $dbname = shift;
    my $dbh = DBI->connect("dbi:SQLite:dbname=$dbname", "", "", {
        AutoCommit => 1,
        RaiseError => 1,
    });

    local $dbh->{AutoCommit} = 0;
    my $v = $dbh->selectrow_array("PRAGMA user_version");
    die "Assert" unless defined $v;
    if ($v == 0) {
        print "Setting up schema for $dbname";
        $dbh->do(<<'EOT');
CREATE TABLE rss_item (
    guid text PRIMARY KEY,
    jira_issues text NOT NULL,
    processed datetime NOT NULL DEFAULT CURRENT_TIMESTAMP
)
EOT
        $dbh->do("PRAGMA user_version = 1");
        $dbh->commit;
    }
    elsif ($v != 1) {
        die "Unrecognized database schema $v for $dbname";
    }
    return $dbh;
}

sub already_processed {
    my $guid = shift;
    my $seen = $dbh->selectrow_array("SELECT count(*) FROM rss_item WHERE guid 
= ?", undef, $guid);
    return $seen;
}

sub remember_processed {
    my $guid = shift;
    $dbh->do("INSERT INTO rss_item(guid, jira_issues) VALUES (?, ?)", undef, 
$guid, join(" ", @_));
}

sub usage {
    die "Usage: $PROGNAME [--dry-run] [--catch-up]\n";
}
_______________________________________________
Matterhorn mailing list
[email protected]
http://lists.opencastproject.org/mailman/listinfo/matterhorn


To unsubscribe please email
[email protected]
_______________________________________________

Reply via email to