mesa_test 1.1.12 → 1.2.1

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/bin/mesa_test +60 -0
  3. data/lib/mesa_test.rb +104 -16
  4. metadata +3 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6197ab41eec170d06d29d19e2e66446c71a673434a316a100bd102e44a849d7d
4
- data.tar.gz: f307cc7d5948121879fd4565ac90fbcf57b6e796ab47fdce4bca7c6f79b9092a
3
+ metadata.gz: 3c01327f74ca824acf8b7cb473561037281255de396cc623c6c636b9c21bb2ed
4
+ data.tar.gz: 52f1c9d09ece9a85bdfc3827249357ec1ada18da6b14d70793df9b082331bbe9
5
5
  SHA512:
6
- metadata.gz: 856b3b1f1bc52c56aae8ca59916f0526306ebff35657b68b26ddcd96313b1f2b0ed051aa9b55c7c8d0378d01b7f433be89fcc035bb61d14cf7dc67fa95616be1
7
- data.tar.gz: a9f230dd702be29a371b0442d8cdc6dc81a2774ddfae9105b7250b401881ca06b2db721728143b112d2e057027b456206d187e7298de0aef31bc5ba25d29a791
6
+ metadata.gz: 91a42fce1cf44a643b465edf60351448ea863ebd8ac4e5f962733928b9c620c1dafb251c38cbc4bd9267309ee6298d96fb05a12b35847a974025aa8a183f9037
7
+ data.tar.gz: 19aca1c41bc5519d8082f7ee5e85398a3652d9b7455f21b4ecf2b2b767084e3abfe5fd52a2630f4a17a8248879e84375549b954453f3c2c79a1acdf6590cd6cf
data/bin/mesa_test CHANGED
@@ -328,8 +328,68 @@ class MesaTest < Thor
328
328
  force_setup: true)
329
329
  end
330
330
 
331
+ desc 'search "QUERY"', 'retrieve JSON test instances matching QUERY'
332
+ long_desc <<-LONGDESC
333
+ Sends a GET request to the MesaTestHub search API. QUERY should be
334
+ quoted. Credentials are read from your mesa_test config file and sent as
335
+ URL query parameters (HTTPS is mandatory).
336
+
337
+ Query syntax is the same key-value form used by the in-browser search box
338
+ at testhub.mesastar.org/test_instances/search (see the "Query syntax"
339
+ panel on that page). Example:
340
+
341
+ mesa_test search "computer: Hercules; passed: false"
342
+
343
+ The raw JSON response body is written to STDOUT, suitable for piping to
344
+ jq or redirecting to a file. If the server reports any rejected query
345
+ clauses in a `failures` array, those are also echoed to STDERR so they
346
+ aren't silently dropped from downstream pipelines. On a non-success HTTP
347
+ status, an error is written to STDERR and the command exits non-zero.
348
+ LONGDESC
349
+
350
+ def search(query)
351
+ s = create_submitter(force: true)
352
+ emit_search_response(s.search(query))
353
+ end
354
+
355
+ desc 'count "QUERY"', 'count test instances matching QUERY'
356
+ long_desc <<-LONGDESC
357
+ Like `search`, but hits the count endpoint. The response is a small JSON
358
+ object containing the result-set size (and any `failures`). Use this
359
+ before `search` when you don't know how large a result set will be.
360
+ LONGDESC
361
+
362
+ def count(query)
363
+ s = create_submitter(force: true)
364
+ emit_search_response(s.search_count(query))
365
+ end
366
+
331
367
  private
332
368
 
369
+ def emit_search_response(response)
370
+ if response.is_a?(Net::HTTPSuccess)
371
+ puts response.body
372
+ warn_search_failures(response.body)
373
+ else
374
+ $stderr.puts "Search request failed: HTTP #{response.code} "\
375
+ "#{response.message}"
376
+ $stderr.puts response.body unless response.body.nil? || response.body.empty?
377
+ exit 1
378
+ end
379
+ end
380
+
381
+ def warn_search_failures(body)
382
+ parsed = JSON.parse(body)
383
+ failures = parsed['failures']
384
+ return unless failures.is_a?(Array) && !failures.empty?
385
+
386
+ $stderr.puts 'Warning: the following query clauses were rejected by '\
387
+ 'the server and ignored:'
388
+ failures.each { |f| $stderr.puts " - #{f}" }
389
+ rescue JSON::ParserError
390
+ # Body wasn't JSON; nothing to surface.
391
+ end
392
+
333
393
  def work_dir(given, default)
334
394
  if given
335
395
  File.expand_path('', given)
data/lib/mesa_test.rb CHANGED
@@ -18,7 +18,6 @@ GITHUB_HTTPS = 'https://github.com/MESAHub/mesa.git'.freeze
18
18
  GITHUB_SSH = 'git@github.com:MESAHub/mesa.git'.freeze
