Skip to content

Commit f0eccb8

Browse files
committed
fix(purchase): extract failed-account save helper to stay under gocyclo:10
The new `if saveErr != nil` audit-loss branch added to executeForAccount on this PR pushed its cyclomatic complexity from 10 to 11, tripping the `gocyclo -over 10` pre-commit hook (and leaving the PR UNSTABLE on three retries). Hoist the credential-failure save into a tiny `persistFailedAccountExecution` helper so executeForAccount drops back to 10 while the audit-loss surfacing behaviour and the new regression test (TestExecuteForAccount_CredentialFailure_SaveErrorSurfaced) remain identical: the helper still does `errors.Join(AUDIT LOSS..., cause)` on save-failure and returns `cause` unchanged on success, so neither the credential error nor the save error can be silently dropped. - gocyclo -over 10 internal/purchase/execution.go: clean (executeForAccount=10). - go vet ./internal/purchase/...: clean. - go test ./internal/purchase/... -count=1: 207 passed.
1 parent 4b68325 commit f0eccb8

1 file changed

Lines changed: 21 additions & 10 deletions

File tree

internal/purchase/execution.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -230,16 +230,11 @@ func (m *Manager) executeForAccount(ctx context.Context, baseExec *config.Purcha
230230
acctExec.Status = "failed"
231231
acctExec.Error = err.Error()
232232
credErr := fmt.Errorf("credential resolution failed for account %s: %w", account.ID, err)
233-
// The failed row is as much a part of the audit trail as a success
234-
// row: if persisting it fails, surface that loss exactly like the
235-
// post-purchase save below does instead of silently dropping it.
236-
if saveErr := m.config.SavePurchaseExecution(ctx, &acctExec); saveErr != nil {
237-
return false, errors.Join(
238-
fmt.Errorf("AUDIT LOSS: failed to save execution record for account %s: %w", account.ID, saveErr),
239-
credErr,
240-
)
241-
}
242-
return false, credErr
233+
// Audit-trail save: the failed row is as much a part of the audit
234+
// trail as a success row, so a save failure must surface (AUDIT LOSS)
235+
// instead of being silently dropped. Extracted to a helper to keep
236+
// executeForAccount under the gocyclo:10 budget.
237+
return false, m.persistFailedAccountExecution(ctx, &acctExec, account, credErr)
243238
}
244239

245240
accountID := account.ExternalID
@@ -297,6 +292,22 @@ func (m *Manager) executeForAccount(ctx context.Context, baseExec *config.Purcha
297292
return committed, nil
298293
}
299294

295+
// persistFailedAccountExecution writes a per-account execution row that the
296+
// caller has already stamped with Status="failed" + Error, and joins any save
297+
// failure with the originating cause via errors.Join so neither error is
298+
// silently dropped (the row is as much audit trail as a success row; issue
299+
// #1184 / COR-10). Extracted from executeForAccount so the new branch keeps
300+
// that function under the gocyclo:10 budget.
301+
func (m *Manager) persistFailedAccountExecution(ctx context.Context, acctExec *config.PurchaseExecution, account config.CloudAccount, cause error) error {
302+
if saveErr := m.config.SavePurchaseExecution(ctx, acctExec); saveErr != nil {
303+
return errors.Join(
304+
fmt.Errorf("AUDIT LOSS: failed to save execution record for account %s: %w", account.ID, saveErr),
305+
cause,
306+
)
307+
}
308+
return cause
309+
}
310+
300311
// resolveSingleAccountProvider derives per-account credentials for the
301312
// single-account execution path. Returns (nil, "", nil) when no account can be
302313
// identified (ambient credentials are used in that case), or when no recs are

0 commit comments

Comments
 (0)