forked from puppetlabs/puppet-docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRakefile
More file actions
366 lines (307 loc) · 12.7 KB
/
Rakefile
File metadata and controls
366 lines (307 loc) · 12.7 KB
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
# encoding: UTF-8
require 'rubygems'
require 'bundler/setup'
require 'rake'
require 'pathname'
require 'fileutils'
require 'yaml'
Dir.glob(File.join("vendor", "gems", "*", "lib")).each do |lib|
$LOAD_PATH.unshift(File.expand_path(lib))
end
begin
require "vlad"
Vlad.load :scm => :git
rescue LoadError
# do nothing
end
$LOAD_PATH.unshift File.expand_path('lib')
references = %w(configuration function indirection metaparameter report type developer man)
top_dir = Dir.pwd
source_dir = "#{top_dir}/source"
output_dir = "#{top_dir}/output"
stash_dir = "#{top_dir}/_stash"
preview_dir = "#{top_dir}/_preview"
version_file = "#{output_dir}/VERSION.txt"
config_data = YAML.load(File.read("#{source_dir}/_config.yml"))
desc "Stash all directories but one in a temporary location. Run a preview server on localhost:4000."
task :preview, :filename do |t, args|
if ["marionette-collective", "puppetdb_master", "puppetdb_1.1", "puppetdb", "mcollective"].include?(args.filename)
abort("\n\n*** External documentation sources aren't supported right now.\n\n")
end
# Make sure we have a stash_directory
FileUtils.mkdir(stash_dir) unless File.exist?(stash_dir)
# Directories and files we have to have for a good live preview
required_dirs = ["_config.yml", "_includes", "_plugins", "files", "favicon.ico", "_layouts","images"]
# Move the things we don't need into the _stash
Dir.glob("#{source_dir}/*") do |directory|
FileUtils.mv directory, stash_dir unless directory.include?(args.filename) || required_dirs.include?(File.basename(directory))
end
# Get all the files we'd like to see in a temporary preview index (so we don't have to hunt for files by name)
Dir.chdir("#{source_dir}/#{args.filename}")
file_list = Dir.glob("**/*.markdown")
preview_index_files = []
file_list.each do |f|
html_name = f.gsub(/\.markdown/,'.html')
preview_index_files << "* [#{args.filename}/#{html_name}](#{args.filename}/#{html_name})\n"
end
preview_index=<<PREVIEW_INDEX
---
layout: frontpage
title: Files Available for Live Preview
canonical: "/"
---
#{preview_index_files}
PREVIEW_INDEX
Dir.chdir(source_dir)
# put our file list index in place
File.open("index.markdown", 'w') {|f| f.write(preview_index) }
# Run our preview server, watching ... watching ...
system("bundle exec jekyll #{preview_dir} --auto --serve")
# When we kill it with a ctl-c ...
puts "\n\n*** Shut down the server."
# Clean up after ourselves (in a separate task in case something goes wrong and we need to do it manually)
Rake::Task['unpreview'].invoke
end
desc "Move all stashed directories back into the source directory, ready for site generation. "
task :unpreview do
puts "\n*** Putting back the stashed files, removing the preview directory."
FileUtils.mv Dir.glob("#{stash_dir}/*"), "#{source_dir}"
FileUtils.rm_rf(preview_dir)
puts "\n*** Done.\n\n"
end
namespace :externalsources do
unless File.exists?("externalsources") && File.directory?("externalsources")
Dir.mkdir("externalsources")
end
# Returns the short name of a repo, which would be the directory name if you did a `git clone` without specifying a directory name. This isn't used anymore, but I left it around in case it's useful later.
def repo_name(repo_url)
repo_url.split('/')[-1].sub(/\.git$/, '')
end
# Returns something like git_github_com_puppetlabs_marionette-collective_git. We use this as the name of the main repo directory, because we may need to disambiguate between two repos with the same short name but a different user account on github.
def repo_unique_id(repo_url)
repo_url.gsub(/[:\/\.]+/, '_')
end
# "Update all working copies defined in source/_config.yml"
task :update do
Rake::Task['externalsources:clone'].invoke
Dir.chdir("externalsources") do
config_data['externalsources'].each do |name, info|
unless File.directory?(name)
puts "Making new working directory for #{name}"
system ("\"#{top_dir}/vendor/bin/git-new-workdir\" '#{repo_unique_id(info['repo'])}' '#{name}' '#{info['commit']}'")
end
Dir.chdir(name) do
puts "Updating #{name}"
system ("git fetch origin && git checkout --force #{info['commit']} && git clean --force .")
end
end
end
end
# "Clone any external documentation repos (from externalsources in source/_config.yml) that don't yet exist"
task :clone do
repos = []
config_data['externalsources'].each do |name, info|
repos << info['repo']
end
Dir.chdir("externalsources") do
repos.uniq.each do |repo|
system ("git clone #{repo} #{repo_unique_id(repo)}") unless File.directory?("#{repo_unique_id(repo)}")
end
end
end
# "Symlink external documentation into place in the source directory"
task :link do
Rake::Task['externalsources:clean'].invoke # Bad things happen if any of these symlinks already exist, and Jekyll will run FOREVER
Rake::Task['externalsources:clean'].reenable
config_data['externalsources'].each do |name, info|
# Have to use absolute paths for the source, since we have no idea how deep in the hierarchy info['url'] is (and thus how many ../..s it would need).
FileUtils.ln_sf "#{top_dir}/externalsources/#{name}/#{info['subdirectory']}", "#{source_dir}#{info['url']}"
end
end
# "Clean up any external source symlinks from the source directory" # In the current implementation, all external sources are symlinks and there are no other symlinks in the source. This means we can naively kill all symlinks in ./source.
task :clean do
allsymlinks = FileList.new("#{source_dir}/**/*").select{|f| File.symlink?(f)}
allsymlinks.each do |f|
File.delete(f)
end
end
end
desc "Generate the documentation"
task :generate do
Rake::Task['externalsources:update'].invoke # Create external sources if necessary, and check out the required working directories
Rake::Task['externalsources:link'].invoke # Link docs folders from external sources into the source at the appropriate places.
system("mkdir -p #{output_dir}")
system("rm -rf #{output_dir}/*")
system("mkdir #{output_dir}/references")
Dir.chdir(source_dir) do
system("bundle exec jekyll #{output_dir}")
end
Rake::Task['references:symlink'].invoke
Rake::Task['symlink_latest_versions'].invoke
Rake::Task['externalsources:clean'].invoke # The opposite of externalsources:link. Delete all symlinks in the source.
Rake::Task['externalsources:clean'].reenable
end
desc "Symlink latest versions of several projects; see symlink_latest and lock_latest lists in _config.yml"
task :symlink_latest_versions do
require 'versionomy'
require 'pathname'
# Auto-link the latest version of every project in symlink_latest
config_data['symlink_latest'].each do |project|
# Skip locked projects
next if config_data['lock_latest'].keys.include?(project)
# this bit is snipped from PuppetDocs::Reference
subdirs = Pathname.new("#{output_dir}/#{project}").children.select do |child|
child.directory? && !child.symlink?
end
versions = []
subdirs.each do |path|
begin
version = Versionomy.parse(path.basename.to_s)
versions << version
rescue
next
end
end
versions.sort! # sorts into ascending order, so most recent is last
Dir.chdir "#{output_dir}/#{project}" do
FileUtils.ln_sf versions.last.to_s, 'latest'
end
end
# Manually link the locked "latest" version of every project in lock_latest
config_data['lock_latest'].each do |project, version|
Dir.chdir "#{output_dir}/#{project}" do
FileUtils.ln_sf version.to_s, 'latest'
end
end
end
desc "Serve generated output on port 9292"
task :serve do
system("rackup")
end
desc "Generate docs and serve locally"
task :run => [:generate, :serve]
task :write_version do
if File.directory?('.git')
current_commit = `git rev-parse HEAD`.strip
File.open(version_file, 'w') do |f|
f.print(current_commit)
end
end
end
task :check_git_dirty_status do
if File.directory?('.git')
Rake::Task['externalsources:clean'].invoke # Don't let leftover symlinks from a cancelled build mark the tree as dirty.
Rake::Task['externalsources:clean'].reenable
if `git status --porcelain 2> /dev/null | tail -n1` != ''
STDOUT.puts "The working directory has uncommitted changes. They're probably either \n incomplete changes you don't want to release, or important changes you \n don't want lost; in either case, you might want to deal with them before \n you build and deploy the site. Continue anyway? (y/n)"
abort "Aborting." unless STDIN.gets.strip.downcase =~ /^y/
end
end
end
task :check_build_version do
abort "No site build found! Run 'rake build' before releasing." unless File.directory?(output_dir)
abort "Site build is empty! Run 'rake build' before releasing." if (Dir.entries(output_dir) - %w{ . .. }).empty?
if File.directory?('.git')
if File.exists?(version_file)
head = `git rev-parse HEAD`.strip
build_version = File.read(version_file)
if head != build_version
STDOUT.puts "This build wasn't built from HEAD and may be outdated. Continue anyway? (y/n)"
abort "Aborting." unless STDIN.gets.strip.downcase =~ /^y/
end
else
STDOUT.puts "Can't tell age of site build; it's probably outdated. Continue anyway? (y/n)"
abort "Aborting." unless STDIN.gets.strip.downcase =~ /^y/
end
end
end
desc "Build the documentation site and prepare it for deployment"
task :build do
Rake::Task['check_git_dirty_status'].invoke
Rake::Task['generate'].invoke
Rake::Task['write_version'].invoke
end
desc "Instead of building real pages, build naked HTML fragments (with no nav, etc.)"
task :build_html_fragments do
Rake::Task['check_git_dirty_status'].invoke
Dir.chdir("#{source_dir}/_layouts") do
FileUtils.mv("default.html", "real_default.html")
FileUtils.mv("fragment.html", "default.html")
end
Rake::Task['generate'].invoke
# don't write version, so we'll give a noisy error if you try to deploy fragments!
Dir.chdir("#{source_dir}/_layouts") do
FileUtils.mv("default.html", "fragment.html")
FileUtils.mv("real_default.html", "default.html")
end
end
desc "Build all references for a new Puppet version"
task :references => [ 'references:check_version', 'references:index:stub', 'references:puppetdoc']
namespace :references do
namespace :symlink do
# "Show the versions that will be symlinked"
task :versions do
require 'puppet_docs'
PuppetDocs::Reference.special_versions.each do |name, (version, source)|
puts "#{name}: #{version}"
end
end
end
# "Symlink the latest & stable directories"
task :symlink do
require 'puppet_docs'
PuppetDocs::Reference.special_versions.each do |name, (version, source)|
Dir.chdir "#{output_dir}/references" do
FileUtils.ln_sf version.to_s, name.to_s
end
end
end
namespace :puppetdoc do
references.each do |name|
# "Write references/VERSION/#{name}"
task name => 'references:check_version' do
require 'puppet_docs'
PuppetDocs::Reference::Generator.new(ENV['VERSION'], name, ENV['COMMIT']).generate
end
end
end
desc "Write all references for VERSION (from optional COMMIT if tag doesn't yet exist)"
task :puppetdoc => references.map { |r| "puppetdoc:#{r}" }
namespace :index do
# "Generate a stub index for VERSION"
task :stub => 'references:check_version' do
filename = Pathname.new("#{source_dir}/references") + ENV['VERSION'] + 'index.markdown'
filename.parent.mkpath
filename.open('w') do |f|
f.puts "---"
f.puts "layout: default"
f.puts "title: #{ENV['VERSION']} References"
f.puts "---\n\n\n"
f.puts "# #{ENV['VERSION']} References\n"
f.puts "* * *\n\n"
references.each do |name|
unless name=="developer" or name=="man"
f.puts "* [#{name.capitalize}](./#{name}.html)"
end
end
f.puts "* [Developer Documentation](./developer/index.html)\n* [Man Pages](./man/index.html)"
end
puts "Wrote #{filename}"
end
end
task :check_version do
abort "No VERSION given to build references for" unless ENV['VERSION']
end
end
desc "Deploy the site to the production servers"
task :deploy do
mirrors = ['mirror0','mirror1']
Rake::Task['build'].invoke
mirrors.each do |mirror|
sh "rake #{mirror} vlad:release"
# Note that the below will always fail on the second mirror, even though it should totally work. Life is filled with mystery. >:|
# Rake::Task[mirror].invoke
# Rake::Task['vlad:release'].reenable # so we can invoke it again if this isn't the last mirror
# Rake::Task['vlad:release'].invoke
end
end