jenkins-json-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.swo
2
+ *.swp
3
+
4
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+
2
+ source :rubygems
3
+
4
+ ## production: trollop, json
5
+ gem 'trollop'
6
+ gem 'json'
7
+
8
+ ## testing: cucumber, rspec, mock-server-thin
9
+ group :test do
10
+ gem 'cucumber'
11
+ gem 'rspec'
12
+ gem 'mock-server-thin'
13
+ end
data/LICENSE ADDED
@@ -0,0 +1,165 @@
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+
9
+ This version of the GNU Lesser General Public License incorporates
10
+ the terms and conditions of version 3 of the GNU General Public
11
+ License, supplemented by the additional permissions listed below.
12
+
13
+ 0. Additional Definitions.
14
+
15
+ As used herein, "this License" refers to version 3 of the GNU Lesser
16
+ General Public License, and the "GNU GPL" refers to version 3 of the GNU
17
+ General Public License.
18
+
19
+ "The Library" refers to a covered work governed by this License,
20
+ other than an Application or a Combined Work as defined below.
21
+
22
+ An "Application" is any work that makes use of an interface provided
23
+ by the Library, but which is not otherwise based on the Library.
24
+ Defining a subclass of a class defined by the Library is deemed a mode
25
+ of using an interface provided by the Library.
26
+
27
+ A "Combined Work" is a work produced by combining or linking an
28
+ Application with the Library. The particular version of the Library
29
+ with which the Combined Work was made is also called the "Linked
30
+ Version".
31
+
32
+ The "Minimal Corresponding Source" for a Combined Work means the
33
+ Corresponding Source for the Combined Work, excluding any source code
34
+ for portions of the Combined Work that, considered in isolation, are
35
+ based on the Application, and not on the Linked Version.
36
+
37
+ The "Corresponding Application Code" for a Combined Work means the
38
+ object code and/or source code for the Application, including any data
39
+ and utility programs needed for reproducing the Combined Work from the
40
+ Application, but excluding the System Libraries of the Combined Work.
41
+
42
+ 1. Exception to Section 3 of the GNU GPL.
43
+
44
+ You may convey a covered work under sections 3 and 4 of this License
45
+ without being bound by section 3 of the GNU GPL.
46
+
47
+ 2. Conveying Modified Versions.
48
+
49
+ If you modify a copy of the Library, and, in your modifications, a
50
+ facility refers to a function or data to be supplied by an Application
51
+ that uses the facility (other than as an argument passed when the
52
+ facility is invoked), then you may convey a copy of the modified
53
+ version:
54
+
55
+ a) under this License, provided that you make a good faith effort to
56
+ ensure that, in the event an Application does not supply the
57
+ function or data, the facility still operates, and performs
58
+ whatever part of its purpose remains meaningful, or
59
+
60
+ b) under the GNU GPL, with none of the additional permissions of
61
+ this License applicable to that copy.
62
+
63
+ 3. Object Code Incorporating Material from Library Header Files.
64
+
65
+ The object code form of an Application may incorporate material from
66
+ a header file that is part of the Library. You may convey such object
67
+ code under terms of your choice, provided that, if the incorporated
68
+ material is not limited to numerical parameters, data structure
69
+ layouts and accessors, or small macros, inline functions and templates
70
+ (ten or fewer lines in length), you do both of the following:
71
+
72
+ a) Give prominent notice with each copy of the object code that the
73
+ Library is used in it and that the Library and its use are
74
+ covered by this License.
75
+
76
+ b) Accompany the object code with a copy of the GNU GPL and this license
77
+ document.
78
+
79
+ 4. Combined Works.
80
+
81
+ You may convey a Combined Work under terms of your choice that,
82
+ taken together, effectively do not restrict modification of the
83
+ portions of the Library contained in the Combined Work and reverse
84
+ engineering for debugging such modifications, if you also do each of
85
+ the following:
86
+
87
+ a) Give prominent notice with each copy of the Combined Work that
88
+ the Library is used in it and that the Library and its use are
89
+ covered by this License.
90
+
91
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
92
+ document.
93
+
94
+ c) For a Combined Work that displays copyright notices during
95
+ execution, include the copyright notice for the Library among
96
+ these notices, as well as a reference directing the user to the
97
+ copies of the GNU GPL and this license document.
98
+
99
+ d) Do one of the following:
100
+
101
+ 0) Convey the Minimal Corresponding Source under the terms of this
102
+ License, and the Corresponding Application Code in a form
103
+ suitable for, and under terms that permit, the user to
104
+ recombine or relink the Application with a modified version of
105
+ the Linked Version to produce a modified Combined Work, in the
106
+ manner specified by section 6 of the GNU GPL for conveying
107
+ Corresponding Source.
108
+
109
+ 1) Use a suitable shared library mechanism for linking with the
110
+ Library. A suitable mechanism is one that (a) uses at run time
111
+ a copy of the Library already present on the user's computer
112
+ system, and (b) will operate properly with a modified version
113
+ of the Library that is interface-compatible with the Linked
114
+ Version.
115
+
116
+ e) Provide Installation Information, but only if you would otherwise
117
+ be required to provide such information under section 6 of the
118
+ GNU GPL, and only to the extent that such information is
119
+ necessary to install and execute a modified version of the
120
+ Combined Work produced by recombining or relinking the
121
+ Application with a modified version of the Linked Version. (If
122
+ you use option 4d0, the Installation Information must accompany
123
+ the Minimal Corresponding Source and Corresponding Application
124
+ Code. If you use option 4d1, you must provide the Installation
125
+ Information in the manner specified by section 6 of the GNU GPL
126
+ for conveying Corresponding Source.)
127
+
128
+ 5. Combined Libraries.
129
+
130
+ You may place library facilities that are a work based on the
131
+ Library side by side in a single library together with other library
132
+ facilities that are not Applications and are not covered by this
133
+ License, and convey such a combined library under terms of your
134
+ choice, if you do both of the following:
135
+
136
+ a) Accompany the combined library with a copy of the same work based
137
+ on the Library, uncombined with any other library facilities,
138
+ conveyed under the terms of this License.
139
+
140
+ b) Give prominent notice with the combined library that part of it
141
+ is a work based on the Library, and explaining where to find the
142
+ accompanying uncombined form of the same work.
143
+
144
+ 6. Revised Versions of the GNU Lesser General Public License.
145
+
146
+ The Free Software Foundation may publish revised and/or new versions
147
+ of the GNU Lesser General Public License from time to time. Such new
148
+ versions will be similar in spirit to the present version, but may
149
+ differ in detail to address new problems or concerns.
150
+
151
+ Each version is given a distinguishing version number. If the
152
+ Library as you received it specifies that a certain numbered version
153
+ of the GNU Lesser General Public License "or any later version"
154
+ applies to it, you have the option of following the terms and
155
+ conditions either of that published version or of any later version
156
+ published by the Free Software Foundation. If the Library as you
157
+ received it does not specify a version number of the GNU Lesser
158
+ General Public License, you may choose any version of the GNU Lesser
159
+ General Public License ever published by the Free Software Foundation.
160
+
161
+ If the Library as you received it specifies that a proxy can decide
162
+ whether future versions of the GNU Lesser General Public License shall
163
+ apply, that proxy's public statement of acceptance of any version is
164
+ permanent authorization for you to choose that version for the
165
+ Library.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # jenkins-json-api
2
+
3
+ Ruby wrapper for Jenkins JSON API
4
+
5
+ ## NOTES
6
+
7
+ * ```features/``` directory is test for the runnable ```rjja``` CLI
8
+ * ```spec/``` directory is tests for the library itself (kinda unit-test)
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'jenkins-json-api'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install jenkins-json-api
23
+
24
+ ## Usage
25
+
26
+ TODO: Write usage instructions here
27
+
28
+ ## Contributing
29
+
30
+ 1. Fork it
31
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
32
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
33
+ 4. Push to the branch (`git push origin my-new-feature`)
34
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ task :default => :spec
data/bin/rjja ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'trollop'
4
+ require 'resolv'
5
+
6
+ require_relative '../lib/jenkins-json-api'
7
+
8
+ # argparsing and handling
9
+ SUB_COMMANDS = %w( job )
10
+ opts = Trollop::options do
11
+ opt :host, "host of Jenkins instance", type: String
12
+ stop_on SUB_COMMANDS
13
+ end
14
+
15
+ Trollop::die :host, "mandatory" unless opts[:host]
16
+
17
+ cmd = ARGV.shift
18
+ cmd_opts = case cmd
19
+ when "job"
20
+ subcmd = ARGV.shift
21
+ case subcmd
22
+ when "list"
23
+ # else
24
+ # Trollop::die "unknown subcommand #{subcmd.inspect}"
25
+ end
26
+ #else
27
+ # Trollop::die "unknown subcommand #{cmd.inspect}"
28
+ end
29
+
30
+ Trollop::die "no action given" if cmd.nil?
31
+
32
+ jenkins = Jenkins.new opts[:host]
33
+
34
+ hostname, port = opts[:host].split ':'
35
+ begin
36
+ Resolv.getaddress hostname
37
+ jenkins.get_all_jobs.each do |job|
38
+ name = job.name
39
+ succ_str = 'failed'
40
+ succ_str = 'success' if job.success?
41
+ puts "#{name} #{succ_str}"
42
+ end
43
+ rescue Resolv::ResolvError, OpenURI::HTTPError
44
+ puts "Error: Network error"
45
+ exit 2
46
+ end
47
+
48
+
@@ -0,0 +1,11 @@
1
+ require 'jenkins-json-api'
2
+
3
+ jenkins = Jenkins.new 'myjenkinshost:80'
4
+
5
+
6
+ jenkins.get_all_jobs.each do |job|
7
+ if job.name =~ /myjobpattern/
8
+ puts job.name
9
+ job.build_async # sending request async, useful if there is many job
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ Feature: handling errors in rjja
2
+ In order to see useful error and help messages
3
+ As an agile developer who using continuous integration
4
+ I want to know what I did wrong
5
+
6
+ Scenario: missing host parameter
7
+ Given the rjja binary
8
+ When I execute rjja with parameters ""
9
+ Then it should print "Error: argument --host mandatory.","Try --help for help."
10
+
11
+ Scenario: no action given
12
+ Given the rjja binary
13
+ When I execute rjja with parameters "--host=somehost"
14
+ Then it should print "Error: no action given.", "Try --help for help."
15
+
16
+ Scenario: non-existent host
17
+ Given the rjja binary
18
+ When I execute rjja with parameters "--host=asdf job list"
19
+ Then it should print "Error: Network error"
@@ -0,0 +1,11 @@
1
+ Feature: rjja - print all job
2
+ In order to get feedback from my jenkins CI tool
3
+ As an agile developer who using continuous integration
4
+ I want to know my jenkins-jobs' names and their statuses
5
+
6
+ Scenario: print all job
7
+ Given jenkins on port "4000" with jobs "firstjob", "secjob" with statuses respectively "success", "failed"
8
+ When I execute rjja with parameters "--host=localhost:4000 job list"
9
+ Then it should print "firstjob success", "secjob failed"
10
+
11
+
@@ -0,0 +1,32 @@
1
+
2
+
3
+ Given /^jenkins on port "(.*?)" with jobs "(.*?)", "(.*?)" with statuses respectively "(.*?)", "(.*?)"$/ do |port, job1, job2, stat1, stat2|
4
+ mock_resp(port: port) do
5
+ get('/api/json') do
6
+ # TODO nicer jenkins response generation
7
+ { 'jobs' => [ { 'name' => job1, 'color' => status_to_color(stat1) },
8
+ { 'name' => job2, 'color' => status_to_color(stat2) } ]
9
+ }.to_json
10
+ end
11
+ end
12
+
13
+ end
14
+
15
+ When /^I execute rjja with parameters "(.*?)"$/ do |params|
16
+ @resp = exec_cli params
17
+ end
18
+
19
+ Then /^it should print "(.*?)"$/ do |line1|
20
+ lines = line1.split /"\s*,\s*"/
21
+ #@resp.chomp.should == line1
22
+ @resp.split("\n").should =~ lines
23
+ end
24
+
25
+ Given /^the rjja binary$/ do
26
+ # TODO File.exists
27
+ end
28
+
29
+ Then /^it should print the usage$/ do
30
+ pending # express the regexp above with the code you wish you had
31
+ end
32
+
@@ -0,0 +1,27 @@
1
+
2
+ require 'mock_server_thin'
3
+
4
+ RJJA_BIN='bin/rjja'
5
+
6
+ def exec_cli(params)
7
+ cmd = "#{RJJA_BIN} #{params}"
8
+ puts cmd
9
+ ret = `#{cmd} 2>&1`
10
+ puts "RETURNED:\n---------\n#{ret}\n-----------"
11
+ ret
12
+ end
13
+
14
+ def status_to_color(s)
15
+ if s =~ /fail/
16
+ 'red'
17
+ else s =~ /succ/
18
+ 'blue'
19
+ end
20
+ end
21
+
22
+ def mock_resp( opts = {}, &block )
23
+ app = Class.new(Sinatra::Base)
24
+ app.class_eval &block
25
+ @server = MockServerThin.new(app,opts,&block).start
26
+ end
27
+
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'jenkins-json-api/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "jenkins-json-api"
8
+ gem.version = Jenkins::Json::Api::VERSION
9
+ gem.authors = ["Marton Suranyi"]
10
+ gem.email = ["marton.suranyi@gmail.com"]
11
+ gem.description = %q{Ruby wrapper for Jenkins JSON API}
12
+ gem.summary = %q{Very experimental!}
13
+ gem.homepage = "https://github.com/susu/jenkins-json-api"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,7 @@
1
+ module Jenkins
2
+ module Json
3
+ module Api
4
+ VERSION = "0.0.1"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,71 @@
1
+
2
+ require 'json'
3
+ require 'open-uri'
4
+
5
+ class Jenkins
6
+
7
+ class Job
8
+ SUCCESS = 'blue'
9
+ FAILED = 'red'
10
+
11
+ def initialize(json)
12
+ @name = json['name']
13
+ @url = json['url']
14
+ @color = json['color']
15
+ end
16
+
17
+ def success?
18
+ return true if color == SUCCESS
19
+ return false if color == FAILED
20
+ raise "Inconsistent class state! color: #{color}"
21
+ end
22
+
23
+ def build
24
+ open url+'build'
25
+ end
26
+
27
+ def build_async
28
+ Process.waitpid @job if @job
29
+ @job = fork do
30
+ build
31
+ end
32
+ end
33
+
34
+ def to_s
35
+ "\n #{super.to_s}\n name: #{name}\n url: #{url}\n success: #{success?}\n"
36
+ end
37
+
38
+ def ==(r)
39
+ r.name == name and
40
+ r.url == url and
41
+ r.success? == success?
42
+ end
43
+
44
+ attr_reader :name, :url, :color
45
+ end
46
+
47
+ def initialize(host)
48
+ @host = host
49
+ end
50
+
51
+ def get_all_jobs
52
+ get_json['jobs'].map { |job| Job.new(job) }
53
+ end
54
+
55
+ def build_all
56
+ get_all_jobs.each do |job|
57
+ job.build
58
+ end
59
+ end
60
+
61
+
62
+ attr_reader :host
63
+ private
64
+ def get_json(med = nil)
65
+ JSON.parse(open( api_url(med) ).read)
66
+ end
67
+ def api_url(med)
68
+ "http://#{host}/api/json"
69
+ end
70
+ end
71
+
@@ -0,0 +1,42 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ require_relative '../lib/jenkins-json-api'
5
+
6
+ describe Jenkins do
7
+ subject { Jenkins.new testhost }
8
+ let(:testhost) { 'myjenkinshost.com' }
9
+
10
+ its(:host) { should == testhost }
11
+
12
+ let(:job1_hash) { { 'name' => 'gerrit_master',
13
+ 'url' => "http://#{testhost}/job/gerrit_master/",
14
+ 'color' => 'blue' } }
15
+ let(:job2_hash) { { 'name' => 'anotherjob',
16
+ 'url' => "http://#{testhost}/job/anotherjob/",
17
+ 'color' => 'red' } }
18
+
19
+ let(:json_hash) { { 'jobs' => [ job1_hash, job2_hash ] } }
20
+
21
+ let(:jobs) { [ Jenkins::Job.new(job1_hash), Jenkins::Job.new(job2_hash) ] }
22
+
23
+ context "get_all_jobs success" do
24
+ before(:each) { JSON.should_receive(:parse).and_return( json_hash ) }
25
+ before(:each) { subject.stub_chain(:open,:read) }
26
+
27
+ its(:get_all_jobs) { should have(2).items }
28
+
29
+ its(:get_all_jobs) do
30
+ should =~ jobs
31
+ end
32
+ end
33
+
34
+ context "build_all" do
35
+ it "should send build URL for all jobs" do
36
+ jobs.each { |job| job.should_receive :build }
37
+ subject.should_receive( :get_all_jobs ).and_return jobs
38
+ subject.build_all
39
+ end
40
+ end
41
+ end
42
+
data/spec/job_spec.rb ADDED
@@ -0,0 +1,24 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ require_relative '../lib/jenkins-json-api'
5
+
6
+ describe Jenkins::Job do
7
+ let(:job1_hash) { { 'name' => 'gerrit_master',
8
+ 'url' => "http://testhost/job/gerrit_master/",
9
+ 'color' => 'blue' } }
10
+
11
+ subject { Jenkins::Job.new(job1_hash) }
12
+ its(:name) { should == 'gerrit_master' }
13
+ its(:url) { should == job1_hash['url'] }
14
+ its(:success?) { should == true }
15
+
16
+ context "build a job" do
17
+
18
+ it "should send url request to build to job" do
19
+ subject.should_receive(:open).once.with "#{job1_hash['url']}build"
20
+
21
+ subject.build
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module JenkinsTestDataGenerator
3
+ def self.root()
4
+ { jobs: [ {name:'proj1'},
5
+ {name:'2ndjob'} ] }.to_json
6
+ end
7
+
8
+ def self.real_root()
9
+ open('spec/root.json').read
10
+ end
11
+ end
12
+
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jenkins-json-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marton Suranyi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-11 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Ruby wrapper for Jenkins JSON API
15
+ email:
16
+ - marton.suranyi@gmail.com
17
+ executables:
18
+ - rjja
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - bin/rjja
28
+ - examples/all_job_runner.rb
29
+ - features/error_handling.feature
30
+ - features/print_jobs.feature
31
+ - features/step_definitions.rb
32
+ - features/support/env.rb
33
+ - jenkins-json-api.gemspec
34
+ - lib/jenkins-json-api.rb
35
+ - lib/jenkins-json-api/version.rb
36
+ - spec/jenkins_spec.rb
37
+ - spec/job_spec.rb
38
+ - spec/spec_helper.rb
39
+ homepage: https://github.com/susu/jenkins-json-api
40
+ licenses: []
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 1.8.24
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Very experimental!
63
+ test_files:
64
+ - features/error_handling.feature
65
+ - features/print_jobs.feature
66
+ - features/step_definitions.rb
67
+ - features/support/env.rb
68
+ - spec/jenkins_spec.rb
69
+ - spec/job_spec.rb
70
+ - spec/spec_helper.rb