diff --git a/CODEOWNERS b/.github/CODEOWNERS similarity index 100% rename from CODEOWNERS rename to .github/CODEOWNERS diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..81eddf2f --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,42 @@ +name: build + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_call: + +permissions: + contents: read + +jobs: + build: + name: build + + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + runs-on: ${{ matrix.os }} + + steps: + - name: checkout + uses: actions/checkout@v4 + + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # pin@v1.245.0 + with: + bundler-cache: true + + - name: build + run: | + GEM_NAME=$(ls | grep gemspec | cut -d. -f1) + echo "Attempting to build gem $GEM_NAME..." + gem build $GEM_NAME + if [ $? -eq 0 ]; then + echo "Gem built successfully!" + else + echo "Gem build failed!" + exit 1 + fi diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 00000000..c4608942 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,26 @@ +name: lint + +on: + push: + branches: + - main + pull_request: + +permissions: + contents: read + +jobs: + lint: + name: lint + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@v4 + + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # pin@v1.245.0 + with: + bundler-cache: true + + - name: lint + run: script/lint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b7d189d3 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,64 @@ +name: release + +on: + workflow_dispatch: + push: + branches: + - main + paths: + - lib/version.rb + +permissions: + contents: write + packages: write + id-token: write + attestations: write + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@v4 + + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # pin@v1.245.0 + with: + bundler-cache: true + + - name: lint + run: script/lint + + - name: test + run: script/test + + - name: set GEM_NAME from gemspec + run: echo "GEM_NAME=$(ls | grep gemspec | cut -d. -f1)" >> $GITHUB_ENV + + # builds the gem and saves the version to GITHUB_ENV + - name: build + run: echo "GEM_VERSION=$(gem build ${{ env.GEM_NAME }}.gemspec 2>&1 | grep Version | cut -d':' -f 2 | tr -d " \t\n\r")" >> $GITHUB_ENV + + - uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # pin@v2 + with: + subject-path: "${{ env.GEM_NAME }}-${{ env.GEM_VERSION }}.gem" + + - name: publish to GitHub packages + run: | + export OWNER=$( echo ${{ github.repository }} | cut -d "/" -f 1 ) + GEM_HOST_API_KEY=${{ secrets.GITHUB_TOKEN }} gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} ${{ env.GEM_NAME }}-${{ env.GEM_VERSION }}.gem + + - name: release + uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # pin@v1.16.0 + with: + artifacts: "${{ env.GEM_NAME }}-${{ env.GEM_VERSION }}.gem" + tag: "v${{ env.GEM_VERSION }}" + generateReleaseNotes: true + + - name: publish to RubyGems + run: | + mkdir -p ~/.gem + echo -e "---\n:rubygems_api_key: ${{ secrets.RUBYGEMS_API_KEY }}" > ~/.gem/credentials + chmod 0600 ~/.gem/credentials + gem push ${{ env.GEM_NAME }}-${{ env.GEM_VERSION }}.gem + rm ~/.gem/credentials diff --git a/.github/workflows/ci.yml b/.github/workflows/test.yml similarity index 56% rename from .github/workflows/ci.yml rename to .github/workflows/test.yml index 9052bde6..44e0690f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/test.yml @@ -1,24 +1,31 @@ -name: CI +name: test + +on: + push: + branches: + - main + pull_request: + permissions: contents: read -on: pull_request - jobs: test: + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - ruby_version: ["3.0", "3.1", "3.2", "3.3"] - runs-on: ubuntu-latest + ruby_version: ["3.1", "3.2", "3.3", "3.4"] + steps: - uses: actions/checkout@v4 + - name: Update .ruby-version with matrix value run: echo "${{ matrix.ruby_version }}" >| .ruby-version - - name: Set up Ruby - uses: ruby/setup-ruby@f26937343756480a8cb3ae1f623b9c8d89ed6984 + + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # pin@v1.245.0 with: bundler-cache: true - rubygems: latest - - name: Run tests - run: bundle exec rake + + - name: test + run: script/test diff --git a/.gitignore b/.gitignore index fb280015..25f6e982 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ spec/reports test/tmp test/version_tmp tmp +bin/ +vendor/ # YARD artifacts .yardoc diff --git a/.ruby-version b/.ruby-version index e4604e3a..4d9d11cf 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.2.1 +3.4.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index b3297896..f9ed0a51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,26 @@ # rubocop-github -## Unreleased +## v0.26.0 -- Update Gemspec `required_ruby_version` to `>= 3.0.0` +- Read the automatic release notes on [the /releases page for this gem](https://github.com/github/rubocop-github/releases). + +## v0.25.0 + +- Read the automatic release notes on [the /releases page for this gem](https://github.com/github/rubocop-github/releases). +- Updated related gems +- Specify plugin class names for included rubocop plugins + +## v0.24.0 + +- Read the automatic release notes on [the /releases page for this gem](https://github.com/github/rubocop-github/releases). + +## v0.23.0 + +- Read the automatic release notes on [the /releases page for this gem](https://github.com/github/rubocop-github/releases). + +## v0.22.0 + +- Read the automatic release notes on [the /releases page for this gem](https://github.com/github/rubocop-github/releases). ## v0.21.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fcab75d4..e5ef656b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,6 @@ We welcome your contributions to the project. Thank you! Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms. - ## What to contribute This repository, `rubocop-github`, is part of a broader RuboCop ecosystem. @@ -50,12 +49,8 @@ Rubocop regularly releases new versions with new cops. We want to keep up to dat ### Releasing a new version -1. Update `rubocop-github.gemspec` with the next version number -1. Update the `CHANGELOG` with changes and contributor -1. Run `bundle` to update gem version contained in the lockfile -1. Make a commit: `Release v{VERSION}` -1. Tag the commit : `git tag v{VERSION}` -1. Create the package: `gem build rubocop-github.gemspec` -1. Push to GitHub: `git push origin && git push origin --tags` -1. Push to Rubygems: `gem push rubocop-github-{VERSION}.gem` -1. Publish a new release on GitHub: https://github.com/github/rubocop-github/releases/new +1. Update [`lib/version.rb`](lib/version.rb) with the next version number +2. Update the `CHANGELOG` with changes and contributor +3. Run `bundle install` to update gem version contained in the lockfile +4. Commit your changes and open a pull request +5. When the pull request is approved and merged into `main`, the [`.github/workflows/release.yml`](.github/workflows/release.yml) workflow will automatically run to release the new version to RubyGems and GitHub Packages 🎉. diff --git a/Gemfile.lock b/Gemfile.lock index e1b6015c..88b38b0e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,102 +1,110 @@ PATH remote: . specs: - rubocop-github (0.21.0) - rubocop (>= 1.37) - rubocop-performance (>= 1.15) - rubocop-rails (>= 2.17) + rubocop-github (0.26.0) + rubocop (>= 1.76) + rubocop-performance (>= 1.24) + rubocop-rails (>= 2.23) GEM remote: https://rubygems.org/ specs: - actionview (7.1.4) - activesupport (= 7.1.4) + actionview (7.2.2.1) + activesupport (= 7.2.2.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activesupport (7.1.4) + activesupport (7.2.2.1) base64 + benchmark (>= 0.3) bigdecimal - concurrent-ruby (~> 1.0, >= 1.0.2) + concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) - mutex_m - tzinfo (~> 2.0) - ast (2.4.2) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + ast (2.4.3) base64 (0.2.0) - bigdecimal (3.1.8) + benchmark (0.4.0) + bigdecimal (3.1.9) builder (3.3.0) - concurrent-ruby (1.3.4) - connection_pool (2.4.1) + concurrent-ruby (1.3.5) + connection_pool (2.5.3) crass (1.0.6) - drb (2.2.1) - erubi (1.13.0) - i18n (1.14.5) + drb (2.2.3) + erubi (1.13.1) + i18n (1.14.7) concurrent-ruby (~> 1.0) - json (2.7.2) - language_server-protocol (3.17.0.3) - loofah (2.22.0) + json (2.12.2) + language_server-protocol (3.17.0.5) + lint_roller (1.1.0) + logger (1.7.0) + loofah (2.24.0) crass (~> 1.0.2) nokogiri (>= 1.12.0) - mini_portile2 (2.8.7) - minitest (5.25.1) - mutex_m (0.2.0) - nokogiri (1.16.7) + mini_portile2 (2.8.8) + minitest (5.25.5) + nokogiri (1.18.8) mini_portile2 (~> 2.8.2) racc (~> 1.4) - nokogiri (1.16.7-arm64-darwin) + nokogiri (1.18.8-arm64-darwin) racc (~> 1.4) - nokogiri (1.16.7-x86_64-darwin) + nokogiri (1.18.8-x86_64-darwin) racc (~> 1.4) - nokogiri (1.16.7-x86_64-linux) + nokogiri (1.18.8-x86_64-linux-gnu) racc (~> 1.4) - parallel (1.26.3) - parser (3.3.4.2) + parallel (1.27.0) + parser (3.3.8.0) ast (~> 2.4.1) racc + prism (1.4.0) racc (1.8.1) - rack (3.1.7) + rack (3.1.16) rails-dom-testing (2.2.0) activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.6.0) + rails-html-sanitizer (1.6.2) loofah (~> 2.21) - nokogiri (~> 1.14) + nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) rainbow (3.1.1) - rake (13.2.1) - regexp_parser (2.9.2) - rexml (3.3.6) - strscan - rubocop (1.65.1) + rake (13.3.0) + regexp_parser (2.10.0) + rubocop (1.76.1) json (~> 2.3) - language_server-protocol (>= 3.17.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 2.4, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.31.1, < 2.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.45.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.32.1) - parser (>= 3.3.1.0) - rubocop-performance (1.21.1) - rubocop (>= 1.48.1, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) - rubocop-rails (2.26.0) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.45.1) + parser (>= 3.3.7.2) + prism (~> 1.4) + rubocop-performance (1.25.0) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.38.0, < 2.0) + rubocop-rails (2.32.0) activesupport (>= 4.2.0) + lint_roller (~> 1.1) rack (>= 1.1) - rubocop (>= 1.52.0, < 2.0) - rubocop-ast (>= 1.31.1, < 2.0) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (1.13.0) - strscan (3.1.0) + securerandom (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - unicode-display_width (2.5.0) + unicode-display_width (3.1.4) + unicode-emoji (~> 4.0, >= 4.0.4) + unicode-emoji (4.0.4) PLATFORMS arm64-darwin-21 @@ -106,10 +114,10 @@ PLATFORMS x86_64-linux DEPENDENCIES - actionview + actionview (~> 7.2.2.1) minitest rake rubocop-github! BUNDLED WITH - 2.4.9 + 2.6.5 diff --git a/README.md b/README.md index 678692b8..ed631b24 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -# RuboCop GitHub ![CI](https://github.com/github/rubocop-github/workflows/CI/badge.svg?event=push) +# RuboCop GitHub + +[![test](https://github.com/github/rubocop-github/actions/workflows/test.yml/badge.svg)](https://github.com/github/rubocop-github/actions/workflows/test.yml) +[![build](https://github.com/github/rubocop-github/actions/workflows/build.yml/badge.svg)](https://github.com/github/rubocop-github/actions/workflows/build.yml) +[![lint](https://github.com/github/rubocop-github/actions/workflows/lint.yml/badge.svg)](https://github.com/github/rubocop-github/actions/workflows/lint.yml) +[![release](https://github.com/github/rubocop-github/actions/workflows/release.yml/badge.svg)](https://github.com/github/rubocop-github/actions/workflows/release.yml) This repository provides recommended RuboCop configuration and additional Cops for use on GitHub open source and internal Ruby projects, and is the home of [GitHub's Ruby Style Guide](./STYLEGUIDE.md). diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md index 758651b6..31f33664 100644 --- a/STYLEGUIDE.md +++ b/STYLEGUIDE.md @@ -3,6 +3,7 @@ This is GitHub's Ruby Style Guide, inspired by [RuboCop's guide][rubocop-guide]. ## Table of Contents + 1. [Layout](#layout) 1. [Indentation](#indentation) 2. [Inline](#inline) @@ -678,7 +679,7 @@ end * Never put a space between a method name and the opening parenthesis. [[link](#no-spaces-method-parens)] - * RuboCop rule: Style/ParenthesesAsGroupedExpression + * RuboCop rule: Lint/ParenthesesAsGroupedExpression ``` ruby # bad @@ -763,6 +764,22 @@ if x > 10 end ``` +* Don't use `unless` with a negated condition. + [[link](#no-unless-negation)] + * RuboCop rule: Style/NegatedUnless + +```ruby +# bad +unless !condition? + do_something +end + +# good +if condition? + do_something +end +``` + ### Ternary operator * Avoid the ternary operator (`?:`) except in cases where all expressions are extremely diff --git a/config/default.yml b/config/default.yml index ee641dfd..55fb0aff 100644 --- a/config/default.yml +++ b/config/default.yml @@ -3,7 +3,10 @@ inherit_from: require: - rubocop-github - - rubocop-performance + +plugins: + - rubocop-performance: + plugin_class_name: RuboCop::Performance::Plugin Bundler/DuplicatedGem: Enabled: true @@ -331,7 +334,8 @@ Layout/SpaceInsideBlockBraces: Enabled: true Layout/SpaceInsideHashLiteralBraces: - Enabled: false + Enabled: true + StyleGuide: https://github.com/github/rubocop-github/blob/main/STYLEGUIDE.md#spaces-operators Layout/SpaceInsideParens: Enabled: true @@ -814,7 +818,7 @@ Naming/MethodName: Naming/MethodParameterName: Enabled: false -Naming/PredicateName: +Naming/PredicatePrefix: Enabled: false Naming/RescuedExceptionsVariableName: @@ -1367,7 +1371,7 @@ Style/NegatedIfElseCondition: Enabled: false Style/NegatedUnless: - Enabled: false + Enabled: true Style/NegatedWhile: Enabled: false diff --git a/config/default_pending.yml b/config/default_pending.yml index 9d189036..5ae412d3 100644 --- a/config/default_pending.yml +++ b/config/default_pending.yml @@ -70,3 +70,47 @@ Style/YAMLFileRead: # new in 1.53 Enabled: false Performance/MapMethodChain: # new in 1.19 Enabled: false +Gemspec/AddRuntimeDependency: # new in 1.65 + Enabled: false +Lint/ConstantReassignment: # new in 1.70 + Enabled: false +Lint/DuplicateSetElement: # new in 1.67 + Enabled: false +Lint/HashNewWithKeywordArgumentsAsDefault: # new in 1.69 + Enabled: false +Lint/NumericOperationWithConstantResult: # new in 1.69 + Enabled: false +Lint/SharedMutableDefault: # new in 1.70 + Enabled: false +Lint/UnescapedBracketInRegexp: # new in 1.68 + Enabled: false +Lint/UselessDefined: # new in 1.69 + Enabled: false +Lint/UselessNumericOperation: # new in 1.66 + Enabled: false +Style/AmbiguousEndlessMethodDefinition: # new in 1.68 + Enabled: false +Style/BitwisePredicate: # new in 1.68 + Enabled: false +Style/CombinableDefined: # new in 1.68 + Enabled: false +Style/DigChain: # new in 1.69 + Enabled: false +Style/FileNull: # new in 1.69 + Enabled: false +Style/FileTouch: # new in 1.69 + Enabled: false +Style/ItAssignment: # new in 1.70 + Enabled: false +Style/KeywordArgumentsMerging: # new in 1.68 + Enabled: false +Style/RedundantInterpolationUnfreeze: # new in 1.66 + Enabled: false +Style/SafeNavigationChainLength: # new in 1.68 + Enabled: false +Style/SendWithLiteralMethodName: # new in 1.64 + Enabled: false +Style/SuperArguments: # new in 1.64 + Enabled: false +Performance/StringBytesize: # new in 1.23 + Enabled: false diff --git a/config/rails.yml b/config/rails.yml index b7b8d6ec..cba38c11 100644 --- a/config/rails.yml +++ b/config/rails.yml @@ -3,7 +3,10 @@ inherit_from: require: - rubocop-github-rails - - rubocop-rails + +plugins: + - rubocop-rails: + plugin_class_name: RuboCop::Rails::Plugin GitHub/RailsControllerRenderActionSymbol: Enabled: true diff --git a/config/rails_pending.yml b/config/rails_pending.yml index 3e9582d9..941a743c 100644 --- a/config/rails_pending.yml +++ b/config/rails_pending.yml @@ -96,3 +96,7 @@ Rails/ThreeStateBooleanColumn: # new in 2.19 Enabled: false Rails/UnusedRenderContent: # new in 2.21 Enabled: false +Rails/EnumSyntax: # new in 2.26 + Enabled: false +Rails/WhereRange: # new in 2.25 + Enabled: false diff --git a/lib/rubocop/cop/github/rails_view_render_literal.rb b/lib/rubocop/cop/github/rails_view_render_literal.rb index c8563868..357b2ee1 100644 --- a/lib/rubocop/cop/github/rails_view_render_literal.rb +++ b/lib/rubocop/cop/github/rails_view_render_literal.rb @@ -54,7 +54,7 @@ def on_send(node) if render_literal?(node) && node.arguments.count > 1 locals = node.arguments[1] - elsif options_pairs = render_with_options?(node) + elsif option_pairs = render_with_options?(node) locals = option_pairs.map { |pair| locals_key?(pair) }.compact.first end diff --git a/lib/version.rb b/lib/version.rb new file mode 100644 index 00000000..8463eaf1 --- /dev/null +++ b/lib/version.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +VERSION = "0.26.0" diff --git a/rubocop-github.gemspec b/rubocop-github.gemspec index 66d16540..b1cf9cc4 100644 --- a/rubocop-github.gemspec +++ b/rubocop-github.gemspec @@ -1,25 +1,33 @@ # frozen_string_literal: true +require_relative "lib/version" + Gem::Specification.new do |s| s.name = "rubocop-github" - s.version = "0.21.0" + s.version = VERSION s.summary = "RuboCop GitHub" - s.description = "Code style checking for GitHub Ruby repositories " + s.description = "Code style checking for GitHub Ruby repositories" s.homepage = "https://github.com/github/rubocop-github" s.license = "MIT" + s.metadata = { + "source_code_uri" => "https://github.com/github/rubocop-github", + "documentation_uri" => "https://github.com/github/rubocop-github", + "bug_tracker_uri" => "https://github.com/github/rubocop-github/issues" + } + s.files = Dir["README.md", "STYLEGUIDE.md", "LICENSE", "config/*.yml", "lib/**/*.rb", "guides/*.md"] - s.add_dependency "rubocop", ">= 1.37" - s.add_dependency "rubocop-performance", ">= 1.15" - s.add_dependency "rubocop-rails", ">= 2.17" + s.required_ruby_version = ">= 3.1.0" - s.add_development_dependency "actionview" + s.add_dependency "rubocop", ">= 1.76" + s.add_dependency "rubocop-performance", ">= 1.24" + s.add_dependency "rubocop-rails", ">= 2.23" + + s.add_development_dependency "actionview", "~> 7.2.2.1" s.add_development_dependency "minitest" s.add_development_dependency "rake" - s.required_ruby_version = ">= 3.0.0" - s.email = "engineering@github.com" s.authors = "GitHub" end diff --git a/script/lint b/script/lint new file mode 100755 index 00000000..4c06652f --- /dev/null +++ b/script/lint @@ -0,0 +1,5 @@ +#! /usr/bin/env bash + +set -e + +bundle exec rake rubocop diff --git a/script/test b/script/test new file mode 100755 index 00000000..05166157 --- /dev/null +++ b/script/test @@ -0,0 +1,5 @@ +#! /usr/bin/env bash + +set -e + +bundle exec rake test diff --git a/test/test_insecure_hash_algorithm.rb b/test/test_insecure_hash_algorithm.rb index 6e0277f3..317562e1 100644 --- a/test/test_insecure_hash_algorithm.rb +++ b/test/test_insecure_hash_algorithm.rb @@ -10,7 +10,7 @@ def cop_class end def make_cop(allowed:) - config = RuboCop::Config.new({"GitHub/InsecureHashAlgorithm" => {"Allowed" => allowed}}) + config = RuboCop::Config.new({ "GitHub/InsecureHashAlgorithm" => { "Allowed" => allowed } }) cop_class.new(config) end