Add user to testrun

* We want to identify a user that has triggered a testrun. Previously (in regular operation), only submission author who were regular users were able to start a testrun. Now, we want to prepare a future where submission authors are programming groups. Still, a testrun is triggered by an individual user and not a group.
* Further, this commit fixes some missing foreign key constrains.
This commit is contained in:
Sebastian Serth
2023-08-20 17:59:24 +02:00
committed by Sebastian Serth
parent e3603758ef
commit be4f2b790d
12 changed files with 61 additions and 15 deletions

View File

@ -525,7 +525,7 @@ class ExercisesController < ApplicationController
def submit
@submission = Submission.create(submission_params)
@submission.calculate_score
@submission.calculate_score(current_user)
if @submission.users.map {|user| lti_outcome_service?(@submission.exercise, user, @submission.study_group_id) }.any?
transmit_lti_score

View File

@ -66,7 +66,7 @@ class RemoteEvaluationController < ApplicationController
validation_token = remote_evaluation_params[:validation_token]
if (remote_evaluation_mapping = RemoteEvaluationMapping.find_by(validation_token:))
@submission = Submission.create(build_submission_params(cause, remote_evaluation_mapping))
@submission.calculate_score
@submission.calculate_score(remote_evaluation_mapping.user)
else
# TODO: better output
# TODO: check token expired?

View File

@ -157,7 +157,7 @@ class RequestForCommentsController < ApplicationController
# execute the tests here and wait until they finished.
# As the same runner is used for the score and test run, no parallelization is possible
# A run is triggered from the frontend and does not need to be handled here.
@request_for_comment.submission.calculate_score
@request_for_comment.submission.calculate_score(current_user)
format.json { render :show, status: :created, location: @request_for_comment }
else
format.html { render :new }

View File

@ -249,7 +249,7 @@ class SubmissionsController < ApplicationController
return true if disable_scoring
# The score is stored separately, we can forward it to the client immediately
client_socket&.send_data(JSON.dump(@submission.calculate_score))
client_socket&.send_data(JSON.dump(@submission.calculate_score(current_user)))
# To enable hints when scoring a submission, uncomment the next line:
# send_hints(client_socket, StructuredError.where(submission: @submission))
rescue Runner::Error => e
@ -284,7 +284,7 @@ class SubmissionsController < ApplicationController
return true if @embed_options[:disable_run]
# The score is stored separately, we can forward it to the client immediately
client_socket&.send_data(JSON.dump(@submission.test(@file)))
client_socket&.send_data(JSON.dump(@submission.test(@file, current_user)))
rescue Runner::Error => e
extract_durations(e)
send_and_store client_socket, {cmd: :status, status: :container_depleted}
@ -396,6 +396,7 @@ class SubmissionsController < ApplicationController
passed: @testrun[:passed],
cause:,
submission: @submission,
user: current_user,
exit_code: @testrun[:exit_code], # might be nil, e.g., when the run did not finish
status: @testrun[:status] || :failed,
output: @testrun[:output].presence, # TODO: Remove duplicated saving of the output after creating TestrunMessages

View File

@ -6,6 +6,7 @@ class ProgrammingGroup < ApplicationRecord
has_many :programming_group_memberships, dependent: :destroy
has_many :external_users, through: :programming_group_memberships, source_type: 'ExternalUser', source: :user
has_many :internal_users, through: :programming_group_memberships, source_type: 'InternalUser', source: :user
has_many :testruns, through: :submissions
belongs_to :exercise
validate :group_size

View File

@ -141,7 +141,7 @@ class Submission < ApplicationRecord
# @raise [Runner::Error] if the score could not be calculated due to a failure with the runner.
# See the specific type and message for more details.
def calculate_score
def calculate_score(requesting_user)
file_scores = nil
# If prepared_runner raises an error, no Testrun will be created.
prepared_runner do |runner, waiting_duration|
@ -153,7 +153,7 @@ class Submission < ApplicationRecord
output = run_test_file file, runner, waiting_duration
# If the previous execution failed and there is at least one more test, we request a new runner.
runner, waiting_duration = swap_runner(runner) if output[:status] == :timeout && index < assessment_number
score_file(output, file)
score_file(output, file, requesting_user)
end
end
# We sort the files again, so that the linter tests are displayed last.
@ -178,10 +178,10 @@ class Submission < ApplicationRecord
# @raise [Runner::Error] if the file could not be tested due to a failure with the runner.
# See the specific type and message for more details.
def test(file)
def test(file, requesting_user)
prepared_runner do |runner, waiting_duration|
output = run_test_file file, runner, waiting_duration
score_file output, file
score_file output, file, requesting_user
rescue Runner::Error => e
e.waiting_duration = waiting_duration
raise
@ -251,7 +251,7 @@ class Submission < ApplicationRecord
}
end
def score_file(output, file)
def score_file(output, file, requesting_user)
assessor = Assessor.new(execution_environment:)
assessment = assessor.assess(output)
passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score]).positive?)
@ -264,6 +264,7 @@ class Submission < ApplicationRecord
end
testrun = Testrun.create(
submission: self,
user: requesting_user,
cause: 'assess', # Required to differ run and assess for RfC show
file:, # Test file that was executed
passed:,

View File

@ -17,6 +17,7 @@ class User < ApplicationRecord
has_many :participations, through: :submissions, source: :exercise, as: :user
has_many :user_proxy_exercise_exercises, as: :user
has_many :user_exercise_interventions, as: :user
has_many :testruns, as: :user
has_many :interventions, through: :user_exercise_interventions
has_many :remote_evaluation_mappings, as: :user
has_one :codeharbor_link, dependent: :destroy