carson 2.8.0 → 2.8.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: 0c3f3bf2f0ea58a2d460c36fb57b6313d5dab97c08b76ec94ae1c1e9b685b24f
4
- data.tar.gz: 48562197450233540c28a6fa912c38eaa636910ed3bab57e32e95d7b0b66c10a
3
+ metadata.gz: 76c0a5589cad84c4aaba1fee42bd667a21a55cea4840092b2984ae9eaeb84f6c
4
+ data.tar.gz: 656462b041f6764fd38780b500945ca0389b8235d741805367613051a27bd9da
5
5
  SHA512:
6
- metadata.gz: 63a4d9fed728d78b2fcaf0d0d6ffb158a93e464af24997d661b24d77a2764e4a84014f45d4cfe2e204c7bac337c796f8e69e3722fe30a135f98650176271dba3
7
- data.tar.gz: aba034301bccbf786198a1a44bd767d3f239370807a68841a89b6ffc40340719ef37dea2ddae9a0d54eedadf1b42c2446d02614721ab946586b809de0438a2d4
6
+ metadata.gz: 14cc66d4582c9ddfb9c5e87ec8e550d1f97cbcf6701a499e730dea4c06b5598ccdc6e8f61057a921ddba2d6ac9799fed4b3191a1a6dc1e440c4bc7249eec06bd
7
+ data.tar.gz: ce5e6f40342c08378830563ae0188cf61964d1f4650cc0be47a8cf52cb72f02b4f6413fa2b8d15a3dc70e3714628897446ab852ab7b276ac68a98cff0e5d1d54
data/RELEASE.md CHANGED
@@ -5,6 +5,48 @@ Release-note scope rule:
5
5
  - `RELEASE.md` records only version deltas, breaking changes, and migration actions.
6
6
  - Operational usage guides live in `MANUAL.md` and `API.md`.
7
7
 
8
+ ## 2.8.1 — Onboard UX and Install Cleanup
9
+
10
+ ### What changed
11
+
12
+ - **Concise onboard output.** `carson onboard` now prints a clean 8-line summary instead of verbose internal state (hook paths, template statuses, config lines). Tells users what happened, what needs attention, and what to do next.
13
+ - **Graceful handling of fresh repos.** Onboard no longer fails with a fatal error on repositories with no commits yet.
14
+ - **Suppressed RubyGems PATH warning.** The misleading `WARNING: You don't have ... in your PATH, gem executables will not run` message from `gem install --user-install` is now suppressed during installation. Carson symlinks the executable to `~/.carson/bin`, making the gem bin directory irrelevant.
15
+
16
+ ### What users must do now
17
+
18
+ 1. Upgrade Carson to `2.8.1`.
19
+
20
+ ### Breaking or removed behaviour
21
+
22
+ - None.
23
+
24
+ ### Upgrade steps
25
+
26
+ ```bash
27
+ cd ~/Dev/carson
28
+ git pull
29
+ bash install.sh
30
+ carson version
31
+ ```
32
+
33
+ ### Engineering Appendix
34
+
35
+ #### Modified components
36
+
37
+ - `lib/carson/runtime.rb` — added `concise?` flag and `with_captured_output` helper for suppressing sub-command detail during onboard.
38
+ - `lib/carson/runtime/local.rb` — rewrote `onboard!` to use concise orchestration (`onboard_apply!`), added `onboard_report_remote!` and `onboard_run_audit!` helpers, added `unless concise?` guards to `prepare!` and `template_apply!`.
39
+ - `install.sh` — capture `gem install` stderr and filter out RubyGems PATH warning.
40
+ - `script/install_global_carson.sh` — same PATH warning suppression.
41
+ - `test/runtime_govern_test.rb` — updated onboard output assertions.
42
+
43
+ #### Public interface and config changes
44
+
45
+ - No new CLI commands or config keys.
46
+ - Exit status contract unchanged.
47
+
48
+ ---
49
+
8
50
  ## 2.8.0 — Interactive Setup and Remote Detection
9
51
 
10
52
  ### What changed
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.8.0
1
+ 2.8.1
@@ -153,26 +153,31 @@ module Carson
153
153
  target_path = File.join( hooks_dir, hook_name )
154
154
  FileUtils.cp( source_path, target_path )
155
155
  FileUtils.chmod( 0o755, target_path )
