yamine 0.8.0 → 0.8.2

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: 04f00c2029bf4cda65d187225d251fc594bacf538092e6a56d9c5a03f9aa47fd
4
- data.tar.gz: 963f1c74d64ddb94199d42325f6d8631a5dd2d618119554a4e1a72849394c5bc
3
+ metadata.gz: 52c2213e83a301befe5e048b7a83eec6e6c945f23475334928a298f81d9e8369
4
+ data.tar.gz: 39e2c51e536b6fa3d50a956bce2b20187899bf52a2c86a3b82ab110877a485fc
5
5
  SHA512:
6
- metadata.gz: 2e02efba8d7c16767b0c4b8908d295f4c095f7c32f5ef90885e1ecf0a50aa68d61cb9e0c780d3729f703fcc14fc282eed46430d4efce631762dbb832ddecf408
7
- data.tar.gz: 6d36c287b907fcfba07da2db3ecf1904ff4b396fb2bf8df277e0f9dfb23515e9245d574fb0bed85a034cd9f41fae14834842c722c3ac298e9f0fafedb1d30b45
6
+ metadata.gz: 543d3ba0a552e5cc2deef0784322d225c99a45ea19e35af090f6d5691d5cfc5b9637e8831755db5509e024a352fa33de70843aef2734353acf9bacfc867e805a
7
+ data.tar.gz: 57213387e578ba71b6d4140dd139d10fe2e7bf5168fe74ad85a3ba2b87089b69959284fc7f531f38034838dc67cb70b86b92f13b926aa638c1291a36bdbb1376
data/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.8.2] — 2026-09-10
4
+
5
+ ### Fixed
6
+
7
+ - **The rest of the `--json` stdout leaks.** Two writers still reached
8
+ stdout during a machine-readable run, corrupting the stream a parser
9
+ reads: the `-> <url>` line from the sequential boot path, and
10
+ "Starting proxy..." — which is printed before the reporter is even
11
+ installed, so it would have been the FIRST line of a `--json` run.
12
+ Both now route through the same stderr-when-json rule as the rest of
13
+ the narration, and the contract is pinned by tests rather than assumed
14
+ (two separate leaks have now been caught here).
15
+
16
+
17
+ ## [0.8.1] — 2026-09-10
18
+
19
+ ### Fixed
20
+
21
+ - **An already-correct `/etc/hosts` no longer reports a failure.**
22
+ `Hosts.sync` rewrote the file unconditionally, so on a normal machine
23
+ (where `/etc/hosts` is root-owned) it raised `Errno::EACCES`, returned
24
+ false, and made `yamine start` print "could not write /etc/hosts (try
25
+ sudo yamine hosts sync)" on every boot — pointing at an elevated write
26
+ for a file that already had exactly the right block. `synced?` existed
27
+ for precisely this guard but `sync` never consulted it. `sync` is now a
28
+ no-op returning true when the block already matches, and the setup step
29
+ reports "already lists N hostname(s)" instead of implying a failure.
30
+ Chrome/Firefox/Edge resolve `*.localhost` natively anyway; the file only
31
+ matters for Safari and custom TLDs.
32
+
33
+
3
34
  ## [0.8.0] — 2026-09-10
4
35
 
5
36
  ### Fixed
@@ -21,7 +21,7 @@ module Yamine
21
21
  # Ownership gate before any side effects: no proxy spawn, no
22
22
  # port allocation when we'd refuse anyway.
23
23
  check_worktree_ownership!(ctx, resolved, force: opts[:force])
24
- ensure_proxy!(ctx)
24
+ ensure_proxy!(ctx, json: opts[:json])
25
25
  boot_all(ctx, resolved, opts)
26
26
  end
27
27
 
@@ -180,7 +180,7 @@ module Yamine
180
180
  rails_dev_host: item[:hostname], database_url: db_url)
181
181
  routes_registered << { hostnames: item[:hostnames], app: app }
182
182
 
183
- puts " -> #{item[:url]}"
183
+ say opts, " -> #{item[:url]}"
184
184
  end
185
185
  children
186
186
  end
