Skip to content

Commit

Permalink
Merge pull request #107 from chef/rishichawda/use-habitat-builds
Browse files Browse the repository at this point in the history
use habitat build instead of omnibus
  • Loading branch information
tpowell-progress authored Feb 3, 2025
2 parents 6a25382 + 6ee4d26 commit fd6e66c
Showing 1 changed file with 114 additions and 120 deletions.
234 changes: 114 additions & 120 deletions bin/appbundle-updater
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,43 @@ require "rubygems/package"
require "zlib"
require "tempfile"

# FIXME: move to helpers mixin

def windows?
@windows ||= RUBY_PLATFORM =~ /mswin|mingw|windows/
end

def chefdk
def habitat
if windows?
Pathname.new(File.join(ENV["SYSTEMDRIVE"], "opscode", ARGV[0]))
Pathname.new(File.join(ENV["SYSTEMDRIVE"], "hab", "pkgs"))
else
Pathname.new(File.join("/opt", ARGV[0]))
Pathname.new(File.join("/hab", "pkgs"))
end
end

# find the path to installed package in habitat package directory
# example, /hab/pkgs/{ARGV[0]}/{ARGV[1]}/x.x.x/xxxxxxxxxxxxxx
def pkg_path
pkg_path = habitat.join(ARGV[0], ARGV[1])
version = Dir.glob("#{pkg_path}/*").max
raise "No existing installation found for #{ARGV[0]}/#{ARGV[1]} in #{pkg_path}" if version.nil?

pkg_path = pkg_path.join(version)
build_no = Dir.glob("#{pkg_path}/*").max
raise "No existing installation found for #{ARGV[0]}/#{ARGV[1]}/#{version} in #{pkg_path}" if build_no.nil?

pkg_path.join(build_no)
end

def vendor_bin_dir
pkg_path.join("vendor", "bin")
end

def bin_dir
chefdk.join("embedded/bin")
pkg_path.join("bin")
end

def ruby_pkg
# NOTE: this is sort of a 'hacky' way maybe to find which ruby binary to use?
File.read("#{pkg_path}/DEPS").split("\n").find { |l| l.start_with?(%r{(core|chef)\/ruby}) }
end

