Class: Binpacker::Report

Inherits:
Object
  • Object
show all
Defined in:
lib/binpacker/report.rb,
sig/binpacker/report.rbs

Overview

Builds the machine-readable Run report: predicted versus actual per-Worker durations plus the worst per-Test Drift. See docs/design/run-report-format.md.

Constant Summary collapse

SCHEMA =

Returns:

1
DRIFT_LIMIT =

Returns:

10

Instance Method Summary collapse

Constructor Details

#initialize(profile:, algorithm:, predicted_loads:, worker_stats:, all_timings:, timings:, shard: nil, discovered: nil, selected: nil) ⇒ Report

Returns a new instance of Report.

Parameters:

  • (defaults to: nil)
  • (defaults to: nil)
  • (defaults to: nil)


12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/binpacker/report.rb', line 12

def initialize(profile:, algorithm:, predicted_loads:, worker_stats:, all_timings:, timings:,
               shard: nil, discovered: nil, selected: nil)
  @profile = profile
  @algorithm = algorithm
  @predicted_loads = predicted_loads
  @worker_stats = worker_stats
  @all_timings = all_timings
  @timings = timings
  @shard = shard
  @discovered = discovered
  @selected = selected
end

Instance Method Details

#shard_sectionHash[Symbol, untyped]?

The audit trail for a sharded run, and the reason discovered is recorded at all.

Shards never talk to each other: each computes the same N-way partition and trusts the others to have computed it identically. They do so only while they agree on the timing data the partition is cut from, which in CI means every shard restoring the same timing cache. A shard that restores a different one — a cache miss where its siblings hit — partitions differently, and the failure is silent: tests land in no shard at all and the build stays green.

discovered is the whole-suite count before slicing, so it agrees across shards that see the same repository. selected is this shard's slice. Summing selected over a matrix's reports and comparing to the shared discovered turns that silent skip into a failure — binpacker shards-check does exactly that.

Returns:



64
65
66
67
68
69
70
71
72
73
# File 'lib/binpacker/report.rb', line 64

def shard_section
  return nil unless @shard

  {
    index: @shard.index,
    total: @shard.total,
    discovered_tests: @discovered,
    selected_tests: @selected
  }
end

#to_hHash[Symbol, untyped]

Returns:



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/binpacker/report.rb', line 25

def to_h
  predicted = @predicted_loads
  actual = @worker_stats.map { |s| s[:total_time] }

  {
    schema: SCHEMA,
    profile: @profile,
    algorithm: @algorithm,
    shard: shard_section,
    worker_count: @worker_stats.size,
    predicted_makespan: round(predicted.max || 0.0),
    actual_makespan: round(actual.max || 0.0),
    workers: workers,
    balance: {
      predicted_deviation_pct: deviation_pct(predicted),
      actual_deviation_pct: deviation_pct(actual)
    },
    drift: drift
  }
end

#write(path) ⇒ Object

Parameters:

Returns:



46
47
48
# File 'lib/binpacker/report.rb', line 46

def write(path)
  File.write(path, JSON.pretty_generate(to_h))
end