grade_runner 0.0.11 → 0.0.12

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b45590a9a30c53dfa993e986ce49f4bc33696f1a35f0e8587a4d9b54dad3f380
4
- data.tar.gz: 76e02456149f91f875c029add83bbdf1d31c7ce4b02fd9dd2729410911cf38b7
3
+ metadata.gz: 4d69d4bf6d04b43a1158cee76f3226460f25df5ed22c2ef51923d457edd6fba9
4
+ data.tar.gz: 5b3b6fe6ca5cefb53e9c03637564ec265d13fff47e0ace72416f87e5c46882e2
5
5
  SHA512:
6
- metadata.gz: 25ccf695386404cf691960d213fed68402ba1269361af0ccf0a82a463d3dadb4065766e0380c6beaf83020eadf31241ee6b72a9041a339fd9930155959f3d664
7
- data.tar.gz: 31adbef7665e978f6292cbf8663f79bc77bc6828c76a8b9afeb740914d762cbefdf1a5c2f88b6d2495819169f9f1a689b355a110ae44597366983e0c6e84c311
6
+ metadata.gz: 46ff93a107026b708e82920099482856d8dc5c303694e24b4e18faf270e8a8ade4429920d69f2b786d1920b1d37629a5f8a8331d8ad19e251e6fc30407889433
7
+ data.tar.gz: e2e70bfb662d4afed2fdf254e49c42cc2ebc9e83154de2a01a6d1ff0ea16bce65e4b06ec4e3f55c982d1ee70019262fb60c5dd38867cabda831f8cd50a26df67
data/Gemfile CHANGED
@@ -4,6 +4,7 @@ source "https://rubygems.org"
4
4
  gem "activesupport", ">= 2.3.5"
5
5
  gem "oj", "~> 3.13.12"
6
6
  gem "octokit", "~> 5.0"
7
+ gem "zip"
7
8
  gem "faraday-retry", "~> 1.0.3"
8
9
  gem "rake", "~> 13"
9
10
  # Add dependencies to develop your gem here.
data/Gemfile.lock CHANGED
@@ -8,6 +8,7 @@ GEM
8
8
  tzinfo (~> 2.0)
9
9
  addressable (2.8.4)
10
10
  public_suffix (>= 2.0.2, < 6.0)
11
+ base64 (0.2.0)
11
12
  binding_of_caller (1.0.0)
12
13
  debug_inspector (>= 0.0.1)
13
14
  builder (3.2.4)
@@ -19,6 +20,7 @@ GEM
19
20
  thread_safe (~> 0.3, >= 0.3.1)
20
21
  diff-lcs (1.5.0)
21
22
  docile (1.4.0)
23
+ domain_name (0.6.20240107)
22
24
  faraday (1.10.3)
23
25
  faraday-em_http (~> 1.0)
24
26
  faraday-em_synchrony (~> 1.0)
@@ -42,6 +44,10 @@ GEM
42
44
  faraday-patron (1.0.0)
43
45
  faraday-rack (1.0.0)
44
46
  faraday-retry (1.0.3)
47
+ ffi (1.17.0)
48
+ ffi-compiler (1.3.2)
49
+ ffi (>= 1.15.5)
50
+ rake
45
51
  git (1.18.0)
46
52
  addressable (~> 2.8)
47
53
  rchardet (~> 1.8)
@@ -53,6 +59,15 @@ GEM
53
59
  oauth2 (~> 1.0)
54
60
  hashie (3.6.0)
55
61
  highline (2.1.0)
62
+ http (5.2.0)
63
+ addressable (~> 2.8)
64
+ base64 (~> 0.1)
65
+ http-cookie (~> 1.0)
66
+ http-form_data (~> 2.2)
67
+ llhttp-ffi (~> 0.5.0)
68
+ http-cookie (1.0.6)
69
+ domain_name (~> 0.5)
70
+ http-form_data (2.3.0)
56
71
  i18n (1.14.1)
57
72
  concurrent-ruby (~> 1.0)
58
73
  interception (0.5)
@@ -67,6 +82,9 @@ GEM
67
82
  rdoc
68
83
  semver
69
84
  jwt (2.7.0)
85
+ llhttp-ffi (0.5.0)
86
+ ffi-compiler (~> 1.0)
87
+ rake (~> 13.0)
70
88
  method_source (1.0.0)
71
89
  mini_portile2 (2.8.1)
72
90
  minitest (5.19.0)
