gemchain

Cascade gem updates through interdependent gem ecosystems.

When you maintain multiple gems that depend on each other, releasing an update to one gem means testing and releasing every gem that depends on it. Gemchain automates this — it warns you before you release, and can cascade updates through the entire dependency chain.

Installation

gem install gemchain

Or add to your Gemfile:

gem "gemchain"

Usage

1. Create a config file

# cascade.yml
workspace: .
include: ask-*

Or specify gems explicitly:

# cascade.yml
workspace: .
gems:
  ask-core: ./ask-core
  ask-agent: ./ask-agent

2. Check your ecosystem

gemchain check

Shows every gem, its version, its dependencies, and how many gems depend on it.

3. Guard a release

gemchain guard ask-core
⚠  Pre-release Guard: ask-core v0.7.0

  7 gem(s) directly depend on ask-core:
    • ask-llm-providers (0.10.0) — requires: ask-core >= 0.1
    • ask-state-providers (0.3.0) — requires: ask-core >= 0.1
    ...

  Before releasing ask-core, make sure these gems still work:
    ⬜ ask-llm-providers (0.10.0)
    ⬜ ask-state-providers (0.3.0)
    ...

4. Cascade an update

gemchain update ask-core 0.8.0 --dry-run    # show the plan, change nothing
gemchain update ask-core 0.8.0 --test-only  # run dependents' suites, change nothing
gemchain update ask-core 0.8.0              # execute: bump, test, release in order
gemchain update ask-core 0.8.0 --yes        # skip per-release confirmations

Execution is end to end: if the source gem isn't already at the target version it is bumped, tested, and released first (dependents resolve the new version from RubyGems); then each dependent gets its constraint updated, tested, and released in topological order — commit, gem build, gem push, git tag, push. Every release asks for confirmation on stdin unless --yes is given. If a test suite fails, the cascade stops immediately and reports — nothing after the failure is touched.

If the source gem is already released at the target version (the common post-release flow — gemchain update ask-tools-shell 0.5.1 right after releasing it), only the dependents are processed.

gemchain link

Prints Gemfile content to add path: references for all workspace gems.

Configuration

cascade.yml options

Option Description
workspace Base directory for relative paths
include Glob pattern(s) for gem directories
exclude Glob pattern(s) to exclude
gems Explicit gem name → path mappings
bump Version bump level for dependent releases: patch, minor, or major (default patch)

How it works

  1. Discovers gems in your workspace (via glob patterns or explicit paths)
  2. Loads each gem's gemspec to build a dependency graph
  3. When you check or guard a gem, it shows all dependents
  4. When you cascade, the executor runs the plan in topological order:
    • Rewrite the version constraint in the dependent's gemspec
    • bundle install, bundle update <gem>, and bundle exec rake test
    • If tests pass: bump the dependent's version, commit, gem build, gem push, git tag, push
    • If tests fail: stop and report — nothing after the failure is touched

Development

git clone https://github.com/ask-rb/gemchain
cd gemchain
bundle install
bundle exec rake test

License

MIT