Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 187 additions & 63 deletions .expeditor/build_gems.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,47 +11,27 @@

$ErrorActionPreference = "Stop"

Write-Output "Are my Hab environment variables set correctly?"
if ([string]::IsNullOrEmpty($env:HAB_AUTH_TOKEN)){
Write-Output ( "=" * 80 )
Write-Error "HAB_AUTH_TOKEN is not set! Please set it before running this script."
Write-Output ( "=" * 80 )
exit 1
}
else {
Write-Output "HAB_AUTH_TOKEN is set correctly."
}

Write-Output "--- :ruby: Removing existing Ruby instances"

$rubies = Get-ChildItem -Path "C:\ruby*"
foreach ($ruby in $rubies){
Remove-Item -LiteralPath $ruby.FullName -Recurse -Force -ErrorAction SilentlyContinue
}

Write-Output "`r"

# Need to set this variable to keep the build from failing while trying to resolve nonsense sdk paths
$env:MSBuildEnableWorkloadResolver = "false"

Write-Output "--- :screwdriver: Installing Habitat via Github"
try {
[Version]$hab_version = (hab --version).split(" ")[1].split("/")[0]
if ($hab_version -lt [Version]"0.85.0" ) {
Write-Host "--- :habicat: Installing the version of Habitat required"
Set-ExecutionPolicy Bypass -Scope Process -Force
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.ps1'))
if (-not $?) { throw "Hab version is older than 0.85 and could not update it." }
} else {
Write-Host "--- :habicat: :thumbsup: Minimum required version of Habitat already installed"
}
}
catch {
# This install fails if Hab isn't on the path when we check for the version. This ensures it is installed
Write-Host "--- :habicat: Installing the version of Habitat required"
Set-ExecutionPolicy Bypass -Scope Process -Force
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.ps1'))
}
# setting the channel in this way gets access to the LTS channel and falls back to stable if the plan doesn't live there.
Write-Output "--- :shovel: Setting the BLDR and REFRESH Channels to LTS"
$env:HAB_BLDR_CHANNEL="base-2025"
$env:HAB_REFRESH_CHANNEL = "base-2025"
Write-Output "`r"

Write-Host "--- :screwdriver: Installing Habitat"
Set-ExecutionPolicy Bypass -Scope Process -Force
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/habitat-sh/habitat/main/components/hab/install.ps1'))
if (-not $?) { throw "unable to install Habitat"}
Write-Output "`r"

Write-Output "--- :screwdriver: Installing the latest Chef-Client"
Expand All @@ -63,28 +43,23 @@ Write-Output "--- :chopsticks: Refreshing the build environment to pick up Hab b
Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
refreshenv
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") + ";c:\opscode\chef\embedded\bin"
# We are being really aggressive about setting the bldr channel because some process keeps changing it to 'stable' which breaks our build
$env:HAB_BLDR_CHANNEL = "base-2025"
$env:HAB_ORIGIN = "chef"
$env:HAB_LICENSE = "accept-no-persist"
[System.Environment]::SetEnvironmentVariable("HAB_BLDR_CHANNEL", "base-2025", "Process")
Write-Output "`r"

Write-Output "--- :building_construction: Correcting a gem build problem, moving header files around"
$filename = "ansidecl.h"
$locale = Get-ChildItem -path c:\opscode -Include $filename -Recurse -ErrorAction Ignore
Write-Output "Copying ansidecl.h to the correct folder"
$parent_folder = $locale.Directory.Parent.FullName[1]
$child_folder = $parent_folder + "\x86_64-w64-mingw32\include"
Write-Output "`r"
Copy-Item $parent_folder -Destination $child_folder -ErrorAction Continue
Write-Output "`r"
# Write-Output "--- :building_construction: Correcting a gem build problem, moving header files around"
# $filename = "ansidecl.h"
# $locale = Get-ChildItem -path c:\opscode -Include $filename -Recurse -ErrorAction Ignore
# Write-Output "Copying ansidecl.h to the correct folder"
# $parent_folder = $locale.Directory.Parent.FullName[1]
# $child_folder = $parent_folder + "\x86_64-w64-mingw32\include"
# Write-Output "`r"
# Copy-Item $parent_folder -Destination $child_folder -ErrorAction Continue
# Write-Output "`r"

Write-Output "--- :construction: Setting up Habitat to build PowerShell DLL's"
$env:HAB_ORIGIN = "chef"
$env:HAB_LICENSE= "accept-no-persist"
$env:FORCE_FFI_YAJL="ext"
if (Test-Path -PathType leaf "/hab/cache/keys/core-*.sig.key") {
if (Test-Path -PathType leaf "/hab/cache/keys/$env:HAB_ORIGIN-*.sig.key") {
Write-Output "--- :key: Using existing fake '$env:HAB_ORIGIN' origin key"
} else {
Write-Output "--- :key: Generating fake '$env:HAB_ORIGIN' origin key"
Expand All @@ -100,8 +75,7 @@ Write-Output "`r"


Write-Output "--- :construction: Building 64-bit PowerShell DLLs"
$env:HAB_BLDR_CHANNEL = "base-2025"
hab pkg build habitat
hab pkg build habitat --refresh-channel base-2025
if (-not $?) { throw "unable to build"}
Write-Output "`r"

Expand All @@ -117,7 +91,7 @@ if (-not $?) { throw "unable to install this build"}
Write-Output "`r"

Write-Output "--- :hammer_and_wrench: Capturing the x64 installation path"
$x64 = hab pkg path chef/chef-powershell-shim
$x64 = hab pkg path $env:HAB_ORIGIN/chef-powershell-shim
Write-Output "Hab thinks it installed my 64-bit dlls here : $x64"
Test-Path -Path $x64
Write-Output "`r"
Expand Down Expand Up @@ -150,7 +124,11 @@ if (-not $?) { throw "unable to install this build"}
Write-Output "`r"

Write-Output "--- :bank: Installing Node via Choco"
choco install nodejs -y
# Use the LTS package (not the rolling "nodejs" package) to avoid picking up
# pre-release/alpha builds (e.g. 26.8.0-alpha.x), which cspell's engines check
# rejects with "Unsupported NodeJS version" even though it's technically newer
# than the minimum supported version.
choco install nodejs-lts -y
if (-not $?) { throw "unable to install Node"}
Write-Output "`r"

Expand Down Expand Up @@ -182,14 +160,14 @@ Write-Output "`r"

Write-Output "--- :building_construction: Setting up Environment Variables for Ruby and Chef PowerShell"
$temp = Get-Location
$gem_path = [string]$temp.path + "\vendor\bundle\ruby\3.1.0"
[Environment]::SetEnvironmentVariable("GEM_PATH", $gem_path)
[Environment]::SetEnvironmentVariable("GEM_ROOT", $gem_path)
[Environment]::SetEnvironmentVariable("BUNDLE_GEMFILE", "$($temp.path)\Gemfile")
Write-Output "--- :gem: Installing uri into the isolated vendor bundle"
New-Item -ItemType Directory -Force -Path $gem_path | Out-Null
gem install uri --install-dir $gem_path --no-document
if (-not $?) { throw "unable to install uri gem" }
Write-Output "`r"

Write-Output "--- :gem: Pre-installing uri gem into vendor bundle to bootstrap Bundler on Ruby 3.1"
$ruby_version = (ruby -e "puts RbConfig::CONFIG['ruby_version']").Trim()
$vendor_dir = "$($temp.path)\vendor\bundle\ruby\$ruby_version"
New-Item -ItemType Directory -Force -Path $vendor_dir | Out-Null
gem install uri --install-dir $vendor_dir --no-document
Write-Output "`r"

Write-Output "--- :put_litter_in_its_place: Removing any existing Chef PowerShell DLL's since they'll conflict with rspec"
Expand All @@ -203,14 +181,160 @@ if (Test-Path $($parent_folder + "\chef.powershell.dll")){
}
Write-Output "`r"

Write-Output "--- :building_construction: It looks like I need to install chef-client"
# as of this build, chef -client was not in base-2025 or stable so we grabbed this version directly
hab pkg install chef/chef-infra-client/18.8.50/20251022232751 --channel "chef-chef-chef-18-habitat-build"
Write-Output "`r"

Write-Output "--- :point_right: finally verifying the gem code (cookstyle, spellcheck, spec)"
bundle install
Write-Output "--- :point_right: finally verifying the gem code (chefstyle, spellcheck, spec)"
bundle update
bundle exec rake gem_check
if (-not $?) { throw "Bundle Gem failed"}

Write-Output "`r"

# There are ~100 released chef-infra-client patch versions per major line, so we
# resolve the newest one for a given major version at run time via the Habitat
# Depot API rather than hardcoding a patch version that will inevitably go stale.
# `hab pkg install chef/chef-infra-client/18` does not support a major-only partial
# version, so we need the fully qualified origin/name/version/release ident anyway.
function Get-LatestHabPackageIdent {
param(
[Parameter(Mandatory=$true)] [string]$Origin,
[Parameter(Mandatory=$true)] [string]$Name,
[Parameter(Mandatory=$true)] [string]$Channel,
[Parameter(Mandatory=$true)] [string]$MajorVersion
)

$matching_releases = @()
$range = 0
do {
$page = Invoke-RestMethod "https://bldr.habitat.sh/v1/depot/channels/$Origin/$Channel/pkgs/$Name`?range=$range"
$matching_releases += $page.data | Where-Object { $_.version -like "$MajorVersion.*" }
$range += $page.data.Count
} while ($page.data.Count -gt 0 -and $range -lt $page.total_count)

if ($matching_releases.Count -eq 0) {
throw "No $Origin/$Name releases matching version '$MajorVersion.*' found in the '$Channel' channel"
}

$latest = $matching_releases | Sort-Object { [version]$_.version }, release | Select-Object -Last 1
return "$($latest.origin)/$($latest.name)/$($latest.version)/$($latest.release)"
}

# Habitat's chef-infra-client vendors a full copy of chef-powershell (lib/, bin/, ext/,
# gemspec) under vendor\gems\chef-powershell-<version>, and its own Bundler-based startup
# activates THAT gemspec before our code ever runs. That means Gem.loaded_specs["chef-powershell"]
# -- which our own resolve_wrapper_dll/resolve_core_wrapper_dll check first -- always points at
# the stale vendored copy, no matter what RUBYOPT/$LOAD_PATH tricks are used to shadow `require`.
# So instead of shadowing, we replace the vendored copy in place with this branch's code and
# freshly built DLLs, which is also a more faithful test of what a real Chef release will do.
function Set-VendoredChefPowerShellGem {
param(
[Parameter(Mandatory=$true)] [string]$ChefPkgIdent,
[Parameter(Mandatory=$true)] [string]$FreshDllBin
)

$chef_pkg_path = hab pkg path $ChefPkgIdent
$vendored_dir = Get-ChildItem "$chef_pkg_path\vendor\gems" -Filter "chef-powershell-*" -Directory -ErrorAction SilentlyContinue | Select-Object -First 1
if (-not $vendored_dir) { throw "Could not find a vendored chef-powershell gem under $chef_pkg_path\vendor\gems" }

Write-Output "Replacing vendored chef-powershell at $($vendored_dir.FullName) with this branch's code + DLLs"
Remove-Item "$($vendored_dir.FullName)\lib" -Recurse -Force
Copy-Item "$project_root\chef-powershell\lib" "$($vendored_dir.FullName)\lib" -Recurse -Force
Copy-Item "$project_root\chef-powershell\chef-powershell.gemspec" "$($vendored_dir.FullName)\chef-powershell.gemspec" -Force

$vendored_dll_dir = "$($vendored_dir.FullName)\bin\ruby_bin_folder\$arch"
Remove-Item $vendored_dll_dir -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $vendored_dll_dir | Out-Null
Copy-Item "$FreshDllBin\*" -Destination $vendored_dll_dir -Recurse -Force
}

function Invoke-ChefPowerShellIntegrationTest {
param(
[Parameter(Mandatory=$true)] [string]$Label,
[Parameter(Mandatory=$true)] [scriptblock]$Invocation,
[string]$ChefPowerShellBin
)

Write-Output "--- :test_tube: $Label"
$original_chef_bin = $env:CHEF_POWERSHELL_BIN
try {
if ($ChefPowerShellBin) { $env:CHEF_POWERSHELL_BIN = $ChefPowerShellBin } else { Remove-Item Env:\CHEF_POWERSHELL_BIN -ErrorAction SilentlyContinue }
& $Invocation
if (-not $?) { throw "$Label failed" }
}
finally {
if ($null -eq $original_chef_bin) { Remove-Item Env:\CHEF_POWERSHELL_BIN -ErrorAction SilentlyContinue } else { $env:CHEF_POWERSHELL_BIN = $original_chef_bin }
}
Write-Output "`r"
}

Write-Output "--- :mag: Determining which Chef version to integration-test against this Ruby"
$ruby_version = (ruby -e "puts RbConfig::CONFIG['ruby_version']").Trim()
Write-Output "System Ruby under test: $ruby_version"
Write-Output "`r"

$integration_test_script = "$project_root\chef-powershell\chef_gem_integration_test.rb"

if ($ruby_version.StartsWith("3.1")) {
# ---- Chef-18 ships as both Omnibus and Habitat: test it both ways ----

Write-Output "--- :gem: Building a local chef-powershell gem to replace Chef-18's bundled version"
Push-Location "$project_root\chef-powershell"
Remove-Item *.gem -ErrorAction SilentlyContinue
gem build chef-powershell.gemspec
if (-not $?) { throw "unable to build the chef-powershell gem" }
$built_gem = (Get-ChildItem *.gem | Select-Object -First 1).FullName
Pop-Location
Write-Output "`r"

Write-Output "--- :gem: Replacing the chef-powershell gem bundled in the Omnibus Chef-18 install"
# RubyGems activates the highest installed version on a plain `require`, not whichever gem
# was installed most recently -- a stale higher-numbered leftover would silently win over
# the one we just built. Remove every other installed version first.
$built_gem_version = [System.IO.Path]::GetFileNameWithoutExtension($built_gem) -replace "^chef-powershell-", ""
(& C:\opscode\chef\embedded\bin\gem.cmd list chef-powershell --local) | Select-String -Pattern "chef-powershell \((.+)\)" | ForEach-Object {
$_.Matches[0].Groups[1].Value -split ", " | Where-Object { $_ -ne $built_gem_version } | ForEach-Object {
Write-Output "Uninstalling stale chef-powershell $_"
& C:\opscode\chef\embedded\bin\gem.cmd uninstall chef-powershell -v $_ --force
}
}
& C:\opscode\chef\embedded\bin\gem.cmd install $built_gem --no-document
if (-not $?) { throw "unable to install local chef-powershell gem into Omnibus Chef-18" }
Write-Output "`r"

Invoke-ChefPowerShellIntegrationTest -Label "Chef-18 (Omnibus) integration test" -ChefPowerShellBin $x64_bin_path -Invocation {
& C:\opscode\chef\embedded\bin\ruby.exe $integration_test_script
}

Write-Output "--- :package: Installing Chef-18 (Habitat) for integration testing"
# chef/chef-infra-client is published to 'stable', not the 'base-2025' channel set above for our own package build
$chef18_ident = Get-LatestHabPackageIdent -Origin "chef" -Name "chef-infra-client" -Channel "stable" -MajorVersion "18"
Write-Output "Resolved latest Chef-18 Habitat package: $chef18_ident"
hab pkg install $chef18_ident --channel stable
if (-not $?) { throw "unable to install $chef18_ident" }
Write-Output "`r"

Set-VendoredChefPowerShellGem -ChefPkgIdent $chef18_ident -FreshDllBin $x64_bin_path

Invoke-ChefPowerShellIntegrationTest -Label "Chef-18 (Habitat) integration test" -Invocation {
hab pkg exec $chef18_ident ruby $integration_test_script
}
}
elseif ($ruby_version.StartsWith("3.4")) {
# ---- Chef-19 ships as Habitat only ----

Write-Output "--- :package: Installing Chef-19 (Habitat) for integration testing"
# chef/chef-infra-client is published to 'stable', not the 'base-2025' channel set above for our own package build
$chef19_ident = Get-LatestHabPackageIdent -Origin "chef" -Name "chef-infra-client" -Channel "stable" -MajorVersion "19"
Write-Output "Resolved latest Chef-19 Habitat package: $chef19_ident"
hab pkg install $chef19_ident --channel stable
if (-not $?) { throw "unable to install $chef19_ident" }
Write-Output "`r"

Set-VendoredChefPowerShellGem -ChefPkgIdent $chef19_ident -FreshDllBin $x64_bin_path

Invoke-ChefPowerShellIntegrationTest -Label "Chef-19 (Habitat) integration test" -Invocation {
hab pkg exec $chef19_ident ruby $integration_test_script
}
}
else {
throw "Unrecognized Ruby version '$ruby_version' - no Chef integration test mapping for it"
}
Write-Output "`r"
16 changes: 10 additions & 6 deletions .expeditor/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ release_branches:
- main:
version_constraint: 19.*
- 18-Stable:
version_constraint: 18.*
version_constraint: 18.*

subscriptions:
# These actions are taken, in order they are specified, anytime a Pull Request is merged.
Expand All @@ -53,9 +53,13 @@ subscriptions:
- "Expeditor: Skip Changelog"
- "Expeditor: Skip All"
- built_in:build_gem:
only_if: built_in:bump_version
only_if: built_in:bump_version
- trigger_pipeline:habitat/build:
ignore_labels:
- "Expeditor: Skip Habitat"
- "Expeditor: Skip All"

- workload: project_promoted:{{agent_id}}:*
actions:
- built_in:rollover_changelog
- built_in:publish_rubygems
# - workload: project_promoted:{{agent_id}}:*
# actions:
# - built_in:rollover_changelog
# - built_in:publish_rubygems
10 changes: 5 additions & 5 deletions .expeditor/manual_gem_release.ps1
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#########
## Purpose:
## This script is written as a manual process for building and publishing the chef-powershell gem.
## This script is written as manual process for bulding and publishing the chef-powershell gem.
## There is currently no process to build a gem on a Windows image.
##
## Assumptions:
## 1) You have access to https://rubygems.org/gems/chef-powershell
## 2) You have already had the changes to your build branch merged back to 18-Stable and you have updated your local 18-Stable branch - 18-Stable should match your local build branch
## 2) You have already had the changes to your build branch merged back to Main and you have updated your local main branch - Main should match your local build branch
## 3) This script will create a temp branch, check out to it, build the dll's and the gem locally and then will publish your gem to Rubygems.org
## 4) Clearly that will create some churn as we'd like to push to Artifactory internally until a given gem is stable. Not possible currently
## 5) You'll need to build and test your completed gem locally and then push directly to Rubygems for now.
Expand Down Expand Up @@ -64,7 +64,7 @@ if (Test-Path $hpath) {
}

Write-Output "--- Setting up Habitat to build PowerShell DLL's"
$env:HAB_ORIGIN = "chef"
$env:HAB_ORIGIN = "ci"
$env:HAB_LICENSE = "accept-no-persist"
$env:FORCE_FFI_YAJL = "ext"

Expand All @@ -78,7 +78,7 @@ else {
Write-Output "`r"

Write-Output "--- :construction: Building 64-bit PowerShell DLL's"
hab pkg build Habitat
hab pkg build habitat --refresh-channel base-2025
if (-not $?) { throw "unable to build" }
Write-Output "`r"

Expand All @@ -91,7 +91,7 @@ if (-not $?) { throw "unable to install this build" }
Write-Output "`r"

Write-Output "--- :hammer_and_wrench: Capturing the x64 installation path"
$x64 = hab pkg path chef/chef-powershell-shim
$x64 = hab pkg path ci/chef-powershell-shim
Write-Output "`r"

. results/last_build.ps1
Expand Down
Loading
Loading