156
- puts_line "hook_written: #{relative_path( target_path )}"
156
+ puts_line "hook_written: #{relative_path( target_path )}" unless concise?
157
157
  end
158
158
  git_system!( "config", "core.hooksPath", hooks_dir )
159
159
  File.write( File.join( hooks_dir, "workflow_style" ), config.workflow_style )
160
- puts_line "configured_hooks_path: #{hooks_dir}"
160
+ puts_line "configured_hooks_path: #{hooks_dir}" unless concise?
161
+ return EXIT_OK if concise?
162
+
161
163
  inspect!
162
164
  end
163
165
 
164
166
  # One-command onboarding for new repositories: detect remote, install hooks,
165
- # apply templates, and produce a first audit report.
167
+ # apply templates, and run initial audit.
166
168
  def onboard!
167
169
  fingerprint_status = block_if_outsider_fingerprints!
168
170
  return fingerprint_status unless fingerprint_status.nil?
169
171
 
170
- print_header "Onboard"
171
172
  unless inside_git_work_tree?
172
173
  puts_line "ERROR: #{repo_root} is not a git repository."
173
174
  return EXIT_ERROR
174
175
  end
175
176
 
177
+ repo_name = File.basename( repo_root )
178
+ puts_line ""
179
+ puts_line "Onboarding #{repo_name}..."
180
+
176
181
  unless global_config_exists?
177
182
  if self.in.respond_to?( :tty? ) && self.in.tty?
178
183
  setup_status = setup!
@@ -182,21 +187,9 @@ module Carson
182
187
  end
183
188
  end
184
189
 
185
- report_detected_remote!
186
- hook_status = prepare!
187
- return hook_status unless hook_status == EXIT_OK
188
-
189
- template_status = template_apply!
190
- return template_status unless template_status == EXIT_OK
191
-
192
- audit_status = audit!
193
- if audit_status == EXIT_OK
194
- puts_line "OK: Carson onboard completed for #{repo_root}."
195
- elsif audit_status == EXIT_BLOCK
196
- puts_line "BLOCK: Carson onboard completed with policy blocks; resolve and rerun carson audit."
197
- end
198
- print_onboarding_guidance
199
- audit_status
190
+ onboard_apply!
191
+ ensure
192
+ @concise = false
200
193
  end
201
194
 
202
195
  # Re-applies hooks, templates, and audit after upgrading Carson.
@@ -287,29 +280,29 @@ module Carson
287
280
  fingerprint_status = block_if_outsider_fingerprints!
288
281
  return fingerprint_status unless fingerprint_status.nil?
289
282
 
290
- print_header "Template Sync Apply"
283
+ print_header "Template Sync Apply" unless concise?
291
284
  results = template_results
292
285
  applied = 0
293
286
  results.each do |entry|
294
287
  if entry.fetch( :status ) == "error"
295
- puts_line "template_file: #{entry.fetch( :file )} status=error reason=#{entry.fetch( :reason )}"
288
+ puts_line "template_file: #{entry.fetch( :file )} status=error reason=#{entry.fetch( :reason )}" unless concise?
296
289
  next
297
290
  end
298
291
 
299
292
  file_path = File.join( repo_root, entry.fetch( :file ) )
300
293
  if entry.fetch( :status ) == "ok"
301
- puts_line "template_file: #{entry.fetch( :file )} status=ok reason=in_sync"
294
+ puts_line "template_file: #{entry.fetch( :file )} status=ok reason=in_sync" unless concise?
302
295
  next
303
296
  end
304
297
 
305
298
  FileUtils.mkdir_p( File.dirname( file_path ) )
306
299
  File.write( file_path, entry.fetch( :applied_content ) )
307
- puts_line "template_file: #{entry.fetch( :file )} status=updated reason=#{entry.fetch( :reason )}"
300
+ puts_line "template_file: #{entry.fetch( :file )} status=updated reason=#{entry.fetch( :reason )}" unless concise?
308
301
  applied += 1
309
302
  end
310
303
 
311
304
  error_count = results.count { |entry| entry.fetch( :status ) == "error" }
312
- puts_line "template_apply_summary: updated=#{applied} error=#{error_count}"
305
+ puts_line "template_apply_summary: updated=#{applied} error=#{error_count}" unless concise?
313
306
  error_count.positive? ? EXIT_ERROR : EXIT_OK
314
307
  end
315
308
 
