代码之家  ›  专栏  ›  技术社区  ›  Andrew

“git”的JIRA代码验证提交挂钩

  •  14
  • Andrew  · 技术社区  · 16 年前

    是否有人可以使用git提交钩子来确保JIRA问题号出现在签入消息中?我还没有从git提交钩子中驱动JIRA的经验,所以任何帮助都将不胜感激——工作源代码更是如此!

    4 回复  |  直到 16 年前
        1
  •  18
  •   Nicolas    16 年前

    chmod a+x .git/hooks/commit-msg
    

    附加以下行,用项目代码替换项目。

    test "" != "$(grep 'PROJECT-' "$1")" || {
            echo >&2 "ERROR: Commit message is missing Jira issue number."
            exit 1
    }
    
        2
  •  1
  •   Lambda    16 年前
    #!/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/repo/.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  = "DEMO"
    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
    
        3
  •  0
  •   user160725 user160725    16 年前

    Ops,我从来没有使用过git,但是我的一个朋友制作了SVN钩子,一个用于创建Subversion钩子的框架。它是用perl编写的。也许这会有所帮助。看看那里:

    http://code.google.com/p/svn-hooks/source/browse/trunk/t/02-jiraacceptance.t

    如果你需要打电话给我们,我们很乐意帮助你。

        4
  •  -1
  •   Greg Hewgill    16 年前

    就像JIRA发行号出现在提交消息的某个地方一样。为此,一个简单的正则表达式匹配即可:

    /[A-Z0-9]+-\d+/
    

    如果需要,为了提供额外的打字保护,您可以确保第一部分与您在JIRA中设置的某些项目标识符相匹配:

    /(ABC|XYZ|PONIES)-\d+/
    

    我发现试图确保 其中一部分是指有效的发行号。实际上没有任何方法可以确定用户是否输入了正确的发行号(即使您设法将其限制为开放发行,用户仍可以输入一个不相关的开放发行号)。在提交代码时,用户应该谨慎。

    推荐文章