livebuzz-gitx 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +31 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +84 -0
- data/Rakefile +5 -0
- data/bin/git-buildtag +6 -0
- data/bin/git-cleanup +7 -0
- data/bin/git-integrate +6 -0
- data/bin/git-nuke +6 -0
- data/bin/git-release +6 -0
- data/bin/git-review +6 -0
- data/bin/git-reviewrequest +8 -0
- data/bin/git-share +6 -0
- data/bin/git-start +6 -0
- data/bin/git-track +6 -0
- data/bin/git-update +6 -0
- data/lib/livebuzz/gitx/cli/base_command.rb +58 -0
- data/lib/livebuzz/gitx/cli/buildtag_command.rb +41 -0
- data/lib/livebuzz/gitx/cli/cleanup_command.rb +47 -0
- data/lib/livebuzz/gitx/cli/integrate_command.rb +95 -0
- data/lib/livebuzz/gitx/cli/nuke_command.rb +64 -0
- data/lib/livebuzz/gitx/cli/release_command.rb +41 -0
- data/lib/livebuzz/gitx/cli/review_command.rb +101 -0
- data/lib/livebuzz/gitx/cli/share_command.rb +17 -0
- data/lib/livebuzz/gitx/cli/start_command.rb +39 -0
- data/lib/livebuzz/gitx/cli/track_command.rb +16 -0
- data/lib/livebuzz/gitx/cli/update_command.rb +37 -0
- data/lib/livebuzz/gitx/configuration.rb +47 -0
- data/lib/livebuzz/gitx/extensions/string.rb +12 -0
- data/lib/livebuzz/gitx/extensions/thor.rb +39 -0
- data/lib/livebuzz/gitx/github.rb +177 -0
- data/lib/livebuzz/gitx/version.rb +5 -0
- data/lib/livebuzz/gitx.rb +10 -0
- data/livebuzz-gitx.gemspec +37 -0
- data/spec/fixtures/vcr_cassettes/pull_request_does_exist_with_failure_status.yml +135 -0
- data/spec/fixtures/vcr_cassettes/pull_request_does_exist_with_success_status.yml +149 -0
- data/spec/fixtures/vcr_cassettes/pull_request_does_not_exist.yml +133 -0
- data/spec/livebuzz/gitx/cli/base_command_spec.rb +41 -0
- data/spec/livebuzz/gitx/cli/buildtag_command_spec.rb +70 -0
- data/spec/livebuzz/gitx/cli/cleanup_command_spec.rb +37 -0
- data/spec/livebuzz/gitx/cli/integrate_command_spec.rb +272 -0
- data/spec/livebuzz/gitx/cli/nuke_command_spec.rb +165 -0
- data/spec/livebuzz/gitx/cli/release_command_spec.rb +148 -0
- data/spec/livebuzz/gitx/cli/review_command_spec.rb +307 -0
- data/spec/livebuzz/gitx/cli/share_command_spec.rb +32 -0
- data/spec/livebuzz/gitx/cli/start_command_spec.rb +96 -0
- data/spec/livebuzz/gitx/cli/track_command_spec.rb +31 -0
- data/spec/livebuzz/gitx/cli/update_command_spec.rb +79 -0
- data/spec/spec_helper.rb +86 -0
- data/spec/support/global_config.rb +24 -0
- data/spec/support/home_env.rb +11 -0
- data/spec/support/matchers/meet_expectations_matcher.rb +7 -0
- data/spec/support/pry.rb +1 -0
- data/spec/support/stub_execution.rb +14 -0
- data/spec/support/timecop.rb +9 -0
- data/spec/support/vcr.rb +6 -0
- data/spec/support/webmock.rb +1 -0
- metadata +350 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0616b6dbae3062ab6f77cd11e45b9d093347109e
|
4
|
+
data.tar.gz: 363feec0115bce1bc18baa4998c8be06e0556bcd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7d08cf9017d8b2a87190849657421a81bd86b423f31e492da77381456c17fc949e10c79715334ccbb54e2dabd11ca18960794135c633bad0650e7f7001294d8f
|
7
|
+
data.tar.gz: fcbbf1f9a923aa23e21c8b1c0691116fd3b39edd77e6d4636a8d79e2efaa9c8315900b70c3689f529c419b9cb9564ab04e300986739dd37c5e24dd68298d2ecc
|
data/.gitignore
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## GIT
|
17
|
+
*.orig
|
18
|
+
|
19
|
+
## PROJECT::GENERAL
|
20
|
+
coverage
|
21
|
+
rdoc
|
22
|
+
pkg
|
23
|
+
|
24
|
+
## bundler
|
25
|
+
Gemfile.lock
|
26
|
+
|
27
|
+
## RSpec temp files
|
28
|
+
spec/tmp
|
29
|
+
|
30
|
+
## RubyMine
|
31
|
+
/.idea/
|
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
livebuzz-gitx
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec, cmd: 'bundle exec rspec', failed_mode: :keep do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Ryan Sonnek
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# livebuzz-gitx
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/livebuzz/livebuzz-gitx.png?branch=master)](https://travis-ci.org/livebuzz/livebuzz-gitx)
|
4
|
+
[![Code Coverage](https://coveralls.io/repos/livebuzz/livebuzz-gitx/badge.png)](https://coveralls.io/r/livebuzz/livebuzz-gitx)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/livebuzz/livebuzz-gitx.png)](https://codeclimate.com/github/livebuzz/livebuzz-gitx)
|
6
|
+
|
7
|
+
Useful Git eXtensions for Development workflow at LiveBuzz.
|
8
|
+
|
9
|
+
Forked from [TheGarage-GitX](https://github.com/thegarage/thegarage-gitx), which is inspired by the [socialcast-git-extensions gem](https://github.com/socialcast/socialcast-git-extensions)
|
10
|
+
|
11
|
+
# Git Extensions for Workflow
|
12
|
+
|
13
|
+
### Options
|
14
|
+
* `--trace` or `-v` = verbose output for debugging commands
|
15
|
+
* `--pretend` or `-p` = dry run commands and do not actually invoke operations
|
16
|
+
|
17
|
+
## git start <new_branch_name (optional)>
|
18
|
+
|
19
|
+
update local repository with latest upstream changes and create a new feature branch
|
20
|
+
|
21
|
+
## git update
|
22
|
+
|
23
|
+
update the local feature branch with latest remote changes plus upstream released changes.
|
24
|
+
|
25
|
+
## git integrate <aggregate_branch_name (optional, default: staging)>
|
26
|
+
|
27
|
+
integrate the current feature branch into an aggregate branch (ex: prototype, staging)
|
28
|
+
|
29
|
+
## git review
|
30
|
+
|
31
|
+
create a pull request on github for peer review of the current branch. This command is re-runnable
|
32
|
+
in order to re-assign pull requests.
|
33
|
+
|
34
|
+
options:
|
35
|
+
* `--assign` or `-a` = assign pull request to github user
|
36
|
+
* `--open` or `-o` = open pull request in default web browser.
|
37
|
+
* `--bump` or `-b` = bump an existing pull request by posting a comment to re-review new changes
|
38
|
+
* `--approve` = approve/signoff on pull request (with optional feedback)
|
39
|
+
* `--reject` = reject pull request (with details)
|
40
|
+
|
41
|
+
NOTE: the `--bump` option will also update the pull request commit status to mark the branch as 'pending peer review'.
|
42
|
+
This setting is cleared when a reviewer approves or rejects the pull request.
|
43
|
+
|
44
|
+
## git release
|
45
|
+
|
46
|
+
release the current feature branch to master. This operation will perform the following:
|
47
|
+
|
48
|
+
* pull in latest code from remote branch
|
49
|
+
* merge in latest code from master branch
|
50
|
+
* prompt user to confirm they actually want to perform the release
|
51
|
+
* merge current branch into master
|
52
|
+
* (optional) cleanup merged branches from remote server
|
53
|
+
|
54
|
+
options:
|
55
|
+
* `--cleanup` = automatically cleanup merged branches after release complete
|
56
|
+
|
57
|
+
# Extra Utility Git Extensions
|
58
|
+
|
59
|
+
## git cleanup
|
60
|
+
|
61
|
+
delete released branches after they have been merged into master.
|
62
|
+
|
63
|
+
## git nuke <aggregate_branch_name>
|
64
|
+
|
65
|
+
reset an aggregate branch (ex: prototype, staging) back to a known good state.
|
66
|
+
|
67
|
+
## git buildtag
|
68
|
+
|
69
|
+
create a build tag for the current Travis-CI build and push it back to origin
|
70
|
+
|
71
|
+
|
72
|
+
## Note on Patches/Pull Requests
|
73
|
+
|
74
|
+
* Fork the project.
|
75
|
+
* Make your feature addition or bug fix.
|
76
|
+
* Add tests for it. This is important so I don't break it in a
|
77
|
+
future version unintentionally.
|
78
|
+
* Commit, do not mess with rakefile, version, or history.
|
79
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
80
|
+
* Send me a pull request. Bonus points for topic branches.
|
81
|
+
|
82
|
+
## Copyright
|
83
|
+
|
84
|
+
Copyright (c) 2015 LiveBuzz Ltd. (c) 2013 The Garage, Inc. See LICENSE for details.
|
data/Rakefile
ADDED
data/bin/git-buildtag
ADDED
data/bin/git-cleanup
ADDED
data/bin/git-integrate
ADDED
data/bin/git-nuke
ADDED
data/bin/git-release
ADDED
data/bin/git-review
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
puts 'WARNING: git reviewrequest has been deprecated. use `git review` instead'
|
4
|
+
|
5
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
6
|
+
require 'livebuzz/gitx/cli/review_command'
|
7
|
+
args = ARGV.dup.unshift('review')
|
8
|
+
LiveBuzz::Gitx::Cli::ReviewCommand.start(args)
|
data/bin/git-share
ADDED
data/bin/git-start
ADDED
data/bin/git-track
ADDED
data/bin/git-update
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'pathname'
|
3
|
+
require 'rugged'
|
4
|
+
require 'livebuzz/gitx'
|
5
|
+
|
6
|
+
module LiveBuzz
|
7
|
+
module Gitx
|
8
|
+
module Cli
|
9
|
+
class BaseCommand < Thor
|
10
|
+
include Thor::Actions
|
11
|
+
|
12
|
+
class MergeError < Thor::Error; end
|
13
|
+
|
14
|
+
add_runtime_options!
|
15
|
+
|
16
|
+
method_option :trace, :type => :boolean, :aliases => '-v'
|
17
|
+
def initialize(*args)
|
18
|
+
super(*args)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def repo
|
24
|
+
@repo ||= begin
|
25
|
+
path = Dir.pwd
|
26
|
+
Rugged::Repository.discover(path)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def checkout_branch(branch_name)
|
31
|
+
run_cmd "git checkout #{branch_name}"
|
32
|
+
end
|
33
|
+
|
34
|
+
# lookup the current branch of the repo
|
35
|
+
def current_branch
|
36
|
+
repo.branches.find(&:head?)
|
37
|
+
end
|
38
|
+
|
39
|
+
def assert_aggregate_branch!(target_branch)
|
40
|
+
fail "Invalid aggregate branch: #{target_branch} must be one of supported aggregate branches #{config.aggregate_branches}" unless config.aggregate_branch?(target_branch)
|
41
|
+
end
|
42
|
+
|
43
|
+
def assert_not_protected_branch!(branch, action)
|
44
|
+
raise "Cannot #{action} reserved branch" if config.reserved_branch?(branch) || config.aggregate_branch?(branch)
|
45
|
+
end
|
46
|
+
|
47
|
+
# helper to invoke other CLI commands
|
48
|
+
def execute_command(command_class, method, args = [])
|
49
|
+
command_class.new.send(method, *args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def config
|
53
|
+
@configuration ||= LiveBuzz::Gitx::Configuration.new(repo.workdir)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'livebuzz/gitx'
|
3
|
+
require 'livebuzz/gitx/cli/base_command'
|
4
|
+
|
5
|
+
module LiveBuzz
|
6
|
+
module Gitx
|
7
|
+
module Cli
|
8
|
+
class BuildtagCommand < BaseCommand
|
9
|
+
|
10
|
+
desc 'buildtag', 'create a tag for the current build and push it back to origin (supports Travis CI and Codeship)'
|
11
|
+
def buildtag
|
12
|
+
fail "Unknown branch. Environment variables TRAVIS_BRANCH or CI_BRANCH are required" unless branch_name
|
13
|
+
fail "Branch must be one of the supported taggable branches: #{config.taggable_branches}" unless config.taggable_branch?(branch_name)
|
14
|
+
|
15
|
+
label = "buildtag generated by build #{build_number}"
|
16
|
+
create_build_tag(branch_name, label)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# pull the current branch name from environment variables
|
22
|
+
# supports Travis CI or Codeship variables
|
23
|
+
# see https://www.codeship.io/documentation/continuous-integration/set-environment-variables/
|
24
|
+
def branch_name
|
25
|
+
ENV['TRAVIS_BRANCH'] || ENV['CI_BRANCH']
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_number
|
29
|
+
ENV['TRAVIS_BUILD_NUMBER'] || ENV['CI_BUILD_NUMBER']
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_build_tag(branch, label)
|
33
|
+
timestamp = Time.now.utc.strftime '%Y-%m-%d-%H-%M-%S'
|
34
|
+
git_tag = "build-#{branch}-#{timestamp}"
|
35
|
+
run_cmd "git tag #{git_tag} -a -m '#{label}'"
|
36
|
+
run_cmd "git push origin #{git_tag}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'livebuzz/gitx'
|
3
|
+
require 'livebuzz/gitx/cli/base_command'
|
4
|
+
|
5
|
+
module LiveBuzz
|
6
|
+
module Gitx
|
7
|
+
module Cli
|
8
|
+
class CleanupCommand < BaseCommand
|
9
|
+
desc 'cleanup', 'Cleanup branches that have been merged into master from the repo'
|
10
|
+
def cleanup
|
11
|
+
checkout_branch LiveBuzz::Gitx::BASE_BRANCH
|
12
|
+
run_cmd "git pull"
|
13
|
+
run_cmd 'git remote prune origin'
|
14
|
+
|
15
|
+
say "Deleting local and remote branches that have been merged into "
|
16
|
+
say LiveBuzz::Gitx::BASE_BRANCH, :green
|
17
|
+
merged_branches(remote: true).each do |branch|
|
18
|
+
run_cmd "git push origin --delete #{branch}"
|
19
|
+
end
|
20
|
+
merged_branches(remote: false).each do |branch|
|
21
|
+
run_cmd "git branch -d #{branch}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# @return list of branches that have been merged
|
28
|
+
def merged_branches(options = {})
|
29
|
+
args = []
|
30
|
+
args << '-r' if options[:remote]
|
31
|
+
args << "--merged"
|
32
|
+
output = run_cmd("git branch #{args.join(' ')}").split("\n")
|
33
|
+
branches = output.map do |branch|
|
34
|
+
branch = branch.gsub(/\*/, '').strip.split(' ').first
|
35
|
+
branch = branch.split('/').last if options[:remote]
|
36
|
+
branch
|
37
|
+
end
|
38
|
+
branches.uniq!
|
39
|
+
branches -= config.reserved_branches
|
40
|
+
branches.reject! { |b| config.aggregate_branch?(b) }
|
41
|
+
|
42
|
+
branches
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'livebuzz/gitx'
|
3
|
+
require 'livebuzz/gitx/cli/base_command'
|
4
|
+
require 'livebuzz/gitx/cli/update_command'
|
5
|
+
require 'livebuzz/gitx/github'
|
6
|
+
|
7
|
+
module LiveBuzz
|
8
|
+
module Gitx
|
9
|
+
module Cli
|
10
|
+
class IntegrateCommand < BaseCommand
|
11
|
+
include LiveBuzz::Gitx::Github
|
12
|
+
desc 'integrate', 'integrate the current branch into one of the aggregate development branches (default = staging)'
|
13
|
+
method_option :resume, :type => :string, :aliases => '-r', :desc => 'resume merging of feature-branch'
|
14
|
+
def integrate(integration_branch = 'staging')
|
15
|
+
assert_aggregate_branch!(integration_branch)
|
16
|
+
|
17
|
+
branch = feature_branch_name
|
18
|
+
print_message(branch, integration_branch)
|
19
|
+
|
20
|
+
begin
|
21
|
+
execute_command(UpdateCommand, :update)
|
22
|
+
rescue
|
23
|
+
fail MergeError, "Merge Conflict Occurred. Please Merge Conflict Occurred. Please fix merge conflict and rerun the integrate command"
|
24
|
+
end
|
25
|
+
|
26
|
+
integrate_branch(branch, integration_branch) unless options[:resume]
|
27
|
+
checkout_branch branch
|
28
|
+
|
29
|
+
create_integrate_comment(branch) unless config.reserved_branch?(branch)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def print_message(branch, integration_branch)
|
35
|
+
message = options[:resume] ? 'Resuming integration of' : 'Integrating'
|
36
|
+
say "#{message} "
|
37
|
+
say "#{branch} ", :green
|
38
|
+
say "into "
|
39
|
+
say integration_branch, :green
|
40
|
+
end
|
41
|
+
|
42
|
+
def integrate_branch(branch, integration_branch)
|
43
|
+
fetch_remote_branch(integration_branch)
|
44
|
+
begin
|
45
|
+
run_cmd "git merge #{branch}"
|
46
|
+
rescue
|
47
|
+
fail MergeError, "Merge Conflict Occurred. Please fix merge conflict and rerun command with --resume #{branch} flag"
|
48
|
+
end
|
49
|
+
run_cmd "git push origin HEAD"
|
50
|
+
end
|
51
|
+
|
52
|
+
def feature_branch_name
|
53
|
+
@feature_branch ||= begin
|
54
|
+
feature_branch = options[:resume] || current_branch.name
|
55
|
+
until local_branch_exists?(feature_branch)
|
56
|
+
feature_branch = ask("#{feature_branch} does not exist. Please select one of the available local branches: #{local_branches}")
|
57
|
+
end
|
58
|
+
feature_branch
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# nuke local branch and pull fresh version from remote repo
|
63
|
+
def fetch_remote_branch(target_branch)
|
64
|
+
create_remote_branch(target_branch) unless remote_branch_exists?(target_branch)
|
65
|
+
run_cmd "git fetch origin"
|
66
|
+
run_cmd "git branch -D #{target_branch}", :allow_failure => true
|
67
|
+
checkout_branch target_branch
|
68
|
+
end
|
69
|
+
|
70
|
+
def local_branch_exists?(branch)
|
71
|
+
local_branches.include?(branch)
|
72
|
+
end
|
73
|
+
|
74
|
+
def local_branches
|
75
|
+
@local_branches ||= repo.branches.each_name(:local)
|
76
|
+
end
|
77
|
+
|
78
|
+
def remote_branch_exists?(target_branch)
|
79
|
+
repo.branches.each_name(:remote).include?("origin/#{target_branch}")
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_remote_branch(target_branch)
|
83
|
+
repo.create_branch(target_branch, LiveBuzz::Gitx::BASE_BRANCH)
|
84
|
+
run_cmd "git push origin #{target_branch}:#{target_branch}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def create_integrate_comment(branch)
|
88
|
+
pull_request = find_or_create_pull_request(branch)
|
89
|
+
comment = '[gitx] integrated into staging :twisted_rightwards_arrows:'
|
90
|
+
github_client.add_comment(github_slug, pull_request.number, comment)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'livebuzz/gitx'
|
3
|
+
require 'livebuzz/gitx/cli/base_command'
|
4
|
+
|
5
|
+
module LiveBuzz
|
6
|
+
module Gitx
|
7
|
+
module Cli
|
8
|
+
class NukeCommand < BaseCommand
|
9
|
+
desc 'nuke', 'nuke the specified aggregate branch and reset it to a known good state'
|
10
|
+
method_option :destination, :type => :string, :aliases => '-d', :desc => 'destination branch to reset to'
|
11
|
+
def nuke(bad_branch)
|
12
|
+
good_branch = options[:destination] || ask("What branch do you want to reset #{bad_branch} to? (default: #{bad_branch})")
|
13
|
+
good_branch = bad_branch if good_branch.length == 0
|
14
|
+
|
15
|
+
last_known_good_tag = current_build_tag(good_branch)
|
16
|
+
return unless yes?("Reset #{bad_branch} to #{last_known_good_tag}? (y/n)", :green)
|
17
|
+
assert_aggregate_branch!(bad_branch)
|
18
|
+
return if migrations_need_to_be_reverted?(bad_branch, last_known_good_tag)
|
19
|
+
|
20
|
+
say "Resetting "
|
21
|
+
say "#{bad_branch} ", :green
|
22
|
+
say "branch to "
|
23
|
+
say last_known_good_tag, :green
|
24
|
+
|
25
|
+
checkout_branch LiveBuzz::Gitx::BASE_BRANCH
|
26
|
+
run_cmd "git branch -D #{bad_branch}", :allow_failure => true
|
27
|
+
run_cmd "git push origin --delete #{bad_branch}", :allow_failure => true
|
28
|
+
run_cmd "git checkout -b #{bad_branch} #{last_known_good_tag}"
|
29
|
+
run_cmd "git push origin #{bad_branch}"
|
30
|
+
run_cmd "git branch --set-upstream-to origin/#{bad_branch}"
|
31
|
+
checkout_branch LiveBuzz::Gitx::BASE_BRANCH
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def migrations_need_to_be_reverted?(bad_branch, last_known_good_tag)
|
37
|
+
return false unless File.exist?('db/migrate')
|
38
|
+
outdated_migrations = run_cmd("git diff #{last_known_good_tag}...#{bad_branch} --name-only db/migrate").split
|
39
|
+
return false if outdated_migrations.empty?
|
40
|
+
|
41
|
+
say "#{bad_branch} contains migrations that may need to be reverted. Ensure any reversable migrations are reverted on affected databases before nuking.", :red
|
42
|
+
say 'Example commands to revert outdated migrations:'
|
43
|
+
outdated_migrations.reverse.each do |migration|
|
44
|
+
version = File.basename(migration).split('_').first
|
45
|
+
say "rake db:migrate:down VERSION=#{version}"
|
46
|
+
end
|
47
|
+
!yes?("Are you sure you want to nuke #{bad_branch}? (y/n) ", :green)
|
48
|
+
end
|
49
|
+
|
50
|
+
def current_build_tag(branch)
|
51
|
+
last_build_tag = build_tags_for_branch(branch).last
|
52
|
+
raise "No known good tag found for branch: #{branch}. Verify tag exists via `git tag -l 'build-#{branch}-*'`" unless last_build_tag
|
53
|
+
last_build_tag
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_tags_for_branch(branch)
|
57
|
+
run_cmd "git fetch --tags"
|
58
|
+
build_tags = run_cmd("git tag -l 'build-#{branch}-*'").split
|
59
|
+
build_tags.sort
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'livebuzz/gitx'
|
3
|
+
require 'livebuzz/gitx/cli/base_command'
|
4
|
+
require 'livebuzz/gitx/cli/update_command'
|
5
|
+
require 'livebuzz/gitx/cli/integrate_command'
|
6
|
+
require 'livebuzz/gitx/cli/cleanup_command'
|
7
|
+
require 'livebuzz/gitx/github'
|
8
|
+
|
9
|
+
module LiveBuzz
|
10
|
+
module Gitx
|
11
|
+
module Cli
|
12
|
+
class ReleaseCommand < BaseCommand
|
13
|
+
include LiveBuzz::Gitx::Github
|
14
|
+
|
15
|
+
desc 'release', 'release the current branch to production'
|
16
|
+
method_option :cleanup, :type => :boolean, :desc => 'cleanup merged branches after release'
|
17
|
+
def release
|
18
|
+
return unless yes?("Release #{current_branch.name} to production? (y/n)", :green)
|
19
|
+
|
20
|
+
branch = current_branch.name
|
21
|
+
assert_not_protected_branch!(branch, 'release')
|
22
|
+
execute_command(UpdateCommand, :update)
|
23
|
+
|
24
|
+
find_or_create_pull_request(branch)
|
25
|
+
status = branch_status(branch)
|
26
|
+
if status != 'success'
|
27
|
+
return unless yes?("Branch status is currently: #{status}. Proceed with release? (y/n)", :red)
|
28
|
+
end
|
29
|
+
|
30
|
+
checkout_branch LiveBuzz::Gitx::BASE_BRANCH
|
31
|
+
run_cmd "git pull origin #{LiveBuzz::Gitx::BASE_BRANCH}"
|
32
|
+
run_cmd "git merge --no-ff #{branch}"
|
33
|
+
run_cmd "git push origin HEAD"
|
34
|
+
|
35
|
+
execute_command(IntegrateCommand, :integrate, 'staging')
|
36
|
+
execute_command(CleanupCommand, :cleanup) if options[:cleanup]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|