From 362b5d30bf97c56cb9ca7618650b5ace93cb8f78 Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Fri, 15 Nov 2013 14:30:32 -0500 Subject: [PATCH 01/10] Respond to /repos.xml with CC XML See #47 --- lib/travis/api/app/responders/xml.rb | 58 ++++++++++-------------- spec/integration/v2/repositories_spec.rb | 4 +- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/lib/travis/api/app/responders/xml.rb b/lib/travis/api/app/responders/xml.rb index 423fca46..64fb85d2 100644 --- a/lib/travis/api/app/responders/xml.rb +++ b/lib/travis/api/app/responders/xml.rb @@ -1,6 +1,22 @@ module Travis::Api::App::Responders +# This XML responder is used if the resource is a Repository, or a collection +# of Repositories. +# It returns XML data conforming to Multiple Project Summary Reporting Standard, +# as explained in http://confluence.public.thoughtworks.org/display/CI/Multiple+Project+Summary+Reporting+Standard class Xml < Base - TEMPLATE = File.read(__FILE__).split("__END__").last.strip + TEMPLATE_ERB = ERB.new <<-EOF +<Projects> +<% @resource.each do |r| %> + <Project + name="<%= r.slug %>" + activity="<%= ACTIVITY[r.last_build.state.to_sym] || ACTIVITY[:default] %>" + lastBuildStatus="<%= STATUS[r.last_build.state.to_sym] || STATUS[:default] %>" + lastBuildLabel="<%= r.last_build.try(:number) %>" + lastBuildTime="<%= r.last_build.finished_at.try(:strftime, '%Y-%m-%dT%H:%M:%S.%L%z') %>" + webUrl="<%= File.join("https://", Travis.config.client_domain, r.slug) %>" /> +<% end %> +</Projects> + EOF STATUS = { default: 'Unknown', @@ -16,13 +32,14 @@ module Travis::Api::App::Responders } def apply? - super && resource.is_a?(Repository) && last_build + super && (single_repo?(resource) || repo_collection?(resource)) end def apply super - TEMPLATE % data + @resource = resource.is_a?(Repository) ? [resource] : resource + TEMPLATE_ERB.result(binding) end private @@ -31,39 +48,12 @@ module Travis::Api::App::Responders 'application/xml;charset=utf-8' end - def data - { - name: resource.slug, - url: File.join("https://", Travis.config.client_domain, resource.slug), - activity: activity, - label: last_build.try(:number), - status: status, - time: last_build.finished_at.try(:strftime, '%Y-%m-%dT%H:%M:%S.%L%z') - } + def single_repo?(resource) + resource.is_a?(Repository) && (@last_build || resource.last_build) end - def status - STATUS[last_build.state.to_sym] || STATUS[:default] - end - - def activity - ACTIVITY[last_build.state.to_sym] || ACTIVITY[:default] - end - - def last_build - @last_build ||= resource.last_build + def repo_collection?(resource) + resource.is_a?(ActiveRecord::Relation) && resource.first.is_a?(Repository) end end end - -__END__ - -<Projects> - <Project - name="%{name}" - activity="%{activity}" - lastBuildStatus="%{status}" - lastBuildLabel="%{label}" - lastBuildTime="%{time}" - webUrl="%{url}" /> -</Projects> diff --git a/spec/integration/v2/repositories_spec.rb b/spec/integration/v2/repositories_spec.rb index fcf89a1f..77cc42b5 100644 --- a/spec/integration/v2/repositories_spec.rb +++ b/spec/integration/v2/repositories_spec.rb @@ -87,9 +87,9 @@ describe 'Repos' do response.should deliver_cc_xml_for(Repository.by_slug('svenfuchs/minimal').first) end - it 'does not respond with cc.xml for /repos list' do + it 'respond with cc.xml for /repos list' do response = get '/repos', {}, 'HTTP_ACCEPT' => 'application/xml; version=2' - response.status.should == 406 + response.should deliver_cc_xml_for(Repository.timeline) end it 'responds with 404 when repo can\'t be found and format is png' do From 0f0ee4778fbbc46766bc7903fd029b5a62458977 Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Mon, 18 Nov 2013 16:55:23 -0500 Subject: [PATCH 02/10] Fix up matcher to account for change in data structure Aggregate CC XML would have a different output --- spec/support/matchers.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index 798c9709..2ab14d83 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -54,7 +54,7 @@ RSpec::Matchers.define :deliver_result_image_for do |name| end end -RSpec::Matchers.define :deliver_cc_xml_for do |repo| +RSpec::Matchers.define :deliver_cc_xml_for do |obj| match do |response| body = response.body @@ -62,6 +62,9 @@ RSpec::Matchers.define :deliver_cc_xml_for do |repo| "expected #{body} to be a valid cc.xml" end + # obj can be a collection of Repositories + repo = obj.is_a?(ActiveRecord::Relation) ? obj.first : obj + body.include?('<Projects>') && body.include?(%(name="#{repo.slug}")) && body.include?("https://www.example.com/#{repo.slug}") end end From 0fe9e6da907c928511e54d925853a61072588ee8 Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Mon, 18 Nov 2013 18:21:32 -0500 Subject: [PATCH 03/10] Remove superfluous ivar --- lib/travis/api/app/responders/xml.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/app/responders/xml.rb b/lib/travis/api/app/responders/xml.rb index 64fb85d2..f5ae39ae 100644 --- a/lib/travis/api/app/responders/xml.rb +++ b/lib/travis/api/app/responders/xml.rb @@ -49,7 +49,7 @@ module Travis::Api::App::Responders end def single_repo?(resource) - resource.is_a?(Repository) && (@last_build || resource.last_build) + resource.is_a?(Repository) && resource.last_build end def repo_collection?(resource) From 67decdfc6a6a1e98a3230dc4c8470418273fa475 Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Tue, 19 Nov 2013 01:19:21 -0500 Subject: [PATCH 04/10] Cast ActiveRecord::Relation into an Array --- lib/travis/api/app/responders/xml.rb | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/travis/api/app/responders/xml.rb b/lib/travis/api/app/responders/xml.rb index f5ae39ae..5c28671f 100644 --- a/lib/travis/api/app/responders/xml.rb +++ b/lib/travis/api/app/responders/xml.rb @@ -32,13 +32,13 @@ module Travis::Api::App::Responders } def apply? - super && (single_repo?(resource) || repo_collection?(resource)) + @resource = Array(resource) + super && @resource.first.is_a?(Repository) end def apply super - @resource = resource.is_a?(Repository) ? [resource] : resource TEMPLATE_ERB.result(binding) end @@ -47,13 +47,5 @@ module Travis::Api::App::Responders def content_type 'application/xml;charset=utf-8' end - - def single_repo?(resource) - resource.is_a?(Repository) && resource.last_build - end - - def repo_collection?(resource) - resource.is_a?(ActiveRecord::Relation) && resource.first.is_a?(Repository) - end end end From 1727b5328efb7f93b9a607af38b614846c8b0983 Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Tue, 19 Nov 2013 01:21:14 -0500 Subject: [PATCH 05/10] Indent comment to match logic level --- lib/travis/api/app/responders/xml.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/travis/api/app/responders/xml.rb b/lib/travis/api/app/responders/xml.rb index 5c28671f..26534513 100644 --- a/lib/travis/api/app/responders/xml.rb +++ b/lib/travis/api/app/responders/xml.rb @@ -1,8 +1,8 @@ module Travis::Api::App::Responders -# This XML responder is used if the resource is a Repository, or a collection -# of Repositories. -# It returns XML data conforming to Multiple Project Summary Reporting Standard, -# as explained in http://confluence.public.thoughtworks.org/display/CI/Multiple+Project+Summary+Reporting+Standard + # This XML responder is used if the resource is a Repository, or a collection + # of Repositories. + # It returns XML data conforming to Multiple Project Summary Reporting Standard, + # as explained in http://confluence.public.thoughtworks.org/display/CI/Multiple+Project+Summary+Reporting+Standard class Xml < Base TEMPLATE_ERB = ERB.new <<-EOF <Projects> From ff37525a5cf53ef0c33fc47c2908c24e776ba73a Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Tue, 19 Nov 2013 01:23:47 -0500 Subject: [PATCH 06/10] Cast in matcher as well To match the previous change with the responder. --- spec/support/matchers.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/support/matchers.rb b/spec/support/matchers.rb index 2ab14d83..883a49f2 100644 --- a/spec/support/matchers.rb +++ b/spec/support/matchers.rb @@ -62,8 +62,7 @@ RSpec::Matchers.define :deliver_cc_xml_for do |obj| "expected #{body} to be a valid cc.xml" end - # obj can be a collection of Repositories - repo = obj.is_a?(ActiveRecord::Relation) ? obj.first : obj + repo = Array(obj).first body.include?('<Projects>') && body.include?(%(name="#{repo.slug}")) && body.include?("https://www.example.com/#{repo.slug}") end From d31a29e54d62799a278f32e0a5c8fba92da59bad Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Sun, 1 Dec 2013 20:42:46 -0500 Subject: [PATCH 07/10] Fix grammar in spec description --- spec/integration/v2/repositories_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/integration/v2/repositories_spec.rb b/spec/integration/v2/repositories_spec.rb index 77cc42b5..ba58957c 100644 --- a/spec/integration/v2/repositories_spec.rb +++ b/spec/integration/v2/repositories_spec.rb @@ -87,7 +87,7 @@ describe 'Repos' do response.should deliver_cc_xml_for(Repository.by_slug('svenfuchs/minimal').first) end - it 'respond with cc.xml for /repos list' do + it 'responds with cc.xml for /repos list' do response = get '/repos', {}, 'HTTP_ACCEPT' => 'application/xml; version=2' response.should deliver_cc_xml_for(Repository.timeline) end From ac106488c705202630eb4a2d142160e34f1774dd Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Sun, 1 Dec 2013 20:44:39 -0500 Subject: [PATCH 08/10] Eschew questionable use of `File.join` For constructing a URL, `File.join` is inappropriate. --- lib/travis/api/app/responders/xml.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/app/responders/xml.rb b/lib/travis/api/app/responders/xml.rb index 26534513..25b8b62c 100644 --- a/lib/travis/api/app/responders/xml.rb +++ b/lib/travis/api/app/responders/xml.rb @@ -13,7 +13,7 @@ module Travis::Api::App::Responders lastBuildStatus="<%= STATUS[r.last_build.state.to_sym] || STATUS[:default] %>" lastBuildLabel="<%= r.last_build.try(:number) %>" lastBuildTime="<%= r.last_build.finished_at.try(:strftime, '%Y-%m-%dT%H:%M:%S.%L%z') %>" - webUrl="<%= File.join("https://", Travis.config.client_domain, r.slug) %>" /> + webUrl="https://<%= Travis.config.client_domain %>/<%= r.slug %>" <% end %> </Projects> EOF From 1eb8ce5a1d2b939a34a5400d400bcb4c264268cb Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Sun, 1 Dec 2013 22:01:12 -0500 Subject: [PATCH 09/10] Add missing closing </Project> tag --- lib/travis/api/app/responders/xml.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/travis/api/app/responders/xml.rb b/lib/travis/api/app/responders/xml.rb index 25b8b62c..0ec6e0d8 100644 --- a/lib/travis/api/app/responders/xml.rb +++ b/lib/travis/api/app/responders/xml.rb @@ -14,6 +14,7 @@ module Travis::Api::App::Responders lastBuildLabel="<%= r.last_build.try(:number) %>" lastBuildTime="<%= r.last_build.finished_at.try(:strftime, '%Y-%m-%dT%H:%M:%S.%L%z') %>" webUrl="https://<%= Travis.config.client_domain %>/<%= r.slug %>" + </Project> <% end %> </Projects> EOF From ea05ef6845624d61d215b68574fabd95a77a0ec6 Mon Sep 17 00:00:00 2001 From: Hiro Asari <asari.ruby@gmail.com> Date: Sun, 1 Dec 2013 22:22:00 -0500 Subject: [PATCH 10/10] Fix closing tag --- lib/travis/api/app/responders/xml.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/travis/api/app/responders/xml.rb b/lib/travis/api/app/responders/xml.rb index 0ec6e0d8..410dec84 100644 --- a/lib/travis/api/app/responders/xml.rb +++ b/lib/travis/api/app/responders/xml.rb @@ -13,8 +13,7 @@ module Travis::Api::App::Responders lastBuildStatus="<%= STATUS[r.last_build.state.to_sym] || STATUS[:default] %>" lastBuildLabel="<%= r.last_build.try(:number) %>" lastBuildTime="<%= r.last_build.finished_at.try(:strftime, '%Y-%m-%dT%H:%M:%S.%L%z') %>" - webUrl="https://<%= Travis.config.client_domain %>/<%= r.slug %>" - </Project> + webUrl="https://<%= Travis.config.client_domain %>/<%= r.slug %>" /> <% end %> </Projects> EOF