perfgate 0.1.0
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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +25 -0
- data/CHANGELOG.md +18 -0
- data/CONTRIBUTING.md +73 -0
- data/LICENSE +201 -0
- data/NOT_FINALIZED.md +70 -0
- data/README.md +86 -0
- data/ROADMAP.md +125 -0
- data/Rakefile +12 -0
- data/SECURITY.md +63 -0
- data/docs/README.md +7 -0
- data/docs/architecture.md +125 -0
- data/docs/compatibility.md +49 -0
- data/docs/launch-article.md +97 -0
- data/docs/onboarding.md +122 -0
- data/docs/telemetry.md +81 -0
- data/examples/rails-rspec-app/.github/workflows/baseline.yml +48 -0
- data/examples/rails-rspec-app/README.md +38 -0
- data/examples/rails-rspec-app/spec/jobs/invoice_job_spec.rb +15 -0
- data/examples/rails-rspec-app/spec/requests/checkout_spec.rb +24 -0
- data/exe/perfgate +7 -0
- data/lib/perfgate/cli/compare_command.rb +91 -0
- data/lib/perfgate/cli/run_command.rb +123 -0
- data/lib/perfgate/cli/run_comparison_reporter.rb +77 -0
- data/lib/perfgate/cli.rb +60 -0
- data/lib/perfgate/comparison/deterministic_metric_decision.rb +34 -0
- data/lib/perfgate/comparison/diagnostics.rb +70 -0
- data/lib/perfgate/comparison/engine.rb +79 -0
- data/lib/perfgate/comparison/metric_change.rb +84 -0
- data/lib/perfgate/comparison/metric_decision.rb +39 -0
- data/lib/perfgate/comparison/statistical_metric_decision.rb +75 -0
- data/lib/perfgate/comparison/workload_comparison.rb +98 -0
- data/lib/perfgate/config/defaults.rb +70 -0
- data/lib/perfgate/config/env_overrides.rb +54 -0
- data/lib/perfgate/config/schema.rb +53 -0
- data/lib/perfgate/config/validator.rb +64 -0
- data/lib/perfgate/config.rb +136 -0
- data/lib/perfgate/errors.rb +20 -0
- data/lib/perfgate/execution/process_runner.rb +71 -0
- data/lib/perfgate/execution/runner.rb +60 -0
- data/lib/perfgate/execution/sample_context.rb +66 -0
- data/lib/perfgate/fingerprints/compatibility.rb +46 -0
- data/lib/perfgate/fingerprints/components.rb +98 -0
- data/lib/perfgate/fingerprints/workload_definition.rb +30 -0
- data/lib/perfgate/instrumentation/allocations.rb +20 -0
- data/lib/perfgate/instrumentation/duration.rb +20 -0
- data/lib/perfgate/instrumentation/gc.rb +30 -0
- data/lib/perfgate/instrumentation/sql_activity.rb +50 -0
- data/lib/perfgate/instrumentation.rb +36 -0
- data/lib/perfgate/metrics/.gitkeep +0 -0
- data/lib/perfgate/policy/engine.rb +73 -0
- data/lib/perfgate/rails/.gitkeep +0 -0
- data/lib/perfgate/report/console.rb +57 -0
- data/lib/perfgate/report/markdown.rb +101 -0
- data/lib/perfgate/reporting/.gitkeep +0 -0
- data/lib/perfgate/rspec/discovery.rb +31 -0
- data/lib/perfgate/rspec/id_resolver.rb +30 -0
- data/lib/perfgate/rspec/workload_builder.rb +48 -0
- data/lib/perfgate/rspec.rb +14 -0
- data/lib/perfgate/serialization/run_result.rb +58 -0
- data/lib/perfgate/statistics/mann_whitney_u.rb +84 -0
- data/lib/perfgate/statistics/summary.rb +60 -0
- data/lib/perfgate/storage/adapter.rb +24 -0
- data/lib/perfgate/storage/archive.rb +69 -0
- data/lib/perfgate/storage/filesystem.rb +121 -0
- data/lib/perfgate/telemetry/.gitkeep +0 -0
- data/lib/perfgate/version.rb +5 -0
- data/lib/perfgate/workloads/registry.rb +50 -0
- data/lib/perfgate/workloads/workload.rb +26 -0
- data/lib/perfgate.rb +46 -0
- data/perfgate.gemspec +41 -0
- data/schemas/comparison-result-v1.schema.json +7 -0
- data/schemas/run-result-v1.schema.json +7 -0
- data/sig/perfgate.rbs +4 -0
- metadata +139 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Perfgate
|
|
4
|
+
module Workloads
|
|
5
|
+
# Collects Workload instances discovered for a run and enforces the
|
|
6
|
+
# uniqueness rule from spec section 9.2: "a duplicate explicit ID is
|
|
7
|
+
# a configuration error".
|
|
8
|
+
class Registry
|
|
9
|
+
include Enumerable
|
|
10
|
+
|
|
11
|
+
class << self
|
|
12
|
+
def instance
|
|
13
|
+
@instance ||= new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def reset!
|
|
17
|
+
@instance = new
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def initialize
|
|
22
|
+
@workloads = {}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def register(workload)
|
|
26
|
+
raise Perfgate::WorkloadError, "duplicate workload id: #{workload.id.inspect}" if @workloads.key?(workload.id)
|
|
27
|
+
|
|
28
|
+
@workloads[workload.id] = workload
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def [](id)
|
|
32
|
+
@workloads[id]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def each(&block)
|
|
36
|
+
return enum_for(:each) unless block
|
|
37
|
+
|
|
38
|
+
@workloads.each_value(&block)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ids
|
|
42
|
+
@workloads.keys
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def clear
|
|
46
|
+
@workloads.clear
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Perfgate
|
|
4
|
+
module Workloads
|
|
5
|
+
# A deterministic executable path measured by Baseline (spec section
|
|
6
|
+
# 7). Normally backed by one RSpec example, but the callable is kept
|
|
7
|
+
# generic so the execution engine can be exercised without RSpec.
|
|
8
|
+
class Workload
|
|
9
|
+
attr_reader :id, :samples, :warmup, :metrics
|
|
10
|
+
|
|
11
|
+
def initialize(id:, samples:, warmup:, metrics: [:duration], &block)
|
|
12
|
+
raise ArgumentError, "workload #{id.inspect} requires a block to execute" unless block
|
|
13
|
+
|
|
14
|
+
@id = id
|
|
15
|
+
@samples = samples
|
|
16
|
+
@warmup = warmup
|
|
17
|
+
@metrics = metrics
|
|
18
|
+
@block = block
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def call
|
|
22
|
+
@block.call
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/perfgate.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "perfgate/version"
|
|
4
|
+
require_relative "perfgate/errors"
|
|
5
|
+
require_relative "perfgate/config"
|
|
6
|
+
require_relative "perfgate/workloads/registry"
|
|
7
|
+
require_relative "perfgate/execution/sample_context"
|
|
8
|
+
|
|
9
|
+
# Baseline is a CI-native performance assurance tool for Ruby on Rails
|
|
10
|
+
# applications. It converts selected RSpec examples into repeatable
|
|
11
|
+
# performance workloads and compares them against a compatible
|
|
12
|
+
# default-branch baseline to produce a merge-gate decision.
|
|
13
|
+
module Perfgate
|
|
14
|
+
class << self
|
|
15
|
+
# Explicitly marks the block whose execution should be measured by
|
|
16
|
+
# Baseline (spec section 9.1). Outside of a running workload sample
|
|
17
|
+
# (e.g. called directly in a plain unit test) this simply executes
|
|
18
|
+
# the block and returns its value without recording anything.
|
|
19
|
+
def measure(&block)
|
|
20
|
+
context = Execution::SampleContext.current
|
|
21
|
+
return block.call unless context
|
|
22
|
+
|
|
23
|
+
context.measure(&block)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The active configuration, loaded via Config.load or Config.default.
|
|
27
|
+
# `baseline run` assigns this after loading baseline.yml.
|
|
28
|
+
def configuration
|
|
29
|
+
@configuration ||= Config.default
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
attr_writer :configuration
|
|
33
|
+
|
|
34
|
+
# Yields the active configuration for in-code customization, e.g.
|
|
35
|
+
# `Perfgate.configure { |config| config.dataset_fingerprint = -> { ... } }`
|
|
36
|
+
# (spec section 12.3).
|
|
37
|
+
def configure
|
|
38
|
+
yield configuration
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# The process-wide workload registry that RSpec discovery populates.
|
|
42
|
+
def registry
|
|
43
|
+
Workloads::Registry.instance
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/perfgate.gemspec
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/perfgate/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "perfgate"
|
|
7
|
+
spec.version = Perfgate::VERSION
|
|
8
|
+
spec.authors = ["Alexander Potrakhov"]
|
|
9
|
+
spec.email = ["bendthe@gmail.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "CI-native performance regression assurance for Rails and RSpec."
|
|
12
|
+
spec.description = "Baseline converts selected RSpec examples into repeatable performance " \
|
|
13
|
+
"workloads, measures application-level signals (duration, SQL activity, " \
|
|
14
|
+
"allocations, GC), compares a pull request against a compatible " \
|
|
15
|
+
"default-branch baseline, and produces a clear CI merge-gate decision."
|
|
16
|
+
spec.homepage = "https://github.com/a11ejandro/perfgate"
|
|
17
|
+
spec.license = "Apache-2.0"
|
|
18
|
+
spec.required_ruby_version = ">= 3.1.0"
|
|
19
|
+
|
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
21
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
|
22
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
23
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
24
|
+
|
|
25
|
+
# Specify which files should be added to the gem when it is released.
|
|
26
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
27
|
+
spec.files = Dir.chdir(__dir__) do
|
|
28
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
29
|
+
(File.expand_path(f) == __FILE__) ||
|
|
30
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ spikes/ .git .github appveyor Gemfile])
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
spec.bindir = "exe"
|
|
34
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
35
|
+
spec.require_paths = ["lib"]
|
|
36
|
+
|
|
37
|
+
spec.add_dependency "rspec-core", "~> 3.12"
|
|
38
|
+
|
|
39
|
+
# For more information and examples about making a new gem, check out our
|
|
40
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
|
41
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://baseline.dev/schemas/comparison-result-v1.schema.json",
|
|
4
|
+
"title": "Baseline Comparison Result v1",
|
|
5
|
+
"description": "Placeholder schema. To be defined per section 14.2 of the technical specification.",
|
|
6
|
+
"type": "object"
|
|
7
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://baseline.dev/schemas/run-result-v1.schema.json",
|
|
4
|
+
"title": "Baseline Run Result v1",
|
|
5
|
+
"description": "Placeholder schema. To be defined per section 14.1 of the technical specification.",
|
|
6
|
+
"type": "object"
|
|
7
|
+
}
|
data/sig/perfgate.rbs
ADDED
metadata
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: perfgate
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Alexander Potrakhov
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-08-27 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rspec-core
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.12'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '3.12'
|
|
27
|
+
description: Baseline converts selected RSpec examples into repeatable performance
|
|
28
|
+
workloads, measures application-level signals (duration, SQL activity, allocations,
|
|
29
|
+
GC), compares a pull request against a compatible default-branch baseline, and produces
|
|
30
|
+
a clear CI merge-gate decision.
|
|
31
|
+
email:
|
|
32
|
+
- bendthe@gmail.com
|
|
33
|
+
executables:
|
|
34
|
+
- perfgate
|
|
35
|
+
extensions: []
|
|
36
|
+
extra_rdoc_files: []
|
|
37
|
+
files:
|
|
38
|
+
- ".rspec"
|
|
39
|
+
- ".rubocop.yml"
|
|
40
|
+
- CHANGELOG.md
|
|
41
|
+
- CONTRIBUTING.md
|
|
42
|
+
- LICENSE
|
|
43
|
+
- NOT_FINALIZED.md
|
|
44
|
+
- README.md
|
|
45
|
+
- ROADMAP.md
|
|
46
|
+
- Rakefile
|
|
47
|
+
- SECURITY.md
|
|
48
|
+
- docs/README.md
|
|
49
|
+
- docs/architecture.md
|
|
50
|
+
- docs/compatibility.md
|
|
51
|
+
- docs/launch-article.md
|
|
52
|
+
- docs/onboarding.md
|
|
53
|
+
- docs/telemetry.md
|
|
54
|
+
- examples/rails-rspec-app/.github/workflows/baseline.yml
|
|
55
|
+
- examples/rails-rspec-app/README.md
|
|
56
|
+
- examples/rails-rspec-app/spec/jobs/invoice_job_spec.rb
|
|
57
|
+
- examples/rails-rspec-app/spec/requests/checkout_spec.rb
|
|
58
|
+
- exe/perfgate
|
|
59
|
+
- lib/perfgate.rb
|
|
60
|
+
- lib/perfgate/cli.rb
|
|
61
|
+
- lib/perfgate/cli/compare_command.rb
|
|
62
|
+
- lib/perfgate/cli/run_command.rb
|
|
63
|
+
- lib/perfgate/cli/run_comparison_reporter.rb
|
|
64
|
+
- lib/perfgate/comparison/deterministic_metric_decision.rb
|
|
65
|
+
- lib/perfgate/comparison/diagnostics.rb
|
|
66
|
+
- lib/perfgate/comparison/engine.rb
|
|
67
|
+
- lib/perfgate/comparison/metric_change.rb
|
|
68
|
+
- lib/perfgate/comparison/metric_decision.rb
|
|
69
|
+
- lib/perfgate/comparison/statistical_metric_decision.rb
|
|
70
|
+
- lib/perfgate/comparison/workload_comparison.rb
|
|
71
|
+
- lib/perfgate/config.rb
|
|
72
|
+
- lib/perfgate/config/defaults.rb
|
|
73
|
+
- lib/perfgate/config/env_overrides.rb
|
|
74
|
+
- lib/perfgate/config/schema.rb
|
|
75
|
+
- lib/perfgate/config/validator.rb
|
|
76
|
+
- lib/perfgate/errors.rb
|
|
77
|
+
- lib/perfgate/execution/process_runner.rb
|
|
78
|
+
- lib/perfgate/execution/runner.rb
|
|
79
|
+
- lib/perfgate/execution/sample_context.rb
|
|
80
|
+
- lib/perfgate/fingerprints/compatibility.rb
|
|
81
|
+
- lib/perfgate/fingerprints/components.rb
|
|
82
|
+
- lib/perfgate/fingerprints/workload_definition.rb
|
|
83
|
+
- lib/perfgate/instrumentation.rb
|
|
84
|
+
- lib/perfgate/instrumentation/allocations.rb
|
|
85
|
+
- lib/perfgate/instrumentation/duration.rb
|
|
86
|
+
- lib/perfgate/instrumentation/gc.rb
|
|
87
|
+
- lib/perfgate/instrumentation/sql_activity.rb
|
|
88
|
+
- lib/perfgate/metrics/.gitkeep
|
|
89
|
+
- lib/perfgate/policy/engine.rb
|
|
90
|
+
- lib/perfgate/rails/.gitkeep
|
|
91
|
+
- lib/perfgate/report/console.rb
|
|
92
|
+
- lib/perfgate/report/markdown.rb
|
|
93
|
+
- lib/perfgate/reporting/.gitkeep
|
|
94
|
+
- lib/perfgate/rspec.rb
|
|
95
|
+
- lib/perfgate/rspec/discovery.rb
|
|
96
|
+
- lib/perfgate/rspec/id_resolver.rb
|
|
97
|
+
- lib/perfgate/rspec/workload_builder.rb
|
|
98
|
+
- lib/perfgate/serialization/run_result.rb
|
|
99
|
+
- lib/perfgate/statistics/mann_whitney_u.rb
|
|
100
|
+
- lib/perfgate/statistics/summary.rb
|
|
101
|
+
- lib/perfgate/storage/adapter.rb
|
|
102
|
+
- lib/perfgate/storage/archive.rb
|
|
103
|
+
- lib/perfgate/storage/filesystem.rb
|
|
104
|
+
- lib/perfgate/telemetry/.gitkeep
|
|
105
|
+
- lib/perfgate/version.rb
|
|
106
|
+
- lib/perfgate/workloads/registry.rb
|
|
107
|
+
- lib/perfgate/workloads/workload.rb
|
|
108
|
+
- perfgate.gemspec
|
|
109
|
+
- schemas/comparison-result-v1.schema.json
|
|
110
|
+
- schemas/run-result-v1.schema.json
|
|
111
|
+
- sig/perfgate.rbs
|
|
112
|
+
homepage: https://github.com/a11ejandro/perfgate
|
|
113
|
+
licenses:
|
|
114
|
+
- Apache-2.0
|
|
115
|
+
metadata:
|
|
116
|
+
homepage_uri: https://github.com/a11ejandro/perfgate
|
|
117
|
+
source_code_uri: https://github.com/a11ejandro/perfgate
|
|
118
|
+
changelog_uri: https://github.com/a11ejandro/perfgate/blob/main/CHANGELOG.md
|
|
119
|
+
rubygems_mfa_required: 'true'
|
|
120
|
+
post_install_message:
|
|
121
|
+
rdoc_options: []
|
|
122
|
+
require_paths:
|
|
123
|
+
- lib
|
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
125
|
+
requirements:
|
|
126
|
+
- - ">="
|
|
127
|
+
- !ruby/object:Gem::Version
|
|
128
|
+
version: 3.1.0
|
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
|
+
requirements:
|
|
131
|
+
- - ">="
|
|
132
|
+
- !ruby/object:Gem::Version
|
|
133
|
+
version: '0'
|
|
134
|
+
requirements: []
|
|
135
|
+
rubygems_version: 3.4.10
|
|
136
|
+
signing_key:
|
|
137
|
+
specification_version: 4
|
|
138
|
+
summary: CI-native performance regression assurance for Rails and RSpec.
|
|
139
|
+
test_files: []
|