From 85a24dbd18feae8ccb07aa44c4e3678b5708c878 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Thu, 21 Mar 2019 03:12:21 +0100 Subject: [PATCH 01/13] Add docs_generation.lock to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 46957c4..94c6605 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Vagrantfile .vagrant +docs_generation.lock From 9fc9c75d54a07564643d381b3efd454ae5cd2a31 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Thu, 21 Mar 2019 03:20:57 +0100 Subject: [PATCH 02/13] Configurable path that defaults to the gitignored ./checkout/ directory Prevents polluting home directory on non-CI/prod servers --- .gitignore | 1 + bin/generate_docs.rb | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 46957c4..d66a6f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Vagrantfile .vagrant +checkout/ diff --git a/bin/generate_docs.rb b/bin/generate_docs.rb index a4795eb..053df9e 100755 --- a/bin/generate_docs.rb +++ b/bin/generate_docs.rb @@ -5,11 +5,23 @@ require 'lock_file' require 'docs_generator' require 'git_manager' +require 'fileutils' + +if ARGV.size > 1 || ARGV.first == "-h" || ARGV.first == "--help" + puts "USAGE: bin/generate_docs.rb [CHECKOUT_PATH]" + exit +end + +CHECKOUT_PATH = ARGV.first || File.join(File.dirname(__FILE__), '../checkout') + +unless Dir.exists?(CHECKOUT_PATH) + FileUtils.mkdir(CHECKOUT_PATH) +end LockFile.acquiring('docs_generation.lock') do - git_manager = GitManager.new(Dir.home) + git_manager = GitManager.new(CHECKOUT_PATH) git_manager.update_master - generator = DocsGenerator.new(Dir.home, git_manager) + generator = DocsGenerator.new(CHECKOUT_PATH, git_manager) generator.generate end From 047ac895b6771608a18f2f3c2abf00accd537989 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Thu, 21 Mar 2019 04:02:43 +0100 Subject: [PATCH 03/13] Create guides directory if it doesn't exist --- lib/generators/release.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/generators/release.rb b/lib/generators/release.rb index e6c642b..9b1d398 100644 --- a/lib/generators/release.rb +++ b/lib/generators/release.rb @@ -35,6 +35,8 @@ def generate_api end def generate_guides + FileUtils.mkdir('guides') unless Dir.exists?('guides') + Dir.chdir('guides') do rake 'guides:generate:html', 'RAILS_VERSION' => target rake 'guides:generate:kindle', 'RAILS_VERSION' => target From 791e3adc94742812947ec5cc57d8acc8f8bf5754 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Thu, 21 Mar 2019 23:41:42 +0100 Subject: [PATCH 04/13] log command executed and Done when finished --- lib/docs_compressor.rb | 4 +++- lib/generators/base.rb | 8 +++++++- lib/git_manager.rb | 12 +++++++----- lib/running.rb | 8 ++++++++ 4 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 lib/running.rb diff --git a/lib/docs_compressor.rb b/lib/docs_compressor.rb index 0fad71f..38a398a 100644 --- a/lib/docs_compressor.rb +++ b/lib/docs_compressor.rb @@ -2,12 +2,14 @@ require 'fileutils' require 'shellwords' require 'logging' +require 'running' # Compresses HTML, JavaScript, and CSS under the given directory, recursively. # # We do this to leverage gzip_static in nginx. class DocsCompressor include Logging + include Running EXTENSIONS = %w(.js .html .css) @@ -40,7 +42,7 @@ def compress_file(file) orig = Shellwords.shellescape(file) dest = Shellwords.shellescape(gzname(file)) - system %(gzip -c -9 #{orig} > #{dest}) + log_and_system %(gzip -c -9 #{orig} > #{dest}) end def compress_file?(file) diff --git a/lib/generators/base.rb b/lib/generators/base.rb index c59da8c..53e070a 100644 --- a/lib/generators/base.rb +++ b/lib/generators/base.rb @@ -74,7 +74,13 @@ def env_as_assigns(env) def run(command, env={}) command = "rvm #{ruby_version} do #{command} >/dev/null" log "#{env_as_assigns(env)} #{command}" - system(env, command) + + if system(env, command) + true + else + log "\"#{command}\" failed to execute" + exit + end end # Runs `bundle exec rake` with the appropriate Bundler and Ruby versions. diff --git a/lib/git_manager.rb b/lib/git_manager.rb index 0184bc1..9ef3f95 100644 --- a/lib/git_manager.rb +++ b/lib/git_manager.rb @@ -1,8 +1,10 @@ require 'logging' +require 'running' # Lightweight wrapper over Git, shells out everything. class GitManager include Logging + include Running attr_reader :basedir @@ -18,7 +20,7 @@ def update_master Dir.chdir(basedir) do unless Dir.exist?('master') log "cloning master into #{basedir}/master" - system "git clone -q #{remote_rails_url} master" + log_and_system "git clone -q #{remote_rails_url} master" end Dir.chdir('master') do @@ -28,8 +30,8 @@ def update_master # git pull from succeeding. Starting with Bundler 1.10, if Gemfile.lock # does not change BUNDLED WITH is left as is, even if versions differ, # but since docs generation is automated better play safe. - system 'git checkout Gemfile.lock' - system 'git pull -q' + log_and_system 'git checkout Gemfile.lock' + log_and_system 'git pull -q' end end end @@ -37,10 +39,10 @@ def update_master def checkout(tag) Dir.chdir(basedir) do log "checking out tag #{tag}" - system "git clone -q #{remote_rails_url} #{tag}" + log_and_system "git clone -q #{remote_rails_url} #{tag}" Dir.chdir(tag) do - system "git checkout -q #{tag}" + log_and_system "git checkout -q #{tag}" end end end diff --git a/lib/running.rb b/lib/running.rb new file mode 100644 index 0000000..b8ddb3f --- /dev/null +++ b/lib/running.rb @@ -0,0 +1,8 @@ +module Running + include Logging + + def log_and_system(*args) + log(args.map(&:to_s).join(' ')) + system(*args).tap { log "Done" } + end +end From 2870bb81b318f35555a1a57234866ecc393fa86c Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Thu, 21 Mar 2019 23:45:40 +0100 Subject: [PATCH 05/13] use abort instead of exit, e.g. same as exit 1 --- lib/generators/base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/generators/base.rb b/lib/generators/base.rb index 53e070a..5b0cf20 100644 --- a/lib/generators/base.rb +++ b/lib/generators/base.rb @@ -79,7 +79,7 @@ def run(command, env={}) true else log "\"#{command}\" failed to execute" - exit + abort end end From 028fc5ed0a7522e713680e0e525feaadac730dc0 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Thu, 21 Mar 2019 23:50:39 +0100 Subject: [PATCH 06/13] defaults to dir home for backward compatibility --- bin/generate_docs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/generate_docs.rb b/bin/generate_docs.rb index 053df9e..d3a37ce 100755 --- a/bin/generate_docs.rb +++ b/bin/generate_docs.rb @@ -12,7 +12,7 @@ exit end -CHECKOUT_PATH = ARGV.first || File.join(File.dirname(__FILE__), '../checkout') +CHECKOUT_PATH = ARGV.first || Dir.home unless Dir.exists?(CHECKOUT_PATH) FileUtils.mkdir(CHECKOUT_PATH) From ce2082a60a7b859eeb8550bf25f4de933fd6b1cf Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Fri, 22 Mar 2019 00:17:28 +0100 Subject: [PATCH 07/13] Add two command line options: --verbose and --target --- bin/generate_docs.rb | 37 +++++++++++++++++++++++++++++++++++-- lib/docs_generator.rb | 12 +++++++++--- lib/generators/base.rb | 9 +++++++-- lib/git_manager.rb | 15 ++++++++++----- 4 files changed, 61 insertions(+), 12 deletions(-) diff --git a/bin/generate_docs.rb b/bin/generate_docs.rb index a4795eb..660993b 100755 --- a/bin/generate_docs.rb +++ b/bin/generate_docs.rb @@ -5,11 +5,44 @@ require 'lock_file' require 'docs_generator' require 'git_manager' +require 'fileutils' +require 'optparse' + +options = {} + +OptionParser.new do |opts| + opts.banner = "Usage: bin/generate_docs.rb [-v|--verbose] [-tTARGET|--target=TARGET]" + + opts.on("-v", "--verbose", "Run verbosely") do |v| + options[:verbose] = v + end + + opts.on( + "-tTARGET", + "--target=TARGET", + "Target directory where to checkout the code, defaults to HOME" + ) do |t| + options[:target] = t + end +end.parse! + +options[:verbose] = false if options[:verbose].nil? +options[:target] ||= Dir.home +options[:target].gsub!(/\/$/, '') + +unless Dir.exists?(options[:target]) + FileUtils.mkdir(options[:target]) +end LockFile.acquiring('docs_generation.lock') do - git_manager = GitManager.new(Dir.home) + git_manager = GitManager.new(options[:target], verbose: options[:verbose]) git_manager.update_master - generator = DocsGenerator.new(Dir.home, git_manager) + generator = DocsGenerator.new( + options[:target], + git_manager, + verbose: options[:verbose] + ) + generator.generate end diff --git a/lib/docs_generator.rb b/lib/docs_generator.rb index 7ed5810..55e4773 100644 --- a/lib/docs_generator.rb +++ b/lib/docs_generator.rb @@ -66,9 +66,10 @@ class DocsGenerator # # @param basedir [String] # @param git_manager [GitManager] - def initialize(basedir, git_manager=GitManager.new(basedir)) + def initialize(basedir, git_manager = GitManager.new(basedir), verbose: false) @basedir = File.expand_path(basedir) @git_manager = git_manager + @verbose = verbose end def generate @@ -98,7 +99,7 @@ def generate_docs_for_release?(tag) def generate_docs_for_release(tag) git_manager.checkout(tag) - generator = Generators::Release.new(tag, tag) + generator = Generators::Release.new(tag, tag, verbose: @verbose) generator.generate DocsCompressor.new(generator.api_output).compress @@ -109,7 +110,12 @@ def generate_docs_for_release(tag) end def generate_edge_docs - generator = Generators::Master.new(git_manager.short_sha1, 'master') + generator = Generators::Master.new( + git_manager.short_sha1, + 'master', + verbose: @verbose + ) + generator.generate DocsCompressor.new(generator.api_output).compress diff --git a/lib/generators/base.rb b/lib/generators/base.rb index c59da8c..66376f5 100644 --- a/lib/generators/base.rb +++ b/lib/generators/base.rb @@ -13,9 +13,14 @@ class Base # @param target [String] A Git reference like 'v4.2.0' or a SHA1 # @param basedir [String] A directory in which target has been checked out - def initialize(target, basedir) + def initialize(target, basedir, verbose: false) @target = target @basedir = File.expand_path(basedir) + @verbose = verbose + end + + def dev_null_unless_verbose + @verbose ? "" : " > /dev/null" end # Generates the documentation for target within basedir. @@ -72,7 +77,7 @@ def env_as_assigns(env) # @param command [String] # @param env [Hash{String => String}] def run(command, env={}) - command = "rvm #{ruby_version} do #{command} >/dev/null" + command = "rvm #{ruby_version} do #{command}#{dev_null_unless_verbose}" log "#{env_as_assigns(env)} #{command}" system(env, command) end diff --git a/lib/git_manager.rb b/lib/git_manager.rb index 0184bc1..448bfbf 100644 --- a/lib/git_manager.rb +++ b/lib/git_manager.rb @@ -6,8 +6,13 @@ class GitManager attr_reader :basedir - def initialize(basedir) + def initialize(basedir, verbose: false) @basedir = File.expand_path(basedir) + @verbose = verbose + end + + def q_unless_verbose + @verbose ? "" : "-q" end def remote_rails_url @@ -18,7 +23,7 @@ def update_master Dir.chdir(basedir) do unless Dir.exist?('master') log "cloning master into #{basedir}/master" - system "git clone -q #{remote_rails_url} master" + system "git clone #{q_unless_verbose} #{remote_rails_url} master" end Dir.chdir('master') do @@ -29,7 +34,7 @@ def update_master # does not change BUNDLED WITH is left as is, even if versions differ, # but since docs generation is automated better play safe. system 'git checkout Gemfile.lock' - system 'git pull -q' + system "git pull #{q_unless_verbose}" end end end @@ -37,10 +42,10 @@ def update_master def checkout(tag) Dir.chdir(basedir) do log "checking out tag #{tag}" - system "git clone -q #{remote_rails_url} #{tag}" + system "git clone #{q_unless_verbose} #{remote_rails_url} #{tag}" Dir.chdir(tag) do - system "git checkout -q #{tag}" + system "git checkout #{q_unless_verbose} #{tag}" end end end From c4982c659a6ef8d8311666fc387d4afc70b1b26e Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Fri, 22 Mar 2019 00:21:40 +0100 Subject: [PATCH 08/13] Actually --help is already auto-generated --- bin/generate_docs.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/generate_docs.rb b/bin/generate_docs.rb index 660993b..a913dce 100755 --- a/bin/generate_docs.rb +++ b/bin/generate_docs.rb @@ -11,7 +11,7 @@ options = {} OptionParser.new do |opts| - opts.banner = "Usage: bin/generate_docs.rb [-v|--verbose] [-tTARGET|--target=TARGET]" + opts.banner = "Usage: bin/generate_docs.rb [options]" opts.on("-v", "--verbose", "Run verbosely") do |v| options[:verbose] = v From b79db9eda76b6e2bca056d39442a0501cf09a240 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Fri, 22 Mar 2019 03:46:28 +0100 Subject: [PATCH 09/13] fix release generator --- lib/generators/release.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/generators/release.rb b/lib/generators/release.rb index 9b1d398..56ce2d2 100644 --- a/lib/generators/release.rb +++ b/lib/generators/release.rb @@ -7,8 +7,8 @@ module Generators class Release < Base include Config::Release - def initialize(tag, basedir) - super(tag, basedir) + def initialize(tag, basedir, verbose: false) + super(tag, basedir, verbose: verbose) @version_number = VersionNumber.new(tag) end From b8151aa80feb0830c6ebba02cf0a4e38182a37d0 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Fri, 22 Mar 2019 03:47:16 +0100 Subject: [PATCH 10/13] add RVM PATH instructions to README Only fish but quite obvious what is going on for other shells users --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index 9dbf522..fe30260 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,16 @@ LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 ``` +## RVM + +Be sure to have rvm binaries in your PATH to make RVM scripting work correctly. + +- With fish shell, in `~/.config/fish/config.fish`: + +``` +set -gx PATH $HOME/.rvm/bin $PATH +``` + ## Deployment Just push to `master`. The cron job in the docs server pulls before invoking From df4b0f0bcc7d537062bfbcef51e721a58c273337 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Fri, 22 Mar 2019 03:47:36 +0100 Subject: [PATCH 11/13] add --tags command line flag to target specific tags --- bin/generate_docs.rb | 10 +++++++++- lib/docs_generator.rb | 17 +++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/bin/generate_docs.rb b/bin/generate_docs.rb index a913dce..f027be7 100755 --- a/bin/generate_docs.rb +++ b/bin/generate_docs.rb @@ -24,6 +24,13 @@ ) do |t| options[:target] = t end + + opts.on( + "--tags=TAGS", + "Comma-separated git tags (e.g. Rails versions) to checkout (format: vX.X.X, edge)" + ) do |t| + options[:tags] = t + end end.parse! options[:verbose] = false if options[:verbose].nil? @@ -41,7 +48,8 @@ generator = DocsGenerator.new( options[:target], git_manager, - verbose: options[:verbose] + verbose: options[:verbose], + tags: options[:tags] ) generator.generate diff --git a/lib/docs_generator.rb b/lib/docs_generator.rb index 55e4773..aa00250 100644 --- a/lib/docs_generator.rb +++ b/lib/docs_generator.rb @@ -66,10 +66,11 @@ class DocsGenerator # # @param basedir [String] # @param git_manager [GitManager] - def initialize(basedir, git_manager = GitManager.new(basedir), verbose: false) + def initialize(basedir, git_manager = GitManager.new(basedir), verbose: false, tags: nil) @basedir = File.expand_path(basedir) @git_manager = git_manager @verbose = verbose + @tags = tags.to_s.split(',') end def generate @@ -83,7 +84,14 @@ def generate_release_docs new_release_docs = false git_manager.release_tags.each do |tag| - if generate_docs_for_release?(tag) + targeted = @tags.any? && @tags.include?(tag) + + if !targeted && @tags.any? + log "Skipping #{tag}" + next + end + + if generate_docs_for_release?(tag) || targeted generate_docs_for_release(tag) new_release_docs = true end @@ -110,6 +118,11 @@ def generate_docs_for_release(tag) end def generate_edge_docs + if @tags.any? && !@tags.include?("edge") + log "Skipping edge" + return + end + generator = Generators::Master.new( git_manager.short_sha1, 'master', From 6ec5648a150d199578530f01789b58ee1b5db927 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Fri, 22 Mar 2019 03:52:07 +0100 Subject: [PATCH 12/13] typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fe30260..e1c1552 100644 --- a/README.md +++ b/README.md @@ -58,4 +58,4 @@ In order to run the test suite you need a recent version of minitest: There are two tasks: The default task, `test`, tests everything except actual docs generation. The `test:all` task runs the entire suite including doc -generation for a few releases, this one takes about 20 minutes in my laptop. +generation for a few releases, this one takes about 20 minutes on my laptop. From 58a3154b3582d2a9865dbbfad5ddcb6914c78da9 Mon Sep 17 00:00:00 2001 From: localhostdotdev Date: Fri, 22 Mar 2019 03:55:35 +0100 Subject: [PATCH 13/13] Add Nokogiri fix instructions in README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e1c1552..d73fb17 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,10 @@ Be sure to have rvm binaries in your PATH to make RVM scripting work correctly. set -gx PATH $HOME/.rvm/bin $PATH ``` +## Nokogiri + +You might need to do `bundle config build.nokogiri --use-system-libraries` on macOS to have nokogiri compile. + ## Deployment Just push to `master`. The cron job in the docs server pulls before invoking