@@ -145,6 +163,7 @@ GEM
145
163
  webrick (1.7.0)
146
164
  yard (0.9.28)
147
165
  webrick (~> 1.7.0)
166
+ zip (2.0.2)
148
167
 
149
168
  PLATFORMS
150
169
  ruby
@@ -153,6 +172,7 @@ DEPENDENCIES
153
172
  activesupport (>= 2.3.5)
154
173
  bundler (~> 2.1.4)
155
174
  faraday-retry (~> 1.0.3)
175
+ http
156
176
  juwelier (~> 2.1.0)
157
177
  octokit (~> 5.0)
158
178
  oj (~> 3.13.12)
@@ -166,6 +186,7 @@ DEPENDENCIES
166
186
  rdoc (~> 6.1)
167
187
  rspec (~> 3.5.0)
168
188
  simplecov
189
+ zip
169
190
 
170
191
  BUNDLED WITH
171
192
  2.1.4
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.11
1
+ 0.0.12
data/grade_runner.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: grade_runner 0.0.11 ruby lib
5
+ # stub: grade_runner 0.0.12 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "grade_runner".freeze
9
- s.version = "0.0.11"
9
+ s.version = "0.0.12".freeze
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Raghu Betina".freeze, "Jelani Woods".freeze]
14
- s.date = "2024-07-09"
14
+ s.date = "2024-07-30"
15
15
  s.description = "This gem runs your RSpec test suite and posts the JSON output to grades.firstdraft.com.".freeze
16
16
  s.email = ["raghu@firstdraft.com".freeze, "jelani@firstdraft.com".freeze]
17
17
  s.extra_rdoc_files = [
@@ -37,47 +37,27 @@ Gem::Specification.new do |s|
37
37
  ]
38
38
  s.homepage = "http://github.com/firstdraft/grade_runner".freeze
39
39
  s.licenses = ["MIT".freeze]
40
- s.rubygems_version = "3.1.6".freeze
40
+ s.rubygems_version = "3.5.16".freeze
41
41
  s.summary = "A Ruby client for [firstdraft Grades](https://grades.firstdraft.com)".freeze
42
42
 
43
- if s.respond_to? :specification_version then
44
- s.specification_version = 4
45
- end
43
+ s.specification_version = 4
46
44
 