ENV["PATH"] = ( [ bin_dir ] + ENV["PATH"].split(File::PATH_SEPARATOR) ).join(File::PATH_SEPARATOR)
Expand All @@ -50,7 +71,7 @@ ENV_KEYS = %w{

def run(cmd)
ENV_KEYS.each { |key| ENV["_YOLO_#{key}"] = ENV[key]; ENV.delete(key) }
ENV["PATH"] = bin_dir.to_s + File::PATH_SEPARATOR + ENV["_YOLO_PATH"]
ENV["PATH"] = habitat.join(ruby_pkg, "bin").to_s + File::PATH_SEPARATOR + ENV["_YOLO_PATH"]
puts " running: #{cmd}"
output = `#{cmd} 2>&1` # FIXME: bash/zsh-ism, will not work on csh
unless $?.exited? && $?.exitstatus == 0
Expand All @@ -66,7 +87,7 @@ TAR_LONGLINK = "././@LongLink".freeze

def install_package_dependencies
banner("Installing Packages")
case `#{bin_dir}/ohai platform_family` # rubocop: disable Lint/LiteralAsCondition
case `hab pkg exec #{ARGV[0]}/#{ARGV[1]} ohai platform_family` # rubocop: disable Lint/LiteralAsCondition
when /debian/
ENV["DEBIAN_FRONTEND"] = "noninteractive"
run("apt-get -y update")
Expand Down Expand Up @@ -118,7 +139,7 @@ def extract_tgz(file, destination = ".")
end
end

App = Struct.new(:name, :repo, :bundle_without, :install_commands, :gems) do
App = Struct.new(:name, :origin, :bundle_without, :install_commands, :gems) do
def initialize(*)
super
self.gems ||= {}
Expand All @@ -129,18 +150,18 @@ App = Struct.new(:name, :repo, :bundle_without, :install_commands, :gems) do
end
end

chef_install_command = "#{bin_dir.join("rake")} install:local"
chef_install_command = "#{vendor_bin_dir.join("rake")} install:local"

CHEFDK_APPS = [
HABITAT_PACKAGES = [
App.new(
"berkshelf",
"berkshelf/berkshelf",
"chef",
"docs changelog",
"#{bin_dir.join("rake")} install"
"#{vendor_bin_dir.join("rake")} install"
),
App.new(
"chef-infra-client",
"chef",
"chef/chef",
"server docgen maintenance pry integration ci chefstyle profile",
chef_install_command,
{
Expand All @@ -150,67 +171,40 @@ CHEFDK_APPS = [
"inspec-core-bin" => %w{development},
}
),
App.new(
"chef-dk",
"chef/chef-dk",
"development test",
"#{bin_dir.join("bundle")} install",
{
"chef" => %w{docgen chefstyle omnibus_package},
"foodcritic" => %w{development test},
"test-kitchen" => %w{changelog debug docs development},
"inspec" => %w{deploy tools maintenance integration},
"chef-run" => %w{changelog docs debug},
"chef-cli" => %w{changelog docs debug},
"berkshelf" => %w{changelog docs debug development},
"chef-bin" => %w{changelog},
"chef-apply" => %w{changelog},
"chef-vault" => %w{changelog},
"ohai" => %w{changelog},
"opscode-pushy-client" => %w{changelog},
"cookstyle" => %w{changelog},
}
),
App.new(
"chef-vault",
"chef/chef-vault",
"chef",
"development",
"#{bin_dir.join("rake")} install"
"#{vendor_bin_dir.join("rake")} install"
),
App.new(
"cookstyle",
"chef/cookstyle",
"chef",
"development debug docs",
"#{bin_dir.join("rake")} install"
),
App.new(
"foodcritic",
"foodcritic/foodcritic",
"development",
"#{bin_dir.join("rake")} install"
"#{vendor_bin_dir.join("rake")} install"
),
App.new(
"inspec",
"chef/inspec",
"chef",
"test integration tools maintenance deploy",
"#{bin_dir.join("rake")} install"
"#{vendor_bin_dir.join("rake")} install"
),
App.new(
"ohai",
"chef/ohai",
"chef",
"development docs debug",
"#{bin_dir.join("rake")} install"
"#{vendor_bin_dir.join("rake")} install"
),
App.new(
"test-kitchen",
"test-kitchen/test-kitchen",
"chef",
"changelog integration debug chefstyle docs",
"#{bin_dir.join("rake")} install"
"#{vendor_bin_dir.join("rake")} install"
),
].freeze

class Updater
attr_reader :app, :ref, :tarball, :repo, :gems, :install_commands
attr_reader :app, :ref, :tarball, :origin, :repo, :gems, :install_commands

def initialize(options)
@app = options[:app]
Expand All @@ -219,6 +213,7 @@ class Updater
@extra_bin_files = options[:extra_bin_files]
@binstubs_source = options[:binstubs_source]
@repo = options[:repo] || @app.repo
@origin = options[:origin] || @app.origin
@gems = @app.gems
@install_commands = @app.install_commands
end
Expand All @@ -228,101 +223,100 @@ class Updater
abort "#{$0} needs to be run as root user or with sudo"
end

banner("Cleaning #{app} checkout")
app_dir.rmtree if app_dir.directory?

top_dir = chefdk.join("embedded/apps")
unless File.exist?(top_dir)
banner("Creating #{top_dir} directory")
FileUtils.mkdir_p top_dir
end

install_package_dependencies

if tarball
# NOTE: THIS IS DELIBERATELY PURE RUBY USING NO NATIVE GEMS AND ONLY
# THE RUBY STDLIB BY DESIGN
git_url = "https://github.com/#{repo}/archive/#{ref}.tar.gz"
banner("Extracting #{app} from #{git_url}")
Dir.chdir(chefdk.join("embedded/apps")) do
Tempfile.open("appbundle-updater") do |tempfile|
tempfile.binmode
URI.open(git_url) do |uri|
tempfile.write(uri.read)
tmp_dir = Dir.mktmpdir
banner("Creating #{tmp_dir}/#{app.name} directory")
app_dir = File.join(tmp_dir, app.name.to_s)

begin
if tarball
# NOTE: THIS IS DELIBERATELY PURE RUBY USING NO NATIVE GEMS AND ONLY
# THE RUBY STDLIB BY DESIGN
git_url = "https://github.com/#{repo}/archive/#{ref}.tar.gz"
banner("Extracting #{app} from #{git_url}")
Dir.chdir(tmp_dir) do
Tempfile.open("appbundle-updater") do |tempfile|
tempfile.binmode
URI.open(git_url) do |uri|
tempfile.write(uri.read)
end
tempfile.close
extract_tgz(tempfile.path)
end
tempfile.close
extract_tgz(tempfile.path)
base = File.basename repo
FileUtils.mv Dir.glob("#{base}-*")[0], app.name.to_s
end
else
git_url = "https://github.com/#{repo}.git"
banner("Cloning #{app} from #{git_url}")
run("git clone #{git_url} #{app_dir}")

banner("Checking out #{app} to #{ref}")
Dir.chdir(app_dir) do
run("git checkout #{ref}")
end
base = File.basename repo
FileUtils.mv Dir.glob("#{base}-*")[0], "#{app.name}"
end
else
git_url = "https://github.com/#{repo}.git"
banner("Cloning #{app} from #{git_url}")
run("git clone #{git_url} #{app_dir}")

banner("Checking out #{app} to #{ref}")
banner("Installing dependencies")
Dir.chdir(app_dir) do
run("git checkout #{ref}")
cmd = "#{vendor_bin_dir.join("bundle")} install"
cmd += " --without #{app.bundle_without}" if app.bundle_without
ruby(cmd)
end
end

banner("Installing dependencies")
Dir.chdir(app_dir) do
cmd = "#{bin_dir.join("bundle")} install"
cmd += " --without #{app.bundle_without}" if app.bundle_without
ruby(cmd)
end

banner("Re-installing git-installed gems")
Dir.chdir(app_dir) do
ruby("post-bundle-install.rb #{chefdk}") if File.exist?("#{app_dir}/post-bundle-install.rb")
end

banner("Installing gem")
Dir.chdir(app_dir) do
Array(install_commands).each do |command|
ruby(command)
banner("Re-installing git-installed gems")
Dir.chdir(app_dir) do
ruby("post-bundle-install.rb #{bin_dir}") if File.exist?("#{app_dir}/post-bundle-install.rb")
end
end

banner("Updating appbundler binstubs for #{app}")
if gems.empty?
banner("Installing gem")
Dir.chdir(app_dir) do
cmd = "#{bin_dir.join("appbundler")} #{app_dir} #{chefdk.join("bin")}"
cmd += " --extra-bin-files #{@extra_bin_files}" if @extra_bin_files
cmd += " --binstubs-source #{@binstubs_source}" if @binstubs_source
ruby(cmd)
Array(install_commands).each do |command|
ruby(command)
end
end
else
gems.each do |gem_name, without|

banner("Updating appbundler binstubs for #{app}")
if gems.empty?
Dir.chdir(app_dir) do
cmd = "#{bin_dir.join("appbundler")} #{app_dir} #{chefdk.join("bin")} #{gem_name}"
cmd += " --without #{without.join(",")}" if without
cmd = "#{vendor_bin_dir.join("appbundler")} #{app_dir} #{bin_dir}"
cmd += " --extra-bin-files #{@extra_bin_files}" if @extra_bin_files
cmd += " --binstubs-source #{@binstubs_source}" if @binstubs_source
ruby(cmd)
end
else
gems.each do |gem_name, without|
Dir.chdir(app_dir) do
cmd = "#{vendor_bin_dir.join("appbundler")} #{app_dir} #{bin_dir} #{gem_name}"
cmd += " --without #{without.join(",")}" if without
cmd += " --extra-bin-files #{@extra_bin_files}" if @extra_bin_files
cmd += " --binstubs-source #{@binstubs_source}" if @binstubs_source
ruby(cmd)
end
end
end
end

banner("Finished!")
rescue => e
puts "aborting!!", e
else
banner("Finished!")
ensure
banner("Cleaning up #{app_dir}")
FileUtils.remove_entry app_dir
banner("Done.")
end
end

private

def app_dir
chefdk.join("embedded/apps/#{app}")
end

def banner(msg)
puts "-----> #{msg}"
end

def ruby(script)
ruby = bin_dir.join("ruby").to_s.tap { |p| p.concat(".exe") if windows? }

run([ruby, script].join(" "))
ruby_cmd = "hab pkg exec #{ruby_pkg} ruby"
run([ruby_cmd, script].join(" "))
end

end
Expand Down Expand Up @@ -356,15 +350,15 @@ class CLI
end
opts.separator("")
opts.separator("App names:")
CHEFDK_APPS.each { |a| opts.separator(" * #{a.name}") }
HABITAT_PACKAGES.each { |a| opts.separator(" * #{a.name}") }
end
@parser.parse!
validate!
end

def validate!
die("PROJECT APP_NAME GIT_REF options are all required") if ARGV.length < 3
options[:app] = CHEFDK_APPS.find { |a| a.name == ARGV[1] }
options[:app] = HABITAT_PACKAGES.find { |a| a.name == ARGV[1] }
die("Invalid APP_NAME: #{ARGV[1]}") if options[:app].nil?
options[:ref] = ARGV[2]
end
Expand Down

0 comments on commit fd6e66c

Please sign in to comment.