Skip to content

Commit

Permalink
Refactor and tidy up
Browse files Browse the repository at this point in the history
  • Loading branch information
eoinkelly committed Nov 23, 2024
1 parent 4d7583d commit 82e3c7f
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 82 deletions.
19 changes: 15 additions & 4 deletions bin/build
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

require "fileutils"
require "yaml"
require_relative "./lib/config"
require_relative "./lib/builder"
require_relative "lib/build_config"
require_relative "lib/builder"
require_relative "lib/terminal"

# Usage:
#
Expand All @@ -19,13 +20,23 @@ require_relative "./lib/builder"
# $ ./build default # build using the default config
# $ ./build basic # build using the basic CI config
# $ ./build react # build using the React CI config
#
# You can capture the output to a file using the `tee` command:
#
# $ ./build all_variants | tee build.log
#
# If you want to capture the output to a file and keep the color output, you can
# use the `unbuffer` command:
#
# $ brew install expect # or your linux distro equivalent
# $ unbuffer ./build all_variants | tee build.log

class Main
class << self
def main
configs = Config.resolve_to_configs(ARGV.first)
configs = BuildConfig.resolve_to_configs(ARGV.first)

puts configs_summary(configs)
Terminal.puts_header(configs_summary(configs))

configs.each do |config|
Builder.new(config:).build
Expand Down
110 changes: 68 additions & 42 deletions bin/compare
Original file line number Diff line number Diff line change
@@ -1,61 +1,87 @@
#!/usr/bin/env ruby

require "fileutils"
require "pry"
require_relative "lib/comparison_config"
require_relative "lib/terminal"

PROJECT_ROOT_PATH = File.absolute_path(File.join(__dir__, "."))
BUILD_PATH = File.join(PROJECT_ROOT_PATH, "tmp/builds")
COMPARISONS_REPO_ROOT_PATH = File.join(PROJECT_ROOT_PATH, "tmp/rails-template-variants-comparison")
ALL_BUILDS = Dir.children(BUILD_PATH)
class Main
class << self
def main
reset_comparison_repo
use_vanilla_rails_as_main_branch

VANILLA_BUILD_NAME = ALL_BUILDS.find { |build_name| build_name.start_with?("vanilla_") }
VANILLA_BUILD_PATH = File.join(BUILD_PATH, VANILLA_BUILD_NAME)
COMPARISON_BUILDS = ALL_BUILDS - [VANILLA_BUILD_NAME]
ComparisonConfig.comparison_builds.each do |build_name|
populate_new_branch_for_build(build_name:)
checkout_main
end
end

def copy_build(build_name:, branch_name:, build_path:)
system("git checkout -b #{branch_name}")
private

# the `.` at the end of the cp command is what copies the contents of the dir
# including "hidden" `.` files (the same trick works with shell `cp` command)
# FileUtils.cp_r("#{build_path}/.", COMPARISONS_REPO_ROOT_PATH)
system("rsync -av --exclude='.git' --exclude='node_modules' --exclude='tmp' #{build_path}/ #{COMPARISONS_REPO_ROOT_PATH}/")
def reset_comparison_repo
repo_path = ComparisonConfig.comparison_repo_root_path

system("git add .")
system("git commit -n -m 'Add #{build_name}'")
end
FileUtils.rm_rf(repo_path)
FileUtils.mkdir_p(repo_path)

Dir.chdir(repo_path) do
system("git init")
system("git remote add origin [email protected]:ackama/rails-template-variants-comparison.git")
end
end

def use_vanilla_rails_as_main_branch
Terminal.puts_header("Adding vanilla Rails build to main branch")
copy_build(build_path: ComparisonConfig.vanilla_build_path)
commit_changes(commit_message: "Add #{ComparisonConfig.vanilla_build_name}")
end

def populate_new_branch_for_build(build_name:)
Terminal.puts_header("Creating branch for #{build_name}")

def main
FileUtils.rm_rf(COMPARISONS_REPO_ROOT_PATH)
FileUtils.mkdir_p(COMPARISONS_REPO_ROOT_PATH)
rm_rf_except_git_dir
create_new_branch(branch_name: build_name)

