Harden occurrence pipeline, strengthen type design#33
Conversation
Replace overbroad rescue in generate_occurrence with explicit error handling for each failure mode (Occurrence.new, persist, LogEmitter). Add @enforce_keys to Result and Events, narrow strategy type from atom() to :direct | :canary | :blue_green, add Result.rolledback/5 factory, add NodeKind.t() type, and fix start_log_emitter typespec. Remove unreachable execute_strategy fallback, add emit_status_log catch-all, check all LogEmitter return values, and log disabled emitter events at debug level. Fix conditional assertion in integration test, add tests for build_entity edge cases, persist error path, and Result enforce_keys. Clean up leaked emitter processes in OccurrenceLogTest. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR hardens the deployment occurrence pipeline and tightens type invariants across deploy results, events, and graph nodes, while adding tests to cover edge cases and prior silent-failure paths.
Changes:
- Replace overbroad exception handling around occurrence generation with explicit error handling and improved diagnostics/logging.
- Strengthen type invariants via
@enforce_keys, narrower strategy types, arolledback/5result constructor, and a dedicatedNodeKind.t()type. - Expand test coverage for malformed resource inputs, occurrence persistence failure paths, integration assertions, and emitter process cleanup.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/nopea/occurrence_test.exs | Adds edge-case tests for entity building and a persist error-path test. |
| test/nopea/occurrence_log_test.exs | Ensures emitter processes are stopped on test exit to prevent leaks. |
| test/nopea/deploy_integration_test.exs | Makes occurrence-file assertion unconditional to avoid silent pass. |
| test/nopea/deploy/result_test.exs | Adds tests for rolledback/5 and @enforce_keys behavior. |
| lib/nopea/occurrence.ex | Makes Occurrence.new/… failure explicit (raise) and widens start_log_emitter/1 spec to include error tuples. |
| lib/nopea/graph/node_kind.ex | Introduces NodeKind.t() as a constrained type. |
| lib/nopea/graph/node.ex | Narrows Node.kind type to NodeKind.t(). |
| lib/nopea/events/emitter.ex | Logs a debug message when emission is ignored due to disabled emitter. |
| lib/nopea/events.ex | Adds @enforce_keys to event struct for stronger invariants. |
| lib/nopea/deploy/spec.ex | Narrows Spec.strategy type to the constrained Result.strategy(). |
| lib/nopea/deploy/result.ex | Adds strategy type, enforces required keys, and adds rolledback/5 constructor. |
| lib/nopea/deploy.ex | Improves occurrence persistence handling and checks LogEmitter return values with explicit logging. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| id: String.t(), | ||
| name: String.t(), | ||
| kind: atom(), | ||
| kind: NodeKind.t(), |
There was a problem hiding this comment.
Node.t/0 now narrows kind to NodeKind.t(), but new/3 is still spec’d as taking atom() and is only guarded by is_atom(kind) (with a runtime NodeKind.valid?/1 check). To keep the public types consistent for Dialyzer/docs, update @spec new/3 (and ideally the guard) to accept NodeKind.t() rather than atom().
Summary
rescuewith explicit error handling —Occurrence.newfailures raise with diagnostics,persist/2errors are logged, allLogEmitterreturn values are checked@enforce_keystoResultandEvents, narrowstrategyfromatom()to:direct | :canary | :blue_green, addResult.rolledback/5factory, defineNodeKind.t()typeif File.exists?assertion in integration test, addbuild_entityedge case tests,persisterror path test, clean up leaked emitter processesWhat was found
Four review agents (code reviewer, silent failure hunter, type design analyzer, test coverage analyzer) identified 17 issues ranging from critical silent data loss to minor type narrowing. All addressed in this PR.
Test plan
mix compile --warnings-as-errorscleanmix format --check-formattedcleanmix credo— no new issues (pre-existing Logger metadata warnings only)🤖 Generated with Claude Code