carson 3.23.0 → 3.23.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 +4 -4
- data/RELEASE.md +21 -0
- data/VERSION +1 -1
- data/lib/carson/ledger.rb +20 -20
- data/lib/carson/runtime/deliver.rb +2 -2
- data/lib/carson/runtime/govern.rb +1 -51
- data/lib/carson/runtime/local/onboard.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b22f115d99fffc1ed689ceb214523b8a33da08fc84a955fcc766d778be21e40c
|
|
4
|
+
data.tar.gz: 6a270c175cb8affabba0d6d747e08701a50c61124a4c5486525113ff350cedbf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00ac0ad1897f1d04520f4653aec941e6d9c0dfeb7d13656a4ecb1eff6a3cffe24af0b839447f1324ac11c6eb6c40e00b01e1cba6c3fa86a5d21871576b4bb2d2
|
|
7
|
+
data.tar.gz: fad5645c4a8befb085b4617db5542117bf593f1475cc5a65ccbf29b207e4c5ea9fd938bb503d2fa35e66b652ecc01fae269d68c5c60f2e895055cd8c3b0190b3
|
data/RELEASE.md
CHANGED
|
@@ -5,6 +5,27 @@ 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
|
+
## 3.23.2
|
|
9
|
+
|
|
10
|
+
### What changed
|
|
11
|
+
|
|
12
|
+
- **Fix: onboard audit exception silently swallowed** — `onboard_run_audit!` referenced an undefined variable `e` instead of `exception` in its rescue clause. When `audit!` raised during `carson onboard`, the NameError was caught by the ensure block's return, giving the user no diagnostic. Now correctly captures the exception and reports "Audit skipped."
|
|
13
|
+
- **Fix: `sync_after_merge!` always reported success** — `Open3.capture3` returns a `Process::Status` object which is always truthy. The sync-failure branch was unreachable. Now correctly calls `.success?` on the status object.
|
|
14
|
+
- **Test coverage: Ledger revision recording** — unit tests for `record_revision` (numbering, `finished_at`, counter bump), `revisions_for_delivery` ordering, and behavioural verification that `active_deliveries` returns exactly the states `Delivery` considers active.
|
|
15
|
+
- **Test coverage: govern reconciliation** — tests for PR MERGED (integrated), PR CLOSED (failed), head-advanced (superseded), and no-agent-provider (escalated) state transitions that were previously stubbed out.
|
|
16
|
+
- **Test coverage: deliver error paths** — push failure and PR creation failure tests exercising actual error handling at the adapter boundary.
|
|
17
|
+
- **Housekeeping** — `Ledger::ACTIVE_DELIVERY_STATES` now references `Delivery::ACTIVE_STATES` instead of maintaining a duplicate. Fixed indentation in `upsert_delivery` and `supersede_branch!`. Corrected "deliver/delivers" to "delivery/deliveries" in govern output.
|
|
18
|
+
|
|
19
|
+
### No migration required
|
|
20
|
+
|
|
21
|
+
## 3.23.1
|
|
22
|
+
|
|
23
|
+
### What changed
|
|
24
|
+
|
|
25
|
+
- **Govern no longer depends on cache-report writes** — `carson govern` no longer writes `govern_latest.md/json` under `~/.carson/cache` as part of its normal execution. Govern now advances deliveries directly from the ledger and prints results to stdout/JSON only.
|
|
26
|
+
|
|
27
|
+
### No migration required
|
|
28
|
+
|
|
8
29
|
## 3.23.0
|
|
9
30
|
|
|
10
31
|
### What changed
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.23.
|
|
1
|
+
3.23.2
|
data/lib/carson/ledger.rb
CHANGED
|
@@ -6,7 +6,7 @@ require "time"
|
|
|
6
6
|
module Carson
|
|
7
7
|
class Ledger
|
|
8
8
|
UNSET = Object.new
|
|
9
|
-
ACTIVE_DELIVERY_STATES =
|
|
9
|
+
ACTIVE_DELIVERY_STATES = Delivery::ACTIVE_STATES
|
|
10
10
|
|
|
11
11
|
def initialize( path: )
|
|
12
12
|
@path = File.expand_path( path )
|
|
@@ -75,16 +75,16 @@ module Carson
|
|
|
75
75
|
[ repository.path, branch_name, head ]
|
|
76
76
|
)
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
if row
|
|
79
|
+
database.execute(
|
|
80
|
+
<<~SQL,
|
|
81
|
+
UPDATE deliveries
|
|
82
|
+
SET worktree_path = ?, authority = ?, status = ?, pr_number = ?, pr_url = ?,
|
|
83
|
+
cause = ?, summary = ?, updated_at = ?
|
|
84
|
+
WHERE id = ?
|
|
85
|
+
SQL
|
|
86
|
+
[ worktree_path, authority, status, pr_number, pr_url, cause, summary, timestamp, row.fetch( "id" ) ]
|
|
87
|
+
)
|
|
88
88
|
return fetch_delivery( database: database, id: row.fetch( "id" ), repository: repository )
|
|
89
89
|
end
|
|
90
90
|
|
|
@@ -283,15 +283,15 @@ module Carson
|
|
|
283
283
|
)
|
|
284
284
|
end
|
|
285
285
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
286
|
+
def supersede_branch!( database:, repository:, branch_name:, timestamp: )
|
|
287
|
+
database.execute(
|
|
288
|
+
<<~SQL,
|
|
289
|
+
UPDATE deliveries
|
|
290
|
+
SET status = ?, superseded_at = ?, updated_at = ?
|
|
291
|
+
WHERE repo_path = ? AND branch_name = ? AND status IN ( #{active_state_placeholders} )
|
|
292
|
+
SQL
|
|
293
|
+
[ "superseded", timestamp, timestamp, repository.path, branch_name, *ACTIVE_DELIVERY_STATES ]
|
|
294
|
+
)
|
|
295
295
|
end
|
|
296
296
|
|
|
297
297
|
def active_state_placeholders
|
|
@@ -311,10 +311,10 @@ module Carson
|
|
|
311
311
|
# Syncs main after a successful merge.
|
|
312
312
|
def sync_after_merge!( remote:, main:, result: )
|
|
313
313
|
main_root = main_worktree_root
|
|
314
|
-
_, pull_stderr,
|
|
314
|
+
_, pull_stderr, pull_status, = Open3.capture3(
|
|
315
315
|
"git", "-C", main_root, "pull", "--ff-only", remote, main
|
|
316
316
|
)
|
|
317
|
-
if
|
|
317
|
+
if pull_status.success?
|
|
318
318
|
result[ :synced ] = true
|
|
319
319
|
puts_verbose "synced #{main} in #{main_root} from #{remote}"
|
|
320
320
|
else
|
|
@@ -2,14 +2,10 @@
|
|
|
2
2
|
# Govern reassesses queued/gated deliveries, records revision cycles, and integrates one ready delivery at a time.
|
|
3
3
|
require "json"
|
|
4
4
|
require "time"
|
|
5
|
-
require "fileutils"
|
|
6
5
|
|
|
7
6
|
module Carson
|
|
8
7
|
class Runtime
|
|
9
8
|
module Govern
|
|
10
|
-
GOVERN_REPORT_MD = "govern_latest.md".freeze
|
|
11
|
-
GOVERN_REPORT_JSON = "govern_latest.json".freeze
|
|
12
|
-
|
|
13
9
|
# Portfolio-level entry point. Scans governed repos (or the current repo) and advances deliveries.
|
|
14
10
|
def govern!( dry_run: false, json_output: false, loop_seconds: nil )
|
|
15
11
|
if loop_seconds
|
|
@@ -31,7 +27,6 @@ module Carson
|
|
|
31
27
|
repositories: repositories.map { |path| govern_repo!( repo_path: path, dry_run: dry_run ) }
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
write_govern_report( report: report )
|
|
35
30
|
if json_output
|
|
36
31
|
output.puts JSON.pretty_generate( report )
|
|
37
32
|
else
|
|
@@ -86,7 +81,7 @@ module Carson
|
|
|
86
81
|
return repo_report
|
|
87
82
|
end
|
|
88
83
|
|
|
89
|
-
puts_line "#{repository.name}: #{deliveries.length} active deliver#{
|
|
84
|
+
puts_line "#{repository.name}: #{deliveries.length} active deliver#{deliveries.length == 1 ? 'y' : 'ies'}"
|
|
90
85
|
|
|
91
86
|
reconciled = deliveries.map { |item| scoped_runtime.send( :reconcile_delivery!, delivery: item ) }
|
|
92
87
|
next_integration_id = reconciled.find( &:ready? )&.id
|
|
@@ -423,51 +418,6 @@ module Carson
|
|
|
423
418
|
""
|
|
424
419
|
end
|
|
425
420
|
|
|
426
|
-
def write_govern_report( report: )
|
|
427
|
-
report_dir = report_dir_path
|
|
428
|
-
FileUtils.mkdir_p( report_dir )
|
|
429
|
-
File.write( File.join( report_dir, GOVERN_REPORT_JSON ), JSON.pretty_generate( report ) )
|
|
430
|
-
File.write( File.join( report_dir, GOVERN_REPORT_MD ), render_govern_markdown( report: report ) )
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
def render_govern_markdown( report: )
|
|
434
|
-
lines = []
|
|
435
|
-
lines << "# Carson Govern Report"
|
|
436
|
-
lines << ""
|
|
437
|
-
lines << "**Cycle**: #{report[ :cycle_at ]}"
|
|
438
|
-
lines << "**Dry run**: #{report[ :dry_run ]}"
|
|
439
|
-
lines << ""
|
|
440
|
-
|
|
441
|
-
Array( report[ :repositories ] ).each do |repo_report|
|
|
442
|
-
lines << "## #{repo_report[ :path ]}"
|
|
443
|
-
lines << ""
|
|
444
|
-
if repo_report[ :error ]
|
|
445
|
-
lines << "**Error**: #{repo_report[ :error ]}"
|
|
446
|
-
lines << ""
|
|
447
|
-
next
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
deliveries = Array( repo_report[ :deliveries ] )
|
|
451
|
-
if deliveries.empty?
|
|
452
|
-
lines << "No active deliveries."
|
|
453
|
-
lines << ""
|
|
454
|
-
next
|
|
455
|
-
end
|
|
456
|
-
|
|
457
|
-
deliveries.each do |delivery|
|
|
458
|
-
lines << "### #{delivery[ :branch ]}"
|
|
459
|
-
lines << ""
|
|
460
|
-
lines << "- **Status**: #{delivery[ :status ]}"
|
|
461
|
-
lines << "- **Action**: #{delivery[ :action ]}"
|
|
462
|
-
lines << "- **Summary**: #{delivery[ :summary ]}" unless delivery[ :summary ].to_s.empty?
|
|
463
|
-
lines << "- **Revision count**: #{delivery[ :revision_count ]}"
|
|
464
|
-
lines << ""
|
|
465
|
-
end
|
|
466
|
-
end
|
|
467
|
-
|
|
468
|
-
lines.join( "\n" )
|
|
469
|
-
end
|
|
470
|
-
|
|
471
421
|
def print_govern_summary( report: )
|
|
472
422
|
Array( report[ :repositories ] ).each do |repo_report|
|
|
473
423
|
if repo_report[ :error ]
|
|
@@ -295,7 +295,7 @@ module Carson
|
|
|
295
295
|
audit_error = nil
|
|
296
296
|
audit_status = with_captured_output { audit! }
|
|
297
297
|
rescue StandardError => exception
|
|
298
|
-
audit_error =
|
|
298
|
+
audit_error = exception
|
|
299
299
|
audit_status = EXIT_OK
|
|
300
300
|
ensure
|
|
301
301
|
return onboard_print_audit_result( status: audit_status, error: audit_error )
|