specguard-ruby 0.3.31 → 0.3.33
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 +4 -4
- data/README.md +2 -2
- data/lib/specguard/client/configuration.rb +102 -2
- data/lib/specguard/client/delivery_warning.rb +43 -0
- data/lib/specguard/client/ingest_cli.rb +1 -2
- data/lib/specguard/client/transport.rb +15 -0
- data/lib/specguard/minitest/reporter.rb +5 -20
- data/lib/specguard/rspec/formatter.rb +5 -21
- data/lib/specguard/version.rb +1 -1
- data/script/bump-version.sh +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f0f1cdce1e2e763d549b0ccb1bd5d9a22b1c5a9da9f63645704af3ecd8149de1
|
|
4
|
+
data.tar.gz: aa80ba0c1f264a50d307c83fd1a8c9a543d6b5eef75037f53ac5ffef68c5d812
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4673b30c851eb2324326704ab72539c4a909b068f1addc354cb461de216816a05ee2f195b01c70a9c78cadd3810760d6d59c89947e6c56a31971ca6915e658e4
|
|
7
|
+
data.tar.gz: fd2ae5c3fafa5ed48b05c71f5109fea22b8b1796b7d0869cf1fb6bcfe2b8adaad440aa79c2cea493c2984bf7fb2a032fe17a7666d19387f4803852692f2f925d
|
data/README.md
CHANGED
|
@@ -1146,8 +1146,8 @@ body is encoded on the wire, never what is in it.
|
|
|
1146
1146
|
|
|
1147
1147
|
| Field | What it holds | Where it comes from |
|
|
1148
1148
|
| --- | --- | --- |
|
|
1149
|
-
| `commit_sha` | the commit the suite ran against | `SPECGUARD_COMMIT_SHA` if you set it, else `GITHUB_SHA`, `CI_COMMIT_SHA`, `CIRCLE_SHA1`, `BUILDKITE_COMMIT`, `GIT_COMMIT`, else `git rev-parse HEAD` |
|
|
1150
|
-
| `branch` | the branch name; `null` on a detached checkout | `SPECGUARD_BRANCH` if you set it, else `GITHUB_REF_NAME`, `CI_COMMIT_REF_NAME`, `CIRCLE_BRANCH`, `BUILDKITE_BRANCH`, `GIT_BRANCH`, else `git symbolic-ref --short -q HEAD` |
|
|
1149
|
+
| `commit_sha` | the commit the suite ran against | `SPECGUARD_COMMIT_SHA` if you set it, else — on a same-repository GitHub Actions `pull_request` / `pull_request_target` run — the pushed head sha from the event payload at `GITHUB_EVENT_PATH` (`GITHUB_SHA` there is an ephemeral merge commit), else `GITHUB_SHA`, `CI_COMMIT_SHA`, `CIRCLE_SHA1`, `BUILDKITE_COMMIT`, `GIT_COMMIT`, else `git rev-parse HEAD` |
|
|
1150
|
+
| `branch` | the branch name; `null` on a detached checkout | `SPECGUARD_BRANCH` if you set it, else — on a same-repository GitHub Actions `pull_request` / `pull_request_target` run — `GITHUB_HEAD_REF` (`GITHUB_REF_NAME` there is `<n>/merge`), else `GITHUB_REF_NAME`, `CI_COMMIT_REF_NAME`, `CIRCLE_BRANCH`, `BUILDKITE_BRANCH`, `GIT_BRANCH`, else `git symbolic-ref --short -q HEAD` |
|
|
1151
1151
|
| `ci_run_id` | your provider's build id, so shards of one run fold together; `null` on a laptop | `SPECGUARD_RUN_ID` if you set it, else `GITHUB_RUN_ID`, `CI_PIPELINE_ID`, `CIRCLE_WORKFLOW_ID`, `BUILDKITE_BUILD_ID`, `BUILD_TAG` |
|
|
1152
1152
|
| `shard_id` | which slice of that run this process is; `null` when unsharded | `SPECGUARD_SHARD_ID` if you set it, else `TEST_ENV_NUMBER`, `CI_NODE_INDEX`, `CIRCLE_NODE_INDEX`, `BUILDKITE_PARALLEL_JOB` |
|
|
1153
1153
|
| `duration_seconds` | wall clock for the whole run | measured by the formatter |
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "json"
|
|
4
|
+
|
|
3
5
|
module SpecGuard
|
|
4
6
|
module Client
|
|
5
7
|
# Where the checkout is sitting — which commit, and which branch — asked of
|
|
@@ -180,6 +182,12 @@ module SpecGuard
|
|
|
180
182
|
# every GitLab, CircleCI, Buildkite and Jenkins run 400ing as a matter of
|
|
181
183
|
# course — the *default* outcome on four of the five providers this gem is
|
|
182
184
|
# likely to meet.
|
|
185
|
+
#
|
|
186
|
+
# On a GitHub Actions `pull_request` / `pull_request_target` run from the
|
|
187
|
+
# same repository, the pushed head commit in the event payload
|
|
188
|
+
# (`#pull_request_head`) is consulted *between* `SPECGUARD_COMMIT_SHA` and
|
|
189
|
+
# the rest of this list: `GITHUB_SHA` there is the ephemeral merge commit
|
|
190
|
+
# (the base tip on `_target`), a sha nobody pushed.
|
|
183
191
|
COMMIT_SHA_KEYS = %w[
|
|
184
192
|
SPECGUARD_COMMIT_SHA
|
|
185
193
|
GITHUB_SHA
|
|
@@ -195,6 +203,11 @@ module SpecGuard
|
|
|
195
203
|
# (`origin/main` on many setups), because `branch` is a free-form string
|
|
196
204
|
# to the platform and inventing a normalization here would be this gem
|
|
197
205
|
# guessing at somebody's ref layout.
|
|
206
|
+
#
|
|
207
|
+
# On a same-repository GitHub Actions `pull_request` /
|
|
208
|
+
# `pull_request_target` run, {PULL_REQUEST_BRANCH_KEYS} (`GITHUB_HEAD_REF`,
|
|
209
|
+
# the source branch) is consulted between `SPECGUARD_BRANCH` and the rest
|
|
210
|
+
# of this list, because `GITHUB_REF_NAME` there is `<n>/merge`.
|
|
198
211
|
BRANCH_KEYS = %w[
|
|
199
212
|
SPECGUARD_BRANCH
|
|
200
213
|
GITHUB_REF_NAME
|
|
@@ -314,6 +327,22 @@ module SpecGuard
|
|
|
314
327
|
# than absent. See trap 1 above.
|
|
315
328
|
BLANK_MEANS_FIRST_SHARD_KEY = "TEST_ENV_NUMBER"
|
|
316
329
|
|
|
330
|
+
# GitHub Actions only: the event that triggered the run, the file holding
|
|
331
|
+
# its payload, and the source branch of a pull request. They are read
|
|
332
|
+
# only together, by `#pull_request_head`, and only when `GITHUB_EVENT_NAME`
|
|
333
|
+
# is one of {PULL_REQUEST_EVENTS}.
|
|
334
|
+
EVENT_NAME_KEYS = %w[GITHUB_EVENT_NAME].freeze
|
|
335
|
+
EVENT_PATH_KEYS = %w[GITHUB_EVENT_PATH].freeze
|
|
336
|
+
PULL_REQUEST_BRANCH_KEYS = %w[GITHUB_HEAD_REF].freeze
|
|
337
|
+
|
|
338
|
+
# The GitHub events whose `GITHUB_SHA` / `GITHUB_REF_NAME` describe a
|
|
339
|
+
# merge ref rather than anything a person pushed.
|
|
340
|
+
PULL_REQUEST_EVENTS = %w[pull_request pull_request_target].freeze
|
|
341
|
+
|
|
342
|
+
# Largest `GITHUB_EVENT_PATH` payload read; a bigger file is treated as
|
|
343
|
+
# unreadable (mirrors specguard-ts).
|
|
344
|
+
MAX_EVENT_PAYLOAD_BYTES = 1024 * 1024
|
|
345
|
+
|
|
317
346
|
OUTPUT_PATH_KEYS = %w[SPECGUARD_OUTPUT_PATH].freeze
|
|
318
347
|
LOCAL_OUTPUT_PATH_KEYS = %w[SPECGUARD_LOCAL_OUTPUT_PATH].freeze
|
|
319
348
|
ENDPOINT_KEYS = %w[SPECGUARD_ENDPOINT].freeze
|
|
@@ -377,10 +406,22 @@ module SpecGuard
|
|
|
377
406
|
# reason, and so a test does not silently pick up the sha or the branch
|
|
378
407
|
# of whatever repository it runs in.
|
|
379
408
|
def initialize(env: ENV, git: GitCheckout)
|
|
380
|
-
|
|
409
|
+
explicit_sha = first_present(env, COMMIT_SHA_KEYS.first(1))
|
|
410
|
+
explicit_branch = first_present(env, BRANCH_KEYS.first(1))
|
|
411
|
+
# One read of the event payload decides branch and sha together, so
|
|
412
|
+
# they cannot disagree; skipped when both were set explicitly.
|
|
413
|
+
pr_head = explicit_sha && explicit_branch ? nil : pull_request_head(env)
|
|
414
|
+
|
|
381
415
|
# `||` short-circuits, which is the whole of "do not spawn a subprocess
|
|
382
416
|
# when a provider already answered".
|
|
383
|
-
@
|
|
417
|
+
@commit_sha = explicit_sha ||
|
|
418
|
+
pr_head&.fetch(:sha) ||
|
|
419
|
+
first_present(env, COMMIT_SHA_KEYS) ||
|
|
420
|
+
blank_to_nil(git.commit_sha)
|
|
421
|
+
@branch = explicit_branch ||
|
|
422
|
+
(pr_head && first_present(env, PULL_REQUEST_BRANCH_KEYS)) ||
|
|
423
|
+
first_present(env, BRANCH_KEYS) ||
|
|
424
|
+
blank_to_nil(git.branch)
|
|
384
425
|
@run_id = first_present(env, RUN_ID_KEYS)
|
|
385
426
|
@shard_id = resolve_shard_id(env)
|
|
386
427
|
@output_path = first_present(env, OUTPUT_PATH_KEYS) || DEFAULT_OUTPUT_PATH
|
|
@@ -393,6 +434,65 @@ module SpecGuard
|
|
|
393
434
|
|
|
394
435
|
private
|
|
395
436
|
|
|
437
|
+
# The pushed head of a GitHub Actions pull-request run, or nil when it
|
|
438
|
+
# cannot be established as a SAME-REPOSITORY pull request.
|
|
439
|
+
#
|
|
440
|
+
# On `pull_request` / `pull_request_target`, `GITHUB_SHA` is the
|
|
441
|
+
# ephemeral merge commit (the base tip on `_target`) and
|
|
442
|
+
# `GITHUB_REF_NAME` is `<n>/merge` — neither is anything a person pushed.
|
|
443
|
+
# `git rev-parse HEAD` does not rescue it: `actions/checkout` puts the
|
|
444
|
+
# merge commit at HEAD. The real head sha lives only in the event payload
|
|
445
|
+
# at `GITHUB_EVENT_PATH`.
|
|
446
|
+
#
|
|
447
|
+
# A fork PR yields nil: `GITHUB_HEAD_REF` is then the FORK's branch name
|
|
448
|
+
# (`main` on a `contrib:main` PR would be filed under the base
|
|
449
|
+
# repository's own `main`), so the merge-ref behaviour is kept. A
|
|
450
|
+
# missing, unreadable, oversized or garbled payload also yields nil.
|
|
451
|
+
# Never raises and shells out to nothing.
|
|
452
|
+
#
|
|
453
|
+
# @return [Hash{Symbol=>String,nil}, nil] `{sha:}` — sha is nil when the
|
|
454
|
+
# payload's head sha is not 40 hex characters (the branch is still the
|
|
455
|
+
# source branch then) — or nil when this is not a same-repo PR.
|
|
456
|
+
def pull_request_head(env)
|
|
457
|
+
return nil unless PULL_REQUEST_EVENTS.include?(first_present(env, EVENT_NAME_KEYS))
|
|
458
|
+
|
|
459
|
+
path = first_present(env, EVENT_PATH_KEYS)
|
|
460
|
+
return nil if path.nil?
|
|
461
|
+
|
|
462
|
+
pull_request = read_event_payload(path)&.fetch("pull_request", nil)
|
|
463
|
+
return nil unless pull_request.is_a?(Hash)
|
|
464
|
+
|
|
465
|
+
head = pull_request["head"]
|
|
466
|
+
base = pull_request["base"]
|
|
467
|
+
head_repo = repo_full_name(head)
|
|
468
|
+
return nil if head_repo.nil? || head_repo != repo_full_name(base)
|
|
469
|
+
|
|
470
|
+
sha = head["sha"]
|
|
471
|
+
{ sha: sha.is_a?(String) && sha.match?(/\A[0-9a-f]{40}\z/i) ? sha : nil }
|
|
472
|
+
rescue ScriptError, StandardError
|
|
473
|
+
nil
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
def repo_full_name(side)
|
|
477
|
+
return nil unless side.is_a?(Hash) && side["repo"].is_a?(Hash)
|
|
478
|
+
|
|
479
|
+
name = side["repo"]["full_name"]
|
|
480
|
+
name.is_a?(String) && !name.empty? ? name : nil
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
# @return [Hash, nil] the parsed payload, or nil if it is absent, not a
|
|
484
|
+
# regular file, larger than {MAX_EVENT_PAYLOAD_BYTES}, or not a JSON
|
|
485
|
+
# object.
|
|
486
|
+
def read_event_payload(path)
|
|
487
|
+
return nil unless File.file?(path)
|
|
488
|
+
|
|
489
|
+
raw = File.open(path, "rb") { |file| file.read(MAX_EVENT_PAYLOAD_BYTES + 1) }
|
|
490
|
+
return nil if raw.nil? || raw.bytesize > MAX_EVENT_PAYLOAD_BYTES
|
|
491
|
+
|
|
492
|
+
parsed = JSON.parse(raw)
|
|
493
|
+
parsed.is_a?(Hash) ? parsed : nil
|
|
494
|
+
end
|
|
495
|
+
|
|
396
496
|
# {SHARD_ID_KEYS} in order, first non-blank wins — except that a
|
|
397
497
|
# {BLANK_MEANS_FIRST_SHARD_KEY} which is *set* counts as a hit even when
|
|
398
498
|
# it is empty, and resolves to `"1"`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SpecGuard
|
|
4
|
+
module Client
|
|
5
|
+
# The two clauses that finish a delivery-failure warning line, shared by
|
|
6
|
+
# the RSpec formatter and the Minitest reporter.
|
|
7
|
+
#
|
|
8
|
+
# Both clients print the same sentence after their own prefix and status
|
|
9
|
+
# clause: where the run ended up, and (when it was saved) the command that
|
|
10
|
+
# gets it back. They used to carry two inline copies kept equal
|
|
11
|
+
# "word-for-word" by hand, and the pair had already been co-edited in
|
|
12
|
+
# separate commits (SPGD-1139, SPGD-1413). One definition here means a
|
|
13
|
+
# wording change cannot reach one client and miss the other.
|
|
14
|
+
#
|
|
15
|
+
# What stays in each client: the prefix, the warning budget (`@warned`),
|
|
16
|
+
# and the `append` that decides whether `error` is nil. Those differ by
|
|
17
|
+
# design; only the clause text is shared.
|
|
18
|
+
module DeliveryWarning
|
|
19
|
+
module_function
|
|
20
|
+
|
|
21
|
+
# Report, not promise. Composed after the write so it can tell the
|
|
22
|
+
# operator which of the two things actually happened. `error` is the
|
|
23
|
+
# client's `append` answer: `nil` means the queue took the run (the
|
|
24
|
+
# success arm, {#replay_clause}); anything else means both sinks are
|
|
25
|
+
# gone and the run really is lost (SPGD-1413).
|
|
26
|
+
def sink_clause(path, error)
|
|
27
|
+
return replay_clause(path) if error.nil?
|
|
28
|
+
|
|
29
|
+
"The replay queue #{path} could not be written either " \
|
|
30
|
+
"(#{error.class}: #{error.message}), so this run's telemetry was lost."
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# The success arm (SPGD-1139): where the run sits AND the command that
|
|
34
|
+
# gets it back, fix-the-delivery first and replay after — the order the
|
|
35
|
+
# ingest CLI's own doctrine describes. The lost-run arm deliberately
|
|
36
|
+
# names no command: with no queue written there is nothing to replay.
|
|
37
|
+
def replay_clause(path)
|
|
38
|
+
"Falling back to #{path}; the test run is unaffected. " \
|
|
39
|
+
"Once the delivery is fixed, replay this run with: bundle exec specguard-ingest #{path}"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -739,8 +739,7 @@ module SpecGuard
|
|
|
739
739
|
raise UsageError, "no endpoint is configured (set SPECGUARD_ENDPOINT)" if blank?(configuration.endpoint)
|
|
740
740
|
raise UsageError, "no API key is configured (set SPECGUARD_API_KEY)" if blank?(configuration.api_key)
|
|
741
741
|
|
|
742
|
-
transport = Transport.
|
|
743
|
-
timeout: configuration.timeout, repository_id: configuration.repository_id)
|
|
742
|
+
transport = Transport.from_configuration(configuration)
|
|
744
743
|
# Asked once, here, so a malformed `SPECGUARD_ENDPOINT` is one exit 2
|
|
745
744
|
# rather than N identical `:failed` lines. `Transport#deliver` would
|
|
746
745
|
# otherwise swallow the same `ArgumentError` once per line and report a
|
|
@@ -293,6 +293,21 @@ module SpecGuard
|
|
|
293
293
|
end
|
|
294
294
|
end
|
|
295
295
|
|
|
296
|
+
# Builds a transport from a {Configuration}, projecting the four settings
|
|
297
|
+
# every ingest writer forwards (endpoint, api_key, timeout, repository_id)
|
|
298
|
+
# so a new keyword is threaded in one place rather than in each writer.
|
|
299
|
+
#
|
|
300
|
+
# @param configuration [Configuration, #endpoint, #api_key, #timeout, #repository_id]
|
|
301
|
+
# @return [Transport]
|
|
302
|
+
def self.from_configuration(configuration)
|
|
303
|
+
new(
|
|
304
|
+
endpoint: configuration.endpoint,
|
|
305
|
+
api_key: configuration.api_key,
|
|
306
|
+
timeout: configuration.timeout,
|
|
307
|
+
repository_id: configuration.repository_id
|
|
308
|
+
)
|
|
309
|
+
end
|
|
310
|
+
|
|
296
311
|
# @param endpoint [String, nil] the installation's base URL. Any trailing
|
|
297
312
|
# slashes are dropped; a path prefix is preserved, so an installation
|
|
298
313
|
# behind `https://tools.example.com/specguard` works.
|
|
@@ -9,6 +9,7 @@ require "fileutils"
|
|
|
9
9
|
# loads them on a minitest-only consumer's machine.
|
|
10
10
|
require_relative "../client"
|
|
11
11
|
require_relative "../client/configuration"
|
|
12
|
+
require_relative "../client/delivery_warning"
|
|
12
13
|
|
|
13
14
|
# The annotation lookup is the third framework-free half: what counts as a
|
|
14
15
|
# test's annotation is a property of the source line, not of the framework
|
|
@@ -244,12 +245,7 @@ module SpecGuard
|
|
|
244
245
|
|
|
245
246
|
def transport_for
|
|
246
247
|
require_relative "../client/transport"
|
|
247
|
-
SpecGuard::Client::Transport.
|
|
248
|
-
endpoint: @configuration.endpoint,
|
|
249
|
-
api_key: @configuration.api_key,
|
|
250
|
-
timeout: @configuration.timeout,
|
|
251
|
-
repository_id: @configuration.repository_id
|
|
252
|
-
)
|
|
248
|
+
SpecGuard::Client::Transport.from_configuration(@configuration)
|
|
253
249
|
end
|
|
254
250
|
|
|
255
251
|
def row_for(result)
|
|
@@ -404,21 +400,10 @@ module SpecGuard
|
|
|
404
400
|
end
|
|
405
401
|
|
|
406
402
|
# Report, not promise — see `#fall_back` for why that is the whole of
|
|
407
|
-
# this slice, and why the order above it did not move.
|
|
403
|
+
# this slice, and why the order above it did not move. The wording is
|
|
404
|
+
# shared with the RSpec formatter in {Client::DeliveryWarning}.
|
|
408
405
|
def sink_clause(path, error)
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
"The replay queue #{path} could not be written either " \
|
|
412
|
-
"(#{error.class}: #{error.message}), so this run's telemetry was lost."
|
|
413
|
-
end
|
|
414
|
-
|
|
415
|
-
# The success arm (SPGD-1139): names the configured path (the one
|
|
416
|
-
# `#append` just wrote) and the replay command, word-for-word the
|
|
417
|
-
# formatter's clause. The lost-run arm names no command — nothing to
|
|
418
|
-
# replay.
|
|
419
|
-
def replay_clause(path)
|
|
420
|
-
"Falling back to #{path}; the test run is unaffected. " \
|
|
421
|
-
"Once the delivery is fixed, replay this run with: bundle exec specguard-ingest #{path}"
|
|
406
|
+
SpecGuard::Client::DeliveryWarning.sink_clause(path, error)
|
|
422
407
|
end
|
|
423
408
|
|
|
424
409
|
# Once per process, like the formatter's `warn_once`: fifty failing
|
|
@@ -48,6 +48,7 @@ require "fileutils"
|
|
|
48
48
|
require_relative "../rspec"
|
|
49
49
|
require_relative "../client/configuration"
|
|
50
50
|
require_relative "../client/transport"
|
|
51
|
+
require_relative "../client/delivery_warning"
|
|
51
52
|
# Brings the linter's discovery chain with it (Scanner, Finding, Schema). That
|
|
52
53
|
# direction is safe — `specguard/rspec` does not require `rspec/core`, so the
|
|
53
54
|
# linter stays loadable without RSpec; it is only the reverse that would break
|
|
@@ -1037,12 +1038,7 @@ module SpecGuard
|
|
|
1037
1038
|
end
|
|
1038
1039
|
|
|
1039
1040
|
def transport_for(configuration)
|
|
1040
|
-
SpecGuard::Client::Transport.
|
|
1041
|
-
endpoint: configuration.endpoint,
|
|
1042
|
-
api_key: configuration.api_key,
|
|
1043
|
-
timeout: configuration.timeout,
|
|
1044
|
-
repository_id: configuration.repository_id
|
|
1045
|
-
)
|
|
1041
|
+
SpecGuard::Client::Transport.from_configuration(configuration)
|
|
1046
1042
|
end
|
|
1047
1043
|
|
|
1048
1044
|
def blank?(value)
|
|
@@ -1201,22 +1197,10 @@ module SpecGuard
|
|
|
1201
1197
|
|
|
1202
1198
|
# Report, not promise. Composed after the write so it can tell the operator
|
|
1203
1199
|
# which of the two things actually happened — see {#fall_back} for why that
|
|
1204
|
-
# is the whole of this slice, and why the order above it did not move.
|
|
1200
|
+
# is the whole of this slice, and why the order above it did not move. The
|
|
1201
|
+
# wording is shared with the Minitest reporter in {Client::DeliveryWarning}.
|
|
1205
1202
|
def sink_clause(path, error)
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
"The replay queue #{path} could not be written either " \
|
|
1209
|
-
"(#{error.class}: #{error.message}), so this run's telemetry was lost."
|
|
1210
|
-
end
|
|
1211
|
-
|
|
1212
|
-
# The success arm (SPGD-1139): where the run sits AND the command that gets
|
|
1213
|
-
# it back, fix-the-delivery first and replay after — the order the ingest
|
|
1214
|
-
# CLI's own doctrine describes. The lost-run arm above deliberately names no
|
|
1215
|
-
# command: with no queue written there is nothing to replay. Kept
|
|
1216
|
-
# word-for-word identical to the Minitest reporter's clause.
|
|
1217
|
-
def replay_clause(path)
|
|
1218
|
-
"Falling back to #{path}; the test run is unaffected. " \
|
|
1219
|
-
"Once the delivery is fixed, replay this run with: bundle exec specguard-ingest #{path}"
|
|
1203
|
+
SpecGuard::Client::DeliveryWarning.sink_clause(path, error)
|
|
1220
1204
|
end
|
|
1221
1205
|
|
|
1222
1206
|
def emit_warning(line)
|
data/lib/specguard/version.rb
CHANGED
data/script/bump-version.sh
CHANGED
|
@@ -58,9 +58,9 @@ if git rev-parse -q --verify "refs/tags/v$NEW_VERSION" >/dev/null || \
|
|
|
58
58
|
exit 1
|
|
59
59
|
fi
|
|
60
60
|
if command -v curl >/dev/null 2>&1; then
|
|
61
|
-
if curl -fsS --max-time 10 "https://rubygems.org/api/v1/versions/specguard-
|
|
61
|
+
if curl -fsS --max-time 10 "https://rubygems.org/api/v1/versions/specguard-ruby.json" 2>/dev/null \
|
|
62
62
|
| grep -q "\"number\":\"$NEW_VERSION\""; then
|
|
63
|
-
echo "Error: specguard-
|
|
63
|
+
echo "Error: specguard-ruby $NEW_VERSION is already published on RubyGems"
|
|
64
64
|
exit 1
|
|
65
65
|
fi
|
|
66
66
|
fi
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: specguard-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.33
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- specguard Agent
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: json
|
|
@@ -52,6 +52,7 @@ files:
|
|
|
52
52
|
- lib/specguard/client/annotation_scanner.rb
|
|
53
53
|
- lib/specguard/client/cli.rb
|
|
54
54
|
- lib/specguard/client/configuration.rb
|
|
55
|
+
- lib/specguard/client/delivery_warning.rb
|
|
55
56
|
- lib/specguard/client/file_selector.rb
|
|
56
57
|
- lib/specguard/client/finding.rb
|
|
57
58
|
- lib/specguard/client/ingest_cli.rb
|