jenkins_job 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+