abak-flow 0.3.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +15 -0
- data/.gitignore +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +10 -1
- data/README.md +13 -30
- data/Rakefile +25 -0
- data/VERSION +1 -1
- data/abak-flow.gemspec +23 -19
- data/bin/request +1 -2
- data/lib/abak-flow/branch.rb +108 -0
- data/lib/abak-flow/branches.rb +68 -0
- data/lib/abak-flow/configuration.rb +67 -0
- data/lib/abak-flow/locales/en.yml +32 -0
- data/lib/abak-flow/locales/ru.yml +32 -0
- data/lib/abak-flow/manager.rb +35 -0
- data/lib/abak-flow/messages.rb +86 -0
- data/lib/abak-flow/pull_request.rb +39 -199
- data/lib/abak-flow/repository.rb +71 -0
- data/lib/abak-flow/request.rb +88 -198
- data/lib/abak-flow/version.rb +1 -1
- data/lib/abak-flow/visitor.rb +43 -0
- data/lib/abak-flow.rb +20 -13
- data/spec/abak-flow/branch_spec.rb +55 -0
- data/spec/abak-flow/branches_spec.rb +20 -0
- data/spec/abak-flow/configuration_spec.rb +73 -0
- data/spec/abak-flow/git_spec.rb +12 -0
- data/spec/abak-flow/github_client_spec.rb +15 -0
- data/spec/abak-flow/messages_spec.rb +146 -0
- data/spec/abak-flow/project_spec.rb +52 -0
- data/spec/abak-flow/pull_request_spec.rb +353 -0
- data/spec/abak-flow/system_spec.rb +97 -0
- data/spec/spec_helper.rb +17 -0
- metadata +82 -31
- data/lib/abak-flow/config.rb +0 -20
- data/lib/abak-flow/extensions.rb +0 -125
- data/lib/abak-flow/github_client.rb +0 -13
@@ -1,221 +1,61 @@
|
|
1
|
-
#
|
1
|
+
# coding: utf-8
|
2
|
+
require "ruler"
|
3
|
+
|
2
4
|
module Abak::Flow
|
3
5
|
class PullRequest
|
4
|
-
|
5
|
-
|
6
|
-
attr_reader :repository, :request_params
|
7
|
-
attr_reader :config, :validator
|
6
|
+
include Ruler
|
8
7
|
|
9
|
-
|
10
|
-
strategy = options.delete(:strategy) || :publish
|
8
|
+
attr_reader :errors, :link
|
11
9
|
|
12
|
-
|
13
|
-
@
|
14
|
-
@
|
10
|
+
def initialize(params, manager)
|
11
|
+
@manager = manager
|
12
|
+
@errors = []
|
15
13
|
|
16
|
-
@
|
14
|
+
@head = params.fetch(:head)
|
15
|
+
@base = params.fetch(:base)
|
16
|
+
@title = params.fetch(:title)
|
17
|
+
@body = params.fetch(:body)
|
17
18
|
end
|
18
19
|
|
19
|
-
|
20
|
-
|
20
|
+
def ready?
|
21
|
+
@errors = []
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@branch_prefix ||= current_branch.include?('/') ? current_branch.split('/').first : ''
|
28
|
-
end
|
23
|
+
multi_ruleset do
|
24
|
+
fact(:head_is_incorrect) { not @head.valid? }
|
25
|
+
fact(:base_is_incorrect) { not @base.valid? }
|
26
|
+
fact(:title_is_incorrect) { @title.empty? }
|
27
|
+
fact(:body_is_incorrect) { @body.empty? }
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
def from_repo
|
35
|
-
@from_repo ||= begin
|
36
|
-
upstream_project = repository.remote_by_name('upstream').project
|
37
|
-
"#{upstream_project.owner}/#{upstream_project.name}"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
alias_method :upstream_project, :from_repo
|
41
|
-
|
42
|
-
def origin_project
|
43
|
-
@origin_project ||= begin
|
44
|
-
origin_project = repository.remote_by_name('origin').project
|
45
|
-
"#{origin_project.owner}/#{origin_project.name}"
|
29
|
+
rule([:head_is_incorrect]) { @errors << I18n.t("pull_request.errors.head_is_incorrect") }
|
30
|
+
rule([:base_is_incorrect]) { @errors << I18n.t("pull_request.errors.base_is_incorrect") }
|
31
|
+
rule([:title_is_incorrect]) { @errors << I18n.t("pull_request.errors.title_is_incorrect") }
|
32
|
+
rule([:body_is_incorrect]) { @errors << I18n.t("pull_request.errors.body_is_incorrect") }
|
46
33
|
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def origin_repo
|
50
|
-
@origin_repo ||= repository.main_project.remote.name
|
51
|
-
end
|
52
|
-
|
53
|
-
def base
|
54
|
-
exit unless validator.valid?
|
55
|
-
|
56
|
-
branch = Abak::Flow::PullRequest.branch_by_prefix(branch_prefix)
|
57
34
|
|
58
|
-
|
35
|
+
@errors.empty? ? true : false
|
59
36
|
end
|
60
37
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
request_params.head || "#{repository.repo_owner}:#{current_branch}"
|
65
|
-
end
|
66
|
-
|
67
|
-
def title
|
68
|
-
exit unless validator.valid?
|
69
|
-
|
70
|
-
request_params.title
|
71
|
-
end
|
72
|
-
|
73
|
-
def body
|
74
|
-
exit unless validator.valid?
|
75
|
-
|
76
|
-
request_params.body
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.branch_by_prefix(prefix)
|
80
|
-
{:feature => :develop, :hotfix => :master}.fetch(prefix.to_sym, '')
|
81
|
-
end
|
82
|
-
|
83
|
-
# TODO Вынести
|
84
|
-
class Validator
|
85
|
-
attr_reader :strategy, :target_object
|
86
|
-
attr_reader :errors, :executed
|
87
|
-
|
88
|
-
def initialize(strategy_name, target_object)
|
89
|
-
@strategy = Abak::Flow::PullRequest.const_get("Strategy#{strategy_name.capitalize}".to_sym)
|
90
|
-
@target_object = target_object
|
91
|
-
@errors = []
|
92
|
-
end
|
93
|
-
|
94
|
-
def valid?
|
95
|
-
return errors.empty? if executed
|
96
|
-
|
97
|
-
validate!
|
98
|
-
errors.empty?
|
99
|
-
end
|
100
|
-
|
101
|
-
protected
|
102
|
-
def validate!
|
103
|
-
@executed = true
|
104
|
-
|
105
|
-
strategy.attributes.each do |attribute|
|
106
|
-
send("validate_#{attribute}")
|
107
|
-
end
|
108
|
-
|
109
|
-
print_errors
|
110
|
-
end
|
111
|
-
|
112
|
-
def print_errors
|
113
|
-
errors.each do |error|
|
114
|
-
say color(error[:message], :error).to_s
|
115
|
-
say color(error[:tip], :info).to_s
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def validate_api_user
|
120
|
-
return if target_object.config.api_user?
|
121
|
-
|
122
|
-
@errors << {
|
123
|
-
:message => 'Необходимо указать своего пользователя API github',
|
124
|
-
:tip => '=> https://github.com/Strech/abak-flow/blob/master/README.md'
|
125
|
-
}
|
126
|
-
end
|
127
|
-
|
128
|
-
def validate_api_token
|
129
|
-
return if target_object.config.api_token?
|
130
|
-
|
131
|
-
@errors << {
|
132
|
-
:message => 'Необходимо указать токен своего пользователя API github',
|
133
|
-
:tip => '=> https://github.com/Strech/abak-flow/blob/master/README.md'
|
134
|
-
}
|
135
|
-
end
|
136
|
-
|
137
|
-
def validate_origin
|
138
|
-
return unless target_object.repository.remote_by_name('origin').nil?
|
139
|
-
|
140
|
-
@errors << {
|
141
|
-
:message => 'Необходимо настроить репозиторий origin (форк) для текущего пользователя',
|
142
|
-
:tip => '=> git remote add origin https://Developer@github.com/abak-press/sample.git'
|
143
|
-
}
|
144
|
-
end
|
145
|
-
|
146
|
-
def validate_upstream
|
147
|
-
return unless target_object.repository.remote_by_name('upstream').nil?
|
148
|
-
|
149
|
-
@errors << {
|
150
|
-
:message => 'Необходимо настроить репозиторий upstream (главный) для текущего пользователя',
|
151
|
-
:tip => '=> git remote add upstream https://Developer@github.com/abak-press/sample.git'
|
152
|
-
}
|
153
|
-
end
|
154
|
-
|
155
|
-
def validate_title
|
156
|
-
return unless target_object.request_params.title.empty?
|
157
|
-
|
158
|
-
@errors << {
|
159
|
-
:message => 'Пожалуйста, укажите что-нибудь для заголовка pull request, например номер вашей задачи вот так:',
|
160
|
-
:tip => '=> git request publish "PC-001"'
|
161
|
-
}
|
162
|
-
end
|
163
|
-
|
164
|
-
def validate_branch
|
165
|
-
return if [:master, :develop].include?(target_object.current_branch.to_sym)
|
166
|
-
|
167
|
-
@errors << {
|
168
|
-
:message => 'Нельзя делать pull request из меток master или develop, попробуйде переключиться, например так:',
|
169
|
-
:tip => '=> git checkout master'
|
170
|
-
}
|
171
|
-
end
|
172
|
-
|
173
|
-
def validate_deleted_branch
|
174
|
-
return unless [:master, :develop].include?(target_object.current_branch.to_sym)
|
175
|
-
|
176
|
-
@errors << {
|
177
|
-
:message => 'Извините, но нельзя удалить ветку develop или master',
|
178
|
-
:tip => '=> git checkout feature/TASK-0001'
|
179
|
-
}
|
180
|
-
end
|
38
|
+
def display_name
|
39
|
+
I18n.t("pull_request.name")
|
181
40
|
end
|
182
41
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
end
|
187
|
-
end
|
42
|
+
def publish
|
43
|
+
begin
|
44
|
+
head_with_repo = [@manager.repository.origin.owner, @head] * ':'
|
188
45
|
|
189
|
-
|
190
|
-
|
191
|
-
StrategyReadycheck.attributes | [:title, :branch]
|
192
|
-
end
|
193
|
-
end
|
46
|
+
response = @manager.github.create_pull_request(
|
47
|
+
@manager.repository.upstream.to_s, @base.to_s, head_with_repo, @title, @body)
|
194
48
|
|
195
|
-
|
196
|
-
def self.attributes
|
197
|
-
StrategyReadycheck.attributes | [:title]
|
198
|
-
end
|
199
|
-
end
|
49
|
+
@link = response._links.html.href
|
200
50
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
end
|
205
|
-
end
|
51
|
+
true
|
52
|
+
rescue Exception => exception
|
53
|
+
backtrace = exception.backtrace[0...10] * "\n"
|
206
54
|
|
207
|
-
|
208
|
-
def self.attributes
|
209
|
-
StrategyReadycheck.attributes | [:deleted_branch]
|
210
|
-
end
|
211
|
-
end
|
55
|
+
@errors = ["#{exception.message}\n\n#{backtrace}"]
|
212
56
|
|
213
|
-
|
214
|
-
def self.attributes
|
215
|
-
[:origin, :upstream, :api_user, :api_token]
|
57
|
+
false
|
216
58
|
end
|
217
59
|
end
|
218
|
-
|
219
|
-
|
220
|
-
end
|
221
|
-
end
|
60
|
+
end # class PullRequest
|
61
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require "i18n"
|
3
|
+
require "ruler"
|
4
|
+
require "forwardable"
|
5
|
+
|
6
|
+
module Abak::Flow
|
7
|
+
class Repository
|
8
|
+
include Ruler
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
REMOTES = [:origin, :upstream].freeze
|
12
|
+
|
13
|
+
def_delegators :@manager, :git
|
14
|
+
|
15
|
+
attr_reader :errors
|
16
|
+
|
17
|
+
def initialize(manager)
|
18
|
+
@manager = manager
|
19
|
+
@errors = []
|
20
|
+
|
21
|
+
configure!
|
22
|
+
end
|
23
|
+
|
24
|
+
def ready?
|
25
|
+
@errors = []
|
26
|
+
|
27
|
+
multi_ruleset do
|
28
|
+
fact(:origin_not_setup) { origin.nil? }
|
29
|
+
fact(:upstream_not_setup) { upstream.nil? }
|
30
|
+
|
31
|
+
rule([:origin_not_setup]) { @errors << I18n.t("repository.errors.origin_not_setup") }
|
32
|
+
rule([:upstream_not_setup]) { @errors << I18n.t("repository.errors.upstream_not_setup") }
|
33
|
+
end
|
34
|
+
|
35
|
+
@errors.empty? ? true : false
|
36
|
+
end
|
37
|
+
|
38
|
+
def display_name
|
39
|
+
I18n.t("repository.name")
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def configure!
|
44
|
+
remotes = Hash[fetch_remotes_from_git]
|
45
|
+
REMOTES.each do |name|
|
46
|
+
define_singleton_method(name) { remotes[name] }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def fetch_remotes_from_git
|
51
|
+
git.remotes.
|
52
|
+
select { |remote| REMOTES.include?(remote.name.to_sym) }.
|
53
|
+
map { |remote| create_remote(remote) }.
|
54
|
+
compact
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_remote(remote)
|
58
|
+
matches = /.+.github\.com[\:|\/](?<owner>.+)\/(?<project>.+).git/.match(remote.url)
|
59
|
+
|
60
|
+
if !matches.nil? && matches.captures.length == 2
|
61
|
+
[remote.name.to_sym, Remote.new(matches[:owner], matches[:project], remote)]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Remote < Struct.new(:owner, :project, :repo)
|
66
|
+
def to_s
|
67
|
+
"#{owner}/#{project}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/abak-flow/request.rb
CHANGED
@@ -1,234 +1,124 @@
|
|
1
|
-
#
|
1
|
+
# coding: utf-8
|
2
|
+
require "commander/import"
|
3
|
+
require "ansi/code"
|
4
|
+
|
2
5
|
module Abak::Flow
|
3
|
-
program :name,
|
6
|
+
program :name, "Утилита для оформления pull request на github.com"
|
4
7
|
program :version, Abak::Flow::VERSION
|
5
|
-
program :description,
|
8
|
+
program :description, "Утилита, заточенная под git-flow но с использованием github.com"
|
6
9
|
|
7
10
|
default_command :help
|
8
|
-
command :publish do |c|
|
9
|
-
c.syntax = 'git request publish <Заголовок>'
|
10
|
-
c.description = 'Оформить pull request из текущей ветки (feature -> develop, hotfix -> master)'
|
11
11
|
|
12
|
-
|
13
|
-
c.
|
14
|
-
c.
|
12
|
+
command :checkup do |c|
|
13
|
+
c.syntax = "git request checkup"
|
14
|
+
c.description = "Проверить все ли настроено для работы с github и удаленными репозиториями"
|
15
15
|
|
16
16
|
c.action do |args, options|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
if request.default_task =~ /^\w+\-\d{1,}$/
|
27
|
-
title = request.default_task if title.empty?
|
28
|
-
body = jira_browse_url + request.default_task
|
29
|
-
end
|
30
|
-
|
31
|
-
request.title = title
|
32
|
-
request.body = body
|
33
|
-
|
34
|
-
exit unless request.valid?
|
35
|
-
|
36
|
-
# Запушим текущую ветку на origin
|
37
|
-
say "=> Обновляю ветку #{request.current_branch} на origin"
|
38
|
-
Hub::Runner.execute('push', 'origin', request.current_branch)
|
39
|
-
|
40
|
-
# Запостим pull request на upstream
|
41
|
-
say '=> Делаю pull request на upstream'
|
42
|
-
begin
|
43
|
-
result = github_client.create_pull_request(request.from_repo, request.base, request.head, request.title, request.body)
|
44
|
-
say color(result._links.html.href, :green).to_s
|
45
|
-
rescue => e
|
46
|
-
say color(e.message, :error).to_s
|
47
|
-
say "\nПроблемы? Попробуйте заглянуть сюда:"
|
48
|
-
say color('=> cписок кодов статуса ответа http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html', :info).to_s
|
17
|
+
m = Manager.new
|
18
|
+
v = Visitor.new(m.configuration, m.repository, call: :ready?, look_for: :errors)
|
19
|
+
|
20
|
+
if v.ready?
|
21
|
+
say ANSI.green { I18n.t("commands.checkup.success") }
|
22
|
+
else
|
23
|
+
say ANSI.red { I18n.t("commands.checkup.fail") }
|
24
|
+
say ANSI.yellow { v.output }
|
49
25
|
end
|
50
26
|
end
|
51
|
-
end
|
52
|
-
|
53
|
-
command :update do |c|
|
54
|
-
c.syntax = 'git request update'
|
55
|
-
c.description = 'Обновить ветку на удаленном (origin) репозитории'
|
56
|
-
|
57
|
-
c.option '--branch STRING', String, 'Имя ветки, которую нужно обновить'
|
58
|
-
|
59
|
-
c.action do |args, options|
|
60
|
-
config = Abak::Flow::Config.current
|
61
|
-
request = Abak::Flow::PullRequest.new(config, :strategy => :update)
|
62
|
-
|
63
|
-
exit unless request.valid?
|
64
|
-
|
65
|
-
# Запушим текущую ветку на origin
|
66
|
-
branch = options.branch || request.current_branch
|
67
|
-
say "=> Обновляю ветку #{branch} на origin"
|
68
|
-
Hub::Runner.execute('push', 'origin', branch)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
command :feature do |c|
|
73
|
-
c.syntax = 'git request feature <Название задачи>'
|
74
|
-
c.description = 'Создать ветку для выполнения задачи. Лучше всего, если название задачи, будет ее номером из jira'
|
27
|
+
end # command :checkup
|
75
28
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
task = args.shift.to_s
|
29
|
+
command :compare do |c|
|
30
|
+
c.syntax = "git request compare"
|
31
|
+
c.description = "Сравнить свою ветку с веткой upstream репозитория"
|
80
32
|
|
81
|
-
|
82
|
-
|
83
|
-
exit
|
84
|
-
end
|
85
|
-
|
86
|
-
unless task =~ /^\w+\-\d{1,}$/
|
87
|
-
say '=> Вы приняли верное решение :)' && exit if agree("Лучше всего завести задачу с именем примерно такого формата PC-001, может попробуем заново? [y/n]:")
|
88
|
-
end
|
89
|
-
|
90
|
-
Hub::Runner.execute('flow', 'feature', 'start', task)
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
command :hotfix do |c|
|
95
|
-
c.syntax = 'git request hotfix <Название задачи>'
|
96
|
-
c.description = 'Создать ветку для выполнения bugfix задачи. Лучше всего, если название задачи, будет ее номером из jira'
|
33
|
+
c.option "--base STRING", String, "Имя ветки с которой нужно сравнить"
|
34
|
+
c.option "--head STRING", String, "Имя ветки которую нужно сравнить"
|
97
35
|
|
98
36
|
c.action do |args, options|
|
99
|
-
|
37
|
+
# TODO : Вот это дубль, хочется его как-то более красиво
|
38
|
+
m = Manager.new
|
39
|
+
v = Visitor.new(m.configuration, m.repository, call: :ready?, look_for: :errors)
|
100
40
|
|
101
|
-
|
41
|
+
unless v.ready?
|
42
|
+
say ANSI.red { I18n.t("commands.compare.fail") }
|
43
|
+
say ANSI.yellow { v.output }
|
102
44
|
|
103
|
-
|
104
|
-
say color('Необходимо указать имя задачи, а лучше всего ее номер из jira', :error).to_s
|
105
|
-
exit
|
45
|
+
exit 1
|
106
46
|
end
|
107
47
|
|
108
|
-
|
109
|
-
|
48
|
+
current = m.git.current_branch
|
49
|
+
head = Branch.new(options.head || current, m)
|
50
|
+
base = Branch.new(options.base || head.pick_up_base_name, m)
|
51
|
+
|
52
|
+
if head.current?
|
53
|
+
say ANSI.white {
|
54
|
+
I18n.t("commands.compare.updating",
|
55
|
+
branch: ANSI.bold { head },
|
56
|
+
upstream: ANSI.bold { "#{m.repository.origin}" }) }
|
57
|
+
|
58
|
+
head.update
|
59
|
+
else
|
60
|
+
say ANSI.yellow {
|
61
|
+
I18n.t("commands.compare.diverging",
|
62
|
+
branch: ANSI.bold { head }) }
|
110
63
|
end
|
111
64
|
|
112
|
-
|
65
|
+
say ANSI.green { head.compare_link(base) }
|
113
66
|
end
|
114
|
-
end
|
67
|
+
end # command :compare
|
115
68
|
|
116
|
-
command :
|
117
|
-
c.syntax =
|
118
|
-
c.description =
|
69
|
+
command :publish do |c|
|
70
|
+
c.syntax = "git request publish"
|
71
|
+
c.description = "Оформить pull request в upstream репозиторий"
|
119
72
|
|
120
|
-
c.option
|
121
|
-
c.option
|
122
|
-
c.option
|
123
|
-
c.option '--origin', 'Удаляет ветку в удаленном репозитории (origin)'
|
73
|
+
c.option "--title STRING", String, "Заголовок для вашего pull request"
|
74
|
+
c.option "--body STRING", String, "Текст для вашего pull request"
|
75
|
+
c.option "--base STRING", String, "Имя ветки, в которую нужно принять изменения"
|
124
76
|
|
125
77
|
c.action do |args, options|
|
126
|
-
|
127
|
-
request = Abak::Flow::PullRequest.new(config, :strategy => :done)
|
128
|
-
branch = options.branch || request.current_branch
|
78
|
+
m = Manager.new
|
129
79
|
|
130
|
-
|
80
|
+
head = Branch.new(m.git.current_branch, m)
|
81
|
+
base = Branch.new(options.base || head.pick_up_base_name, m)
|
131
82
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
83
|
+
title = options.title || head.pick_up_title
|
84
|
+
body = [
|
85
|
+
options.body || (head.mappable? ? nil : I18n.t("commands.publish.nothing")),
|
86
|
+
head.pick_up_body
|
87
|
+
].compact * "\n\n"
|
136
88
|
|
137
|
-
|
138
|
-
|
139
|
-
if [:all, :origin].include?(type)
|
140
|
-
say '=> Вы приняли верное решение :)' && exit unless agree("#{warning} [y/n]:")
|
141
|
-
end
|
89
|
+
p = PullRequest.new({base: base, head: head, title: title, body: body}, m)
|
90
|
+
v = Visitor.new(m.configuration, m.repository, p, call: :ready?, look_for: :errors)
|
142
91
|
|
143
|
-
|
144
|
-
|
145
|
-
say
|
146
|
-
Hub::Runner.execute('push', request.origin_repo, ':' + branch)
|
147
|
-
end
|
92
|
+
unless v.ready?
|
93
|
+
say ANSI.red { I18n.t("commands.publish.fail") }
|
94
|
+
say ANSI.yellow { v.output }
|
148
95
|
|
149
|
-
|
150
|
-
say "=> Удаляю локальную ветку #{branch}"
|
151
|
-
Hub::Runner.execute('checkout', 'develop')
|
152
|
-
Hub::Runner.execute('branch', '-D', branch)
|
96
|
+
exit 1
|
153
97
|
end
|
154
|
-
end
|
155
|
-
end
|
156
98
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
99
|
+
say ANSI.white {
|
100
|
+
I18n.t("commands.publish.updating",
|
101
|
+
branch: ANSI.bold { head },
|
102
|
+
upstream: ANSI.bold { "#{m.repository.origin}" }) }
|
161
103
|
|
162
|
-
|
163
|
-
config = Abak::Flow::Config.current
|
164
|
-
request = Abak::Flow::PullRequest.new(config, :strategy => :readycheck)
|
165
|
-
|
166
|
-
if config.proxy?
|
167
|
-
message = "== В качестве прокси будет установлено значение #{config.proxy} =="
|
168
|
-
say color('=' * message.length, :info).to_s
|
169
|
-
say color(message, :info).to_s
|
170
|
-
say color('=' * message.length + "\n", :info).to_s
|
171
|
-
end
|
104
|
+
head.update
|
172
105
|
|
173
|
-
say
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
command :garbage do |c|
|
178
|
-
c.syntax = 'git request status'
|
179
|
-
c.description = 'Проверить пригодность удаленных (origin) веток и возможность их уничтожения (ветки master, develop игнорируются)'
|
106
|
+
say ANSI.white {
|
107
|
+
I18n.t("commands.publish.requesting",
|
108
|
+
branch: ANSI.bold { "#{m.repository.origin.owner}:#{head}" },
|
109
|
+
upstream: ANSI.bold { "#{m.repository.upstream.owner}:#{base}" }) }
|
180
110
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
say "=> Обновляю данные о репозитории upstream"
|
193
|
-
%w(origin upstream).each { |remote| Hub::Runner.execute('fetch', remote, '-p') }
|
194
|
-
|
195
|
-
say "=> Загружаю список веток для origin"
|
196
|
-
branches = github_client.branches(request.origin_project).
|
197
|
-
reject { |branch| %w(master develop).include? branch.name }
|
198
|
-
|
199
|
-
say "=> На origin найдено веток: #{branches.count}\n\n"
|
200
|
-
branches.each_with_index do |branch, index|
|
201
|
-
index += 1
|
202
|
-
|
203
|
-
base = Abak::Flow::PullRequest.branch_by_prefix branch.name.split('/').first
|
204
|
-
|
205
|
-
upstream_branch = %x(git branch -r --contain #{branch.commit.sha} | grep upstream/#{base} 2> /dev/null).strip
|
206
|
-
local_sha = %x(git show #{branch.name} --format=%H --no-notes 2> /dev/null | head -n 1).strip
|
207
|
-
|
208
|
-
statuses = {
|
209
|
-
unused: upstream_branch.empty?,
|
210
|
-
differ: !local_sha.empty? && local_sha != branch.commit.sha,
|
211
|
-
missing: local_sha.empty?
|
212
|
-
}
|
213
|
-
|
214
|
-
unless statuses.values.inject &:|
|
215
|
-
say color("#{index}) #{branch.name} → можно удалить", :debug).to_s
|
216
|
-
say "\n"
|
217
|
-
next
|
218
|
-
end
|
219
|
-
|
220
|
-
diagnoses = statuses.select { |_,bool| bool }.
|
221
|
-
map { |name,_| messages[name].first }.
|
222
|
-
map { |msg| "#{' ' * (index.to_s.length + 2)} ↪ #{msg}" }.
|
223
|
-
join("\n")
|
224
|
-
|
225
|
-
if statuses.select { |_,bool| bool }.keys == [:missing]
|
226
|
-
say color("#{index}) #{branch.name} → потенциально можно удалить", :warning).to_s
|
227
|
-
say "#{diagnoses}\n\n"
|
228
|
-
else
|
229
|
-
say "#{index}) #{branch.name}\n#{diagnoses}\n\n"
|
230
|
-
end
|
111
|
+
v = Visitor.new(p, call: :publish, look_for: :errors)
|
112
|
+
if v.ready?
|
113
|
+
say ANSI.green {
|
114
|
+
I18n.t("commands.publish.success",
|
115
|
+
link: ANSI.bold { p.link }) }
|
116
|
+
else
|
117
|
+
say ANSI.red { I18n.t("commands.publish.fail") }
|
118
|
+
say ANSI.yellow { v.output }
|
119
|
+
|
120
|
+
exit 3
|
231
121
|
end
|
232
122
|
end
|
233
|
-
end
|
234
|
-
end
|
123
|
+
end # command :publish
|
124
|
+
end
|
data/lib/abak-flow/version.rb
CHANGED