Dir.chdir(COMPARISONS_REPO_ROOT_PATH) do
system("git init")
system("git remote add origin [email protected]:ackama/rails-template-variants-comparison.git")
build_path = File.join(ComparisonConfig.build_path, build_name)
copy_build(build_path:)

copy_build(
build_name: VANILLA_BUILD_NAME,
branch_name: "main",
build_path: VANILLA_BUILD_PATH
)
commit_changes(commit_message: "Add #{build_name}")
end

def checkout_main
Dir.chdir(ComparisonConfig.comparison_repo_root_path) do
system("git checkout main")
end
end

COMPARISON_BUILDS.each do |build_name|
build_path = File.join(BUILD_PATH, build_name)
keepers = [".git", "."]
deletable_files = Dir.glob("{*,.*}").reject { |f| keepers.include?(f) }
# clean out all the files from the previous build (except .git)
def rm_rf_except_git_dir
Dir.chdir(ComparisonConfig.comparison_repo_root_path) do
keepers = [".git", "."]
deletable_files = Dir.glob("{*,.*}").reject { |f| keepers.include?(f) }

# clean out all the files from the previous build (except .git)
FileUtils.rm_rf(deletable_files)
FileUtils.rm_rf(deletable_files)
end
end

copy_build(
build_name:,
branch_name: build_name,
build_path:
)
def create_new_branch(branch_name:)
Dir.chdir(ComparisonConfig.comparison_repo_root_path) do
system("git checkout -b #{branch_name}")
end
end

def commit_changes(commit_message:)
Dir.chdir(ComparisonConfig.comparison_repo_root_path) do
system("git add .")
# skip pre-commit hooks because they're not relevant here
system("git commit --quiet --no-verify -m '#{commit_message}'")
end
end

# go back to main before we start the next build
system("git checkout main")
def copy_build(build_path:)
system("rsync -qav --exclude='.git' --exclude='node_modules' --exclude='tmp' #{build_path}/ #{ComparisonConfig.comparison_repo_root_path}/")
end
end
end

main
Main.main
26 changes: 13 additions & 13 deletions bin/create_prs
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
#!/usr/bin/env ruby

PROJECT_ROOT_PATH = File.absolute_path(File.join(__dir__, "."))
BUILD_PATH = File.join(PROJECT_ROOT_PATH, "tmp/builds")
COMPARISONS_REPO_ROOT_PATH = File.join(PROJECT_ROOT_PATH, "tmp/rails-template-variants-comparison")
ALL_BUILDS = Dir.children(BUILD_PATH)
VANILLA_BUILD_NAME = ALL_BUILDS.find { |build_name| build_name.start_with?("vanilla_") }
COMPARISON_BUILDS = ALL_BUILDS - [VANILLA_BUILD_NAME]
require_relative "lib/comparison_config"
require_relative "lib/terminal"

def main
Dir.chdir(COMPARISONS_REPO_ROOT_PATH) do
COMPARISON_BUILDS.each do |build_name|
puts build_name
# add --dry-run to test
system("gh pr create --title 'Compare #{build_name} against vanilla Rails' --body 'Compare #{build_name} against vanilla Rails' --base main --head #{build_name}")
class Main
class << self
def main(dry_run:)
Dir.chdir(ComparisonConfig.comparison_repo_root_path) do
ComparisonConfig.comparison_builds.each do |build_name|
Terminal.puts_header("Creating PR for #{build_name}")
cmd = "gh pr create --title 'Compare #{build_name} against vanilla Rails' --body 'Compare #{build_name} against vanilla Rails' --base main --head #{build_name} #{dry_run ? "--dry-run" : ""}"
system(cmd)
end
end
end
end
end

main
Main.main(dry_run: ARGV.include?("--dry-run"))
2 changes: 1 addition & 1 deletion bin/lib/config.rb → bin/lib/build_config.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class Config
class BuildConfig
PROJECT_ROOT_PATH = File.absolute_path(File.join(__dir__, "../.."))
CI_CONFIGS_PATH = File.join(PROJECT_ROOT_PATH, "ci/configs")
BUILD_PATH = File.join(PROJECT_ROOT_PATH, "tmp/builds")
Expand Down
46 changes: 24 additions & 22 deletions bin/lib/builder.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
##
# Invokes the template as a user would, not as CI does via the build-and-test script.
# Automatically removes old DB before generating the app if required
#
require "rubygems"

