Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to 1.0 #5612

Closed
juanibiapina opened this issue Feb 27, 2018 · 29 comments
Closed

Bump to 1.0 #5612

juanibiapina opened this issue Feb 27, 2018 · 29 comments

Comments

@juanibiapina
Copy link

It's used in production by too many people.

@mikegee
Copy link
Contributor

mikegee commented Feb 27, 2018

I don't think anything substantial has changed since I asked. We're just hacking away, making Rubocop better one cop at a time.

@juanibiapina
Copy link
Author

I've updated from 0.52 to 0.53 and the defaults changed, breaking the build.

"I don't want us to release one new major release per month for trivial breaking changes"

That's what major releases are for. We're not going to run out of numbers. The release process is exactly the same.

@mikegee
Copy link
Contributor

mikegee commented Feb 27, 2018

I've updated from 0.52 to 0.53 and the defaults changed, breaking the build.

There was nothing special about 0.53. Every update to Rubocop breaks someone's build.

I don't think @bbatsov wants to increment the major version with every release. Let's help think about a solution to that.

@bbatsov
Copy link
Collaborator

bbatsov commented Mar 5, 2018

Unfortunately a lot of work remains before we can tag a 1.0 release. I know that everyone's eager to see one out there, but the version doesn't mean much if the necessary code quality is not there.

I've updated from 0.52 to 0.53 and the defaults changed, breaking the build.

Btw, changes to cops will never result in major version changes, because they are not tied to RuboCop's API. I guess they are the thing that's most annoying to end users, but I don't see those going away even after a 1.0 release. New cops always have some flaws that require significant rework/changes in later releases where more people have tried them in the real world, community style practices changes and evolve, etc.

@skatkov
Copy link

skatkov commented Mar 5, 2018

Unfortunately a lot of work remains before we can tag a 1.0 release.

@bbatsov is there any roadmap for 1.0 version? Anything I can read up and maybe help?

@deivid-rodriguez
Copy link
Contributor

Btw, changes to cops will never result in major version changes, because they are not tied to RuboCop's API. I guess they are the thing that's most annoying to end users, but I don't see those going away even after a 1.0 release. New cops always have some flaws that require significant rework/changes in later releases where more people have tried them in the real world, community style practices changes and evolve, etc.