19
19
 
20
20
  class MesaTestSubmitter
21
- # DEFAULT_URI = 'https://mesa-test-hub.herokuapp.com'.freeze
22
21
  DEFAULT_URI = 'https://testhub.mesastar.org'.freeze
23
22
 
24
23
  # set up config file for computer
@@ -52,8 +51,9 @@ e-mail and password will be stored in plain text.'
52
51
 
53
52
  # Get API key for submitting failure logs
54
53
  response = shell.ask 'What is the logs submission API token associated '\
55
- "with the email #{s.email} (required; contact Philip Mocz if you "\
56
- "need a key)? (#{s.logs_token})", :blue
54
+ "with the email #{s.email} (required; if you don't have one, ask a "\
55
+ "MESA testing maintainer or a representative from Flatiron for a "\
56
+ "key)? (#{s.logs_token})", :blue
57
57
  s.logs_token = response unless response.empty?
58
58
 
59
59
  # Determine if we'll use ssh or https to access github
@@ -330,7 +330,12 @@ e-mail and password will be stored in plain text.'
330
330
  password: password,
331
331
  computer_name: computer_name
332
332
  }.to_json
333
- JSON.parse(https.request(request).body).to_hash
333
+ response = testhub_request(https, request)
334
+ # if the hub was unreachable, behave as an unverified computer; the
335
+ # network error has already been reported by testhub_request
336
+ return {} if response.nil?
337
+
338
+ JSON.parse(response.body).to_hash
334
339
  end
335
340
 
336
341
  # submit entire commit's worth of test cases, OR submit compilation status
@@ -366,11 +371,15 @@ e-mail and password will be stored in plain text.'
366
371
  request.body = request_data.to_json
367
372
 
368
373
  # actually do the submission
369
- response = https.request request
374
+ response = testhub_request(https, request)
370
375
 
371
- if !response.is_a? Net::HTTPCreated
376
+ if response.nil?
377
+ # network failure; testhub_request already explained why
378
+ false
379
+ elsif !response.is_a? Net::HTTPCreated
372
380
  shell.say "\nFailed to submit some or all test case instances and/or "\
373
- 'commit data.', :red
381
+ "commit data (server responded #{response.code} "\
382
+ "#{response.message}).", :red
374
383
  false
375
384
  else
376
385
  shell.say "\nSuccessfully submitted commit #{mesa.sha}.", :green
@@ -427,12 +436,16 @@ e-mail and password will be stored in plain text.'
427
436
  request.body = request_data.to_json
428
437
 
429
438
  # actually do the submission
430
- response = https.request request
439
+ response = testhub_request(https, request)
431
440
 
432
- if !response.is_a? Net::HTTPCreated
441
+ if response.nil?
442
+ # network failure; testhub_request already explained why
443
+ return false
444
+ elsif !response.is_a? Net::HTTPCreated
433
445
  shell.say "\nFailed to submit #{test_case.test_name} for commit "\
434
- "#{mesa.sha}", :red
435
- false
446
+ "#{mesa.sha} (server responded #{response.code} "\
447
+ "#{response.message}).", :red
448
+ return false
436
449
  else
437
450
  shell.say "\nSuccessfully submitted instance of #{test_case.test_name} "\
438
451
  "for commit #{mesa.sha}.", :green
@@ -444,17 +457,50 @@ e-mail and password will be stored in plain text.'
444
457
  end
445
458
  end
446
459
 
460
+ # Perform an HTTP request against the test hub with bounded connect/read
461
+ # timeouts, so a slow or unreachable server (e.g. while it is under heavy
462
+ # load) fails fast with a clear message instead of hanging on the default
463
+ # 60-second connect timeout and then dumping a raw Ruby backtrace. Returns
464
+ # the Net::HTTPResponse, or +nil+ if the request could not be completed
465
+ # because of a network problem.
466
+ def testhub_request(https, request)
467
+ https.open_timeout = 10
468
+ https.read_timeout = 60
469
+ https.request(request)
470
+ rescue StandardError => e
471
+ shell.say "\nCould not reach the test hub at #{https.address} "\
472
+ "(#{e.class}: #{e.message}).", :red
473
+ nil
474
+ end
475
+
447
476
  # make generic request to LOGS server
448
477
  # +params+ is a hash of data to be encoded as JSON and sent off
478
+ #
479
+ # Returns the Net::HTTPResponse on success, or +nil+ if the request could
480
+ # not be completed because of a network problem (the LOGS server being
481
+ # unreachable, slow, or refusing connections). The LOGS server only receives
482
+ # diagnostic build/test output, so a failure here must never crash the run or
483
+ # fail a CI build whose actual test results already reached the test hub. We
484
+ # cap the connect/read time so we fail fast instead of hanging on the default
485
+ # 60-second open timeout for every test case.
449
486
  def submit_logs(params)
