conformance-kit 0.4.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f0701a2aba3683c8dff95e66fb8721c6a5dc51211e3afdb10ab30eaf8dae480
4
- data.tar.gz: def47390a131f01068f3da132c1054ba763ceff96a64a103d7b39064e4d60f7b
3
+ metadata.gz: 18bb6e4722bbdc745b4efcbd1f9b3c3106b6193f235f9657d33e94f41c93b38a
4
+ data.tar.gz: 6b023ed04a3167ab8a43f0689691a4416b7ab5fcb2714d71bb1864d62162c3df
5
5
  SHA512:
6
- metadata.gz: b875f57d615bb14cfe2bbb42f0250409c3dcf91e30c344d44a59f3dc3a71a8ed4c7ddb64dc56972db6bf86292a4ee049483c9ee89fb49ad568fc0f3a6cd1e3d1
7
- data.tar.gz: 6b52bcfc88febff716fa8554ab6b4c44c3729b8762d94151f48c535a0af6d5207fa27db63e5e64a10d879fda0bf96653f3b7f2e10626df770342abb502c99eed
6
+ metadata.gz: 16280d264476d1b02f60039e2c03dc821fc3f063e861b90a5b3fceae5e0fd53620d51c538cdd290169a5c348ac178b565b03c1867acdf24d37992ee5152ce061
7
+ data.tar.gz: 46cbb7fcfdf0ed59f99aa8f11b837b5aff4ad502062b66f0a964feb6f9e7529059f61c86451b276529c78b18f3f933e3438f8b916385a05350a510bb7f7d2ae8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ - `ConformanceKit::Store.fetch` on a non-main Ractor below Ruby 3.4: threads that race on the first fetch now get the first value stored instead of each keeping its own (the race shrinks from the whole initializer to the publish; a thread switch inside the publish itself remains possible, as no Ractor-local lock exists before 3.4) (found by zoolutions/docs-kit#103, whose copy of the Store had the same `||= [yield]`).
6
+
3
7
  ## 0.4.0
4
8
 
5
9
  - `main_only:` takes `ancestor:` rules (with optional `ivars:`): framework class state on the gem's own subclasses (ActiveRecord, ActionController, Rails::Engine, ActiveSupport::Concern, ...) in one entry per framework instead of one per ivar per class. Constants are never covered; unused rules are listed as stale; an entry with an unknown key, or an ancestor every module has (`Object`, `Module`, ...), is a config error. `Audit::Finding` gains a `rule` member (the covering rule, or nil).
data/README.md CHANGED
@@ -16,7 +16,7 @@ Background, the finalize-at-boot pattern and the settled decisions: [zoolutions/
16
16
  ```ruby
17
17
  # Gemfile
18
18
  group :development, :test do
19
- gem "conformance-kit", "~> 0.3", require: false
19
+ gem "conformance-kit", "~> 0.4", require: false
20
20
  gem "rubocop-thread_safety", ">= 0.8", require: false # for config/rubocop.yml
21
21
  gem "async", require: false # optional: runs the fiber example
22
22
  end
@@ -182,7 +182,7 @@ Turns on the six `rubocop-thread_safety` cops (`ClassAndModuleAttributes`, `Clas
182
182
  Conformance runs as **one reusable workflow in this repo**, `.github/workflows/conformance.yml`. Any repo can call it, inside zoolutions or not. A repo opts in with
183
183
 
184
184
  1. `.conformance.yml` (above),
185
- 2. the Gemfile lines (`conformance-kit ~> 0.3`, `rubocop-thread_safety >= 0.8`),
185
+ 2. the Gemfile lines (`conformance-kit ~> 0.4`, `rubocop-thread_safety >= 0.8`),
186
186
  3. `inherit_gem: { conformance-kit: config/rubocop.yml }` in `.rubocop.yml`,
187
187
  4. a caller, pinned to a release tag:
188
188
 
@@ -199,7 +199,7 @@ permissions:
199
199
 
200
200
  jobs:
201
201
  conformance:
202
- uses: zoolutions/conformance-kit/.github/workflows/conformance.yml@v0.3.0
202
+ uses: zoolutions/conformance-kit/.github/workflows/conformance.yml@v0.4.0
203
203
  ```
204
204
 
205
205
  To make it a merge requirement, add `conformance / Conformance settings` and `conformance / Conformance (Ruby 4.0)` to the required status checks in the repo's branch ruleset. Require both: if the settings job fails, the gate is skipped, and a skipped check does not block a merge. The prefix is the caller's job id (`conformance` above) and the Ruby is `ractor.ruby`, so the names change with either. Leave the probes out: they never fail. A repo or org that only allows selected actions must allow `zoolutions/conformance-kit/.github/workflows/conformance.yml@*`.
@@ -220,6 +220,7 @@ version: 2
220
220
  multi-ecosystem-groups:
221
221
  conformance-kit:
222
222
  schedule: { interval: weekly }
223
+ labels: ["dependencies", "devops"] # your repo's own type + area labels
223
224
  updates:
224
225
  - package-ecosystem: github-actions
225
226
  directory: /
@@ -8,8 +8,11 @@ module ConformanceKit
8
8
  # a Mutex, created at load (never lazily, so there is no check-then-set race);
9
9
  # it is the kit's one allowlisted main-only state (.conformance.yml). A
10
10
  # non-main Ractor on 3.2/3.3 cannot read it, so it keeps its own values in
11
- # Ractor-local storage instead (not locked: one Ractor's threads may race to
12
- # build a value, as with any `||=`).
11
+ # Ractor-local storage instead. No lock can be shared there, so threads of
12
+ # one Ractor may each build a value; they all return the first one
13
+ # published, except in the rare case of a thread switch inside the publish
14
+ # itself (`Ractor.current[slot] ||= built` is a read and a write), which no
15
+ # Ractor-local primitive before 3.4 can close.
13
16
  module Store
14
17
  # rubocop:disable ThreadSafety/MutableClassInstanceVariable -- main-only fallback, guarded by @fallback_lock
15
18
  @fallback_lock = Mutex.new
@@ -31,9 +34,17 @@ module ConformanceKit
31
34
 
32
35
  def main_ractor? = !defined?(::Ractor) || ::Ractor.current == ::Ractor.main
33
36
 
34
- # Boxed, so a nil or false value is cached rather than rebuilt on every fetch.
37
+ # Boxed, so a nil or false value is cached rather than rebuilt on every
38
+ # fetch. Built before the check-and-publish, never between them: threads
39
+ # that raced on the build return whichever value was stored first (see
40
+ # the module comment for the switch-inside-the-publish limit).
35
41
  def ractor_local(key)
36
- (::Ractor.current[:"conformance_kit_store/#{key}"] ||= [yield]).first
42
+ slot = :"conformance_kit_store/#{key}"
43
+ stored = ::Ractor.current[slot]
44
+ return stored.first if stored
45
+
46
+ built = [yield]
47
+ (::Ractor.current[slot] ||= built).first
37
48
  end
38
49
 
39
50
  public
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ConformanceKit
4
- VERSION = "0.4.0"
4
+ VERSION = "0.4.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: conformance-kit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - mhenrixon