I actually have a proposal regarding this that I think could alleviate these issues. Once 1.0 is released (whenever that happens, doesn't matter), new cops are introduced disabled by default. Only on major version bumps, disabled by default cops will be promoted to enabled by default. I think the problem is not about new cops having flaws, but about them being enabled in the default configuration and thus breaking people's builds just because of doing their job (finding offenses). Would this make any sense?

@juanibiapina
Copy link
Author

Semver is there to protect us. In practical terms, what we want to do is run bundle update and be certain everything will work. With that in mind, rubocop should consider what cops are enabled or disabled by default as part of the major version. This is not strictly an API change, but it's a behavior change.

A possible better overall approach would be to not have anything enabled by default. Perhaps add a command to generate the initial configuration file for a project, or provide several possible "default" configs in other repos with good defaults. The fact that rubocop includes the "community guidelines" as defaults is a big problem that ties this gem to the horrible guidelines of that other repo.

@Drenmi
Copy link
Collaborator

Drenmi commented Mar 6, 2018

Perhaps add a command to generate the initial configuration file for a project, or provide several possible "default" configs in other repos with good defaults.

I am working on a proposal for a presets feature, that can support different defaults for common frameworks (read Rails) with known false positives fixed through configuration.

The fact that rubocop includes the "community guidelines" as defaults is a big problem that ties this gem to the horrible guidelines of that other repo.

Well. It doesn't, and the fact that people think it does is a growing problem. RuboCop was originally made to enforce the style guide, but the style guide now represents only a small subset of all the default cops.

@juanibiapina
Copy link
Author

juanibiapina commented Mar 6, 2018

@Drenmi presets solve both problems and allow all cops to be disabled by default.

@deivid-rodriguez
Copy link
Contributor

@juanibiapina Note though that you can already do this via DisabledByDefault: true config. That will certainly reduce the number of breaking changes you get between releases because no new cops will be applied unless you explicitly enable them.

@juanibiapina
Copy link
Author

@deivid-rodriguez Thanks, and I've used this before. But the current situation still violates the principle of least astonishment.

@deivid-rodriguez
Copy link
Contributor

I disagree, mine was just a proposal for post 1.0. For now, I don't really feel surprised when rubocop 0.x breaks my build.

@jfelchner
Copy link
Contributor

@bbatsov do you have a roadmap or goals for the code quality you'd like to see?

@gilmoreorless
Copy link

I've just done a fairly sizeable RuboCop upgrade, and I'd like to share some thoughts on what could make the experience better for people. First of all though, thank you for putting in all the work over the years to keep this project going. 😃

This isn't intended to be a massive rant, or to criticise you for not doing exactly what I want. But I do have suggestions for areas that need improvement. My primary dev experience is in the JS community, but recently I've been working on a large legacy Rails app. I've noticed a stark difference in the state of linting tools for Ruby and JS code.

I think it would be good for RuboCop to emulate some of how the ESLint project is run, because it's been a lot easier to consistently upgrade.

There are 2 main things that ESLint does which would solve a lot of the RuboCop upgrade pains:

1. There is a defined subset of recommended-by-default rules

These are tuned to include most of the code smells that could possibly cause errors, but don't include most of the purely stylistic choices. Additionally, it's really easy to read the full rules list and work out what's enabled by default and what's not.

RuboCop, however, seems to enable almost everything by default, even though some of the cops can actually end up disagreeing with each other. Even running RuboCop on this repository shows hundreds of warnings. So how useful are the defaults if the tool that enforces them doesn't adhere to them?

It seems that @Drenmi's proposal for presets mentioned above would solve a lot of this pain.

2. Rules are only turned on by default in major releases

This is what allows users to upgrade minor versions of ESLint as much as they want without worrying if their build will suddenly fail due to new linting rules. This is pretty much what @deivid-rodriguez was suggesting above:

Once 1.0 is released (whenever that happens, doesn't matter), new cops are introduced disabled by default. Only on major version bumps, disabled by default cops will be promoted to enabled by default.

ESLint provides migration guides for every major version, telling users exactly what rules will now be enabled, or which rules have changed semantics. For example: https://eslint.org/docs/user-guide/migrating-to-4.0.0

As far as I can see for RuboCop, most PRs for new cops enable the cop by default. This is what causes most of the upgrade pain between RuboCop versions, where previously-valid code is suddenly marked as failing checks.

Btw, changes to cops will never result in major version changes, because they are not tied to RuboCop's API. I guess they are the thing that's most annoying to end users, but I don't see those going away even after a 1.0 release.

@bbatsov It worries me slightly that you think individual cops are not part of RuboCop's API. I'd guess that for most users, the cops and their configuration are the API. ESLint always distinguishes between breaking changes for users (those who just run the linting in their builds) and developers (those who are writing custom plugins).


I recognise that it's hard work running a open source library that is depended on by so many people. But it's precisely the fact that it's largely-depended on that makes this issue important.

Some quotes from elsewhere in this issue:

There was nothing special about 0.53. Every update to Rubocop breaks someone's build.

For now, I don't really feel surprised when rubocop 0.x breaks my build.

I don't think it's right that a library that has over 30 million downloads is widely accepted as breaking people's builds with every release.

@perlun
Copy link

perlun commented May 18, 2018

Very well written @gilmoreorless, couldn't agree with you more. Thanks for taking the time to write a very factual statement on why the current situation is problematic, focusing on what can we do to improve instead of merely stating things are bad - much appreciated.

I also think that "the cops and their default configuration are the API" is completely true. I wouldn't be concerned if new, potentially dangerous or breaking cops were introduced in new releases if they were disabled by default.

The reason I came to think about this today was a gem we're developing that is not pegged to a particular Rubocop version - we always try to use "latest released version", which can be a somewhat painful experience. Today, I did an unrelated change to the gem and the Travis builds started failing - because 0.56 introduces incompatible changes:

.rubocop.yml: Lint/EndAlignment has the wrong namespace - should be Layout
Error: The `Style/MethodMissing` cop has been split into `Style/MethodMissingSuper` and `Style/MissingRespondToMissing`.
(obsolete configuration found in .rubocop_todo.yml, please update it)

In my case, it's probably easy to fix because I can just re-run rubocop --auto-gen, but the cost of potentially 30 million users doing this is not insignificant.


I want to state a fact that has perhaps been overlooked in the discussion before, but first: I am perfectly aware of the fact that 0.x versions are allowed to include any breaking changes, per the SemVer semantics. That's not the question here, not at all. The question is more, as you suggest - should a 30 million downloads gem really be using a 0.x version number? To me, the answer is clearly "no". 1.0 does not mean "this product is now feature-complete" from the authors perspective, it more means "this product is ready to use for production". The way the SemVer spec puts it:

How do I know when to release 1.0.0?

If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you’re worrying a lot about backwards compatibility, you should probably already be 1.0.0.

The fact I wanted to state, which is perhaps obvious to everyone, but it still deserves to be mentioned: Nothing of it this will be simpler just because Rubocop goes to 1.0. It doesn't mean that some magic fairy will come and sparkle "backwards compatibility dust" on all PR:s and changes. Instead, it means that some of these things will be a lot harder - you have to think more on "can this change go into version 1.x or should it be a 2.0 feature" etc.

But, the strategies outlines by @gilmoreorless is a good step in helping out in that direction, so properly applied, they can really be useful.

(Personal note: I maintain a 100+-million download gem. The current version which we released some month ago has about 1 million downloads. Trust me when I say from personal experience that "I know this is hard" - a seemingly subtle, innocent change can have drastic consequences. There is really no workaround to this - large-scale software development, either in terms of "huge code base" or "huge number of users" is hard and will probably always be so. But the SemVer guidelines are helpful in providing a proper strategy for how to think about boring things like release management and the likes.)

@bbatsov
Copy link
Collaborator

bbatsov commented May 18, 2018

I'll be speaking about the future of RuboCop and this magical 1.0 release at a couple of conferences over the course of next few weeks. I've got a reasonably good idea for where I want us to get, but I don't really have the time to execute my vision myself.

I guess sharing a roadmap would help to channel efforts in the right direction, so I plan to do this soon.

I understand everyone's frustration, but people should also understand I'm doing what I can with the limited time I can allocate to the project.

@jfelchner
Copy link
Contributor

@bbatsov I think zero people are judging you for not doing this sooner. Rubocop is a huge project and it is surprisingly stable (breakages are typically intentional). A project of this magnitude requires more of a time commitment than almost anyone realizes. You also have a group of regular contributors that come back again and again. That speaks volumes to your management style.

As @perlun mentioned, going past 0.x is hard and requires biting off more responsibility. If you don't have that time, I don't think there's a single person that would say "I'd rather have no Rubocop than a Rubocop that stays on 0.x."

I would personally love to see a "Rubocop 1.0 Quest" issue that outlines exactly what you want with checkboxes next to them. We can link PRs to each item and get moving towards the goal.

@juanibiapina
Copy link
Author

It takes very little time to bump the version to 1.0 and release a new version right now, make a statement that the project starts using semantic versioning and add a a reminder to be careful to the contributing instructions.

@bbatsov
Copy link
Collaborator

bbatsov commented May 19, 2018

It takes very little effort to do it, but I don't really want to release 1.0 and some massive changes right afterwards, so I'd rather do them before hand. E.g. - remove all non-essential cops from the core (e.g. Rails, Performance, etc), cleanup and unify the config. This 1.0 probably won't be appreciated much if it quickly jumped to version 20. :-)

@juanibiapina
Copy link
Author

It's not about appreciation. It's actually better that it quickly jumps to 20 if those numbers are all meaningful.

So if these massive changes are actually difficult to migrate to, we'll have to lock our current versions to the latest 0.x release (and backward bug fixes still need to come out anyway). Instead, 1.0 should come now and you could do breaking changes as slow or fast as you want. Maybe just cramp it all in 2.0 like you want to do with 1.0, or do it properly, slowly.

@bbatsov
Copy link
Collaborator

bbatsov commented May 19, 2018

(and backward bug fixes still need to come out anyway)

Provided there's someone with time to backport bugfixes, that is. 😉 I understand how things are supposed to happen very well - I'm just skeptical this is going to be in the project's best interest down the road, as theory and practice often diverge (especially when you don't have much time to work on something). We've got some contributors who have been around for a while, but we don't have that many of them, and we should be careful how we use the time they can dedicate on the project.

@juanibiapina
Copy link
Author

Exactly. Hence, given that everyone has little spare time, it will probably take months to get this magical release out (if it ever works). The saner thing to do is to make 1.0 now and let it slowly grow version numbers as features are slowly added by contributors. One major feature per release, no breaking changes to current projects. No wasting everyone's time testing big releases.

Nothing else changes. Your roadmap continues, do whatever you want to do, but instead of bumping minors, just bump majors.

@bbatsov
Copy link
Collaborator

bbatsov commented May 19, 2018

Perhaps you're right. I'll ruminate on the subject, but generally I'm not opposed to the idea.

The fact that rubocop includes the "community guidelines" as defaults is a big problem that ties this gem to the horrible guidelines of that other repo.

I strong disagree with this point, though. The project was created with the sole goal of pushing for (some degree of) code style unity in the community, the fact that at some point we've made many cops configurable never changed the primary focus. RuboCop will never be decoupled from the "horrible" guidelines of the other repo.

@juanibiapina
Copy link
Author

Cool. Then I'm satisfied. Would you write down later the results of you ruminations here or should I just close it ?

@dirtyharrycallahan
Copy link

~~Romantic~ semantic versioning is not a silver bullet that will completely take away the pain (and benefits) of upgrades. There will always be new bugs, bug fixes that change behavior, and new features to leverage. Deciding to upgrade will always or at least should involve a careful review of change logs and documentation to make an informed decision about if and when to upgrade. Many large and successful projects, Python, Ruby, Rails, npm, ... don't follow semantic versioning. 1.0 means that there will be 2.0 and so on so if you do attempt semantic versioning then then you will have to consider multiple major versions, roadmaps, ... that will demand more time from the project leader who has already stated that time is a constraint.

@jfelchner
Copy link
Contributor

jfelchner commented May 20, 2018

@juanibiapina I appreciate your thoughts and obviously whatever @bbatsov thinks is correct here is what we'll do, but with all due respect, you are missing a big piece of experience on what the reality of maintaining a huge open source project like Rubocop is versus the theory of what should happen.

In fact, based on your Github history, you've not only never committed to Rubocop (and therefore don't understand the complexity of the code) but rarely contributed to an open source project at all. I'm not saying that as a slight, I'm just pointing out that it's easy to open an issue saying "Please do this." before fully understanding the ramifications of those decisions.