@@ -680,12 +673,66 @@ module Carson
680
673
  end
681
674
  end
682
675
 
683
- def print_onboarding_guidance
684
- puts_line ""
685
- puts_line "Carson is ready. Current workflow: #{config.workflow_style}"
676
+ # Concise onboard orchestration: hooks, templates, remote, audit, guidance.
677
+ def onboard_apply!
678
+ @concise = true
679
+
680
+ hook_status = prepare!
681
+ return hook_status unless hook_status == EXIT_OK
682
+ puts_line "Hooks installed (#{config.required_hooks.count} hooks)."
683
+
684
+ template_drift_count = template_results.count { |entry| entry.fetch( :status ) != "ok" }
685
+ template_status = template_apply!
686
+ return template_status unless template_status == EXIT_OK
687
+ if template_drift_count.positive?
688
+ puts_line "Templates synced (#{template_drift_count} file#{plural_suffix( count: template_drift_count )} updated)."
689
+ else
690
+ puts_line "Templates in sync."
691
+ end
692
+
693
+ onboard_report_remote!
694
+ audit_status = onboard_run_audit!
695
+
686
696
  puts_line ""
687
- puts_line "Reconfigure anytime with: carson setup"
688
- puts_line "Run carson refresh after changing config."
697
+ puts_line "Carson is ready. Workflow: #{config.workflow_style}"
698
+ puts_line "Reconfigure anytime: carson setup"
699
+ audit_status
700
+ end
701
+
702
+ # Friendly remote status for onboard output.
703
+ def onboard_report_remote!
704
+ if git_remote_exists?( remote_name: config.git_remote )
705
+ puts_line "Remote: #{config.git_remote} (connected)."
706
+ else
707
+ puts_line "Remote not configured yet — carson setup will walk you through it."
708
+ end
709
+ end
710
+
711
+ # Runs audit with captured output; reports summary instead of full detail.
712
+ def onboard_run_audit!
713
+ audit_error = nil
714
+ audit_status = with_captured_output { audit! }
715
+ rescue StandardError => e
716
+ audit_error = e
717
+ audit_status = EXIT_OK
718
+ ensure
719
+ return onboard_print_audit_result( status: audit_status, error: audit_error )
720
+ end
721
+
722
+ def onboard_print_audit_result( status:, error: )
723
+ if error
724
+ if error.message.to_s.match?( /HEAD|rev-parse/ )
725
+ puts_line "No commits yet — run carson audit after your first commit."
726
+ else
727
+ puts_line "Audit skipped — run carson audit for details."
728
+ end
729
+ return EXIT_OK
730
+ end
731
+
732
+ if status == EXIT_BLOCK
733
+ puts_line "Some checks need attention — run carson audit for details."
734
+ end
735
+ status
689
736
  end
690
737
 
691
738
  # Uses `git remote get-url` as existence check to avoid parsing remote lists.
@@ -4,6 +4,7 @@
4
4
  require "fileutils"
5
5
  require "json"
6
6
  require "open3"
7
+ require "stringio"
7
8
  require "time"
8
9
 
9
10
  module Carson
@@ -28,6 +29,7 @@ module Carson
28
29
  @out = out
29
30
  @err = err
30
31
  @in = in_stream
32
+ @concise = false
31
33
  @config = Config.load( repo_root: repo_root )
32
34
  @git_adapter = Adapters::Git.new( repo_root: repo_root )
33
35
  @github_adapter = Adapters::GitHub.new( repo_root: repo_root )
@@ -37,6 +39,22 @@ module Carson
37
39
 
38
40
  attr_reader :repo_root, :tool_root, :out, :err, :in, :config, :git_adapter, :github_adapter
39
41
 
42
+ # Returns true when output should be minimal (used by onboard/refresh).
43
+ def concise?
44
+ @concise
45
+ end
46
+
47
+ # Runs a block with all output captured (suppressed from the user).
48
+ # Returns the block's return value; output is silently discarded.
49
+ def with_captured_output
50
+ saved_out, saved_err = @out, @err
51
+ @out = StringIO.new
52
+ @err = StringIO.new
53
+ yield
54
+ ensure
55
+ @out, @err = saved_out, saved_err
56
+ end
57
+
40
58
  # Current local branch name.
41
59
  def current_branch
42
60
  git_capture!( "rev-parse", "--abbrev-ref", "HEAD" ).strip
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carson
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hailei Wang