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

发布于 2024-08-05 20:50:21 字数 110 浏览 10 评论 0原文

有谁有我可以使用的 git commit hook 来确保 JIRA 问题号出现在签入消息中吗?我没有从 git commit hook 驱动 JIRA 的经验,所以任何帮助将不胜感激 - 工作源更是如此!

Does anyone have a git commit hook I can use that will ensure a JIRA issue number appears in the checkin message? I've got no experience driving JIRA from a git commit hook so any help would be appreciated -- working source even more so!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

半边脸i 2024-08-12 20:50:21

首先,使挂钩可执行:

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

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

test "" != "$(grep 'PROJECT-' "$1")" || {
        echo >&2 "ERROR: Commit message is missing Jira issue number."
        exit 1
}

First, make the hook executable:

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

Append the following lines, substituting PROJECT with your project's code.

test "" != "$(grep 'PROJECT-' "$1")" || {
        echo >&2 "ERROR: Commit message is missing Jira issue number."
        exit 1
}
凉墨 2024-08-12 20:50:21
#!/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 <[email protected]>
#     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
#!/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 <[email protected]>
#     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
甜尕妞 2024-08-12 20:50:21

Ops,我仍然从未使用过 git,但一位朋友制作了 SVN-Hooks,一个用于创建 Subversion hook 的框架。它是用 Perl 编码的。也许这有任何帮助。看看那里:

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

如果您需要致电我们,我们会尽快很乐意提供帮助。

Ops, I never, still, used git but a friend made SVN-Hooks, a framework for creating Subversion hooks. It was coded in perl. Maybe this help in any way.Take a look on it there:

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

And if you need call us, ASAP we 'll be glad to help.

落花浅忆 2024-08-12 20:50:21

我会编写一个提交挂钩,以确保看起来像 JIRA 问题编号的内容出现在提交消息中的某处。为此,一个简单的正则表达式匹配就可以做到:

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

如果您愿意,为了额外的拼写错误保护,您可以确保第一部分与您在 JIRA 中设置的某些项目标识符匹配:

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

我发现尝试没有什么价值确保其中的数字部分引用有效的发行号。实际上没有任何方法可以确定用户是否输入了正确的问题编号(即使您设法将其限制为未解决的问题,用户仍然可以输入不相关的未解决的问题编号)。用户在提交代码时应谨慎行事。

I would write a commit hook that ensures that something that looks like a JIRA issue number appears somewhere in the commit message. To do that, a simple regular expression match would do it:

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

If you want, for extra typo-protection you can ensure that the first part matches with some project identifier that you have set up in JIRA:

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

I find there is little value in trying to make sure that the number part of that refers to a valid issue number. There isn't really any way to determine whether the user has entered the correct issue number (even if you manage to limit it to open issues, the user could still enter an unrelated open issue number). Users should be expected to take due care when committing code.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文