forked from openshift/openshift-docs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Rakefile
466 lines (424 loc) · 15.6 KB
/
Rakefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
require 'asciidoctor'
require 'git'
require 'logger'
require 'pandoc-ruby'
require 'pathname'
require 'rake'
require 'yaml'
BUILD_FILENAME = '_build_cfg.yml'
BUILDER_DIRNAME = '_build_system'
PREVIEW_DIRNAME = '_preview'
PACKAGE_DIRNAME = '_package'
BLANK_STRING_RE = Regexp.new('^\s*$')
PRODUCT_AUTHOR = "OpenShift Documentation Project <[email protected]>"
def source_dir
@source_dir ||= File.expand_path(Dir.pwd)
end
def template_dir
@template_dir ||= File.join(source_dir,'_templates')
end
def preview_dir
@preview_dir ||= begin
preview_dir = File.join(source_dir,PREVIEW_DIRNAME)
if not File.exists?(preview_dir)
Dir.mkdir(preview_dir)
end
preview_dir
end
end
def package_dir
@package_dir ||= begin
package_dir = File.join(source_dir,PACKAGE_DIRNAME)
if not File.exists?(package_dir)
Dir.mkdir(package_dir)
end
package_dir
end
end
def git
@git ||= Git.open(source_dir)
end
def git_checkout branch_name
target_branch = git.branches.local.select{ |b| b.name == branch_name }[0]
if not target_branch.current
target_branch.checkout
end
end
# Returns the local git branches; current branch is always first
def local_branches
@local_branches ||= begin
branches = []
branches << git.branches.local.select{ |b| b.current }[0].name
branches << git.branches.local.select{ |b| not b.current }.map{ |b| b.name }
branches.flatten
end
end
def build_config_file
@build_config_file ||= File.join(source_dir,BUILD_FILENAME)
end
def build_config
@build_config ||= validate_config(YAML.load_stream(open(build_config_file)))
end
def distro_map
@distro_map ||= begin
{ 'openshift-origin' => {
:name => 'OpenShift Origin',
:branches => {
'master' => {
:name => 'Nightly Build',
:dir => 'latest',
},
'origin-4' => {
:name => 'Version 4',
:dir => 'stable',
},
},
},
'openshift-online' => {
:name => 'OpenShift Online',
:branches => {
'online' => {
:name => 'Latest Release',
:dir => 'online',
},
},
},
'openshift-enterprise' => {
:name => 'OpenShift Enterprise',
:branches => {
'enterprise-2.2' => {
:name => 'Version 2.2',
:dir => 'enterprise/v2.2',
},
},
}
}
end
end
def distro_branches
@distro_branches ||= distro_map.map{ |distro,dconfig| dconfig[:branches].keys }.flatten
end
def page(args)
page_css = ''
args[:css].each do |sheet|
sheet_href = args[:css_path] + sheet
page_css << "<link href=\"#{sheet_href}\" rel=\"stylesheet\" />\n"
end
page_head = <<EOF
<!DOCTYPE html>
<html>
<head>
<title>#{args[:distro]} #{args[:version]} | #{args[:group_title]} | #{args[:topic_title]}</title>
#{page_css}
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h3>OpenShift Documentation <small>#{args[:distro]} #{args[:version]}</small></h3>
<div class="row">
<div class="col-md-3">
<form method="get" onsubmit="window.location.href='https://www.google.com/search?as_q=' + this.elements.docsSearch.value + '&as_sitesearch=openshift.github.io';">
<div class="input-group">
<!-- <span class="input-group-addon"><span class="glyphicon glyphicon-search"></span></span> //-->
<input id="docsSearch" name="docsSearch" type="text" class="form-control" />
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="window.location.href='https://www.google.com/search?as_q=' + this.form.elements.docsSearch.value + '&as_sitesearch=openshift.github.io';">Search</button>
</span>
</div>
<p> </p>
</form>
EOF
page_nav = [' <div class="panel-group">']
groupidx = 0
args[:navigation].each do |topic_group|
current_group = topic_group[:id] == args[:group_id]
page_nav << ' <div class="panel panel-default">'
page_nav << ' <div class="panel-heading">'
page_nav << ' <h3 class="panel-title">'
page_nav << " <a data-toggle=\"collapse\" data-parent=\"#accordion\" href=\"#topicGroup#{groupidx}\">#{topic_group[:name]}</a>"
page_nav << ' </h3>'
page_nav << ' </div>'
page_nav << " <ul id=\"topicGroup#{groupidx}\" class=\"list-group panel-collapse collapse#{current_group ? ' in' : ''}\">"
topic_group[:topics].each do |topic|
current_topic = topic[:id] == args[:topic_id]
page_nav << " <li class=\"list-group-item\"><a class=\"list-group-item#{current_topic ? ' active' : ''}\" href=\"#{topic[:path]}\">#{topic[:name]}</a></li>"
end
page_nav << ' </ul>'
page_nav << ' </div>'
groupidx = groupidx + 1
end
page_nav << ' </div>'
page_body = <<EOF
</div>
<div class="col-md-9">
<div class="page-header">
<h2>#{args[:group_title]}: #{args[:topic_title]}</h2>
</div>
#{args[:content]}
</div>
</div>
</div>
</body>
</html>
EOF
page_txt = ''
page_txt << page_head
page_txt << "\n"
page_txt << page_nav.join("\n")
page_txt << "\n"
page_txt << page_body
page_txt
end
def parse_distros distros_string, for_validation=false
values = distros_string.split(',').map{ |v| v.strip }
return values if for_validation
return distro_map.keys if values.include?('all')
return values.uniq
end
def validate_distros distros_string
return false if not distros_string.is_a?(String)
values = parse_distros(distros_string, true)
values.each do |v|
return false if not v == 'all' or not distro_map.keys.include?(v)
end
return true
end
def validate_config config_data
# Validate/normalize the config file straight away
if not config_data.is_a?(Array)
raise "The configutaration in #{build_config_file} is malformed; the build system is expecting an array of topic groups."
end
config_data.each do |topic_group|
# Check for presence of topic group keys
['Name','Dir','Topics'].each do |group_key|
if not topic_group.has_key?(group_key)
raise "One of the topic groups in #{build_config_file} is missing the '#{group_key}' key."
end
end
# Check for right format of topic group values
['Name','Dir'].each do |group_key|
if not topic_group[group_key].is_a?(String)
raise "One of the topic groups in #{build_config_file} is not using a string for the #{group_key} setting; current value is #{topic_group[group_key].inspect}"
end
if topic_group[group_key].empty? or topic_group[group_key].match BLANK_STRING_RE
raise "One of the topic groups in #{build_config_file} is using a blank value for the #{group_key} setting."
end
end
if not File.exists?(File.join(source_dir,topic_group['Dir']))
raise "In #{build_config_file}, the directory #{topic_group['Dir']} for topic group #{topic_group['Name']} does not exist under #{source_dir}"
end
# Validate the Distros setting
if topic_group.has_key?('Distros')
if not validate_distros(topic_group['Distros'])
key_list = distro_map.keys.map{ |k| "'#{k.to_s}'" }.sort.join(', ')
raise "In #{build_config_file}, the Distros value #{topic_group['Distros'].inspect} for topic group #{topic_group['Name']} is not valid. Legal values are 'all', #{key_list}, or a comma-separated list of legal values."
end
topic_group['Distros'] = parse_distros(topic_group['Distros'])
else
topic_group['Distros'] = parse_distros('all')
end
if not topic_group['Topics'].is_a?(Array)
raise "The #{topic_group['Name']} topic group in #{build_config_file} is malformed; the build system is expecting an array of 'Topic' definitions."
end
# Generate an ID for this topic group
topic_group['ID'] = camelize topic_group['Name']
# Now buzz through the topics
topic_group['Topics'].each do |topic|
['Name','File'].each do |topic_key|
if not topic[topic_key].is_a?(String)
raise "In #{build_config_file}, topic group #{topic_group['Name']}, one of the topics is not using a string for the '#{topic_key}' setting; current value is #{topic[topic_key].inspect}"
end
if topic[topic_key].empty? or topic[topic_key].match BLANK_STRING_RE
raise "In #{build_config_file}, topic group #{topic_group['Name']}, one of the topics is using a blank value for the '#{topic_key}' setting"
end
end
# Normalize the filenames
if topic['File'].end_with?('.adoc')
topic['File'] = topic['File'][0..-6]
end
if not File.exists?(File.join(source_dir,topic_group['Dir'],"#{topic['File']}.adoc"))
raise "In #{build_config_file}, could not find file #{topic['File']} under directory #{topic_group['Dir']} for topic #{topic['Name']} in topic group #{topic_group['Name']}."
end
if topic.has_key?('Distros')
if not validate_distros(topic['Distros'])
key_list = distro_map.keys.map{ |k| "'#{k.to_s}'" }.sort.join(', ')
raise "In #{build_config_file}, the Distros value #{topic_group['Distros'].inspect} for topic item #{topic['Name']} in topic group #{topic_group['Name']} is not valid. Legal values are 'all', #{key_list}, or a comma-separated list of legal values."
end
topic['Distros'] = parse_distros(topic['Distros'])
else
topic['Distros'] = parse_distros('all')
end
# Generate an ID for this topic
topic['ID'] = "#{topic_group['ID']}::#{camelize(topic['Name'])}"
end
end
config_data
end
def camelize text
text.split(' ').map{ |t| t.capitalize }.join
end
def nav_tree distro
@nav_tree ||= begin
navigation = []
build_config.each do |topic_group|
next if not topic_group['Distros'].include?(distro)
next if topic_group['Topics'].select{ |t| t['Distros'].include?(distro) }.length == 0
topic_list = []
topic_group['Topics'].each do |topic|
next if not topic['Distros'].include?(distro)
topic_list << {
:path => "../#{topic_group['Dir']}/#{topic['File']}.html",
:name => topic['Name'],
:id => topic['ID'],
}
end
navigation << { :name => topic_group['Name'], :id => topic_group['ID'], :topics => topic_list }
end
navigation
end
end
task :build do
# First, notify the user of missing local branches
missing_branches = []
distro_branches.sort.each do |dbranch|
next if local_branches.include?(dbranch)
missing_branches << dbranch
end
if missing_branches.length > 0
puts "\nNOTE: The following branches do not exist in your local git repo:"
missing_branches.each do |mbranch|
puts "- #{mbranch}"
end
puts "The build will proceed but these branches will not be generated."
end
distro_map.each do |distro,distro_config|
puts "\n\nBuilding #{distro_config[:name]}"
distro_config[:branches].each do |branch,branch_config|
if missing_branches.include?(branch)
puts "- skipping #{branch}"
next
end
puts "- building #{branch}"
# Put us on the correct branch
git_checkout(branch)
# Create the target dir
branch_path = "#{preview_dir}/#{branch_config[:dir]}"
system("mkdir -p #{branch_path}/stylesheets")
# Copy stylesheets into preview area
system("cp -r _stylesheets/*css #{branch_path}/stylesheets")
# Build the landing page
navigation = nav_tree(distro)
# Build the topic files
build_config.each do |topic_group|
next if not topic_group['Distros'].include?(distro)
next if topic_group['Topics'].select{ |t| t['Distros'].include?(distro) }.length == 0
src_group_path = File.join(source_dir,topic_group['Dir'])
tgt_group_path = File.join(branch_path,topic_group['Dir'])
if not File.exists?(tgt_group_path)
Dir.mkdir(tgt_group_path)
end
topic_group['Topics'].each do |topic|
next if not topic['Distros'].include?(distro)
puts " - #{topic['ID']}"
src_file_path = File.join(src_group_path,"#{topic['File']}.adoc")
tgt_file_path = File.join(tgt_group_path,"#{topic['File']}.html")
topic_adoc = File.open(src_file_path,'r').read
topic_html = Asciidoctor.render topic_adoc, :header_footer => false, :safe => :unsafe, :attributes => ['source-highlighter=coderay','coderay-css=style',"imagesdir=#{src_group_path}/images",'linkcss!','icons=font','idprefix=','idseparator=-','sectanchors', distro, "product-title=#{distro_config[:name]}", "product-version=#{branch_config[:name]}", "product-author=#{PRODUCT_AUTHOR}"]
full_file_text = page({
:distro => distro_config[:name],
:version => branch_config[:name],
:group_title => topic_group['Name'],
:topic_title => topic['Name'],
:content => topic_html,
:navigation => navigation,
:group_id => topic_group['ID'],
:topic_id => topic['ID'],
:css_path => "#{branch_path}/stylesheets/",
:css => [
'bootstrap_default.min.css',
'font-awesome.min.css',
'foundation.css',
'origin.css',
]
})
File.write(tgt_file_path,full_file_text)
end
end
end
# Return to the original branch
git_checkout(local_branches[0])
end
end
task :package do
builds = [
{ :branch => 'master',
:branch_dir => ['/','openshift_origin/nightly'],
:doc_version => 'OpenShift Origin Latest'
},
]
branches = `git branch`.split(/\n/).map{ |branch| branch.strip }
# Remeber the working branch so that we can return here later.
working_branch = 'master'
branches.each do |branch|
next if not branch.start_with?('*')
working_branch = branch.sub!(/^\* /,'')
end
# Make sure the working branch doesn't have any uncommitted changes
changed_files = `git status --porcelain`
if not changed_files.empty?
puts "Warning: Your current branch has uncommitted changes. Hit <CTRL+C> if you want to exit."
print "Starting packager in "
[3,2,1].each do |i|
print "#{i}..."
sleep 1
end
print "\n"
end
# Now make sure the build branches are available.
missing_branches = false
builds.each do |build|
if not branches.include?(build[:branch])
if not missing_branches
puts "ERROR: One or more branches for packaging are not available in this local repo:"
missing_branches = true
end
puts "- #{build[:branch]}"
end
end
if missing_branches
puts "Add these branches and rerun the packaging command."
exit 1
end
# Start packaging. Clear out the old package dir before making the new package
if Dir.entries('..').include?('_package')
system 'rm', '-rf', '../_package'
end
Dir.mkdir('../_package')
# Now make each package.
builds.each do |build|
# Check out this build branch
system("git checkout #{build[:branch]}")
if not $?.exitstatus == 0
puts "ERROR: Could not check out branch #{build[:branch]}, please investigate."
exit 1
end
# Make the build dir
build_dir = "../_package/#{build[:site_dir]}"
Dir.mkdir(build_dir)
# Build the docs
Rake::Task['build'].execute
# Clean everything up
Rake::Task['clean'].execute
end
# Return to the original branch
system("git checkout #{working_branch}")
puts "Packaging completed."
end
task :clean do
sh "rm -rf _preview/* _package/*" do |ok,res|
if ! ok
puts "Nothing to clean."
end
end
end