daq_flow 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +62 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +165 -0
  8. data/Rakefile +10 -0
  9. data/bin/daq_flow +23 -0
  10. data/flash_flow.gemspec +28 -0
  11. data/flash_flow.yml.erb.example +42 -0
  12. data/lib/flash_flow.rb +7 -0
  13. data/lib/flash_flow/branch_merger.rb +55 -0
  14. data/lib/flash_flow/cmd_runner.rb +54 -0
  15. data/lib/flash_flow/config.rb +84 -0
  16. data/lib/flash_flow/data.rb +6 -0
  17. data/lib/flash_flow/data/base.rb +89 -0
  18. data/lib/flash_flow/data/bitbucket.rb +152 -0
  19. data/lib/flash_flow/data/branch.rb +124 -0
  20. data/lib/flash_flow/data/collection.rb +211 -0
  21. data/lib/flash_flow/data/github.rb +140 -0
  22. data/lib/flash_flow/data/store.rb +44 -0
  23. data/lib/flash_flow/git.rb +267 -0
  24. data/lib/flash_flow/install.rb +19 -0
  25. data/lib/flash_flow/lock.rb +23 -0
  26. data/lib/flash_flow/merge.rb +6 -0
  27. data/lib/flash_flow/merge/acceptance.rb +154 -0
  28. data/lib/flash_flow/merge/base.rb +116 -0
  29. data/lib/flash_flow/merge_order.rb +27 -0
  30. data/lib/flash_flow/notifier.rb +23 -0
  31. data/lib/flash_flow/options.rb +34 -0
  32. data/lib/flash_flow/resolve.rb +143 -0
  33. data/lib/flash_flow/shadow_repo.rb +44 -0
  34. data/lib/flash_flow/time_helper.rb +32 -0
  35. data/lib/flash_flow/version.rb +4 -0
  36. data/log/.keep +0 -0
  37. data/test/lib/data/test_base.rb +10 -0
  38. data/test/lib/data/test_branch.rb +206 -0
  39. data/test/lib/data/test_collection.rb +308 -0
  40. data/test/lib/data/test_store.rb +70 -0
  41. data/test/lib/lock/test_github.rb +74 -0
  42. data/test/lib/merge/test_acceptance.rb +230 -0
  43. data/test/lib/test_branch_merger.rb +78 -0
  44. data/test/lib/test_config.rb +63 -0
  45. data/test/lib/test_git.rb +73 -0
  46. data/test/lib/test_merge_order.rb +71 -0
  47. data/test/lib/test_notifier.rb +33 -0
  48. data/test/lib/test_resolve.rb +69 -0
  49. data/test/minitest_helper.rb +41 -0
  50. data/update_gem.sh +5 -0
  51. metadata +192 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 33db5905fd00b05127ee7fb761b6e7c0fe7b89f099f1afe916a5dfe0b6200530
4
+ data.tar.gz: b13fc8564da32777578df3574300292eae18f921a386041ecd78540272c5d5b0
5
+ SHA512:
6
+ metadata.gz: b0b1c21344c05c378027335209a898bbf584455184b35c77b037fad4db90ebd3fdd083aa0c6b2ae7cd1a1378de8c8128a5973463cca64aea76a07b7f9b8e3e33
7
+ data.tar.gz: 153b426a3577f8dc3648135fb1299229e824e86865ff4fc90638129036c7e024410a00857c4ed04a8907628d945c7c45296f0d1606913832bd61b53be84233d7
@@ -0,0 +1,11 @@
1
+ *.gem
2
+ coverage
3
+ /.bundle
4
+ .env
5
+ /log/*.log
6
+ /tmp
7
+ /doc
8
+ public/*
9
+ vendor/bundle
10
+ .DS_Store
11
+ .idea/
@@ -0,0 +1 @@
1
+ 2.5.1
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,62 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ daq_flow (1.0.0)
5
+ octokit (~> 4.1)
6
+ tb-bjb (>= 1.6.2)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activemodel (5.2.3)
12
+ activesupport (= 5.2.3)
13
+ activesupport (5.2.3)
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ i18n (>= 0.7, < 2)
16
+ minitest (~> 5.1)
17
+ tzinfo (~> 1.1)
18
+ addressable (2.5.2)
19
+ public_suffix (>= 2.0.2, < 4.0)
20
+ concurrent-ruby (1.1.5)
21
+ faraday (0.15.4)
22
+ multipart-post (>= 1.2, < 3)
23
+ faraday-http-cache (1.3.1)
24
+ faraday (~> 0.8)
25
+ faraday_middleware (0.13.1)
26
+ faraday (>= 0.7.4, < 1.0)
27
+ i18n (1.6.0)
28
+ concurrent-ruby (~> 1.0)
29
+ minitest (5.3.5)
30
+ minitest-stub_any_instance (1.0.1)
31
+ multipart-post (2.0.0)
32
+ octokit (4.14.0)
33
+ sawyer (~> 0.8.0, >= 0.5.3)
34
+ public_suffix (3.0.3)
35
+ rake (10.4.2)
36
+ sawyer (0.8.1)
37
+ addressable (>= 2.3.5, < 2.6)
38
+ faraday (~> 0.8, < 1.0)
39
+ simple_oauth (0.3.1)
40
+ tb-bjb (1.6.2)
41
+ activemodel (>= 4.1.6)
42
+ activesupport (>= 4.1.6)
43
+ faraday (~> 0.9)
44
+ faraday-http-cache (~> 1.2)
45
+ faraday_middleware (~> 0.10)
46
+ simple_oauth (~> 0.3)
47
+ thread_safe (0.3.6)
48
+ tzinfo (1.2.5)
49
+ thread_safe (~> 0.1)
50
+
51
+ PLATFORMS
52
+ ruby
53
+
54
+ DEPENDENCIES
55
+ bundler (~> 1.6)
56
+ daq_flow!
57
+ minitest (> 0)
58
+ minitest-stub_any_instance (> 0)
59
+ rake (> 0)
60
+
61
+ BUNDLED WITH
62
+ 1.17.1
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 FlashFunders
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.
@@ -0,0 +1,165 @@
1
+ # Flash Flow
2
+
3
+ Flash Flow is a ruby gem that helps your team keep your acceptance environment up to date. Check out
4
+ [this gist](https://gist.github.com/bradleyjucsc/bfbb8742889edf1b423a) for a detailed explanation of
5
+ how it works.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'flash_flow'
12
+
13
+ And then run:
14
+
15
+ $ bundle install
16
+ $ bundle exec flash_flow --install
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install flash_flow
21
+
22
+ And then run:
23
+
24
+ $ flash_flow --install
25
+
26
+ After "installing" flash_flow, you'll have a file "config/flash_flow.yml.erb". If your remote is origin,
27
+ your master branch is master, and you're fine using "acceptance" as the branch that flash_flow owns, you
28
+ are ready to go for flash_flow basic. If not, edit that file and change branch and remote names accordingly.
29
+
30
+ ## Usage
31
+ flash_flow is a ruby script which, in the simplest case, can just be run by calling `flash_flow`.
32
+ What that will do (once your application is properly configured) is:
33
+
34
+ 1. Push your branch to the `remote`
35
+ 2. Reset your `merge_branch` to be the same as your `master_branch`
36
+ 3. Get your list of pull requests from github (or use the saved list, more on that later)
37
+ 4. Filter out any "removed" branches
38
+ 5. Merge the rest into the newly created `merge_branch`
39
+ 6. Push the `merge_branch` to the `remote`
40
+ 7. The `merge_branch` is now a merge of your master branch plus all of your pull requests.
41
+
42
+ ### Notes
43
+
44
+ 1. Step 1 will not push your branch if you're on either the `merge_branch` or `master_branch`, but it will
45
+ still merge all the other branches and push the result.
46
+ 2. flash_flow creates a copy of your local git repo. The copy lives in /your/repo/dir/../.flash_flow/.
47
+ That's where it merges all the code and pushes to the remote from. This "shadow" directory is used so
48
+ that your local git repository is still available for your use while flash flow is running.
49
+
50
+
51
+ ### Configuring a lock
52
+ We use the "lock" configuration in flash_flow.yml. The lock ensures that no one else is running flash_flow
53
+ while you are so that you don't inadvertently have your newly pushed branch overwritten. The way we lock you
54
+ out is super janky, we open an issue on github when flash_flow starts and close it when flash_flow is done.
55
+ To configure the lock you need to specify the class name, your github token, your github repo, and the issue_id
56
+ that you want to open and close each time. The email alerts you get from github about this issue are annoying
57
+ and should be ignored.
58
+
59
+ ### Configuring branches
60
+ We use github to track our branches that we want to merge, and there are a few things about that worth noting.
61
+ In step 1 after your branch is pushed, a pull request into `master_branch` will be created on github. If you
62
+ add the "do not merge" label to a pull request, it will be excluded from the `merge_branch`. This is extremely
63
+ useful whenever one of your co-workers breaks the build, you can either run `flash_flow --no-merge` from their
64
+ branch, or go directly to github and add the "do not merge" label and then re-run flash_flow from your branch.
65
+
66
+ To use github as your source of merge branches you have to configure it with the class name, github token and
67
+ repo, your master branch name and both the unmergeable label and do not merge label, which must exist on github.
68
+ The unmergeable label is added to a pull request that has a conflict that can't be resolved and is therefore
69
+ excluded from the merge branch.
70
+
71
+ ### Configuring an issue tracker
72
+ We use Pivotal Tracker. When we have finished work for a story on a particular branch we run
73
+ `flash_flow --story <story_id>`, which will transition all of those stories to "finished" if they were previously
74
+ "started".
75
+
76
+ When code deploys to our review environment, our deploy script runs `flash_flow --review-deploy`, which transitions
77
+ stories associated with merged branches from "finished" to "delivered". At the same time, for a branch that has been
78
+ removed ("--no-merge"), if the story is "delivered" it will transition back to "finished". This means that the only
79
+ buttons that have to be manually clicked in tracker are "Start" and "Accept/Reject".
80
+
81
+ In addition, as part of our production deploy script, we run `flash_flow --prod-deploy`, which takes all the stories
82
+ that are newly in the `master_branch` and adds a comment "Deployed to production on 12/25/2015 at 11:11pm". Tracker
83
+ doesn't support a real state for "In production", so for us this comment serves as that state.
84
+
85
+ ### Runtime options
86
+
87
+ #### -v, --version
88
+ Print the current version of flash flow and exit.
89
+
90
+ #### -n, --no-merge
91
+ Runs flash_flow, but excludes the branch that you're on from the merge branch. If the branch you're on has breaking
92
+ tests, you may want to get it out of your `merge_branch`, and this will do that and ensure that the next times
93
+ flash_flow is run by anyone else it will not be included. It will add the "do not merge" label to your github pull
94
+ request if you're using that. Anytime you run flash_flow without this option, the branch you're running from will
95
+ be included in the `merge_branch` even if it has previously been set to "do not merge".
96
+
97
+ #### --rerere-forget
98
+ If you've resolved a merge conflict the wrong way, run with this option on the problem branch. The remembered
99
+ resolution will be deleted and you'll get to re-resolve your conflict.
100
+
101
+ #### --story <story_id>
102
+ Associates a story id with this branch. See "configuring an issue tracker" for why this can be useful.
103
+
104
+ #### --stories <story_id1,storyid2...>
105
+ Same as --story, but a comma-separated list so you can pass more than one story at a time.
106
+
107
+ #### -f, --force-push
108
+ Forces pushes your branch. All it does is add "-f" to the git push command, so you'd better make sure you know what
109
+ you're doing if you use this. The `merge_branch` always gets force pushed at the end, this option has nothing to do
110
+ with that.
111
+
112
+ #### --release-notes <hours>
113
+ Lists all the stories that have been deployed to production in the last <hours> hours. Only relevant if you run
114
+ --prod-deploy when you deploy.
115
+
116
+ #### --config-file FILE_PATH
117
+ This tells flash_flow how to find the configuration file. If you just put the file in config/flash_flow.yml you will
118
+ never need this option.
119
+
120
+ #### --prod-deploy
121
+ If you have Pivotal Tracker configured it will look at all stories associated with branches, and if that branch is
122
+ deployed to `master_branch` it will add a comment to those stories that says
123
+ "Deployed to production on MM/DD/YY at XX:XX". This is meant to be used right after every deploy to your production
124
+ environment. The acceptance branch will not be re-built in this case.
125
+
126
+ #### --review-deploy
127
+ If you have Pivotal Tracker configured it will look at all stories associated with branches, and if that branch is
128
+ deployed to `acceptance_branch` it will mark any finished stories as delivered. This is best used right after every
129
+ deploy to your acceptance environment. The acceptance branch will not be re-built in this case.
130
+
131
+ #### --resolve
132
+ Launch a bash shell to save your conflict resolutions. If your branch didn't merge the last time you ran flash flow
133
+ you'll run this command. This drops you into bash where you can save your resolved conflicts, then those resolutions
134
+ will be remembered the next time you run flash flow.
135
+
136
+ #### --resolve-manual
137
+ Print instructions that will show you how to resolve your merge conflicts without using flash flow's version of the
138
+ shell. If you don't use bash, or flash flow does odd things to your bash config, this is the way to go.
139
+
140
+ ### A note about merge conflicts
141
+ When we first started using flash_flow, if your branch had a merge conflict you were out of luck. You had to wait for
142
+ the branch that you were conflicting with to be merged to master, merge master into your branch, and then try again to
143
+ get your code into the merge branch.
144
+
145
+ Then we discovered `git rerere`, which is [the coolest feature of git that almost no one seems to have heard of](https://git-scm.com/blog/2010/03/08/rerere.html). Basically
146
+ what rerere does is remember how you resolved conflicts and auto-apply those patches when it notices the same conflicts.
147
+
148
+ If your branch has a conflict with the `merge_branch` flash_flow will look for a rerere patch and apply that if it
149
+ exists. If it doesn't, flash_flow will not merge your branch (but will continue merging all the others), and it will
150
+ spit out instructions for how to make your branch merge successfully. Once you follow those instructions (which involve
151
+ resolving the merge conflicts and saving the resolution), the next time you run flash_flow it will use that resolution
152
+ and everything will be sunshine and ponies.
153
+
154
+ In addition, flash_flow takes all your patches and copies them into the `merge_branch` where they are saved. Every time
155
+ flash_flow is run, those patches are first copied out of the `merge_branch` into your local rerere cache. The result of
156
+ this is that every time flash_flow is run all previous resolutions are available so once you've merged your branch and
157
+ flash_flow'ed it, it will merge successfully for everyone else too. rerere ftwftwftw.
158
+
159
+ ## Contributing
160
+
161
+ 1. Fork it ( https://github.com/flashfunders/flash_flow/fork )
162
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
163
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
164
+ 4. Push to the branch (`git push origin my-new-feature`)
165
+ 5. Create a new Pull Request
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "test"
6
+ t.test_files = FileList['test/test*.rb', 'test/**/test*.rb']
7
+ t.verbose = true
8
+ end
9
+
10
+ task :default => [:test]
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'flash_flow'
4
+
5
+ options = FlashFlow::Options.parse
6
+
7
+ if options[:install]
8
+ FlashFlow::Install.install
9
+ exit(0)
10
+ elsif options[:version]
11
+ puts "Flash flow version #{FlashFlow::VERSION}\n"
12
+ exit(0)
13
+ end
14
+
15
+ FlashFlow::Config.configure!(options[:config_file])
16
+ case
17
+ when options[:resolve]
18
+ FlashFlow::Resolve.new(FlashFlow::Config.configuration.git, FlashFlow::Config.configuration.branch_info_file, logger: FlashFlow::Config.configuration.logger).start
19
+ when options[:resolve_manual]
20
+ FlashFlow::Resolve.new(FlashFlow::Config.configuration.git, FlashFlow::Config.configuration.branch_info_file, logger: FlashFlow::Config.configuration.logger).manual_instructions
21
+ else
22
+ FlashFlow::Merge::Acceptance.new(options).run
23
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'flash_flow/version'
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "daq_flow"
7
+ spec.version = FlashFlow::VERSION
8
+ spec.authors = ["Brad Bennett"]
9
+ spec.email = ["bradleyjaybennett@gmail.com"]
10
+ spec.summary = %q{Merge your open prs together}
11
+ spec.description = %q{Flash flow is a command line tool for keeping your acceptance environment up to date}
12
+ spec.homepage = "https://github.com/bradleyjucsc/flash_flow"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency 'octokit', "~> 4.1"
21
+ spec.add_dependency 'tb-bjb', ">= 1.6.2"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rake", "> 0"
25
+ spec.add_development_dependency "minitest", "> 0"
26
+ # spec.add_development_dependency "byebug", "> 0"
27
+ spec.add_development_dependency 'minitest-stub_any_instance', "> 0"
28
+ end
@@ -0,0 +1,42 @@
1
+ ## The basic settings for your app
2
+
3
+ git:
4
+ # This is what allows you to resolve merge conflicts using flash_flow, rerere is amazing. There's
5
+ # more description elsewhere about how this works.
6
+ use_rerere: true
7
+
8
+ # Which remote your branches use
9
+ remote: origin
10
+
11
+ # This branch is owned by flash_flow, and will be overwritten. Don't use a branch to which you make
12
+ # commits. Treat this as 100% ephemeral, this is the branch that you should deploy automatically to
13
+ # your review/staging env.
14
+ merge_branch: acceptance
15
+
16
+ # This is your mainline production branch that is the basis for the merge branch
17
+ master_branch: master
18
+
19
+ # An arbitrary file that flash_flow will write to in the merge branch and use to store branch information.
20
+ # Make sure it doesn't collide with a file you actually need in your application. You don't need to look at
21
+ # this file in general.
22
+ branch_info_file: 'flash_flow.json'
23
+
24
+
25
+
26
+ ### Everything below here is optional and should be deleted or remain commented out if you don't need it
27
+
28
+ ## We use Bitbucket as our source of truth for which branches to merge. All open pull requests that don't
29
+ ## have the "do not merge" label on them get merged. If you configure this flash_flow will automatically
30
+ ## create a PR for your branch when it runs. If your branch can't merge, it will still be PR'ed, but it
31
+ ## will have the "unmergeable" label on it (that label is strictly informational, no functionality is
32
+ ## affected at all).
33
+
34
+ #branches:
35
+ # class:
36
+ # name: 'FlashFlow::Data::Bitbucket'
37
+ # token: <%= ENV['GH_TOKEN'] %>
38
+ # repo: # Your github repo. For example, the flash_flow repo is 'flashfunders/flash_flow'
39
+ # master_branch: master
40
+ # unmergeable_label: unmergeable
41
+ # do_not_merge_label: 'do not merge'
42
+ # shippable_label: 'shippable'
@@ -0,0 +1,7 @@
1
+ module FlashFlow; end
2
+
3
+ require 'flash_flow/options'
4
+ require 'flash_flow/install'
5
+ require 'flash_flow/config'
6
+ require 'flash_flow/resolve'
7
+ require 'flash_flow/merge'
@@ -0,0 +1,55 @@
1
+ module FlashFlow
2
+ class BranchMerger
3
+
4
+ attr_reader :conflict_sha, :resolutions, :result
5
+
6
+ def initialize(git, branch)
7
+ @git = git
8
+ @branch = branch
9
+ end
10
+
11
+ def do_merge(rerere_forget)
12
+ if sha.nil?
13
+ @result = :deleted
14
+ return
15
+ end
16
+
17
+ @git.run("merge --no-ff #{@git.remote}/#{@branch.ref}")
18
+
19
+ if @git.last_success? || try_rerere(rerere_forget)
20
+ @result = :success
21
+ else
22
+ @conflict_sha = merge_rollback
23
+ @result = :conflict
24
+ end
25
+ end
26
+
27
+ def sha
28
+ @sha if defined?(@sha)
29
+ @sha = get_sha
30
+ end
31
+
32
+ private
33
+
34
+ def try_rerere(rerere_forget)
35
+ if rerere_forget
36
+ @git.run('rerere forget')
37
+ false
38
+ else
39
+ @resolutions = @git.rerere_resolve!
40
+ end
41
+ end
42
+
43
+ def get_sha
44
+ @git.run("rev-parse #{@git.remote}/#{@branch.ref}")
45
+ @git.last_stdout.strip if @git.last_success?
46
+ end
47
+
48
+ def merge_rollback
49
+ @git.run("reset --hard HEAD")
50
+ @git.run("rev-parse HEAD")
51
+ @git.last_stdout.strip
52
+ end
53
+ end
54
+ end
55
+