47
- if s.respond_to? :add_runtime_dependency then
48
- s.add_runtime_dependency(%q<activesupport>.freeze, [">= 2.3.5"])
49
- s.add_runtime_dependency(%q<oj>.freeze, ["~> 3.13.12"])
50
- s.add_runtime_dependency(%q<octokit>.freeze, ["~> 5.0"])
51
- s.add_runtime_dependency(%q<faraday-retry>.freeze, ["~> 1.0.3"])
52
- s.add_runtime_dependency(%q<rake>.freeze, ["~> 13"])
53
- s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
54
- s.add_development_dependency(%q<rdoc>.freeze, ["~> 6.1"])
55
- s.add_development_dependency(%q<bundler>.freeze, ["~> 2.1.4"])
56
- s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
57
- s.add_development_dependency(%q<simplecov>.freeze, [">= 0"])
58
- s.add_development_dependency(%q<pry>.freeze, ["~> 0"])
59
- s.add_development_dependency(%q<pry-byebug>.freeze, ["~> 3"])
60
- s.add_development_dependency(%q<pry-doc>.freeze, ["~> 0"])
61
- s.add_development_dependency(%q<pry-remote>.freeze, ["~> 0"])
62
- s.add_development_dependency(%q<pry-rescue>.freeze, ["~> 1"])
63
- s.add_development_dependency(%q<pry-stack_explorer>.freeze, ["~> 0"])
64
- else
65
- s.add_dependency(%q<activesupport>.freeze, [">= 2.3.5"])
66
- s.add_dependency(%q<oj>.freeze, ["~> 3.13.12"])
67
- s.add_dependency(%q<octokit>.freeze, ["~> 5.0"])
68
- s.add_dependency(%q<faraday-retry>.freeze, ["~> 1.0.3"])
69
- s.add_dependency(%q<rake>.freeze, ["~> 13"])
70
- s.add_dependency(%q<rspec>.freeze, ["~> 3.5.0"])
71
- s.add_dependency(%q<rdoc>.freeze, ["~> 6.1"])
72
- s.add_dependency(%q<bundler>.freeze, ["~> 2.1.4"])
73
- s.add_dependency(%q<juwelier>.freeze, ["~> 2.1.0"])
74
- s.add_dependency(%q<simplecov>.freeze, [">= 0"])
75
- s.add_dependency(%q<pry>.freeze, ["~> 0"])
76
- s.add_dependency(%q<pry-byebug>.freeze, ["~> 3"])
77
- s.add_dependency(%q<pry-doc>.freeze, ["~> 0"])
78
- s.add_dependency(%q<pry-remote>.freeze, ["~> 0"])
79
- s.add_dependency(%q<pry-rescue>.freeze, ["~> 1"])
80
- s.add_dependency(%q<pry-stack_explorer>.freeze, ["~> 0"])
81
- end
45
+ s.add_runtime_dependency(%q<activesupport>.freeze, [">= 2.3.5".freeze])
46
+ s.add_runtime_dependency(%q<oj>.freeze, ["~> 3.13.12".freeze])
47
+ s.add_runtime_dependency(%q<octokit>.freeze, ["~> 5.0".freeze])
48
+ s.add_runtime_dependency(%q<zip>.freeze, [">= 0".freeze])
49
+ s.add_runtime_dependency(%q<faraday-retry>.freeze, ["~> 1.0.3".freeze])
50
+ s.add_runtime_dependency(%q<rake>.freeze, ["~> 13".freeze])
51
+ s.add_development_dependency(%q<rspec>.freeze, ["~> 3.5.0".freeze])
52
+ s.add_development_dependency(%q<rdoc>.freeze, ["~> 6.1".freeze])
53
+ s.add_development_dependency(%q<bundler>.freeze, ["~> 2.1.4".freeze])
54
+ s.add_development_dependency(%q<juwelier>.freeze, ["~> 2.1.0".freeze])
55
+ s.add_development_dependency(%q<simplecov>.freeze, [">= 0".freeze])
56
+ s.add_development_dependency(%q<pry>.freeze, ["~> 0".freeze])
57
+ s.add_development_dependency(%q<pry-byebug>.freeze, ["~> 3".freeze])
58
+ s.add_development_dependency(%q<pry-doc>.freeze, ["~> 0".freeze])
59
+ s.add_development_dependency(%q<pry-remote>.freeze, ["~> 0".freeze])
60
+ s.add_development_dependency(%q<pry-rescue>.freeze, ["~> 1".freeze])
61
+ s.add_development_dependency(%q<pry-stack_explorer>.freeze, ["~> 0".freeze])
82
62
  end
83
63
 
data/lib/tasks/grade.rake CHANGED
@@ -2,6 +2,9 @@ require "active_support/core_ext/object/blank"
2
2
  require "grade_runner/runner"
3
3
  require "octokit"
4
4
  require "yaml"
5
+ require "zip"
6
+ require "fileutils"
7
+ require "open-uri"
5
8
 
6
9
  desc "Alias for \"grade:next\"."
7
10
  task grade: "grade:all" do
@@ -14,10 +17,11 @@ namespace :grade do
14
17
  input_token = ARGV[1]
15
18
  file_token = nil
16
19
 
17
- config_dir_name = find_or_create_config_dif
20
+ config_dir_name = find_or_create_directory(".vscode")
18
21
  config_file_name = "#{config_dir_name}/.ltici_apitoken.yml"
19
22
  student_config = {}
20
23
  student_config["submission_url"] = "https://grades.firstdraft.com"
24
+ student_config["github_username"] = retrieve_github_username
21
25
 
22
26
  if File.exist?(config_file_name)
23
27
  begin
@@ -47,7 +51,6 @@ namespace :grade do
47
51
  while new_personal_access_token == "" do
48
52
  print "> "
49
53
  new_personal_access_token = $stdin.gets.chomp.strip
50
-
51
54
  if new_personal_access_token!= "" && is_valid_token?(submission_url, new_personal_access_token) == false
52
55
  puts "Please enter valid token"
53
56
  new_personal_access_token = ""
@@ -67,17 +70,19 @@ namespace :grade do
67
70
  student_config["personal_access_token"] = nil
68
71
  update_config_file(config_file_name, student_config)
69
72
  puts "Your access token looked invalid, so we've reset it to be blank. Please re-run rails grade and, when asked, copy-paste your token carefully from the assignment page."
70
- else
71
- full_reponame = upstream_repo(submission_url, token)
73
+ else
74
+ resource_info = upstream_repo(submission_url, token)
75
+ full_reponame = resource_info.fetch("repo_slug")
76
+ remote_spec_folder_sha = resource_info.fetch("spec_folder_sha")
77
+ source_code_url = resource_info.fetch("source_code_url")
72
78
  set_upstream_remote(full_reponame)
