Skip to content

Instantly share code, notes, and snippets.

@dave1010
Forked from elskwid/jira_post_receive.rb
Created March 24, 2011 14:48
Show Gist options
  • Select an option

  • Save dave1010/885178 to your computer and use it in GitHub Desktop.

Select an option

Save dave1010/885178 to your computer and use it in GitHub Desktop.

Revisions

  1. dave1010 revised this gist Mar 24, 2011. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion jira_post_receive.rb
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,7 @@
    #!/usr/bin/env ruby
    #
    # From http://foodforsamurai.com/post/483440483/git-to-jira
    #
    # Update JIRA with git commit messages
    #
    # == Usage ==
    @@ -213,4 +215,4 @@ def branch_updated?
    old_commit, new_commit, ref = STDIN.gets.split
    JiraPostReceive.new(old_commit, new_commit, ref).run

    exit 0
    exit 0
  2. @invalid-email-address Anonymous created this gist Oct 21, 2008.
    216 changes: 216 additions & 0 deletions jira_post_receive.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,216 @@
    #!/usr/bin/env ruby
    #
    # Update JIRA with git commit messages
    #
    # == Usage ==
    #
    # To update a JIRA issue, prepend the first line of your git commit message
    # with the issue key and a colon:
    #
    # $ git commit -m "GIT-1: Updates something"
    #
    # A comment will be added to the GIT-1 issue that looks something like:
    #
    # Commit: <Hash>
    # Author: Bob Example <bob@example.com>
    # Date: Mon Jul 14 14:00:00 -0400 2008
    #
    # GIT-1: Updates something
    #
    # To change an issue's status, append an action string:
    #
    # GIT-1 resolved: Updates something
    # GIT-1 closed: Finishes this
    # GIT-1 reopen: Starting work on this
    #
    # To update multiple issues, separate them with a comma:
    #
    # GIT-1, GIT-2: Adds comments to GIT-1 and GIT-2
    # GIT-1, GIT-2 resolved: Updates GIT-1 and resolves GIT-2
    #
    # == Installation ==
    #
    # To get this working, first install a few gems:
    #
    # $ gem install soap4r
    #
    # Now, jira4r, which has to be pulled down from subversion:
    #
    # $ svn co http://svn.rubyhaus.org/jira4r/trunk jira4r
    # $ cd jira4r
    # $ gem build jira4r.gemspec
    # $ gem install jira4r-*.gem
    #
    # And finally, grit, a Ruby git library. As of today (July 14, 2008),
    # the most updated fork is being maintained by Scott Chacon on github.
    # For whatever reason, my attempt to install the gem directly wasn't
    # working (doesn't appear to be exposed?), so I cloned and installed
    # directly:
    #
    # $ git clone git://github.com/schacon/grit.git
    # $ cd grit
    # $ gem build grit.gemspec
    # $ gem install grit-*.gem
    #
    # When the gem gets fixed, it should be a simple:
    #
    # $ gem sources --add http://gems.github.com
    # $ gem install schacon-grit
    #
    # Now just copy/symlink/move an executable copy of this file into your
    # .git/hooks directory (be sure not to overwrite an existing hook):
    #
    # $ cp jira-post-receive /path/to/repository/.git/hooks/post-receive
    #
    # And don't forget to update some globals below. Voila. You should be
    # in business.
    #
    # == TODO ==
    #
    # * Get status changes with comments working.
    #

    require "rubygems"
    require "jira4r/jira_tool"
    require "grit"

    # Don't forget to set these.
    #
    # I'd recommend creating a dedicated user in JIRA to execute these updates.
    # That user will need permissions to:
    #
    # * Browse Projects
    # * Resolve Issues
    # * Close Issues
    # * Add Comments
    #
    # (I think that's comprehensive.)
    JIRA_ADDRESS = "http://yourserver.com/jira"
    JIRA_PROJECT = "DEWEBMO"
    JIRA_USERNAME = "user"
    JIRA_PASSWORD = "password"

    class JiraPostReceive
    def initialize(old_commit, new_commit, ref)
    @old_commit = old_commit
    @new_commit = new_commit
    @ref = ref

    @repo = Grit::Repo.new(".")
    end

    def jira
    unless @jira
    @jira = Jira4R::JiraTool.new(2, JIRA_ADDRESS)
    @jira.logger = Logger.new("/dev/null")
    @jira.login(JIRA_USERNAME, JIRA_PASSWORD)
    end
    @jira
    end

    def run
    unless issues.empty?
    jira # Sets up access to Jira4R::V2 constants

    issues.each do |issue|
    begin
    send_comment(issue)
    send_new_status(issue) if issue[:new_status]
    rescue
    next
    end
    end
    end
    end

    # Adds a comment to the JIRA issue
    #
    # Unfortunately, all comments originate from the dedicated JIRA user
    # that's used to post the comment. It's possible to set a different
    # author for the comment, but looking one up via email in JIRA doesn't
    # seem possible without giving the user administrative rights.
    def send_comment(issue)
    comment = Jira4R::V2::RemoteComment.new
    comment.author = JIRA_USERNAME
    comment.body = generate_comment(issue[:commit])

    jira.addComment(issue[:key], comment)
    end

    def send_new_status(issue)
    status_string = case issue[:new_status]
    when "resolved" then "Resolve Issue"
    when "closed" then "Close Issue"
    when "reopen" then "Reopen Issue"
    end

    if status = jira.getAvailableActions(issue[:key]).
    find { |a| a.name == status_string }
    jira.progressWorkflowAction(issue[:key], status.id.to_s, [])
    end
    end

    def issues
    issues = []
    issued_commits.each do |commit|
    issue_string = commit.short_message.match(/(.*?):/)[1]
    issue_string.split(",").each do |snippet|
    snippet.strip!
    snippet =~ /(#{JIRA_PROJECT}-\d+)\s?(resolved|closed|reopen)?/i
    issues << { :key => $1, :new_status => $2, :commit => commit }
    end
    end
    issues
    end

    def issued_commits
    new_commits.select do |commit|
    commit.short_message =~ /(#{JIRA_PROJECT}-\d+)(.*):/
    end
    end

    # Fetch commits that are new to the repository
    #
    # That super-piped git command makes sure that we only update JIRA with
    # commits that are new, and haven't been seen in any other branches.
    # It's lifted verbatim from the post-receive-email hook that's shipped
    # in the git repository (contrib/hooks/post-receive-email).
    def new_commits
    common_cmd = "git rev-parse --not --branches | " +
    "grep -v $(git rev-parse #{@ref}) | " +
    "git rev-list --stdin "

    commit_ids = if branch_created?
    `#{common_cmd} #{@new_commit}`.split
    elsif branch_updated?
    `#{common_cmd} #{@old_commit}..#{@new_commit}`.split
    else
    []
    end

    commit_ids.map { |id| @repo.commit(id) }.reverse
    end

    def generate_comment(commit)
    <<-EOS
    Commit: #{commit.id}
    Author: #{commit.author.name} <#{commit.author.email}>
    Date: #{commit.authored_date}
    #{commit.message}
    EOS
    end

    def branch_created?
    @ref =~ /refs\/heads/ && @old_commit =~ /^0+$/
    end

    def branch_updated?
    @ref =~ /refs\/heads/ && @old_commit !~ /^0+$/ && @new_commit !~ /^0+$/
    end
    end

    old_commit, new_commit, ref = STDIN.gets.split
    JiraPostReceive.new(old_commit, new_commit, ref).run

    exit 0