jenkins_job 0.1.0

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
+ pkg
2
+ .idea
3
+ .dister
4
+ rdoc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :gemcutter
2
+
3
+ # Specify your gem's dependencies in jenkins_job.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,25 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jenkins_job (0.1.0)
5
+ thor (~> 0.14.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ fakefs (0.3.1)
11
+ mocha (0.9.4)
12
+ rake
13
+ rake (0.8.7)
14
+ shoulda (2.11.3)
15
+ thor (0.14.6)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ bundler (~> 1.0.0)
22
+ fakefs (~> 0.3.1)
23
+ jenkins_job!
24
+ mocha
25
+ shoulda
data/README.rdoc ADDED
@@ -0,0 +1,46 @@
1
+ = jenkins_job
2
+
3
+ jenkins_job is a cli tool that simplifies the management of Jenkins/Hudson jobs.
4
+
5
+ Most of my projects have more than one branch to keep tested.
6
+ I prefer to have a Jenkins' job per branch, instead of having a single job with
7
+ multiple branches. This leads to have multiple similar jobs to maintain.
8
+
9
+ == Common workflow
10
+
11
+ Make sure your job name contains a reference to the branch being tested, e.g.:
12
+ <project_name>_<branch_name>
13
+
14
+ Manage the project testing the master/trunk branch using the web interface.
15
+ Then clone it and change the branch to be tested using the following command:
16
+ jenkins_job clone foo_master --original_branch master --new_branch production
17
+
18
+ The previous command uses the foo_master job as a reference and creates a
19
+ new project named foo_production testing the production branch.
20
+
21
+ Note well: the command must be executed within the directory containing
22
+ Jenkins' jobs, which is <jenkins_home>/jobs.
23
+
24
+ == Other features
25
+ jenkins_job can help you in other ways.
26
+
27
+ == Disable/enable projects
28
+ It's possible to enable or disable multiple projects with a simple command:
29
+ jenkins_job enable|disable project1 project2 project3 ...
30
+
31
+ Thanks to bash file globbing you can change all the 'master' projects by typing:
32
+ jenkins_job enable|disable foo_*
33
+
34
+ == Copy settings to other projects
35
+ Suppose you have configured irc notifications for one of your projects and you
36
+ want to copy this configuration to other jobs.
37
+
38
+ Irc notification plugin saves its settings under the following xml node:
39
+ project/hudson.plugins.ircbot.IrcPublisher
40
+
41
+ Just execute this command:
42
+ jenkins_job copy_setting hudson.plugins.ircbot.IrcPublisher foo_master bar_master
43
+
44
+ Now the bar_master project will have the irc notifications turned on and
45
+ configured like foo_master.
46
+
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ require 'bundler'
2
+ require 'rake'
3
+ require 'rake/rdoctask'
4
+ require 'rake/testtask'
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ task :default => "test"
8
+
9
+ require 'rake/testtask'
10
+ Rake::TestTask.new(:test) do |test|
11
+ test.libs << 'lib' << 'test'
12
+ test.pattern = 'test/**/*_test.rb'
13
+ test.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'jenkins_job'
20
+ rdoc.options << '--line-numbers' << "--main" << "README.rdoc"
21
+ rdoc.rdoc_files.include('README.rdoc')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ desc "Clean files generated by rake tasks"
26
+ task :clobber => [:clobber_rdoc]
data/bin/jenkins_job ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path('../../lib/jenkins_job',__FILE__)
3
+ JenkinsJob::Cli.start(ARGV)
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path("../lib/jenkins_job/version", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "jenkins_job"
6
+ s.version = JenkinsJob::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ['Flavio Castelli']
9
+ s.email = ['flavio@castelli.name']
10
+ # s.homepage = "https://features.opensuse.org/311133"
11
+ s.summary = "Simple cli tool created to manage Jenkins job files."
12
+ s.description = "Handle your Jenkins job configuration files in an easier way."
13
+
14
+ s.required_rubygems_version = ">= 1.3.6"
15
+ s.rubyforge_project = "jenkins_job"
16
+
17
+ s.add_dependency "thor", "~>0.14.0"
18
+
19
+ s.add_development_dependency "bundler", "~>1.0.0"
20
+ s.add_development_dependency "fakefs", "~>0.3.1"
21
+ s.add_development_dependency "mocha"
22
+ s.add_development_dependency "shoulda"
23
+ s.files = `git ls-files`.split("\n")
24
+ s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
25
+ s.require_path = 'lib'
26
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+
4
+ require File.expand_path('../jenkins_job/cli', __FILE__)
5
+ require File.expand_path('../jenkins_job/project', __FILE__)
6
+
7
+ module JenkinsJob
8
+ autoload :Version, File.expand_path('../jenkins_job/version', __FILE__)
9
+ end
@@ -0,0 +1,78 @@
1
+ require 'thor'
2
+
3
+ module JenkinsJob
4
+ class Cli < Thor
5
+ include Thor::Actions
6
+
7
+ desc "clone PROJECT [PROJECT, ...]", "Clone project changing its name and its branch"
8
+ method_option :original_branch, :default => 'master', :type => :string
9
+ method_option :new_branch, :type => :string
10
+ method_option :force, :type => :boolean
11
+ def clone *project
12
+ force = options[:force] || false
13
+ project.each do |p|
14
+ # calculate the new dir
15
+ new_dir = p.gsub(options[:original_branch],
16
+ options[:new_branch])
17
+
18
+ if File.exists?(new_dir)
19
+ if !force && !yes?("#{new_dir} already exists, delete it? [y/n]")
20
+ say "#{p} -> #{new_dir} - skipped by user choice", :yellow
21
+ next
22
+ else
23
+ FileUtils.rm_rf(new_dir)
24
+ end
25
+ end
26
+
27
+ FileUtils.mkdir_p new_dir
28
+ config_lines = File.open(File.join(p, 'config.xml'), 'r').readlines
29
+ File.open(File.join(new_dir, 'config.xml'), 'w') do |file|
30
+ config_lines.each do |line|
31
+ file.write(line.gsub(options[:original_branch],
32
+ options[:new_branch]))
33
+ end
34
+ end
35
+ say "#{p} -> #{new_dir} - done", :green
36
+ end
37
+ end
38
+
39
+ desc "clean PROJECT [PROJECT, ...]",
40
+ "Remove all the useless files generated by hudson from the specified projects"
41
+ def clean *project
42
+ project.each do |p|
43
+ Project.new(p).clean
44
+ end
45
+ end
46
+
47
+ desc "disable PROJECT [PROJECT, ...]", "disable the specified projects"
48
+ def disable *project
49
+ project.each do |p|
50
+ Project.new(p).disable
51
+ puts "#{p} - disabled"
52
+ end
53
+ end
54
+
55
+ desc "enable PROJECT [PROJECT, ...]", "enable the specified projects"
56
+ def enable *project
57
+ project.each do |p|
58
+ Project.new(p).enable
59
+ puts "#{p} - enabled"
60
+ end
61
+ end
62
+
63
+ desc "copy_setting SOURCE_PROJECT SETTING_NAME DEST_PROJECT",
64
+ "Copy SETTING_NAME from SOURCE_PROJECT to DEST_PROJECT"
65
+ def copy_setting source_project, setting_name, dest_project
66
+ source = Project.new(source_project)
67
+ dest = Project.new(dest_project)
68
+
69
+ setting = source.setting(setting_name)
70
+ if setting.nil?
71
+ say "#{source_project} doesn't contain the specified setting", :red
72
+ else
73
+ dest.update_setting(setting_name, setting)
74
+ say "#{setting_name} copied", :green
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,92 @@
1
+ require 'rexml/document'
2
+
3
+ module JenkinsJob
4
+ class Project
5
+
6
+ def initialize dir
7
+ raise "#{dir} does not exists" unless File.exists? dir
8
+ raise "#{dir} is not a directory" unless File.directory?(dir)
9
+
10
+ @config_file = File.join(dir, 'config.xml')
11
+ if !File.exists?(@config_file)
12
+ raise "#{dir} doesn't contain config.xml file"
13
+ end
14
+ @dir = dir
15
+ end
16
+
17
+ # removes all the useless files generated by hudson, keeps only config.xml
18
+ def clean
19
+ Dir.chdir(@dir) do
20
+ ['builds', 'last*', '*.log', 'next*'].each do |pattern|
21
+ FileUtils.rm_rf Dir.glob(pattern)
22
+ end
23
+ end
24
+ end
25
+
26
+ def enabled?
27
+ !disabled?
28
+ end
29
+
30
+ def disabled?
31
+ doc = REXML::Document.new(File.open(@config_file, 'r'))
32
+ disabled_node = doc.elements['project/disabled']
33
+ return false if disabled_node.nil?
34
+ return true if disabled_node.text.downcase == 'true'
35
+ false
36
+ end
37
+
38
+ # disable the project
39
+ def disable
40
+ doc = REXML::Document.new(File.open(@config_file, 'r'))
41
+ disabled_node = doc.elements['project/disabled']
42
+ if disabled_node.nil?
43
+ disabled_node = REXML::Element.new 'disabled'
44
+ disabled_node.text = 'true'
45
+ project_node = doc.elements['project']
46
+ project_node << disabled_node
47
+ else
48
+ if !disabled_node.text.downcase == 'true'
49
+ return
50
+ else
51
+ disabled_node.text = 'true'
52
+ end
53
+ end
54
+ File.open(@config_file, File::WRONLY|File::TRUNC) do |file|
55
+ doc.write file
56
+ end
57
+ end
58
+
59
+ # enable the project
60
+ def enable
61
+ doc = REXML::Document.new(File.open(@config_file, 'r'))
62
+ disabled_node = doc.elements['project/disabled']
63
+ if !disabled_node.nil?
64
+ disabled_node.text = "false"
65
+ File.open(@config_file, File::WRONLY|File::TRUNC) do |file|
66
+ doc.write file
67
+ end
68
+ end
69
+ end
70
+
71
+ # Returns a REXML::Element identified by project/name
72
+ def setting name
73
+ doc = REXML::Document.new(File.open(@config_file, 'r'))
74
+ doc.elements["project/#{name}"]
75
+ end
76
+
77
+ # Update setting
78
+ # name: the name of the setting
79
+ # node: the REXML::Element to insert
80
+ def update_setting name, node
81
+ doc = REXML::Document.new(File.open(@config_file, 'r'))
82
+ old = doc.elements["project/#{name}"]
83
+ doc.root.elements.delete(old) unless old.nil?
84
+ project_node = doc.elements['project']
85
+ project_node << node
86
+ File.open(@config_file, File::WRONLY|File::TRUNC) do |file|
87
+ doc.write file
88
+ end
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,3 @@
1
+ module JenkinsJob
2
+ VERSION = "0.1.0"
3
+ end
data/test/cli_test.rb ADDED
@@ -0,0 +1,202 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class CliTest < Test::Unit::TestCase
4
+ context 'clean' do
5
+ should 'handle more than one project per time' do
6
+ projects = %w(foo bar foobar)
7
+
8
+ fake_project = mock()
9
+ fake_project.expects(:clean)\
10
+ .times(projects.size)\
11
+ .returns(true)
12
+
13
+ projects.each do |p|
14
+ JenkinsJob::Project.expects(:new).with(p)\
15
+ .returns(fake_project)
16
+ end
17
+ cmd = ['clean'] + projects
18
+ capture(:stdout) do
19
+ JenkinsJob::Cli.start(cmd)
20
+ end
21
+ end
22
+ end
23
+
24
+ context 'disable' do
25
+ should 'handle more than one project per time' do
26
+ projects = %w(foo bar foobar)
27
+
28
+ fake_project = mock()
29
+ fake_project.expects(:disable)\
30
+ .times(projects.size)\
31
+ .returns(true)
32
+
33
+ projects.each do |p|
34
+ JenkinsJob::Project.expects(:new).with(p)\
35
+ .returns(fake_project)
36
+ end
37
+ cmd = ['disable'] + projects
38
+ capture(:stdout) do
39
+ JenkinsJob::Cli.start(cmd)
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'enable' do
45
+ should 'handle more than one project per time' do
46
+ projects = %w(foo bar foobar)
47
+
48
+ fake_project = mock()
49
+ fake_project.expects(:enable)\
50
+ .times(projects.size)\
51
+ .returns(true)
52
+
53
+ projects.each do |p|
54
+ JenkinsJob::Project.expects(:new).with(p)\
55
+ .returns(fake_project)
56
+ end
57
+ cmd = ['enable'] + projects
58
+ capture(:stdout) do
59
+ JenkinsJob::Cli.start(cmd)
60
+ end
61
+ end
62
+ end
63
+
64
+ context 'clone' do
65
+ setup do
66
+ File.open(File.expand_path('../fixtures/foo_master/config.xml',
67
+ __FILE__), 'r') do |file|
68
+ @source_xml = file.readlines
69
+ end
70
+
71
+ File.open(File.expand_path('../fixtures/foo_production/config.xml',
72
+ __FILE__), 'r') do |file|
73
+ @expected_xml = file.readlines
74
+ end
75
+
76
+ FakeFS.activate!
77
+ FakeFS::FileSystem.clear
78
+ FileUtils.mkdir_p 'foo_master'
79
+ File.open('foo_master/config.xml', 'w') do |file|
80
+ file.write @source_xml
81
+ end
82
+ end
83
+
84
+ teardown do
85
+ FakeFS.deactivate!
86
+ end
87
+
88
+ should 'clone some projects' do
89
+ capture(:stdout) do
90
+ JenkinsJob::Cli.start(['clone', 'foo_master', '--original_branch',
91
+ 'master', '--new_branch', 'production'])
92
+ end
93
+
94
+ assert File.directory? 'foo_production'
95
+ assert File.exists? 'foo_production/config.xml'
96
+ actual_xml = File.open('foo_production/config.xml', 'r') do |file|
97
+ file.readlines
98
+ end
99
+ assert_equal @expected_xml, actual_xml
100
+ end
101
+
102
+ context 'final project already exists' do
103
+ setup do
104
+ FileUtils.mkdir_p 'foo_production'
105
+ FileUtils.touch 'foo_production/config.xml'
106
+ end
107
+
108
+ teardown do
109
+ FileUtils.rm_rf 'foo_production'
110
+ end
111
+
112
+ context 'force overwrite enabled' do
113
+ should 'not prompt user when force is set to true' do
114
+ JenkinsJob::Cli.any_instance.expects(:yes?).never
115
+
116
+ capture(:stdout) do
117
+ JenkinsJob::Cli.start(['clone', 'foo_master', '--original_branch',
118
+ 'master', '--new_branch', 'production',
119
+ '--force'])
120
+ end
121
+
122
+ assert File.directory? 'foo_production'
123
+ assert File.exists? 'foo_production/config.xml'
124
+ actual_xml = File.open('foo_production/config.xml', 'r') do |file|
125
+ file.readlines
126
+ end
127
+ assert_equal @expected_xml, actual_xml
128
+ end
129
+ end
130
+
131
+ context 'force overwrite is not set' do
132
+ context 'user wants to overwrite' do
133
+ should 'overwrite the old contents and create the new ones' do
134
+ JenkinsJob::Cli.any_instance.expects(:yes?).once.returns(true)
135
+ capture(:stdout) do
136
+ JenkinsJob::Cli.start(['clone', 'foo_master', '--original_branch',
137
+ 'master', '--new_branch', 'production'])
138
+ end
139
+ assert File.directory? 'foo_production'
140
+ assert File.exists? 'foo_production/config.xml'
141
+ actual_xml = File.open('foo_production/config.xml', 'r') do |file|
142
+ file.readlines
143
+ end
144
+ assert_equal @expected_xml, actual_xml
145
+ end
146
+ end
147
+
148
+ context "user doesn't want to overwrite" do
149
+ should 'preserve the old contents' do
150
+ JenkinsJob::Cli.any_instance.expects(:yes?).once.returns(false)
151
+ capture(:stdout) do
152
+ JenkinsJob::Cli.start(['clone', 'foo_master', '--original_branch',
153
+ 'master', '--new_branch', 'production'])
154
+ end
155
+ assert File.directory? 'foo_production'
156
+ assert File.exists? 'foo_production/config.xml'
157
+ actual_xml = File.open('foo_production/config.xml', 'r') do |file|
158
+ file.readlines
159
+ end
160
+ assert actual_xml.empty?
161
+ end
162
+ end
163
+
164
+ end
165
+ end
166
+ end
167
+
168
+ context 'copy settings' do
169
+ should 'spot a missing setting' do
170
+ source = mock()
171
+ source.expects(:setting).with('irc_bot').once.returns(nil)
172
+
173
+ dest = mock()
174
+ dest.expects(:update_setting).never
175
+
176
+ JenkinsJob::Project.expects(:new).twice.returns(source).then.returns(dest)
177
+ JenkinsJob::Cli.any_instance.expects(:say).with(is_a(String), :red).once
178
+
179
+ capture(:stdout) do
180
+ JenkinsJob::Cli.start(['copy_setting', 'foo_master', 'irc_bot',
181
+ 'foo_production'])
182
+ end
183
+
184
+ end
185
+
186
+ should 'handle an existing setting' do
187
+ source = mock()
188
+ source.expects(:setting).with('irc_bot').once.returns('foo')
189
+
190
+ dest = mock()
191
+ dest.expects(:update_setting).with('irc_bot', 'foo').once
192
+
193
+ JenkinsJob::Project.expects(:new).twice.returns(source).then.returns(dest)
194
+ JenkinsJob::Cli.any_instance.expects(:say).with(is_a(String), :green).once
195
+ capture(:stdout) do
196
+ JenkinsJob::Cli.start(['copy_setting', 'foo_master', 'irc_bot',
197
+ 'foo_production'])
198
+ end
199
+ end
200
+
201
+ end
202
+ end
@@ -0,0 +1,111 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <project>
3
+ <actions/>
4
+ <description>foo [master] tests</description>
5
+ <keepDependencies>false</keepDependencies>
6
+ <properties/>
7
+ <scm class='hudson.plugins.git.GitSCM'>
8
+ <configVersion>1</configVersion>
9
+ <remoteRepositories>
10
+ <org.spearce.jgit.transport.RemoteConfig>
11
+ <string>origin</string>
12
+ <int>5</int>
13
+ <string>fetch</string>
14
+ <string>+refs/heads/*:refs/remotes/origin/*</string>
15
+ <string>receivepack</string>
16
+ <string>git-upload-pack</string>
17
+ <string>uploadpack</string>
18
+ <string>git-upload-pack</string>
19
+ <string>url</string>
20
+ <string>foo_user@git.example.com:foo.git</string>
21
+ <string>tagopt</string>
22
+ <string/>
23
+ </org.spearce.jgit.transport.RemoteConfig>
24
+ </remoteRepositories>
25
+ <branches>
26
+ <hudson.plugins.git.BranchSpec>
27
+ <name>master</name>
28
+ </hudson.plugins.git.BranchSpec>
29
+ </branches>
30
+ <mergeOptions/>
31
+ <recursiveSubmodules>false</recursiveSubmodules>
32
+ <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
33
+ <authorOrCommitter>false</authorOrCommitter>
34
+ <clean>false</clean>
35
+ <pruneBranches>false</pruneBranches>
36
+ <buildChooser class='hudson.plugins.git.util.DefaultBuildChooser'/>
37
+ <gitTool>Default</gitTool>
38
+ <submoduleCfg class='list'/>
39
+ <relativeTargetDir/>
40
+ <excludedRegions/>
41
+ <excludedUsers/>
42
+ <skipTag>false</skipTag>
43
+ </scm>
44
+ <assignedNode>slave01</assignedNode>
45
+ <canRoam>false</canRoam>
46
+ <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
47
+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
48
+ <triggers class='vector'>
49
+ <hudson.triggers.SCMTrigger>
50
+ <spec>*/5 * * * *</spec>
51
+ </hudson.triggers.SCMTrigger>
52
+ </triggers>
53
+ <concurrentBuild>false</concurrentBuild>
54
+ <builders>
55
+ <hudson.plugins.rake.Rake>
56
+ <rakeInstallation>(Default)</rakeInstallation>
57
+ <rakeFile/>
58
+ <rakeLibDir/>
59
+ <rakeWorkingDir>foo</rakeWorkingDir>
60
+ <tasks>db:create db:migrate ci:setup:testunit test:test:rcov</tasks>
61
+ <silent>false</silent>
62
+ </hudson.plugins.rake.Rake>
63
+ </builders>
64
+ <publishers>
65
+ <hudson.tasks.junit.JUnitResultArchiver>
66
+ <testResults>**/foo/test/reports/*.xml</testResults>
67
+ <keepLongStdio>false</keepLongStdio>
68
+ <testDataPublishers/>
69
+ </hudson.tasks.junit.JUnitResultArchiver>
70
+ <hudson.plugins.rubyMetrics.railsStats.RailsStatsPublisher>
71
+ <rake>
72
+ <rakeInstallation>(Default)</rakeInstallation>
73
+ <rakeWorkingDir/>
74
+ <tasks>stats</tasks>
75
+ <silent>true</silent>
76
+ </rake>
77
+ <rakeInstallation>(Default)</rakeInstallation>
78
+ <rakeWorkingDir/>
79
+ <task>stats</task>
80
+ </hudson.plugins.rubyMetrics.railsStats.RailsStatsPublisher>
81
+ <hudson.plugins.rubyMetrics.railsNotes.RailsNotesPublisher>
82
+ <rake>
83
+ <rakeInstallation>(Default)</rakeInstallation>
84
+ <rakeWorkingDir/>
85
+ <tasks>notes</tasks>
86
+ <silent>true</silent>
87
+ </rake>
88
+ <rakeInstallation>(Default)</rakeInstallation>
89
+ <rakeWorkingDir/>
90
+ <task>notes</task>
91
+ </hudson.plugins.rubyMetrics.railsNotes.RailsNotesPublisher>
92
+ <hudson.plugins.rubyMetrics.rcov.RcovPublisher>
93
+ <reportDir>foo/coverage/test/</reportDir>
94
+ <targets>
95
+ <hudson.plugins.rubyMetrics.rcov.model.MetricTarget>
96
+ <metric>TOTAL_COVERAGE</metric>
97
+ <healthy>80</healthy>
98
+ <unhealthy>0</unhealthy>
99
+ <unstable>0</unstable>
100
+ </hudson.plugins.rubyMetrics.rcov.model.MetricTarget>
101
+ <hudson.plugins.rubyMetrics.rcov.model.MetricTarget>
102
+ <metric>CODE_COVERAGE</metric>
103
+ <healthy>80</healthy>
104
+ <unhealthy>0</unhealthy>
105
+ <unstable>0</unstable>
106
+ </hudson.plugins.rubyMetrics.rcov.model.MetricTarget>
107
+ </targets>
108
+ </hudson.plugins.rubyMetrics.rcov.RcovPublisher>
109
+ </publishers>
110
+ <buildWrappers/>
111
+ <disabled>false</disabled></project>
@@ -0,0 +1,111 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <project>
3
+ <actions/>
4
+ <description>foo [production] tests</description>
5
+ <keepDependencies>false</keepDependencies>
6
+ <properties/>
7
+ <scm class='hudson.plugins.git.GitSCM'>
8
+ <configVersion>1</configVersion>
9
+ <remoteRepositories>
10
+ <org.spearce.jgit.transport.RemoteConfig>
11
+ <string>origin</string>
12
+ <int>5</int>
13
+ <string>fetch</string>
14
+ <string>+refs/heads/*:refs/remotes/origin/*</string>
15
+ <string>receivepack</string>
16
+ <string>git-upload-pack</string>
17
+ <string>uploadpack</string>
18
+ <string>git-upload-pack</string>
19
+ <string>url</string>
20
+ <string>foo_user@git.example.com:foo.git</string>
21
+ <string>tagopt</string>
22
+ <string/>
23
+ </org.spearce.jgit.transport.RemoteConfig>
24
+ </remoteRepositories>
25
+ <branches>
26
+ <hudson.plugins.git.BranchSpec>
27
+ <name>production</name>
28
+ </hudson.plugins.git.BranchSpec>
29
+ </branches>
30
+ <mergeOptions/>
31
+ <recursiveSubmodules>false</recursiveSubmodules>
32
+ <doGenerateSubmoduleConfigurations>false</doGenerateSubmoduleConfigurations>
33
+ <authorOrCommitter>false</authorOrCommitter>
34
+ <clean>false</clean>
35
+ <pruneBranches>false</pruneBranches>
36
+ <buildChooser class='hudson.plugins.git.util.DefaultBuildChooser'/>
37
+ <gitTool>Default</gitTool>
38
+ <submoduleCfg class='list'/>
39
+ <relativeTargetDir/>
40
+ <excludedRegions/>
41
+ <excludedUsers/>
42
+ <skipTag>false</skipTag>
43
+ </scm>
44
+ <assignedNode>slave01</assignedNode>
45
+ <canRoam>false</canRoam>
46
+ <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
47
+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
48
+ <triggers class='vector'>
49
+ <hudson.triggers.SCMTrigger>
50
+ <spec>*/5 * * * *</spec>
51
+ </hudson.triggers.SCMTrigger>
52
+ </triggers>
53
+ <concurrentBuild>false</concurrentBuild>
54
+ <builders>
55
+ <hudson.plugins.rake.Rake>
56
+ <rakeInstallation>(Default)</rakeInstallation>
57
+ <rakeFile/>
58
+ <rakeLibDir/>
59
+ <rakeWorkingDir>foo</rakeWorkingDir>
60
+ <tasks>db:create db:migrate ci:setup:testunit test:test:rcov</tasks>
61
+ <silent>false</silent>
62
+ </hudson.plugins.rake.Rake>
63
+ </builders>
64
+ <publishers>
65
+ <hudson.tasks.junit.JUnitResultArchiver>
66
+ <testResults>**/foo/test/reports/*.xml</testResults>
67
+ <keepLongStdio>false</keepLongStdio>
68
+ <testDataPublishers/>
69
+ </hudson.tasks.junit.JUnitResultArchiver>
70
+ <hudson.plugins.rubyMetrics.railsStats.RailsStatsPublisher>
71
+ <rake>
72
+ <rakeInstallation>(Default)</rakeInstallation>
73
+ <rakeWorkingDir/>
74
+ <tasks>stats</tasks>
75
+ <silent>true</silent>
76
+ </rake>
77
+ <rakeInstallation>(Default)</rakeInstallation>
78
+ <rakeWorkingDir/>
79
+ <task>stats</task>
80
+ </hudson.plugins.rubyMetrics.railsStats.RailsStatsPublisher>
81
+ <hudson.plugins.rubyMetrics.railsNotes.RailsNotesPublisher>
82
+ <rake>
83
+ <rakeInstallation>(Default)</rakeInstallation>
84
+ <rakeWorkingDir/>
85
+ <tasks>notes</tasks>
86
+ <silent>true</silent>
87
+ </rake>
88
+ <rakeInstallation>(Default)</rakeInstallation>
89
+ <rakeWorkingDir/>
90
+ <task>notes</task>
91
+ </hudson.plugins.rubyMetrics.railsNotes.RailsNotesPublisher>
92
+ <hudson.plugins.rubyMetrics.rcov.RcovPublisher>
93
+ <reportDir>foo/coverage/test/</reportDir>
94
+ <targets>
95
+ <hudson.plugins.rubyMetrics.rcov.model.MetricTarget>
96
+ <metric>TOTAL_COVERAGE</metric>
97
+ <healthy>80</healthy>
98
+ <unhealthy>0</unhealthy>
99
+ <unstable>0</unstable>
100
+ </hudson.plugins.rubyMetrics.rcov.model.MetricTarget>
101
+ <hudson.plugins.rubyMetrics.rcov.model.MetricTarget>
102
+ <metric>CODE_COVERAGE</metric>
103
+ <healthy>80</healthy>
104
+ <unhealthy>0</unhealthy>
105
+ <unstable>0</unstable>
106
+ </hudson.plugins.rubyMetrics.rcov.model.MetricTarget>
107
+ </targets>
108
+ </hudson.plugins.rubyMetrics.rcov.RcovPublisher>
109
+ </publishers>
110
+ <buildWrappers/>
111
+ <disabled>false</disabled></project>
@@ -0,0 +1,115 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class ProjectTest < Test::Unit::TestCase
4
+ context 'valid project' do
5
+ setup do
6
+ @dir = File.expand_path('../fixtures/foo_master', __FILE__)
7
+ end
8
+
9
+ should 'not raise exceptions' do
10
+ assert_nothing_raised do
11
+ JenkinsJob::Project.new @dir
12
+ end
13
+ end
14
+
15
+ should 'understand project is enabled' do
16
+ project = JenkinsJob::Project.new @dir
17
+ assert project.enabled?
18
+ assert !project.disabled?
19
+ end
20
+ end
21
+
22
+ context 'invalid project' do
23
+ setup do
24
+ FakeFS.activate!
25
+ FakeFS::FileSystem.clear
26
+ end
27
+
28
+ teardown do
29
+ FakeFS.deactivate!
30
+ end
31
+
32
+ should 'find missing directory' do
33
+ assert_raises RuntimeError do
34
+ JenkinsJob::Project.new 'foo_master'
35
+ end
36
+ end
37
+
38
+ should 'find missing config' do
39
+ FileUtils.mkdir_p 'foo_master'
40
+ assert_raises RuntimeError do
41
+ JenkinsJob::Project.new 'foo_master'
42
+ end
43
+ end
44
+ end
45
+
46
+ context 'alter project' do
47
+ setup do
48
+ File.open(File.expand_path('../fixtures/foo_master/config.xml',
49
+ __FILE__), 'r') do |file|
50
+ @source_xml = file.readlines
51
+ end
52
+
53
+ FakeFS.activate!
54
+ FakeFS::FileSystem.clear
55
+
56
+ FileUtils.mkdir_p 'foo_master'
57
+ File.open('foo_master/config.xml', 'w') do |file|
58
+ file.write @source_xml
59
+ end
60
+ @project = JenkinsJob::Project.new 'foo_master'
61
+ assert @project.enabled?
62
+ end
63
+
64
+ teardown do
65
+ FakeFS.deactivate!
66
+ end
67
+
68
+ should 'enable and disable project' do
69
+ @project.enable
70
+ assert @project.enabled?
71
+
72
+ @project.disable
73
+ assert @project.disabled?
74
+
75
+ @project.enable
76
+ assert @project.enabled?
77
+ end
78
+
79
+ context 'settings' do
80
+ should 'return a project setting' do
81
+ actual = @project.setting('disabled')
82
+ assert_equal 'false', actual.text
83
+ end
84
+
85
+ should "return a nil if setting doesn't exist" do
86
+ actual = @project.setting('foobar')
87
+ assert_nil actual
88
+ end
89
+
90
+ should 'update an existing setting by overwriting it' do
91
+ node = REXML::Element.new 'disabled'
92
+ node.text = 'true'
93
+
94
+ assert @project.enabled?
95
+ @project.update_setting 'disabled', node
96
+ assert @project.disabled?
97
+ end
98
+
99
+ should 'update an existing setting by overwriting it' do
100
+ parent = REXML::Element.new 'foobar_parent'
101
+ node = REXML::Element.new 'foobar'
102
+ node.text = 'hello world'
103
+ parent << node
104
+
105
+
106
+ @project.update_setting 'foobar_parent', parent
107
+ actual_node = @project.setting 'foobar_parent/foobar'
108
+ assert_equal 1, @project.setting('foobar_parent').size
109
+ assert_equal node.text, actual_node.text
110
+ end
111
+
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path('../../lib/jenkins_job',__FILE__)
2
+ require 'test/unit'
3
+ require 'mocha'
4
+ require 'shoulda'
5
+ require 'stringio'
6
+ require 'fakefs/safe'
7
+
8
+ class Object
9
+ def capture(stream)
10
+ begin
11
+ stream = stream.to_s
12
+ eval "$#{stream} = StringIO.new"
13
+ yield
14
+ result = eval("$#{stream}").string
15
+ ensure
16
+ eval("$#{stream} = #{stream.upcase}")
17
+ end
18
+ result
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jenkins_job
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Flavio Castelli
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-02-25 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: thor
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 39
30
+ segments:
31
+ - 0
32
+ - 14
33
+ - 0
34
+ version: 0.14.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 23
46
+ segments:
47
+ - 1
48
+ - 0
49
+ - 0
50
+ version: 1.0.0
51
+ type: :development
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: fakefs
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 17
62
+ segments:
63
+ - 0
64
+ - 3
65
+ - 1
66
+ version: 0.3.1
67
+ type: :development
68
+ version_requirements: *id003
69
+ - !ruby/object:Gem::Dependency
70
+ name: mocha
71
+ prerelease: false
72
+ requirement: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ type: :development
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: shoulda
85
+ prerelease: false
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 3
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ type: :development
96
+ version_requirements: *id005
97
+ description: Handle your Jenkins job configuration files in an easier way.
98
+ email:
99
+ - flavio@castelli.name
100
+ executables:
101
+ - jenkins_job
102
+ extensions: []
103
+
104
+ extra_rdoc_files: []
105
+
106
+ files:
107
+ - .gitignore
108
+ - Gemfile
109
+ - Gemfile.lock
110
+ - README.rdoc
111
+ - Rakefile
112
+ - bin/jenkins_job
113
+ - jenkins_job.gemspec
114
+ - lib/jenkins_job.rb
115
+ - lib/jenkins_job/cli.rb
116
+ - lib/jenkins_job/project.rb
117
+ - lib/jenkins_job/version.rb
118
+ - test/cli_test.rb
119
+ - test/fixtures/foo_master/config.xml
120
+ - test/fixtures/foo_production/config.xml
121
+ - test/project_test.rb
122
+ - test/test_helper.rb
123
+ has_rdoc: true
124
+ homepage:
125
+ licenses: []
126
+
127
+ post_install_message:
128
+ rdoc_options: []
129
+
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ none: false
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ hash: 3
138
+ segments:
139
+ - 0
140
+ version: "0"
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ none: false
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ hash: 23
147
+ segments:
148
+ - 1
149
+ - 3
150
+ - 6
151
+ version: 1.3.6
152
+ requirements: []
153
+
154
+ rubyforge_project: jenkins_job
155
+ rubygems_version: 1.5.2
156
+ signing_key:
157
+ specification_version: 3
158
+ summary: Simple cli tool created to manage Jenkins job files.
159
+ test_files: []
160
+