73
- sync_specs_with_source(full_reponame)
79
+ sync_specs_with_source(full_reponame, remote_spec_folder_sha, source_code_url)
74
80
 
75
81
  path = File.join(project_root, "/tmp/output/#{Time.now.to_i}.json")
76
82
  `bin/rails db:migrate RAILS_ENV=test` if defined?(Rails)
77
83
  `RAILS_ENV=test bundle exec rspec --format JsonOutputFormatter --out #{path}`
78
84
  rspec_output_json = Oj.load(File.read(path))
79
- github_email = `git config user.email`.chomp
80
- username = github_username(github_email)
85
+ username = retrieve_github_username
81
86
  reponame = project_root.to_s.split("/").last
82
87
  sha = `git rev-parse HEAD`.slice(0..7)
83
88
 
@@ -102,12 +107,13 @@ namespace :grade do
102
107
 
103
108
  desc "Reset access token saved in YAML file."
104
109
  task :reset_token do
105
- config_dir_name = find_or_create_config_dif
110
+ config_dir_name = find_or_create_directory(".vscode")
106
111
  config_file_name = "#{config_dir_name}/.ltici_apitoken.yml"
107
112
  submission_url = "https://grades.firstdraft.com"
108
113
 
109
114
  student_config = {}
110
115
  student_config["submission_url"] = submission_url
116
+ student_config["github_username"] = retrieve_github_username
111
117
  puts "Enter your access token for this project"
112
118
  new_personal_access_token = ""
113
119
 
@@ -131,34 +137,62 @@ namespace :grade do
131
137
 
132
138
  end
133
139
 
134
- def sync_specs_with_source(full_reponame)
135
- if Octokit.repository?(full_reponame)
136
- repo_contents = Octokit.contents(full_reponame)
137
- remote_spec_folder = repo_contents.find { |git_object| git_object[:name] == 'spec' }
138
- if remote_spec_folder.blank?
139
- abort("The project #{full_reponame} does not have specs.")
140
- end
141
- remote_sha = remote_spec_folder[:sha]
142
- # Discard unstaged changes in spec folder
143
- `git checkout spec -q`
144
- `git clean spec -f -q`
145
- local_sha = `git ls-tree HEAD #{project_root.join('spec')}`.chomp.split[2]
146
-
147
- unless remote_sha == local_sha
148
- `git fetch upstream -q`
149
- # Remove local contents of spec folder
150
- `rm -rf spec/*`
151
- default_branch = `git remote show upstream | grep 'HEAD branch' | cut -d' ' -f5`.chomp
152
- # Overwrite local contents of spec folder with contents from upstream branch
153
- `git checkout upstream/#{default_branch} spec/ -q`
154
- # Unstage new spec file contents
155
- # - if wrong token is used, spec files can be removed properly when unstaged
156
- # - spec file changes committed by learner are removed and updated
157
- # - we are not committing spec file changes by default to avoid confusing the git history
158
- `git restore --staged spec/*`
140
+ def sync_specs_with_source(full_reponame, remote_sha, repo_url)
141
+ # Unstage staged changes in spec folder
142
+ `git restore --staged spec/* `
143
+ # Discard unstaged changes in spec folder
144
+ `git checkout spec -q`
145
+ `git clean spec -f -q`
146
+ local_sha = `git ls-tree HEAD #{project_root.join('spec')}`.chomp.split[2]
147
+
148
+ unless remote_sha == local_sha
149
+ find_or_create_directory("tmp")
150
+ find_or_create_directory("tmp/backup")
151
+ files_and_subfolders_inside_specs = Dir.glob("spec/*")
152
+ # Temporarily move specs
153
+ FileUtils.mv(files_and_subfolders_inside_specs, "tmp/backup")
154
+
155
+ download_file(repo_url, "tmp/spec.zip")
156
+ extracted_zip_folder = extract_zip("tmp/spec.zip", "tmp")
157
+ source_directory = extracted_zip_folder.join("spec")
158
+ overwrite_spec_folder(source_directory)
159
+
160
+ FileUtils.rm(project_root.join("tmp/spec.zip"))
161
+ FileUtils.rm_rf(extracted_zip_folder)
162
+ FileUtils.rm_rf("tmp/backup")
163
+ `git add spec/`
164
+ `git commit spec/ -m "Update spec/ folder to latest version" --author "First Draft <grades@firstdraft.com>"`
165
+ end
166
+ end
167
+
168
+ def download_file(url, destination)
169
+ download = URI.open(url)
170
+ IO.copy_stream(download, destination)
171
+ end
172
+
173
+ def extract_zip(folder, destination)
174
+ extracted_file_path = project_root.join(destination)
175
+ Zip::File.open(folder) do |zip_file|
176
+ zip_file.each_with_index do |file, index|
177
+ # Get name of root folder in zip file
178
+ if index == 0
179
+ extracted_file_path = extracted_file_path.join(file.name)
180
+ end
181
+ file_path = File.join(destination, file.name)
182
+ FileUtils.mkdir_p(File.dirname(file_path))
183
+ file.extract(file_path)
159
184
  end