The saner thing to do is to make 1.0 now and let it slowly grow version numbers as features are slowly added by contributors.

"Saner" how exactly? If the only difference is that we're bumping majors instead of minors, how does that help anyone? In my opinion, "saner" would be to get Rubocop to a place where we don't have to bump majors much at all.

One major feature per release, no breaking changes to current projects.

You're acting like this has zero time cost. It does not.

No wasting everyone's time testing big releases.

Everyone still has to test big releases. Semver doesn't change that. Again, if we're simply switching from bumping minors to bumping majors, the only difference is added work for contributors/maintainers.

It seems your main point is that you want to know that your build isn't going to break when you upgrade. In that case, lock it to ~> 0.55.0 instead of ~> 1.0. You can explicitly change to ~> 0.56.0 whenever you'd like and test that release.

Nothing else changes. Your roadmap continues, do whatever you want to do, but instead of bumping minors, just bump majors.

Spoken like someone who has never Semver'ed a project before. 😉 There would be issues that arise when you release a minor version which actually breaks backwards compatibility. This requires more work on the maintainers part to straighten out (eg yanking versions which has its own problems).

Additionally, Rubocop is a large project with many moving pieces. Currently the time the contributors spend on development doesn't have to involve worrying much about whether their changes are backwards compatible. That changes post-1.0.