@@ -548,7 +548,11 @@ module Yamine
548
548
  Yamine::Resolver.resolve(Dir.pwd, variant: variant, tld: tld)
549
549
  end
550
550
 
551
- def ensure_proxy!(ctx)
551
+ # json: keeps stdout free for the machine-readable stream — this runs
552
+ # BEFORE boot_all installs the reporter, so its progress line is the
553
+ # one piece of narration that could still land mid-JSON and break a
554
+ # parser on the first line of a --json run.
555
+ def ensure_proxy!(ctx, json: false)
552
556
  port = ctx.proxy_port
553
557
  tls = ctx.proxy_tls
554
558
  if ProxyControl.listening?(port)
@@ -570,7 +574,8 @@ module Yamine
570
574
  $stderr.puts " Or start the proxy by hand: sudo yamine proxy start"
571
575
  exit 1
572
576
  end
573
- puts "Starting proxy#{privileged ? " (sudo)" : ""}..."
577
+ starting = "Starting proxy#{privileged ? " (sudo)" : ""}..."
578
+ json ? $stderr.puts(starting) : puts(starting)
574
579
  begin
575
580
  Yamine::ProxyControl.spawn_daemon(store: ctx.store, port: port, tls: tls, sudo: privileged)
576
581
  rescue Yamine::ProxyNotRunningError => e
@@ -220,6 +220,8 @@ module Yamine
220
220
  hostnames = ctx.store.load_routes.map { |r| r["hostname"] }
221
221
  if hostnames.empty?
222
222
  puts " No routes registered yet — hosts sync will happen on the next boot."
223
+ elsif Yamine::Hosts.synced?(hostnames)
224
+ puts " /etc/hosts already lists #{hostnames.length} hostname(s)."
223
225
  elsif Yamine::Hosts.sync(hostnames)
224
226
  puts " Synced #{hostnames.length} hostname(s) to /etc/hosts."
225
227
  else
@@ -758,8 +760,12 @@ module Yamine
758
760
  end
759
761
  end
760
762
 
761
- # 3. Hosts (best-effort: only needed for Safari; warn, don't fail)
762
- unless Hosts.sync(ctx.store.load_routes.map { |r| r["hostname"] })
763
+ # 3. Hosts (best-effort: only needed for Safari and custom TLDs —
764
+ # Chrome/Firefox/Edge resolve *.localhost natively). Already-synced
765
+ # is the common case and must stay silent: warning there sent
766
+ # people to a sudo write for a file that needed nothing.
767
+ hostnames = ctx.store.load_routes.map { |r| r["hostname"] }
768
+ unless hostnames.empty? || Yamine::Hosts.synced?(hostnames) || Hosts.sync(hostnames)
763
769
  warn "Warning: could not write /etc/hosts (try sudo yamine hosts sync)."
764
770
  end
765
771
  end
data/lib/yamine/hosts.rb CHANGED
@@ -41,7 +41,20 @@ module Yamine
41
41
  names
42
42
  end
43
43
 
44
+ # Bring the managed block to exactly these hostnames. Idempotent: when
45
+ # the block already matches, this is a no-op returning true.
46
+ #
47
+ # The short-circuit is load-bearing, not an optimization. /etc/hosts is
48
+ # root-owned on a normal machine, so a rewrite fails without sudo — and
49
+ # `setup` and every boot's workstation check run this. Without the
50
+ # guard, a machine whose hosts file was already correct got a
51
+ # "could not write /etc/hosts (try sudo yamine hosts sync)" warning on
52
+ # every run, sending people to an elevated write for a file that
53
+ # needed nothing. (Chrome/Firefox/Edge resolve *.localhost natively;
54
+ # /etc/hosts only matters for Safari and custom TLDs.)
44
55
  def sync(hostnames, path = PATH)
56
+ return true if synced?(hostnames, path)
57
+
45
58
  content = read(path)
46
59
  block = managed_block(hostnames)
47
60
  if content.include?(BEGIN_MARKER)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yamine
4
- VERSION = "0.8.0"
4
+ VERSION = "0.8.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yamine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto