Skip to content

Unify release scripts and automate version management across all packages #1876

@AbanoubGhadban

Description

@AbanoubGhadban

Summary

Currently, React on Rails has two separate release scripts with different workflows:

  • Root release script (/rakelib/release.rake): Releases react-on-rails gem, react-on-rails NPM, and react-on-rails-pro NPM
  • Pro release script (/react_on_rails_pro/rakelib/release.rake): Releases react_on_rails_pro gem and node-renderer NPM

This creates maintenance overhead and potential for version mismatches. We need a unified release script that handles all packages consistently.

Current State

Packages with separate versioning:

  • Core: react-on-rails (gem + NPM + react-on-rails-pro NPM) - Currently v16.1.1
  • Pro: react_on_rails_pro gem + node-renderer NPM - Currently v4.0.0

Version files that need updating (6 locations):

  1. /lib/react_on_rails/version.rb
  2. /packages/react-on-rails/package.json
  3. /packages/react-on-rails-pro/package.json (version + dependency)
  4. /react_on_rails_pro/lib/react_on_rails_pro/version.rb
  5. /react_on_rails_pro/package.json (node-renderer)
  6. /package.json (root workspace)

Dependency management:

  • react-on-rails-pro NPM depends on react-on-rails NPM
  • react_on_rails_pro gem depends on react_on_rails gem

Goals

Unified Versioning Strategy

Move to synchronized versioning where all packages share the same version number, simplifying the mental model for users and maintainers.

Single Release Script

Create one rake task at the root that:

  • ✅ Updates all 6 version files atomically
  • ✅ Updates dependency declarations with exact versions (no ^ or ~)
  • ✅ Supports both semver bump types (patch, minor, major) AND explicit versions
  • ✅ Publishes all packages together (NPM + RubyGems)
  • ✅ Handles both public packages (npmjs.org) and private packages (GitHub Packages)

Key Features to Preserve

  • Dry run mode for testing
  • Verdaccio support for local testing
  • Skip push option for testing git operations
  • Uncommitted changes validation
  • Automatic Gemfile.lock updates

Implementation Plan

  1. Rewrite /rakelib/release.rake with unified logic for all packages
  2. Update /react_on_rails_pro/rakelib/release.rake to deprecate and redirect to root
  3. Update /react_on_rails_pro/script/release to call root rake task
  4. Test thoroughly with dry runs before production use

Usage Examples

# Semver bump
rake release[patch]                           # Bump patch version
rake release[minor]                           # Bump minor version
rake release[major]                           # Bump major version

# Explicit version
rake release[17.0.0]                          # Set to specific version

# With options
rake release[patch,true]                      # Dry run
rake release[17.0.0,false,verdaccio]          # Test with Verdaccio
rake release[17.0.0,false,npm,skip_push]      # Skip git push

Benefits

  • ✅ Simplified release process - one command to release everything
  • ✅ Prevents version mismatches across packages
  • ✅ Reduces maintenance overhead
  • ✅ Clearer mental model for users (one version number to track)
  • ✅ Atomic version updates across all files
  • ✅ Consistent dependency pinning

Testing Strategy

  • Dry run mode to verify all file updates
  • Verdaccio testing for NPM packages
  • Local testing with skip_push option
  • Verification of all 6 version files + 2 dependency declarations

Additional Feature: Strict Version Validation

During implementation, we also added strict version validation to complement the unified release script. This ensures that users have the correct version configuration at runtime.

Problem

Users could misconfigure package.json (wrong versions, conflicting packages, semver wildcards) and only discover issues at runtime. Warnings were easily missed in server logs.

Solution

The application now validates configuration at boot time and raises clear, actionable errors for misconfigurations.

Validation Checks

The new validate_version_and_package_compatibility! method enforces:

  1. package.json exists - Ensures the file is present before checking versions
  2. Package compatibility - Detects conflicting installations:
    • Both react-on-rails and react-on-rails-pro packages installed
    • Pro gem installed but using base package
    • Pro package installed but Pro gem is missing
  3. Exact versions - Enforces exact version matching (no ^, ~, >, <, *)
  4. Version match - Ensures gem and npm package versions match exactly

Error Examples

Users now get clear, actionable error messages at boot:

**ERROR** ReactOnRails: Both 'react-on-rails' and 'react-on-rails-pro' packages are installed.

If you're using React on Rails Pro, only install the 'react-on-rails-pro' package.
The Pro package already includes all functionality from the base package.

Fix:
  1. Remove 'react-on-rails' from your package.json dependencies
  2. Run: yarn remove react-on-rails
  3. Keep only: react-on-rails-pro

Package.json location: /path/to/package.json
**ERROR** ReactOnRails: The 'react-on-rails' package version is not an exact version.

Detected: ^16.1.1
     Gem: 16.1.1

React on Rails requires exact version matching between the gem and npm package.
Do not use ^, ~, >, <, *, or other semver ranges.

Fix:
  Run: yarn add react-on-rails@16.1.1 --exact

Package.json location: /path/to/package.json

Implementation Details

  • Integrated into Rails engine initializer (config.after_initialize)
  • Runs once at application boot
  • Replaces deprecated log_if_gem_and_node_package_versions_differ method
  • Added comprehensive test coverage (53 tests)
  • Applied DRY principle with shared package_installed?(package_name) helper

Benefits

  • Fail-fast - Configuration errors caught immediately at boot
  • Clear guidance - Users know exactly what's wrong and how to fix it
  • Prevents runtime errors - No more version mismatch surprises
  • Better developer experience - Immediate feedback on configuration issues
  • Complements release script - Ensures installed versions match what was released

Files Changed

  • lib/react_on_rails/engine.rb - Added validation initializer
  • lib/react_on_rails/version_checker.rb - Core validation logic
  • spec/react_on_rails/version_checker_spec.rb - Test coverage
  • spec/react_on_rails/fixtures/ - New test fixtures for Pro package scenarios

See PR #1881 for full implementation details.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions