git_workflow 0.0.5

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.
Files changed (74) hide show
  1. data/README.markdown +77 -0
  2. data/Rakefile +33 -0
  3. data/bin/git-finish +4 -0
  4. data/bin/git-start +4 -0
  5. data/bin/git-workflow-setup +4 -0
  6. data/features/core_functionality/4049578_need_the_ability_to_start_a_new_branch.feature +15 -0
  7. data/features/core_functionality/4049611_need_the_ability_to_finish_a_specified_branch.feature +17 -0
  8. data/features/core_functionality/4056359_start_with_local_branch_already_present.feature +16 -0
  9. data/features/core_functionality/4056363_finish_the_current_branch.feature +17 -0
  10. data/features/core_functionality/4056389_changes_to_pt_story_name_cause_branch_issues.feature +25 -0
  11. data/features/core_functionality/4135658_control_output_verbosity_using_v_switch.feature +32 -0
  12. data/features/core_functionality/4468313_get_config_value_for_is_producing_an_error_log.feature +43 -0
  13. data/features/extensions/4058326_display_story_description_on_start.feature +14 -0
  14. data/features/git_branching/4135501_allow_branch_start_point_to_be_specified_from_command_line.feature +27 -0
  15. data/features/hooks/4069174_investigate_the_effort_required_to_add_pre_amp_post_hooks.feature +24 -0
  16. data/features/hooks/4199841_need_hooks_for_my_workflow.feature +51 -0
  17. data/features/hooks/4199845_need_hooks_for_sanger_workflow.feature +66 -0
  18. data/features/hooks/4205913_output_from_rake_tests_should_be_seen.feature +19 -0
  19. data/features/hooks/4424828_git_start_is_missing_pt_integration_for_my_hooks.feature +15 -0
  20. data/features/pivotal_tracker_api/4133291_chores_go_straight_to_accepted_not_to_finished.feature +15 -0
  21. data/features/release/4132264_fix_the_libxml_warnings_from_nokogiri.feature +20 -0
  22. data/features/step_definitions/aruba_extensions.rb +4 -0
  23. data/features/step_definitions/configuration_steps.rb +38 -0
  24. data/features/step_definitions/git_steps.rb +102 -0
  25. data/features/step_definitions/misc_steps.rb +3 -0
  26. data/features/step_definitions/pivotal_tracker_steps.rb +43 -0
  27. data/features/step_definitions/project_code_steps.rb +35 -0
  28. data/features/support/aruba.rb +1 -0
  29. data/features/support/hooks/configuration.rb +4 -0
  30. data/features/support/hooks/environment.rb +49 -0
  31. data/features/support/hooks/pivotal_tracker.rb +170 -0
  32. data/lib/git_workflow.rb +5 -0
  33. data/lib/git_workflow/callbacks.rb +16 -0
  34. data/lib/git_workflow/callbacks/pivotal_tracker_support.rb +64 -0
  35. data/lib/git_workflow/callbacks/remote_git_branch_support.rb +9 -0
  36. data/lib/git_workflow/callbacks/styles/debug.rb +58 -0
  37. data/lib/git_workflow/callbacks/styles/default.rb +43 -0
  38. data/lib/git_workflow/callbacks/styles/mine.rb +52 -0
  39. data/lib/git_workflow/callbacks/styles/sanger.rb +48 -0
  40. data/lib/git_workflow/callbacks/test_code_support.rb +29 -0
  41. data/lib/git_workflow/command_line.rb +46 -0
  42. data/lib/git_workflow/commands.rb +4 -0
  43. data/lib/git_workflow/commands/base.rb +31 -0
  44. data/lib/git_workflow/commands/finish.rb +36 -0
  45. data/lib/git_workflow/commands/setup.rb +157 -0
  46. data/lib/git_workflow/commands/start.rb +30 -0
  47. data/lib/git_workflow/configuration.rb +93 -0
  48. data/lib/git_workflow/core_ext.rb +106 -0
  49. data/lib/git_workflow/git.rb +143 -0
  50. data/lib/git_workflow/logger.yaml +27 -0
  51. data/lib/git_workflow/logging.rb +77 -0
  52. data/lib/git_workflow/story.rb +96 -0
  53. data/spec/core_functionality/4056539_support_http_proxy_spec.rb +68 -0
  54. data/spec/core_functionality/4058365_bad_request_on_story_update_spec.rb +13 -0
  55. data/spec/core_functionality/4058394_make_commands_more_verbose_spec.rb +41 -0
  56. data/spec/core_functionality/4058719_error_if_none_of_the_required_configuration_values_are_set_spec.rb +21 -0
  57. data/spec/core_functionality/4058861_git_config_returns_empty_strings_which_should_be_nil_spec.rb +59 -0
  58. data/spec/core_functionality/4172431_add_git_workflow_setup_command_to_make_setup_easier_spec.rb +148 -0
  59. data/spec/core_functionality/4199841_need_callbacks_for_my_workflow_spec.rb +97 -0
  60. data/spec/extensions/4199841_need_callbacks_for_my_workflow_spec.rb +167 -0
  61. data/spec/extensions/4205913_output_from_rake_tests_should_be_seen_spec.rb +34 -0
  62. data/spec/git_branching/4058723_branches_end_in_if_the_last_character_is_invalid_spec.rb +40 -0
  63. data/spec/git_branching/4059824_code_is_not_using_workflow_localbranchconvention_to_decode_branch_names_on_finish_spec.rb +115 -0
  64. data/spec/git_branching/4216087_support_pushing_branches_spec.rb +44 -0
  65. data/spec/hooks/4199845_need_hooks_for_sanger_workflow_spec.rb +27 -0
  66. data/spec/pivotal_tracker_api/4056381_pt_api_token_not_being_passed_in_headers_spec.rb +40 -0
  67. data/spec/pivotal_tracker_api/4056638_library_code_using_localhost_spec.rb +16 -0
  68. data/spec/pivotal_tracker_api/4056661_content_type_header_should_be_text_xml_on_updates_spec.rb +16 -0
  69. data/spec/pivotal_tracker_api/4058718_if_pt_username_is_not_set_use_user_name_spec.rb +26 -0
  70. data/spec/pivotal_tracker_api/4146016_decode_the_xml_encoded_text_of_description_and_name_spec.rb +63 -0
  71. data/spec/shared_examples/configuration.rb +10 -0
  72. data/spec/shared_examples/story.rb +17 -0
  73. data/spec/spec_helper.rb +18 -0
  74. metadata +220 -0
