et 0.5.8 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +456 -0
- data/.ruby-version +1 -1
- data/Gemfile.lock +27 -23
- data/README.md +17 -0
- data/et.gemspec +3 -2
- data/lib/et.rb +1 -0
- data/lib/et/api.rb +40 -60
- data/lib/et/fallback_connection.rb +29 -0
- data/lib/et/lesson.rb +10 -14
- data/lib/et/runner.rb +2 -2
- data/lib/et/submission_file_list.rb +57 -0
- data/lib/et/version.rb +1 -1
- data/spec/cli/get_lesson_spec.rb +14 -14
- data/spec/cli/list_lessons_spec.rb +1 -1
- data/spec/data/bloated-challenge/.etignore +4 -0
- data/spec/data/bloated-challenge/.lesson.yml +3 -0
- data/spec/data/bloated-challenge/bloated-challenge.md +3 -0
- data/spec/data/bloated-challenge/node_modules/boo/somefile.js +1 -0
- data/spec/data/bloated-challenge/problem.rb +1 -0
- data/spec/data/bloated-challenge/rando_folder/rando_file.js +1 -0
- data/spec/data/sample-challenge/.etignore +1 -0
- data/spec/data/sample-challenge/.lesson.yml +0 -2
- data/spec/data/sample-exercise/.etignore +1 -0
- data/spec/data/sample-exercise/.lesson.yml +0 -2
- data/spec/lib/api_spec.rb +54 -88
- data/spec/lib/fallback_connection_spec.rb +42 -0
- data/spec/lib/submission_file_list_spec.rb +31 -0
- data/spec/spec_helper.rb +0 -5
- metadata +55 -14
|
@@ -2,7 +2,7 @@ describe "list lessons" do
|
|
|
2
2
|
let(:sample_lessons_file) { project_root.join("spec/data/lessons.json") }
|
|
3
3
|
|
|
4
4
|
let(:sample_lessons) do
|
|
5
|
-
JSON.parse(File.read(sample_lessons_file)
|
|
5
|
+
JSON.parse(File.read(sample_lessons_file))['lessons']
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
it "prints the titles and slug" do
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
alert('please do not include this file');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# YOUR CODE GOES HERE
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log('I am random');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sample-challenge.md
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sample-exercise.md
|
data/spec/lib/api_spec.rb
CHANGED
|
@@ -10,26 +10,24 @@ describe ET::API do
|
|
|
10
10
|
|
|
11
11
|
describe "lessons" do
|
|
12
12
|
it "queries for a list of lessons" do
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
expect(http).to receive(:request).and_return(response)
|
|
25
|
-
expect(response).to receive(:body).and_return(lessons_response)
|
|
13
|
+
client = Faraday.new do |builder|
|
|
14
|
+
builder.response :json
|
|
15
|
+
|
|
16
|
+
builder.adapter :test do |stubs|
|
|
17
|
+
stubs.get("/lessons.json") do
|
|
18
|
+
[200, {}, lessons_response]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
allow_any_instance_of(ET::FallbackConnection).to receive(:open).and_yield(client)
|
|
26
24
|
|
|
27
25
|
results = api.list_lessons
|
|
28
26
|
|
|
29
27
|
expect(results.count).to eq(3)
|
|
30
|
-
expect(results[0][
|
|
31
|
-
expect(results[0][
|
|
32
|
-
expect(results[0][
|
|
28
|
+
expect(results[0]['title']).to eq("Max Number")
|
|
29
|
+
expect(results[0]['slug']).to eq("max-number")
|
|
30
|
+
expect(results[0]['type']).to eq("exercise")
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
let(:lesson_response) do
|
|
@@ -37,99 +35,67 @@ describe ET::API do
|
|
|
37
35
|
end
|
|
38
36
|
|
|
39
37
|
it "queries for a single lesson" do
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
http = double
|
|
43
|
-
|
|
44
|
-
lesson_uri = URI("http://localhost:3000/lessons/rock-paper-scissors.json?submittable=1")
|
|
45
|
-
expect(Net::HTTP::Get).to receive(:new).
|
|
46
|
-
with(lesson_uri).
|
|
47
|
-
and_return(request)
|
|
48
|
-
expect(Net::HTTP).to receive(:start).with(
|
|
49
|
-
lesson_uri.host,
|
|
50
|
-
lesson_uri.port,
|
|
51
|
-
use_ssl: lesson_uri.scheme == "https").
|
|
52
|
-
and_yield(http)
|
|
53
|
-
expect(http).to receive(:request).and_return(response)
|
|
54
|
-
expect(response).to receive(:body).and_return(lesson_response)
|
|
55
|
-
|
|
56
|
-
result = api.get_lesson("rock-paper-scissors")
|
|
38
|
+
client = Faraday.new do |builder|
|
|
39
|
+
builder.response :json
|
|
57
40
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
41
|
+
builder.adapter :test do |stubs|
|
|
42
|
+
stubs.get("/lessons/rock-paper-scissors.json") do
|
|
43
|
+
[200, {}, lesson_response]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
62
47
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
dbl_os = double
|
|
66
|
-
allow(dbl_os).to receive(:platform_family?).with(:windows).and_return(false)
|
|
67
|
-
expect(ET::OperatingSystem).to receive(:new).and_return(dbl_os)
|
|
48
|
+
allow_any_instance_of(ET::FallbackConnection).
|
|
49
|
+
to receive(:open).and_yield(client)
|
|
68
50
|
|
|
69
|
-
|
|
70
|
-
expect{ api.list_lessons }.to raise_error(OpenSSL::SSL::SSLError)
|
|
71
|
-
end
|
|
51
|
+
result = api.get_lesson("rock-paper-scissors")
|
|
72
52
|
|
|
73
|
-
|
|
74
|
-
http
|
|
75
|
-
allow(http).to receive(:start).and_yield(http)
|
|
76
|
-
allow(http).to receive(:verify_mode=)
|
|
77
|
-
allow(http).to receive(:use_ssl=)
|
|
78
|
-
response = double
|
|
79
|
-
|
|
80
|
-
allow(http).to receive(:request).and_return(response)
|
|
81
|
-
allow(response).to receive(:body).and_return(lessons_response)
|
|
82
|
-
|
|
83
|
-
allow(Net::HTTP).to receive(:start).
|
|
84
|
-
with(
|
|
85
|
-
lessons_uri.host,
|
|
86
|
-
lessons_uri.port,
|
|
87
|
-
use_ssl: lessons_uri.scheme == 'https').
|
|
88
|
-
and_raise(OpenSSL::SSL::SSLError)
|
|
89
|
-
|
|
90
|
-
expect(Net::HTTP).to receive(:new).with(
|
|
91
|
-
lessons_uri.host,
|
|
92
|
-
lessons_uri.port).
|
|
93
|
-
and_return(http)
|
|
94
|
-
|
|
95
|
-
dbl_os = double
|
|
96
|
-
allow(dbl_os).to receive(:platform_family?).and_return(:windows)
|
|
97
|
-
allow(ET::OperatingSystem).to receive(:new).and_return(dbl_os)
|
|
98
|
-
|
|
99
|
-
api.list_lessons
|
|
53
|
+
expect(result['title']).to eq("Rock, Paper, Scissors")
|
|
54
|
+
expect(result['archive_url']).to eq('http://example.com/rock-paper-scissors.tar.gz')
|
|
100
55
|
end
|
|
101
56
|
end
|
|
102
57
|
|
|
103
58
|
context 'downloading files' do
|
|
104
59
|
it 'returns nil when a 404 is encountered' do
|
|
60
|
+
filename = 'somefile.tar.gz'
|
|
61
|
+
client = Faraday.new do |builder|
|
|
62
|
+
builder.response :json
|
|
63
|
+
|
|
64
|
+
builder.adapter :test do |stubs|
|
|
65
|
+
stubs.get("/#{filename}") do
|
|
66
|
+
[404, {}, '']
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
105
70
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
allow(response).to receive(:code).and_return("404")
|
|
109
|
-
allow(http).to receive(:request).and_return(response)
|
|
110
|
-
allow(Net::HTTP).to receive(:start).and_yield(http)
|
|
71
|
+
allow_any_instance_of(ET::FallbackConnection).
|
|
72
|
+
to receive(:open).and_yield(client)
|
|
111
73
|
|
|
112
|
-
expect(api.download_file("http://example.com
|
|
74
|
+
expect(api.download_file("http://example.com/#{filename}")).to be_nil
|
|
113
75
|
end
|
|
76
|
+
|
|
114
77
|
it 'returns a local file when a challenge is successfully downloaded' do
|
|
115
78
|
path = '/tmp/et'
|
|
116
|
-
filename = '
|
|
79
|
+
filename = 'some-challenge.tar.gz'
|
|
117
80
|
|
|
118
81
|
FileUtils.rm_rf(File.join(path, filename))
|
|
119
82
|
FileUtils.mkdir_p(path)
|
|
120
83
|
|
|
84
|
+
filename = 'somefile.tar.gz'
|
|
85
|
+
client = Faraday.new do |builder|
|
|
86
|
+
builder.adapter :test do |stubs|
|
|
87
|
+
stubs.get("/#{filename}") do
|
|
88
|
+
[200, {}, '']
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
allow_any_instance_of(ET::FallbackConnection).
|
|
94
|
+
to receive(:open).and_yield(client)
|
|
121
95
|
allow(Dir).to receive(:mktmpdir).and_return(path)
|
|
122
96
|
allow(SecureRandom).to receive(:hex).and_return(filename)
|
|
123
97
|
|
|
124
|
-
|
|
125
|
-
response = double
|
|
126
|
-
file_contents = File.read(File.join(File.dirname(__FILE__), "../data/some-challenge.tar.gz"))
|
|
127
|
-
allow(response).to receive(:body).and_return(file_contents)
|
|
128
|
-
allow(response).to receive(:code).and_return("200")
|
|
129
|
-
allow(http).to receive(:request).and_return(response)
|
|
130
|
-
allow(Net::HTTP).to receive(:start).and_yield(http)
|
|
131
|
-
|
|
132
|
-
url = 'http://example.com/some-challenge.tar.gz'
|
|
98
|
+
url = "http://example.com/#{filename}"
|
|
133
99
|
|
|
134
100
|
expect(api.download_file(url)).to eql(File.join(path, filename))
|
|
135
101
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
describe ET::FallbackConnection do
|
|
2
|
+
let(:cnn) do
|
|
3
|
+
ET::FallbackConnection.new(:url => 'http://localhost')
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
context 'ssl verification' do
|
|
7
|
+
it 're-raises an exception for non Windows machines' do
|
|
8
|
+
dbl_os = double
|
|
9
|
+
allow(dbl_os).to receive(:platform_family?).with(:windows).and_return(false)
|
|
10
|
+
expect(ET::OperatingSystem).to receive(:new).and_return(dbl_os)
|
|
11
|
+
|
|
12
|
+
allow_any_instance_of(Faraday::Connection).
|
|
13
|
+
to receive(:get).and_raise(Faraday::SSLError.new(OpenSSL::SSL::SSLError))
|
|
14
|
+
|
|
15
|
+
expect{ cnn.open {|client| client.get('/') }}.
|
|
16
|
+
to raise_error(Faraday::SSLError)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'swallows the exception for windows machines and reissues' do
|
|
20
|
+
dbl_os = double
|
|
21
|
+
allow(dbl_os).to receive(:platform_family?).and_return(:windows)
|
|
22
|
+
allow(ET::OperatingSystem).to receive(:new).and_return(dbl_os)
|
|
23
|
+
|
|
24
|
+
called_twice = false
|
|
25
|
+
allow_any_instance_of(Faraday::Connection).to receive(:get) do |*args|
|
|
26
|
+
if args[0].ssl.verify != false
|
|
27
|
+
#simulate a windows SSL verification failed
|
|
28
|
+
raise Faraday::SSLError.new(OpenSSL::SSL::SSLError.new)
|
|
29
|
+
elsif args[0].ssl.verify == false
|
|
30
|
+
#flip the switch that the request was reissued without SSL verification
|
|
31
|
+
called_twice = true
|
|
32
|
+
double(:body => '{}')
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
cnn.open do |client|
|
|
37
|
+
client.get('/')
|
|
38
|
+
end
|
|
39
|
+
expect(called_twice).to be(true)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
describe ET::SubmissionFileList do
|
|
2
|
+
let(:file_list) do
|
|
3
|
+
path = File.expand_path(File.join(
|
|
4
|
+
File.dirname(__FILE__), "../data/bloated-challenge"))
|
|
5
|
+
ET::SubmissionFileList.new(path)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it 'includes a relevant file' do
|
|
9
|
+
expect(file_list).to include('problem.rb')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'includes .etignore' do
|
|
13
|
+
expect(file_list).to include('.etignore')
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'ignores a standard file' do
|
|
17
|
+
expect(file_list).to_not include('sample-challenge.md')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'ignores a file included in the default globs' do
|
|
21
|
+
expect(file_list).to_not include('node_modules/somefile.js')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'ignores a file included in a glob' do
|
|
25
|
+
expect(file_list).to_not include('node_modules/boo/somefile.js')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'ignores a file included in .etignore' do
|
|
29
|
+
expect(file_list).to_not include('rando_folder/rando_file.js')
|
|
30
|
+
end
|
|
31
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: et
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adam Sheehan
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-06-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: pry
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
17
|
- - "~>"
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
19
|
+
version: '0'
|
|
20
20
|
type: :development
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
26
|
+
version: '0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: rspec
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
34
|
-
type: :
|
|
33
|
+
version: '3.0'
|
|
34
|
+
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
40
|
+
version: '3.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: rake
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '
|
|
47
|
+
version: '10'
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '
|
|
54
|
+
version: '10'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec-mocks
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -94,6 +94,34 @@ dependencies:
|
|
|
94
94
|
- - '='
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: 2.11.0
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: faraday
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - "~>"
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0.9'
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - "~>"
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0.9'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: faraday_middleware
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0.10'
|
|
118
|
+
type: :runtime
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0.10'
|
|
97
125
|
description: |
|
|
98
126
|
Users can download challenges and submit their solutions via the command-line
|
|
99
127
|
interface.
|
|
@@ -105,6 +133,8 @@ extra_rdoc_files: []
|
|
|
105
133
|
files:
|
|
106
134
|
- ".gitignore"
|
|
107
135
|
- ".rspec"
|
|
136
|
+
- ".rubocop.yml"
|
|
137
|
+
- ".rubocop_todo.yml"
|
|
108
138
|
- ".ruby-gemset"
|
|
109
139
|
- ".ruby-version"
|
|
110
140
|
- ".travis.yml"
|
|
@@ -120,21 +150,31 @@ files:
|
|
|
120
150
|
- lib/et/challenge.rb
|
|
121
151
|
- lib/et/config.rb
|
|
122
152
|
- lib/et/exercise.rb
|
|
153
|
+
- lib/et/fallback_connection.rb
|
|
123
154
|
- lib/et/formatter.rb
|
|
124
155
|
- lib/et/lesson.rb
|
|
125
156
|
- lib/et/operating_system.rb
|
|
126
157
|
- lib/et/runner.rb
|
|
158
|
+
- lib/et/submission_file_list.rb
|
|
127
159
|
- lib/et/version.rb
|
|
128
160
|
- spec/cli/get_lesson_spec.rb
|
|
129
161
|
- spec/cli/init_spec.rb
|
|
130
162
|
- spec/cli/list_lessons_spec.rb
|
|
131
163
|
- spec/cli/run_exercise_test_suite_spec.rb
|
|
132
164
|
- spec/cli/submit_lesson_spec.rb
|
|
165
|
+
- spec/data/bloated-challenge/.etignore
|
|
166
|
+
- spec/data/bloated-challenge/.lesson.yml
|
|
167
|
+
- spec/data/bloated-challenge/bloated-challenge.md
|
|
168
|
+
- spec/data/bloated-challenge/node_modules/boo/somefile.js
|
|
169
|
+
- spec/data/bloated-challenge/problem.rb
|
|
170
|
+
- spec/data/bloated-challenge/rando_folder/rando_file.js
|
|
133
171
|
- spec/data/challenge.json
|
|
134
172
|
- spec/data/lessons.json
|
|
173
|
+
- spec/data/sample-challenge/.etignore
|
|
135
174
|
- spec/data/sample-challenge/.lesson.yml
|
|
136
175
|
- spec/data/sample-challenge/problem.rb
|
|
137
176
|
- spec/data/sample-challenge/sample-challenge.md
|
|
177
|
+
- spec/data/sample-exercise/.etignore
|
|
138
178
|
- spec/data/sample-exercise/.lesson.yml
|
|
139
179
|
- spec/data/sample-exercise/lib/sample_exercise.rb
|
|
140
180
|
- spec/data/sample-exercise/sample-exercise.md
|
|
@@ -145,8 +185,10 @@ files:
|
|
|
145
185
|
- spec/lib/challenge_spec.rb
|
|
146
186
|
- spec/lib/config_spec.rb
|
|
147
187
|
- spec/lib/exercise_spec.rb
|
|
188
|
+
- spec/lib/fallback_connection_spec.rb
|
|
148
189
|
- spec/lib/lesson_spec.rb
|
|
149
190
|
- spec/lib/operating_system_spec.rb
|
|
191
|
+
- spec/lib/submission_file_list_spec.rb
|
|
150
192
|
- spec/spec_helper.rb
|
|
151
193
|
- spec/support/helpers/archive_helper.rb
|
|
152
194
|
- spec/support/helpers/output_catcher.rb
|
|
@@ -172,8 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
172
214
|
- !ruby/object:Gem::Version
|
|
173
215
|
version: '0'
|
|
174
216
|
requirements: []
|
|
175
|
-
|
|
176
|
-
rubygems_version: 2.4.5.1
|
|
217
|
+
rubygems_version: 3.0.3
|
|
177
218
|
signing_key:
|
|
178
219
|
specification_version: 4
|
|
179
220
|
summary: Command-line interface for the event horizon.
|