featureparity 0.0.29 → 0.0.30

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: 5cef61c9093573a494f9d27b203554e51dfc2f0a6d60ae43e666564c8e2b1740
4
- data.tar.gz: 7162500244354be8c93a78499e479ac30a7df2d25ab4f818ce3451a6819ce960
3
+ metadata.gz: 7b3bad4ccc28e0695bdb790ecc37d6836d5477a84de09442c5255df871d98444
4
+ data.tar.gz: 67fcd3d1ac1a1a7bd41197ae674942fea80d20bbea22d856075face50ad87007
5
5
  SHA512:
6
- metadata.gz: a4733078f1af140723dadb54a0ed5e3ba5c80b771a48ba9f8364c6dcfb088cb9e3c39c79fac27b0fd5083e2339e47b8b6fb76fe5c54fde772f68fdbc2a005e7d
7
- data.tar.gz: 21330096e2f61cf6100dc54708c25818647f88581e0d0ef073bc84b2ec532556582012d899a663a0e96ce9e757ff6f5ae0ec51338be797bc19363f40e97d86af
6
+ metadata.gz: b276bc10363baf2fe27e843e0824ed205ed62f7836f4671cf53db15fc92ddc6a579a2fb1f5da34c4f34e672ffe2c14c418d10239e55066aa1a4b5806f078b930
7
+ data.tar.gz: 2769c008ecac2bdd2f02c13ef34cdc91619085709965138dc8750ab4127ebd22d119eae646a89202217db47235ddc4e75e1efae24528feeed1b1a7d53ec20f80
data/lib/fp/client.rb CHANGED
@@ -318,12 +318,16 @@ module Fp
318
318
  # only do that by fetching the test files from GitHub, which fails silently on a
319
319
  # private repo, so resolved results are always sent when we have them.
320
320
  def ingest_ci_results(project_id, ci_url:, surface:, junit_xml:, pr_url: nil, results: nil,
321
- test_revisions: nil, unmarked_failures: nil, orphan_markers: nil, sha: nil)
321
+ test_revisions: nil, unmarked_failures: nil, orphan_markers: nil, sha: nil,
322
+ local: false)
322
323
  body = {
323
324
  ci_url: ci_url,
324
325
  surface: surface,
325
326
  junit_xml: junit_xml
326
327
  }
328
+ # A run on someone's machine rather than in CI (`fp ci-report --local`): there may be
329
+ # no run URL to record, and the server only accepts that when told so.
330
+ body[:local] = true if local
327
331
  # Only send pr_url when set, so a merged-branch run stays a plain ingest.
328
332
  body[:pr_url] = pr_url if pr_url && !pr_url.empty?
329
333
  # The checkout commit, so the receipt (or a PR run's branch verdict) links the
@@ -49,6 +49,12 @@ module Fp
49
49
  # of `passing`, and no merged evidence is demoted. Run it without --pr on pushes to
50
50
  # the default branch to record the real `passing`, superseding any pr_passing a prior
51
51
  # PR run left behind.
52
+ #
53
+ # --local is for when there is no CI to run the suite — a team out of CI minutes, or
54
+ # one without a pipeline yet (Fizzy #1837). A person runs the suite on their own
55
+ # machine and reports it the same way CI would; --ci-url becomes optional. The verdict
56
+ # is stamped on HEAD, so the working tree has to be clean: a result from edits nobody
57
+ # committed would be recorded against a commit that never ran them.
52
58
  class CiReport < Base
53
59
  help_summary 'CI only: ingest real pass/fail results (writes passing/failing evidence)'
54
60
  help_usage 'fp ci-report --junit <file>... --project <slug> --surface <surface> --ci-url URL [--pr URL]'
@@ -62,10 +68,13 @@ module Fp
62
68
  help_flag :repo, 'Repository the tests live in (org/repo)'
63
69
  help_flag :sha, 'Checkout commit SHA'
64
70
  help_flag :allow_empty, 'Do not error when a report resolves no fp:<slug> markers'
71
+ help_flag :local, 'No CI available: report a suite a person ran locally at a clean, committed HEAD (--ci-url optional)'
65
72
  help_example 'fp ci-report --junit junit.xml --project stowzilla --surface api --ci-url "$CI_RUN_URL"'
