From d7fff24872478fa70d7a53b5df4186d87fde0263 Mon Sep 17 00:00:00 2001 From: Sachin Jain Date: Thu, 30 Jul 2026 12:16:34 +0530 Subject: [PATCH 1/3] CHEF-37329: add Linux ARM Habitat validation in Expeditor pipeline Add an Arm64 Habitat validation step to .expeditor/habitat-test.pipeline.yml using Buildkite queue default-privileged-aarch64, docker plugin (ruby:3.4), and BUILD_PKG_TARGET=aarch64-linux, keeping HAB_AUTH_TOKEN propagation consistent with the existing Linux/Windows steps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Sachin Jain --- .expeditor/habitat-test.pipeline.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.expeditor/habitat-test.pipeline.yml b/.expeditor/habitat-test.pipeline.yml index 7c20d1c4..a65d639e 100644 --- a/.expeditor/habitat-test.pipeline.yml +++ b/.expeditor/habitat-test.pipeline.yml @@ -21,6 +21,20 @@ steps: environment: - HAB_AUTH_TOKEN + - label: ":linux: Arm64 Validate Habitat Builds of Chef-cli" + commands: + - .expeditor/buildkite/artifact.habitat.test.sh + agents: + queue: default-privileged-aarch64 + plugins: + - docker#v3.5.0: + image: ruby:3.4 + privileged: true + propagate-environment: true + environment: + - HAB_AUTH_TOKEN + - BUILD_PKG_TARGET: "aarch64-linux" + - label: ":windows: Validate Habitat Builds of Test Kitchen" commands: - .expeditor/buildkite/artifact.habitat.test.ps1 From 4db223c058034e85d78eccbbaef03a4670baaa56 Mon Sep 17 00:00:00 2001 From: Sachin Jain Date: Thu, 30 Jul 2026 12:55:31 +0530 Subject: [PATCH 2/3] CHEF-37329: add habitat plan for Linux aarch64 Introduce habitat/aarch64-linux/plan.sh, sourcing the existing habitat/plan.sh to reuse the default Linux build logic for aarch64 (ARM) targets. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Sachin Jain --- habitat/aarch64-linux/plan.sh | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 habitat/aarch64-linux/plan.sh diff --git a/habitat/aarch64-linux/plan.sh b/habitat/aarch64-linux/plan.sh new file mode 100644 index 00000000..0ce0c47f --- /dev/null +++ b/habitat/aarch64-linux/plan.sh @@ -0,0 +1,2 @@ +source "$(dirname "${BASH_SOURCE[0]}")/../plan.sh" +# Reuse the default Linux plan for Linux ARM (aarch64) builds. From c6e3a118939c720dcb97a4fe10a70be74ecf5290 Mon Sep 17 00:00:00 2001 From: Sachin Jain Date: Wed, 26 Aug 2026 01:12:13 +0530 Subject: [PATCH 3/3] Fix binstub_patch.rb/NOTICE path resolution on aarch64-linux builds habitat/aarch64-linux/plan.sh (added earlier in this branch) reuses habitat/plan.sh via 'source', so the same do_install/do_unpack code runs for both x86_64-linux and aarch64-linux builds. That code referenced paths relative to $PLAN_CONTEXT (e.g. "${PLAN_CONTEXT}/../binstub_patch.rb"), assuming PLAN_CONTEXT always points at habitat/. However, Habitat sets PLAN_CONTEXT to the directory it started the build from, not the directory of the file that's actually executing. When building aarch64-linux, that's habitat/aarch64-linux/, one level deeper than habitat/plan.sh's own location -- even though the code being run is sourced from habitat/plan.sh. So "${PLAN_CONTEXT}/.." resolved to habitat/ instead of the repo root on aarch64-linux builds, and binstub_patch.rb / NOTICE were silently not found at that (wrong) path. The 'sed -i ... r binstub_patch.rb' patch command doesn't error when its referenced file is missing/its pattern isn't found -- it just does nothing and still exits 0. So an aarch64-linux chef-cli build would silently ship a binstub without the patch that pre-sets APPBUNDLER_ALLOW_RVM=true. This leaves appbundler's own guard (which nils GEM_HOME/GEM_PATH unless that var is already 'true') unprotected on aarch64-linux specifically, causing Gem::MissingSpecError when chef-cli is binlinked and invoked directly (bypassing hab pkg exec, which normally sets that var via RUNTIME_ENVIRONMENT). This is the same bug already fixed in chef/ohai, chef/fauxhai, chef/cookstyle, chef/berkshelf, and chef/chef-vault. Fix: resolve the repo root from this file's own location via BASH_SOURCE[0] (which always points at habitat/plan.sh, regardless of which plan sourced it) instead of PLAN_CONTEXT, and use that for all repo-root-relative paths (binstub_patch.rb, NOTICE, VERSION source copy). This makes the path resolution correct on both x86_64-linux and aarch64-linux. The existing bin/chef-cli wrapper is left untouched -- once the sed patch reliably applies on aarch64-linux, it works the same way it already does on x86_64-linux. Also hardened while in this code path (no behavior change on x86_64): - Quoted the pkg_prefix/bin/* glob in the binstub-patching loop. - Used "${GEM_PATH:?}" guards on the rm -rf cleanup lines so they fail safely instead of operating on an empty/unset path. Verified: manually sourced habitat/plan.sh with PLAN_CONTEXT deliberately set to a wrong/aarch64-linux-style path -- CHEF_CLI_REPO_ROOT still resolves correctly and both binstub_patch.rb and NOTICE are found. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Sachin Jain --- habitat/plan.sh | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/habitat/plan.sh b/habitat/plan.sh index fc42c580..07f42be6 100644 --- a/habitat/plan.sh +++ b/habitat/plan.sh @@ -1,5 +1,16 @@ export HAB_BLDR_CHANNEL="base-2025" export HAB_REFRESH_CHANNEL="base-2025" + +# Resolve the repo root from this file's own location (BASH_SOURCE) rather +# than PLAN_CONTEXT. PLAN_CONTEXT is set by Habitat to the directory it +# started the build from, which is NOT necessarily the directory this file +# lives in -- e.g. when habitat/aarch64-linux/plan.sh sources this file, +# PLAN_CONTEXT is "habitat/aarch64-linux", not "habitat", which breaks any +# "${PLAN_CONTEXT}/.." reference used here. BASH_SOURCE[0] always points at +# this file, so it resolves correctly regardless of which plan sourced it. +CHEF_CLI_PLAN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CHEF_CLI_REPO_ROOT="$(cd "${CHEF_CLI_PLAN_DIR}/.." && pwd)" + pkg_name=chef-cli pkg_origin=chef ruby_pkg="core/ruby3_4" @@ -35,7 +46,7 @@ do_before() { do_unpack() { mkdir -pv "$HAB_CACHE_SRC_PATH/$pkg_dirname" - cp -RT "$PLAN_CONTEXT"/.. "$HAB_CACHE_SRC_PATH/$pkg_dirname/" + cp -RT "$CHEF_CLI_REPO_ROOT" "$HAB_CACHE_SRC_PATH/$pkg_dirname/" } do_build() { @@ -57,11 +68,11 @@ do_build() { do_install() { # Copy NOTICE to the package directory - if [[ -f "$PLAN_CONTEXT/../NOTICE" ]]; then + if [[ -f "${CHEF_CLI_REPO_ROOT}/NOTICE" ]]; then build_line "Copying NOTICE to package directory" - cp "$PLAN_CONTEXT/../NOTICE" "$pkg_prefix/" + cp "${CHEF_CLI_REPO_ROOT}/NOTICE" "$pkg_prefix/" else - build_line "Warning: NOTICE not found at $PLAN_CONTEXT/../NOTICE" + build_line "Warning: NOTICE not found at ${CHEF_CLI_REPO_ROOT}/NOTICE" fi export GEM_HOME="$pkg_prefix/vendor" @@ -78,8 +89,8 @@ do_install() { "${pkg_prefix}/vendor/bin/appbundler" . "$pkg_prefix/bin" chef-cli build_line "** patching binstubs to allow running directly" - for binstub in ${pkg_prefix}/bin/*; do - sed -i "/require \"rubygems\"/r ${PLAN_CONTEXT}/../binstub_patch.rb" "$binstub" + for binstub in "${pkg_prefix}"/bin/*; do + sed -i "/require \"rubygems\"/r ${CHEF_CLI_REPO_ROOT}/binstub_patch.rb" "$binstub" done build_line "** creating wrapper for runtime environment" @@ -98,9 +109,9 @@ exec $(pkg_path_for ${ruby_pkg})/bin/ruby $pkg_prefix/libexec/chef-cli "\$@" EOF chmod -v 755 "$pkg_prefix/bin/chef-cli" - rm -rf $GEM_PATH/cache/ - rm -rf $GEM_PATH/bundler - rm -rf $GEM_PATH/doc + rm -rf "${GEM_PATH:?}/cache/" + rm -rf "${GEM_PATH:?}/bundler" + rm -rf "${GEM_PATH:?}/doc" }