ucb_rails_ci 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +102 -0
- data/README.md +49 -0
- data/Rakefile +370 -0
- data/ci.rb +244 -0
- data/lib/ucb_rails_ci.rb +3 -0
- data/lib/ucb_rails_ci/railtie.rb +11 -0
- data/tasks/ucb_rails_ci.rake +161 -0
- data/templates/travis.yml.erb +36 -0
- data/ucb_rails_ci.gemspec +19 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7fd00d015b13a606625896918ba8ba848a39e7c0
|
4
|
+
data.tar.gz: c53a1860d8fda5030635caee14840f8ff6c08cc5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9b25c28b48232f954e30155acbcf71b76a23a602bde491eda844bb40b5ba055f5dd95870e521cb4a2a9aa651ea93044195992a90df811a80c47b2e1f5274a9fc
|
7
|
+
data.tar.gz: bae199cd74d50285bdd896e3bb63574dc8fe1197fd90ac5d3db73f634f0562008402b70d798e011180d81ad38809511b1290ccb4974d978b3092f09bcd430029
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ucb_rails_ci (1.0.0)
|
5
|
+
builder
|
6
|
+
bundler
|
7
|
+
github_api
|
8
|
+
rake
|
9
|
+
travis
|
10
|
+
warbler
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: https://rubygems.org/
|
14
|
+
specs:
|
15
|
+
addressable (2.3.7)
|
16
|
+
backports (3.6.4)
|
17
|
+
builder (3.2.2)
|
18
|
+
coderay (1.1.0)
|
19
|
+
descendants_tracker (0.0.4)
|
20
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
21
|
+
ethon (0.7.3)
|
22
|
+
ffi (>= 1.3.0)
|
23
|
+
faraday (0.9.1)
|
24
|
+
multipart-post (>= 1.2, < 3)
|
25
|
+
faraday_middleware (0.9.1)
|
26
|
+
faraday (>= 0.7.4, < 0.10)
|
27
|
+
ffi (1.9.3)
|
28
|
+
gh (0.14.0)
|
29
|
+
addressable
|
30
|
+
backports
|
31
|
+
faraday (~> 0.8)
|
32
|
+
multi_json (~> 1.0)
|
33
|
+
net-http-persistent (>= 2.7)
|
34
|
+
net-http-pipeline
|
35
|
+
github_api (0.12.2)
|
36
|
+
addressable (~> 2.3)
|
37
|
+
descendants_tracker (~> 0.0.4)
|
38
|
+
faraday (~> 0.8, < 0.10)
|
39
|
+
hashie (>= 3.3)
|
40
|
+
multi_json (>= 1.7.5, < 2.0)
|
41
|
+
nokogiri (~> 1.6.3)
|
42
|
+
oauth2
|
43
|
+
hashie (3.3.2)
|
44
|
+
highline (1.7.0)
|
45
|
+
jruby-jars (1.7.17)
|
46
|
+
jruby-rack (1.1.18)
|
47
|
+
json (1.8.1)
|
48
|
+
jwt (1.2.1)
|
49
|
+
launchy (2.4.3)
|
50
|
+
addressable (~> 2.3)
|
51
|
+
method_source (0.8.2)
|
52
|
+
mini_portile (0.6.2)
|
53
|
+
multi_json (1.10.1)
|
54
|
+
multi_xml (0.5.5)
|
55
|
+
multipart-post (2.0.0)
|
56
|
+
net-http-persistent (2.9.4)
|
57
|
+
net-http-pipeline (1.0.1)
|
58
|
+
nokogiri (1.6.6.2)
|
59
|
+
mini_portile (~> 0.6.0)
|
60
|
+
oauth2 (1.0.0)
|
61
|
+
faraday (>= 0.8, < 0.10)
|
62
|
+
jwt (~> 1.0)
|
63
|
+
multi_json (~> 1.3)
|
64
|
+
multi_xml (~> 0.5)
|
65
|
+
rack (~> 1.2)
|
66
|
+
pry (0.9.12.4)
|
67
|
+
coderay (~> 1.0)
|
68
|
+
method_source (~> 0.8)
|
69
|
+
slop (~> 3.4)
|
70
|
+
pusher-client (0.6.0)
|
71
|
+
json
|
72
|
+
websocket (~> 1.0)
|
73
|
+
rack (1.6.0)
|
74
|
+
rake (10.4.2)
|
75
|
+
rubyzip (1.1.7)
|
76
|
+
slop (3.4.7)
|
77
|
+
thread_safe (0.3.4)
|
78
|
+
travis (1.7.5)
|
79
|
+
addressable (~> 2.3)
|
80
|
+
backports
|
81
|
+
faraday (~> 0.9)
|
82
|
+
faraday_middleware (~> 0.9, >= 0.9.1)
|
83
|
+
gh (~> 0.13)
|
84
|
+
highline (~> 1.6)
|
85
|
+
launchy (~> 2.1)
|
86
|
+
pry (~> 0.9, < 0.10)
|
87
|
+
pusher-client (~> 0.4)
|
88
|
+
typhoeus (~> 0.6, >= 0.6.8)
|
89
|
+
typhoeus (0.7.1)
|
90
|
+
ethon (>= 0.7.1)
|
91
|
+
warbler (1.4.5)
|
92
|
+
jruby-jars (>= 1.5.6, < 2.0)
|
93
|
+
jruby-rack (>= 1.1.1, < 1.3)
|
94
|
+
rake (>= 0.9.6)
|
95
|
+
rubyzip (>= 0.9, < 1.2)
|
96
|
+
websocket (1.0.7)
|
97
|
+
|
98
|
+
PLATFORMS
|
99
|
+
ruby
|
100
|
+
|
101
|
+
DEPENDENCIES
|
102
|
+
ucb_rails_ci!
|
data/README.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
Rakefile
|
2
|
+
========
|
3
|
+
|
4
|
+
Rake commands for command line deployment. Basic usage:
|
5
|
+
|
6
|
+
```
|
7
|
+
# SVN/jenkins deploys
|
8
|
+
|
9
|
+
rake deploy APP=<app name> # defaults to trunk
|
10
|
+
rake deploy APP=<app name> BRANCH=<branch name>
|
11
|
+
rake deploy APP=<app name> TAG=<tag>
|
12
|
+
|
13
|
+
# Github/Travis-CI deploys
|
14
|
+
rake gdeploy APP=<app name> # defaults to master
|
15
|
+
rake gdeploy APP=<app name> BRANCH=<branch name>
|
16
|
+
rake gdeploy APP=<app name> TAG=<tag>
|
17
|
+
|
18
|
+
# Restarting
|
19
|
+
rake restart APP=<app name>
|
20
|
+
```
|
21
|
+
|
22
|
+
ucb\_rails\_ci.rake
|
23
|
+
=======
|
24
|
+
|
25
|
+
Automatically included in any project that wants to be deployed via
|
26
|
+
Github/Travis. Basic tasks for prepping and precompiling a rails project.
|
27
|
+
|
28
|
+
Examples:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
rake ci:setup # any preliminary setup
|
32
|
+
rake ci:war # Build a war file for JRuby deployment
|
33
|
+
```
|
34
|
+
|
35
|
+
ci.rb
|
36
|
+
=====
|
37
|
+
|
38
|
+
Simple scripts to supplement CI build. This applies to jenkins only -- Travis
|
39
|
+
uses a different mechanism.
|
40
|
+
|
41
|
+
Usage:
|
42
|
+
|
43
|
+
```
|
44
|
+
ci.rb APP_NAME [--run-specs-false] [--compile-assets-flag]
|
45
|
+
|
46
|
+
--run-specs-flag (defaults is true)
|
47
|
+
--compile-assets-flag (defaults is true)
|
48
|
+
```
|
49
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,370 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'erb'
|
3
|
+
require 'yaml'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'github_api'
|
6
|
+
|
7
|
+
sync = true
|
8
|
+
|
9
|
+
################################################################################
|
10
|
+
# Initialization
|
11
|
+
################################################################################
|
12
|
+
task :default => :deploy
|
13
|
+
|
14
|
+
desc "deploy the application"
|
15
|
+
|
16
|
+
task :do_deploy => [:symlink_configs, :disable_web, :tomcat_stop,
|
17
|
+
:deploy_war, :load_crontab, :tomcat_start, :enable_web]
|
18
|
+
|
19
|
+
task :deploy => [:parse_args, :svn_export, :do_deploy]
|
20
|
+
task :gdeploy => [:parse_args, :github_release_export, :do_deploy]
|
21
|
+
|
22
|
+
desc "Full restart without deploy"
|
23
|
+
task :restart => [:disable_web, :tomcat_stop, :tomcat_start, :enable_web]
|
24
|
+
|
25
|
+
task :parse_args do
|
26
|
+
unless ENV['APP']
|
27
|
+
$stderr.puts "Usage: rake APP=<app_name>"
|
28
|
+
exit(1)
|
29
|
+
end
|
30
|
+
|
31
|
+
base_dir = ENV['DEPLOY_BASE'] || ENV['HOME']
|
32
|
+
config_dir = "#{base_dir}/.deploy_config/#{ENV['APP']}"
|
33
|
+
work_dir = "#{base_dir}/.deploy_work"
|
34
|
+
|
35
|
+
$config = OpenStruct.new(YAML.load_file("#{config_dir}/deploy.yml"))
|
36
|
+
$config.config_dir = config_dir
|
37
|
+
$config.debug = (ENV['DEBUG'] == 'true')
|
38
|
+
$config.app_name = ENV['APP']
|
39
|
+
$config.app_user = "app_#{ENV['APP']}"
|
40
|
+
$config.tag = ENV['TAG']
|
41
|
+
$config.branch = ENV['BRANCH'] || $config.tag || 'master'
|
42
|
+
$config.war = ENV['WAR'] || ($config.branch == 'master') ? 'trunk.war' : "#{$config.branch}.war"
|
43
|
+
$config.release_url = "#{$config.svn_project_url}/#{$config.war}"
|
44
|
+
$config.work_dir = "#{work_dir}/#{$config.app_name}"
|
45
|
+
|
46
|
+
if $config.github_api_token
|
47
|
+
$github = Github.new do |c|
|
48
|
+
c.oauth_token = $config.github_api_token
|
49
|
+
c.user = 'ucb-ist-eas'
|
50
|
+
c.repo = $config.app_name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if $config.debug
|
55
|
+
puts($config.inspect)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
################################################################################
|
61
|
+
# Deploy War
|
62
|
+
################################################################################
|
63
|
+
desc "Deploy the war file to tomcat webapps dir"
|
64
|
+
task :deploy_war => [:parse_args, :ensure_work_directory] do
|
65
|
+
progress "Deploying war to tomcat" do
|
66
|
+
|
67
|
+
webapps = $config.webapps_dir
|
68
|
+
app = $config.app_name
|
69
|
+
root = "ROOT"
|
70
|
+
app_user = $config.app_user
|
71
|
+
|
72
|
+
FileUtils.cd($config.work_dir) do
|
73
|
+
run_cmd "sudo -u #{app_user} rm -rf #{webapps}/#{root}/*"
|
74
|
+
run_cmd "rm -rf #{webapps}/#{root}"
|
75
|
+
run_cmd "cp -R . #{webapps}/#{app}"
|
76
|
+
run_cmd "mv #{webapps}/#{app} #{webapps}/#{root}"
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
################################################################################
|
84
|
+
# Start/Stop Tomcat
|
85
|
+
################################################################################
|
86
|
+
desc "stop tomcat application server"
|
87
|
+
task :tomcat_stop => [:parse_args] do
|
88
|
+
unless $dry_run
|
89
|
+
status_cmd = "sudo service tomcat6-#{$config.app_name} status"
|
90
|
+
stop_cmd = "sudo service tomcat6-#{$config.app_name} stop"
|
91
|
+
|
92
|
+
output = `#{status_cmd}`.chomp
|
93
|
+
if $?.exitstatus == 3
|
94
|
+
puts(output)
|
95
|
+
else
|
96
|
+
output = `#{stop_cmd}`.chomp
|
97
|
+
if $?.exitstatus == 0
|
98
|
+
puts(output)
|
99
|
+
else
|
100
|
+
$stderr.puts(output)
|
101
|
+
exit(1)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
desc "start tomcat application server"
|
108
|
+
task :tomcat_start => [:parse_args] do
|
109
|
+
unless $dry_run
|
110
|
+
output = `sudo service tomcat6-#{$config.app_name} start`.chomp
|
111
|
+
puts(output)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
################################################################################
|
117
|
+
# Checkout Source Code
|
118
|
+
################################################################################
|
119
|
+
def copy_yml_configs
|
120
|
+
Dir["#{$config.config_dir}/*.yml"].each do |file_path|
|
121
|
+
file_name = File.basename(file_path)
|
122
|
+
unless file_name == "deploy.yml"
|
123
|
+
`cp #{file_path} ./WEB-INF/config/#{file_name}`
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def configure_web_xml
|
129
|
+
web_xml = "WEB-INF/web.xml"
|
130
|
+
|
131
|
+
lines = File.readlines(web_xml)
|
132
|
+
File.open(web_xml, "w") do |f|
|
133
|
+
lines.each do |line|
|
134
|
+
if line =~ /<param-value>production<\/param-value>/
|
135
|
+
f.puts("<param-value>#{$config.rails_env}<\/param-value>")
|
136
|
+
elsif line =~ /<param-value>ci<\/param-value>/
|
137
|
+
f.puts("<param-value>#{$config.rails_env}<\/param-value>")
|
138
|
+
else
|
139
|
+
f.puts(line)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def symlink_tmp_to_temp
|
146
|
+
`ln -s /var/lib/tomcat6-#{$config.app_name}/temp WEB-INF/tmp`
|
147
|
+
end
|
148
|
+
|
149
|
+
def extract_war
|
150
|
+
`jar -xvf *.war`
|
151
|
+
`rm -rf *.war`
|
152
|
+
end
|
153
|
+
|
154
|
+
desc "Embed and link configs"
|
155
|
+
task :symlink_configs => [:ensure_work_directory] do
|
156
|
+
progress "Embedding configs and linking directories" do
|
157
|
+
|
158
|
+
FileUtils.cd($config.work_dir) do
|
159
|
+
extract_war
|
160
|
+
copy_yml_configs
|
161
|
+
configure_web_xml
|
162
|
+
symlink_tmp_to_temp
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
desc "download project from svn"
|
169
|
+
task :svn_export => [:parse_args, :svn_war_exists, :ensure_work_directory] do
|
170
|
+
progress "Exporting code from SVN (#{$config.release_url})" do
|
171
|
+
|
172
|
+
app_dir = $config.app_name
|
173
|
+
|
174
|
+
if File.exists?(app_dir)
|
175
|
+
puts "App dir #{app_dir} already exists. Incomplete deploy?"
|
176
|
+
exit(1)
|
177
|
+
end
|
178
|
+
|
179
|
+
run_cmd("svn export #{$config.release_url}")
|
180
|
+
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
desc "download project from github"
|
185
|
+
task :github_release_export => [:parse_args, :ensure_work_directory] do
|
186
|
+
if $config.tag.nil?
|
187
|
+
|
188
|
+
# Look at the list of releases and pick with the highest number matching the branch
|
189
|
+
releases = $github.repos.releases.list('ucb-ist-eas', $config.app_name)
|
190
|
+
branch_tags = releases.map(&:tag_name).select { |t| t =~ /\A#{$config.branch}-\d+\Z/ }
|
191
|
+
branch_tags.sort_by! { |t| t =~ /-(\d+)\Z/; $1.to_i }
|
192
|
+
|
193
|
+
if branch_tags.empty?
|
194
|
+
puts "No tags found for BRANCH=#{$config.branch}. Use TAG variable to specify a particular tag."
|
195
|
+
exit 1
|
196
|
+
else
|
197
|
+
$config.tag = branch_tags.last
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
progress "Exporting war file from GitHub for tag #{$config.tag}" do
|
202
|
+
|
203
|
+
app_dir = $config.app_name
|
204
|
+
orig_war = "#{$config.app_name}.war"
|
205
|
+
|
206
|
+
cmd = %{github-release download
|
207
|
+
-s #{$config.github_api_token}
|
208
|
+
-u ucb-ist-eas
|
209
|
+
-r #{$config.app_name}
|
210
|
+
-t #{$config.tag}
|
211
|
+
-n #{orig_war}}
|
212
|
+
|
213
|
+
cmd.gsub!(/[[:space:]]+/, " ")
|
214
|
+
|
215
|
+
run_cmd cmd, fail_msg: "Could not download the release. Is the tag right? Is github-release installed?"
|
216
|
+
|
217
|
+
FileUtils.mv(orig_war, $config.war)
|
218
|
+
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
task :svn_war_exists => [:svn_project_exists] do
|
223
|
+
run_cmd "svn ls #{$config.release_url} 2>&1",
|
224
|
+
fail_msg: "SVN URL not found: #{$config.release_url}"
|
225
|
+
end
|
226
|
+
|
227
|
+
task :svn_project_exists => [:parse_args] do
|
228
|
+
run_cmd "svn ls #{$config.svn_project_url} 2>&1",
|
229
|
+
fail_msg: "SVN URL not found: #{$config.svn_project_url}"
|
230
|
+
end
|
231
|
+
|
232
|
+
desc "Create work directory if necessary"
|
233
|
+
task :ensure_work_directory => [:parse_args] do
|
234
|
+
run_cmd "mkdir -p #{$config.work_dir}",
|
235
|
+
fail_msg: "Cannot create work directory: #{$config.work_dir}"
|
236
|
+
|
237
|
+
FileUtils.cd($config.work_dir)
|
238
|
+
end
|
239
|
+
|
240
|
+
################################################################################
|
241
|
+
# Enable/Disable web
|
242
|
+
################################################################################
|
243
|
+
desc "remove maintenance file and enable web access to app"
|
244
|
+
task :enable_web => [:parse_args] do
|
245
|
+
progress "Enabling tomcat proxy, remove maint message" do
|
246
|
+
|
247
|
+
file = $config.work_dir
|
248
|
+
FileUtils.rm_rf(file) if File.exists?(file)
|
249
|
+
FileUtils.rm_rf($config.maint_file) if File.exists?($config.maint_file)
|
250
|
+
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
desc "display maintenance file and disable web access to app"
|
255
|
+
task :disable_web => [:parse_args] do
|
256
|
+
progress "Disabling tomcat proxy, display maint message" do
|
257
|
+
|
258
|
+
maint_start = Time.now.strftime("%m-%d-%Y %H:%M:%S")
|
259
|
+
template = ERB.new($template)
|
260
|
+
File.open($config.maint_file, "w") do |f|
|
261
|
+
f.puts template.result(binding)
|
262
|
+
end
|
263
|
+
|
264
|
+
raise "file is missing" unless File.exists?($config.maint_file)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
$template = %q{
|
269
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
270
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
271
|
+
|
272
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
273
|
+
|
274
|
+
<head>
|
275
|
+
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
276
|
+
<title>Site Maintenance</title>
|
277
|
+
<style type="text/css">
|
278
|
+
body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
|
279
|
+
div.dialog {
|
280
|
+
width: 35em;
|
281
|
+
padding: 0 3em;
|
282
|
+
margin: 3em auto 0 auto;
|
283
|
+
border: 1px solid #ccc;
|
284
|
+
border-right-color: #999;
|
285
|
+
border-bottom-color: #999;
|
286
|
+
}
|
287
|
+
h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
|
288
|
+
</style>
|
289
|
+
</head>
|
290
|
+
|
291
|
+
<body>
|
292
|
+
<div class="dialog">
|
293
|
+
<h1>Site Maintenance</h1>
|
294
|
+
<p>
|
295
|
+
The site is down for maintenance as of: <strong><%= maint_start %></strong> <br/>
|
296
|
+
it should be available shortly.
|
297
|
+
</p>
|
298
|
+
</div>
|
299
|
+
</body>
|
300
|
+
</html>
|
301
|
+
}
|
302
|
+
|
303
|
+
|
304
|
+
################################################################################
|
305
|
+
# Cron Jobs
|
306
|
+
################################################################################
|
307
|
+
|
308
|
+
desc "load cron jobs from crontab"
|
309
|
+
task :load_crontab do
|
310
|
+
crontab_file = "#{$config.app_name}/config/crontab.txt"
|
311
|
+
if $config.rails_env == "production" && File.exists?(crontab_file)
|
312
|
+
`/usr/bin/crontab -u app_#{$config.app_name} #{crontab_file}`
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
################################################################################
|
317
|
+
# Misc
|
318
|
+
################################################################################
|
319
|
+
|
320
|
+
desc "curls the ~/app_monitor url and performs a basic health check"
|
321
|
+
task :health_check => [:parse_args] do
|
322
|
+
progress "Performing health check" do
|
323
|
+
|
324
|
+
result = `curl -m 10 -s localhost:#{$config.tomcat_port}/app_monitor`.chomp
|
325
|
+
|
326
|
+
raise result unless result == "OK"
|
327
|
+
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
def run_cmd(cmd_str, opts = {})
|
332
|
+
IO.popen(cmd_str) { |f|0
|
333
|
+
until f.eof?
|
334
|
+
str = f.gets
|
335
|
+
puts(str) if $debug_mode
|
336
|
+
end
|
337
|
+
}
|
338
|
+
|
339
|
+
if opts[:fail_msg] && $?.exitstatus.to_i != 0
|
340
|
+
raise(opts[:fail_msg])
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
def progress(msg)
|
345
|
+
print "%-59s" % [msg + ":"]
|
346
|
+
yield
|
347
|
+
puts "[#{" OK ".green}]"
|
348
|
+
rescue
|
349
|
+
puts "[#{"FAILED".red}]"
|
350
|
+
exit(1)
|
351
|
+
end
|
352
|
+
|
353
|
+
class String
|
354
|
+
# colorization
|
355
|
+
def colorize(color_code)
|
356
|
+
"\e[#{color_code}m#{self}\e[0m"
|
357
|
+
end
|
358
|
+
|
359
|
+
def red
|
360
|
+
colorize(31)
|
361
|
+
end
|
362
|
+
|
363
|
+
def green
|
364
|
+
colorize(32)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
|
369
|
+
|
370
|
+
|
data/ci.rb
ADDED
@@ -0,0 +1,244 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'warbler'
|
6
|
+
|
7
|
+
class CiBuild
|
8
|
+
attr_accessor :app_name, :workspace_path, :jenkins_home, :run_specs_flag, :compile_assets_flag, :build_number
|
9
|
+
|
10
|
+
def initialize(args={})
|
11
|
+
@app_name = args.fetch(:app_name)
|
12
|
+
@workspace_path = args.fetch(:workspace_path)
|
13
|
+
@jenkins_home = args.fetch(:jenkins_home)
|
14
|
+
|
15
|
+
@run_specs_flag = args.fetch(:run_specs_flag, true)
|
16
|
+
@compile_assets_flag = args.fetch(:compile_assets_flag, true)
|
17
|
+
|
18
|
+
@build_number = args.fetch(:build_number, nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
Dir.chdir(workspace_path) do
|
23
|
+
clean_workspace
|
24
|
+
run_bundle_install
|
25
|
+
setup_dot_yml_files
|
26
|
+
|
27
|
+
if run_specs_flag
|
28
|
+
setup_db
|
29
|
+
run_rspec_suite
|
30
|
+
end
|
31
|
+
|
32
|
+
compile_assets if compile_assets_flag
|
33
|
+
|
34
|
+
record_build_number
|
35
|
+
archive_war_file
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def clean_workspace
|
43
|
+
FileUtils.rm_rf("#{workspace_path}/.rvmrc") if File.exists?("#{workspace_path}/.rvmrc")
|
44
|
+
end
|
45
|
+
|
46
|
+
def job_name
|
47
|
+
workspace_path =~ /jobs\/(.+)\/workspace$/
|
48
|
+
$1
|
49
|
+
end
|
50
|
+
|
51
|
+
def war_archive_url
|
52
|
+
"#{war_archive_root}/#{app_name}/"
|
53
|
+
end
|
54
|
+
|
55
|
+
def war_archive_root
|
56
|
+
"svn+ssh://svn@code.berkeley.edu/eas-rails/wars"
|
57
|
+
end
|
58
|
+
|
59
|
+
def war_name
|
60
|
+
if git_repo?
|
61
|
+
git_war_name
|
62
|
+
elsif svn_repo?
|
63
|
+
svn_war_name
|
64
|
+
else
|
65
|
+
raise "Unrecognized SCM"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def git_repo?
|
70
|
+
Dir["#{workspace_path}/.*"].any? { |f| File.basename(f) == ".git" }
|
71
|
+
end
|
72
|
+
|
73
|
+
def svn_repo?
|
74
|
+
Dir["#{workspace_path}/.*"].any? { |f| File.basename(f) == ".svn" }
|
75
|
+
end
|
76
|
+
|
77
|
+
def svn_war_name
|
78
|
+
ENV['SVN_URL'].split("/").pop
|
79
|
+
end
|
80
|
+
|
81
|
+
def git_war_name
|
82
|
+
branch = ENV['GIT_BRANCH']
|
83
|
+
(branch == "master") ? "trunk" : branch
|
84
|
+
end
|
85
|
+
|
86
|
+
def default_env_vars
|
87
|
+
["WEBKIT=false", "QMAKE=/usr/bin/qmake-qt47"]
|
88
|
+
end
|
89
|
+
|
90
|
+
def run_cmd(cmd, env_vars = [])
|
91
|
+
# TODO: Enable after qt47 is installed
|
92
|
+
# env = (default_env_vars + env_vars).join(" ")
|
93
|
+
|
94
|
+
env = env_vars.join(" ")
|
95
|
+
full_cmd = "#{env} #{cmd}"
|
96
|
+
$stdout.puts("#{full_cmd} ... ")
|
97
|
+
|
98
|
+
output = `#{full_cmd} 2>&1`
|
99
|
+
$stdout.puts(output)
|
100
|
+
|
101
|
+
if $?.success?
|
102
|
+
$stdout.puts("[OK]")
|
103
|
+
else
|
104
|
+
$stdout.puts("[FAILED]")
|
105
|
+
$stdout.puts($?.exitstatus)
|
106
|
+
exit($?.exitstatus)
|
107
|
+
end
|
108
|
+
|
109
|
+
output
|
110
|
+
end
|
111
|
+
|
112
|
+
def run_bundle_install
|
113
|
+
run_cmd("bundle install")
|
114
|
+
end
|
115
|
+
|
116
|
+
def setup_dot_yml_files
|
117
|
+
create_db_yml
|
118
|
+
Dir.glob("config/*.yml.example").each do |file_path|
|
119
|
+
file_name = File.basename(file_path).split(".")[0..1].join(".")
|
120
|
+
next if file_name == "database.yml"
|
121
|
+
dir_name = File.dirname(file_path)
|
122
|
+
FileUtils.cp(file_path, File.join(dir_name, file_name))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def setup_db
|
127
|
+
run_cmd("bundle exec rake db:migrate", ["RAILS_ENV=test"])
|
128
|
+
end
|
129
|
+
|
130
|
+
def create_db_yml
|
131
|
+
db_yml_contents = <<-DB
|
132
|
+
test: &test
|
133
|
+
adapter: sqlite3
|
134
|
+
database: #{app_name}
|
135
|
+
username: jenkins
|
136
|
+
password: jenkins
|
137
|
+
host: localhost
|
138
|
+
|
139
|
+
legacy_test: &legacy_test
|
140
|
+
adapter: sqlite3
|
141
|
+
database: db/legacy_test.sqlite3
|
142
|
+
|
143
|
+
ci:
|
144
|
+
<<: *test
|
145
|
+
|
146
|
+
legacy_ci:
|
147
|
+
<<: *legacy_test
|
148
|
+
|
149
|
+
DB
|
150
|
+
File.open("config/database.yml", "w") do |f|
|
151
|
+
f.write(db_yml_contents)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def run_rspec_suite
|
156
|
+
run_cmd("bundle exec rspec spec --tag ~js --format RspecJunitFormatter --out results.xml", ["RAILS_ENV=test"])
|
157
|
+
end
|
158
|
+
|
159
|
+
def compile_assets
|
160
|
+
cache_compiled_assets
|
161
|
+
run_cmd("bundle exec rake assets:precompile", ["RAILS_ENV=ci"])
|
162
|
+
end
|
163
|
+
|
164
|
+
def cache_compiled_assets
|
165
|
+
link = "#{jenkins_home}/.jenkins/jobs/#{job_name}/workspace/tmp"
|
166
|
+
target = "#{jenkins_home}/tmp/#{job_name}"
|
167
|
+
|
168
|
+
FileUtils.mkdir(target) unless File.exists?(target)
|
169
|
+
FileUtils.rm_rf(link) if File.exists?(link)
|
170
|
+
File.symlink(target, link) unless File.symlink?(link)
|
171
|
+
end
|
172
|
+
|
173
|
+
def record_build_number
|
174
|
+
if build_number
|
175
|
+
path = File.join(workspace_path, 'BUILD')
|
176
|
+
File.open(path, "w") do |f|
|
177
|
+
puts "Storing build number #{build_number} into #{path}"
|
178
|
+
f.write(build_number)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def archive_war_file
|
184
|
+
create_war
|
185
|
+
remove_war if war_checked_in?
|
186
|
+
commit_war
|
187
|
+
end
|
188
|
+
|
189
|
+
def create_war
|
190
|
+
RakeFileUtils.verbose_flag = true
|
191
|
+
Warbler::Task.new('trunk')
|
192
|
+
|
193
|
+
$stdout.print("Building war file: ")
|
194
|
+
Rake::Task['trunk'].invoke()
|
195
|
+
|
196
|
+
FileUtils.mv("workspace.war", "#{war_name}.war")
|
197
|
+
end
|
198
|
+
|
199
|
+
def war_checked_in?
|
200
|
+
wars = run_cmd("svn list #{war_archive_url}").split("\n")
|
201
|
+
wars.include?("#{war_name}.war")
|
202
|
+
end
|
203
|
+
|
204
|
+
def remove_war
|
205
|
+
run_cmd("svn rm #{war_archive_url}/#{war_name}.war -m 'removing war #{war_name}.war' &")
|
206
|
+
run_cmd("sleep 2s")
|
207
|
+
end
|
208
|
+
|
209
|
+
def commit_war
|
210
|
+
run_cmd("svn import #{war_name}.war #{war_archive_url}/#{war_name}.war -m 'committing war #{war_name}.war'")
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
if __FILE__ == $PROGRAM_NAME
|
216
|
+
def extract_optional_args(optional_args)
|
217
|
+
optional_args.inject({}) do |hash, arg|
|
218
|
+
key, val = arg.split("=")
|
219
|
+
if val == "false"
|
220
|
+
val = false
|
221
|
+
elsif val.nil?
|
222
|
+
val = true
|
223
|
+
else
|
224
|
+
val = val
|
225
|
+
end
|
226
|
+
|
227
|
+
key = key[2..-1].gsub("-", "_").to_sym
|
228
|
+
hash[key] = val
|
229
|
+
hash
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
args = {
|
234
|
+
:app_name => ARGV[0],
|
235
|
+
:workspace_path => ENV['WORKSPACE'],
|
236
|
+
:jenkins_home => ENV['HOME'],
|
237
|
+
}
|
238
|
+
|
239
|
+
optional_args = extract_optional_args(ARGV[1..-1])
|
240
|
+
|
241
|
+
|
242
|
+
p args.merge(optional_args)
|
243
|
+
CiBuild.new(args.merge(optional_args)).run
|
244
|
+
end
|
data/lib/ucb_rails_ci.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
|
2
|
+
require 'warbler'
|
3
|
+
|
4
|
+
namespace :ci do
|
5
|
+
|
6
|
+
desc "Run CI setup tasks"
|
7
|
+
task :setup => %w[ config:copy_defaults ]
|
8
|
+
|
9
|
+
desc "Run Rspec for CI"
|
10
|
+
task :spec => %w[ setup spec ]
|
11
|
+
|
12
|
+
task :war => %w[ war:archive ]
|
13
|
+
|
14
|
+
namespace :war do
|
15
|
+
|
16
|
+
task :archive do
|
17
|
+
if war_branch?
|
18
|
+
Rake::Task['ci:war:prepare'].invoke
|
19
|
+
Rake::Task['ci:war:create'].invoke
|
20
|
+
else
|
21
|
+
puts "Not creating a war because this is a personal branch (has a / in it)"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
task :create do
|
27
|
+
create_war
|
28
|
+
end
|
29
|
+
|
30
|
+
task :prepare => %w[ assets:precompile ] do
|
31
|
+
record_build_number
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def record_build_number
|
36
|
+
if build_number = ENV['TRAVIS_BUILD_NUMBER']
|
37
|
+
path = File.join(workspace_path, 'BUILD')
|
38
|
+
File.open(path, "w") do |f|
|
39
|
+
puts "Storing build number #{build_number} into #{path}"
|
40
|
+
f.write(build_number)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_war
|
46
|
+
RakeFileUtils.verbose_flag = true
|
47
|
+
Warbler::Task.new(branch)
|
48
|
+
|
49
|
+
$stdout.print("Building war file: ")
|
50
|
+
Rake::Task[branch].invoke()
|
51
|
+
end
|
52
|
+
|
53
|
+
def branch
|
54
|
+
branch = ENV['TRAVIS_BRANCH']
|
55
|
+
|
56
|
+
unless branch
|
57
|
+
branch = `git rev-parse --abbrev-ref HEAD`.strip
|
58
|
+
end
|
59
|
+
|
60
|
+
branch = 'trunk' if branch == 'master'
|
61
|
+
branch
|
62
|
+
end
|
63
|
+
|
64
|
+
def war_name
|
65
|
+
branch
|
66
|
+
end
|
67
|
+
|
68
|
+
def war_branch?
|
69
|
+
!branch.include?('/')
|
70
|
+
end
|
71
|
+
|
72
|
+
def workspace_path
|
73
|
+
ENV['TRAVIS_BUILD_DIR'] || '.'
|
74
|
+
end
|
75
|
+
|
76
|
+
def app_name
|
77
|
+
if ENV['TRAVIS_REPO_SLUG']
|
78
|
+
ENV['TRAVIS_REPO_SLUG'].split('/').last
|
79
|
+
else
|
80
|
+
url = `git config --get remote.origin.url`
|
81
|
+
if url =~ /ucb-ist-eas\/(.*)\.git/
|
82
|
+
$1
|
83
|
+
else
|
84
|
+
raise "cannot determine branch"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def run_cmd(cmd, env_vars = [])
|
90
|
+
# TODO: Enable after qt47 is installed
|
91
|
+
# env = (default_env_vars + env_vars).join(" ")
|
92
|
+
|
93
|
+
env = env_vars.join(" ")
|
94
|
+
full_cmd = "#{env} #{cmd}"
|
95
|
+
$stdout.puts("#{full_cmd} ... ")
|
96
|
+
|
97
|
+
output = `#{full_cmd} 2>&1`
|
98
|
+
$stdout.puts(output)
|
99
|
+
|
100
|
+
if $?.success?
|
101
|
+
$stdout.puts("[OK]")
|
102
|
+
else
|
103
|
+
$stdout.puts("[FAILED]")
|
104
|
+
$stdout.puts($?.exitstatus)
|
105
|
+
exit($?.exitstatus)
|
106
|
+
end
|
107
|
+
|
108
|
+
output
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
namespace :config do
|
114
|
+
|
115
|
+
desc "copy .example files into their real locations"
|
116
|
+
task :copy_defaults do
|
117
|
+
Dir.glob("config/*.yml.example").each do |file_path|
|
118
|
+
file_name = File.basename(file_path).split(".")[0..1].join(".")
|
119
|
+
dir_name = File.dirname(file_path)
|
120
|
+
FileUtils.cp(file_path, File.join(dir_name, file_name))
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
desc "Generate .travis.yml file for use with Travis-CI"
|
125
|
+
task :generate_travis_yml do
|
126
|
+
|
127
|
+
require 'erb'
|
128
|
+
|
129
|
+
`travis help`
|
130
|
+
if $? == 1
|
131
|
+
puts "This command requires the travis CLI. Install it with 'gem install travis'"
|
132
|
+
exit 1
|
133
|
+
end
|
134
|
+
|
135
|
+
filename = File.join(File.dirname(__FILE__), "..", "templates", "travis.yml.erb")
|
136
|
+
input = File.read(filename)
|
137
|
+
erb = ERB.new(input)
|
138
|
+
|
139
|
+
print "App Name: "
|
140
|
+
app_name = $stdin.gets.strip
|
141
|
+
|
142
|
+
print "Github API Key: "
|
143
|
+
api_key = $stdin.gets.strip
|
144
|
+
|
145
|
+
print "Slack Integration Key (optional): "
|
146
|
+
slack_key = $stdin.gets.strip
|
147
|
+
slack_key = nil if slack_key == ''
|
148
|
+
|
149
|
+
text = erb.result(binding)
|
150
|
+
File.write(Rails.root.join('.travis.yml'), text)
|
151
|
+
|
152
|
+
`travis encrypt --add deploy.api-key #{api_key}`
|
153
|
+
|
154
|
+
if slack_key
|
155
|
+
`travis encrypt --add notifications.slack #{slack_key}`
|
156
|
+
end
|
157
|
+
|
158
|
+
`travis lint`
|
159
|
+
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
branches:
|
2
|
+
except:
|
3
|
+
- /^.*-\d+$/ # exclude build tags
|
4
|
+
- /^.*\/.*+$/ # exclude private branches (with slash)
|
5
|
+
language: ruby
|
6
|
+
env: SQLITE=true
|
7
|
+
rvm:
|
8
|
+
- jruby-19mode
|
9
|
+
install: bundle install --full-index --without='development production' --path vendor/bundle --jobs=3 --retry=3
|
10
|
+
script:
|
11
|
+
- bundle exec rake ci:setup
|
12
|
+
- bundle exec rake db:migrate
|
13
|
+
- bundle exec rake db:test:prepare
|
14
|
+
- mkdir -p tmp/cache
|
15
|
+
- xvfb-run bundle exec rspec
|
16
|
+
cache:
|
17
|
+
directories:
|
18
|
+
- vendor/bundle
|
19
|
+
before_deploy:
|
20
|
+
- bundle exec rake ci:war RAILS_ENV=ci
|
21
|
+
- git tag $TRAVIS_BRANCH-$TRAVIS_BUILD_NUMBER # remove this if you want to tag manually
|
22
|
+
deploy:
|
23
|
+
provider: releases
|
24
|
+
api-key:
|
25
|
+
file: <%= app_name %>.war
|
26
|
+
skip_cleanup: true
|
27
|
+
on:
|
28
|
+
#tags: true # enable if you want to only build via manual tags
|
29
|
+
all_branches: true
|
30
|
+
# addons:
|
31
|
+
# code_climate:
|
32
|
+
# repo_token: (insert repo token from code climate)
|
33
|
+
<% if slack_key %>
|
34
|
+
notifications:
|
35
|
+
slack:
|
36
|
+
<% end %>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'ucb_rails_ci'
|
3
|
+
s.version = '1.0.1'
|
4
|
+
s.summary = "CI and deployment integration for UCB Rails apps"
|
5
|
+
s.description = "Tools for enabling Rails apps to be built on Travis and deployed from GitHub"
|
6
|
+
s.authors = ["Ken Miller"]
|
7
|
+
s.email = 'ken@berkeley.edu'
|
8
|
+
s.date = Time.now.utc.strftime("%Y-%m-%d")
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.homepage = 'https://github.com/ucb-ist-eas/ucb_rails_ci'
|
11
|
+
s.bindir = 'bin'
|
12
|
+
|
13
|
+
s.add_runtime_dependency 'rake'
|
14
|
+
s.add_runtime_dependency 'bundler'
|
15
|
+
s.add_runtime_dependency 'builder'
|
16
|
+
s.add_runtime_dependency 'warbler'
|
17
|
+
s.add_runtime_dependency 'github_api'
|
18
|
+
s.add_runtime_dependency 'travis'
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ucb_rails_ci
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ken Miller
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: builder
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: warbler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: github_api
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: travis
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Tools for enabling Rails apps to be built on Travis and deployed from
|
98
|
+
GitHub
|
99
|
+
email: ken@berkeley.edu
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- Gemfile
|
105
|
+
- Gemfile.lock
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- ci.rb
|
109
|
+
- lib/ucb_rails_ci.rb
|
110
|
+
- lib/ucb_rails_ci/railtie.rb
|
111
|
+
- tasks/ucb_rails_ci.rake
|
112
|
+
- templates/travis.yml.erb
|
113
|
+
- ucb_rails_ci.gemspec
|
114
|
+
homepage: https://github.com/ucb-ist-eas/ucb_rails_ci
|
115
|
+
licenses: []
|
116
|
+
metadata: {}
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - '>='
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
requirements: []
|
132
|
+
rubyforge_project:
|
133
|
+
rubygems_version: 2.2.2
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: CI and deployment integration for UCB Rails apps
|
137
|
+
test_files: []
|