-
Notifications
You must be signed in to change notification settings - Fork 10
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
Update all Rubocop dependencies #124
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks very much for this @csutter 🎉 - It does look like we've fallen rather far behind. Further than I had realised. So it's great you've got the ball rolling on this 👍
I've been trying this out on some of our repos and it is flagging quite a lot of violations which is a bit of a pain and may make this a bit difficult to transition to. Some of these look good and autocorrectable (Style/StringConcatenation, Layout/EmptyLinesAroundAttributeAccessor) others seem like they might be a bit of a pain (Naming/VariableNumber, Lint/MissingSuper). I've put some details up about them below so I can share the impact with other GOV.UK devs.
A thing I noticed is that when we run rubocop in repos with minitest we're now seeing:
Tip: Based on detected gems, the following RuboCop extension libraries might be helpful:
* rubocop-minitest (http://github.com/rubocop-hq/rubocop-minitest)
You can opt out of this message by adding the following to your config (see https://docs.rubocop.org/rubocop/extensions.html#extension-suggestions for more options):
AllCops:
SuggestExtensions: false
I feel like we should set SuggestExtensions: false
in this gem as this bundles all our various conventions together. It seems a bit of an unhelpful message for consumers of this.
Analysis of rules that might be a pain and thoughts:
Naming/VariableNumber: Use normalcase for symbol numbers. (https://rubystyle.guide#snake-case-symbols-methods-vars-with-numbers)
This expects rescue_from GdsApi::ContentStore::ItemNotFound, with: :error_404
to be rescue_from GdsApi::ContentStore::ItemNotFound, with: :error404
- which is consistent with our approach to variable names with numbers but I don't think it's particularly liked. This seems the most controversial change (in Smart Answers it has > 200 offences) and suggests changing things like born_on_or_before_6_april_1935
to born_on_or_before_6april1935
which seem much less legible. I wonder if we're fighting against an unwritten GOV.UK convention following https://rubystyle.guide/#snake-case-symbols-methods-vars-with-numbers and should change to snake_case - simplest thing for now would be disable CheckMethodNames
and CheckSymbols
options for this so we could defer this conversation to be outside this PR.
Style/OptionalBooleanParameter: Use keyword arguments when defining method with boolean argument. (https://rubystyle.guide#boolean-keyword-arguments)
This expects def format_document_data(documents, data_category = "", with_image_url = false)
to be def format_document_data(documents, data_category = "", with_image_url: false)
- seems good to go in.
Lint/ConstantDefinitionInBlock: Do not define constants this way within a block. (https://rubystyle.guide#no-constant-definition-in-block)
This seems to be mostly when constants are defined in test files or classes. This is arguably a dubious practice where there are better Ruby approaches to do this so I think this is good to go in (but might cause some pain).
Lint/MissingSuper: Call super to initialize state of the parent class. (https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Lint/MissingSuper)
This seems to cause a pain for classes that are inherited without an initialize method (~100 offences in https://github.com/alphagov/content-publisher) - I'm not too sure if this is overstepping a linting mark here and will annoy people but my gut says it's good to include.
RSpec/StubbedMock: Prefer allow over expect when configuring a response. (https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/StubbedMock)
This disallows expect(x).to receive(y)
- this rule should be disabled for consistency with the disabling of RSpec/MessageSpies, otherwise I fear it'll be quite disruptive.
RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5] (https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers)
This limits the amount of let
definitions in a Spec. I think this should be disabled for consistency with [the convention of disabling arbitrary limits](RSpec/MultipleMemoizedHelpers: Example group has too many memoized helpers [6/5] (https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/RSpec/MultipleMemoizedHelpers)
Rails/LexicallyScopedActionFilter: update is not explicitly defined on the class. (https://rails.rubystyle.guide#lexically-scoped-action-filter)
This complains if filters are specified for actions that are defined in inherited actions. Will be a pain for a https://github.com/alphagov/whitehall but rule intent seems good so I think it's good to go in.
Gemspec/RequiredRubyVersion: required_ruby_version should be specified.
This complains if a gem doesn't specify a required_ruby_version
or when the .rubocop.yml
for a gem references a Ruby version greater than the one in the Gemfile. We (GOV.UK) often don't set a required_ruby_version (example) and often have .ruby-version
files that are newer Rubies than what the gem may work with. It strikes me here that GOV.UK isn't following Ruby versioning best practices for gems and this rule would help that so I think this rule would be good to keep, but would come with some pain of adoption.
CHANGELOG.md
Outdated
@@ -1,3 +1,14 @@ | |||
# 4.0.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be more conventional to flag this as "Unreleased" as per: https://github.com/alphagov/rubocop-govuk/pull/19/files#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4edR1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an aside it looks like we've had points of contention in the past regarding what deems an update to this project to be a major version bump: #54 so that might be something to leave to us to have an internal chat on. I think it probably counts as a major version though given the major bump of rubocop - we tend to prefix the breaking changes with "BREAKING: " - I guess the breaking ones we have are rubocop, rubocop-ast and rubocop-rspec?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair – my thought was that "this upgrade will be painful downstream", but from the point of view of this gem's API, it hasn't changed at all. Happy to defer that decision to release time!
spec.add_dependency "rubocop-rake", "0.5.1" | ||
spec.add_dependency "rubocop-rspec", "1.42.0" | ||
spec.add_dependency "rubocop-rspec", "~> 2.1.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your logic to apply this to > 1 ones makes sense to me. It wouldn't surprise me too much if we hit a problem and need to go back but it does seem better to go this direction so bug fixes don't need a new gem release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree, I can't imagine it would be too much of an issue. Rubocop versioning has this to say since their move past 1.0:
RuboCop is stable between major versions, both in terms of API and cop configuration. We aim the ease the maintenance of RuboCop extensions (by keeping the API stable) and the upgrades between RuboCop releases (by not enabling new cops and changing the configuration of existing cops). All big (breaking) changes are reserved for major releases.
And:
Bug-fix (point) releases (if any) address only serious bugs and never contain new features.
We already have NewCops: disable
in the default config, so any new rules between explicit releases of rubocop-govuk
should not impact apps when patch level releases come out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great stuff 👍 Yeah my concern lies from a recent memory that the version of rubocop-ast could cause a bit of a pain hopefully their release process will mean that no longer happens at patch versions.
- Update rubocop to 1.7.0 - Update rubocop-ast to 1.4.0 - Update rubocop-rails to 2.9.1 - Update rubocop-rspec to 2.1.0 - Make stable dependencies (>= 1.0) less strict on patch version - Disable `SuggestExtensions` to stop Rubocop suggesting additional extensions at runtime - Explicitly set target Ruby version to `>= 2.6` in gemspec - Downgrade local Ruby version to `2.6.6` to capture lowest supported Ruby version - Fix namespace change of `Capybara/FeatureMethods`
Thanks @csutter this looks good to me. I'll try chat to some other people about this over the next couple of days. It seems reasonable to me that we merge this and look at resolving our rule amends in a separate PR once merged, then you'll not get caught up in our policies. But I'll see if that concerns anyone else. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @csutter for pushing this and @kevindew for getting a handle on the consequences it will have around GOV.UK. We do seem to have a problem keeping up-to-date with mainstream RuboCop.
I don't think it's feasible for us to keep up-to-date with RuboCop on a regular basis. But neither do we want to miss out on specific new features. Perhaps a compromise here would be to switch to an "allowed list" approach, which would minimise future disruption. I think the most important thing about a styleguide is that it's consistent and stable.
Anyway, let's see if we can get this in. I've tested this with a bunch of apps: Email Alert Frontend, Email Alert API, Smart Answers, Whitehall, Content Publisher and Collections Publisher.
I've also tried to go through the huge CHANGELOG. Around half of the new Cops are either pending or disabled. The following are enabled, but appear to be benign (from my testing):
- Lint/DuplicateElsifCondition (not seen, makes sense)
- Style/HashAsLastArrayItem (not seen, autocorrectable)
- Lint/DuplicateRescueException (not seen, makes sense)
- Lint/FloatComparison (not seen, makes sense)
- Lint/TopLevelReturnWithArgument (not seen)
- Lint/EmptyConditionalBody (not seen, makes sense)
- Lint/OutOfRangeRegexpRef (not seen, makes sense)
- Style/RedundantSelfAssignment (not seen, makes sense)
- Layout/EmptyLineAfterMultilineCondition (not seen)
- Style/SoleNestedConditional (autocorrectable)
- Style/KeywordParametersOrder (autocorrectable)
- Lint/EmptyFile (not seen, makes sense)
- Lint/TrailingCommaInAttributeDeclaration (autocorrectable)
- Layout/BeginEndAlignment (not seen)
- Lint/IdentityComparison (autocorrectable)
- Lint/HashCompareByIdentity (not seen, makes sense)
- Style/ClassEqualityComparison (autocorrectable)
- Lint/RedundantSafeNavigation (not seen, makes sense)
- Lint/UselessTimes (not seen, makes sense)
I have seen the following, all of which seem good to go in:
- Style/OptionalBooleanParameter (lots of these, makes sense)
- Lint/ConstantDefinitionInBlock (seen a few, makes sense)
- Style/ExplicitBlockArgument (a few of these, autocorrectable)
- Style/GlobalStdStream (seen a few, makes sense)
- Lint/BinaryOperatorWithIdenticalOperands (seen in Smart Answers, makes sense)
- Lint/SelfAssignment (seen in Whitehall, makes sense)
- Lint/DuplicateRequire (seen in Whitehall, makes sense)
- Style/CaseLikeIf (lots of these, unsafe autocorrectable)
- Lint/UnreachableLoop (not seen, makes sense)
I'm less convinced about the following:
-
Style/CombinableLoops:
- Not seen, but seems pretty arbitrary. Could be buggy. Worth a try, I suppose.
-
Style/StringConcatenation:
- Lots of these, potentially less readable. Unsafe auto-correctable, so worth a try.
-
Lint/UselessMethodDefinition:
- Seen in Whitehall, and potentially buggy / less readable. Suggest we turn it off.
-
Lint/MissingSuper:
- Lots of these, and potentially buggy - this is what tests are for. Suggest we turn it off.
-
Style/SingleArgumentDig:
- Seen in one of the email apps, potentially less readable. Unsafe auto-correctable, so worth a try.
-
Style/HashLikeCase:
- Not seen, seems very arbitrary. Suggest we turn it off if it causes a problem.
-
RSpec/StubbedMock:
- Agree as Kev described.
-
Gemspec/RequiredRubyVersion:
- Agree as Kev described.
-
Naming/VariableNumber:
- Lots of these, and agree it has already reduced readability. Since it's not autocorrectable, it would be expensive to switch in any direction, apart from disabling the new options. I think the styleguide is too prescriptive here, since it assumes all number in identifiers have no meaning, which is incorrect. Suggest we turn it off entirely.
-
RSpec/MultipleMemoizedHelpers:
- Not seen, agree as Kev described.
-
Rails/LexicallyScopedActionFilter:
- Not seen - pretty sure this is already enabled.
I think it's valid for this PR to go in as-is, since we seem to be near agreement with the follow-up changes to config, and provided @kevindew is happy to do look at those.
@@ -1,5 +1,6 @@ | |||
AllCops: | |||
NewCops: disable | |||
SuggestExtensions: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kevindew so I noticed you saw the mintiest suggestion in some repos. I don't think we shouldn't be enabling this option here, instead it should be added to the local project rubocop config as it feels like project specific annoyance. Possible that projects (in and outside GOV.UK) use this gem and extension suggestions would indeed be helpful.
This also has a larger impact of silencing not just suggestions for minitest, but all extension suggestions. I feel that at the very least, we could limit it to that:
AllCops:
SuggestExtensions:
rubocop-minitest: false
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I see the problem this option faces us with is one of consistency rather than it being a project annoyance, where the suggestion encourages you to take an approach inconsistent with the direction of this project. rubocop-govuk acts as a batteries included tool with various extensions and configs bundled that you can choose, and across GOV.UK there is a favouring (and lots of work) into trying to keep apps consistent with this styleguide rather than deviating in their own directions. This suggestion seems to encourage an app to go in its own direction and to end up with some extensions provided by this gem and others at an app level which seems potentially harmful.
I wouldn't have qualms with extra extensions, that are useful, being a part of this gem - minitest seems reasonable given a few of our apps use it. But I think having rubocop-govuk suggest ones to install at a project level is a step away from consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, I also agree we should turn off suggestions: in addition to what @kevindew says, we're not acting on the ones we have, so it's not clear what the benefit of the suggestion is. We can always turn it on in future if we feel we've missed out on something in the majority of our repos.
Thanks @csutter for raising this! It's good to be moving to a stable releases of most of the dependencies. On the whole I think we should only disable cops for rules and styles we'd explicitly not like to add to our style guide, rather than rules that cause upgrading pain for our existing repositories. For example, the From reading the comments above, plus my own thoughts, we should only disable the following cops:
There was suggestion for disabling other following cops, but recommend we don't:
Also I think it would be good to break these changes into scoped commits. It'll provide a clear history and let us describe the reasoning for each change in the commit message. We could roughly scope them to following individual changes:
|
Thanks @theseanything - I think the most reasonable next step is to get this PR merged and then have a separate one for the rule changes. It seems like everyone is pretty happy with disabling Naming/VariableNumber and RSpec/MultipleMemoizedHelper which seems pretty straight forward. I'll plan to open a PR for those two. Sean's stats on Lint/UselessMethodDefinition and Lint/MissingSuper seem sufficient to justify that it's not as much of a pain to fix these as it might have seemed, can always disable later if they are buggy as feared. That leaves one, RSpec/StubbedMock, left. I think I might have misinterpreted this rule in my first assessment as I thought it disallowed |
I've opened #125 to disable the problematic rules. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the follow-up PR @kevindew! I'm going to add a couple of comments to that, as I still have concerns about "Lint/UselessMethodDefinition" and "Lint/MissingSuper", and more generally how we're going to apply this update so repos don't get left behind.
Any chance of releasing this, guys? |
Also, thanks for massively updating this project with newer rubocop config |
We've released it today. It's currently 4.0.0.pre.1 while we trial the rules in our project. Hopefully within a couple of weeks we should release the final release. Do feel free to use the pre-release and to feedback if you find any of the new cops painful. |
Unfortunately using the pessimistic operator (~>, also known as twiddle-waka) [1] for rubocop gem dependencies doesn't play nicely with Dependabot. When these are used Dependabot will update the gemspec to allow a range of gem versions. This is not ideal as it can mean that different installations of rubocop-govuk may have different linting rules (and for gem development there can be differences between local installs and CI systems). This change removes the ambiguous versioning and switches to the exact version being defined again, as things were before #124. The reason this was changed previously was to allow bug fixes to rubocop dependencies to be used without cutting a new gem. This benefit however seems to be offset by the frustrations of the PR's Dependabot opens being unsafe to merge directly. For reference, Dependabot has a number of versioning strategies [2], however when you have a pessimistic operator it seems to always end up expanding the range as far as I can tell [3]. [1]: https://thoughtbot.com/blog/rubys-pessimistic-operator [2]: https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates#versioning-strategy [3]: https://github.com/dependabot/dependabot-core/blob/dd1fba76003434639209627676febc595787ba7c/bundler/lib/dependabot/bundler/update_checker/requirements_updater.rb#L78-L80
A reasonably major change so I've bumped the major version number. Rubocop and a bunch of its sub-gems have passed 1.0 now, so their versioning should be more stable, so I've made the gemspec more lenient w.r.t. patch versions (I was going to be super ambitious and even include minor versions but reckoned you'd probably like to keep things relatively predictable).
I reckon some of the new cops may be undesirable so there may need to be further updates once a few apps update to this version.
TargetRubyVersion
settingCapybara/FeatureMethods