Skip to content

Commit

Permalink
DX-2042: Add spec for includes
Browse files Browse the repository at this point in the history
Add a spec that ensures includes are used where possible, using Octokit
to post code review comments to files that should be using an include,
but doesn't.
  • Loading branch information
asbjornu committed Feb 13, 2023
1 parent ee6a8e1 commit 29aec90
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 0 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,5 @@ jobs:
- name: rspec
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_CONTEXT: ${{ toJson(github) }}
run: bundle exec rake
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ end
group :test do
gem 'html-proofer', '>= 4'
gem 'html-proofer-unrendered-markdown', '>= 0.2'
gem 'octokit', '>= 6.0.1'
gem 'rake', '>= 13'
gem 'rspec', '>= 3'
gem 'rubocop', '>= 1'
Expand Down
7 changes: 7 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ GEM
racc (~> 1.4)
nokogiri (1.14.1-x86_64-linux)
racc (~> 1.4)
octokit (6.0.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
open3 (0.1.2)
parallel (1.22.1)
parser (3.2.0.0)
Expand Down Expand Up @@ -157,6 +160,9 @@ GEM
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
swedbank-pay-design-guide-jekyll-theme (1.16.2)
faraday (>= 1.0.1, < 3)
jekyll (>= 3.7, < 5.0)
Expand Down Expand Up @@ -194,6 +200,7 @@ DEPENDENCIES
jemoji
kramdown (>= 2.3)
kramdown-plantuml (>= 1.3)
octokit (>= 6.0.1)
rake (>= 13)
rouge (>= 4.0.1)
rspec (>= 3)
Expand Down
86 changes: 86 additions & 0 deletions spec/include_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# frozen_string_literal: true

require_relative './support/githubber'

describe 'includes used' do
def make_relative(path)
root_dir = File.expand_path(File.join(__dir__, '..')) + File::SEPARATOR
path.sub(root_dir, '')
end

def create_pull_request_review(message, filename, line_number)
@githubber.create_pull_request_review(message, filename, line_number)
true
rescue StandardError => e
puts 'Failed to create pull request review. Falling back to regular spec failure.'
puts e
false
end

def line_should_use_include(line)
return nil if line.include? '<!--noinclude-->'

match = line.match(/&nbsp;`([^\|]+)`/)

return nil unless match

field_name = match[1]
include_file = @fields[field_name]

return nil unless include_file
return nil if line.include? "{% include #{include_file}"

[include_file, field_name]
end

before(:all) do
def map_file(file_name)
field_name = File.basename(file_name, '.md').gsub(/-[a-z]/) { |match| match[1].upcase }
file_name = file_name.split('_includes/').last
[ field_name, file_name ]
end

root_dir = File.expand_path(File.join(__dir__, '..'))
include_dir = File.join(root_dir, '_includes')
@fields = Dir.glob(File.join(include_dir, 'fields', '*.md')).map { |f| map_file(f) }.to_h
@events = Dir.glob(File.join(include_dir, 'events', '*.md')).map { |f| map_file(f) }.to_h
@files = Dir.glob(File.join(root_dir, '**', '*.md')).reject { |f| f.include?('_includes/fields') || f.include?('_includes/events') }
@githubber = SwedbankPay::Githubber.new
end

context 'with fields' do
subject { @fields }
it { is_expected.not_to be_empty }
end

context 'with events' do
subject { @events }
it { is_expected.not_to be_empty }
end

context 'with GITHUB_CONTEXT' do
subject { ENV['GITHUB_CONTEXT'] }
it { is_expected.not_to be_empty }
end

context 'with files' do
subject { @files }
it { is_expected.not_to be_empty }

it 'should use includes where available' do
@files.each do |file|
File.readlines(file).each_with_index do |line, line_number|
(include_file, field_name) = line_should_use_include(line)
next unless include_file

relative_filename = make_relative(file)
msg = "#{relative_filename}:#{line_number} should use the include '#{include_file}' for the field `#{field_name}`."

unless create_pull_request_review(msg, relative_filename, line_number)
expect(line).to include("{% include #{include_file}"), msg
end
end
end
end
end
end
40 changes: 40 additions & 0 deletions spec/support/githubber.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

require 'octokit'

module SwedbankPay
class Githubber
def initialize
github_token = ENV['GITHUB_TOKEN']
github_context_env = ENV['GITHUB_CONTEXT']

raise 'GITHUB_TOKEN is not set' if github_token.nil? || github_token.empty?
raise 'GITHUB_CONTEXT is not set' if github_context_env.nil? || github_context_env.empty?

@octokit = Octokit::Client.new(access_token: github_token)
@github_context = JSON.parse(github_context_env)
end

def create_pull_request_review(message, filename, line_number)
repo = @github_context['repository']
pr_number = @github_context['event']['number']

raise 'Could not find repository' if repo.nil? || repo.empty?
raise 'Could not find pull request number' if pr_number.nil? || pr_number.zero?

comments = [{ path: filename, position: line_number, body: message }]
options = { event: 'REQUEST_CHANGES', comments: comments }

puts "Creating pull request review for #{filename}:#{line_number} in #{repo}##{pr_number}."

# TODO: For some reason, the API call below fails with the following error:
# POST https://api.github.com/repos/SwedbankPay/developer.swedbankpay.com/pulls/1711/reviews:
# 422 - Unprocessable Entity
# Error summary:
# Pull request review thread position is invalid and Pull request review
# thread diff hunk can't be blank
# // See: https://docs.github.com/rest/reference/pulls#create-a-review-for-a-pull-request
@octokit.create_pull_request_review(repo, pr_number, options)
end
end
end

0 comments on commit 29aec90

Please sign in to comment.