@@ -0,0 +1,5 @@
1
+ require 'git_workflow/core_ext'
2
+ require 'git_workflow/logging'
3
+ require 'git_workflow/configuration'
4
+ require 'git_workflow/story'
5
+ require 'git_workflow/commands'
@@ -0,0 +1,16 @@
1
+ # Automatically load the callbacks associated with the current settings
2
+ module GitWorkflow
3
+ module Callbacks
4
+ module Loader
5
+ extend GitWorkflow::Git
6
+ extend GitWorkflow::Logging::ClassMethods
7
+
8
+ callbacks = get_config_value_for('workflow.callbacks', 'default')
9
+ log(:info, "Loading the '#{ callbacks }' hooks") do
10
+ callback_name = "git_workflow/callbacks/styles/#{ callbacks }"
11
+ require callback_name
12
+ callback_name.constantize.setup
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,64 @@
1
+ module GitWorkflow
2
+ module Callbacks
3
+ module PivotalTrackerSupport
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ protected
9
+
10
+ def story(id, &block)
11
+ yield(GitWorkflow::Story.new(pivotal_tracker_service_for(id)))
12
+ end
13
+
14
+ private
15
+
16
+ def pivotal_tracker_service_for(story_id)
17
+ self.class.enable_http_proxy_if_present
18
+ url = self.class.pivotal_tracker_url_for(Configuration.instance.project_id, story_id)
19
+
20
+ debug("Using PT URL '#{ url }'")
21
+ RestClient::Resource.new(
22
+ url,
23
+ :headers => { 'X-TrackerToken' => Configuration.instance.api_token }
24
+ )
25
+ end
26
+
27
+ def start_story_on_pivotal_tracker!(story)
28
+ info("Marking story #{ story.story_id } as started") do
29
+ story.service! do |xml|
30
+ xml.current_state(story.start_state)
31
+ end
32
+ end
33
+ end
34
+
35
+ def finish_story_on_pivotal_tracker!(story)
36
+ info("Marking story #{ story.story_id } as finished") do
37
+ story.service! do |xml|
38
+ xml.current_state(story.finish_state)
39
+ end
40
+ end
41
+ end
42
+
43
+ module ClassMethods
44
+ def value_of_environment_variable(key)
45
+ ENV[key]
46
+ end
47
+
48
+ def enable_http_proxy_if_present
49
+ proxy = value_of_environment_variable('http_proxy')
50
+ proxy ||= value_of_environment_variable('HTTP_PROXY')
51
+ unless proxy.nil?
52
+ debug("Enabling HTTP proxy '#{ proxy }'")
53
+ RestClient.proxy = proxy
54
+ end
55
+ end
56
+
57
+ def pivotal_tracker_url_for(project_id, story_id)
58
+ "http://www.pivotaltracker.com/services/v3/projects/#{ project_id }/stories/#{ story_id }"
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,9 @@
1
+ module GitWorkflow
2
+ module Callbacks
3
+ module RemoteGitBranchSupport
4
+ def push_current_branch_to(remote_branch_name)
5
+ repository.push("HEAD:#{ remote_branch_name }")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,58 @@
1
+ require 'git_workflow/callbacks/styles/default'
2
+ require 'git_workflow/callbacks/pivotal_tracker_support'
3
+ require 'git_workflow/commands/start'
4
+ require 'git_workflow/commands/finish'
5
+ require 'log4r'
6
+
7
+ module GitWorkflow
8
+ module Callbacks
9
+ module Styles
10
+ module Debug
11
+ def self.setup(start_command = GitWorkflow::Commands::Start, finish_command = GitWorkflow::Commands::Finish)
12
+ Default.setup(start_command, finish_command)
13
+
14
+ start_command.send(:include, StartBehaviour)
15
+ finish_command.send(:include, FinishBehaviour)
16
+
17
+ require 'git_workflow/logging'
18
+ Log4r::Outputter['verbose_information'].level = Log4r::DEBUG
19
+ end
20
+
21
+ module StartBehaviour
22
+ def self.included(base)
23
+ base.instance_eval do
24
+ include GitWorkflow::Callbacks::PivotalTrackerSupport
25
+ extend GitWorkflow::Callbacks::Styles::Debug
26
+ debug_method(:start)
27
+ debug_method(:start_story_on_pivotal_tracker!)
28
+ end
29
+ end
30
+ end
31
+
32
+ module FinishBehaviour
33
+ def self.included(base)
34
+ base.instance_eval do
35
+ include GitWorkflow::Callbacks::PivotalTrackerSupport
36
+ extend GitWorkflow::Callbacks::Styles::Debug
37
+ debug_method(:finish)
38
+ debug_method(:finish_story_on_pivotal_tracker!)
39
+ end
40
+ end
41
+ end
42
+
43
+ def debug_method(method)
44
+ chain_methods(method, :debug) do |with_chain_method, without_chain_method|
45
+ class_eval <<-END_OF_DEBUG_METHOD
46
+ def #{ with_chain_method }(*args, &block)
47
+ debug("#{ method }(\#{ args.map(&:inspect).join(',') })") do
48
+ #{ without_chain_method }(*args, &block)
49
+ end
50
+ end
51
+ END_OF_DEBUG_METHOD
52
+ end
53
+ alias_method_chain(method, :debug)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,43 @@
1
+ require 'git_workflow/callbacks/pivotal_tracker_support'
2
+ require 'git_workflow/commands/start'
3
+ require 'git_workflow/commands/finish'
4
+
5
+ module GitWorkflow
6
+ module Callbacks
7
+ module Styles
8
+ module Default
9
+ def self.setup(start_class = GitWorkflow::Commands::Start, finish_class = GitWorkflow::Commands::Finish)
10
+ start_class.send(:include, StartBehaviour)
11
+ finish_class.send(:include, FinishBehaviour)
12
+ end
13
+
14
+ module StartBehaviour
15
+ def self.included(base)
16
+ base.instance_eval do
17
+ include GitWorkflow::Callbacks::PivotalTrackerSupport
18
+ end
19
+ end
20
+
21
+ def start(story, source)
22
+ checkout_or_create_branch(story.branch_name, source)
23
+ end
24
+ end
25
+
26
+ module FinishBehaviour
27
+ def self.included(base)
28
+ base.instance_eval do
29
+ include GitWorkflow::Callbacks::PivotalTrackerSupport
30
+ end
31
+ end
32
+
33
+ def finish(story, branch_name)
34
+ in_git_branch(branch_name) do
35
+ merge_branch(story.branch_name, branch_name)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
@@ -0,0 +1,52 @@
1
+ require 'git_workflow/callbacks/test_code_support'
2
+ require 'git_workflow/callbacks/remote_git_branch_support'
3
+ require 'git_workflow/callbacks/pivotal_tracker_support'
4
+ require 'git_workflow/commands/start'
5
+ require 'git_workflow/commands/finish'
6
+
7
+ module GitWorkflow
8
+ module Callbacks
9
+ module Styles
10
+ module Mine
11
+ def self.setup(start_class = GitWorkflow::Commands::Start, finish_class = GitWorkflow::Commands::Finish)
12
+ start_class.send(:include, StartBehaviour)
13
+ finish_class.send(:include, FinishBehaviour)
14
+ end
15
+
16
+ module StartBehaviour
17
+ def self.included(base)
18
+ base.instance_eval do
19
+ include GitWorkflow::Callbacks::PivotalTrackerSupport
20
+ end
21
+ end
22
+
23
+ def start(story, source)
24
+ checkout_or_create_branch(story.branch_name, source)
25
+ end
26
+ end
27
+
28
+ module FinishBehaviour
29
+ def self.included(base)
30
+ base.instance_eval do
31
+ include GitWorkflow::Callbacks::PivotalTrackerSupport
32
+ include GitWorkflow::Callbacks::TestCodeSupport
33
+ include GitWorkflow::Callbacks::RemoteGitBranchSupport
34
+ end
35
+ end
36
+
37
+ def finish(story, branch_name)
38
+ in_git_branch(story.branch_name) do
39
+ run_tests!(:spec, :features)
40
+ end
41
+ in_git_branch(branch_name) do
42
+ merge_branch(story.branch_name, branch_name)
43
+ run_tests_with_recovery!(:spec, :features)
44
+ push_current_branch_to(branch_name) if branch_name == 'master'
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,48 @@
1
+ require 'git_workflow/callbacks/test_code_support'
2
+ require 'git_workflow/callbacks/remote_git_branch_support'
3
+ require 'git_workflow/callbacks/pivotal_tracker_support'
4
+ require 'git_workflow/commands/start'
5
+ require 'git_workflow/commands/finish'
6
+
7
+ module GitWorkflow
8
+ module Callbacks
9
+ module Styles
10
+ module Sanger
11
+ def self.setup(start_command = GitWorkflow::Commands::Start, finish_command = GitWorkflow::Commands::Finish)
12
+ start_command.send(:include, StartBehaviour)
13
+ finish_command.send(:include, FinishBehaviour)
14
+ end
15
+
16
+ module StartBehaviour
17
+ def self.included(base)
18
+ base.instance_eval do
19
+ include GitWorkflow::Callbacks::PivotalTrackerSupport
20
+ end
21
+ end
22
+
23
+ def start(story, source)
24
+ checkout_or_create_branch(story.branch_name, source || 'master')
25
+ end
26
+ end
27
+
28
+ module FinishBehaviour
29
+ def self.included(base)
30
+ base.instance_eval do
31
+ include GitWorkflow::Callbacks::PivotalTrackerSupport
32
+ include GitWorkflow::Callbacks::TestCodeSupport
33
+ include GitWorkflow::Callbacks::RemoteGitBranchSupport
34
+ end
35
+ end
36
+
37
+ def finish(story, branch_name)
38
+ in_git_branch(story.branch_name) do
39
+ run_tests!(:test, :features)
40
+ push_current_branch_to(story.remote_branch_name)
41
+ story.comment("Fixed on #{ story.remote_branch_name }. Needs merging into master")
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ module GitWorkflow
2
+ module Callbacks
3
+ module TestCodeSupport
4
+ Failure = Class.new(StandardError)
5
+
6
+ def run_tests!(*rake_test_tasks)
7
+ run_tests(*rake_test_tasks) or raise Failure, 'The tests failed, please fix and try again'
8
+ end
9
+
10
+ def run_tests_with_recovery!(*rake_test_tasks)
11
+ until run_tests(*rake_test_tasks)
12
+ spawn_shell_for_recovery or raise Failure, 'The tests failed. Please fix and then "git push origin master"'
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def run_tests(*rake_test_tasks)
19
+ system('rake', *rake_test_tasks.map(&:to_s))
20
+ end
21
+
22
+ def spawn_shell_for_recovery
23
+ # TODO: spawn a shell with a message
24
+ # TODO: if the exit is complete failure return false
25
+ return false
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ require 'optparse'
2
+ require 'log4r'
3
+ require 'git_workflow/logging'
4
+
5
+ module GitWorkflow
6
+ module CommandLine
7
+ InvalidCommandLine = Class.new(StandardError)
8
+
9
+ private
10
+
11
+ def parse_command_line(command_line_arguments, &block)
12
+ parser = create_parser
13
+ parser.parse!(command_line_arguments)
14
+ yield(command_line_arguments) if block_given?
15
+ rescue InvalidCommandLine => exception
16
+ puts parser
17
+ exit 1
18
+ end
19
+
20
+ def create_parser
21
+ ::OptionParser.new do |options|
22
+ usage_info(options)
23
+
24
+ options.separator ''
25
+ options.separator 'Common options:'
26
+
27
+ options.on('-V', '--verbose') do
28
+ Log4r::Outputter['verbose_information'].level = Log4r::DEBUG
29
+ end
30
+ options.on('-h', '--help') do
31
+ puts options
32
+ exit
33
+ end
34
+ options.on('-v', '--version') do
35
+ # TODO: get the version from the gem?
36
+ exit
37
+ end
38
+
39
+ options.separator ''
40
+ options.separator 'Command options:'
41
+
42
+ command_specific_options(options)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,4 @@
1
+ require 'git_workflow/commands/base'
2
+ require 'git_workflow/commands/start'
3
+ require 'git_workflow/commands/finish'
4
+ require 'git_workflow/commands/setup'
@@ -0,0 +1,31 @@
1
+ require 'git_workflow/core_ext'
2
+ require 'git_workflow/logging'
3
+ require 'git_workflow/configuration'
4
+ require 'git_workflow/git'
5
+ require 'git_workflow/story'
6
+ require 'git_workflow/command_line'
7
+ require 'rest_client'
8
+
9
+ module GitWorkflow
10
+ module Commands
11
+ class Base
12
+ include Execution
13
+ include GitWorkflow::Logging
14
+ include GitWorkflow::Git
15
+ include GitWorkflow::CommandLine
16
+
17
+ def initialize(command_line_arguments, &block)
18
+ parse_command_line(command_line_arguments, &block)
19
+
20
+ # Such a hack! This effectively the callbacks to only be loaded after the
21
+ # command line arguments have been processed, injecting them into an already
22
+ # instantiated command. Really should refactor that!
23
+ require 'git_workflow/callbacks'
24
+ end
25
+
26
+ def command_specific_options(options)
27
+ options.separator ' This command has no specific options'
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ require 'git_workflow/commands/base'
2
+ require 'git_workflow/configuration'
3
+
4
+ module GitWorkflow
5
+ module Commands
6
+ class Finish < Base
7
+ def initialize(command_line_arguments)
8
+ super(command_line_arguments) do |remaining_arguments|
9
+ @story_id, @target_branch = remaining_arguments
10
+ @target_branch ||= 'master'
11
+ end
12
+ end
13
+
14
+ def execute
15
+ story_or_current_branch(@story_id) do |story|
16
+ finish(story, @target_branch)
17
+ finish_story_on_pivotal_tracker!(story)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def story_or_current_branch(id, &block)
24
+ story(id || extract_story_from_branch(repository.current_branch), &block)
25
+ end
26
+
27
+ def extract_story_from_branch(branch)
28
+ GitWorkflow::Configuration.instance.local_branch_convention.from(branch)
29
+ end
30
+
31
+ def usage_info(options)
32
+ options.banner = 'Usage: git finish [<PT story number> [<target branch>]]'
33
+ end
34
+ end
35
+ end
36
+ end