grade_runner 0.0.10 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54341e166f0121e0e0c49b298ffab7fdb9c288b769e432a25103da828d0340a3
4
- data.tar.gz: 743765e6cefe82977460154250c9abf8f5dbb4d00cb5a3a8c22eb3a888a5d16c
3
+ metadata.gz: 4d69d4bf6d04b43a1158cee76f3226460f25df5ed22c2ef51923d457edd6fba9
4
+ data.tar.gz: 5b3b6fe6ca5cefb53e9c03637564ec265d13fff47e0ace72416f87e5c46882e2
5
5
  SHA512:
6
- metadata.gz: 91dbca294ec84fe7e1efd7dab82fbf827c61a86f7bb4bf54199ccd505efd1141a83246f326ca8a3aac9d5310a8d444da547cabc1a39b15eb6fe088a88bba703e
7
- data.tar.gz: 6347b18ff8ca7b3c806511a5b054019729fe40327e4f02c2f9bdb3061686312c8278bd5ab94c0ab32f6445785fd5392a972b995c6cf7bcbf097d978b37b9a82b
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.10
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.10 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.10"
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
- `RAILS_ENV=test bundle exec rspec --order default --format JsonOutputFormatter --out #{path}`
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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grade_runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Raghu Betina
@@ -9,7 +9,7 @@ authors:
9
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
@@ -279,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
279
293
  - !ruby/object:Gem::Version
280
294
  version: '0'
281
295
  requirements: []
282
- rubygems_version: 3.1.6
296
+ rubygems_version: 3.5.16
283
297
  signing_key:
284
298
  specification_version: 4
285
299
  summary: A Ruby client for [firstdraft Grades](https://grades.firstdraft.com)