diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml new file mode 100644 index 000000000..d2e59dbb0 --- /dev/null +++ b/.github/workflows/danger.yml @@ -0,0 +1,23 @@ +name: Danger +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + danger: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2.7' + + - name: Install dependencies + run: bundle install + + - name: Run Danger + env: + DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bundle exec danger --verbose \ No newline at end of file diff --git a/.github/workflows/danger_target.yml b/.github/workflows/danger_target.yml new file mode 100644 index 000000000..00da8ffb8 --- /dev/null +++ b/.github/workflows/danger_target.yml @@ -0,0 +1,29 @@ +name: Danger +on: + pull_request_target: + types: [opened, synchronize, reopened] +jobs: + danger: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.ref }} + repository: ${{ github.event.pull_request.head.repo.full_name }} + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2.7' + + - name: Install dependencies + run: bundle install + + + - name: Run Danger + env: + DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: bundle exec danger --verbose \ No newline at end of file diff --git a/Dangerfile b/Dangerfile new file mode 100644 index 000000000..5179b84e9 --- /dev/null +++ b/Dangerfile @@ -0,0 +1,59 @@ +# Dangerfile + +# --- PR Size Checks --- +warn("Pull request is too big (more than 500 LoC).") if git.lines_of_code > 500 +warn("Pull request is too small (less than 50 LoC).") if git.lines_of_code < 50 + +# --- File Change Checks --- +warn("Pull request touches too many files (more than 30 files).") if git.modified_files.count > 30 + +# --- Commit Message Checks --- +commit_messages = git.commits.map(&:message) +duplicated_commits = commit_messages.group_by(&:itself).select { |_, v| v.size > 1 } +warn("Pull request has duplicated commit messages.") if duplicated_commits.any? + +# --- TODO/FIXME Checks --- +todo_fixme = (git.modified_files + git.added_files).any? do |file| + File.read(file).match?(/\b(TODO|FIXME)\b/i) +end +warn("Pull request contains TODO or FIXME comments.") if todo_fixme + +# --- Temp File Checks --- +temp_files = git.added_files.any? { |file| file.match?(/(tmp|temp|cache)/i) } +warn("Pull request includes temp, tmp, or cache files.") if temp_files + +# --- Missing Test Checks --- +warn("There are no test changes in this PR.") if (git.modified_files + git.added_files).none? { |f| f.include?('spec/') || f.include?('test/') } + + +# --- .md File Changes --- +md_changes = git.modified_files.any? { |file| file.end_with?('.md') } +warn("Pull request modifies markdown files (*.md). Make sure you have a good reason.") if md_changes + +# --- DB Schema Changes --- +schema_changes = git.modified_files.any? { |file| file.match?(/db\/schema\.rb$/) } +unless git.modified_files.any? { |file| file.match?(/db\/migrate\//) } + warn("Schema changes detected without a corresponding DB migration.") if schema_changes +end + +# --- Config/Setup File Changes (selected ones not excluded) --- +config_files = %w[ + config/database.yml + config/secrets.yml + config/secrets.yml.example + config/settings.yml + config/settings.yml.example + setup.sh + config.ru +] +changed_config_files = git.modified_files.select { |file| config_files.include?(file) } +warn("Pull request modifies config or setup files: #{changed_config_files.join(', ')}.") if changed_config_files.any? + + +# --- Shallow Tests (RSpec) --- +# (Rules 37-41 — Shallow tests — assuming you want them included) +shallow_test_files = git.modified_files.select { |file| file.include?('spec/') } +shallow_test_warning = shallow_test_files.any? do |file| + File.read(file).match?(/\bit\b|\bspecify\b/) +end +warn("RSpec tests seem shallow (single `it` blocks or no context). Consider improving test structure.") if shallow_test_warning diff --git a/Gemfile b/Gemfile index b5f47ee4b..a9e65ec86 100644 --- a/Gemfile +++ b/Gemfile @@ -47,6 +47,7 @@ group :development, :test do gem 'simplecov', require: false, group: :test gem 'coveralls' gem 'simplecov_json_formatter' + gem 'danger' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 9cca8ef5d..70f485173 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,8 +82,16 @@ GEM bootsnap (1.18.4) msgpack (~> 1.2) builder (3.2.4) + claide (1.1.0) + claide-plugins (0.9.2) + cork + nap + open4 (~> 1.3) + colored2 (3.1.2) concurrent-ruby (1.3.5) connection_pool (2.5.0) + cork (0.3.0) + colored2 (~> 3.1) coveralls (0.7.1) multi_json (~> 1.3) rest-client @@ -91,6 +99,20 @@ GEM term-ansicolor thor crass (1.0.6) + danger (9.5.1) + base64 (~> 0.2) + claide (~> 1.0) + claide-plugins (>= 0.9.2) + colored2 (~> 3.1) + cork (~> 0.1) + faraday (>= 0.9.0, < 3.0) + faraday-http-cache (~> 2.0) + git (~> 1.13) + kramdown (~> 2.3) + kramdown-parser-gfm (~> 1.0) + octokit (>= 4.0) + pstore (~> 0.1) + terminal-table (>= 1, < 4) database_cleaner-active_record (2.2.0) activerecord (>= 5.a) database_cleaner-core (~> 2.0.0) @@ -111,8 +133,19 @@ GEM railties (>= 5.0.0) faker (3.2.0) i18n (>= 1.8.11, < 2) + faraday (2.13.1) + faraday-net_http (>= 2.0, < 3.5) + json + logger + faraday-http-cache (2.5.1) + faraday (>= 0.8) + faraday-net_http (3.4.0) + net-http (>= 0.5.0) find_with_order (1.3.1) activerecord (>= 3) + git (1.19.1) + addressable (~> 2.8) + rchardet (~> 1.8) globalid (1.2.1) activesupport (>= 6.1) http-accept (1.7.0) @@ -129,6 +162,10 @@ GEM json-schema (3.0.0) addressable (>= 2.8) jwt (2.7.1) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) language_server-protocol (3.17.0.3) lingua (0.6.2) logger (1.6.6) @@ -150,6 +187,9 @@ GEM msgpack (1.8.0) multi_json (1.15.0) mysql2 (0.5.5) + nap (1.1.0) + net-http (0.6.0) + uri net-imap (0.5.6) date net-protocol @@ -169,6 +209,10 @@ GEM racc (~> 1.4) nokogiri (1.15.2-x86_64-linux) racc (~> 1.4) + octokit (10.0.0) + faraday (>= 1, < 3) + sawyer (~> 0.9) + open4 (1.3.4) parallel (1.23.0) parser (3.2.2.3) ast (~> 2.4.1) @@ -176,6 +220,7 @@ GEM pp (0.6.2) prettyprint prettyprint (0.2.0) + pstore (0.2.0) psych (5.2.3) date stringio @@ -224,6 +269,7 @@ GEM zeitwerk (~> 2.6) rainbow (3.1.1) rake (13.0.6) + rchardet (1.9.0) rdoc (6.12.0) psych (>= 4.0.0) regexp_parser (2.8.1) @@ -277,6 +323,9 @@ GEM rubocop-ast (1.29.0) parser (>= 3.2.1.0) ruby-progressbar (1.13.0) + sawyer (0.9.2) + addressable (>= 2.3.5) + faraday (>= 0.17.3, < 3) securerandom (0.4.1) simplecov (0.22.0) docile (~> 1.1) @@ -289,6 +338,8 @@ GEM sync (0.5.0) term-ansicolor (1.11.2) tins (~> 1.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) thor (1.2.2) timeout (0.4.3) tins (1.38.0) @@ -319,6 +370,7 @@ DEPENDENCIES bcrypt (~> 3.1.7) bootsnap (>= 1.18.4) coveralls + danger database_cleaner-active_record debug factory_bot_rails