66
73
  help_example 'fp ci-report --junit web.xml --surface web --base-dir frontend --pr "$PR_URL"'
74
+ help_example 'fp ci-report --local --junit junit.xml --surface api'
67
75
  help_note "This is CI's command, not an agent's: only it writes passing/failing. Run it on both\n" \
68
- 'green and red builds (if: always()) so failures show on the matrix.'
76
+ "green and red builds (if: always()) so failures show on the matrix.\n" \
77
+ 'Out of CI minutes? A person can run the suite and report it with --local; agents report with fp report.'
69
78
 
70
79
  KNOWN_FLAGS = {
71
80
  project: :string,
@@ -77,7 +86,8 @@ module Fp
77
86
  base_dir: :string,
78
87
  repo: :string,
79
88
  sha: :string,
80
- allow_empty: :boolean
89
+ allow_empty: :boolean,
90
+ local: :boolean
81
91
  }.freeze
82
92
 
83
93
  def run(args)
@@ -88,7 +98,7 @@ module Fp
88
98
 
89
99
  require_project!(opts)
90
100
  require_flag(opts, :surface)
91
- require_flag(opts, :ci_url)
101
+ require_flag(opts, :ci_url) unless opts[:local]
92
102
 
93
103
  if junit_paths.empty?
94
104
  output.error('--junit <path> is required (may be given more than once).')
@@ -103,6 +113,7 @@ module Fp
103
113
 
104
114
  project_id = resolve_project_id(opts[:project])
105
115
  known = known_slugs(project_id)
116
+ require_clean_tree!(opts) if opts[:local]
106
117
  commit_sha = resolve_commit_sha(opts)
107
118
  repo = opts[:repo] || presence(ENV['GITHUB_REPOSITORY'])
108
119
 
@@ -147,6 +158,7 @@ module Fp
147
158
  junit_xml: resolved_reports.first[:xml],
148
159
  pr_url: opts[:pr],
149
160
  sha: commit_sha,
161
+ local: opts[:local],
150
162
  results: combined_results,
151
163
  test_revisions: combined_revisions,
152
164
  unmarked_failures: totals[:unmarked_failures],
@@ -359,6 +371,23 @@ module Fp
359
371
  exit 1
360
372
  end
361
373
 
374
+ # A local run is recorded against HEAD, so HEAD has to be what ran. Untracked files
375
+ # are ignored: the report itself is usually one.
376
+ def require_clean_tree!(opts)
377
+ root = Fp::JUnit.repo_root_for(opts[:base_dir] || Dir.pwd)
378
+ stdout, _stderr, status = Open3.capture3('git', 'status', '--porcelain', '--untracked-files=no',
379
+ chdir: root || Dir.pwd)
380
+ unless status.success?
381
+ output.error('--local needs a git checkout: the results are recorded against the commit that ran them.')
382
+ exit 1
383
+ end
384
+ return if stdout.strip.empty?
385
+
386
+ output.error('--local refuses a working tree with uncommitted changes: the results would be ' \
387
+ 'recorded against a commit that never ran them. Commit (and push) first, then re-run the suite.')
388
+ exit 1
389
+ end
390
+
362
391
  def resolve_commit_sha(opts)
363
392
  explicit = presence(opts[:sha])
364
393
  return explicit if explicit
@@ -403,6 +432,7 @@ module Fp
403
432
 
404
433
  output.success(data) do
405
434
  mode = opts[:pr] ? " (PR mode — passing tests recorded as pr_passing)" : ''
435
+ mode += ' (local run, no CI)' if opts[:local]
406
436
  puts "Ingested CI results for surface '#{opts[:surface]}'#{mode}:"
407
437
  totals[:reports].each do |report|
408
438
  report[:results].each do |r|
data/lib/fp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fp
4
- VERSION = '0.0.29'
4
+ VERSION = '0.0.30'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: featureparity
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.29
4
+ version: 0.0.30
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stowzilla
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-11-03 00:00:00.000000000 Z
11
+ date: 2026-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: net-http