feat(jobs): emit job.enqueue + worktree.pruned audit rows

Deferred audit retrofits from Plan #5 self-review:
- WebhookNotifier now records a job.enqueue audit row after each
  successful repo.Enqueue (best-effort: failures are warn-logged, not
  propagated). Added optional audit.Recorder + *slog.Logger params to
  NewWebhookNotifier.
- WorktreePrune.executionPhase now records a worktree.pruned audit row
  after each successful FinishPruneSuccess. Added optional audit.Recorder
  param to NewWorktreePrune.
- app.go wires the existing auditRec into both constructors.
- integration_test.go: drop the _ = auditRec suppression and pass
  auditRec into the webhook notifier so the closed-loop test exercises
  the audit emit path.
This commit is contained in:
2026-05-06 13:35:45 +08:00
parent f6089ac5fb
commit b1ccce567e
6 changed files with 65 additions and 28 deletions
+5 -5
View File
@@ -95,7 +95,7 @@ func TestWorktreePrune_WarningPhase(t *testing.T) {
gitr := &fakePruner{}
cfg := runners.WorktreePruneConfig{IdleThreshold: 7 * 24 * time.Hour, WarningLead: 3 * 24 * time.Hour}
r := runners.NewWorktreePrune(repo, gitr, disp, cfg, discardLogger())
r := runners.NewWorktreePrune(repo, gitr, disp, cfg, discardLogger(), nil)
r.Run(context.Background())
require.Len(t, repo.markedWarning, 1)
@@ -124,7 +124,7 @@ func TestWorktreePrune_ExecutionPhaseSuccess(t *testing.T) {
gitr := &fakePruner{}
cfg := runners.WorktreePruneConfig{IdleThreshold: 7 * 24 * time.Hour, WarningLead: 3 * 24 * time.Hour}
r := runners.NewWorktreePrune(repo, gitr, &recordingDispatcher{}, cfg, discardLogger())
r := runners.NewWorktreePrune(repo, gitr, &recordingDispatcher{}, cfg, discardLogger(), nil)
r.Run(context.Background())
assert.True(t, repo.tryStartCalled[id])
@@ -146,7 +146,7 @@ func TestWorktreePrune_ExecutionFailureRollsBack(t *testing.T) {
gitr := &fakePruner{err: errors.New("git worktree remove failed")}
cfg := runners.WorktreePruneConfig{IdleThreshold: 7 * 24 * time.Hour, WarningLead: 3 * 24 * time.Hour}
r := runners.NewWorktreePrune(repo, gitr, &recordingDispatcher{}, cfg, discardLogger())
r := runners.NewWorktreePrune(repo, gitr, &recordingDispatcher{}, cfg, discardLogger(), nil)
r.Run(context.Background())
assert.True(t, repo.tryStartCalled[id])
@@ -162,7 +162,7 @@ func TestWorktreePrune_NoRowsIsNoOp(t *testing.T) {
disp := &recordingDispatcher{}
cfg := runners.WorktreePruneConfig{IdleThreshold: 7 * 24 * time.Hour, WarningLead: 3 * 24 * time.Hour}
r := runners.NewWorktreePrune(repo, gitr, disp, cfg, discardLogger())
r := runners.NewWorktreePrune(repo, gitr, disp, cfg, discardLogger(), nil)
r.Run(context.Background())
assert.Empty(t, repo.markedWarning)
@@ -185,7 +185,7 @@ func TestWorktreePrune_CASLostSkipsSilently(t *testing.T) {
gitr := &fakePruner{}
cfg := runners.WorktreePruneConfig{IdleThreshold: 7 * 24 * time.Hour, WarningLead: 3 * 24 * time.Hour}
r := runners.NewWorktreePrune(repo, gitr, &recordingDispatcher{}, cfg, discardLogger())
r := runners.NewWorktreePrune(repo, gitr, &recordingDispatcher{}, cfg, discardLogger(), nil)
r.Run(context.Background())
// TryStartPrune was called but failed.