Merge remote-tracking branch 'origin/master' into exercise-anomaly-detection
# Conflicts: # Capfile # Gemfile.lock # db/schema.rb
29
.travis.yml
@ -5,20 +5,18 @@ services:
|
||||
|
||||
addons:
|
||||
code_climate:
|
||||
repo_token: 53a2c2608c848714e96f6a1fc0365dcfdfec051f7827d50cea965ea625f49734
|
||||
postgresql: "9.5"
|
||||
repo_token:
|
||||
secure: "cZoMNjQKB/D7W4B7JDk9PXooy2WCDypu7R4C/Vi0DziZCU9HRwLbdt9aoH5hgHFa7Fe2rHFgflPAAP7h698ozvP0waFtPqLAj+PbEt27LbBDvW8JcvNkKXA0rj5wyTkzuc/0kD+kPB4oDXMak6gZlB9HCJDsa3kdXScQGTVuPdU="
|
||||
postgresql: "9.6"
|
||||
|
||||
before_install:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
# Config to run docker tests - doesn't work so far
|
||||
# - sudo apt-get update
|
||||
# - sudo apt-get upgrade lxc-docker
|
||||
# - echo 'DOCKER_OPTS="-H tcp://127.0.0.1:4243 -H unix:///var/run/docker.sock --iptables=false"' | sudo tee /etc/default/docker > /dev/null
|
||||
# - export DOCKER_HOST=tcp://192.168.23.75:2375
|
||||
# - sudo service docker restart
|
||||
# - sleep 5
|
||||
# - docker pull openhpi/docker_ruby
|
||||
- echo 'DOCKER_OPTS="-H tcp://127.0.0.1:2376 -H unix:///var/run/docker.sock --iptables=false"' | sudo tee /etc/default/docker > /dev/null
|
||||
- sudo service docker restart
|
||||
- sleep 5
|
||||
- docker pull openhpi/co_execenv_python
|
||||
- docker pull openhpi/co_execenv_java
|
||||
|
||||
before_script:
|
||||
- cp .rspec.travis .rspec
|
||||
@ -26,18 +24,13 @@ before_script:
|
||||
- cp config/code_ocean.yml.travis config/code_ocean.yml
|
||||
- cp config/database.yml.travis config/database.yml
|
||||
- cp config/secrets.yml.travis config/secrets.yml
|
||||
- cp config/docker.yml.erb.travis config/docker.yml.erb
|
||||
- psql --command='CREATE DATABASE travis_ci_test;' --username=postgres
|
||||
- bundle exec rake db:schema:load RAILS_ENV=test
|
||||
|
||||
cache: bundler
|
||||
language: ruby
|
||||
rvm:
|
||||
- 2.3.1
|
||||
# - 2.1.5
|
||||
# - 2.2.1
|
||||
- 2.3.6
|
||||
|
||||
script: bundle exec rspec --color --format documentation --require spec_helper --require rails_helper --tag ~docker
|
||||
# one of the solutions I've found
|
||||
# - sudo docker run --rm=true -v `pwd`:/ansible-apache:rw weldpua2008/docker-ansible:${OS_TYPE}${OS_VERSION}_v${ANSIBLE_VERSION} /bin/bash -c "/ansible-apache/tests/test-in-docker-image.sh ${OS_TYPE} ${OS_VERSION} ${ANSIBLE_VERSION}"
|
||||
|
||||
|
||||
script: bundle exec rspec --color --format documentation --require spec_helper --require rails_helper && bundle exec codeclimate-test-reporter
|
||||
|
7
Capfile
@ -1,8 +1,13 @@
|
||||
require 'capistrano/setup'
|
||||
require 'capistrano/deploy'
|
||||
require 'capistrano/scm/git'
|
||||
require 'capistrano/puma'
|
||||
require 'capistrano/puma/nginx'
|
||||
require 'capistrano/rails'
|
||||
require 'capistrano/rvm'
|
||||
require 'capistrano/upload-config'
|
||||
require "whenever/capistrano"
|
||||
require 'whenever/capistrano'
|
||||
|
||||
install_plugin Capistrano::SCM::Git
|
||||
install_plugin Capistrano::Puma
|
||||
install_plugin Capistrano::Puma::Nginx
|
||||
|
41
Gemfile
@ -1,42 +1,43 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'activerecord-jdbcpostgresql-adapter', platform: :jruby
|
||||
gem 'bcrypt', '~> 3.1.7'
|
||||
gem 'bcrypt'
|
||||
gem 'bootstrap-will_paginate'
|
||||
gem 'carrierwave'
|
||||
gem 'coffee-rails', '~> 4.0.0'
|
||||
gem 'concurrent-ruby', '~> 1.0.1'
|
||||
gem 'concurrent-ruby-ext', '~> 1.0.1', platform: :ruby
|
||||
gem 'docker-api','~> 1.25.0', require: 'docker'
|
||||
gem 'factory_bot_rails', '~> 4.8.2'
|
||||
gem 'coffee-rails'
|
||||
gem 'concurrent-ruby'
|
||||
gem 'concurrent-ruby-ext', platform: :ruby
|
||||
gem 'docker-api', require: 'docker'
|
||||
gem 'factory_bot_rails'
|
||||
gem 'forgery'
|
||||
gem 'highline'
|
||||
gem 'jbuilder', '~> 2.0'
|
||||
gem 'jbuilder'
|
||||
gem 'jquery-rails'
|
||||
gem 'jquery-turbolinks'
|
||||
gem 'ims-lti'
|
||||
gem 'ims-lti', '1.1.10' # version 1.1.13 will crash, because @provider.valid_request?(request) on lti.rb line 89 will return false.
|
||||
gem 'kramdown'
|
||||
gem 'newrelic_rpm'
|
||||
gem 'pg', platform: :ruby
|
||||
gem 'pg', '< 1.0', platform: :ruby
|
||||
gem 'pry-byebug'
|
||||
gem 'puma', '~> 2.15.3'
|
||||
gem 'puma'
|
||||
gem 'pundit'
|
||||
gem 'rails', '4.2.5'
|
||||
gem 'rails-i18n', '~> 4.0.0'
|
||||
gem 'rails', '4.2.10'
|
||||
gem 'rails-i18n'
|
||||
gem 'ransack'
|
||||
gem 'rubytree'
|
||||
gem 'sass-rails', '~> 4.0.3'
|
||||
gem 'sdoc', '~> 0.4.0', group: :doc
|
||||
gem 'sass-rails'
|
||||
gem 'sdoc', group: :doc
|
||||
gem 'slim'
|
||||
gem 'bootstrap_pagedown'
|
||||
gem 'pagedown-rails', '~> 1.1.4'
|
||||
gem 'pagedown-rails'
|
||||
gem 'sorcery'
|
||||
gem 'thread_safe'
|
||||
gem 'turbolinks'
|
||||
gem 'uglifier', '>= 1.3.0'
|
||||
gem 'will_paginate', '~> 3.0'
|
||||
gem 'turbolinks', '< 5.0.0' # newer versions prevent loading ACE if the page containing is not accessed directly / refreshed
|
||||
gem 'uglifier'
|
||||
gem 'will_paginate'
|
||||
gem 'tubesock'
|
||||
gem 'faye-websocket'
|
||||
gem 'eventmachine', '1.0.9.1' # explicitly added, this is used by faye-websocket, version 1.2.5 still has an error in eventmachine.rb:202: [BUG] Segmentation fault, which is not yet fixed and causes the whole ruby process to crash
|
||||
gem 'nokogiri'
|
||||
gem 'd3-rails'
|
||||
gem 'rest-client'
|
||||
@ -46,7 +47,7 @@ gem 'whenever', require: false
|
||||
group :development, :staging do
|
||||
gem 'better_errors', platform: :ruby
|
||||
gem 'binding_of_caller', platform: :ruby
|
||||
gem 'capistrano', '~> 3.3.0'
|
||||
gem 'capistrano'
|
||||
gem 'capistrano3-puma'
|
||||
gem 'capistrano-rails'
|
||||
gem 'capistrano-rvm'
|
||||
@ -54,7 +55,7 @@ group :development, :staging do
|
||||
gem 'rack-mini-profiler'
|
||||
gem 'rubocop', require: false
|
||||
gem 'rubocop-rspec'
|
||||
gem 'web-console', '~> 2.0', platform: :ruby
|
||||
gem 'web-console', platform: :ruby
|
||||
end
|
||||
|
||||
group :development, :test, :staging do
|
||||
|
162
Gemfile.lock
@ -2,43 +2,42 @@ GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
ZenTest (4.11.0)
|
||||
actionmailer (4.2.5)
|
||||
actionpack (= 4.2.5)
|
||||
actionview (= 4.2.5)
|
||||
activejob (= 4.2.5)
|
||||
actionmailer (4.2.10)
|
||||
actionpack (= 4.2.10)
|
||||
actionview (= 4.2.10)
|
||||
activejob (= 4.2.10)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.5)
|
||||
actionview (= 4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
actionpack (4.2.10)
|
||||
actionview (= 4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
rack (~> 1.6)
|
||||
rack-test (~> 0.6.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
actionview (4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
activejob (4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
activejob (4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
globalid (>= 0.3.0)
|
||||
activemodel (4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
activemodel (4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.5)
|
||||
activemodel (= 4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
activerecord (4.2.10)
|
||||
activemodel (= 4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
arel (~> 6.0)
|
||||
activerecord-jdbc-adapter (1.3.19)
|
||||
activerecord (>= 2.2)
|
||||
activerecord-jdbcpostgresql-adapter (1.3.19)
|
||||
activerecord-jdbc-adapter (~> 1.3.19)
|
||||
jdbc-postgres (>= 9.1)
|
||||
activesupport (4.2.5)
|
||||
activesupport (4.2.10)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
@ -59,7 +58,7 @@ GEM
|
||||
will_paginate
|
||||
bootstrap_pagedown (1.1.0)
|
||||
rails (>= 3.2)
|
||||
builder (3.2.2)
|
||||
builder (3.2.3)
|
||||
byebug (8.2.2)
|
||||
capistrano (3.3.5)
|
||||
capistrano-stats (~> 1.1.0)
|
||||
@ -110,6 +109,7 @@ GEM
|
||||
concurrent-ruby (1.0.2-java)
|
||||
concurrent-ruby-ext (1.0.2)
|
||||
concurrent-ruby (~> 1.0.2)
|
||||
crass (1.0.3)
|
||||
d3-rails (3.5.11)
|
||||
railties (>= 3.1)
|
||||
database_cleaner (1.5.1)
|
||||
@ -139,13 +139,14 @@ GEM
|
||||
ffi (1.9.10)
|
||||
ffi (1.9.10-java)
|
||||
forgery (0.6.0)
|
||||
globalid (0.3.7)
|
||||
activesupport (>= 4.1.0)
|
||||
globalid (0.4.1)
|
||||
activesupport (>= 4.2.0)
|
||||
highline (1.7.8)
|
||||
hike (1.2.3)
|
||||
http-cookie (1.0.2)
|
||||
domain_name (~> 0.5)
|
||||
i18n (0.7.0)
|
||||
i18n (0.9.5)
|
||||
concurrent-ruby (~> 1.0)
|
||||
ims-lti (1.1.10)
|
||||
builder
|
||||
oauth (~> 0.4.5)
|
||||
@ -159,19 +160,21 @@ GEM
|
||||
jquery-turbolinks (2.1.0)
|
||||
railties (>= 3.1.0)
|
||||
turbolinks
|
||||
json (1.8.3)
|
||||
json (1.8.3-java)
|
||||
json (1.8.6)
|
||||
json (1.8.6-java)
|
||||
jwt (1.5.1)
|
||||
kramdown (1.9.0)
|
||||
loofah (2.0.3)
|
||||
loofah (2.2.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.6.4)
|
||||
mime-types (>= 1.16, < 4)
|
||||
mail (2.7.0)
|
||||
mini_mime (>= 0.1.1)
|
||||
method_source (0.8.2)
|
||||
mime-types (2.99.3)
|
||||
mini_portile2 (2.1.0)
|
||||
minitest (5.10.1)
|
||||
multi_json (1.12.1)
|
||||
mini_mime (1.0.0)
|
||||
mini_portile2 (2.3.0)
|
||||
minitest (5.11.3)
|
||||
multi_json (1.13.1)
|
||||
multi_xml (0.5.5)
|
||||
multipart-post (2.0.0)
|
||||
net-scp (1.2.1)
|
||||
@ -179,9 +182,9 @@ GEM
|
||||
net-ssh (3.0.2)
|
||||
netrc (0.10.3)
|
||||
newrelic_rpm (3.14.3.313)
|
||||
nokogiri (1.7.0.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
nokogiri (1.7.0.1-java)
|
||||
nokogiri (1.8.2)
|
||||
mini_portile2 (~> 2.3.0)
|
||||
nokogiri (1.8.2-java)
|
||||
nyan-cat-formatter (0.11)
|
||||
rspec (>= 2.99, >= 2.14.2, < 4)
|
||||
oauth (0.4.7)
|
||||
@ -203,6 +206,11 @@ GEM
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
slop (~> 3.4)
|
||||
pry (0.10.3-java)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.8.1)
|
||||
slop (~> 3.4)
|
||||
spoon (~> 0.0)
|
||||
pry-byebug (3.3.0)
|
||||
byebug (~> 8.0)
|
||||
pry (~> 0.10)
|
||||
@ -210,26 +218,26 @@ GEM
|
||||
puma (2.15.3-java)
|
||||
pundit (1.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
rack (1.6.5)
|
||||
rack (1.6.9)
|
||||
rack-mini-profiler (0.10.1)
|
||||
rack (>= 1.2.0)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.2.5)
|
||||
actionmailer (= 4.2.5)
|
||||
actionpack (= 4.2.5)
|
||||
actionview (= 4.2.5)
|
||||
activejob (= 4.2.5)
|
||||
activemodel (= 4.2.5)
|
||||
activerecord (= 4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
rails (4.2.10)
|
||||
actionmailer (= 4.2.10)
|
||||
actionpack (= 4.2.10)
|
||||
actionview (= 4.2.10)
|
||||
activejob (= 4.2.10)
|
||||
activemodel (= 4.2.10)
|
||||
activerecord (= 4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.5)
|
||||
railties (= 4.2.10)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.8)
|
||||
activesupport (>= 4.2.0.beta, < 5.0)
|
||||
rails-dom-testing (1.0.9)
|
||||
activesupport (>= 4.2.0, < 5.0)
|
||||
nokogiri (~> 1.6)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
@ -237,13 +245,13 @@ GEM
|
||||
rails-i18n (4.0.8)
|
||||
i18n (~> 0.7)
|
||||
railties (~> 4.0)
|
||||
railties (4.2.5)
|
||||
actionpack (= 4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
railties (4.2.10)
|
||||
actionpack (= 4.2.10)
|
||||
activesupport (= 4.2.10)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rainbow (2.2.1)
|
||||
rake (12.0.0)
|
||||
rake (12.3.0)
|
||||
ransack (1.7.0)
|
||||
actionpack (>= 3.0)
|
||||
activerecord (>= 3.0)
|
||||
@ -319,6 +327,8 @@ GEM
|
||||
bcrypt (~> 3.1)
|
||||
oauth (~> 0.4, >= 0.4.4)
|
||||
oauth2 (>= 0.8.0)
|
||||
spoon (0.0.6)
|
||||
ffi
|
||||
spring (1.6.3)
|
||||
sprockets (2.12.4)
|
||||
hike (~> 1.2)
|
||||
@ -334,16 +344,16 @@ GEM
|
||||
net-ssh (>= 2.8.0)
|
||||
structured_warnings (0.2.0)
|
||||
temple (0.7.6)
|
||||
thor (0.19.4)
|
||||
thread_safe (0.3.5)
|
||||
thread_safe (0.3.5-java)
|
||||
thor (0.20.0)
|
||||
thread_safe (0.3.6)
|
||||
thread_safe (0.3.6-java)
|
||||
tilt (1.4.1)
|
||||
tubesock (0.2.5)
|
||||
rack (>= 1.5.0)
|
||||
websocket (>= 1.1.0)
|
||||
turbolinks (2.5.3)
|
||||
coffee-rails
|
||||
tzinfo (1.2.2)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (2.7.2)
|
||||
execjs (>= 0.3.0)
|
||||
@ -377,13 +387,13 @@ PLATFORMS
|
||||
DEPENDENCIES
|
||||
activerecord-jdbcpostgresql-adapter
|
||||
autotest-rails
|
||||
bcrypt (~> 3.1.7)
|
||||
bcrypt
|
||||
better_errors
|
||||
binding_of_caller
|
||||
bootstrap-will_paginate
|
||||
bootstrap_pagedown
|
||||
byebug
|
||||
capistrano (~> 3.3.0)
|
||||
capistrano
|
||||
capistrano-rails
|
||||
capistrano-rvm
|
||||
capistrano-upload-config
|
||||
@ -391,32 +401,33 @@ DEPENDENCIES
|
||||
capybara
|
||||
carrierwave
|
||||
codeclimate-test-reporter
|
||||
coffee-rails (~> 4.0.0)
|
||||
concurrent-ruby (~> 1.0.1)
|
||||
concurrent-ruby-ext (~> 1.0.1)
|
||||
coffee-rails
|
||||
concurrent-ruby
|
||||
concurrent-ruby-ext
|
||||
d3-rails
|
||||
database_cleaner
|
||||
docker-api (~> 1.25.0)
|
||||
factory_bot_rails (~> 4.8.2)
|
||||
docker-api
|
||||
eventmachine (= 1.0.9.1)
|
||||
factory_bot_rails
|
||||
faye-websocket
|
||||
forgery
|
||||
highline
|
||||
ims-lti
|
||||
jbuilder (~> 2.0)
|
||||
ims-lti (= 1.1.10)
|
||||
jbuilder
|
||||
jquery-rails
|
||||
jquery-turbolinks
|
||||
kramdown
|
||||
newrelic_rpm
|
||||
nokogiri
|
||||
nyan-cat-formatter
|
||||
pagedown-rails (~> 1.1.4)
|
||||
pg
|
||||
pagedown-rails
|
||||
pg (< 1.0)
|
||||
pry-byebug
|
||||
puma (~> 2.15.3)
|
||||
puma
|
||||
pundit
|
||||
rack-mini-profiler
|
||||
rails (= 4.2.5)
|
||||
rails-i18n (~> 4.0.0)
|
||||
rails (= 4.2.10)
|
||||
rails-i18n
|
||||
rake
|
||||
ransack
|
||||
rest-client
|
||||
@ -426,8 +437,8 @@ DEPENDENCIES
|
||||
rubocop-rspec
|
||||
rubytree
|
||||
rubyzip
|
||||
sass-rails (~> 4.0.3)
|
||||
sdoc (~> 0.4.0)
|
||||
sass-rails
|
||||
sdoc
|
||||
selenium-webdriver
|
||||
simplecov
|
||||
slim
|
||||
@ -435,8 +446,11 @@ DEPENDENCIES
|
||||
spring
|
||||
thread_safe
|
||||
tubesock
|
||||
turbolinks
|
||||
uglifier (>= 1.3.0)
|
||||
web-console (~> 2.0)
|
||||
turbolinks (< 5.0.0)
|
||||
uglifier
|
||||
web-console
|
||||
whenever
|
||||
will_paginate (~> 3.0)
|
||||
will_paginate
|
||||
|
||||
BUNDLED WITH
|
||||
1.16.1
|
||||
|
@ -26,4 +26,4 @@
|
||||
//= require markdown.converter
|
||||
//= require markdown.sanitizer
|
||||
//= require markdown.editor
|
||||
//= require ../../../vendor/assets/javascripts/ace/ext-language_tools
|
||||
//= require ace/ext-language_tools
|
@ -3,7 +3,7 @@
|
||||
}
|
||||
|
||||
.chosen-container {
|
||||
width: 100% !important;
|
||||
width: 250px !important;
|
||||
}
|
||||
|
||||
.code-field {
|
||||
|
@ -9,7 +9,7 @@ module SubmissionScoring
|
||||
assessment = assessor.assess(output)
|
||||
passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0))
|
||||
testrun_output = passed ? nil : 'message: ' + output[:message].to_s + "\n stdout: " + output[:stdout].to_s + "\n stderr: " + output[:stderr].to_s
|
||||
if !testrun_output.blank?
|
||||
unless testrun_output.blank?
|
||||
submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(testrun_output)
|
||||
@ -47,6 +47,14 @@ module SubmissionScoring
|
||||
end
|
||||
end
|
||||
submission.update(score: score)
|
||||
if submission.normalized_score == 1.0
|
||||
Thread.new do
|
||||
RequestForComment.where(exercise_id: submission.exercise_id, user_id: submission.user_id, user_type: submission.user_type).each{ |rfc|
|
||||
rfc.full_score_reached = true
|
||||
rfc.save
|
||||
}
|
||||
end
|
||||
end
|
||||
outputs
|
||||
end
|
||||
end
|
||||
|
@ -416,6 +416,9 @@ class ExercisesController < ApplicationController
|
||||
flash[:notice] = I18n.t('exercises.submit.full_score_redirect_to_rfc')
|
||||
flash.keep(:notice)
|
||||
|
||||
# increase counter 'times_featured' in rfc
|
||||
rfc.increment!(:times_featured)
|
||||
|
||||
respond_to do |format|
|
||||
format.html {redirect_to(rfc)}
|
||||
format.json {render(json: {redirect: url_for(rfc)})}
|
||||
|
@ -14,46 +14,40 @@ class RequestForCommentsController < ApplicationController
|
||||
def index
|
||||
@search = RequestForComment
|
||||
.last_per_user(2)
|
||||
.joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
left outer join "files" f on f.context_id = s.id
|
||||
left outer join "comments" on comments.file_id = f.id')
|
||||
.group('request_for_comments.id, request_for_comments.user_id, request_for_comments.exercise_id,
|
||||
request_for_comments.file_id, request_for_comments.question, request_for_comments.created_at,
|
||||
request_for_comments.updated_at, request_for_comments.user_type, request_for_comments.solved,
|
||||
request_for_comments.submission_id, request_for_comments.row_number') # ugly, but rails wants it this way
|
||||
.select('request_for_comments.*, max(comments.updated_at) as last_comment')
|
||||
.with_last_activity
|
||||
.search(params[:q])
|
||||
@request_for_comments = @search.result.order('created_at DESC').paginate(page: params[:page], total_entries: @search.result.length)
|
||||
@request_for_comments = @search.result
|
||||
.order('created_at DESC')
|
||||
.paginate(page: params[:page], total_entries: @search.result.length)
|
||||
authorize!
|
||||
end
|
||||
|
||||
# GET /my_request_for_comments
|
||||
def get_my_comment_requests
|
||||
@search = RequestForComment
|
||||
.with_last_activity
|
||||
.where(user_id: current_user.id)
|
||||
.joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
left outer join "files" f on f.context_id = s.id
|
||||
left outer join "comments" on comments.file_id = f.id')
|
||||
.group('request_for_comments.id')
|
||||
.select('request_for_comments.*, max(comments.updated_at) as last_comment')
|
||||
.search(params[:q])
|
||||
@request_for_comments = @search.result.order('created_at DESC').paginate(page: params[:page])
|
||||
@request_for_comments = @search.result
|
||||
.order('created_at DESC')
|
||||
.paginate(page: params[:page])
|
||||
render 'index'
|
||||
end
|
||||
|
||||
# GET /my_rfc_activity
|
||||
def get_rfcs_with_my_comments
|
||||
@search = RequestForComment
|
||||
.with_last_activity
|
||||
.joins(:comments) # we don't need to outer join here, because we know the user has commented on these
|
||||
.where(comments: {user_id: current_user.id})
|
||||
.joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
left outer join "files" f on f.context_id = s.id
|
||||
left outer join "comments" as c on c.file_id = f.id')
|
||||
.group('request_for_comments.id')
|
||||
.select('request_for_comments.*, max(c.updated_at) as last_comment')
|
||||
.search(params[:q])
|
||||
@request_for_comments = @search.result.order('last_comment DESC').paginate(page: params[:page])
|
||||
@request_for_comments = @search.result
|
||||
.order('last_comment DESC')
|
||||
.paginate(page: params[:page])
|
||||
render 'index'
|
||||
end
|
||||
|
||||
# GET /request_for_comments/1/mark_as_solved
|
||||
def mark_as_solved
|
||||
authorize!
|
||||
@request_for_comment.solved = true
|
||||
@ -66,6 +60,7 @@ class RequestForCommentsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# POST /request_for_comments/1/set_thank_you_note
|
||||
def set_thank_you_note
|
||||
authorize!
|
||||
@request_for_comment.thank_you_note = params[:note]
|
||||
@ -82,10 +77,6 @@ class RequestForCommentsController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def submit
|
||||
|
||||
end
|
||||
|
||||
# GET /request_for_comments/1
|
||||
# GET /request_for_comments/1.json
|
||||
def show
|
||||
@ -146,10 +137,6 @@ class RequestForCommentsController < ApplicationController
|
||||
authorize!
|
||||
end
|
||||
|
||||
def comment_params
|
||||
params.permit(:exercise_id, :feedback_text).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
end
|
||||
|
||||
private
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_request_for_comment
|
||||
@ -162,4 +149,8 @@ class RequestForCommentsController < ApplicationController
|
||||
params.require(:request_for_comment).permit(:exercise_id, :file_id, :question, :requested_at, :solved, :submission_id).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
end
|
||||
|
||||
def comment_params
|
||||
params.permit(:exercise_id, :feedback_text).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -202,21 +202,11 @@ class SubmissionsController < ApplicationController
|
||||
tubesock.close
|
||||
end
|
||||
|
||||
def extract_errors
|
||||
if !@message_buffer.blank?
|
||||
@submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(@message_buffer)
|
||||
StructuredError.create_from_template(template, @message_buffer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def handle_message(message, tubesock, container)
|
||||
@run_output ||= ""
|
||||
@raw_output ||= ''
|
||||
@run_output ||= ''
|
||||
# Handle special commands first
|
||||
if (/^#exit/.match(message))
|
||||
if /^#exit/.match(message)
|
||||
# Just call exit_container on the docker_client.
|
||||
# Do not call kill_socket for the websocket to the client here.
|
||||
# @docker_client.exit_container closes the socket to the container,
|
||||
@ -228,17 +218,17 @@ class SubmissionsController < ApplicationController
|
||||
# Filter out information about run_command, test_command, user or working directory
|
||||
run_command = @submission.execution_environment.run_command % command_substitutions(params[:filename])
|
||||
test_command = @submission.execution_environment.test_command % command_substitutions(params[:filename])
|
||||
if !(/root|workspace|#{run_command}|#{test_command}/.match(message))
|
||||
unless /root|workspace|#{run_command}|#{test_command}/.match(message)
|
||||
parse_message(message, 'stdout', tubesock)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def parse_message(message, output_stream, socket, recursive = true)
|
||||
parsed = '';
|
||||
parsed = ''
|
||||
begin
|
||||
parsed = JSON.parse(message)
|
||||
if(parsed.class == Hash && parsed.key?('cmd'))
|
||||
if parsed.class == Hash and parsed.key?('cmd')
|
||||
socket.send_data message
|
||||
Rails.logger.info('parse_message sent: ' + message)
|
||||
else
|
||||
@ -248,24 +238,24 @@ class SubmissionsController < ApplicationController
|
||||
end
|
||||
rescue JSON::ParserError => e
|
||||
# Check wether the message contains multiple lines, if true try to parse each line
|
||||
if ((recursive == true) && (message.include? "\n"))
|
||||
if recursive and message.include? "\n"
|
||||
for part in message.split("\n")
|
||||
self.parse_message(part,output_stream,socket,false)
|
||||
end
|
||||
elsif(message.include? "<img")
|
||||
elsif message.include? '<img'
|
||||
#Rails.logger.info('img foung')
|
||||
@buffering = true
|
||||
@buffer = ""
|
||||
@buffer = ''
|
||||
@buffer += message
|
||||
#Rails.logger.info('Starting to buffer')
|
||||
elsif(@buffering && (message.include? "/>"))
|
||||
elsif @buffering and message.include? '/>'
|
||||
@buffer += message
|
||||
parsed = {'cmd'=>'write','stream'=>output_stream,'data'=>@buffer}
|
||||
socket.send_data JSON.dump(parsed)
|
||||
#socket.send_data @buffer
|
||||
@buffering = false
|
||||
#Rails.logger.info('Sent complete buffer')
|
||||
elsif(@buffering)
|
||||
elsif @buffering
|
||||
@buffer += message
|
||||
#Rails.logger.info('Appending to buffer')
|
||||
else
|
||||
@ -275,18 +265,30 @@ class SubmissionsController < ApplicationController
|
||||
Rails.logger.info('parse_message sent: ' + JSON.dump(parsed))
|
||||
end
|
||||
ensure
|
||||
@raw_output += parsed['data'] if parsed.class == Hash and parsed.key? 'data'
|
||||
# save the data that was send to the run_output if there is enough space left. this will be persisted as a testrun with cause "run"
|
||||
@run_output += JSON.dump(parsed) if @run_output.size <= max_run_output_buffer_size
|
||||
end
|
||||
end
|
||||
|
||||
def save_run_output
|
||||
if !@run_output.blank?
|
||||
unless @run_output.blank?
|
||||
@run_output = @run_output[(0..max_run_output_buffer_size-1)] # trim the string to max_message_buffer_size chars
|
||||
Testrun.create(file: @file, cause: 'run', submission: @submission, output: @run_output)
|
||||
end
|
||||
end
|
||||
|
||||
def extract_errors
|
||||
unless @raw_output.blank?
|
||||
@submission.exercise.execution_environment.error_templates.each do |template|
|
||||
pattern = Regexp.new(template.signature).freeze
|
||||
if pattern.match(@raw_output)
|
||||
StructuredError.create_from_template(template, @raw_output, @submission)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def score
|
||||
hijack do |tubesock|
|
||||
Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive?
|
||||
|
@ -47,7 +47,7 @@ class ExecutionEnvironment < ActiveRecord::Base
|
||||
private :validate_docker_image?
|
||||
|
||||
def working_docker_image?
|
||||
DockerClient.pull(docker_image) unless DockerClient.image_tags.include?(docker_image)
|
||||
DockerClient.pull(docker_image) unless DockerClient.find_image_by_tag(docker_image).blank?
|
||||
output = DockerClient.new(execution_environment: self).execute_arbitrary_command(VALIDATION_COMMAND)
|
||||
errors.add(:docker_image, "error: #{output[:stderr]}") if output[:stderr].present?
|
||||
rescue DockerClient::Error => error
|
||||
|
@ -10,7 +10,13 @@ class RequestForComment < ActiveRecord::Base
|
||||
scope :unsolved, -> { where(solved: [false, nil]) }
|
||||
|
||||
def self.last_per_user(n = 5)
|
||||
from("(#{row_number_user_sql}) as request_for_comments").where("row_number <= ?", n)
|
||||
from("(#{row_number_user_sql}) as request_for_comments")
|
||||
.where("row_number <= ?", n)
|
||||
.group('request_for_comments.id, request_for_comments.user_id, request_for_comments.exercise_id,
|
||||
request_for_comments.file_id, request_for_comments.question, request_for_comments.created_at,
|
||||
request_for_comments.updated_at, request_for_comments.user_type, request_for_comments.solved,
|
||||
request_for_comments.full_score_reached, request_for_comments.submission_id, request_for_comments.row_number')
|
||||
# ugly, but necessary
|
||||
end
|
||||
|
||||
# not used right now, finds the last submission for the respective user and exercise.
|
||||
@ -46,12 +52,20 @@ class RequestForComment < ActiveRecord::Base
|
||||
commenters.uniq {|user| user.id}
|
||||
end
|
||||
|
||||
def self.with_last_activity
|
||||
self.joins('join "submissions" s on s.id = request_for_comments.submission_id
|
||||
left outer join "files" f on f.context_id = s.id
|
||||
left outer join "comments" c on c.file_id = f.id')
|
||||
.group('request_for_comments.id')
|
||||
.select('request_for_comments.*, max(c.updated_at) as last_comment')
|
||||
end
|
||||
|
||||
def to_s
|
||||
"RFC-" + self.id.to_s
|
||||
end
|
||||
|
||||
private
|
||||
def self.row_number_user_sql
|
||||
select("id, user_id, exercise_id, file_id, question, created_at, updated_at, user_type, solved, submission_id, row_number() OVER (PARTITION BY user_id ORDER BY created_at DESC) as row_number").to_sql
|
||||
select("id, user_id, exercise_id, file_id, question, created_at, updated_at, user_type, solved, full_score_reached, submission_id, row_number() OVER (PARTITION BY user_id ORDER BY created_at DESC) as row_number").to_sql
|
||||
end
|
||||
end
|
||||
|
@ -1,9 +1,10 @@
|
||||
class StructuredError < ActiveRecord::Base
|
||||
belongs_to :error_template
|
||||
belongs_to :submission
|
||||
belongs_to :file, class_name: 'CodeOcean::File'
|
||||
|
||||
def self.create_from_template(template, message_buffer)
|
||||
instance = self.create(error_template: template)
|
||||
def self.create_from_template(template, message_buffer, submission)
|
||||
instance = self.create(error_template: template, submission: submission)
|
||||
template.error_template_attributes.each do |attribute|
|
||||
StructuredErrorAttribute.create_from_template(attribute, instance, message_buffer)
|
||||
end
|
||||
|
@ -3,15 +3,13 @@ class StructuredErrorAttribute < ActiveRecord::Base
|
||||
belongs_to :error_template_attribute
|
||||
|
||||
def self.create_from_template(attribute, structured_error, message_buffer)
|
||||
match = false
|
||||
value = nil
|
||||
result = message_buffer.match(attribute.regex)
|
||||
if result != nil
|
||||
match = true
|
||||
if result.captures.size > 0
|
||||
value = result.captures[0]
|
||||
end
|
||||
end
|
||||
self.create(structured_error: structured_error, error_template_attribute: attribute, value: value, match: match)
|
||||
self.create(structured_error: structured_error, error_template_attribute: attribute, value: value, match: result != nil)
|
||||
end
|
||||
end
|
||||
|
@ -8,6 +8,7 @@ class Submission < ActiveRecord::Base
|
||||
belongs_to :exercise
|
||||
|
||||
has_many :testruns
|
||||
has_many :structured_errors
|
||||
has_many :comments, through: :files
|
||||
|
||||
delegate :execution_environment, to: :exercise
|
||||
|
@ -1,5 +1,6 @@
|
||||
#flash.fixed_error_messages data-message-failure=t('shared.message_failure')
|
||||
- %w[alert danger info notice success warning].each do |severity|
|
||||
div.alert.flash class="alert-#{{'alert' => 'warning', 'notice' => 'success'}.fetch(severity, severity)}"
|
||||
p id="flash-#{severity}" = flash[severity]
|
||||
span.fa.fa-times
|
||||
#flash-container
|
||||
#flash.container.fixed_error_messages data-message-failure=t('shared.message_failure')
|
||||
- %w[alert danger info notice success warning].each do |severity|
|
||||
div.alert.flash class="alert-#{{'alert' => 'warning', 'notice' => 'success'}.fetch(severity, severity)}"
|
||||
p id="flash-#{severity}" = flash[severity]
|
||||
span.fa.fa-times
|
||||
|
@ -32,8 +32,8 @@ html lang='en'
|
||||
li = link_to(t('shared.help.link'), '#modal-help', data: {toggle: 'modal'})
|
||||
= render('session')
|
||||
.container data-controller=controller_name
|
||||
= render('breadcrumbs')
|
||||
= render('flash')
|
||||
= render('breadcrumbs')
|
||||
- if (controller_name == "exercises" && action_name == "implement")
|
||||
.container-fluid
|
||||
= yield
|
||||
|
@ -27,6 +27,9 @@ h1 = RequestForComment.model_name.human(count: 2)
|
||||
- if request_for_comment.solved?
|
||||
td
|
||||
span class="fa fa-check" aria-hidden="true"
|
||||
- elsif request_for_comment.full_score_reached
|
||||
td
|
||||
span class="fa fa-check" style="color:darkgrey" aria-hidden="true"
|
||||
- else
|
||||
td = ''
|
||||
td = link_to(request_for_comment.exercise.title, request_for_comment)
|
||||
|
@ -17,7 +17,7 @@ namespace :deploy do
|
||||
after :compile_assets, :copy_vendor_assets do
|
||||
on roles(fetch(:assets_roles)) do
|
||||
within release_path do
|
||||
execute :cp, 'vendor/assets/images/*', 'public/assets/'
|
||||
execute :cp, '-r', 'vendor/assets/images/', 'public/assets/'
|
||||
execute :cp, '-r', 'vendor/assets/javascripts/ace', 'public/assets/'
|
||||
end
|
||||
end
|
||||
|
@ -34,7 +34,21 @@ production:
|
||||
ws_host: ws://localhost:4243 #url to connect rails server to docker host
|
||||
ws_client_protocol: wss:// #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production)
|
||||
|
||||
staging:
|
||||
<<: *default
|
||||
host: unix:///var/run/docker.sock
|
||||
pool:
|
||||
active: true
|
||||
refill:
|
||||
async: false
|
||||
batch_size: 8
|
||||
interval: 15
|
||||
timeout: 60
|
||||
workspace_root: <%= Rails.root.join('tmp', 'files', Rails.env) %>
|
||||
ws_host: ws://localhost:4243 #url to connect rails server to docker host
|
||||
ws_client_protocol: 'wss:' #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production)
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
host: tcp://192.168.59.104:2376
|
||||
host: tcp://127.0.0.1:2376
|
||||
workspace_root: <%= File.join('/', 'shared', Rails.env) %>
|
||||
|
@ -32,7 +32,7 @@ production:
|
||||
timeout: 60
|
||||
workspace_root: <%= Rails.root.join('tmp', 'files', Rails.env) %>
|
||||
ws_host: ws://localhost:4243 #url to connect rails server to docker host
|
||||
ws_client_protocol: 'wss:' #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production)
|
||||
ws_client_protocol: wss:// #set the websocket protocol to be used by the client to connect to the rails server (ws on development, wss on production)
|
||||
|
||||
staging:
|
||||
<<: *default
|
||||
@ -50,5 +50,5 @@ staging:
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
host: tcp://192.168.59.104:2376
|
||||
host: tcp://127.0.0.1:2376
|
||||
workspace_root: <%= File.join('/', 'shared', Rails.env) %>
|
@ -35,6 +35,9 @@ Rails.application.configure do
|
||||
# yet still be able to expire them through the digest params.
|
||||
config.assets.digest = true
|
||||
|
||||
# Suppress logger output for asset requests.
|
||||
config.assets.quiet = true
|
||||
|
||||
# Adds additional error checking when serving assets at runtime.
|
||||
# Checks for improperly declared sprockets dependencies.
|
||||
# Raises helpful error messages.
|
||||
|
@ -0,0 +1,5 @@
|
||||
class AddSubmissionToStructuredErrors < ActiveRecord::Migration
|
||||
def change
|
||||
add_reference :structured_errors, :submission, index: true
|
||||
end
|
||||
end
|
@ -0,0 +1,15 @@
|
||||
class AddReachedFullScoreToRequestForComment < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :request_for_comments, :full_score_reached, :boolean, default: false
|
||||
RequestForComment.find_each { |rfc|
|
||||
if rfc.submission.present? and rfc.submission.exercise.has_user_solved(rfc.user)
|
||||
rfc.full_score_reached = true
|
||||
rfc.save
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :request_for_comments, :full_score_reached
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
class AddTimesFeaturedToRequestForComments < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :request_for_comments, :times_featured, :integer, default: 0
|
||||
end
|
||||
end
|
10
db/migrate/20180222145909_fix_timestamps_on_feedback.rb
Normal file
@ -0,0 +1,10 @@
|
||||
class FixTimestampsOnFeedback < ActiveRecord::Migration
|
||||
def up
|
||||
change_column_default(:user_exercise_feedbacks, :created_at, nil)
|
||||
change_column_default(:user_exercise_feedbacks, :updated_at, nil)
|
||||
end
|
||||
|
||||
def down
|
||||
|
||||
end
|
||||
end
|
27
db/schema.rb
@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20180226131340) do
|
||||
ActiveRecord::Schema.define(version: 20180222145909) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@ -291,16 +291,18 @@ ActiveRecord::Schema.define(version: 20180226131340) do
|
||||
end
|
||||
|
||||
create_table "request_for_comments", force: :cascade do |t|
|
||||
t.integer "user_id", null: false
|
||||
t.integer "exercise_id", null: false
|
||||
t.integer "file_id", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.integer "exercise_id", null: false
|
||||
t.integer "file_id", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "user_type", limit: 255
|
||||
t.string "user_type", limit: 255
|
||||
t.text "question"
|
||||
t.boolean "solved", default: false
|
||||
t.boolean "solved", default: false
|
||||
t.integer "submission_id"
|
||||
t.text "thank_you_note"
|
||||
t.boolean "full_score_reached", default: false
|
||||
t.integer "times_featured", default: 0
|
||||
end
|
||||
|
||||
create_table "searches", force: :cascade do |t|
|
||||
@ -326,8 +328,11 @@ ActiveRecord::Schema.define(version: 20180226131340) do
|
||||
t.integer "file_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "submission_id"
|
||||
end
|
||||
|
||||
add_index "structured_errors", ["submission_id"], name: "index_structured_errors_on_submission_id", using: :btree
|
||||
|
||||
create_table "submissions", force: :cascade do |t|
|
||||
t.integer "exercise_id"
|
||||
t.float "score"
|
||||
@ -368,15 +373,15 @@ ActiveRecord::Schema.define(version: 20180226131340) do
|
||||
end
|
||||
|
||||
create_table "user_exercise_feedbacks", force: :cascade do |t|
|
||||
t.integer "exercise_id", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.string "user_type", null: false
|
||||
t.integer "exercise_id", null: false
|
||||
t.integer "user_id", null: false
|
||||
t.string "user_type", null: false
|
||||
t.integer "difficulty"
|
||||
t.integer "working_time_seconds"
|
||||
t.string "feedback_text"
|
||||
t.integer "user_estimated_worktime"
|
||||
t.datetime "created_at", default: '2017-11-20 18:20:25', null: false
|
||||
t.datetime "updated_at", default: '2017-11-20 18:20:25', null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "user_exercise_interventions", force: :cascade do |t|
|
||||
|
@ -1,3 +1,8 @@
|
||||
#flash-container {
|
||||
position: relative;
|
||||
top: -21px;
|
||||
}
|
||||
|
||||
.flash {
|
||||
display: none;
|
||||
|
||||
@ -10,14 +15,10 @@
|
||||
}
|
||||
|
||||
.fixed_error_messages {
|
||||
position: fixed;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
top: 20px;
|
||||
left: 0;
|
||||
padding: inherit;
|
||||
width: 100%;
|
||||
padding-left: 10%;
|
||||
padding-right: 10%;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
|
||||
|
14
provision.sh
@ -13,7 +13,7 @@ add-apt-repository ppa:chris-lea/node.js
|
||||
apt-get update
|
||||
|
||||
# code_ocean
|
||||
apt-get install -y postgresql-client postgresql-9.5 postgresql-server-dev-9.5 vagrant
|
||||
apt-get install -y postgresql-client postgresql-10 postgresql-server-dev-10 vagrant
|
||||
|
||||
# Docker
|
||||
if [ ! -f /etc/default/docker ]
|
||||
@ -49,18 +49,18 @@ apt-get install -y libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
|
||||
gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
|
||||
curl -L https://get.rvm.io | bash -s stable
|
||||
source /etc/profile.d/rvm.sh
|
||||
rvm install 2.3.1
|
||||
rvm use 2.3.1 --default
|
||||
rvm install 2.3.6
|
||||
rvm use 2.3.6 --default
|
||||
ruby -v
|
||||
|
||||
# rails
|
||||
apt-get -y install nodejs
|
||||
gem install rails -v 4.2.1
|
||||
gem install rails -v 4.2.10
|
||||
|
||||
# drop postgres access control
|
||||
if ! grep -q code_ocean /etc/postgresql/9.5/main/pg_hba.conf
|
||||
if ! grep -q code_ocean /etc/postgresql/10/main/pg_hba.conf
|
||||
then
|
||||
cat >/etc/postgresql/9.3/main/pg_hba.conf <<EOF
|
||||
cat >/etc/postgresql/10/main/pg_hba.conf <<EOF
|
||||
# code_ocean: drop access control
|
||||
local all all trust
|
||||
host all all 127.0.0.1/32 trust
|
||||
@ -110,7 +110,7 @@ passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
|
||||
server {
|
||||
server_name codeocean.local;
|
||||
root /vagrant/public;
|
||||
passenger_ruby /usr/local/rvm/gems/ruby-2.1.5/wrappers/ruby;
|
||||
passenger_ruby /usr/local/rvm/gems/ruby-2.3.6/wrappers/ruby;
|
||||
passenger_sticky_sessions on;
|
||||
passenger_enabled on;
|
||||
passenger_app_env development;
|
||||
|
Before Width: | Height: | Size: 140 KiB |
@ -98,7 +98,7 @@ describe Lti do
|
||||
let(:consumer) { FactoryBot.create(:consumer) }
|
||||
let(:score) { 0.5 }
|
||||
let(:submission) { FactoryBot.create(:submission) }
|
||||
let!(:lti_parameter) { FactoryBot.create(:lti_parameter)}
|
||||
let!(:lti_parameter) { FactoryBot.create(:lti_parameter, consumers_id: consumer.id, external_users_id: submission.user_id, exercises_id: submission.exercise_id)}
|
||||
|
||||
context 'with an invalid score' do
|
||||
it 'raises an exception' do
|
||||
@ -114,7 +114,6 @@ describe Lti do
|
||||
|
||||
context 'when grading is not supported' do
|
||||
it 'returns a corresponding status' do
|
||||
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
|
||||
expect_any_instance_of(IMS::LTI::ToolProvider).to receive(:outcome_service?).and_return(false)
|
||||
expect(controller.send(:send_score, submission.exercise_id, score, submission.user_id)[:status]).to eq('unsupported')
|
||||
end
|
||||
@ -133,12 +132,10 @@ describe Lti do
|
||||
end
|
||||
|
||||
it 'sends the score' do
|
||||
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
|
||||
controller.send(:send_score, submission.exercise_id, score, submission.user_id)
|
||||
end
|
||||
|
||||
it 'returns code, message, and status' do
|
||||
skip('ralf: this does not work, since send_score pulls data from the database, which then returns an empty array. On this is called .first, which returns nil and lets the test fail. Before Toms changes, this was taken from the session, which could be mocked')
|
||||
result = controller.send(:send_score, submission.exercise_id, score, submission.user_id)
|
||||
expect(result[:code]).to eq(response.response_code)
|
||||
expect(result[:message]).to eq(response.body)
|
||||
|
@ -2,6 +2,7 @@ FactoryBot.define do
|
||||
factory :user_exercise_feedback, class: UserExerciseFeedback do
|
||||
created_by_external_user
|
||||
feedback_text 'Most suitable exercise ever'
|
||||
association :exercise, factory: :math
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -2,12 +2,22 @@ require 'rails_helper'
|
||||
require 'seeds_helper'
|
||||
|
||||
describe DockerClient, docker: true do
|
||||
WORKSPACE_PATH = '/tmp/code_ocean_test'
|
||||
|
||||
let(:command) { 'whoami' }
|
||||
let(:docker_client) { described_class.new(execution_environment: FactoryBot.build(:java), user: FactoryBot.build(:admin)) }
|
||||
let(:execution_environment) { FactoryBot.build(:java) }
|
||||
let(:image) { double }
|
||||
let(:submission) { FactoryBot.create(:submission) }
|
||||
let(:workspace_path) { '/tmp' }
|
||||
let(:workspace_path) { WORKSPACE_PATH }
|
||||
|
||||
before(:all) do
|
||||
FileUtils.mkdir_p(WORKSPACE_PATH)
|
||||
end
|
||||
|
||||
after(:all) do
|
||||
FileUtils.rm_rf(WORKSPACE_PATH)
|
||||
end
|
||||
|
||||
describe '.check_availability!' do
|
||||
context 'when a socket error occurs' do
|
||||
@ -129,7 +139,7 @@ describe DockerClient, docker: true do
|
||||
after(:each) { docker_client.send(:create_workspace_files, container, submission) }
|
||||
|
||||
it 'creates submission-specific directories' do
|
||||
expect(Dir).to receive(:mkdir).at_least(:once)
|
||||
expect(Dir).to receive(:mkdir).at_least(:once).and_call_original
|
||||
end
|
||||
|
||||
it 'copies binary files' do
|
||||
|
@ -16,13 +16,8 @@
|
||||
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
||||
|
||||
unless RUBY_PLATFORM == 'java'
|
||||
if ENV['CODECLIMATE_REPO_TOKEN']
|
||||
require 'codeclimate-test-reporter'
|
||||
CodeClimate::TestReporter.start
|
||||
else
|
||||
require 'simplecov'
|
||||
SimpleCov.start('rails')
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.configure do |config|
|
||||
|
@ -1,6 +1,5 @@
|
||||
FactoryBot.define do
|
||||
factory :error_template_attribute do
|
||||
error_template nil
|
||||
key "MyString"
|
||||
regex "MyString"
|
||||
end
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |