summaryrefslogtreecommitdiff
path: root/habitat
diff options
context:
space:
mode:
authorRobb Kidd <robb@thekidds.org>2019-10-01 17:21:09 -0400
committerChristopher A. Snapp <csnapp@chef.io>2020-07-13 10:19:45 -0600
commita555ea251f8f94df7093e87402187d3644aabdbe (patch)
treeb0d11c7c96031edc1fe0ba5336aa8a63f0b68c44 /habitat
parent04eac6a86e51d71cdbfbe163ebb70a887c1c9ddb (diff)
downloadchef-a555ea251f8f94df7093e87402187d3644aabdbe.tar.gz
refactor Linux hab plan based on lessons from Windows plan
Lots of things changing in here. Let's take them in a possibly weird order. * do_prepare() Move all the settng of build environment ..uh.. settings into the prepare function. Notable things: - GEM_HOME is set to a vendor directory under pkg_prefix so that all gem installs (regardless of bundle install or gem install) will be installed _there_. Expect to see all gems shipped with chef-client under this directory. - Multiple bundle config --local commands. These are executed in a subshell after changing directory to the CACHE_PATH so that the bundler configuration will be written out to a `.bundle/config` file there. bundle commands will be run from this location later, so these settings become effective for the duration of the build and obviate the need for a _bundle helper function. * pkg_bin_dirs=() Add the `vendor/bin` directory (remember, vendor/ is where gems get installed, so the binstubs created by the installation will appear here in vendor/bin/) to the PATH of this package's runtime environment because there are commands in there people sometimes want to run. They won't be fast and they might end up with conflicts with gems installed by the user or by downstream pacakges because they haven't been appbundled. * do_setup_environment() These are environment variables we'll want set to these defaults at runtime. - GEM_PATH gets this package's gem installation directory pushed onto it making the gems available at runtime regardless of whether bundle exec is used. - APPBUNDLER_ALLOW_RVM is a flag looked for by the binstubs generated by appbundler. Setting this to "true" has nothing to do with RVM and everything to do with asking the appbundled binstub to not wipe out the carefully constructed `GEM_PATH` from this package and any possible others that "publish" to the runtime environment that gems are available within. - SSL_CERT_FILE - trust the CA cert package from core, by default, but downstream packages can override this if they like with something custom. * do_build() Life is simpler in the build function now. Build environment is all setup, so here we: - bundle install to retrieve dependencies based on the Gemfile+.lock - run the rake install for the project which builds and installs the gems whose source are in this repo (chef, chef-bin, chef-config) - for any gem installed via a git reference, we change to the source directory and rake install it, too, to install it like any other gem This results in a clean collection of all the required gems installed like normal gems under "vendor/gems." With that directory on the GEM_PATH, we don't need to care about whether the gems were installed by path reference or via git. * do_install() OK. I fibbed about not needing to tell bundler anything else. For install, we're going to generate the appbundled binstubs that lockdown the versions of gems required by particular commands. appbundler uses the project's Gemfile+lock to determine those version, so for the install actions, we tell bundler via an environment variable that the Gemfile to work with is over in CACHE_PATH. Then we iterate over the names of gems we want appbundled binstubs for in this package. Those will land in pkg_prefix/bin/. Note: there's nothing to copy here during install because all the gem install actions were targeting pkg_prefix/vendor so what we would copy is here already. * do_after() Stuff to make the package smaller. - We don't need the cached .gem artifacts. - We don't need the cache of git repos retrieved by bundler (those gems are installed at this point like any other gem.) - We don't need to ship the gem API documentation. (I imagine we could change our minds about this later.) - We don't need the spec tests for all the gems ... except for our own chef gem which, for Reasons, we keep the spec suite around for post-build functional testing. * pkg_deps() Ruby comes with a version of bundler that works at the moment. We don't have to risk conflicts between the version of Ruby this package depends on and the version of Ruby core/bundler was built against. Signed-off-by: Robb Kidd <robb@thekidds.org> Signed-off-by: Christopher A. Snapp <csnapp@chef.io>
Diffstat (limited to 'habitat')
-rw-r--r--habitat/plan.sh137
1 files changed, 68 insertions, 69 deletions
diff --git a/habitat/plan.sh b/habitat/plan.sh
index 6e113e8a95..967cdd334e 100644
--- a/habitat/plan.sh
+++ b/habitat/plan.sh
@@ -1,10 +1,13 @@
-pkg_name=chef-infra-client
-pkg_origin=chef
+_chef_client_ruby="core/ruby27"
+pkg_name="chef-infra-client"
+pkg_origin="chef"
pkg_maintainer="The Chef Maintainers <humans@chef.io>"
pkg_description="The Chef Infra Client"
pkg_license=('Apache-2.0')
-pkg_bin_dirs=(bin)
-_chef_client_ruby="core/ruby27"
+pkg_bin_dirs=(
+ bin
+ vendor/bin
+)
pkg_build_deps=(
core/make
core/gcc
@@ -52,10 +55,34 @@ do_verify() {
return 0
}
+do_setup_environment() {
+ push_runtime_env GEM_PATH "${pkg_prefix}/vendor"
+
+ set_runtime_env APPBUNDLER_ALLOW_RVM "true" # prevent appbundler from clearing out the carefully constructed runtime GEM_PATH
+ set_runtime_env SSL_CERT_FILE "$(pkg_path_for cacerts)/ssl/cert.pem"
+ set_runtime_env LANG "en_US.UTF-8"
+ set_runtime_env LC_CTYPE "en_US.UTF-8"
+}
+
do_prepare() {
- export OPENSSL_LIB_DIR=$(pkg_path_for openssl)/lib
- export OPENSSL_INCLUDE_DIR=$(pkg_path_for openssl)/include
- export SSL_CERT_FILE=$(pkg_path_for cacerts)/ssl/cert.pem
+ export GEM_HOME="${pkg_prefix}/vendor"
+ export OPENSSL_LIB_DIR="$(pkg_path_for openssl)/lib"
+ export OPENSSL_INCLUDE_DIR="$(pkg_path_for openssl)/include"
+ export SSL_CERT_FILE="$(pkg_path_for cacerts)/ssl/cert.pem"
+ export CPPFLAGS="${CPPFLAGS} ${CFLAGS}"
+
+ ( cd "$CACHE_PATH"
+ bundle config --local build.nokogiri "--use-system-libraries \
+ --with-zlib-dir=$(pkg_path_for zlib) \
+ --with-xslt-dir=$(pkg_path_for libxslt) \
+ --with-xml2-include=$(pkg_path_for libxml2)/include/libxml2 \
+ --with-xml2-lib=$(pkg_path_for libxml2)/lib"
+ bundle config --local jobs "$(nproc)"
+ bundle config --local without server docgen maintenance pry travis integration ci chefstyle
+ bundle config --local shebang "$(pkg_path_for "$_chef_client_ruby")/bin/ruby"
+ bundle config --local retry 5
+ bundle config --local silence_root_warning 1
+ )
build_line "Setting link for /usr/bin/env to 'coreutils'"
if [ ! -f /usr/bin/env ]; then
@@ -64,58 +91,46 @@ do_prepare() {
}
do_build() {
- local _libxml2_dir
- local _libxslt_dir
- local _zlib_dir
- export CPPFLAGS
- export GEM_HOME
- export GEM_PATH
- export NOKOGIRI_CONFIG
-
- _libxml2_dir=$(pkg_path_for libxml2)
- _libxslt_dir=$(pkg_path_for libxslt)
- _zlib_dir=$(pkg_path_for zlib)
-
- CPPFLAGS="${CPPFLAGS} ${CFLAGS}"
- GEM_HOME=${pkg_prefix}/bundle
- GEM_PATH=${GEM_HOME}
- NOKOGIRI_CONFIG="--use-system-libraries \
- --with-zlib-dir=${_zlib_dir} \
- --with-xslt-dir=${_libxslt_dir} \
- --with-xml2-include=${_libxml2_dir}/include/libxml2 \
- --with-xml2-lib=${_libxml2_dir}/lib"
-
- build_line "Executing bundle install inside hab-cache path. ($CACHE_PATH/chef-config)"
- ( cd "$CACHE_PATH/chef-config" || exit_with "unable to enter hab-cache directory" 1
- bundle config --local build.nokogiri "${NOKOGIRI_CONFIG}"
- bundle config --local silence_root_warning 1
- _bundle_install "${pkg_prefix}/bundle"
+ ( cd "$CACHE_PATH" || exit_with "unable to enter hab-cache directory" 1
+ build_line "Installing gem dependencies ..."
+ bundle install
+ build_line "Installing this project's gems ..."
+ bundle exec rake install
+ for gem in $GEM_HOME/bundler/gems/*; do
+ ( cd $gem
+ build_line "Installing gems from git repos properly ..."
+ rake install
+ )
+ done
)
-
- build_line "Executing bundle install inside source path. ($SRC_PATH)"
- _bundle_install "${pkg_prefix}/bundle"
}
do_install() {
- build_line "Copying directories from source to pkg_prefix"
- mkdir -p "${pkg_prefix}/chef"
- for dir in bin chef-bin chef-config chef-utils lib chef.gemspec Gemfile Gemfile.lock; do
- cp -rv "${SRC_PATH}/${dir}" "${pkg_prefix}/chef/"
- done
-
- # If we generated them on install, bundler thinks our source is in $HAB_CACHE_SOURCE_PATH
- build_line "Generating binstubs with the correct path"
- ( cd "$pkg_prefix/chef" || exit_with "unable to enter pkg prefix directory" 1
- _bundle_install \
- "${pkg_prefix}/bundle" \
- --local \
- --quiet \
- --binstubs "${pkg_prefix}/bin"
+ ( cd "$pkg_prefix" || exit_with "unable to enter pkg prefix directory" 1
+ export BUNDLE_GEMFILE="${CACHE_PATH}/Gemfile"
+ build_line "** fixing binstub shebangs"
+ fix_interpreter "${pkg_prefix}/vendor/bin/*" "$_chef_client_ruby" bin/ruby
+ export BUNDLE_GEMFILE="${CACHE_PATH}/Gemfile"
+ for gem in chef-bin chef inspec-core-bin ohai; do
+ build_line "** generating binstubs for $gem with precise version pins"
+ appbundler $CACHE_PATH $pkg_prefix/bin $gem
+ done
)
+}
- build_line "Fixing bin/ruby and bin/env interpreters"
- fix_interpreter "${pkg_prefix}/bin/*" core/coreutils bin/env
- fix_interpreter "${pkg_prefix}/bin/*" "$_chef_client_ruby" bin/ruby
+do_after() {
+ build_line "Trimming the fat ..."
+
+ # We don't need the cache of downloaded .gem files ...
+ rm -r "$pkg_prefix/vendor/cache"
+ # ... or bundler's cache of git-ref'd gems
+ rm -r "$pkg_prefix/vendor/bundler"
+ # We don't need the gem docs.
+ rm -r "$pkg_prefix/vendor/doc"
+ # We don't need to ship the test suites for every gem dependency,
+ # only Chef's for package verification.
+ find "$pkg_prefix/vendor/gems" -name spec -type d | grep -v "chef-${pkg_version}" \
+ | while read spec_dir; do rm -r "$spec_dir"; done
}
do_end() {
@@ -128,19 +143,3 @@ do_end() {
do_strip() {
return 0
}
-
-# Helper function to wrap up some repetitive bundle install flags
-_bundle_install() {
- local path
- path="$1"
- shift
-
- bundle install ${*:-} \
- --jobs "$(nproc)" \
- --without development:test:docgen \
- --path "$path" \
- --shebang="$(pkg_path_for "$_chef_client_ruby")/bin/ruby" \
- --no-clean \
- --retry 5 \
- --standalone
-}