ucb_rails_ci 1.0.1
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.
- 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: []
|