Skip to content

Commit 200e7f1

Browse files
authored
Merge pull request #183 from AaronC81/seed-failures
Run examples on GitHub Actions
2 parents f4113a6 + 229d5a6 commit 200e7f1

File tree

4 files changed

+134
-61
lines changed

4 files changed

+134
-61
lines changed

.github/workflows/examples.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Run Sord on examples
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
test:
7+
runs-on: ubuntu-latest
8+
continue-on-error: false
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Set up Ruby
12+
uses: ruby/setup-ruby@v1
13+
with:
14+
ruby-version: 3.4 # Use latest for best chance of dependencies resolving
15+
- name: Install dependencies
16+
run: bundle install
17+
- name: Install example dependencies
18+
run: sudo apt-get install libldap2-dev libidn11-dev # Dependencies for `addressable`
19+
- name: Run examples (RBI)
20+
run: bundle exec rake examples:seed[rbi]
21+
- name: Run examples (RBS)
22+
run: bundle exec rake examples:seed[rbs]

.github/workflows/ruby.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jobs:
66
test:
77
strategy:
88
matrix:
9-
ruby: [3.0, 3.1]
9+
ruby: [3.0, 3.1, 3.2, 3.3, 3.4]
1010
continue-on-error: false
1111

1212
runs-on: ubuntu-latest

Rakefile

Lines changed: 109 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -19,85 +19,138 @@ REPOS = {
1919
zeitwerk: 'https://github.com/fxn/zeitwerk'
2020
}
2121

22-
namespace :examples do
23-
require 'fileutils'
24-
require 'rainbow'
22+
# Thrown by tasks to present a "friendly" error message and abort the task.
23+
class TaskError < StandardError
24+
end
2525

26-
desc "Clone git repositories and run Sord on them as examples"
27-
task :seed, [:mode, :clean] do |t, args|
28-
if File.directory?('sord_examples')
29-
puts Rainbow('sord_examples directory already exists, please delete the directory or run a reseed!').red
30-
exit
31-
end
26+
# Handles Sord examples, including checkout and running Sord to generate types.
27+
class ExampleRunner
28+
attr_reader :mode, :mode_arg, :clean
29+
alias clean? clean
30+
31+
# @return [<Symbol>] Names of gems where Sord failed.
32+
attr_accessor :failed_examples
3233

33-
if args[:mode] == 'rbi'
34-
mode_arg = '--rbi'
35-
elsif args[:mode] == 'rbs'
36-
mode_arg = '--rbs'
34+
# @param [String] mode "rbi" or "rbs".
35+
# @param [Boolean] clean Run Sord with additional options to generate minimal type output.
36+
def initialize(mode:, clean: false)
37+
@mode = mode
38+
@clean = clean
39+
40+
if mode == 'rbi'
41+
@mode_arg = '--rbi'
42+
elsif mode == 'rbs'
43+
@mode_arg = '--rbs'
3744
else
38-
puts Rainbow('please specify \'rbi\' or \'rbs\'!').red
39-
exit
45+
raise TaskError, 'please specify \'rbi\' or \'rbs\'!'
46+
end
47+
48+
@failed_examples = []
49+
end
50+
51+
# Create the `sord_examples` directory, ready for checkouts.
52+
# @raise [TaskError] If it already exists.
53+
def create_examples_dir
54+
if File.directory?(File.join(__dir__, 'sord_examples'))
55+
raise TaskError, 'sord_examples directory already exists, please delete the directory or run a reseed!'
4056
end
4157

4258
FileUtils.mkdir 'sord_examples'
43-
FileUtils.cd 'sord_examples'
44-
45-
Bundler.with_clean_env do
46-
# Shallow clone each of the repositories, then bundle install and run sord.
47-
REPOS.each do |name, url|
48-
puts "Cloning #{name}..."
49-
system("git clone #{url} --depth=1")
50-
FileUtils.cd name.to_s
59+
end
60+
61+
# Check that the `sord_examples` directory exists.
62+
# @raise [TaskError] If it doesn't.
63+
def validate_examples_dir
64+
unless File.directory?(File.join(__dir__, 'sord_examples'))
65+
raise TaskError, 'The sord_examples directory does not exist. Have you run the seed task?'
66+
end
67+
end
68+
69+
# Check out a repository, add Sord to its Gemfile, and install its dependencies.
70+
# @param [Symbol] name Name of the checkout.
71+
# @param [String] url Git URL.
72+
def prepare_checkout(name, url)
73+
Dir.chdir(File.join(__dir__, 'sord_examples')) do
74+
puts "Cloning #{name}..."
75+
system("git clone #{url} --depth=1")
76+
77+
Dir.chdir(name.to_s) do
5178
# Add sord to gemfile.
5279
`echo "gem 'sord', path: '../../'" >> Gemfile`
80+
5381
# Run bundle install.
5482
system('bundle install')
55-
# Generate sri
56-
puts "Generating rbi for #{name}..."
57-
if args[:clean]
58-
system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg} --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
59-
else
60-
system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg}")
61-
end
62-
puts "#{name}.#{args[:mode]} generated!"
63-
FileUtils.cd '..'
6483
end
6584
end
85+
end
6686

67-
puts Rainbow("Seeding complete!").green
87+
# Run Sord on a checked-out repository.
88+
# @param [Symbol] name Name of the checkout.
89+
def generate_types(name)
90+
puts "Generating rbi for #{name}..."
91+
92+
Dir.chdir(File.join(__dir__, 'sord_examples', name.to_s)) do
93+
if clean?
94+
system("bundle exec sord ../#{name}.#{mode} #{mode_arg} --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
95+
else
96+
system("bundle exec sord ../#{name}.#{mode} #{mode_arg}")
97+
end
98+
99+
if $?.success?
100+
puts "#{name}.#{mode} generated!"
101+
else
102+
puts "Sord exited with error"
103+
failed_examples << name
104+
end
105+
end
68106
end
69107

70-
desc 'Regenerate the rbi files in sord_examples.'
71-
task :reseed, [:mode, :clean] do |t, args|
72-
if Dir.exist?('sord_examples')
73-
FileUtils.cd 'sord_examples'
74-
else
75-
raise Rainbow("The sord_examples directory does not exist. Have you run the seed task?").red.bold
108+
# Check that all Sord executions were successful.
109+
# @raise [TaskError] If any failed.
110+
def validate_sord_success
111+
if failed_examples.any?
112+
raise TaskError, "Not all Sord runs were successful: #{failed_examples.map(&:to_s).join(', ')}"
76113
end
114+
end
115+
end
77116

78-
if args[:mode] == 'rbi'
79-
mode_arg = '--rbi'
80-
elsif args[:mode] == 'rbs'
81-
mode_arg = '--rbs'
82-
else
83-
puts Rainbow('please specify \'rbi\' or \'rbs\'!').red
84-
exit
117+
namespace :examples do
118+
require 'fileutils'
119+
require 'rainbow'
120+
121+
desc "Clone git repositories and run Sord on them as examples"
122+
task :seed, [:mode, :clean] do |t, args|
123+
examples = ExampleRunner.new(**args)
124+
examples.create_examples_dir
125+
126+
Bundler.with_clean_env do
127+
REPOS.each do |name, url|
128+
examples.prepare_checkout(name, url)
129+
examples.generate_types(name)
130+
end
85131
end
132+
examples.validate_sord_success
133+
134+
puts Rainbow("Seeding complete!").green
135+
136+
rescue TaskError => e
137+
abort Rainbow(e.to_s).red
138+
end
139+
140+
desc 'Regenerate the rbi files in sord_examples.'
141+
task :reseed, [:mode, :clean] do |t, args|
142+
examples = ExampleRunner.new(**args)
143+
examples.validate_examples_dir
86144

87145
REPOS.keys.each do |name|
88-
FileUtils.cd name.to_s
89-
puts "Regenerating rbi file for #{name}..."
90-
Bundler.with_clean_env do
91-
if args[:clean]
92-
system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg} --no-regenerate --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
93-
else
94-
system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg} --no-regenerate")
95-
end
96-
end
97-
FileUtils.cd '..'
146+
examples.generate_types(name)
98147
end
148+
examples.validate_sord_success
99149

100150
puts Rainbow("Re-seeding complete!").green
151+
152+
rescue TaskError => e
153+
abort Rainbow(e.to_s).red
101154
end
102155

103156
desc 'Delete the sord_examples directory to allow the seeder to run again.'

lib/sord/generator.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,8 @@ def run
681681
end
682682
end
683683
rescue
684-
Logging.error($!)
685-
$@.each do |line|
686-
puts " #{line}"
687-
end
684+
Logging.error("An internal error occurred while running Sord: #{$!}")
685+
raise
688686
end
689687

690688
# Given two pairs of arrays representing method parameters, in the form

0 commit comments

Comments
 (0)