Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning,
and yes, platform and engine support are part of the public API.
Please file a bug if you notice a violation of semantic versioning.
Unreleased
Added
Changed
Deprecated
Removed
Fixed
Security
3.1.1 - 2026-06-06
- TAG: v3.1.1
- COVERAGE: 90.23% – 822/911 lines in 29 files
- BRANCH COVERAGE: 80.51% – 157/195 branches in 29 files
- 42.25% documented
Added
- Added the
pluginAppraisals DSL for generator-only companion gems that
should be loaded while Appraisal2 generates gemfiles without being serialized
into generated appraisal gemfiles. - Added the
generator_onlyroot Gemfile DSL for dependencies that Bundler
should install in the active generator bundle but Appraisal2 should not
serialize into generated appraisal gemfiles.
3.1.0 - 2026-06-06
- TAG: v3.1.0
- COVERAGE: 90.14% – 814/903 lines in 29 files
- BRANCH COVERAGE: 80.00% – 148/185 branches in 29 files
- 42.70% documented
Added
- Added Appraisal lifecycle hooks, including
Appraisal.transform_gemfile
for plugins that need to normalize generated Appraisal gemfiles in memory
before Appraisal2 writes them. - Added explicit
generate-installandgenerate-updateCLI commands for
workflows that need to regenerate Appraisal gemfiles before resolving them. - Added named appraisal support for
generate,generate-install, and
generate-update.
Changed
- Changed
installandupdateto resolve existing Appraisal gemfiles without
rewriting them, while still generating missing Appraisal gemfiles to preserve
the basic install workflow. -
Updated the deprecated
rake appraisal:installtask to delegate to
appraisal generate-install, preserving its historical generate-and-install
behavior. - Documented the Appraisal2 3.1.0 command lifecycle changes, named appraisal
generation commands, and generated gemfile transform hooks in the README.
3.0.9 - 2026-06-05
- TAG: v3.0.9
- COVERAGE: 89.69% – 748/834 lines in 28 files
- BRANCH COVERAGE: 80.61% – 133/165 branches in 28 files
- 42.69% documented
Changed
- Raised the
version_gemruntime dependency floor toversion_gem>= 1.1.10. - Updated local generated funding environment metadata to use the
appraisal-rbOpenCollective handle.
3.0.8 - 2026-06-05
- TAG: v3.0.8
- COVERAGE: 89.69% – 748/834 lines in 28 files
- BRANCH COVERAGE: 80.61% – 133/165 branches in 28 files
- 42.69% documented
Fixed
- Fixed generated project metadata and README links to use the
appraisal-rb
organization derived from the gemspec homepage instead ofpboling. - Fixed acceptance test Bundler pinning so CI uses
BUNDLER_VERSIONinstead of
RubyGems_version_selector arguments that stagedbin/bundlebinstubs do
not support.
3.0.7 - 2026-06-05
- TAG: v3.0.7
- COVERAGE: 89.69% – 748/834 lines in 28 files
- BRANCH COVERAGE: 80.61% – 133/165 branches in 28 files
- 42.69% documented
Added
- Added
Appraisal2::Version/Appraisal2::VERSIONconstants backed by
version_gem, including an RBS signature for the version namespace. - Added appraisal and CI coverage for runtime dependency HEADs, templating
self-tests, license scanning, Open Collective backer updates, and
per-engine/per-version Ruby workflows. - Added generated local-development support files, including
mise.toml,
.env.local.example, StructuredMerge git driver configuration, and refreshed
contributor/operator guides.
Changed
- Refreshed project automation and CI templates with the current
kettle-jem
template output. - CI now runs appraisals through
Appraisal.root.gemfile, installs each
appraisal with retry handling, and useskettle-testas the default test
runner. - Runtime dependency matrix handling now includes extracted stdlib gem
appraisals forerb,mutex_m, andstringio, with version-specific
stdlib gemfiles selected by the active Ruby version. - Development tooling floors were refreshed, including
kettle-dev2.x,
kettle-test2.x,kettle-soup-cover2.x,gitmoji-regex2.x, current
documentation gems, andturbo_tests2as the default test runner. - Gem metadata now uses the generated
licensesfield, GitHub source,
changelog, bug tracker, wiki, and funding URLs, and a generated version-gem
loader in the gemspec. - Documentation was refreshed for contributor setup, local environment
variables, appraisal maintenance, test execution, RuboCop Gradual, Reek, and
generated project automation.
Removed
- Removed the Ruby 2.3 CI appraisal/workflow and replaced dashed Ruby workflow
filenames with dotted Ruby-version workflow names. -
Removed the legacy CodeQL and Discord notifier workflows from the generated
workflow set. - Removed the stale duplicate Runtime Deps @ HEAD workflow that bypassed the
generateddep-headsappraisal workflow.
Fixed
-
Fixed local
kettle-testacceptance spec isolation so parallel workers use
process-specific Bundler, gem build, and stage directories instead of
deleting each other’s temporary workspaces. -
Rendered generated
LICENSE.mdcopyright notice lines as a Markdown list. - Fixed appraisal install commands so lockfiles with
BUNDLED WITHinstall and
select that Bundler version instead of rewriting the lockfile with the parent
process Bundler. - Fixed local acceptance test isolation so
kettle-testworkers do not mix
Bundler versions or share user-level installer cache state. - Fixed JRuby 9.2 CI bootstrapping by installing RubyGems 3.3.27 and Bundler
2.3.27 instead of using the default JRuby toolchain versions. - Fixed CI failures by preserving Bundler-generated
bin/bundletest binstubs
instead of replacing them with custom bundle wrappers. - Fixed Ruby 3.0 and 3.1 appraisal stdlib gemfiles so they do not load
conflictingerbversion constraints. - Fixed TruffleRuby 23.1 CI bootstrapping by routing that workflow through the
Ruby 3.2 appraisal Gemfile, which applies thejsonceiling only on
TruffleRuby 23.1, and by running the test command directly once that Gemfile
is active.
3.0.6 - 2026-02-17
- TAG: v3.0.6
- COVERAGE: 88.34% – 727/823 lines in 27 files
- BRANCH COVERAGE: 76.05% – 127/167 branches in 27 files
- 43.11% documented
Added
- Test for bundler handling with pre-existing appraisal lockfiles
- Added acceptance test that verifies appraisal correctly handles
gemfiles/*.gemfile.lockfiles withBUNDLED WITHspecified - Test validates that:
- Appraisal gemfiles with pre-created lockfiles install correctly
- Lockfiles preserve the
BUNDLED WITHsection reporting which bundler version was used - The bundler version in the lockfile is correctly maintained during installation
- Note: Multi-version bundler switching in CI would require pre-installing multiple bundler versions; coverage is limited to lockfile preservation and environment handling.
- Added acceptance test that verifies appraisal correctly handles
Fixed
- Restore bundler’s automatic version switching for modern bundler versions (2.2+)
- Bundler can detect and switch to the version specified in
Gemfile.lock(or appraisal lockfiles) viaBUNDLED WITH - Previously,
with_original_envstripped all bundler-related variables, preventing bundler from detecting version mismatches and breaking test isolation - Now uses
with_bundler_envwith selective cleanup:- Starts from
Bundler.original_envwhen available - Preserves critical bundler and isolation variables (for example:
BUNDLE_GEMFILE,BUNDLE_APP_CONFIG,BUNDLE_PATH,BUNDLE_USER_CACHE) - Removes
BUNDLER_SETUPandBUNDLER_VERSIONactivation markers - Removes
bundler/setupfromRUBYOPTto prevent auto-activation in subprocesses - Prevents
BUNDLE_LOCKFILElockfile pollution of subprocesses so per-gemfile lockfiles are created correctly
- Starts from
- This approach:
- Lets subprocess bundler start fresh and process the target gemfile cleanly
- Preserves test isolation and prevents global config pollution
- Enables committing appraisal lockfiles with specific bundler versions for stable, repeatable builds
- This fix maintains backward compatibility with all bundler versions
- Bundler can detect and switch to the version specified in
3.0.5 - 2026-02-14
- TAG: v3.0.5
- COVERAGE: 89.67% – 703/784 lines in 27 files
- BRANCH COVERAGE: 82.99% – 122/147 branches in 27 files
- 43.03% documented
Added
- Documentation of
BUNDLE_PATHfor caching gems
Fixed
- Restore support for
BUNDLE_PATHenvironment variable which regressed inv3.0.3-
BUNDLE_PATHis explicitly preserved to support CI environments that rely on it for gem caching.
-
3.0.4 - 2026-02-10
- TAG: v3.0.4
- COVERAGE: 89.67% – 703/784 lines in 27 files
- BRANCH COVERAGE: 83.45% – 121/145 branches in 27 files
- 43.03% documented
Changed
- Documentation cleanup
- Fixed typos in docs
3.0.3 - 2026-02-07
- TAG: v3.0.3
- COVERAGE: 89.67% – 703/784 lines in 27 files
- BRANCH COVERAGE: 83.45% – 121/145 branches in 27 files
- 43.03% documented
Added
- New CLI specs for testing named appraisal commands with options
- Shared RSpec contexts for mocking gem managers (
BundlerAdapterandOreAdapter) to facilitate faster unit testing
Changed
- Improved documentation for using
installandupdatecommands with named appraisals and options - Added examples showing correct command order:
appraisal <NAME> install --gem-manager=ore - Enhanced “Using Ore with Appraisal2” section with named appraisal examples
- Refactored
OreAdapterto use theAppraisal::Commandabstraction, unifying command execution across gem managers - Enhanced
Appraisal::Commandwith a:skip_bundle_execoption to support standalone executables likeore. When this option is enabled,Commandnow also skipsBundler.with_original_envwrapping andensure_bundler_is_availablechecks, avoiding unnecessary Bundler overhead. - Significantly optimized unit tests in
cli_spec.rbandappraisal_spec.rbby using gem manager mocks, reducing execution time from seconds to milliseconds
Fixed
- Removed
Dir.chdirintogemfiles/directory before runningorecommands. - Improved robustness of acceptance tests in isolated environments, especially on Ruby HEAD.
- Updated
setup_gem_path_for_local_installto correctly includeTMP_GEM_ROOTand more reliably detect the parent project’svendor/bundlegem directory. - Added a fallback to remote installation in
build_default_gemfileifbundle install --localfails, preventing test failures when dependencies are missing from the local cache.
- Updated
- Improved robustness against Bundler installation failures in CI, especially on Ruby HEAD.
-
Appraisal::Commandand acceptance tests now only attempt to install Bundler if no version is currently available, avoiding unnecessary and potentially failing version-specific installations. - Removed aggressive Bundler version matching and “downgrading” logic that stripped prerelease suffixes.
-
-
BREAKING BUG FIX: Fixed CLI to properly handle
installandupdatecommands when targeting a specific appraisal with options- Previously
appraisal <NAME> install --gem-manager=orewould incorrectly try to run the Unixinstallcommand - Now correctly invokes the appraisal install/update methods with proper option parsing
- Fixes error:
/usr/bin/install: unrecognized option '--gem-manager=ore'
- Previously
- Fixed argument parsing in CLI where repeated values could be mis-parsed as gem names instead of option values (e.g.,
appraisal <NAME> update ore -g ore). - Improved shell-escaping handling in
Appraisal::Commandand updated acceptance tests to match the more robust output - Standardized on
clean_name(underscores) for gemfile paths across the test suite for consistency
3.0.2 - 2026-02-06
- TAG: v3.0.2
- COVERAGE: 77.11% – 603/782 lines in 27 files
- BRANCH COVERAGE: 83.96% – 89/106 branches in 27 files
- 43.03% documented
Added
- funding documentation
- Ruby version compatibility badges for v1.8 - v2.2, v3.4, v4.0
- Appraisal & CI workflow for ruby v3.4
3.0.1 - 2026-02-06
- TAG: v3.0.1
- COVERAGE: 77.11% – 603/782 lines in 27 files
- BRANCH COVERAGE: 83.96% – 89/106 branches in 27 files
- 43.03% documented
Added
- Support for ore-light as an alternative gem manager via
--gem-manager=oreCLI option- New
GemManager::OreAdapterclass implementing ore-light integration - New
GemManager::BundlerAdapterclass (extracted from existing bundler logic) - New
GemManager::Factoryclass for creating gem manager adapters - New
GemManager::Baseabstract base class defining the gem manager interface - New
OreNotAvailableErrorandUnknownGemManagerErrorerror classes - Acceptance tests for ore install and update commands (tagged with
:oremetadata for conditional execution) - Unit tests for all gem manager adapter classes
- README documentation for ore usage, including installation, CLI options, and example workflows
- New
- New
-g/--gem-managerCLI option to select gem manager (bundler or ore) for install/update commands - New
Appraisal::Customize.reset!class method to reset customization state (useful for testing) - Improved test coverage from 66.7% to 76.4% line coverage, 61.5% to 77.4% branch coverage
- New unit tests for
BundlerDSLclass (including APPRAISAL_INDENTER variations) - New unit tests for
Commandclass - New unit tests for
Conditionalclass - New unit tests for
Sourceclass - New unit tests for
Gitclass - New unit tests for
Pathclass - New unit tests for
OrderedHashclass - New unit tests for
Dependencyclass - New unit tests for
Groupclass - New unit tests for
Platformclass - New unit tests for
GemManager::Factoryclass - New unit tests for error classes (
AppraisalsNotFound,OreNotAvailableError,UnknownGemManagerError) - Enhanced
DependencyListtests with edge cases - Enhanced
Gemfiletests with load/run/dup edge cases
- New unit tests for
- Added documentation on hostile takeover of RubyGems
- https://dev.to/galtzo/hostile-takeover-of-rubygems-my-thoughts-5hlo
- CLI configs for RuboCop, RubyGems, YARD, and JRuby (for local development only)
Changed
- Improved test isolation for acceptance tests to prevent modification of parent project’s Gemfile.lock
- Added
BUNDLE_APP_CONFIGisolation to prevent reading/writing parent’s.bundle/config - Added explicit
BUNDLE_GEMFILEprefix to all bundle commands in tests - Added
BUNDLE_LOCKFILEenvironment variable to explicitly control where lockfiles are written - Set
BUNDLE_IGNORE_FUNDING_REQUESTSandBUNDLE_DISABLE_SHARED_GEMSfor cleaner test output - Added
BUNDLE_USER_CACHEisolation to prevent polluting user’s gem cache - Fixed overly broad
Filestubs in unit tests that interfered with RSpec error formatting - Changed
bundle_without_spec.rbto useskip_forinstead ofpending_forto prevent test setup from running on unsupported Ruby versions (which was polluting the project Gemfile.lock with test gems)
- Added
- YARD CLI config switch from custom Kramdown support to yard-fence
Fixed
- Fixed
BundlerAdapter#installnot passinggemfile_pathtoCommand.new, which caused bundler to potentially write to the wrong Gemfile.lock whenBundler.with_original_envreset the environment - Fixed ore-light adapter path resolution: ore now runs from the gemfile’s directory so relative path dependencies resolve correctly (ore resolves paths relative to working directory, not gemfile location)
- Fixed Thor
invoke(:generate, [])call inupdatecommand to pass empty options hash, preventing argument leakage
Security
- Ore adapter now uses array-based command construction for
Kernel.systemcalls instead of string interpolation, preventing potential shell injection vulnerabilities
3.0.0 - 2025-07-28
- Initial release as a hard fork of appraisal v3.0.0.rc1 with many improvements - by @pboling
- support for
eval_gemfile - support for Ruby 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6 (all removed, or planned-to-be, in thoughtbot’s
appraisal)- NOTE: The setup-ruby GH Action only ships support for Ruby 2.3+, so older Rubies are no longer tested in CI. Compatibility is assumed thanks to
enforcing the syntax for the oldest supported Ruby, which is Ruby v1.8. File a bug if you find something broken.
- NOTE: The setup-ruby GH Action only ships support for Ruby 2.3+, so older Rubies are no longer tested in CI. Compatibility is assumed thanks to
- Support for JRuby 9.4+
- updated and improved documentation
- maintainability tracked with QLTY.sh and the reek gem
- code coverage tracked with Coveralls, QLTY.sh, and the kettle-soup-cover gem
- other minor fixes and improvements
- support for