geometrialab-abak-flow 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +7 -0
- data/README.md +116 -0
- data/Rakefile +1 -0
- data/VERSION +1 -0
- data/bin/request +4 -0
- data/geometrialab-abak-flow.gemspec +24 -0
- data/lib/abak-flow/hub_extensions.rb +111 -0
- data/lib/abak-flow/request.rb +285 -0
- data/lib/abak-flow/version.rb +5 -0
- data/lib/abak-flow.rb +11 -0
- metadata +117 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
Abak-flow
|
2
|
+
=========
|
3
|
+
Нет, это не новая идеология ведения проекта, это всего лишь набор утилит которые помогают связать использование [git-flow](https://github.com/nvie/gitflow) и [github flow](http://scottchacon.com/2011/08/31/github-flow.html)
|
4
|
+
|
5
|
+
# Концепция
|
6
|
+
Идеология git-flow использует следующий набор веток:
|
7
|
+
|
8
|
+
* *master* - всегда пригодна для развертывания
|
9
|
+
* *develop* - основная ветка разработки
|
10
|
+
* *hotfix* - ветка для изменений которые попадут на продакшен сервер
|
11
|
+
* *feature* - ветки для крупных задач
|
12
|
+
|
13
|
+
Github-flow же наоборот ведет основную разработку в ветке master, но при этом master является пригодным для развертывания в любой момент.
|
14
|
+
|
15
|
+
После долгих раздумий было принято применить следующий набор правил, для разработки на github:
|
16
|
+
|
17
|
+
1. Вся разработка любой задачи и функционала ведется только в ветках **feature**
|
18
|
+
2. Разработаный функционал из ветки **feature** оформляется pull request только в ветку **develop**
|
19
|
+
3. Все исправления ошибок, которые должны попасть на продакшен сервер делаются только в ветках **hotfix**
|
20
|
+
4. Исправленные ошибки из ветки **hotfix** фофрмляются pull request только в ветку **master**
|
21
|
+
5. После получения исправлений на текущий момент в репозитории инициируется merge ветки **master** в **develop**
|
22
|
+
|
23
|
+
|
24
|
+
# Установка
|
25
|
+
|
26
|
+
$ gem install abak-flow
|
27
|
+
$ git config --global alias.request '!request'
|
28
|
+
$ git config --global abak.apiuser your_github_mail@gmail.com
|
29
|
+
$ git config --global abak.apitoken 0123456789yourf0123456789token
|
30
|
+
$ git remote add upstream git://github.com/github_user_name/project.git
|
31
|
+
|
32
|
+
### А если я использую прокси, как быть?
|
33
|
+
$ git config --global abak.proxy http://my-proxy.com:3129
|
34
|
+
|
35
|
+
Далее по приоритету идут переменные окружения. Сначала **http_proxy**, затем **HTTP_PROXY**
|
36
|
+
|
37
|
+
Т.е если вы используете переменные окружения, то просто не указывайте прокси в конфиге
|
38
|
+
|
39
|
+
### А если у меня есть баг-трэкер?
|
40
|
+
$ git config --global abak.tracker http://mytracker.com/ticket/
|
41
|
+
|
42
|
+
К указанному адресу будет доавлен номер тикета для формирования ссылок на задачи в описании пулл реквестов.
|
43
|
+
|
44
|
+
---
|
45
|
+
|
46
|
+
**Заметьте:** В конфиге git, значением *abak.apiuser* должен являться тот email адрес, под которым вы заходите на github
|
47
|
+
|
48
|
+
**Обратите внимание:** В данном контексте под **upstream** подразумевается адрес репозитория в который будут оформляться pull request. А репозиторием **origin** будет являться ваш форк
|
49
|
+
|
50
|
+
# С чего начать?
|
51
|
+
|
52
|
+
$ git request readycheck
|
53
|
+
|
54
|
+
или
|
55
|
+
|
56
|
+
$ git request help
|
57
|
+
|
58
|
+
**Примечание:** Вообще-то все комманды поддерживают опцию *--help*, но вот именно *git request --help* успевает перехватиться самим git и он конечно неодумевает как ему показать хэлп по внешней комманде
|
59
|
+
|
60
|
+
# Примеры использования
|
61
|
+
### Самый простой способ начать новую задачу:
|
62
|
+
|
63
|
+
$ git checkout develop
|
64
|
+
$ git request feature 'TASK-001'
|
65
|
+
$ touch 'hello.txt' && echo 'Hello world!' > hello.txt
|
66
|
+
$ git commit -a -m 'Hello world commit'
|
67
|
+
$ git request publish
|
68
|
+
|
69
|
+
Теперь то же самое, только словами:
|
70
|
+
|
71
|
+
* Переключимся в ветку develop
|
72
|
+
* Abak-flow создаст ветку, пригодную для оформления pull request (правила именования и правила самого реквеста)
|
73
|
+
* Простое создание нового файла
|
74
|
+
* Git процедуры добавления своих изменений в репозиторий
|
75
|
+
* Затем публикация вашей ветки на вашем форке (если таковая уже есть, то просто обновление), затем оформление pull request из этой ветки в соответствующую правилам ветку на upstream (в данном случае это будет ветка develop)
|
76
|
+
|
77
|
+
Для задач, которые должны быть выполнены в виде hotfix принцип тот же:
|
78
|
+
|
79
|
+
$ git checkout master
|
80
|
+
$ git request hotfix 'TASK-001'
|
81
|
+
$ …
|
82
|
+
$ git request publish
|
83
|
+
|
84
|
+
*На самом деле переключаться на master или develop в самом начале вовсе не обязательно, этот шаг был приведен для пущей ясности*
|
85
|
+
|
86
|
+
### Обновление ветки на удаленном репозитории:
|
87
|
+
|
88
|
+
$ git checkout feature/TASK-001
|
89
|
+
$ git request update
|
90
|
+
|
91
|
+
### Завершение текущей задачи:
|
92
|
+
Вообще, завершать задачу лучше только после того, как ваш pull request был принят. Почему? На самом деле по ряду причин. По умолчанию эта команда удаляет как вашу текущую ветку с задачей в локальном репозитории и в добавок ко всему - на вашем удаленном репозитории (форке)
|
93
|
+
|
94
|
+
$ git co feature/TASK-001
|
95
|
+
$ git request done
|
96
|
+
|
97
|
+
Чтобы оставить какую либо ветку в живых возможно напрямую указать, какую копию ветки **удалить**, локальную или же удаленную (на origin)
|
98
|
+
|
99
|
+
$ git co feature/TASK-001
|
100
|
+
$ git request done --origin
|
101
|
+
|
102
|
+
Или же так
|
103
|
+
|
104
|
+
$ git co feature/TASK-001
|
105
|
+
$ git request done --local
|
106
|
+
|
107
|
+
## Маленькие хитрости
|
108
|
+
Если сразу правильно именовать ветки, т.е ветку с задачей создавать с именем, такого формата TASK-001, то, в описание pull request автоматически вставится ссылка на задачу в jira, а в имя pull request сразу вставится название, состоящее из имени задачи, т.е TASK-001
|
109
|
+
|
110
|
+
## А помощь?
|
111
|
+
Многие команды имеют какие-то дополнительные опции. Но они нужны только в экзотических случаях. Но при любом раскладе подсказку и тонкий намек всегда можно получить воспользовавших такой командой:
|
112
|
+
|
113
|
+
$ git request done --help
|
114
|
+
|
115
|
+
# В заключении
|
116
|
+
Данный репозиторий и изложенные в нем идеи ни в коем случае не претендуют на идеал и совершенство. Это всего лишь узко заточенная комбинация гемов
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.2
|
data/bin/request
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path('../lib', __FILE__)
|
3
|
+
require 'abak-flow/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'geometrialab-abak-flow'
|
7
|
+
s.version = Abak::Flow::VERSION
|
8
|
+
s.authors = ['Strech (aka Sergey Fedorov)']
|
9
|
+
s.email = ['oni.strech@gmail.com']
|
10
|
+
s.homepage = 'https://github.com/Strech/abak-flow'
|
11
|
+
s.summary = %q{Совмещение 2-х подходов разработки Git-flow & Github-flow}
|
12
|
+
s.description = %q{Простой набор правил и комманд, заточеных для работы в git-flow с использование в качестве удаленного репозитория github}
|
13
|
+
|
14
|
+
# s.rubyforge_project = 'abak-flow'
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ['lib']
|
20
|
+
|
21
|
+
s.add_runtime_dependency 'hub'
|
22
|
+
s.add_runtime_dependency 'commander'
|
23
|
+
s.add_runtime_dependency 'octokit'
|
24
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Abak::Flow
|
2
|
+
class ::Hub::Runner
|
3
|
+
def execute
|
4
|
+
if args.noop?
|
5
|
+
puts commands
|
6
|
+
elsif not args.skip?
|
7
|
+
if args.chained?
|
8
|
+
execute_command_chain
|
9
|
+
else
|
10
|
+
%x{#{args.to_exec.join(' ')}}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ::Hub::Commands
|
17
|
+
def pull_request(args)
|
18
|
+
args.shift
|
19
|
+
options = { }
|
20
|
+
force = explicit_owner = false
|
21
|
+
base_project = local_repo.main_project
|
22
|
+
head_project = local_repo.current_project
|
23
|
+
|
24
|
+
from_github_ref = lambda do |ref, context_project|
|
25
|
+
if ref.index(':')
|
26
|
+
owner, ref = ref.split(':', 2)
|
27
|
+
project = github_project(context_project.name, owner)
|
28
|
+
end
|
29
|
+
[project || context_project, ref]
|
30
|
+
end
|
31
|
+
|
32
|
+
while arg = args.shift
|
33
|
+
case arg
|
34
|
+
when '-f'
|
35
|
+
force = true
|
36
|
+
when '-b'
|
37
|
+
base_project, options[:base] = from_github_ref.call(args.shift, base_project)
|
38
|
+
when '-h'
|
39
|
+
head = args.shift
|
40
|
+
explicit_owner = !!head.index(':')
|
41
|
+
head_project, options[:head] = from_github_ref.call(head, head_project)
|
42
|
+
when '-i'
|
43
|
+
options[:issue] = args.shift
|
44
|
+
when '-d'
|
45
|
+
options[:body] = args.shift
|
46
|
+
else
|
47
|
+
if url = resolve_github_url(arg) and url.project_path =~ /^issues\/(\d+)/
|
48
|
+
options[:issue] = $1
|
49
|
+
base_project = url.project
|
50
|
+
elsif !options[:title] then options[:title] = arg
|
51
|
+
else
|
52
|
+
abort "invalid argument: #{arg}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
options[:project] = base_project
|
58
|
+
options[:base] ||= master_branch.short_name
|
59
|
+
|
60
|
+
if tracked_branch = options[:head].nil? && current_branch.upstream
|
61
|
+
if base_project == head_project and tracked_branch.short_name == options[:base]
|
62
|
+
$stderr.puts "Aborted: head branch is the same as base (#{options[:base].inspect})"
|
63
|
+
warn "(use `-h <branch>` to specify an explicit pull request head)"
|
64
|
+
abort
|
65
|
+
end
|
66
|
+
end
|
67
|
+
options[:head] ||= (tracked_branch || current_branch).short_name
|
68
|
+
|
69
|
+
# when no tracking, assume remote branch is published under active user's fork
|
70
|
+
user = github_user(true, head_project.host)
|
71
|
+
if head_project.owner != user and !tracked_branch and !explicit_owner
|
72
|
+
head_project = head_project.owned_by(user)
|
73
|
+
end
|
74
|
+
|
75
|
+
remote_branch = "#{head_project.remote}/#{options[:head]}"
|
76
|
+
options[:head] = "#{head_project.owner}:#{options[:head]}"
|
77
|
+
|
78
|
+
if !force and tracked_branch and local_commits = git_command("rev-list --cherry #{remote_branch}...")
|
79
|
+
$stderr.puts "Aborted: #{local_commits.split("\n").size} commits are not yet pushed to #{remote_branch}"
|
80
|
+
warn "(use `-f` to force submit a pull request anyway)"
|
81
|
+
abort
|
82
|
+
end
|
83
|
+
|
84
|
+
if args.noop?
|
85
|
+
puts "Would reqest a pull to #{base_project.owner}:#{options[:base]} from #{options[:head]}"
|
86
|
+
exit
|
87
|
+
end
|
88
|
+
|
89
|
+
unless options[:title] or options[:issue]
|
90
|
+
base_branch = "#{base_project.remote}/#{options[:base]}"
|
91
|
+
changes = git_command "log --no-color --pretty=medium --cherry %s...%s" %
|
92
|
+
[base_branch, remote_branch]
|
93
|
+
|
94
|
+
options[:title], options[:body] = pullrequest_editmsg(changes) { |msg|
|
95
|
+
msg.puts "# Requesting a pull to #{base_project.owner}:#{options[:base]} from #{options[:head]}"
|
96
|
+
msg.puts "#"
|
97
|
+
msg.puts "# Write a message for this pull request. The first block"
|
98
|
+
msg.puts "# of text is the title and the rest is description."
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
pull = create_pullrequest(options)
|
103
|
+
|
104
|
+
args.executable = 'echo'
|
105
|
+
args.replace [pull['html_url']]
|
106
|
+
rescue HTTPExceptions
|
107
|
+
display_http_exception("creating pull request", $!.response)
|
108
|
+
exit 1
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,285 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
module Abak::Flow
|
3
|
+
# @TODO Сделать класс, в котором собрать общие куски из задач
|
4
|
+
|
5
|
+
program :name, 'Утилита для оформления pull request на github.com'
|
6
|
+
program :version, Abak::Flow::VERSION
|
7
|
+
program :description, 'Утилита, заточенная под git-flow но с использованием github.com'
|
8
|
+
|
9
|
+
default_command :help
|
10
|
+
command :publish do |c|
|
11
|
+
c.syntax = 'git request publish <Заголовок>'
|
12
|
+
c.description = 'Оформить pull request из текущей ветки (feature -> develop, hotfix -> master)'
|
13
|
+
|
14
|
+
# Опции нужны, если человек хочет запушить ветку, с именем отличным от стандарта
|
15
|
+
c.option '--head STRING', String, 'Имя ветки, которую нужно принять в качестве изменений'
|
16
|
+
c.option '--base STRING', String, 'Имя ветки, в которую нужно принять изменения'
|
17
|
+
|
18
|
+
c.action do |args, options|
|
19
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
20
|
+
|
21
|
+
request_rules = {:feature => :develop, :hotfix => :master}
|
22
|
+
|
23
|
+
repository = Hub::Commands.send :local_repo
|
24
|
+
current_branch = repository.current_branch.short_name
|
25
|
+
remote_branch, task = current_branch.split('/').push(nil).map(&:to_s)
|
26
|
+
|
27
|
+
title = args.first.to_s.strip
|
28
|
+
title = task if task =~ /^\w+\-\d{1,}$/ && title.empty?
|
29
|
+
|
30
|
+
tracker_url = Hub::Commands.send(:git_reader).read_config('abak.tracker')
|
31
|
+
api_user = Hub::Commands.send(:git_reader).read_config('abak.apiuser')
|
32
|
+
api_token = Hub::Commands.send(:git_reader).read_config('abak.apitoken')
|
33
|
+
config_proxy = Hub::Commands.send(:git_reader).read_config('abak.proxy')
|
34
|
+
env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
35
|
+
|
36
|
+
client_opts = {:proxy => config_proxy || env_proxy} if config_proxy || env_proxy
|
37
|
+
client_opts ||= {}
|
38
|
+
|
39
|
+
api_client = Octokit::Client.new({:login => api_user, :oauth_token => api_token}.merge(client_opts))
|
40
|
+
|
41
|
+
# Проверим, что мы не в мастере или девелопе
|
42
|
+
if [:master, :develop].include? current_branch.to_sym
|
43
|
+
say color('Нельзя делать pull request из меток master или develop', :error).to_s
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
|
47
|
+
# Проверим, что у нас настроен origin
|
48
|
+
if repository.remote_by_name('origin').nil?
|
49
|
+
say color('Необходимо настроить репозиторий origin (форк) для текущего пользователя', :error).to_s
|
50
|
+
say color('=> git remote add origin https://Developer@github.com/abak-press/sample.git', :info).to_s
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
|
54
|
+
# Проверим, что у нас настроен upstream
|
55
|
+
if repository.remote_by_name('upstream').nil?
|
56
|
+
say color('Необходимо настроить репозиторий upstream (главный) для текущего пользователя', :error).to_s
|
57
|
+
say color('=> git remote add upstream https://Developer@github.com/abak-press/sample.git', :info).to_s
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
|
61
|
+
if title.empty?
|
62
|
+
say color('Пожалуйста, укажите что-нибудь для заголовка pull request, например номер вашей задачи вот так:', :error).to_s
|
63
|
+
say color('=> git request publish "PC-001"', :info).to_s
|
64
|
+
exit
|
65
|
+
end
|
66
|
+
|
67
|
+
# Проверим, что у нас указан апи юзер
|
68
|
+
if api_user.empty?
|
69
|
+
say color('Необходимо указать своего пользователя API github', :error).to_s
|
70
|
+
say color('=> https://github.com/Strech/abak-flow/blob/master/README.md', :info).to_s
|
71
|
+
exit
|
72
|
+
end
|
73
|
+
|
74
|
+
# Проверим, что у нас указан токен
|
75
|
+
if api_token.empty?
|
76
|
+
say color('Необходимо указать токен своего пользователя API github', :error).to_s
|
77
|
+
say color('=> https://github.com/Strech/abak-flow/blob/master/README.md', :info).to_s
|
78
|
+
exit
|
79
|
+
end
|
80
|
+
|
81
|
+
upstream_project = repository.remote_by_name('upstream').project
|
82
|
+
|
83
|
+
# Расставим ветки согласно правилам
|
84
|
+
head = "#{repository.repo_owner}:#{current_branch}"
|
85
|
+
base = "#{repository.remote_by_name('upstream').project.owner}:#{request_rules.fetch(remote_branch.to_sym, '')}"
|
86
|
+
|
87
|
+
head = options.head unless options.head.nil?
|
88
|
+
base = options.base unless options.base.nil?
|
89
|
+
|
90
|
+
# Запушим текущую ветку на origin
|
91
|
+
# TODO Может быть лучше достать дерективу конфига origin?
|
92
|
+
say "=> Обновляю ветку #{current_branch} на origin"
|
93
|
+
Hub::Runner.execute('push', 'origin', current_branch)
|
94
|
+
|
95
|
+
# Запостим pull request на upstream
|
96
|
+
body = tracker_url + task if task =~ /^\w+\-\d{1,}$/
|
97
|
+
body ||= 'Я забыл какая это задача :('
|
98
|
+
|
99
|
+
say '=> Делаю pull request на upstream'
|
100
|
+
result = api_client.create_pull_request("#{upstream_project.owner}/#{upstream_project.name}", base, head, title, body)
|
101
|
+
say result._links.self.href
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
command :update do |c|
|
106
|
+
c.syntax = 'git request update'
|
107
|
+
c.description = 'Обновить ветку на удаленном (origin) репозитории'
|
108
|
+
|
109
|
+
c.option '--branch STRING', String, 'Имя ветки, которую нужно обновить'
|
110
|
+
|
111
|
+
c.action do |args, options|
|
112
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
113
|
+
|
114
|
+
repository = Hub::Commands.send :local_repo
|
115
|
+
current_branch = repository.current_branch.short_name
|
116
|
+
|
117
|
+
# Проверим, что у нас настроен origin
|
118
|
+
if repository.remote_by_name('origin').nil?
|
119
|
+
say color('Необходимо настроить репозиторий origin (форк) для текущего пользователя', :error).to_s
|
120
|
+
say color('=> git remote add origin https://Developer@github.com/abak-press/sample.git', :info).to_s
|
121
|
+
exit
|
122
|
+
end
|
123
|
+
|
124
|
+
# Запушим текущую ветку на origin
|
125
|
+
branch = options.branch || current_branch
|
126
|
+
say "=> Обновляю ветку #{branch} на origin"
|
127
|
+
Hub::Runner.execute('push', 'origin', branch)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
command :feature do |c|
|
132
|
+
c.syntax = 'git request feature <Название задачи>'
|
133
|
+
c.description = 'Создать ветку для выполнения задачи. Лучше всего, если название задачи, будет ее номером из jira'
|
134
|
+
|
135
|
+
c.action do |args, options|
|
136
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
137
|
+
|
138
|
+
task = args.shift.to_s
|
139
|
+
|
140
|
+
if task.empty?
|
141
|
+
say color('Необходимо указать имя задачи, а лучше всего ее номер из jira', :error).to_s
|
142
|
+
exit
|
143
|
+
end
|
144
|
+
|
145
|
+
unless task =~ /^\w+\-\d{1,}$/
|
146
|
+
say '=> Вы приняли верное решение :)' && exit if agree("Лучше всего завести задачу с именем примерно такого формата PC-001, может попробуем заново? [y/n]:")
|
147
|
+
end
|
148
|
+
|
149
|
+
Hub::Runner.execute('flow', 'feature', 'start', task)
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
command :hotfix do |c|
|
154
|
+
c.syntax = 'git request hotfix <Название задачи>'
|
155
|
+
c.description = 'Создать ветку для выполнения bugfix задачи. Лучше всего, если название задачи, будет ее номером из jira'
|
156
|
+
|
157
|
+
c.action do |args, options|
|
158
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
159
|
+
|
160
|
+
task = args.shift.to_s
|
161
|
+
|
162
|
+
if task.empty?
|
163
|
+
say color('Необходимо указать имя задачи, а лучше всего ее номер из jira', :error).to_s
|
164
|
+
exit
|
165
|
+
end
|
166
|
+
|
167
|
+
unless task =~ /^\w+\-\d{1,}$/
|
168
|
+
say '=> Вы приняли верное решение :)' && exit if agree("Лучше всего завести задачу с именем примерно такого формата PC-001, может попробуем заново? [y/n]:")
|
169
|
+
end
|
170
|
+
|
171
|
+
Hub::Runner.execute('flow', 'hotfix', 'start', task)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
command :done do |c|
|
176
|
+
c.syntax = 'git request done'
|
177
|
+
c.description = 'Завершить pull request. По умолчанию удаляются ветки как локальная (local), так и удаленная (origin)'
|
178
|
+
|
179
|
+
c.option '--branch STRING', String, 'Имя ветки pull request которой нужно закрыть'
|
180
|
+
c.option '--all', 'Удаляет ветку в локальном репозитории и в удалнном (local + origin) (по умолчанию)'
|
181
|
+
c.option '--local', 'Удаляет ветку только в локальном репозитории (local)'
|
182
|
+
c.option '--origin', 'Удаляет ветку в удаленном репозитории (origin)'
|
183
|
+
|
184
|
+
c.action do |args, options|
|
185
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
186
|
+
|
187
|
+
repository = Hub::Commands.send :local_repo
|
188
|
+
current_branch = repository.current_branch.short_name
|
189
|
+
branch = options.branch || current_branch
|
190
|
+
|
191
|
+
type = :all
|
192
|
+
if [options.local, options.origin].compact.count == 1
|
193
|
+
type = options.local ? :local : :origin
|
194
|
+
end
|
195
|
+
|
196
|
+
if [:master, :develop].include? branch.to_sym
|
197
|
+
say color('Извините, но нельзя удалить ветку develop или master', :error).to_s
|
198
|
+
exit
|
199
|
+
end
|
200
|
+
|
201
|
+
warning = "Внимание! Alarm! Danger! Achtung\nЕсли вы удалите ветку на удаленном репозитории, а ваш pull request еще не приняли, вы рискуете потерять проделанную работу.\nВы уверены, что хотите продолжить?"
|
202
|
+
if [:all, :origin].include?(type)
|
203
|
+
say '=> Вы приняли верное решение :)' && exit unless agree("#{warning} [y/n]:")
|
204
|
+
end
|
205
|
+
|
206
|
+
# @TODO Проверку на наличие ветки на origin
|
207
|
+
if [:all, :origin].include? type
|
208
|
+
say "=> Удаляю ветку #{branch} на origin"
|
209
|
+
Hub::Runner.execute('push', repository.main_project.remote.name, ':' + branch)
|
210
|
+
end
|
211
|
+
|
212
|
+
if [:all, :local].include? type
|
213
|
+
remote_branch, task = current_branch.split('/').push(nil).map(&:to_s)
|
214
|
+
|
215
|
+
say "=> Удаляю локальную ветку #{branch}"
|
216
|
+
Hub::Runner.execute('checkout', 'develop')
|
217
|
+
Hub::Runner.execute('branch', '-D', branch)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# TODO Отрефакторить эту какашку
|
223
|
+
command :readycheck do |c|
|
224
|
+
c.syntax = 'git request readycheck'
|
225
|
+
c.description = 'Проверить все ли настроено для работы с github и удаленным (origin) репозиторием'
|
226
|
+
|
227
|
+
c.action do |args, options|
|
228
|
+
HighLine.color_scheme = HighLine::SampleColorScheme.new
|
229
|
+
repository = Hub::Commands.send :local_repo
|
230
|
+
current_branch = repository.current_branch.short_name
|
231
|
+
|
232
|
+
api_user = Hub::Commands.send(:git_reader).read_config('abak.apiuser').to_s
|
233
|
+
api_token = Hub::Commands.send(:git_reader).read_config('abak.apitoken').to_s
|
234
|
+
config_proxy = Hub::Commands.send(:git_reader).read_config('abak.proxy')
|
235
|
+
env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
236
|
+
|
237
|
+
errors = []
|
238
|
+
|
239
|
+
# Проверим, что у нас настроен origin
|
240
|
+
if repository.remote_by_name('origin').nil?
|
241
|
+
errors << [
|
242
|
+
'Необходимо настроить репозиторий origin (форк) для текущего пользователя',
|
243
|
+
'=> git remote add origin https://Developer@github.com/abak-press/sample.git'
|
244
|
+
]
|
245
|
+
end
|
246
|
+
|
247
|
+
# Проверим, что у нас настроен upstream
|
248
|
+
if repository.remote_by_name('upstream').nil?
|
249
|
+
errors << [
|
250
|
+
'Необходимо настроить репозиторий upstream (главный) для текущего пользователя',
|
251
|
+
'=> git remote add upstream https://Developer@github.com/abak-press/sample.git'
|
252
|
+
]
|
253
|
+
end
|
254
|
+
|
255
|
+
# Проверим, что у нас указан апи юзер
|
256
|
+
if api_user.empty?
|
257
|
+
errors << [
|
258
|
+
'Необходимо указать своего пользователя API github',
|
259
|
+
'=> https://github.com/Strech/abak-flow/blob/master/README.md'
|
260
|
+
]
|
261
|
+
end
|
262
|
+
|
263
|
+
# Проверим, что у нас указан токен
|
264
|
+
if api_token.empty?
|
265
|
+
errors << [
|
266
|
+
'Необходимо указать токен своего пользователя API github',
|
267
|
+
'=> https://github.com/Strech/abak-flow/blob/master/README.md'
|
268
|
+
]
|
269
|
+
end
|
270
|
+
|
271
|
+
if config_proxy || env_proxy
|
272
|
+
message = "== В качестве прокси будет установлено значение #{config_proxy || env_proxy} =="
|
273
|
+
say color('=' * message.length, :info).to_s
|
274
|
+
say color(message, :info).to_s
|
275
|
+
say color('=' * message.length + "\n", :info).to_s
|
276
|
+
end
|
277
|
+
|
278
|
+
errors.each do |error|
|
279
|
+
say "#{color(error.first, :error)}\n#{color(error.last, :info)}"
|
280
|
+
end
|
281
|
+
|
282
|
+
say color('Хм ... кажется у вас все готово к работе', :debug).to_s if errors.count.zero?
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
data/lib/abak-flow.rb
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geometrialab-abak-flow
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 3
|
9
|
+
version: 0.2.3
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Strech (aka Sergey Fedorov)
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2012-05-21 00:00:00 +04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: hub
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: commander
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id002
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: octokit
|
46
|
+
prerelease: false
|
47
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
type: :runtime
|
55
|
+
version_requirements: *id003
|
56
|
+
description: !binary |
|
57
|
+
0J/RgNC+0YHRgtC+0Lkg0L3QsNCx0L7RgCDQv9GA0LDQstC40Lsg0Lgg0LrQ
|
58
|
+
vtC80LzQsNC90LQsINC30LDRgtC+0YfQtdC90YvRhSDQtNC70Y8g0YDQsNCx
|
59
|
+
0L7RgtGLINCyIGdpdC1mbG93INGBINC40YHQv9C+0LvRjNC30L7QstCw0L3Q
|
60
|
+
uNC1INCyINC60LDRh9C10YHRgtCy0LUg0YPQtNCw0LvQtdC90L3QvtCz0L4g
|
61
|
+
0YDQtdC/0L7Qt9C40YLQvtGA0LjRjyBnaXRodWI=
|
62
|
+
|
63
|
+
email:
|
64
|
+
- oni.strech@gmail.com
|
65
|
+
executables:
|
66
|
+
- request
|
67
|
+
extensions: []
|
68
|
+
|
69
|
+
extra_rdoc_files: []
|
70
|
+
|
71
|
+
files:
|
72
|
+
- .gitignore
|
73
|
+
- Gemfile
|
74
|
+
- README.md
|
75
|
+
- Rakefile
|
76
|
+
- VERSION
|
77
|
+
- bin/request
|
78
|
+
- geometrialab-abak-flow.gemspec
|
79
|
+
- lib/abak-flow.rb
|
80
|
+
- lib/abak-flow/hub_extensions.rb
|
81
|
+
- lib/abak-flow/request.rb
|
82
|
+
- lib/abak-flow/version.rb
|
83
|
+
has_rdoc: true
|
84
|
+
homepage: https://github.com/Strech/abak-flow
|
85
|
+
licenses: []
|
86
|
+
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
segments:
|
97
|
+
- 0
|
98
|
+
version: "0"
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.3.6
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: !binary |
|
113
|
+
0KHQvtCy0LzQtdGJ0LXQvdC40LUgMi3RhSDQv9C+0LTRhdC+0LTQvtCyINGA
|
114
|
+
0LDQt9GA0LDQsdC+0YLQutC4IEdpdC1mbG93ICYgR2l0aHViLWZsb3c=
|
115
|
+
|
116
|
+
test_files: []
|
117
|
+
|