go_cd_feed 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.rvmrc +1 -0
  4. data/.zeroci.yml +1 -0
  5. data/Gemfile +4 -0
  6. data/Gemfile.lock +32 -0
  7. data/README.textile +36 -0
  8. data/Rakefile +39 -0
  9. data/bin/go_api_client +3 -0
  10. data/go_api_client.gemspec +27 -0
  11. data/lib/go_api_client.rb +60 -0
  12. data/lib/go_api_client/atom.rb +4 -0
  13. data/lib/go_api_client/atom/author.rb +42 -0
  14. data/lib/go_api_client/atom/entry.rb +34 -0
  15. data/lib/go_api_client/atom/feed.rb +44 -0
  16. data/lib/go_api_client/atom/feed_page.rb +49 -0
  17. data/lib/go_api_client/commit.rb +30 -0
  18. data/lib/go_api_client/helpers.rb +1 -0
  19. data/lib/go_api_client/helpers/simple_attribute_support.rb +11 -0
  20. data/lib/go_api_client/http_fetcher.rb +43 -0
  21. data/lib/go_api_client/job.rb +64 -0
  22. data/lib/go_api_client/pipeline.rb +49 -0
  23. data/lib/go_api_client/stage.rb +57 -0
  24. data/lib/go_api_client/user.rb +36 -0
  25. data/lib/go_api_client/version.rb +9 -0
  26. data/ssh_keys/git-ci.zeroci.com +27 -0
  27. data/ssh_keys/git-ci.zeroci.com.pub +1 -0
  28. data/ssh_keys/git-ssh +3 -0
  29. data/test/fixtures/building/job_1.xml +41 -0
  30. data/test/fixtures/building/job_2.xml +43 -0
  31. data/test/fixtures/building/job_3.xml +40 -0
  32. data/test/fixtures/building/job_4.xml +40 -0
  33. data/test/fixtures/building/pipeline_1.xml +45 -0
  34. data/test/fixtures/building/pipeline_2.xml +39 -0
  35. data/test/fixtures/building/pipeline_3.xml +71 -0
  36. data/test/fixtures/building/stages.xml +180 -0
  37. data/test/fixtures/building/stages_1.xml +16 -0
  38. data/test/fixtures/building/stages_2.xml +16 -0
  39. data/test/fixtures/building/stages_3.xml +16 -0
  40. data/test/fixtures/building/stages_4.xml +16 -0
  41. data/test/fixtures/job_1_console.log.txt +82 -0
  42. data/test/fixtures/job_2_console.log.txt +82 -0
  43. data/test/fixtures/jobs_1.xml +29 -0
  44. data/test/fixtures/jobs_2.xml +29 -0
  45. data/test/fixtures/jobs_with_no_properties.xml +42 -0
  46. data/test/fixtures/ordering/go/api/jobs/1.xml +29 -0
  47. data/test/fixtures/ordering/go/api/jobs/10.xml +31 -0
  48. data/test/fixtures/ordering/go/api/jobs/2.xml +29 -0
  49. data/test/fixtures/ordering/go/api/jobs/3.xml +29 -0
  50. data/test/fixtures/ordering/go/api/jobs/4.xml +29 -0
  51. data/test/fixtures/ordering/go/api/jobs/5.xml +29 -0
  52. data/test/fixtures/ordering/go/api/jobs/6.xml +29 -0
  53. data/test/fixtures/ordering/go/api/jobs/7.xml +31 -0
  54. data/test/fixtures/ordering/go/api/jobs/8.xml +31 -0
  55. data/test/fixtures/ordering/go/api/jobs/9.xml +31 -0
  56. data/test/fixtures/ordering/go/api/pipelines/defaultPipeline/1.xml +31 -0
  57. data/test/fixtures/ordering/go/api/pipelines/defaultPipeline/2.xml +26 -0
  58. data/test/fixtures/ordering/go/api/pipelines/defaultPipeline/3.xml +26 -0
  59. data/test/fixtures/ordering/go/api/pipelines/defaultPipeline/4.xml +27 -0
  60. data/test/fixtures/ordering/go/api/pipelines/defaultPipeline/5.xml +33 -0
  61. data/test/fixtures/ordering/go/api/pipelines/defaultPipeline/stages.xml +255 -0
  62. data/test/fixtures/ordering/go/api/stages/1.xml +14 -0
  63. data/test/fixtures/ordering/go/api/stages/10.xml +14 -0
  64. data/test/fixtures/ordering/go/api/stages/2.xml +14 -0
  65. data/test/fixtures/ordering/go/api/stages/3.xml +14 -0
  66. data/test/fixtures/ordering/go/api/stages/4.xml +14 -0
  67. data/test/fixtures/ordering/go/api/stages/5.xml +14 -0
  68. data/test/fixtures/ordering/go/api/stages/6.xml +14 -0
  69. data/test/fixtures/ordering/go/api/stages/7.xml +14 -0
  70. data/test/fixtures/ordering/go/api/stages/8.xml +14 -0
  71. data/test/fixtures/ordering/go/api/stages/9.xml +14 -0
  72. data/test/fixtures/pagination/stages.xml +636 -0
  73. data/test/fixtures/pagination/stages_before_7916973.xml +615 -0
  74. data/test/fixtures/pagination/stages_before_7959831.xml +615 -0
  75. data/test/fixtures/pipelines_1.xml +32 -0
  76. data/test/fixtures/stages.xml +63 -0
  77. data/test/fixtures/stages_1.xml +14 -0
  78. data/test/fixtures/stages_2.xml +14 -0
  79. data/test/fixtures/stages_empty.xml +9 -0
  80. data/test/go_api_client/atom/author_test.rb +27 -0
  81. data/test/go_api_client/atom/entry_test.rb +27 -0
  82. data/test/go_api_client/atom/feed_page_test.rb +41 -0
  83. data/test/go_api_client/atom/feed_test.rb +25 -0
  84. data/test/go_api_client/building_test.rb +38 -0
  85. data/test/go_api_client/commit_test.rb +38 -0
  86. data/test/go_api_client/job_test.rb +42 -0
  87. data/test/go_api_client/pipeline_test.rb +34 -0
  88. data/test/go_api_client/stage_test.rb +75 -0
  89. data/test/go_api_client/user_test.rb +27 -0
  90. data/test/test_helper.rb +31 -0
  91. metadata +272 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 086892ef807a155548eb78d3d29957a83a0dcaad
