From c000a76c9271a97c213fbe84ac48abf9ac8d03cd Mon Sep 17 00:00:00 2001 From: Naragod Date: Sun, 7 Jun 2026 20:58:30 -0400 Subject: [PATCH 1/2] TICKET-611: Autotester - ai-gateway connection --- Changelog.md | 1 + app/helpers/automated_tests_helper.rb | 12 ++++++++---- spec/jobs/autotest_run_job_spec.rb | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index d48cae06f5..2998366622 100644 --- a/Changelog.md +++ b/Changelog.md @@ -24,6 +24,7 @@ - Updated links to refer to new documentation website (#8049) - Added a submissions table filter option that lets graders with manage submissions permission view either all submissions or only their assigned submissions (#8047) - Added a submission scope filter to the grading view so TAs with manage submissions permission can navigate either all submissions or only their assigned submissions (#8046) +- Forward the test batch id to the autotester so AI grading telemetry can attribute mass-grading runs (#7991) - Removed Graders Subcomponent and added a Graders column in the Assignment Grades tab (#7967) - Added GET /test_runs API route (#8055) diff --git a/app/helpers/automated_tests_helper.rb b/app/helpers/automated_tests_helper.rb index 9666027a84..365ee9ecaf 100644 --- a/app/helpers/automated_tests_helper.rb +++ b/app/helpers/automated_tests_helper.rb @@ -111,10 +111,11 @@ def test_data(test_run_ids) end def get_markus_address(host_with_port) + base = ENV.fetch('MARKUS_URL', host_with_port) if Rails.application.config.relative_url_root.nil? - host_with_port + base else - host_with_port + Rails.application.config.relative_url_root + base + Rails.application.config.relative_url_root end end @@ -209,6 +210,8 @@ def run_tests(assignment, host_with_port, group_ids, role, collected: true, batc req.body = { test_data: test_data, categories: role.student? ? ['student'] : ['instructor'], + # Maps to TestBatch.id for telemetry attribution; null for solo runs. + batch_id: batch&.id, request_high_priority: batch.nil? && role.student? }.to_json res = send_request!(req, uri) @@ -307,10 +310,11 @@ def set_headers(req, api_key) # Get the current URL for this MarkUs instance (adds the relative url root to +host_with_port+) if it exists. def get_markus_address(host_with_port) + base = ENV.fetch('MARKUS_URL', host_with_port) if Rails.application.config.relative_url_root.nil? - host_with_port + base else - host_with_port + Rails.application.config.relative_url_root + base + Rails.application.config.relative_url_root end end diff --git a/spec/jobs/autotest_run_job_spec.rb b/spec/jobs/autotest_run_job_spec.rb index 00512018c7..72a447beae 100644 --- a/spec/jobs/autotest_run_job_spec.rb +++ b/spec/jobs/autotest_run_job_spec.rb @@ -287,6 +287,28 @@ end end end + + context 'batch_id attribution' do + it 'forwards the batch id for a multi-group run' do + expect_any_instance_of(AutotestRunJob).to receive(:send_request!) do |_j, net_obj| + expect(JSON.parse(net_obj.body)['batch_id']).to eq TestBatch.first.id + dummy_return + end + subject + end + + context 'when there is a single group' do + let(:n_groups) { 1 } + + it 'forwards a null batch id for a solo run' do + expect_any_instance_of(AutotestRunJob).to receive(:send_request!) do |_j, net_obj| + expect(JSON.parse(net_obj.body)).to include('batch_id' => nil) + dummy_return + end + subject + end + end + end end context 'tests are not set up' do From 4a85f93fefb18d2a2524c91b0564c8ecce56d82a Mon Sep 17 00:00:00 2001 From: Naragod Date: Tue, 28 Jul 2026 01:19:50 -0400 Subject: [PATCH 2/2] TICKET-611: Harden the MARKUS_URL address override --- app/helpers/automated_tests_helper.rb | 20 ++++---------------- spec/jobs/autotest_run_job_spec.rb | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/app/helpers/automated_tests_helper.rb b/app/helpers/automated_tests_helper.rb index 365ee9ecaf..0becaecd92 100644 --- a/app/helpers/automated_tests_helper.rb +++ b/app/helpers/automated_tests_helper.rb @@ -110,13 +110,11 @@ def test_data(test_run_ids) .each { |h| h[:test_categories] = [h['user_type'].downcase] } end + # Get the current URL for this MarkUs instance, with the relative url root appended if it exists. + # +MARKUS_URL+ overrides +host_with_port+ to give the autotester an address it can reach. def get_markus_address(host_with_port) - base = ENV.fetch('MARKUS_URL', host_with_port) - if Rails.application.config.relative_url_root.nil? - base - else - base + Rails.application.config.relative_url_root - end + base = ENV['MARKUS_URL'].presence || host_with_port + "#{base}#{Rails.application.config.relative_url_root}" end # Sends RESTful api requests to the autotester @@ -308,16 +306,6 @@ def set_headers(req, api_key) req['Content-Type'] = 'application/json' end - # Get the current URL for this MarkUs instance (adds the relative url root to +host_with_port+) if it exists. - def get_markus_address(host_with_port) - base = ENV.fetch('MARKUS_URL', host_with_port) - if Rails.application.config.relative_url_root.nil? - base - else - base + Rails.application.config.relative_url_root - end - end - # Gets the feedback file data from the autotester for the TestRun with autotest_test_id = +test_id+ # and adds it to the +results+ hash. def add_feedback_data(results, settings_id, test_id, autotest_setting) diff --git a/spec/jobs/autotest_run_job_spec.rb b/spec/jobs/autotest_run_job_spec.rb index 72a447beae..9c23d6f6fd 100644 --- a/spec/jobs/autotest_run_job_spec.rb +++ b/spec/jobs/autotest_run_job_spec.rb @@ -7,6 +7,9 @@ let(:role) { create(:instructor) } before do + # MARKUS_URL overrides host_with_port when set, so unset it here to keep these + # expectations independent of the developer's environment. + stub_const('ENV', ENV.to_h.except('MARKUS_URL')) allow_any_instance_of(AutotestSetting).to( receive(:send_request!).and_return(OpenStruct.new(body: { api_key: 'someapikey' }.to_json)) ) @@ -309,6 +312,28 @@ end end end + + context 'file_url host' do + it 'uses MARKUS_URL when set, since the autotester may not reach the browser-facing host' do + stub_const('ENV', ENV.to_h.merge('MARKUS_URL' => 'http://autotest-reachable:3000')) + expect_any_instance_of(AutotestRunJob).to receive(:send_request!) do |_j, net_obj| + urls = JSON.parse(net_obj.body)['test_data'].pluck('file_url') + expect(urls).to all(start_with('http://autotest-reachable:3000/')) + dummy_return + end + subject + end + + it 'falls back to host_with_port when MARKUS_URL is set but empty' do + stub_const('ENV', ENV.to_h.merge('MARKUS_URL' => '')) + expect_any_instance_of(AutotestRunJob).to receive(:send_request!) do |_j, net_obj| + urls = JSON.parse(net_obj.body)['test_data'].pluck('file_url') + expect(urls).to all(start_with("#{host_with_port}/")) + dummy_return + end + subject + end + end end context 'tests are not set up' do