jenkins-capistrano 0.0.2 → 0.0.3

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/README.rst ADDED
@@ -0,0 +1,86 @@
1
+ ==================
2
+ jenkins-capistrano
3
+ ==================
4
+
5
+ The capistrano tasks for Jenkins CI Server
6
+
7
+ Installation
8
+ ============
9
+
10
+ Add this line to your application's Gemfile::
11
+
12
+ gem 'jenkins-capistrano'
13
+
14
+ And then execute::
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as::
19
+
20
+ $ gem install jenkins-capistrano
21
+
22
+ Example
23
+ =======
24
+
25
+ Job Configuration
26
+ ~~~~~~~~~~~~~~~~~
27
+
28
+ The following code will creates or updates Jenkins jobs before each deploy task:
29
+
30
+ config directory structure(name your config.xml as a job name)::
31
+
32
+ config
33
+ ├── deploy.rb
34
+ └── jenkins
35
+    └── jobs
36
+    ├── job-name1.xml
37
+    ├── job-name2.xml
38
+    └── job-name3.xml
39
+
40
+
41
+ deploy.rb::
42
+
43
+ set :application, "your-awesome-app"
44
+ set :scm, :git
45
+ set :repository, "https://github.com/your/repository.git"
46
+
47
+ set :jenkins_host, 'http://localhost:8080'
48
+ # set :jenkins_username, '' # default empty
49
+ # set :jenkins_password, '' # default empty
50
+ # set :jenkins_job_config_dir, 'config/jenkins/jobs'
51
+
52
+ before 'deploy', 'jenkins:deploy_jobs'
53
+
54
+ Node Configuration
55
+ ~~~~~~~~~~~~~~~~~~
56
+
57
+ config directory structure::
58
+
59
+ config
60
+ ├── deploy.rb
61
+ └── jenkins
62
+    └── nodes
63
+    ├── node1.json
64
+    ├── node2.json
65
+    └── node3.json
66
+
67
+ deploy.rb::
68
+
69
+ set :application, "your-awesome-app"
70
+ set :scm, :git
71
+ set :repository, "https://github.com/your/repository.git"
72
+
73
+ set :jenkins_host, 'http://localhost:8080'
74
+ # set :jenkins_username, '' # default empty
75
+ # set :jenkins_password, '' # default empty
76
+ # set :jenkins_node_config_dir, 'config/jenkins/nodes'
77
+
78
+ before 'deploy', 'jenkins:config_nodes'
79
+
80
+ ## Contributing
81
+
82
+ 1. Fork it
83
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
84
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
85
+ 4. Push to the branch (`git push origin my-new-feature`)
86
+ 5. Create new Pull Request
@@ -16,8 +16,9 @@ Gem::Specification.new do |gem|
16
16
  gem.version = Jenkins::Capistrano::VERSION
17
17
 
18
18
  gem.add_dependency 'capistrano'
19
- gem.add_dependency 'httparty', '~> 0.6.1'
19
+ gem.add_dependency 'httparty', '~> 0.8.3'
20
20
  gem.add_dependency 'hpricot'
21
21
 
22
22
  gem.add_development_dependency 'rake'
23
+ gem.add_development_dependency 'pry'
23
24
  end
@@ -18,15 +18,22 @@ Capistrano::Configuration.instance(:must_exist).load do
18
18
  _cset(:jenkins_password) { '' }
19
19
 
20
20
  _cset(:jenkins_job_config_dir) { 'config/jenkins/jobs' }
21
+ _cset(:jenkins_node_config_dir) { 'config/jenkins/nodes' }
21
22
 
22
23
  def client
23
24
  @client ||= Jenkins::Client.new(jenkins_host, { :username => jenkins_username, :password => jenkins_password})
24
25
  end
25
26
 
26
27
  def job_configs
28
+ abort "Please create the jenkins_job_config_dir first: #{jenkins_job_config_dir}" unless Dir.exists? jenkins_job_config_dir
27
29
  Dir.glob("#{jenkins_job_config_dir}/*.xml")
28
30
  end
29
31
 
32
+ def node_configs
33
+ abort "Please create the jenkins_node_config_dir first: #{jenkins_node_config_dir}" unless Dir.exists? jenkins_node_config_dir
34
+ Dir.glob("#{jenkins_node_config_dir}/*.json")
35
+ end
36
+
30
37
  # minimum configurations
31
38
  #
32
39
  # role :jenkins, 'localhost:8080'
@@ -41,7 +48,7 @@ Capistrano::Configuration.instance(:must_exist).load do
41
48
  task :deploy_jobs do
42
49
  strategy = fetch(:jenkins_job_deploy_strategy, :clean)
43
50
  logger.info "deploying jenkins jobs to #{jenkins_host}"
44
- logger.warn "no job configs found." if job_configs.empty?
51
+ logger.important "no job configs found." if job_configs.empty?
45
52
  job_configs.each do |file|
46
53
  name = File.basename(file, '.xml')
47
54
  client.create_or_update_job(name, File.read(file))
@@ -50,6 +57,26 @@ Capistrano::Configuration.instance(:must_exist).load do
50
57
 
51
58
  end
52
59
 
60
+ desc <<-DESC
61
+ Configure the nodes to Jenkins server -- meaning create or update --
62
+
63
+ set :jenkins_node_config_dir, 'config/jenkins/nodes'
64
+ set :jenkins_node_deploy_strategy, :clean | :merge
65
+ DESC
66
+ task :config_nodes do
67
+ strategy = fetch(:jenkins_node_deploy_strategy, :clean)
68
+ logger.info "configuring jenkins nodes to #{jenkins_host}"
69
+ logger.important "no node configs found." if node_configs.empty?
70
+ node_configs.each do |file|
71
+ name = File.basename(file, '.json')
72
+ opts = JSON.parse(File.read(file)).to_hash.
73
+ inject({}) { |mem, (key, val)| mem[key.to_sym] = val; mem }
74
+ client.config_node(name, opts)
75
+ logger.trace "node #{name} created."
76
+ end
77
+
78
+ end
79
+
53
80
  end
54
81
 
55
82
  end
@@ -1,5 +1,6 @@
1
1
  require 'httparty'
2
2
  require 'cgi/util'
3
+ require 'json'
3
4
 
4
5
  module Jenkins
5
6
  class Client
@@ -37,6 +38,42 @@ module Jenkins
37
38
  end
38
39
  end
39
40
 
41
+ def add_node(name, opts = {})
42
+ options = default_node_options.merge(opts)
43
+ options[:name] = name
44
+ options[:labels] = options[:labels].split(/\s*,\s*/).join(' ') if options[:labels]
45
+
46
+ response = post_form("/computer/doCreateItem", node_form_fields(options))
47
+ case response
48
+ when Net::HTTPFound
49
+ { :name => options[:name], :slave_host => options[:slave_host] }
50
+ else
51
+ raise ServerError, parse_error_message(response)
52
+ end
53
+ end
54
+
55
+ def update_node(name, opts = {})
56
+ options = default_node_options.merge(opts)
57
+ options[:name] = name
58
+ options[:labels] = options[:labels].split(/\s*,\s*/).join(' ') if options[:labels]
59
+
60
+ response = post_form("/computer/#{CGI::escape(name)}/configSubmit", node_form_fields(options))
61
+ case response
62
+ when Net::HTTPFound
63
+ { :name => options[:name], :slave_host => options[:slave_host] }
64
+ else
65
+ raise ServerError, parse_error_message(response)
66
+ end
67
+ end
68
+
69
+ def config_node(name, opts = {})
70
+ begin
71
+ add_node(name, opts)
72
+ rescue ServerError => e
73
+ update_node(name, opts)
74
+ end
75
+ end
76
+
40
77
  private
41
78
  def xml_body(xml_str)
42
79
  {
@@ -52,6 +89,57 @@ module Jenkins
52
89
  error_msg = doc.search("td#main-panel p")
53
90
  error_msg.inner_text.empty? ? "Server error: code=#{response.code}, #{response.body}" : error_msg
54
91
  end
92
+
93
+ def post_form(path, fields)
94
+ url = URI.parse("#{self.class.base_uri}/#{path}")
95
+ req = Net::HTTP::Post.new(url.path)
96
+
97
+ basic_auth = self.class.default_options[:basic_auth]
98
+ req.basic_auth basic_auth[:username], basic_auth[:password] if basic_auth
99
+
100
+ req.set_form_data(fields)
101
+ http = Net::HTTP.new(url.host, url.port)
102
+ http.request(req)
103
+ end
104
+
105
+ def default_node_options
106
+ {
107
+ :slave_port => 22,
108
+ :slave_user => 'jenkins',
109
+ :master_key => "/var/lib/jenkins/.ssh/id_rsa",
110
+ :slave_fs => "/data/jenkins-slave/",
111
+ :description => "Automatically created by capistrano-jenkins",
112
+ :executors => 2,
113
+ :exclusive => true
114
+ }
115
+ end
116
+
117
+ def node_form_fields(options = {})
118
+ {
119
+ "name" => options[:name],
120
+ "type" => "hudson.slaves.DumbSlave$DescriptorImpl",
121
+ "json" => {
122
+ "name" => options[:name],
123
+ "type" => "hudson.slaves.DumbSlave$DescriptorImpl",
124
+ "nodeDescription" => options[:description],
125
+ "numExecutors" => options[:executors],
126
+ "remoteFS" => options[:slave_fs],
127
+ "labelString" => options[:labels],
128
+ "mode" => options[:exclusive] ? "EXCLUSIVE" : "NORMAL",
129
+ "retentionStrategy" => { "stapler-class" => "hudson.slaves.RetentionStrategy$Always" },
130
+ "nodeProperties" => { "stapler-class-bag" => "true" },
131
+ "launcher" => {
132
+ "stapler-class" => "hudson.plugins.sshslaves.SSHLauncher",
133
+ "host" => options[:slave_host],
134
+ "port" => options[:slave_port],
135
+ "username" => options[:slave_user],
136
+ "privatekey" => options[:master_key],
137
+ }
138
+ }.to_json
139
+ }
140
+ end
141
+
142
+
55
143
  end
56
144
  end
57
145
 
@@ -1,5 +1,5 @@
1
1
  module Jenkins
2
2
  module Capistrano
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jenkins-capistrano
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 0.6.1
37
+ version: 0.8.3
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 0.6.1
45
+ version: 0.8.3
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: hpricot
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -75,6 +75,22 @@ dependencies:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: pry
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
78
94
  description: The capistrano tasks for Jenkins CI Server
79
95
  email:
80
96
  - cynipe@gmail.com
@@ -85,7 +101,7 @@ files:
85
101
  - .gitignore
86
102
  - Gemfile
87
103
  - LICENSE
88
- - README.md
104
+ - README.rst
89
105
  - Rakefile
90
106
  - jenkins-capistrano.gemspec
91
107
  - lib/jenkins-capistrano.rb
@@ -105,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
105
121
  version: '0'
106
122
  segments:
107
123
  - 0
108
- hash: -981150246330867854
124
+ hash: 2715284464672624709
109
125
  required_rubygems_version: !ruby/object:Gem::Requirement
110
126
  none: false
111
127
  requirements:
@@ -114,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
130
  version: '0'
115
131
  segments:
116
132
  - 0
117
- hash: -981150246330867854
133
+ hash: 2715284464672624709
118
134
  requirements: []
119
135
  rubyforge_project:
120
136
  rubygems_version: 1.8.24
data/README.md DELETED
@@ -1,53 +0,0 @@
1
- # jenkins-capistrano
2
-
3
- The capistrano tasks for Jenkins CI Server
4
-
5
- ## Installation
6
-
7
- Add this line to your application's Gemfile:
8
-
9
- gem 'jenkins-capistrano'
10
-
11
- And then execute:
12
-
13
- $ bundle
14
-
15
- Or install it yourself as:
16
-
17
- $ gem install jenkins-capistrano
18
-
19
- ## Example
20
-
21
- The following code will creates or updates Jenkins jobs before each deploy task:
22
-
23
- config directory structure(name your config.xml as a job name):
24
-
25
- config
26
- ├── deploy.rb
27
- └── jenkins
28
-    └── jobs
29
-    ├── job-name1.xml
30
-    ├── job-name2.xml
31
-    └── job-name3.xml
32
-
33
-
34
- deploy.rb:
35
-
36
- set :application, "your-awesome-app"
37
- set :scm, :git
38
- set :repository, "https://github.com/your/repository.git"
39
-
40
- set :jenkins_host, 'http://localhost:8080'
41
- # set :jenkins_username, '' # default empty
42
- # set :jenkins_password, '' # default empty
43
- # set :jenkins_job_config_dir, 'config/jenkins/jobs'
44
-
45
- before 'deploy', 'jenkins:deploy_jobs'
46
-
47
- ## Contributing
48
-
49
- 1. Fork it
50
- 2. Create your feature branch (`git checkout -b my-new-feature`)
51
- 3. Commit your changes (`git commit -am 'Added some feature'`)
52
- 4. Push to the branch (`git push origin my-new-feature`)
53
- 5. Create new Pull Request