450
487
  #uri = URI('https://logs.mesastar.org/uploads')
451
488
  uri = URI('https://mesa-logs.flatironinstitute.org/uploads')
452
489
  https = Net::HTTP.new(uri.host, uri.port)
453
490
  https.use_ssl = true
491
+ https.open_timeout = 10
492
+ https.read_timeout = 30
454
493
  req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json',
455
494
  'X-Api-Key' => logs_token)
456
495
  req.body = params.to_json
457
- https.request(req)
496
+ begin
497
+ https.request(req)
498
+ rescue StandardError => e
499
+ shell.say "\nCould not reach the LOGS server at #{uri.host} "\
500
+ "(#{e.class}: #{e.message}). Skipping log upload; this does "\
501
+ 'not affect test results already sent to the test hub.', :yellow
502
+ nil
503
+ end
458
504
  end
459
505
 
460
506
  # send build log to the logs server
@@ -473,9 +519,13 @@ e-mail and password will be stored in plain text.'
473
519
  res = submit_logs(build_log_params(mesa))
474
520
 
475
521
  # report out results
476
- if !res.is_a? Net::HTTPOK
522
+ if res.nil?
523
+ # network failure; submit_logs already explained why. Don't fail the run.
524
+ false
525
+ elsif !res.is_a? Net::HTTPOK
477
526
  shell.say "\nFailed to submit build.log to the LOGS server for commit "\
478
- "#{mesa.sha}.", :red
527
+ "#{mesa.sha} (server responded #{res.code} #{res.message}).",
528
+ :red
479
529
  false
480
530
  else
481
531
  shell.say "\nSuccessfully submitted build.log to the LOGS server for "\
@@ -503,9 +553,13 @@ e-mail and password will be stored in plain text.'
503
553
  res = submit_logs(test_log_params(test_case))
504
554
 
505
555
  # report out results
506
- if !res.is_a? Net::HTTPOK
556
+ if res.nil?
557
+ # network failure; submit_logs already explained why. Don't fail the run.
558
+ false
559
+ elsif !res.is_a? Net::HTTPOK
507
560
  shell.say "Failed to submit logs for test case #{test_case.test_name} "\
508
- "in commit #{test_case.mesa.sha}.", :red
561
+ "in commit #{test_case.mesa.sha} (server responded "\
562
+ "#{res.code} #{res.message}).", :red
509
563
  false
510
564
  else
511
565
  shell.say "Successfully submitted logs for test case "\
@@ -515,6 +569,40 @@ e-mail and password will be stored in plain text.'
515
569
  end
516
570
  end
517
571
 
572
+ # GET a search query from the testhub. Credentials and the query string
573
+ # ride in the URL's query parameters (per the testhub search API contract;
574
+ # the controller also accepts session auth, but a CLI sends them in-band).
575
+ # Returns the raw Net::HTTP response.
576
+ def search(query_text)
577
+ get_search('/test_instances/search.json', query_text)
578
+ end
579
+
580
+ # Like #search, but hits the count endpoint. Useful for sizing a result set
581
+ # before pulling the full payload.
582
+ def search_count(query_text)
583
+ get_search('/test_instances/search_count.json', query_text)
584
+ end
585
+
586
+ private
587
+
588
+ def get_search(path, query_text)
589
+ uri = URI.parse(base_uri + path)
590
+ uri.query = URI.encode_www_form(
591
+ email: email,
592
+ password: password,
593
+ query_text: query_text
594
+ )
595
+
596
+ https = Net::HTTP.new(uri.hostname, uri.port)
597
+ https.use_ssl = base_uri.include? 'https'
598
+
599
+ request = Net::HTTP::Get.new(
600
+ uri,
601
+ initheader = { 'Accept' => 'application/json' }
602
+ )
603
+
604
+ https.request(request)
605
+ end
518
606
  end
519
607
 
520
608
  class Mesa
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mesa_test
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.12
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - William Wolf
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-05-20 00:00:00.000000000 Z
10
+ date: 2026-05-29 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: json
@@ -66,7 +65,6 @@ homepage: https://github.com/MESAHub/mesa_test
66
65
  licenses:
67
66
  - MIT
68
67
  metadata: {}
69
- post_install_message:
70
68
  rdoc_options: []
71
69
  require_paths:
72
70
  - lib
@@ -81,8 +79,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
79
  - !ruby/object:Gem::Version
82
80
  version: '0'
83
81
  requirements: []
84
- rubygems_version: 3.4.17
85
- signing_key:
82
+ rubygems_version: 3.7.1
86
83
  specification_version: 4
87
84
  summary: Command line tool for running and reporting the MESA test suites.
88
85
  test_files: []