diff --git a/Gemfile.lock b/Gemfile.lock index af217b6..7be2ec2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -5,60 +5,84 @@ PATH hashie (~> 2.0.5) jiralicious (~> 0.4.0) octokit (~> 2.0) - pivotal-tracker (~> 0.5.12) thor (~> 0.18.1) + tracker_api (~> 0.2.0) GEM remote: https://rubygems.org/ specs: - addressable (2.3.5) + activemodel (4.2.1) + activesupport (= 4.2.1) + builder (~> 3.1) + activesupport (4.2.1) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + addressable (2.3.8) + axiom-types (0.1.1) + descendants_tracker (~> 0.0.4) + ice_nine (~> 0.11.0) + thread_safe (~> 0.3, >= 0.3.1) builder (3.2.2) + coercible (1.0.0) + descendants_tracker (~> 0.0.1) crack (0.1.8) - fakefs (0.5.0) - faraday (0.9.0) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) + equalizer (0.0.11) + excon (0.45.3) + fakefs (0.6.7) + faraday (0.9.1) multipart-post (>= 1.2, < 3) - happymapper (0.4.1) - libxml-ruby (~> 2.0) + faraday_middleware (0.9.1) + faraday (>= 0.7.4, < 0.10) hashie (2.0.5) - httparty (0.11.0) - multi_json (~> 1.0) + httparty (0.13.5) + json (~> 1.8) multi_xml (>= 0.5.2) - jiralicious (0.4.0) + i18n (0.7.0) + ice_nine (0.11.1) + jiralicious (0.4.3) crack (~> 0.1.8) hashie (>= 1.1) - httparty (>= 0.10, < 0.12.0) + httparty (>= 0.10) json (>= 1.6, < 1.9.0) - json (1.8.1) - libxml-ruby (2.7.0) - mime-types (2.1) - mini_portile (0.5.2) - multi_json (1.8.4) + nokogiri + oauth + json (1.8.2) + mini_portile (0.6.2) + minitest (5.6.1) multi_xml (0.5.5) multipart-post (2.0.0) - nokogiri (1.6.1) - mini_portile (~> 0.5.0) - nokogiri-happymapper (0.5.8) - nokogiri (~> 1.5) - octokit (2.7.1) + nokogiri (1.6.6.2) + mini_portile (~> 0.6.0) + oauth (0.4.7) + octokit (2.7.2) sawyer (~> 0.5.2) - pivotal-tracker (0.5.12) - builder - builder - crack - happymapper (>= 0.3.2) - nokogiri (>= 1.4.3) - nokogiri (>= 1.5.5) - nokogiri-happymapper (>= 0.5.4) - rest-client (~> 1.6.0) - rest-client (~> 1.6.0) - rake (10.1.1) - rest-client (1.6.7) - mime-types (>= 1.16) + rake (10.4.2) rr (1.1.2) - sawyer (0.5.3) + sawyer (0.5.5) addressable (~> 2.3.5) faraday (~> 0.8, < 0.10) thor (0.18.1) + thread_safe (0.3.5) + tracker_api (0.2.9) + activemodel + activesupport + addressable + excon + faraday (~> 0.9.0) + faraday_middleware + virtus + tzinfo (1.2.2) + thread_safe (~> 0.1) + virtus (1.0.5) + axiom-types (~> 0.1) + coercible (~> 1.0) + descendants_tracker (~> 0.0, >= 0.0.3) + equalizer (~> 0.0, >= 0.0.9) PLATFORMS ruby diff --git a/assisted_workflow.gemspec b/assisted_workflow.gemspec index a0bb01a..77106dc 100644 --- a/assisted_workflow.gemspec +++ b/assisted_workflow.gemspec @@ -23,10 +23,10 @@ Gem::Specification.new do |gem| gem.add_development_dependency "fakefs" gem.add_dependency "thor", "~> 0.18.1" - gem.add_dependency "pivotal-tracker", "~> 0.5.12" gem.add_dependency "jiralicious", "~> 0.4.0" gem.add_dependency "octokit", "~> 2.0" gem.add_dependency "hashie", "~> 2.0.5" + gem.add_dependency "tracker_api", "~> 0.2.0" gem.description = < story_onwer_username.story_id.story_name - def create_story_branch(story) + def create_story_branch(story, username) log "creating the feature branch" - branch = branch_name(story) + branch = branch_name(story, username) git "checkout -b #{branch}" # git "push --set-upstream origin #{branch}" end @@ -97,9 +97,9 @@ def system_error? $? != 0 end - def branch_name(story) + def branch_name(story, username) description = story.name.to_s.downcase.gsub(/\W/, "_").slice(0, DESCRIPTION_LIMIT) - [story.other_id, story.id, description].join(".").downcase + [username, story.id, description].join(".").downcase end def not_commited_changes @@ -110,4 +110,4 @@ def check_everything_commited! raise AssistedWorkflow::Error, "git: there are not commited changes" unless not_commited_changes.empty? end end -end \ No newline at end of file +end diff --git a/lib/assisted_workflow/addons/github.rb b/lib/assisted_workflow/addons/github.rb index ba0e8b8..18d27e7 100644 --- a/lib/assisted_workflow/addons/github.rb +++ b/lib/assisted_workflow/addons/github.rb @@ -22,12 +22,8 @@ def description @issue.body.to_s.gsub("\r\n", "\n") end - def other_id - @issue.assignee.login - end - def current_state - other_id + @issue.assignee.login end def labels @@ -118,5 +114,9 @@ def pending_stories(options = {}) def valid? @client.user_authenticated? end + + def username + @username + end end -end \ No newline at end of file +end diff --git a/lib/assisted_workflow/addons/jira.rb b/lib/assisted_workflow/addons/jira.rb index 72b6aa9..58bb517 100644 --- a/lib/assisted_workflow/addons/jira.rb +++ b/lib/assisted_workflow/addons/jira.rb @@ -21,10 +21,6 @@ def name @issue.summary end - def other_id - @issue.fields.current["assignee"]["name"].split.join - end - def current_state @issue.fields.current["status"]["name"] end @@ -102,4 +98,4 @@ def move_story!(story, status) end end end -end \ No newline at end of file +end diff --git a/lib/assisted_workflow/addons/pivotal.rb b/lib/assisted_workflow/addons/pivotal.rb index 444c751..613847b 100644 --- a/lib/assisted_workflow/addons/pivotal.rb +++ b/lib/assisted_workflow/addons/pivotal.rb @@ -1,6 +1,6 @@ require "assisted_workflow/exceptions" require "assisted_workflow/addons/base" -require 'pivotal_tracker' +require "tracker_api" # wrapper class to pivotal api client module AssistedWorkflow::Addons @@ -10,9 +10,9 @@ class Pivotal < Base def initialize(output, options = {}) super - PivotalTracker::Client.token = options["token"] + @client = TrackerApi::Client.new(token: options["token"]) begin - @project = PivotalTracker::Project.find(options["project_id"]) + @project = @client.project(options["project_id"]) rescue raise AssistedWorkflow::Error, "pivotal project #{options["project_id"]} not found." end @@ -23,22 +23,21 @@ def initialize(output, options = {}) def find_story(story_id) if story_id.to_i > 0 log "loading story ##{story_id}" - story = @project.stories.find(story_id) - story.other_id = @username || @fullname - story.other_id = story.other_id.to_s.downcase.split.join - story + @project.story(story_id) end end def start_story(story, options = {}) log "starting story ##{story.id}" - update_story! story, options.merge(:current_state => "started") + options.delete(:estimate) if options[:estimate].nil? + update_story!(story, options.merge(:current_state => "started")) end - + def finish_story(story, options = {}) log "finishing story ##{story.id}" - if update_story! story, :current_state => finished_state(story) - story.notes.create(:text => options[:note]) if options[:note] + saved = update_story! story, :current_state => finished_state(story) + if saved && options[:note] + add_comment_to_story(story, options[:note]) end end @@ -46,14 +45,24 @@ def pending_stories(options = {}) log "loading pending stories" states = ["unstarted"] states << "started" if options[:include_started] - @project.stories.all(:state => states, :owned_by => @fullname, :limit => 5) + filter_str = "state:#{states.join(',')} owned_by:#{@client.me.id}" + @project.stories(:filter => filter_str, :limit => 5) end def valid? !@project.nil? end - + private + + def add_comment_to_story(story, text) + url = "/projects/#{story.project_id}/stories/#{story.id}/comments" + @client.post(url, params: {:text => text}) + rescue TrackerApi::Error => e + body = e.response[:body] + msg = body["possible_fix"] || body["general_problem"] + raise AssistedWorkflow::Error, msg + end def finished_state(story) if story.story_type == "chore" @@ -65,10 +74,16 @@ def finished_state(story) def update_story!(story, attributes) if story - story.update(attributes) - raise AssistedWorkflow::Error, story.errors.first.to_s if story.errors.any? + begin + story.attributes = attributes + story.save + rescue TrackerApi::Error => e + body = e.response[:body] + msg = body["possible_fix"] || body["general_problem"] + raise AssistedWorkflow::Error, msg + end true end end end -end \ No newline at end of file +end diff --git a/lib/assisted_workflow/cli.rb b/lib/assisted_workflow/cli.rb index b9e43cc..8fe0756 100644 --- a/lib/assisted_workflow/cli.rb +++ b/lib/assisted_workflow/cli.rb @@ -45,7 +45,7 @@ def start(story_id=nil) else tracker.start_story(story, :estimate => options[:estimate]) out.print_story story - git.create_story_branch(story) + git.create_story_branch(story, github.username) out.next_command "after commiting your changes, submit a pull request using:", "$ aw submit" end end @@ -151,4 +151,4 @@ def awfile end end end -end \ No newline at end of file +end diff --git a/spec/assisted_workflow/addons/git_spec.rb b/spec/assisted_workflow/addons/git_spec.rb index 2e58b7d..8f7a1f5 100644 --- a/spec/assisted_workflow/addons/git_spec.rb +++ b/spec/assisted_workflow/addons/git_spec.rb @@ -5,18 +5,18 @@ before do @git = AssistedWorkflow::Addons::Git.new(nil, :silent => true) stub(@git).system_error?{ false } - stub(@git).system("git rev-parse --abbrev-ref HEAD"){ "flavio.00001.new_feature"} + stub(@git).system("git rev-parse --abbrev-ref HEAD"){ "flavio.1234.new_feature"} end it "creates a story branch" do - mock(@git).system("git checkout -b flavio.00001.new_feature") - @git.create_story_branch(story) + mock(@git).system("git checkout -b flavio.1234.new_feature") + @git.create_story_branch(story, "flavio") end it "raises a git error when git command does not exit with success" do mock(@git).system_error?{ true } - mock(@git).system("git checkout -b flavio.00001.new_feature") - proc { @git.create_story_branch(story) }.must_raise AssistedWorkflow::Addons::GitError, "git command error" + mock(@git).system("git checkout -b flavio.1234.new_feature") + proc { @git.create_story_branch(story, "flavio") }.must_raise AssistedWorkflow::Addons::GitError, "git command error" end @@ -24,9 +24,9 @@ mock(@git).system("git status --porcelain"){ "" } mock(@git).system("git checkout master") mock(@git).system("git pull --rebase") - mock(@git).system("git checkout flavio.00001.new_feature") + mock(@git).system("git checkout flavio.1234.new_feature") mock(@git).system("git rebase master") - mock(@git).system("git push -u -f origin flavio.00001.new_feature") + mock(@git).system("git push -u -f origin flavio.1234.new_feature") @git.rebase_and_push end @@ -38,11 +38,11 @@ end it "returns the story_id from branch name" do - @git.current_story_id.must_equal "00001" + @git.current_story_id.must_equal "1234" end it "return the current branch name" do - @git.current_branch.must_equal "flavio.00001.new_feature" + @git.current_branch.must_equal "flavio.1234.new_feature" end it "returns the repository name assigned to origin" do @@ -54,33 +54,47 @@ before do mock(@git).system("git status --porcelain"){ "" } - mock(@git).system("git checkout flavio.00001.new_feature") + mock(@git).system("git checkout flavio.1234.new_feature") mock(@git).system("git checkout master") mock(@git).system("git pull --rebase") end it "returns true if current branch is merged into master" do - mock(@git).system("git branch --merged"){ "flavio.00001.new_feature" } + mock(@git).system("git branch --merged"){ "flavio.1234.new_feature" } @git.check_merged!.must_equal true end it "returns false if current branch is not merged into master" do - mock(@git).system("git branch --merged"){ "flavio.00002.other_feature" } + mock(@git).system("git branch --merged"){ "flavio.1234.other_feature" } proc { @git.check_merged! }.must_raise AssistedWorkflow::Error, "this branch is not merged into master" end end it "removes current branch and its remote version" do - mock(@git).system("git push origin :flavio.00001.new_feature") + mock(@git).system("git push origin :flavio.1234.new_feature") mock(@git).system("git checkout master") - mock(@git).system("git branch -D flavio.00001.new_feature") + mock(@git).system("git branch -D flavio.1234.new_feature") @git.remove_branch end private #================================================================== def story - @story ||= PivotalTracker::Story.new(:id => "00001", :name => "New Feature", :description => "Feature description", :other_id => "flavio") + # stubs + @client = TrackerApi::Client.new(token: "mypivotaltoken") + stub(TrackerApi::Client).new{ @client } + + any_instance_of(TrackerApi::Resources::Story) do |klass| + stub(klass).comments { [] } + stub(klass).tasks { [] } + end + @story ||= TrackerApi::Resources::Story.new(:id => "1234", + :name => "New Feature", + :description => "Feature description", + :client => @client) + stub(@story).save {} + + @story end -end \ No newline at end of file +end diff --git a/spec/assisted_workflow/addons/github_spec.rb b/spec/assisted_workflow/addons/github_spec.rb index 878f130..8dcff6a 100644 --- a/spec/assisted_workflow/addons/github_spec.rb +++ b/spec/assisted_workflow/addons/github_spec.rb @@ -1,5 +1,4 @@ require 'spec_helper' -require 'pivotal_tracker' require 'assisted_workflow/addons/github' describe AssistedWorkflow::Addons::Github do @@ -25,25 +24,25 @@ end it "creates a new valid pull request from a pivotal story" do - mock(@client).create_pull_request("fakeuser/fakerepo", "master", "fakeuser.00001.new_feature", "[#00001] New Feature", "Feature description"){ pull_request } + mock(@client).create_pull_request("fakeuser/fakerepo", "master", "fakeuser.1234.new_feature", "[#1234] New Feature", "Feature description"){ pull_request } @github.create_pull_request( - "fakeuser.00001.new_feature", story + "fakeuser.1234.new_feature", story ).must_match /fakeuser\/fakerepo\/pull\/1/ end it "creates a new valid pull request from a github story" do - mock(@client).create_pull_request_for_issue("fakeuser/fakerepo", "master", "fakeuser.00001.new_feature", 10){ pull_request } + mock(@client).create_pull_request_for_issue("fakeuser/fakerepo", "master", "fakeuser.1234.new_feature", 10){ pull_request } @github.create_pull_request( - "fakeuser.00001.new_feature", + "fakeuser.1234.new_feature", AssistedWorkflow::Addons::GithubStory.new(gh_issue(:number => 10)) ).must_match /fakeuser\/fakerepo\/pull\/1/ end it "raises on creating an invalid pull request" do - mock(@client).create_pull_request("fakeuser/fakerepo", "master", "fakeuser.00001.new_feature", "[#00001] New Feature", "Feature description"){ nil } + mock(@client).create_pull_request("fakeuser/fakerepo", "master", "fakeuser.1234.new_feature", "[#1234] New Feature", "Feature description"){ nil } proc { @github.create_pull_request( - "fakeuser.00001.new_feature", story + "fakeuser.1234.new_feature", story ) }.must_raise AssistedWorkflow::Error, "error on submiting the pull request" end @@ -55,7 +54,6 @@ story = @github.find_story("10") story.id.must_equal "10" - story.other_id.must_match /fakeuser/ end it "returns pending stories" do @@ -82,7 +80,19 @@ private #================================================================== def story - @story ||= PivotalTracker::Story.new(:id => "00001", :name => "New Feature", :description => "Feature description") + # stubs + @client = TrackerApi::Client.new(token: "mypivotaltoken") + stub(TrackerApi::Client).new{ @client } + + any_instance_of(TrackerApi::Resources::Story) do |klass| + stub(klass).comments { [] } + stub(klass).tasks { [] } + end + @story ||= TrackerApi::Resources::Story.new(:id => "1234", :name => "New Feature", + :description => "Feature description", :client => @client) + stub(@story).save {} + + @story end def agent_stub @@ -108,4 +118,4 @@ def client_stub stub(client).user_authenticated?{ true } client end -end \ No newline at end of file +end diff --git a/spec/assisted_workflow/addons/jira_spec.rb b/spec/assisted_workflow/addons/jira_spec.rb index 284b689..44f7cb3 100644 --- a/spec/assisted_workflow/addons/jira_spec.rb +++ b/spec/assisted_workflow/addons/jira_spec.rb @@ -74,7 +74,6 @@ story = @jira.find_story("aw-01") story.id.must_equal "aw-01" - story.other_id.must_match /jirauser/ end it "returns pending stories" do @@ -134,4 +133,4 @@ def mock_transition(story_id, status_id) mock(Jiralicious::Issue).get_transitions(url){ response } mock(Jiralicious::Issue).transition(url, {"transition" => status_id}) end -end \ No newline at end of file +end diff --git a/spec/assisted_workflow/addons/pivotal_spec.rb b/spec/assisted_workflow/addons/pivotal_spec.rb index 2b5ae3d..cc485af 100644 --- a/spec/assisted_workflow/addons/pivotal_spec.rb +++ b/spec/assisted_workflow/addons/pivotal_spec.rb @@ -11,9 +11,11 @@ "fullname" => "Flavio Granero" } # stubs - @project = PivotalTracker::Project.new(:id => "1") - stub(PivotalTracker::Project).find(@configuration["project_id"]){ @project } - + @client = TrackerApi::Client.new(token: "mypivotaltoken") + stub(TrackerApi::Client).new{ @client } + @project = TrackerApi::Resources::Project.new(client: @client, id: 1) + stub(@client).project(@configuration["project_id"]){ @project } + @pivotal = AssistedWorkflow::Addons::Pivotal.new(nil, @configuration) end @@ -49,23 +51,23 @@ end it "finds a story by id" do - mock(PivotalTracker::Story).find("100001", @project.id) do |story_id, project_id| - story_stub(:id => story_id, :project_id => project_id) + mock(@project).story("100001") do |story_id| + story_stub(:id => story_id, :project_id => @project.id) end story = @pivotal.find_story("100001") - story.id.must_equal "100001" - story.other_id.must_match /flavio/ + story.id.must_equal 100001 end it "returns pending stories" do - mock(PivotalTracker::Story).all(@project, :state => ["unstarted", "started"], :owned_by => @configuration["fullname"], :limit => 5) do |project| + stub(@project).stories do [ - story_stub(:id => "100001", :project_id => project.id), - story_stub(:id => "100002", :project_id => project.id) + story_stub(:id => "100001", :project_id => @project.id), + story_stub(:id => "100002", :project_id => @project.id) ] end - + stub(@client).me{ TrackerApi::Resources::Me.new } + stories = @pivotal.pending_stories(:include_started => true) stories.size.must_equal 2 end @@ -74,30 +76,29 @@ story = story_stub(:id => "100001", :project_id => @project.id) @pivotal.start_story(story, :estimate => "3") story.current_state.must_match /started/ - story.estimate.must_equal "3" - story.errors.must_be_empty + story.estimate.must_equal 3 end it "finishes a story" do story = story_stub(:id => "100001", :project_id => @project.id) - any_instance_of(PivotalTracker::Note) do |klass| - stub(klass).create{ true } - end + #stub post to create comment + url = "/projects/#{story.project_id}/stories/#{story.id}/comments" + stub(@client).post(url, :params => {:text=>"pull_request_url"}){} @pivotal.finish_story(story, :note => "pull_request_url") story.current_state.must_match /finished/ - story.errors.must_be_empty end private #=================================================================== def story_stub(attributes = {}) - story = PivotalTracker::Story.new(attributes) - stub(story).update do |attrs| - story.send(:update_attributes, attrs) - story + any_instance_of(TrackerApi::Resources::Story) do |klass| + stub(klass).comments { [] } + stub(klass).tasks { [] } end - + story = TrackerApi::Resources::Story.new(attributes.merge(client: @client)) + stub(story).save {} + story end -end \ No newline at end of file +end