Changelog

SemVer 2.0.0 Keep-A-Changelog 1.0.0

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 plugin Appraisals DSL for generator-only companion gems that
    should be loaded while Appraisal2 generates gemfiles without being serialized
    into generated appraisal gemfiles.
  • Added the generator_only root 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-install and generate-update CLI 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 install and update to resolve existing Appraisal gemfiles without
    rewriting them, while still generating missing Appraisal gemfiles to preserve
    the basic install workflow.
  • Updated the deprecated rake appraisal:install task 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_gem runtime dependency floor to version_gem >= 1.1.10.
  • Updated local generated funding environment metadata to use the
    appraisal-rb OpenCollective 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 of pboling.
  • Fixed acceptance test Bundler pinning so CI uses BUNDLER_VERSION instead of
    RubyGems _version_ selector arguments that staged bin/bundle binstubs 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::VERSION constants 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 uses kettle-test as the default test
    runner.
  • Runtime dependency matrix handling now includes extracted stdlib gem
    appraisals for erb, mutex_m, and stringio, with version-specific
    stdlib gemfiles selected by the active Ruby version.
  • Development tooling floors were refreshed, including kettle-dev 2.x,
    kettle-test 2.x, kettle-soup-cover 2.x, gitmoji-regex 2.x, current
    documentation gems, and turbo_tests2 as the default test runner.
  • Gem metadata now uses the generated licenses field, 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
    generated dep-heads appraisal workflow.

Fixed

  • Fixed local kettle-test acceptance 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.md copyright notice lines as a Markdown list.

  • Fixed appraisal install commands so lockfiles with BUNDLED WITH install and
    select that Bundler version instead of rewriting the lockfile with the parent
    process Bundler.
  • Fixed local acceptance test isolation so kettle-test workers 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/bundle test binstubs
    instead of replacing them with custom bundle wrappers.
  • Fixed Ruby 3.0 and 3.1 appraisal stdlib gemfiles so they do not load
    conflicting erb version constraints.
  • Fixed TruffleRuby 23.1 CI bootstrapping by routing that workflow through the
    Ruby 3.2 appraisal Gemfile, which applies the json ceiling 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.lock files with BUNDLED WITH specified
    • Test validates that:
      • Appraisal gemfiles with pre-created lockfiles install correctly
      • Lockfiles preserve the BUNDLED WITH section 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.

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) via BUNDLED WITH
    • Previously, with_original_env stripped all bundler-related variables, preventing bundler from detecting version mismatches and breaking test isolation
    • Now uses with_bundler_env with selective cleanup:
      • Starts from Bundler.original_env when available
      • Preserves critical bundler and isolation variables (for example: BUNDLE_GEMFILE, BUNDLE_APP_CONFIG, BUNDLE_PATH, BUNDLE_USER_CACHE)
      • Removes BUNDLER_SETUP and BUNDLER_VERSION activation markers
      • Removes bundler/setup from RUBYOPT to prevent auto-activation in subprocesses
      • Prevents BUNDLE_LOCKFILE lockfile pollution of subprocesses so per-gemfile lockfiles are created correctly
    • 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

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_PATH for caching gems

Fixed

  • Restore support for BUNDLE_PATH environment variable which regressed in v3.0.3
    • BUNDLE_PATH is 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 (BundlerAdapter and OreAdapter) to facilitate faster unit testing

Changed

  • Improved documentation for using install and update commands 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 OreAdapter to use the Appraisal::Command abstraction, unifying command execution across gem managers
  • Enhanced Appraisal::Command with a :skip_bundle_exec option to support standalone executables like ore. When this option is enabled, Command now also skips Bundler.with_original_env wrapping and ensure_bundler_is_available checks, avoiding unnecessary Bundler overhead.
  • Significantly optimized unit tests in cli_spec.rb and appraisal_spec.rb by using gem manager mocks, reducing execution time from seconds to milliseconds

Fixed

  • Removed Dir.chdir into gemfiles/ directory before running ore commands.
  • Improved robustness of acceptance tests in isolated environments, especially on Ruby HEAD.
    • Updated setup_gem_path_for_local_install to correctly include TMP_GEM_ROOT and more reliably detect the parent project’s vendor/bundle gem directory.
    • Added a fallback to remote installation in build_default_gemfile if bundle install --local fails, preventing test failures when dependencies are missing from the local cache.
  • Improved robustness against Bundler installation failures in CI, especially on Ruby HEAD.
    • Appraisal::Command and 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 install and update commands when targeting a specific appraisal with options
    • Previously appraisal <NAME> install --gem-manager=ore would incorrectly try to run the Unix install command
    • Now correctly invokes the appraisal install/update methods with proper option parsing
    • Fixes error: /usr/bin/install: unrecognized option '--gem-manager=ore'
  • 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::Command and 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=ore CLI option
    • New GemManager::OreAdapter class implementing ore-light integration
    • New GemManager::BundlerAdapter class (extracted from existing bundler logic)
    • New GemManager::Factory class for creating gem manager adapters
    • New GemManager::Base abstract base class defining the gem manager interface
    • New OreNotAvailableError and UnknownGemManagerError error classes
    • Acceptance tests for ore install and update commands (tagged with :ore metadata for conditional execution)
    • Unit tests for all gem manager adapter classes
    • README documentation for ore usage, including installation, CLI options, and example workflows
  • New -g / --gem-manager CLI 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 BundlerDSL class (including APPRAISAL_INDENTER variations)
    • New unit tests for Command class
    • New unit tests for Conditional class
    • New unit tests for Source class
    • New unit tests for Git class
    • New unit tests for Path class
    • New unit tests for OrderedHash class
    • New unit tests for Dependency class
    • New unit tests for Group class
    • New unit tests for Platform class
    • New unit tests for GemManager::Factory class
    • New unit tests for error classes (AppraisalsNotFound, OreNotAvailableError, UnknownGemManagerError)
    • Enhanced DependencyList tests with edge cases
    • Enhanced Gemfile tests with load/run/dup edge cases
  • 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_CONFIG isolation to prevent reading/writing parent’s .bundle/config
    • Added explicit BUNDLE_GEMFILE prefix to all bundle commands in tests
    • Added BUNDLE_LOCKFILE environment variable to explicitly control where lockfiles are written
    • Set BUNDLE_IGNORE_FUNDING_REQUESTS and BUNDLE_DISABLE_SHARED_GEMS for cleaner test output
    • Added BUNDLE_USER_CACHE isolation to prevent polluting user’s gem cache
    • Fixed overly broad File stubs in unit tests that interfered with RSpec error formatting
    • Changed bundle_without_spec.rb to use skip_for instead of pending_for to prevent test setup from running on unsupported Ruby versions (which was polluting the project Gemfile.lock with test gems)
  • YARD CLI config switch from custom Kramdown support to yard-fence

Fixed

  • Fixed BundlerAdapter#install not passing gemfile_path to Command.new, which caused bundler to potentially write to the wrong Gemfile.lock when Bundler.with_original_env reset 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 in update command to pass empty options hash, preventing argument leakage

Security

  • Ore adapter now uses array-based command construction for Kernel.system calls 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 Enforced Code Style Linter enforcing the syntax for the oldest supported Ruby, which is Ruby v1.8. File a bug if you find something broken.
    • 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