abak-flow 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .idea/
6
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'hub', '~> 1.8.1'
6
+ gem 'commander', '~> 4.0.7'
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ Abak-flow
2
+ =========
3
+ Нет, это не новая идеология ведения проекта, это всего лишь набор утилит которые помогают связать использование git-flow и github
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
+
27
+ # С чего начать?
28
+ $ git request help
29
+
30
+ # Примеры использования
31
+ *в процессе*
32
+
33
+ # В заключении
34
+ Данный репозиторий и изложенные в нем идеи ни в коем случае не претендуют на идеал и совершенство. Это всего лишь узко заточенная комбинация гемов
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/abak-flow.gemspec ADDED
@@ -0,0 +1,23 @@
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 = '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
+ end
data/bin/request ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding: utf-8 -*-
3
+ require 'abak-flow'
4
+ require "abak-flow/request"
data/lib/abak-flow.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'hub'
2
+ require 'abak-flow/hub_extensions'
3
+ require 'abak-flow/version'
4
+ require "commander/import"
@@ -0,0 +1,114 @@
1
+ module Abak::Flow
2
+ module RunnerExtension
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 CommandsExtension
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
+
112
+ Hub::Runner.send :include, RunnerExtension
113
+ Hub::Commands.send :include, CommandsExtension
114
+ end
@@ -0,0 +1,123 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Abak::Flow
3
+ # @TODO Сделать класс, в котором собрать общие куски из задач
4
+
5
+ program :name, 'Утилита для оформления pull request на github.com'
6
+ program :version, '0.0.1'
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
+ repository = Hub::Commands.send :local_repo
20
+ current_branch = repository.current_branch.short_name
21
+ request_rules = {
22
+ :feature => :develop,
23
+ :hotfix => :master
24
+ }
25
+ jira_browse_url = 'http://jira.dev.apress.ru/browse/'
26
+
27
+ # Проверим, что мы не в мастере или девелопе
28
+ if [:master, :develop].include? current_branch.to_sym
29
+ say 'Нельзя делать pull request из меток master или develop'
30
+ exit
31
+ end
32
+
33
+ # Проверим, что у нас настроен upstream
34
+ if repository.remote_by_name('upstream').nil?
35
+ say 'Необходимо настроить репозиторий upstream (главный) для текущего пользователя'
36
+ say '=> git remote add upstream https://Developer@github.com/abak-press/sample.git'
37
+ exit
38
+ end
39
+
40
+ if args.first.to_s.empty?
41
+ say 'Пожалуйста, укажите в заголовке номер вашей задачи, например так:'
42
+ say '=> git request "PC-001"'
43
+ exit
44
+ end
45
+
46
+ # Расставим ветки согласно правилам
47
+ remote_branch, task = current_branch.split('/').push(nil).map(&:to_s)
48
+ head = "#{repository.repo_owner}:#{current_branch}"
49
+ base = "#{repository.remote_by_name('upstream').project.owner}:#{request_rules.fetch(remote_branch.to_sym, '')}"
50
+
51
+ head = options.head unless options.head.nil?
52
+ base = options.base unless options.base.nil?
53
+
54
+ # Запушим текущую ветку на origin
55
+ # @TODO Может быть лучше достать дерективу конфига origin?
56
+ say "=> Обновляю ветку #{current_branch} на origin"
57
+ Hub::Runner.execute('push', repository.main_project.remote.name, current_branch)
58
+
59
+ # Запостим pull request на upstream
60
+ command_options = ['pull-request', args.first, '-b', base, '-h', head, '-d']
61
+ command_options |= ['-d', jira_browse_url + task] if task =~ /^\w+\-\d{1,}$/
62
+
63
+ say '=> Делаю pull request на upstream'
64
+ say Hub::Runner.execute(*command_options)
65
+ end
66
+ end
67
+
68
+ command :update do |c|
69
+ c.syntax = 'git request update'
70
+ c.description = 'Обновить ветку на удаленном (origin) репозитории'
71
+
72
+ c.option '--branch STRING', String, 'Имя ветки, которую нужно обновить'
73
+
74
+ c.action do |args, options|
75
+ repository = Hub::Commands.send :local_repo
76
+ current_branch = repository.current_branch.short_name
77
+
78
+ # Запушим текущую ветку на origin
79
+ branch = options.branch || current_branch
80
+ say "=> Обновляю ветку #{branch} на origin"
81
+ Hub::Runner.execute('push', repository.main_project.remote.name, branch)
82
+ end
83
+ end
84
+
85
+ command :done do |c|
86
+ c.syntax = 'git request done'
87
+ c.description = 'Завершить pull request. По умолчанию удаляются ветки как локальная (local), так и удаленная (origin)'
88
+
89
+ c.option '--branch STRING', String, 'Имя ветки pull request которой нужно закрыть'
90
+ c.option '--all', 'Удаляет ветку в локальном репозитории и в удалнном (local + origin) (по умолчанию)'
91
+ c.option '--local', 'Удаляет ветку только в локальном репозитории (local)'
92
+ c.option '--origin', 'Удаляет ветку в удаленном репозитории (origin)'
93
+
94
+ c.action do |args, options|
95
+ repository = Hub::Commands.send :local_repo
96
+ current_branch = repository.current_branch.short_name
97
+ branch = options.branch || current_branch
98
+
99
+ type = :all
100
+ if [options.local, options.origin].compact.count == 1
101
+ type = options.local ? :local : :origin
102
+ end
103
+
104
+ warning = "Внимание! Alarm! Danger! Achtung\nЕсли вы удалите ветку на удаленном репозитории, а ваш pull request еще не приняли, вы рискуете потерять проделанную работу.\nВы уверены, что хотите продолжить?"
105
+ if [:all, :origin].include?(type)
106
+ say '=> Вы приняли верное решение :)' && exit unless agree("#{warning} [yes/no/y/n]:")
107
+ end
108
+
109
+ if [:all, :origin].include? type
110
+ say "=> Удаляю ветку #{branch} на origin"
111
+ Hub::Runner.execute('push', repository.main_project.remote.name, ':' + branch)
112
+ end
113
+
114
+ if [:all, :local].include? type
115
+ remote_branch, task = current_branch.split('/').push(nil).map(&:to_s)
116
+
117
+ say "=> Удаляю локальную ветку #{branch}"
118
+ Hub::Runner.execute('checkout', 'develop')
119
+ Hub::Runner.execute('branch', '-D', branch)
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,5 @@
1
+ module Abak
2
+ module Flow
3
+ VERSION = '0.1.0'
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: abak-flow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Strech (aka Sergey Fedorov)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-04 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: hub
16
+ requirement: &70279720232900 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70279720232900
25
+ - !ruby/object:Gem::Dependency
26
+ name: commander
27
+ requirement: &70279720232480 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70279720232480
36
+ description: Простой набор правил и комманд, заточеных для работы в git-flow с использование
37
+ в качестве удаленного репозитория github
38
+ email:
39
+ - oni.strech@gmail.com
40
+ executables:
41
+ - request
42
+ extensions: []
43
+ extra_rdoc_files: []
44
+ files:
45
+ - .gitignore
46
+ - Gemfile
47
+ - README.md
48
+ - Rakefile
49
+ - VERSION
50
+ - abak-flow.gemspec
51
+ - bin/request
52
+ - lib/abak-flow.rb
53
+ - lib/abak-flow/hub_extensions.rb
54
+ - lib/abak-flow/request.rb
55
+ - lib/abak-flow/version.rb
56
+ homepage: https://github.com/Strech/abak-flow
57
+ licenses: []
58
+ post_install_message:
59
+ rdoc_options: []
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ! '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubyforge_project: abak-flow
76
+ rubygems_version: 1.8.10
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Совмещение 2-х подходов разработки Git-flow & Github-flow
80
+ test_files: []