4
+ data.tar.gz: ad11e247b17715789ca4c6d2c89b70e2620a7bb4
5
+ SHA512:
6
+ metadata.gz: 7a1d5677978816d8ce71f4175facb10b6e5f4bc52ce3484031e0bd241829882e44117f15b4fc7b95bf62ecc82844bf09df0ef7c78ec5b8beda9b3c8819220725
7
+ data.tar.gz: 06fe1c81e5193525e59e3b677021a31ab1636ac4dcc51efcfadddd48d2e2035892db950f8f3be534748e9c4e5611c1c5f14046d4aaf5aaa3e918f82a9fa9010c
@@ -0,0 +1,8 @@
1
+ coverage
2
+ .bundle
3
+ bundle/
4
+ pkg/*
5
+ /tmp/
6
+ /vendor/ruby
7
+ .idea/*
8
+ TAGS
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.9.2-p290@go-api-client
@@ -0,0 +1 @@
1
+ post_build: curl -fu go-saas-admin:h0nkyt0nk -X POST http://ci.zeroci.com:8153/go/api/pipelines/Go-API-Client/schedule -d "materials[go-api-client]=$GO_REVISION"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in go_api_client.gemspec
4
+ gemspec
@@ -0,0 +1,32 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ go_api_client (0.2.0)
5
+ nokogiri
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ addressable (2.2.7)
11
+ crack (0.3.1)
12
+ multi_json (1.2.0)
13
+ nokogiri (1.5.2)
14
+ rake (0.9.2.2)
15
+ simplecov (0.6.1)
16
+ multi_json (~> 1.0)
17
+ simplecov-html (~> 0.5.3)
18
+ simplecov-html (0.5.3)
19
+ test-unit (2.4.8)
20
+ webmock (1.8.0)
21
+ addressable (>= 2.2.7)
22
+ crack (>= 0.1.7)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ go_api_client!
29
+ rake
30
+ simplecov
31
+ test-unit
32
+ webmock
@@ -0,0 +1,36 @@
1
+ h2. Go API Client Gem
2
+
3
+ This gem provides API access to the go api.
4
+
5
+ h2. Installation
6
+
7
+ <pre>$ [sudo] gem install go_api_client</pre>
8
+
9
+ h2. Usage
10
+
11
+ h2. License
12
+
13
+ Go API Client Gem is MIT Licensed
14
+
15
+ The MIT License
16
+
17
+ Copyright (c) 2012 ThoughtWorks, Inc. (http://thoughtworks.com)
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ of this software and associated documentation files (the "Software"), to deal
21
+ in the Software without restriction, including without limitation the rights
22
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ copies of the Software, and to permit persons to whom the Software is
24
+ furnished to do so, subject to the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be included in
27
+ all copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
35
+ THE SOFTWARE.
36
+
@@ -0,0 +1,39 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ desc "Run all tests"
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.test_files = FileList['test/**/*test.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ desc "upload the gem to artifact repository"
12
+ task :upload do
13
+ go_artifact_repository_parent = ENV['ARTIFACT_REPO_PARENT'] || Dir.home
14
+ go_artifact_repository_name = ENV['ARTIFACT_REPO_NAME'] || "go-api-client-artifact"
15
+ go_artifact_repository_path = go_artifact_repository_parent + "/" + go_artifact_repository_name
16
+
17
+ ssh_key_path = File.expand_path("../ssh_keys/git-ci.zeroci.com",__FILE__)
18
+ git_ssh_path = File.expand_path("../ssh_keys/git-ssh",__FILE__)
19
+
20
+ artifact_repository_host = "ec2-184-72-152-107.compute-1.amazonaws.com"
21
+ artifact_repository_user = "git"
22
+
23
+ commit_msg = "New Artifact"
24
+ sh "chmod 0400 #{ssh_key_path}"
25
+ if !File.exists?(go_artifact_repository_path)
26
+ clone_cmd = "GIT_SSH=#{git_ssh_path} git clone #{artifact_repository_user}@#{artifact_repository_host}:#{go_artifact_repository_name}"
27
+ sh "cd #{go_artifact_repository_parent} && #{clone_cmd}"
28
+ end
29
+
30
+ sh "bundle exec rake build"
31
+ sh "cp pkg/* #{go_artifact_repository_path}"
32
+ sh "cd #{go_artifact_repository_path} && git add ."
33
+ sh "cd #{go_artifact_repository_path} && git commit -m\'#{commit_msg}\'"
34
+ push_cmd = "GIT_SSH=#{git_ssh_path} git push origin master"
35
+ sh "cd #{go_artifact_repository_path} && #{push_cmd}"
36
+ end
37
+
38
+ desc "the default task"
39
+ task :default => :test
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "go_api_client"
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "go_cd_feed"
6
+ s.version = '1.0.0'
7
+ s.authors = ["Nikhil Mungel", "Ketan Padegaonkar", "Shishir Das", "Bill DePhillips"]
8
+ s.email = ["hyfather@gmail.com", "KetanPadegaonkar@gmail.com", "shishir.das@gmail.com", "bill.dephillips@gmail.com"]
9
+ s.homepage = "http://github.com/rearadmiral/go-api-client.git"
10
+ s.summary = %q{Client to parse Go CI atom feed}
11
+ s.description = %q{(Fork of go_api_client) This gem parses atom feed generated by the Go.CD server and provides an OO representation of the pipelines and stages.}
12
+
13
+ s.rubyforge_project = "go_cd_feed"
14
+
15
+ s.files = `git ls-files`.split("\n") - `git ls-files -- vendor/cache`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ # specify any dependencies here; for example:
21
+ s.add_development_dependency "webmock"
22
+ s.add_development_dependency "simplecov"
23
+ s.add_development_dependency 'rake'
24
+ s.add_development_dependency 'test-unit'
25
+
26
+ s.add_runtime_dependency "nokogiri"
27
+ end
@@ -0,0 +1,60 @@
1
+ require 'nokogiri'
2
+
3
+ require 'net/http'
4
+
5
+ require 'go_api_client/version'
6
+ require 'go_api_client/helpers'
7
+ require 'go_api_client/http_fetcher'
8
+
9
+ require 'go_api_client/atom'
10
+ require 'go_api_client/pipeline'
11
+ require 'go_api_client/stage'
12
+ require 'go_api_client/job'
13
+ require 'go_api_client/commit'
14
+ require 'go_api_client/user'
15
+
16
+
17
+ module GoApiClient
18
+ def self.runs(options)
19
+ options = ({:protocol => 'http', :port => 8153, :username => nil, :password => nil, :latest_atom_entry_id => nil, :pipeline_name => 'defaultPipeline'}).merge(options)
20
+
21
+ http_fetcher = GoApiClient::HttpFetcher.new(:username => options[:username], :password => options[:password])
22
+
23
+ feed_url = "#{options[:protocol]}://#{options[:host]}:#{options[:port]}/go/api/pipelines/#{options[:pipeline_name]}/stages.xml"
24
+
25
+ feed = GoApiClient::Atom::Feed.new(feed_url, options[:latest_atom_entry_id])
26
+ feed.fetch!(http_fetcher)
27
+
28
+ pipelines = {}
29
+ stages = feed.entries.collect do |entry|
30
+ Stage.from(entry.stage_href, :authors => entry.authors, :pipeline_cache => pipelines, :http_fetcher => http_fetcher)
31
+ end
32
+
33
+ pipelines.values.each do |p|
34
+ p.stages = p.stages.sort_by {|s| s.completed_at }
35
+ end
36
+
37
+ return {
38
+ :pipelines => pipelines.values.sort_by {|p| p.counter},
39
+ :latest_atom_entry_id => stages.empty? ? options[:latest_atom_entry_id] : feed.entries.first.id
40
+ }
41
+ end
42
+
43
+ def self.build_in_progress?(options)
44
+ raise ArgumentError("Hostname is mandatory") unless options[:host]
45
+ options = ({:protocol => 'http', :port => 8153, :username => nil, :password => nil}).merge(options)
46
+ http_fetcher = GoApiClient::HttpFetcher.new(:username => options[:username], :password => options[:password])
47
+ url = "#{options[:protocol]}://#{options[:host]}:#{options[:port]}/go/cctray.xml"
48
+ doc = Nokogiri::XML(http_fetcher.get_response_body(url))
49
+ doc.xpath("//Project[contains(@activity, 'Building')]").count > 0
50
+ end
51
+
52
+ def self.build_finished?(options)
53
+ !build_in_progress?(options)
54
+ end
55
+
56
+ def self.schedule_pipeline(host)
57
+ uri = URI("http://#{host}:8153/go/api/pipelines/defaultPipeline/schedule")
58
+ Net::HTTP.post_form(uri, {})
59
+ end
60
+ end
@@ -0,0 +1,4 @@
1
+ require 'go_api_client/atom/author'
2
+ require 'go_api_client/atom/entry'
3
+ require 'go_api_client/atom/feed_page'
4
+ require 'go_api_client/atom/feed'
@@ -0,0 +1,42 @@
1
+ module GoApiClient
2
+ module Atom
3
+ class Author
4
+
5
+ attr_accessor :name, :email, :uri
6
+
7
+ include GoApiClient::Helpers::SimpleAttributesSupport
8
+
9
+ def initialize(root, attributes={})
10
+ @root = root
11
+ super(attributes)
12
+ end
13
+
14
+ def parse!
15
+ self.name = @root.xpath('xmlns:name').first.content
16
+ self.email = @root.xpath('xmlns:email').first.content rescue nil
17
+ self.uri = @root.xpath('xmlns:uri').first.content rescue nil
18
+
19
+ if email.nil? || email.empty?
20
+ if name =~ /(.*) <(.+?)>/
21
+ self.name, self.email = $1, $2
22
+ end
23
+ end
24
+
25
+ @root = nil
26
+ self
27
+ end
28
+
29
+ def ==(other)
30
+ other && self.class.equal?(other.class) &&
31
+ name == other.name &&
32
+ email == other.email &&
33
+ uri == other.uri
34
+ end
35
+
36
+ def hash
37
+ self.class.hash ^ name.hash ^ email.hash ^ uri.hash
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,34 @@
1
+ require 'time'
2
+
3
+ module GoApiClient
4
+ module Atom
5
+ class Entry
6
+
7
+ attr_accessor :authors, :id, :updated_at, :title, :stage_href, :pipelines
8
+
9
+ include GoApiClient::Helpers::SimpleAttributesSupport
10
+
11
+ def initialize(root, attributes={})
12
+ @root = root
13
+ super(attributes)
14
+ end
15
+
16
+ def parse!
17
+ self.updated_at = Time.parse(@root.xpath('xmlns:updated').first.content).utc
18
+ self.id = @root.xpath('xmlns:id').first.content
19
+ self.title = @root.xpath('xmlns:title').first.content
20
+ self.stage_href = @root.
21
+ xpath("xmlns:link[@type='application/vnd.go+xml' and @rel='alternate']").
22
+ first.
23
+ attributes["href"].value
24
+
25
+ self.authors = @root.xpath('xmlns:author').collect do |author|
26
+ Author.new(author).parse!
27
+ end
28
+ @root = nil
29
+ self
30
+ end
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,44 @@
1
+ module GoApiClient
2
+ module Atom
3
+ class Feed
4
+ attr_accessor :feed_pages, :entries
5
+
6
+ PAGE_FETCH_LIMIT = 2
7
+
8
+ def initialize(atom_feed_url, last_entry_id=nil)
9
+ @atom_feed_url = atom_feed_url
10
+ @last_entry_id = last_entry_id
11
+ end
12
+
13
+ def fetch!(http_fetcher = HttpFetcher.new)
14
+ self.entries = []
15
+ pages_fetched = 0
16
+ feed_url = @atom_feed_url
17
+
18
+ begin
19
+ doc = Nokogiri::XML(http_fetcher.get_response_body(feed_url))
20
+ pages_fetched += 1
21
+ if pages_fetched > PAGE_FETCH_LIMIT
22
+ puts "=" * 100
23
+ puts ""
24
+ puts "[GO WATCHDOG] not fetching past #{PAGE_FETCH_LIMIT} pages of the Go event feed."
25
+ puts "If there is no green build in those pages, Go Watchdog may not work properly."
26
+ puts "Get your build green first!"
27
+ puts ""
28
+ puts "=" * 100
29
+ break
30
+ end
31
+ feed_page = GoApiClient::Atom::FeedPage.new(doc.root).parse!
32
+
33
+ self.entries += if feed_page.contains_entry?(@last_entry_id)
34
+ feed_page.entries_after(@last_entry_id)
35
+ else
36
+ feed_page.entries
37
+ end
38
+ feed_url = feed_page.next_page
39
+ end while feed_page.next_page && !feed_page.contains_entry?(@last_entry_id)
40
+ self
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,49 @@
1
+ require 'time'
2
+ module GoApiClient
3
+ module Atom
4
+ class FeedPage
5
+ attr_accessor :updated_at, :next_page, :url, :entries
6
+
7
+ include GoApiClient::Helpers::SimpleAttributesSupport
8
+
9
+ def initialize(root, attributes={})
10
+ @root = root
11
+ super(attributes)
12
+ end
13
+
14
+ def parse!
15
+ self.updated_at = Time.parse(@root.xpath('xmlns:updated').first.content).utc
16
+ self.next_page = href_from(@root.xpath("xmlns:link[@rel='next']"))
17
+ self.url = href_from(@root.xpath("xmlns:link[@rel='self']"))
18
+ self.entries = @root.xpath("xmlns:entry").collect do |entry|
19
+ Entry.new(entry).parse!
20
+ end
21
+ @root = nil
22
+ self
23
+ end
24
+
25
+ def entries_after(entry_or_id)
26
+ index = if entry_or_id.is_a?(String)
27
+ entries.find_index {|e| e.id == entry_or_id}
28
+ else
29
+ entries.find_index {|e| e == entry_or_id}
30
+ end
31
+
32
+ index.zero? ? [] : entries[0..index-1]
33
+ end
34
+
35
+ def contains_entry?(entry_or_id)
36
+ if entry_or_id.is_a?(String)
37
+ entries.find {|e| e.id == entry_or_id}
38
+ else
39
+ entries.include?(entry_or_id)
40
+ end
41
+ end
42
+
43
+ private
44
+ def href_from(xml)
45
+ xml.first.attribute('href').value unless xml.empty?
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,30 @@
1
+ module GoApiClient
2
+ class Commit
3
+
4
+ attr_accessor :revision, :message, :time, :user
5
+
6
+ include GoApiClient::Helpers::SimpleAttributesSupport
7
+
8
+ def initialize(root, attributes={})
9
+ @root = root
10
+ super(attributes)
11
+ end
12
+
13
+ def parse!
14
+ self.revision = @root.xpath("./revision").first.content
15
+ self.message = @root.xpath("./message").first.content
16
+ self.time = Time.parse(@root.xpath("./checkinTime").first.content).utc
17
+ self.user = User.parse(@root.xpath("./user").first.content)
18
+ @root = nil
19
+ self
20
+ end
21
+
22
+ def to_s
23
+ "commit #{revision}
24
+ Author: #{user}
25
+ Date: #{time}
26
+
27
+ #{message.each_line.collect {|l| " #{l}"}}"
28
+ end
29
+ end
30
+ end