Those are just two examples. There are numerous other issues that will creep up.

Considering the solution to this issue is "Lock your version and purposefully bump it." which requires almost zero effort (even on CI), I'm not sure "Just go to 1.0 before we think it's ready." is a good plan.

I want 1.0 as much as anyone, but if @bbatsov has a plan with some major breaking changes, in my opinion, we should just hold off until it's ready.

@deivid-rodriguez
Copy link
Contributor

Not sure how much effort this could involve or whether this could actually make sense, but...

Some modified form of semantic versioning could start being followed while staying on the 0.x series, so we can get the best of both worlds:

  • Less surprises and easier upgrades for users.
  • More peaceful life for maintainers since the 0.x safeguard is kept to communicate everything 0.x communicates here: project still lacks some major refactorings & breaking changes so that maintainers feel confortable calling it 1.0, project lacks financing and contributors lack time so that they feel confortable committing to 1.0, and so on.

Something like:

  • 0.x for majors (breaking changes in cops, new cops being turned on by default).
  • 0.x.y for minors (new cops / features being introduced).
  • 0.x.y.z for patches (bug fixes).

Thoughts?

@juanibiapina
Copy link
Author

juanibiapina commented May 21, 2018

This has degenerated too much, so I'm closing it. Thanks for everyone who contributed arguments.

@bbatsov
Copy link
Collaborator

bbatsov commented Jun 9, 2018

For the sake of completeness - take a look at https://github.com/rubocop-hq/rubocop/milestone/4 and https://speakerdeck.com/bbatsov/all-about-rubocop-rubykaigi-2018?slide=157

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants