kstrano 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/bin/kumafy ADDED
@@ -0,0 +1,251 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'fileutils'
5
+ require 'highline'
6
+ require 'net/http'
7
+ require 'net/https'
8
+ require 'uri'
9
+
10
+ DEPLOY_GIST = "https://raw.github.com/Kunstmaan/kStrano/master/config/deploy.rb"
11
+ PRODUCTION_GIST = "https://raw.github.com/Kunstmaan/kStrano/master/config/production.rb"
12
+ STAGING_GIST = "https://raw.github.com/Kunstmaan/kStrano/master/config/staging.rb"
13
+
14
+ BUILD_GIST = "https://raw.github.com/Kunstmaan/kStrano/master/config/build.xml"
15
+ PHPCS_GIST = "https://raw.github.com/Kunstmaan/kStrano/master/config/phpcs.xml"
16
+ PHPMD_GIST = "https://raw.github.com/Kunstmaan/kStrano/master/config/phpmd.xml"
17
+ PHPUNIT_GIST = "https://raw.github.com/Kunstmaan/kStrano/master/config/phpunit.xml.dist"
18
+
19
+ def update_capfile(base, context, force)
20
+ file = File.join(base, "Capfile")
21
+
22
+ if !File.exists?("Capfile")
23
+ abort "Make sure the project has been capified or capifonied."
24
+ else
25
+ includestr = "load Gem.find_files('kstrano.rb').last.to_s"
26
+ fcontent = ""
27
+ File.open(file, "r") do |f|
28
+ f.each do |line|
29
+ fcontent << line
30
+ if line.include? includestr
31
+ abort "This project is already kumafied!" unless force
32
+ return
33
+ end
34
+ end
35
+ end
36
+
37
+ File.open(file, "w") do |f|
38
+ fcontent.each_line do |line|
39
+ if line.include? "load 'app/config/deploy'"
40
+ f.print includestr + "\r\n"
41
+ end
42
+ f.print line
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def update_deploy_config(ui, base, context, force)
49
+
50
+ deploy = File.join(base, "app", "config", "deploy.rb")
51
+ write_deploy = true
52
+ #if File.exists?(deploy)
53
+ #overwrite = ui.ask("The file #{deploy} already exists, do you want to override it? ") { |q| q.default = 'n' }
54
+ #if !overwrite.match(/^y/)
55
+ # write_deploy = false
56
+ #end
57
+ #end
58
+
59
+ if write_deploy
60
+ deploy_gist = get_plain_secure(DEPLOY_GIST).body
61
+ context["app_name"] ||= ui.ask("What's the name of the application?")
62
+ app_name = context["app_name"]
63
+ deploy_gist.gsub!(/(:application,\s)(\"\")/, '\1' + "\"#{app_name}\"")
64
+ deploy_gist.gsub!(/(:admin_runner,\s)(\"\")/, '\1' + "\"#{app_name}\"")
65
+
66
+ campfire_room = ui.ask("What's the name of the campfire room for this project?")
67
+ if !campfire_room.nil? && !campfire_room.empty?
68
+ deploy_gist.gsub!(/(:campfire_room,\s)(nil)/, '\1' + "\"#{campfire_room}\"")
69
+ context["campfire_room"] = campfire_room
70
+ end
71
+
72
+ airbrake_api_key = ui.ask("What's the api key of this project for airbrake?")
73
+ if !airbrake_api_key.nil? && !airbrake_api_key.empty?
74
+ deploy_gist.gsub!(/(:airbrake_api_key,\s)(nil)/, '\1' + "\"#{airbrake_api_key}\"")
75
+ context["airbrake_api_key"] = airbrake_api_key
76
+ end
77
+
78
+ File.open(deploy, "w") do |f|
79
+ deploy_gist.each_line do |line|
80
+ f.print line
81
+ end
82
+ end
83
+ end
84
+
85
+ deploy_dir = File.join(base, "app", "config", "deploy")
86
+ Dir.mkdir(deploy_dir) unless File.directory?(deploy_dir)
87
+
88
+ {
89
+ "production" => PRODUCTION_GIST,
90
+ "staging" => STAGING_GIST
91
+ }.each do |env, gist|
92
+ file = File.join(deploy_dir, "#{env}.rb")
93
+ write = true
94
+
95
+ if File.exists?(file)
96
+ overwrite = ui.ask("The file #{file} already exists, do you want to override it? ") { |q| q.default = 'n' }
97
+ if !overwrite.match(/^y/)
98
+ write = false
99
+ end
100
+ end
101
+
102
+ if write
103
+ gist_body = get_plain_secure(gist).body
104
+ server = ui.ask("On which server is the #{env} environment deployed?")
105
+ if !server.match(/^.*\.kunstmaan\.be$/)
106
+ server = "#{server}.kunstmaan.be"
107
+ end
108
+
109
+ gist_body.gsub!(/(:domain,\s)(\"\")/, '\1' + "\"#{server}\"")
110
+
111
+ File.open(file, "w") do |f|
112
+ gist_body.each_line do |line|
113
+ f.print line
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+
121
+ def update_jenkins_config(ui, base, context, force)
122
+ file = File.join(base, "build.xml")
123
+ write = true
124
+
125
+ if File.exists?(file)
126
+ overwrite = ui.ask("The file #{file} already exists, do you want to override it? ") { |q| q.default = 'n' }
127
+ if !overwrite.match(/^y/)
128
+ write = false
129
+ end
130
+ end
131
+
132
+ if write
133
+ gist_body = get_plain_secure(BUILD_GIST).body
134
+
135
+ context["app_name"] ||= ui.ask("What's the name of the application?")
136
+ app_name = context["app_name"]
137
+ gist_body.gsub!(/(\<project\sname=)(\"\")/, '\1' + "\"#{app_name}\"")
138
+
139
+ File.open(file, "w") do |f|
140
+ gist_body.each_line do |line|
141
+ f.print line
142
+ end
143
+ end
144
+ end
145
+
146
+ build_dir = File.join(base, "build")
147
+ Dir.mkdir(build_dir) unless File.directory?(build_dir)
148
+
149
+ {
150
+ File.join(build_dir, "phpcs.xml") => PHPCS_GIST,
151
+ File.join(build_dir, "phpmd.xml") => PHPMD_GIST,
152
+ File.join(base, "app", "phpunit.xml.dist") => PHPUNIT_GIST
153
+ }.each do |file, gist|
154
+ write = true
155
+
156
+ if File.exists?(file)
157
+ overwrite = ui.ask("The file #{file} already exists, do you want to override it? ") { |q| q.default = 'n' }
158
+ if !overwrite.match(/^y/)
159
+ write = false
160
+ end
161
+ end
162
+
163
+ if write
164
+ gist_body = get_plain_secure(gist).body
165
+
166
+ File.open(file, "w") do |f|
167
+ gist_body.each_line do |line|
168
+ f.print line
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ end
175
+
176
+ def get_plain_secure(url)
177
+ uri = URI.parse url
178
+ http = Net::HTTP.new(uri.host, uri.port)
179
+ http.use_ssl = uri.is_a?(URI::HTTPS)
180
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl?
181
+ http.start { |http| http.get(uri.path, {}) }
182
+ end
183
+
184
+ def validate_path
185
+ if ARGV.empty?
186
+ abort "Please specify the directory to kumafy, e.g. `#{File.basename($0)} .'"
187
+ elsif !File.exists?(ARGV.first)
188
+ abort "`#{ARGV.first}' does not exist."
189
+ elsif !File.directory?(ARGV.first)
190
+ abort "`#{ARGV.first}' is not a directory."
191
+ elsif ARGV.length > 1
192
+ abort "Too many arguments; please specify only the directory to kumafy."
193
+ end
194
+ end
195
+
196
+ force = false
197
+
198
+ OptionParser.new do |opts|
199
+ opts.banner = "Usage: #{File.basename($0)} [path]"
200
+
201
+ opts.on("-h", "--help", "Displays this help info") do
202
+ puts opts
203
+ exit 0
204
+ end
205
+
206
+ opts.on("-c", "--config", "Creates the configuration files needed for deployment") do
207
+ validate_path
208
+ ui = HighLine.new
209
+ base = ARGV.shift
210
+ context = Hash.new
211
+ update_deploy_config ui, base, context, force
212
+ exit 0
213
+ end
214
+
215
+ opts.on("-j", "--jenkins", "Creates the jenkins configuration files for this project") do
216
+ validate_path
217
+ ui = HighLine.new
218
+ base = ARGV.shift
219
+ context = Hash.new
220
+ update_jenkins_config ui, base, context, force
221
+ exit 0
222
+ end
223
+
224
+ opts.on("-f", "--force", "This will force the kumafying of the project") do
225
+ force = true
226
+ end
227
+
228
+ begin
229
+ opts.parse!(ARGV)
230
+ rescue OptionParser::ParseError => e
231
+ warn e.message
232
+ puts opts
233
+ exit 1
234
+ end
235
+ end
236
+
237
+ validate_path
238
+
239
+ ui = HighLine.new
240
+ base = ARGV.shift
241
+ context = Hash.new
242
+
243
+ puts "[start] kcapifony"
244
+ %x(kcapifony .)
245
+ puts "[end] kcapifony"
246
+
247
+ update_capfile base, context, force
248
+ update_deploy_config ui, base, context, force
249
+ update_jenkins_config ui, base, context, force
250
+
251
+ puts "[done] project kumafied!"
@@ -0,0 +1,33 @@
1
+ module Kumastrano
2
+ # Using the gem https://github.com/airbrake/airbrake doesn't work because it's made for rails apps, it needs rake etc. + you need to have the i18n gem
3
+ # This will integrate a very easy command to tell airbrake a deploy has been done
4
+ class AirbrakeHelper
5
+
6
+ require 'net/http'
7
+ require 'uri'
8
+ require 'etc'
9
+
10
+ def self.notify(api_key, revision, repository, environment = 'production', username = Etc.getlogin.capitalize)
11
+ uri = URI.parse("http://airbrake.io")
12
+
13
+ params = {
14
+ 'api_key' => api_key,
15
+ 'deploy[rails_env]' => environment, # Environment of the deploy (production, staging), this needs to be the current environment
16
+ 'deploy[scm_revision]' => revision, # The given revision/sha that is being deployed, this needs to be the current_revision variable
17
+ 'deploy[scm_repository]' => repository, # Address of your repository to help with code lookups
18
+ 'deploy[local_username]' => username # Who is deploying
19
+ }
20
+
21
+ post = Net::HTTP::Post.new("/deploys")
22
+ post.set_form_data(params)
23
+
24
+ res = Net::HTTP.start(uri.host, uri.port) {|http| http.request(post)}
25
+
26
+ if res.code.to_i == 200
27
+ return true
28
+ else
29
+ return false
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,25 @@
1
+ module Kumastrano
2
+ class CampfireHelper
3
+
4
+ require 'broach'
5
+
6
+ def self.speak(campfire_account, campfire_token, campfire_room, message="")
7
+ ## extracted this to here, because i don't know how to call capistrano tasks with arguments
8
+ ## else i just had to make one capistrano task which i could call
9
+ if !campfire_account.nil? && !campfire_token.nil? && !campfire_room.nil?
10
+
11
+ Broach.settings = {
12
+ 'account' => campfire_account,
13
+ 'token' => campfire_token,
14
+ 'use_ssl' => true
15
+ }
16
+
17
+ room = Broach::Room.find_by_name campfire_room
18
+
19
+ if !room.nil?
20
+ room.speak message
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ module Kumastrano
2
+ class GitHelper
3
+
4
+ require 'cgi'
5
+
6
+ def self.fetch
7
+ %x(git fetch)
8
+ end
9
+
10
+ def self.merge_base(commit1, commit2 = "HEAD")
11
+ base = %x(git merge-base #{commit1} #{commit2})
12
+ base.strip
13
+ end
14
+
15
+ def self.commit_hash(commit = "HEAD")
16
+ hash = %x(git rev-parse #{commit})
17
+ hash.strip
18
+ end
19
+
20
+ def self.branch_name(commit = "HEAD")
21
+ name = %x(git name-rev --name-only #{commit})
22
+ name.strip
23
+ end
24
+
25
+ def self.origin_refspec
26
+ refspec = %x(git config remote.origin.fetch)
27
+ refspec.strip
28
+ end
29
+
30
+ def self.origin_url
31
+ url = %x(git config remote.origin.url)
32
+ url.strip
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,132 @@
1
+ module Kumastrano
2
+ class JenkinsHelper
3
+
4
+ require 'cgi'
5
+ require 'net/http'
6
+ require 'uri'
7
+ require 'json'
8
+
9
+ def self.available?(base_uri)
10
+ res = get_plain("#{base_uri}")
11
+ res.code.to_i == 200
12
+ end
13
+
14
+ def self.build_and_wait(job_uri, timeout=300, interval=2)
15
+ success = false
16
+ last_build_info = nil
17
+ prev_build = Kumastrano::JenkinsHelper.last_build_number(job_uri)
18
+ Kumastrano::JenkinsHelper.build_job(job_uri)
19
+ Kumastrano.poll("A timeout occured", timeout, interval) do
20
+ ## wait for the building to be finished
21
+ last_build_info = Kumastrano::JenkinsHelper.build_info(job_uri)
22
+ result = last_build_info['result'] ## SUCCESS or FAILURE
23
+ building = last_build_info['building']
24
+ number = last_build_info['number']
25
+ if number == (prev_build + 1) && "false" == building.to_s && !result.nil?
26
+ if "SUCCESS" == result
27
+ success = true
28
+ else
29
+ success = false
30
+ end
31
+ true
32
+ else
33
+ false
34
+ end
35
+ end
36
+ return success, last_build_info
37
+ end
38
+
39
+ def self.fetch_build_hash_from_build_info(build_info, branch_name)
40
+ actions = build_info['actions']
41
+
42
+ build_hash = nil
43
+ actions.each do |list|
44
+ last_revision = list['lastBuiltRevision']
45
+ if !last_revision.nil? && branch_name == last_revision['branch'][0]['name'].sub("origin/", "")
46
+ build_hash = last_revision['branch'][0]['SHA1']
47
+ break
48
+ end
49
+ end
50
+
51
+ build_hash
52
+ end
53
+
54
+ def self.make_safe_job_name(app_name, branch_name)
55
+ job_name = "#{app_name} (#{branch_name})"
56
+ job_name.gsub(/[#*\/\\]/, "-") # \/#* is unsafe for jenkins job name, because not uri safe
57
+ end
58
+
59
+ def self.job_url_for_branch(jenkins_base_uri, branch_name)
60
+ current_job_url = nil
61
+ Kumastrano::JenkinsHelper.list_jobs(jenkins_base_uri).each do |job|
62
+ name = job["name"]
63
+ url = job["url"]
64
+ if /.*\(#{branch_name}\)/.match(name)
65
+ current_job_url = url
66
+ break
67
+ end
68
+ end
69
+ current_job_url
70
+ end
71
+
72
+ def self.job_url_for_name(jenkins_base_uri, job_name)
73
+ current_job_url = nil
74
+ Kumastrano::JenkinsHelper.list_jobs(jenkins_base_uri).each do |job|
75
+ name = job["name"]
76
+ url = job["url"]
77
+ if job_name == name
78
+ current_job_url = url
79
+ break
80
+ end
81
+ end
82
+ current_job_url
83
+ end
84
+
85
+ def self.list_jobs(base_uri)
86
+ res = get_plain("#{base_uri}/api/json?tree=jobs[name,url]")
87
+ parsed_res = JSON.parse(res.body)["jobs"]
88
+ end
89
+
90
+ def self.create_new_job(base_uri, job_name, config)
91
+ uri = URI.parse("#{base_uri}/createItem/api/json")
92
+ request = Net::HTTP::Post.new(uri.path + "?name=#{CGI.escape(job_name)}")
93
+ request.body = config
94
+ request["Content-Type"] = "application/xml"
95
+ res = Net::HTTP.start(uri.host, uri.port) {|http| http.request(request)}
96
+ if res.code.to_i == 200
97
+ puts "job created"
98
+ else
99
+ puts "job not created"
100
+ puts res.body
101
+ end
102
+ end
103
+
104
+ def self.retrieve_config_xml(job_uri)
105
+ res = get_plain("#{job_uri}/config.xml").body
106
+ end
107
+
108
+ def self.build_job(job_uri)
109
+ res = get_plain("#{job_uri}/build")
110
+ res.code.to_i == 302
111
+ end
112
+
113
+ def self.last_build_number(job_uri)
114
+ res = get_plain("#{job_uri}/api/json?tree=lastBuild[number]")
115
+ parsed_res = JSON.parse(res.body)
116
+ parsed_res['lastBuild']['number']
117
+ end
118
+
119
+ def self.build_info(job_uri, build="lastBuild")
120
+ res = get_plain("#{job_uri}/#{build}/api/json")
121
+ parsed_res = JSON.parse(res.body)
122
+ end
123
+
124
+ private
125
+
126
+ def self.get_plain(uri)
127
+ uri = URI.parse uri
128
+ res = Net::HTTP.start(uri.host, uri.port) { |http| http.get(uri.path, {}) }
129
+ end
130
+
131
+ end
132
+ end
@@ -0,0 +1,27 @@
1
+ module Kumastrano
2
+
3
+ def poll(msg=nil, seconds=10.0, interval_seconds=1.0)
4
+ (seconds / interval_seconds).to_i.times do
5
+ result = yield
6
+ return if result
7
+ sleep interval_seconds
8
+ end
9
+ msg ||= "polling failed after #{seconds} seconds"
10
+ raise msg
11
+ end
12
+
13
+ def say(text)
14
+ Capistrano::CLI.ui.say(" * #{text}")
15
+ end
16
+
17
+ def ask(question, default='n')
18
+ agree = Capistrano::CLI.ui.agree(" #{question} ") do |q|
19
+ q.default = default
20
+ end
21
+
22
+ agree
23
+ end
24
+
25
+ module_function :poll, :say, :ask
26
+
27
+ end
data/lib/kstrano.rb ADDED
@@ -0,0 +1,298 @@
1
+ set :jenkins_base_uri, ""
2
+ set :jenkins_base_job_name, "Default"
3
+ set :jenkins_poll_timeout, 300
4
+ set :jenkins_poll_interval, 2
5
+ set :jenkins_enabled, false
6
+
7
+ set :campfire_room, nil
8
+ set :campfire_token, "" ## kbot
9
+ set :campfire_account, "Kunstmaan"
10
+
11
+ set :airbrake_api_key, nil
12
+
13
+
14
+ require "#{File.dirname(__FILE__)}/helpers/git_helper.rb"
15
+ require "#{File.dirname(__FILE__)}/helpers/jenkins_helper.rb"
16
+ require "#{File.dirname(__FILE__)}/helpers/airbrake_helper.rb"
17
+ require "#{File.dirname(__FILE__)}/helpers/campfire_helper.rb"
18
+ require "#{File.dirname(__FILE__)}/helpers/kuma_helper.rb"
19
+ require 'rexml/document'
20
+ require 'etc'
21
+
22
+ namespace :kuma do
23
+
24
+ desc "Run fixcron for the current project"
25
+ task :fixcron do
26
+ sudo "sh -c 'if [ -f /opt/kDeploy/tools/fixcron.py ] ; then cd /opt/kDeploy/tools/; python fixcron.py #{application}; fi'"
27
+ end
28
+
29
+ desc "Run fixperms for the current project"
30
+ task :fixperms do
31
+ sudo "sh -c 'if [ -f /opt/kDeploy/tools/fixperms.py ] ; then cd /opt/kDeploy/tools/; python fixperms.py #{application}; fi'"
32
+ end
33
+
34
+ end
35
+
36
+ namespace :airbrake do
37
+
38
+ desc "Register a deploy with airbrake.io"
39
+ task :notify do
40
+ if !airbrake_api_key.nil?
41
+ revision = Kumastrano::GitHelper::commit_hash
42
+ repository = Kumastrano::GitHelper::origin_url
43
+ env ||= "production"
44
+ success = Kumastrano::AirbrakeHelper.notify airbrake_api_key, revision, repository, env
45
+ Kumastrano.say "Failed notifying airbrake of the new deploy" unless success
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ namespace :campfire do
52
+
53
+ desc "Say something on campfire"
54
+ task:say do
55
+ if !campfire_room.nil?
56
+ message = ARGV.join(' ').gsub('campfire:say', '')
57
+ Kumastrano::CampfireHelper.speak campfire_account, campfire_token, campfire_room, message
58
+ exit
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ namespace :jenkins do
65
+
66
+ desc "create a job for the current branch and application on Jenkins"
67
+ task:create_job do
68
+ ## 1. locate the job in jenkins
69
+ current_branch = Kumastrano::GitHelper.branch_name
70
+ job_name = Kumastrano::JenkinsHelper.make_safe_job_name(application, current_branch)
71
+ current_job_url = Kumastrano::JenkinsHelper.job_url_for_name(jenkins_base_uri, job_name)
72
+
73
+ ## 2. if no job was found, first create a job for this branch
74
+ if current_job_url.nil?
75
+ Kumastrano.say "no job found for branch #{current_branch} on #{application}, we'll create one now"
76
+ default_job_url = Kumastrano::JenkinsHelper.job_url_for_name(jenkins_base_uri, jenkins_base_job_name)
77
+ if !default_job_url.nil?
78
+ current_refspec = Kumastrano::GitHelper.origin_refspec
79
+ current_url = Kumastrano::GitHelper.origin_url
80
+
81
+ default_job_config = Kumastrano::JenkinsHelper.retrieve_config_xml default_job_url
82
+ document = REXML::Document.new default_job_config
83
+ root = document.root
84
+
85
+ ## change the description
86
+ root.elements['description'].text = "This job will be used for testing the branch #{current_branch}"
87
+
88
+ ## change the git config
89
+ git_element = root.elements["scm[@class='hudson.plugins.git.GitSCM']"]
90
+ git_element.elements["userRemoteConfigs/hudson.plugins.git.UserRemoteConfig/refspec"].text = current_refspec
91
+ git_element.elements["userRemoteConfigs/hudson.plugins.git.UserRemoteConfig/url"].text = current_url
92
+ git_element.elements["branches/hudson.plugins.git.BranchSpec/name"].text = current_branch
93
+
94
+ ## create the new job based on the modified git config
95
+ Kumastrano::JenkinsHelper.create_new_job(jenkins_base_uri, job_name, document.to_s)
96
+ current_job_url = Kumastrano::JenkinsHelper.job_url_for_name(jenkins_base_uri, job_name)
97
+ end
98
+ else
99
+ Kumastrano.say "there was already a job available on Jenkins for branch #{current_branch} on #{application}"
100
+ end
101
+
102
+ current_job_url
103
+ end
104
+
105
+ desc "Try to build the current branch on Jenkins"
106
+ task:build do
107
+ current_job_url = jenkins::create_job
108
+ current_branch = Kumastrano::GitHelper.branch_name
109
+
110
+ if !current_job_url.nil?
111
+ job_name = Kumastrano::JenkinsHelper.make_safe_job_name(application, current_branch)
112
+ prev_build = Kumastrano::JenkinsHelper.last_build_number current_job_url
113
+ Kumastrano.say "start building build ##{(prev_build + 1)} on job #{job_name}, this can take a while"
114
+
115
+ result, last_build_info = Kumastrano::JenkinsHelper.build_and_wait current_job_url, jenkins_poll_timeout, jenkins_poll_interval
116
+
117
+ message = ""
118
+ if result
119
+ Kumastrano.say "the build was succesful"
120
+ message = "was a success"
121
+ else
122
+ Kumastrano.say "the build failed"
123
+ message = "failed"
124
+ end
125
+
126
+ Kumastrano::CampfireHelper.speak campfire_account, campfire_token, campfire_room, "#{Etc.getlogin.capitalize} just builded a new version of #{current_branch} on #{application} and it #{message}. You can view the results here #{current_job_url}/lastBuild."
127
+ else
128
+ Kumastrano.say "no job found for #{job_name}, cannot build"
129
+ end
130
+ end
131
+
132
+ end
133
+
134
+ namespace :deploy do
135
+
136
+ task :symlink, :except => { :no_release => true } do
137
+ on_rollback do
138
+ if previous_release
139
+ try_sudo "ln -sf #{previous_release} #{current_path}; true"
140
+ else
141
+ logger.important "no previous release to rollback to, rollback of symlink skipped"
142
+ end
143
+ end
144
+
145
+ try_sudo "ln -sfT #{latest_release} #{current_path}"
146
+ end
147
+
148
+ end
149
+
150
+ ## Capistrano callbacks ##
151
+
152
+ # Before deploy:
153
+ ## Check if there is a build on jenkins. If none is available, it will create one.
154
+ ## Notify on Campfire what the deployer did.
155
+ before :deploy do
156
+ ## only do this in production environment
157
+ if env == 'production' and jenkins_enabled
158
+ can_deploy = false
159
+ current_branch = Kumastrano::GitHelper.branch_name
160
+ current_hash = Kumastrano::GitHelper.commit_hash
161
+
162
+ if Kumastrano::JenkinsHelper.available? jenkins_base_uri
163
+ ## Allways fetch the latest information from git
164
+ Kumastrano::GitHelper.fetch
165
+
166
+ job_name = Kumastrano::JenkinsHelper.make_safe_job_name(application, current_branch)
167
+ current_job_url = Kumastrano::JenkinsHelper.job_url_for_name(jenkins_base_uri, job_name)
168
+
169
+ if current_job_url.nil?
170
+ ## No job exists for the current branch, we'll create a job.
171
+ if Kumastrano.ask "no job found for the current branch, do you want to create a job for #{current_branch} on #{application}?", 'y'
172
+ current_job_url = jenkins::create_job
173
+ end
174
+ end
175
+
176
+ if !current_job_url.nil?
177
+ ## we have a job url, get info of the lastBuild
178
+ last_build_info = Kumastrano::JenkinsHelper.build_info current_job_url
179
+ result = last_build_info['result'] ## SUCCESS or FAILURE
180
+ build_hash = Kumastrano::JenkinsHelper.fetch_build_hash_from_build_info(last_build_info, current_branch)
181
+
182
+ if !build_hash.nil?
183
+ if build_hash == current_hash
184
+ if "SUCCESS" == result
185
+ ## The hash of the last build is the same as my hash we can deploy
186
+ can_deploy = true
187
+ else
188
+ ## The hash of the last build is the same as the current hash, but the build failed.
189
+ if Kumastrano.ask "the last build for the branch #{current_branch} for commit #{current_hash} failed, do you want to build again?", 'y'
190
+ prev_build = Kumastrano::JenkinsHelper.last_build_number current_job_url
191
+ Kumastrano.say "start building build ##{(prev_build + 1)} on job #{job_name}, this can take a while"
192
+ result, last_build_info = Kumastrano::JenkinsHelper.build_and_wait current_job_url, jenkins_poll_timeout, jenkins_poll_interval
193
+ new_build_hash = Kumastrano::JenkinsHelper.fetch_build_hash_from_build_info(last_build_info, current_branch)
194
+ if !result.nil? && result && !new_build_hash.nil? && new_build_hash = current_hash
195
+ can_deploy = true
196
+ else
197
+ Kumastrano.say "there is still something wrong with #{current_branch} on #{application}, please check manually and try deploying again afterwards!"
198
+ end
199
+ end
200
+ end
201
+ else
202
+ merge_base = Kumastrano::GitHelper.merge_base(build_hash, current_hash)
203
+ if merge_base == build_hash
204
+ ## The build commit is an ancestor of HEAD
205
+ if Kumastrano.ask "the last build for the branch #{current_branch} is from an older commit do you want to build again? (jenkins=#{build_hash}, local=#{current_hash})", 'y'
206
+ prev_build = Kumastrano::JenkinsHelper.last_build_number current_job_url
207
+ Kumastrano.say "start building build ##{(prev_build + 1)} on job #{job_name}, this can take a while"
208
+ result, last_build_info = Kumastrano::JenkinsHelper.build_and_wait current_job_url, jenkins_poll_timeout, jenkins_poll_interval
209
+ new_build_hash = Kumastrano::JenkinsHelper.fetch_build_hash_from_build_info(last_build_info, current_branch)
210
+ if !result.nil? && result && !new_build_hash.nil? && new_build_hash = current_hash
211
+ can_deploy = true
212
+ else
213
+ Kumastrano.say "there is still something wrong with #{current_branch} on #{application}, please check manually and try deploying again afterwards!"
214
+ end
215
+ end
216
+ elsif merge_base == current_hash
217
+ ## The current HEAD is an ancestor of the build hash
218
+ Kumastrano.say "the latest build is of a newer commit, someone else is probably working on the same branch, try updating your local repository first. (jenkins=#{build_hash}, local=#{current_hash})"
219
+ else
220
+ ## Something is wrong, we don't know what try building again
221
+ if Kumastrano.ask "the latest build isn't a valid build, do you want to try building again? (jenkins=#{build_hash}, local=#{current_hash})", 'y'
222
+ prev_build = Kumastrano::JenkinsHelper.last_build_number current_job_url
223
+ Kumastrano.say "start building build ##{(prev_build + 1)} on job #{job_name}, this can take a while"
224
+ result, last_build_info = Kumastrano::JenkinsHelper.build_and_wait current_job_url, jenkins_poll_timeout, jenkins_poll_interval
225
+ new_build_hash = Kumastrano::JenkinsHelper.fetch_build_hash_from_build_info(last_build_info, current_branch)
226
+ if !result.nil? && result && !new_build_hash.nil? && new_build_hash = current_hash
227
+ can_deploy = true
228
+ else
229
+ Kumastrano.say "there is still something wrong with #{current_branch} on #{application}, please check manually and try deploying again afterwards!"
230
+ end
231
+ end
232
+ end
233
+ end
234
+ else
235
+ ## No build found, try building it
236
+ if Kumastrano.ask "no build found, do you want to try building it?", 'y'
237
+ prev_build = Kumastrano::JenkinsHelper.last_build_number current_job_url
238
+ Kumastrano.say "start building build ##{(prev_build + 1)} on job #{job_name}, this can take a while"
239
+ result, last_build_info = Kumastrano::JenkinsHelper.build_and_wait current_job_url, jenkins_poll_timeout, jenkins_poll_interval
240
+ new_build_hash = Kumastrano::JenkinsHelper.fetch_build_hash_from_build_info(last_build_info, current_branch)
241
+ if !result.nil? && result && !new_build_hash.nil? && new_build_hash = current_hash
242
+ can_deploy = true
243
+ else
244
+ Kumastrano.say "there is still something wrong with #{current_branch} on #{application}, please check manually and try deploying again afterwards!"
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
250
+
251
+ if !can_deploy
252
+ if Kumastrano.ask "no valid build found for #{current_hash} on branch #{current_branch}, do you still want to deploy?"
253
+ Kumastrano::CampfireHelper.speak campfire_account, campfire_token, campfire_room, "#{Etc.getlogin.capitalize} ignored the fact there was something wrong with #{current_branch} on #{application} and still went on with deploying it!!"
254
+ else
255
+ Kumastrano::CampfireHelper.speak campfire_account, campfire_token, campfire_room, "#{Etc.getlogin.capitalize} wanted to deploy #{current_branch} on #{application} but there is something wrong with the code, so he cancelled it!"
256
+ exit
257
+ end
258
+ else
259
+ Kumastrano::CampfireHelper.speak campfire_account, campfire_token, campfire_room, "#{Etc.getlogin.capitalize} is deploying #{current_branch} for #{application}"
260
+ end
261
+ else
262
+ Kumastrano.say "jenkins on demand is disabled, skipping..."
263
+ end
264
+ end
265
+
266
+ # Before update_code:
267
+ ## Make the cached_copy readable for the current user
268
+ before "deploy:update_code" do
269
+ user = Etc.getlogin
270
+ sudo "sh -c 'if [ -d #{shared_path}/cached-copy ] ; then chown -R #{user}:#{user} #{shared_path}/cached-copy; fi'" if deploy_via == :rsync_with_remote_cache || deploy_via == :remote_cache
271
+ end
272
+
273
+ # After update_code:
274
+ ## Fix the permissions of the cached_copy so that it's readable for the project user
275
+ after "deploy:update_code" do
276
+ sudo "sh -c 'if [ -d #{shared_path}/cached-copy ] ; then chown -R #{application}:#{application} #{shared_path}/cached-copy; fi'" if deploy_via == :rsync_with_remote_cache || deploy_via == :remote_cache
277
+ end
278
+
279
+ # Before finalize_update:
280
+ ## Create the parameters.ini if it's a symfony project
281
+ ## Fix the permissions of the latest release, so that it's readable for the project user
282
+ before "deploy:finalize_update" do
283
+ sudo "sh -c 'if [ -d #{shared_path}/cached-copy ] ; then chmod -R ug+rx #{latest_release}/paramDecode; fi'"
284
+ sudo "sh -c 'if [ -f #{latest_release}/paramDecode ] ; then cd #{latest_release} && ./paramDecode; fi'" # Symfony specific: will generate the parameters.ini
285
+ sudo "chown -R #{application}:#{application} #{latest_release}"
286
+ sudo "setfacl -R -m group:admin:rwx #{latest_release}"
287
+ end
288
+
289
+ # After deploy:
290
+ ## Notify the people on campfire of this deploy
291
+ ## Notify airbrake to add a new deploy to the deploy history
292
+ after :deploy do
293
+ current_branch = Kumastrano::GitHelper.branch_name
294
+ Kumastrano::CampfireHelper.speak campfire_account, campfire_token, campfire_room, "#{Etc.getlogin.capitalize} successfuly deployed #{current_branch} for #{application}"
295
+ airbrake::notify
296
+ deploy::cleanup ## cleanup old releases
297
+ kuma::fixcron
298
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kstrano
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kunstmaan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capistrano
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 2.12.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 2.12.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: capistrano-ext
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 1.2.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.2.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: capistrano_colors
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.5.5
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.5.5
62
+ - !ruby/object:Gem::Dependency
63
+ name: kcapifony
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 2.1.3
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 2.1.3
78
+ - !ruby/object:Gem::Dependency
79
+ name: json
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: 1.6.6
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 1.6.6
94
+ - !ruby/object:Gem::Dependency
95
+ name: broach
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: 0.2.1
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 0.2.1
110
+ - !ruby/object:Gem::Dependency
111
+ name: highline
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: 1.6.11
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: 1.6.11
126
+ description: Deploying applications with Capistrano, Jenkins and GIT.
127
+ email: support@kunstmaan.be
128
+ executables:
129
+ - kumafy
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - lib/helpers/airbrake_helper.rb
134
+ - lib/helpers/campfire_helper.rb
135
+ - lib/helpers/git_helper.rb
136
+ - lib/helpers/jenkins_helper.rb
137
+ - lib/helpers/kuma_helper.rb
138
+ - lib/kstrano.rb
139
+ - bin/kumafy
140
+ homepage: https://github.com/Kunstmaan/kStrano
141
+ licenses: []
142
+ post_install_message:
143
+ rdoc_options: []
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ requirements: []
159
+ rubyforge_project:
160
+ rubygems_version: 1.8.23
161
+ signing_key:
162
+ specification_version: 3
163
+ summary: Deploying applications with Capistrano, Jenkins and GIT.
164
+ test_files: []