Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

RFC: Combine multiple RSpec repositories into a single one. #2509

@xaviershay

Description

@xaviershay

Summary

Combine rspec-core, rspec-mocks, rspec-expectations, rspec-support, rspec-dev (which would be mostly deprecated with this proposal), the rspec meta-gem, and possible rspec-rails into a single repository.

Motivation

Making cross-cutting changes to RSpec involves a complicated dance of PRs. Selected examples:

  • Upgrading rubocop involved multiple PRs, that all needed to be somewhat kept in sync as a result of changes/feedback, and are still pending a final rspec-dev sync. As well as been a pain at the time, this has caused confusion for a subsequent contribution.
  • Adding to rspec-support to fix a bug in (say) rspec-mocks requires a PR to support, a PR to mocks pointing at that branch to demonstrate that the support change works, merging the support PR, then redoing the mocks PR to point back at master. (e.g. Add specs demonstrating problem with verified doubles and keyword args. rspec-mocks#726)
  • Any of the rspec-dev tasks to "sync" configuration to all repos requires a PR for each repo.
  • complex and partially overlapping CI builds

It's also not always clear to issue reporters which project is appropriate for an issue. We shouldn't expect newcomers to know which sub-project an issue could be related to!

Approach

Issues

Given a motivation is to simplify issue reporting, we should migrate them all to the main rspec project (which current has issues disabled) using something like github-issues-import. We can use tags (mocks, etc...) to track what came from where, but for new issues they would be optional.

Inflight PRs

We should explicitly close or merge every open PR. This will include closing many stale PRs, that will need to be re-opened against the new monorepo. We can mitigate this with a notice period (i.e. "one month from now we're merging repos").

CI

I see two ways to set up CI:

  1. Run all the specs for each project on every CI. Conceptually the simplest, potential downside is runtime. Given a lot of build time is build setup (installing ruby, gems, etc...) I suspect this will work out fine.
  2. Add conditional build logic to identify which projects are likely affected based on file paths changed, and only run those. Speeds things up, but more complicated and not technically as thorough (though probably good enough).

This is where rspec-rails would be an interesting addition, because it has a test matrix with rails versions that isn't applicable to the other projects and would probably force us to option 2. I'm leaning towards keeping it out, at least to begin with. We can always incorporate it later!

For now we should benchmark option 1.

rspec-dev

We need to audit rspec-dev to see what things it does are still appropriate and how to best incorporate them into the monorepo. Given it's primarily used to "manage" multiple repos, my hope is it can be mostly deprecated. This will be investigated in the prototype suggested below.

Drawbacks and mitigations

  • Git history is harder to work with. We should keep around the old git projects for spelunking purposes.
  • Intermingled git logs. I'm not worried about this. Possibly consider it an upside, being able to see what was happening across the entire project.
  • Easy to accidentally add unwanted dependencies. Since the code is "there" this potentially makes it easier to accidentally introduce coupling between the various components. I figure we have enough history and discipline keeping them separate that this shouldn't be an issue in practice.
  • wrap up or manually transfer all hanging pull requests in Expectations/Mocks/Support/Core
  • align git version tags - they overlap, and we need to keep them in sync
  • CI limit of simultaneous jobs constraints our a bit tighter

Next steps

  • Feedback from other members of core team.
  • Create a new project to test this idea (rspec-monorepo), including setting up CI and incorporating rspec-dev.

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