160
- else
161
- abort("The project #{full_reponame} does not exist.")
185
+ end
186
+ extracted_file_path
187
+ end
188
+
189
+ def overwrite_spec_folder(source_directory)
190
+ destination_directory = "spec"
191
+ # Get all files in the source directory
192
+ files = Dir.glob("#{source_directory}/*")
193
+ # Move each file to the destination directory
194
+ files.each do |file|
195
+ FileUtils.mv(file, destination_directory)
162
196
  end
163
197
  end
164
198
 
@@ -175,10 +209,10 @@ def update_config_file(config_file_name, config)
175
209
  File.write(config_file_name, YAML.dump(config))
176
210
  end
177
211
 
178
- def find_or_create_config_dif
179
- config_dir_name = File.join(project_root, ".vscode")
180
- Dir.mkdir(config_dir_name) unless Dir.exist?(config_dir_name)
181
- config_dir_name
212
+ def find_or_create_directory(directory_name)
213
+ directory = File.join(project_root, directory_name)
214
+ Dir.mkdir(directory) unless Dir.exist?(directory)
215
+ directory
182
216
  end
183
217
 
184
218
  def is_valid_token?(root_url, token)
@@ -203,20 +237,29 @@ def upstream_repo(root_url, token)
203
237
  res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
204
238
  http.request(req)
205
239
  end
206
- result = Oj.load(res.body)
207
- result["repo_slug"]
240
+ Oj.load(res.body)
208
241
  rescue => e
209
242
  return false
210
243
  end
211
244
 
212
- def github_username(primary_email)
213
- return "" if primary_email.blank?
214
- username = `git config user.name`.chomp
215
- search_results = Octokit.search_users("#{primary_email} in:email").fetch(:items)
216
- if search_results.present?
217
- username = search_results.first.fetch(:login, username)
245
+ def retrieve_github_username
246
+ config_dir_name = find_or_create_directory(".vscode")
247
+ config_file_name = "#{config_dir_name}/.ltici_apitoken.yml"
248
+ if File.exist?(config_file_name)
249
+ config = YAML.load_file(config_file_name)
250
+ if config["github_username"].present?
251
+ return config["github_username"]
252
+ end
253
+ else
254
+ github_email = `git config user.email`.chomp
255
+ return "" if github_email.blank?
256
+ username = `git config user.name`.chomp
257
+ search_results = Octokit.search_users("#{github_email} in:email").fetch(:items)
258
+ if search_results.present?
259
+ username = search_results.first.fetch(:login, username)
260
+ end
261
+ return username
218
262
  end
219
- username
220
263
  end
221
264
 
222
265
  def project_root
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grade_runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raghu Betina
8
8
  - Jelani Woods
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-07-09 00:00:00.000000000 Z
12
+ date: 2024-08-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: '5.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: zip
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
56
70
  - !ruby/object:Gem::Dependency
57
71
  name: faraday-retry
58
72
  requirement: !ruby/object:Gem::Requirement
@@ -264,7 +278,7 @@ homepage: http://github.com/firstdraft/grade_runner
264
278
  licenses:
265
279
  - MIT
266
280
  metadata: {}
267
- post_install_message:
281
+ post_install_message:
268
282
  rdoc_options: []
269
283
  require_paths:
270
284
  - lib
@@ -279,8 +293,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
279
293
  - !ruby/object:Gem::Version
280
294
  version: '0'
281
295
  requirements: []
282
- rubygems_version: 3.4.6
283
- signing_key:
296
+ rubygems_version: 3.5.16
297
+ signing_key:
284
298
  specification_version: 4
285
299
  summary: A Ruby client for [firstdraft Grades](https://grades.firstdraft.com)
286
300
  test_files: []