class Builder
def initialize(config:)
@config = config
@rails_cmd_version = build_rails_cmd_version(target_rails_major_minor: config.target_rails_major_minor)
end

def build
verify_rails_cmd_is_expected_version!

Dir.chdir(@config.build_path) do
delete_any_previous_build
drop_dbs_from_previous_build

# TODO: how to handle errors? raise? or log and continue? or rename the app dir with a .failed suffix?
# TODO: how to handle output? redirect to a file? or sep files for stdout and stderr?

if @config.vanilla?
Terminal.puts_header("Building vanilla Rails app")
system(build_vanilla_cmd_env, build_vanilla_cmd)
else
Terminal.puts_header("Building Rails app")
system(build_cmd_env, build_cmd)
end
end
Expand All @@ -29,20 +25,33 @@ def build

def base_cmd_parts
[
"rails new #{@config.app_name}",
"rails _#{@rails_cmd_version}_ new #{@config.app_name}",
"-d postgresql",
"--skip-javascript",
"--skip-kamal",
"--skip-solid"
]
end

def verify_rails_cmd_is_expected_version!
actual_rails_version = `rails -v`.strip.sub("Rails ", "")
def build_rails_cmd_version(target_rails_major_minor:)
specs = Gem::Specification.find_all_by_name("rails")

raise "No versions of gem '#{gem_name}' are installed" if specs.empty?

return if actual_rails_version.start_with?(@config.target_rails_major_minor)
version = specs
.map { _1.version.to_s }
.sort
.reverse
.find { |v| v.start_with?(target_rails_major_minor) }
test_cmd = "rails _#{version}_ -v"
expected_test_output = "Rails #{version}"
actual_test_output = `#{test_cmd}`.strip

raise "Expected Rails version #{@config.target_rails_major_minor}, but got #{actual_rails_version}"
raise "Command failed: #{test_cmd}. Actual: #{actual_test_output}" unless expected_test_output == actual_test_output

Terminal.puts_header("Using Rails version #{version}")

version
end

def delete_any_previous_build
Expand Down Expand Up @@ -84,17 +93,10 @@ def build_vanilla_cmd
base_cmd_parts.join(" ")
end

def print_separator
puts ""
puts "*" * 80
puts ""
end

def drop_dbs_from_previous_build
print_separator
Terminal.puts_header("Dropping databases from previous build")
system "psql -c 'DROP DATABASE IF EXISTS #{@config.app_name}_test;'"
system "psql -c 'DROP DATABASE IF EXISTS #{@config.app_name}_development;'"
system "psql -c 'DROP DATABASE IF EXISTS #{@config.app_name}_test;'"
print_separator
end
end
30 changes: 30 additions & 0 deletions bin/lib/comparison_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
class ComparisonConfig
PROJECT_ROOT_PATH = File.absolute_path(File.join(__dir__, "../.."))
BUILD_PATH = File.join(PROJECT_ROOT_PATH, "tmp/builds")

class << self
def build_path
BUILD_PATH
end

def comparison_repo_root_path
File.join(PROJECT_ROOT_PATH, "tmp/rails-template-variants-comparison")
end

def vanilla_build_name
all_builds.find { |build_name| build_name.start_with?("vanilla_") }
end

def vanilla_build_path
File.join(BUILD_PATH, vanilla_build_name)
end

def comparison_builds
all_builds - [vanilla_build_name]
end

def all_builds
Dir.children(BUILD_PATH)
end
end
end
12 changes: 12 additions & 0 deletions bin/lib/terminal.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class Terminal
class << self
def puts_header(title)
puts <<~EO_HEADER
#{title}
#{"=" * title.length}
EO_HEADER
end
end
end

0 comments on commit 82e3c7f

Please sign in to comment.