Я установил «side_status.rb» на стороне сервера на Assembla. Хотя это именно то, что я ищу (теоретически), оно не отображается, пока разработчик не попытается нажать на сервер. Если перед тем, как нажать, они совершили несколько коммитов, становится невероятно неприятно возвращаться к истории и редактировать любые недействительные сообщения фиксации.Нужна помощь при создании крючка «commit-msg» на стороне клиента Git
Я ищу, чтобы создать крючок на стороне клиента, который отклонит фиксацию разработчика, если открытый код в Assembla не упоминается в сообщении фиксации. Я предполагаю, что, поскольку он является клиентским, он не сможет проверить, открыт ли билет в пространстве проекта Assembla. Однако, если крючок мог хотя бы проверить, что «#n» был включен в сообщение фиксации (где 0 < n < 10 000), он должен поймать большинство недействительных сообщений фиксации.
GitHub предоставил образец кода для клиентской стороны «commit-msg». Я хотел бы помощи в модификации коды ниже, чтобы вместо искать номер билета (#n) в сообщении фиксации (или открытый билет в пространстве проекта Assembla, если это возможно):
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}
Я также при условии, исходный код на стороне сервера крюка, который отклоняет фиксацию, если она не содержит действительный номер открытого билета в сообщении фиксации (ticket_status.rb):
#!/usr/bin/env ruby
# -*- encoding : utf-8 -*-
#
# Reject a push to a branch if it has commits that do refer a ticket in open state
#
# ref = ARGV[0]
sha_start = ARGV[1]
sha_end = ARGV[2]
# HOOK PARAMS
space = 'space-wiki-name'
api_key = 'user-api-key'
api_secret = 'user-api-secret'
# HOOK START, end of params block
require "net/https"
require "uri"
begin
require "json"
rescue LoadError
require 'rubygems'
require 'json'
end
# Check referred tickets that are in open stage
class TicketValidator
API_URL = "https://api.assembla.com"
attr_accessor :space, :api_key, :api_secret
def initialize()
@ticket_statuses = []
@tickets = {}
end
def init
init_http
load_statuses
end
def check(sha, comment)
comment.to_s.scan(/#\d+/).each do |t|
ticket = t.tr('#', '')
# Do not check it twice
next if @tickets[ticket]
ticket_js = api_call "/v1/spaces/#{space}/tickets/#{ticket}.json"
error = nil
if ticket_js['error'].nil?
unless @ticket_statuses.include? ticket_js['status'].downcase
error = "Ticket #{t} is not open!"
end
else
error = ticket_js['error']
end
if error
@tickets[ticket] = {:error => error, :sha => sha}
else
@tickets[ticket] = :ok
end
end
end
def load_statuses
statuses = api_call "/v1/spaces/#{space}/tickets/statuses.json"
statuses.each do |status|
if status["state"] == 1 # open
@ticket_statuses << status["name"].downcase
end
end
end
def api_call(uri)
request = Net::HTTP::Get.new(uri,
{'Content-Type' => 'application/json',
'X-Api-Key' => api_key,
'X-Api-Secret' => api_secret})
result = @http.request(request)
JSON.parse(result.body)
end
def init_http
uri = URI.parse(API_URL)
@http = Net::HTTP.new(uri.host, uri.port)
@http.use_ssl = true
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
def show_decision!
@tickets.reject! {|_, value| value == :ok }
unless @tickets.empty?
puts "You have references to tickets in closed state"
@tickets.each do |ticket, details|
puts "\t#{details[:sha]} - ##{ticket} #{details[:error]}"
end
puts "Valid statuses: #{@ticket_statuses.join(', ')}"
exit 1
end
end
end
class Parser
def initialize(text, validator)
@text = text
@validator = validator
end
def parse
commit = nil
comment = nil
@validator.init
@text.to_s.split("\n").each do |line|
if line =~ /^commit: ([a-z0-9]+)$/i
new_commit = $1
if comment
@validator.check(commit, comment)
comment = nil
end
commit = new_commit
else
comment = comment.to_s + line + "\n"
end
end
# Check last commit
@validator.check(commit, comment) if comment
end
end
text = `git log --pretty='format:commit: %h%n%B' #{sha_start}..#{sha_end}`
@validator = TicketValidator.new
@validator.space = space
@validator.api_key = api_key
@validator.api_secret = api_secret
Parser.new(text, @validator).parse
@validator.show_decision!
Любой помощь очень ценится. Спасибо