omgkit 2.13.0 → 2.15.0
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.
- package/README.md +93 -10
- package/package.json +2 -2
- package/plugin/agents/api-designer.md +5 -0
- package/plugin/agents/architect.md +8 -0
- package/plugin/agents/brainstormer.md +4 -0
- package/plugin/agents/cicd-manager.md +6 -0
- package/plugin/agents/code-reviewer.md +6 -0
- package/plugin/agents/copywriter.md +2 -0
- package/plugin/agents/data-engineer.md +255 -0
- package/plugin/agents/database-admin.md +10 -0
- package/plugin/agents/debugger.md +10 -0
- package/plugin/agents/devsecops.md +314 -0
- package/plugin/agents/docs-manager.md +4 -0
- package/plugin/agents/domain-decomposer.md +181 -0
- package/plugin/agents/embedded-systems.md +397 -0
- package/plugin/agents/fullstack-developer.md +12 -0
- package/plugin/agents/game-systems-designer.md +375 -0
- package/plugin/agents/git-manager.md +10 -0
- package/plugin/agents/journal-writer.md +2 -0
- package/plugin/agents/ml-engineer.md +284 -0
- package/plugin/agents/observability-engineer.md +353 -0
- package/plugin/agents/oracle.md +9 -0
- package/plugin/agents/performance-engineer.md +290 -0
- package/plugin/agents/pipeline-architect.md +6 -0
- package/plugin/agents/planner.md +12 -0
- package/plugin/agents/platform-engineer.md +325 -0
- package/plugin/agents/project-manager.md +3 -0
- package/plugin/agents/researcher.md +5 -0
- package/plugin/agents/scientific-computing.md +426 -0
- package/plugin/agents/scout.md +3 -0
- package/plugin/agents/security-auditor.md +7 -0
- package/plugin/agents/sprint-master.md +17 -0
- package/plugin/agents/tester.md +10 -0
- package/plugin/agents/ui-ux-designer.md +12 -0
- package/plugin/agents/vulnerability-scanner.md +6 -0
- package/plugin/commands/data/pipeline.md +47 -0
- package/plugin/commands/data/quality.md +49 -0
- package/plugin/commands/domain/analyze.md +34 -0
- package/plugin/commands/domain/map.md +41 -0
- package/plugin/commands/game/balance.md +56 -0
- package/plugin/commands/game/optimize.md +62 -0
- package/plugin/commands/iot/provision.md +58 -0
- package/plugin/commands/ml/evaluate.md +47 -0
- package/plugin/commands/ml/train.md +48 -0
- package/plugin/commands/perf/benchmark.md +54 -0
- package/plugin/commands/perf/profile.md +49 -0
- package/plugin/commands/platform/blueprint.md +56 -0
- package/plugin/commands/security/audit.md +54 -0
- package/plugin/commands/security/scan.md +55 -0
- package/plugin/commands/sre/dashboard.md +53 -0
- package/plugin/registry.yaml +711 -0
- package/plugin/skills/ai-ml/experiment-tracking/SKILL.md +338 -0
- package/plugin/skills/ai-ml/feature-stores/SKILL.md +340 -0
- package/plugin/skills/ai-ml/llm-ops/SKILL.md +454 -0
- package/plugin/skills/ai-ml/ml-pipelines/SKILL.md +390 -0
- package/plugin/skills/ai-ml/model-monitoring/SKILL.md +398 -0
- package/plugin/skills/ai-ml/model-serving/SKILL.md +386 -0
- package/plugin/skills/event-driven/cqrs-patterns/SKILL.md +348 -0
- package/plugin/skills/event-driven/event-sourcing/SKILL.md +334 -0
- package/plugin/skills/event-driven/kafka-deep/SKILL.md +252 -0
- package/plugin/skills/event-driven/saga-orchestration/SKILL.md +335 -0
- package/plugin/skills/event-driven/schema-registry/SKILL.md +328 -0
- package/plugin/skills/event-driven/stream-processing/SKILL.md +313 -0
- package/plugin/skills/game/game-audio/SKILL.md +446 -0
- package/plugin/skills/game/game-networking/SKILL.md +490 -0
- package/plugin/skills/game/godot-patterns/SKILL.md +413 -0
- package/plugin/skills/game/shader-programming/SKILL.md +492 -0
- package/plugin/skills/game/unity-patterns/SKILL.md +488 -0
- package/plugin/skills/iot/device-provisioning/SKILL.md +405 -0
- package/plugin/skills/iot/edge-computing/SKILL.md +369 -0
- package/plugin/skills/iot/industrial-protocols/SKILL.md +438 -0
- package/plugin/skills/iot/mqtt-deep/SKILL.md +418 -0
- package/plugin/skills/iot/ota-updates/SKILL.md +426 -0
- package/plugin/skills/microservices/api-gateway-patterns/SKILL.md +201 -0
- package/plugin/skills/microservices/circuit-breaker-patterns/SKILL.md +246 -0
- package/plugin/skills/microservices/contract-testing/SKILL.md +284 -0
- package/plugin/skills/microservices/distributed-tracing/SKILL.md +246 -0
- package/plugin/skills/microservices/service-discovery/SKILL.md +304 -0
- package/plugin/skills/microservices/service-mesh/SKILL.md +181 -0
- package/plugin/skills/mobile-advanced/mobile-ci-cd/SKILL.md +407 -0
- package/plugin/skills/mobile-advanced/mobile-security/SKILL.md +403 -0
- package/plugin/skills/mobile-advanced/offline-first/SKILL.md +473 -0
- package/plugin/skills/mobile-advanced/push-notifications/SKILL.md +494 -0
- package/plugin/skills/mobile-advanced/react-native-deep/SKILL.md +374 -0
- package/plugin/skills/simulation/numerical-methods/SKILL.md +434 -0
- package/plugin/skills/simulation/parallel-computing/SKILL.md +382 -0
- package/plugin/skills/simulation/physics-engines/SKILL.md +377 -0
- package/plugin/skills/simulation/validation-verification/SKILL.md +479 -0
- package/plugin/skills/simulation/visualization-scientific/SKILL.md +365 -0
- package/plugin/workflows/ai-engineering/agent-development.md +3 -3
- package/plugin/workflows/ai-engineering/fine-tuning.md +3 -3
- package/plugin/workflows/ai-engineering/model-evaluation.md +3 -3
- package/plugin/workflows/ai-engineering/prompt-engineering.md +2 -2
- package/plugin/workflows/ai-engineering/rag-development.md +4 -4
- package/plugin/workflows/ai-ml/data-pipeline.md +188 -0
- package/plugin/workflows/ai-ml/experiment-cycle.md +203 -0
- package/plugin/workflows/ai-ml/feature-engineering.md +208 -0
- package/plugin/workflows/ai-ml/model-deployment.md +199 -0
- package/plugin/workflows/ai-ml/monitoring-setup.md +227 -0
- package/plugin/workflows/api/api-design.md +1 -1
- package/plugin/workflows/api/api-testing.md +2 -2
- package/plugin/workflows/content/technical-docs.md +1 -1
- package/plugin/workflows/database/migration.md +1 -1
- package/plugin/workflows/database/optimization.md +1 -1
- package/plugin/workflows/database/schema-design.md +3 -3
- package/plugin/workflows/development/bug-fix.md +3 -3
- package/plugin/workflows/development/code-review.md +2 -1
- package/plugin/workflows/development/feature.md +3 -3
- package/plugin/workflows/development/refactor.md +2 -2
- package/plugin/workflows/event-driven/consumer-groups.md +190 -0
- package/plugin/workflows/event-driven/event-storming.md +172 -0
- package/plugin/workflows/event-driven/replay-testing.md +186 -0
- package/plugin/workflows/event-driven/saga-implementation.md +206 -0
- package/plugin/workflows/event-driven/schema-evolution.md +173 -0
- package/plugin/workflows/fullstack/authentication.md +4 -4
- package/plugin/workflows/fullstack/full-feature.md +4 -4
- package/plugin/workflows/game-dev/content-pipeline.md +218 -0
- package/plugin/workflows/game-dev/platform-submission.md +263 -0
- package/plugin/workflows/game-dev/playtesting.md +237 -0
- package/plugin/workflows/game-dev/prototype-to-production.md +205 -0
- package/plugin/workflows/microservices/contract-first.md +151 -0
- package/plugin/workflows/microservices/distributed-tracing.md +166 -0
- package/plugin/workflows/microservices/domain-decomposition.md +123 -0
- package/plugin/workflows/microservices/integration-testing.md +149 -0
- package/plugin/workflows/microservices/service-mesh-setup.md +153 -0
- package/plugin/workflows/microservices/service-scaffolding.md +151 -0
- package/plugin/workflows/omega/1000x-innovation.md +2 -2
- package/plugin/workflows/omega/100x-architecture.md +2 -2
- package/plugin/workflows/omega/10x-improvement.md +2 -2
- package/plugin/workflows/quality/performance-optimization.md +2 -2
- package/plugin/workflows/research/best-practices.md +1 -1
- package/plugin/workflows/research/technology-research.md +1 -1
- package/plugin/workflows/security/penetration-testing.md +3 -3
- package/plugin/workflows/security/security-audit.md +3 -3
- package/plugin/workflows/sprint/sprint-execution.md +2 -2
- package/plugin/workflows/sprint/sprint-retrospective.md +1 -1
- package/plugin/workflows/sprint/sprint-setup.md +1 -1
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Circuit Breaker Patterns
|
|
2
|
+
|
|
3
|
+
Resilience patterns with Resilience4j, Polly, bulkheads, timeouts, retries, and fallback strategies.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Circuit breakers prevent cascade failures in distributed systems by detecting failures and temporarily stopping requests to failing services.
|
|
8
|
+
|
|
9
|
+
## Key Patterns
|
|
10
|
+
|
|
11
|
+
### Circuit Breaker States
|
|
12
|
+
- **Closed**: Normal operation, requests pass through
|
|
13
|
+
- **Open**: Failure threshold exceeded, requests fail fast
|
|
14
|
+
- **Half-Open**: Testing if service recovered
|
|
15
|
+
|
|
16
|
+
### Related Patterns
|
|
17
|
+
- **Retry**: Attempt failed operations again
|
|
18
|
+
- **Timeout**: Limit operation duration
|
|
19
|
+
- **Bulkhead**: Isolate failures to prevent spread
|
|
20
|
+
- **Fallback**: Provide alternative when primary fails
|
|
21
|
+
|
|
22
|
+
## Resilience4j Implementation
|
|
23
|
+
|
|
24
|
+
### Circuit Breaker
|
|
25
|
+
```java
|
|
26
|
+
// Configuration
|
|
27
|
+
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
|
|
28
|
+
.failureRateThreshold(50) // Open if 50% fail
|
|
29
|
+
.waitDurationInOpenState(Duration.ofSeconds(30))
|
|
30
|
+
.permittedNumberOfCallsInHalfOpenState(3)
|
|
31
|
+
.slidingWindowType(SlidingWindowType.COUNT_BASED)
|
|
32
|
+
.slidingWindowSize(10)
|
|
33
|
+
.build();
|
|
34
|
+
|
|
35
|
+
CircuitBreaker circuitBreaker = CircuitBreaker.of("userService", config);
|
|
36
|
+
|
|
37
|
+
// Usage
|
|
38
|
+
Supplier<User> decoratedSupplier = CircuitBreaker
|
|
39
|
+
.decorateSupplier(circuitBreaker, () -> userService.getUser(userId));
|
|
40
|
+
|
|
41
|
+
Try<User> result = Try.ofSupplier(decoratedSupplier)
|
|
42
|
+
.recover(CallNotPermittedException.class, e -> getCachedUser(userId));
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Retry with Backoff
|
|
46
|
+
```java
|
|
47
|
+
RetryConfig retryConfig = RetryConfig.custom()
|
|
48
|
+
.maxAttempts(3)
|
|
49
|
+
.waitDuration(Duration.ofMillis(500))
|
|
50
|
+
.exponentialBackoff(2, Duration.ofSeconds(10))
|
|
51
|
+
.retryOnException(e -> e instanceof TransientException)
|
|
52
|
+
.build();
|
|
53
|
+
|
|
54
|
+
Retry retry = Retry.of("userService", retryConfig);
|
|
55
|
+
|
|
56
|
+
Supplier<User> retryingSupplier = Retry
|
|
57
|
+
.decorateSupplier(retry, () -> userService.getUser(userId));
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Bulkhead
|
|
61
|
+
```java
|
|
62
|
+
// Thread pool bulkhead
|
|
63
|
+
ThreadPoolBulkheadConfig bulkheadConfig = ThreadPoolBulkheadConfig.custom()
|
|
64
|
+
.maxThreadPoolSize(10)
|
|
65
|
+
.coreThreadPoolSize(5)
|
|
66
|
+
.queueCapacity(20)
|
|
67
|
+
.build();
|
|
68
|
+
|
|
69
|
+
ThreadPoolBulkhead bulkhead = ThreadPoolBulkhead.of("userService", bulkheadConfig);
|
|
70
|
+
|
|
71
|
+
CompletionStage<User> result = bulkhead.executeSupplier(
|
|
72
|
+
() -> userService.getUser(userId)
|
|
73
|
+
);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Combined Resilience
|
|
77
|
+
```java
|
|
78
|
+
// Combine patterns
|
|
79
|
+
Supplier<User> resilientSupplier = Decorators
|
|
80
|
+
.ofSupplier(() -> userService.getUser(userId))
|
|
81
|
+
.withRetry(retry)
|
|
82
|
+
.withCircuitBreaker(circuitBreaker)
|
|
83
|
+
.withBulkhead(bulkhead)
|
|
84
|
+
.withFallback(Arrays.asList(
|
|
85
|
+
CallNotPermittedException.class,
|
|
86
|
+
BulkheadFullException.class
|
|
87
|
+
), e -> getCachedUser(userId))
|
|
88
|
+
.decorate();
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Node.js Implementation (opossum)
|
|
92
|
+
|
|
93
|
+
### Basic Circuit Breaker
|
|
94
|
+
```javascript
|
|
95
|
+
const CircuitBreaker = require('opossum');
|
|
96
|
+
|
|
97
|
+
const options = {
|
|
98
|
+
timeout: 3000, // 3 seconds
|
|
99
|
+
errorThresholdPercentage: 50,
|
|
100
|
+
resetTimeout: 30000, // 30 seconds
|
|
101
|
+
volumeThreshold: 5, // Minimum calls before calculating
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const breaker = new CircuitBreaker(callExternalService, options);
|
|
105
|
+
|
|
106
|
+
// Events
|
|
107
|
+
breaker.on('success', (result) => console.log('Success:', result));
|
|
108
|
+
breaker.on('timeout', () => console.log('Timeout'));
|
|
109
|
+
breaker.on('reject', () => console.log('Rejected - circuit open'));
|
|
110
|
+
breaker.on('open', () => console.log('Circuit opened'));
|
|
111
|
+
breaker.on('halfOpen', () => console.log('Circuit half-open'));
|
|
112
|
+
breaker.on('close', () => console.log('Circuit closed'));
|
|
113
|
+
breaker.on('fallback', (result) => console.log('Fallback:', result));
|
|
114
|
+
|
|
115
|
+
// Fallback
|
|
116
|
+
breaker.fallback(() => ({ cached: true, data: getCachedData() }));
|
|
117
|
+
|
|
118
|
+
// Usage
|
|
119
|
+
const result = await breaker.fire(requestParams);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Health Check Integration
|
|
123
|
+
```javascript
|
|
124
|
+
const breaker = new CircuitBreaker(callService, options);
|
|
125
|
+
|
|
126
|
+
// Health endpoint
|
|
127
|
+
app.get('/health', (req, res) => {
|
|
128
|
+
const health = {
|
|
129
|
+
status: breaker.opened ? 'degraded' : 'healthy',
|
|
130
|
+
circuitBreaker: {
|
|
131
|
+
state: breaker.opened ? 'open' : (breaker.halfOpen ? 'half-open' : 'closed'),
|
|
132
|
+
stats: breaker.stats
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
res.json(health);
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Configuration Guidelines
|
|
140
|
+
|
|
141
|
+
### Circuit Breaker Tuning
|
|
142
|
+
```yaml
|
|
143
|
+
# Conservative (for critical services)
|
|
144
|
+
failure_threshold: 25%
|
|
145
|
+
sliding_window: 20 calls
|
|
146
|
+
wait_in_open: 60 seconds
|
|
147
|
+
half_open_calls: 3
|
|
148
|
+
|
|
149
|
+
# Aggressive (for non-critical services)
|
|
150
|
+
failure_threshold: 50%
|
|
151
|
+
sliding_window: 10 calls
|
|
152
|
+
wait_in_open: 30 seconds
|
|
153
|
+
half_open_calls: 5
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Retry Configuration
|
|
157
|
+
```yaml
|
|
158
|
+
# Idempotent operations (safe to retry)
|
|
159
|
+
max_attempts: 3
|
|
160
|
+
initial_delay: 100ms
|
|
161
|
+
multiplier: 2
|
|
162
|
+
max_delay: 5s
|
|
163
|
+
jitter: 0.1
|
|
164
|
+
|
|
165
|
+
# Non-idempotent (use with caution)
|
|
166
|
+
max_attempts: 1
|
|
167
|
+
# Or use retry only for specific errors
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Timeout Guidelines
|
|
171
|
+
```yaml
|
|
172
|
+
# Timeouts should be:
|
|
173
|
+
# - Shorter than user patience (< 5s for UI)
|
|
174
|
+
# - Longer than P99 latency
|
|
175
|
+
# - Account for downstream timeouts
|
|
176
|
+
|
|
177
|
+
http_client: 5s
|
|
178
|
+
database: 10s
|
|
179
|
+
external_api: 15s
|
|
180
|
+
batch_operations: 60s
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## Best Practices
|
|
184
|
+
|
|
185
|
+
1. **Fail Fast**: Don't wait for timeouts when circuit is open
|
|
186
|
+
2. **Graceful Degradation**: Always have fallbacks
|
|
187
|
+
3. **Monitor Circuit State**: Alert on open circuits
|
|
188
|
+
4. **Tune Thresholds**: Based on actual failure patterns
|
|
189
|
+
5. **Test Failure Modes**: Chaos engineering
|
|
190
|
+
|
|
191
|
+
## Fallback Strategies
|
|
192
|
+
|
|
193
|
+
### Cached Response
|
|
194
|
+
```javascript
|
|
195
|
+
async function getUser(userId) {
|
|
196
|
+
try {
|
|
197
|
+
return await userService.getUser(userId);
|
|
198
|
+
} catch (error) {
|
|
199
|
+
return await cache.get(`user:${userId}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Default Value
|
|
205
|
+
```javascript
|
|
206
|
+
async function getRecommendations(userId) {
|
|
207
|
+
try {
|
|
208
|
+
return await recommendationService.get(userId);
|
|
209
|
+
} catch (error) {
|
|
210
|
+
return getDefaultRecommendations();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Degraded Service
|
|
216
|
+
```javascript
|
|
217
|
+
async function getProductDetails(productId) {
|
|
218
|
+
try {
|
|
219
|
+
return await getFullDetails(productId);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
// Return basic info from database
|
|
222
|
+
return await getBasicDetails(productId);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Anti-Patterns
|
|
228
|
+
|
|
229
|
+
- Circuit breaker without fallback
|
|
230
|
+
- Same timeout as downstream service
|
|
231
|
+
- Not resetting circuit after deployment
|
|
232
|
+
- Ignoring circuit breaker metrics
|
|
233
|
+
- Retrying non-idempotent operations
|
|
234
|
+
|
|
235
|
+
## When to Use
|
|
236
|
+
|
|
237
|
+
- Calling external/third-party services
|
|
238
|
+
- Microservice-to-microservice communication
|
|
239
|
+
- Operations that can fail transiently
|
|
240
|
+
- When graceful degradation is acceptable
|
|
241
|
+
|
|
242
|
+
## When NOT to Use
|
|
243
|
+
|
|
244
|
+
- Local operations that won't fail externally
|
|
245
|
+
- When all-or-nothing is required
|
|
246
|
+
- Very fast operations where overhead matters
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: contract-testing
|
|
3
|
+
description: Consumer-driven contract testing with Pact, schema validation, provider verification, and CI/CD integration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Contract Testing
|
|
7
|
+
|
|
8
|
+
Consumer-driven contract testing with Pact, schema validation, provider verification, and CI/CD integration.
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
Contract testing ensures services can communicate correctly by verifying that providers meet consumer expectations without requiring full integration tests.
|
|
13
|
+
|
|
14
|
+
## Key Concepts
|
|
15
|
+
|
|
16
|
+
### Consumer-Driven Contracts
|
|
17
|
+
- **Consumer**: Service that calls another service
|
|
18
|
+
- **Provider**: Service being called
|
|
19
|
+
- **Contract**: Expected interactions defined by consumer
|
|
20
|
+
- **Pact**: Contract file containing interactions
|
|
21
|
+
|
|
22
|
+
### Contract Types
|
|
23
|
+
- **Consumer Contracts**: What consumer expects
|
|
24
|
+
- **Provider Contracts**: What provider guarantees
|
|
25
|
+
- **Bidirectional**: Both sides define expectations
|
|
26
|
+
|
|
27
|
+
## Pact Implementation
|
|
28
|
+
|
|
29
|
+
### Consumer Test (JavaScript)
|
|
30
|
+
```javascript
|
|
31
|
+
const { Pact } = require('@pact-foundation/pact');
|
|
32
|
+
|
|
33
|
+
const provider = new Pact({
|
|
34
|
+
consumer: 'OrderService',
|
|
35
|
+
provider: 'UserService',
|
|
36
|
+
port: 1234,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('User Service Contract', () => {
|
|
40
|
+
beforeAll(() => provider.setup());
|
|
41
|
+
afterAll(() => provider.finalize());
|
|
42
|
+
afterEach(() => provider.verify());
|
|
43
|
+
|
|
44
|
+
describe('get user by id', () => {
|
|
45
|
+
beforeEach(() => {
|
|
46
|
+
return provider.addInteraction({
|
|
47
|
+
state: 'user with id 123 exists',
|
|
48
|
+
uponReceiving: 'a request for user 123',
|
|
49
|
+
withRequest: {
|
|
50
|
+
method: 'GET',
|
|
51
|
+
path: '/users/123',
|
|
52
|
+
headers: {
|
|
53
|
+
Accept: 'application/json',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
willRespondWith: {
|
|
57
|
+
status: 200,
|
|
58
|
+
headers: {
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
},
|
|
61
|
+
body: {
|
|
62
|
+
id: '123',
|
|
63
|
+
name: Matchers.string('John Doe'),
|
|
64
|
+
email: Matchers.email(),
|
|
65
|
+
createdAt: Matchers.iso8601DateTime(),
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('returns user details', async () => {
|
|
72
|
+
const user = await userClient.getUser('123');
|
|
73
|
+
expect(user.id).toBe('123');
|
|
74
|
+
expect(user.name).toBeDefined();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Provider Verification (JavaScript)
|
|
81
|
+
```javascript
|
|
82
|
+
const { Verifier } = require('@pact-foundation/pact');
|
|
83
|
+
|
|
84
|
+
describe('User Service Provider Verification', () => {
|
|
85
|
+
it('validates the expectations of OrderService', async () => {
|
|
86
|
+
const verifier = new Verifier({
|
|
87
|
+
provider: 'UserService',
|
|
88
|
+
providerBaseUrl: 'http://localhost:8080',
|
|
89
|
+
pactBrokerUrl: 'https://pact-broker.example.com',
|
|
90
|
+
publishVerificationResult: true,
|
|
91
|
+
providerVersion: process.env.GIT_SHA,
|
|
92
|
+
stateHandlers: {
|
|
93
|
+
'user with id 123 exists': async () => {
|
|
94
|
+
await createTestUser({ id: '123', name: 'John Doe' });
|
|
95
|
+
},
|
|
96
|
+
'no users exist': async () => {
|
|
97
|
+
await clearAllUsers();
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await verifier.verifyProvider();
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Pact Matchers
|
|
108
|
+
```javascript
|
|
109
|
+
const { Matchers } = require('@pact-foundation/pact');
|
|
110
|
+
|
|
111
|
+
// Type matchers
|
|
112
|
+
Matchers.string('example') // Any string
|
|
113
|
+
Matchers.integer(123) // Any integer
|
|
114
|
+
Matchers.decimal(12.34) // Any decimal
|
|
115
|
+
Matchers.boolean(true) // Any boolean
|
|
116
|
+
|
|
117
|
+
// Format matchers
|
|
118
|
+
Matchers.email() // Valid email
|
|
119
|
+
Matchers.uuid() // Valid UUID
|
|
120
|
+
Matchers.iso8601DateTime() // ISO 8601 datetime
|
|
121
|
+
Matchers.ipv4Address() // IPv4 address
|
|
122
|
+
|
|
123
|
+
// Collection matchers
|
|
124
|
+
Matchers.eachLike({ // Array with items like...
|
|
125
|
+
id: Matchers.integer(),
|
|
126
|
+
name: Matchers.string()
|
|
127
|
+
}, { min: 1 })
|
|
128
|
+
|
|
129
|
+
// Regex matcher
|
|
130
|
+
Matchers.term({
|
|
131
|
+
matcher: '^[A-Z]{2}[0-9]{4}$',
|
|
132
|
+
generate: 'AB1234'
|
|
133
|
+
})
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Pact Broker
|
|
137
|
+
|
|
138
|
+
### Publishing Contracts
|
|
139
|
+
```bash
|
|
140
|
+
# Publish pact files to broker
|
|
141
|
+
pact-broker publish ./pacts \
|
|
142
|
+
--consumer-app-version=$GIT_SHA \
|
|
143
|
+
--branch=$GIT_BRANCH \
|
|
144
|
+
--broker-base-url=https://pact-broker.example.com \
|
|
145
|
+
--broker-token=$PACT_BROKER_TOKEN
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Can-I-Deploy Check
|
|
149
|
+
```bash
|
|
150
|
+
# Check if safe to deploy
|
|
151
|
+
pact-broker can-i-deploy \
|
|
152
|
+
--pacticipant=OrderService \
|
|
153
|
+
--version=$GIT_SHA \
|
|
154
|
+
--to-environment=production \
|
|
155
|
+
--broker-base-url=https://pact-broker.example.com
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Webhooks
|
|
159
|
+
```json
|
|
160
|
+
{
|
|
161
|
+
"description": "Trigger provider verification on contract change",
|
|
162
|
+
"events": [
|
|
163
|
+
{ "name": "contract_content_changed" }
|
|
164
|
+
],
|
|
165
|
+
"request": {
|
|
166
|
+
"method": "POST",
|
|
167
|
+
"url": "https://ci.example.com/trigger",
|
|
168
|
+
"headers": {
|
|
169
|
+
"Content-Type": "application/json"
|
|
170
|
+
},
|
|
171
|
+
"body": {
|
|
172
|
+
"provider": "${pactbroker.providerName}",
|
|
173
|
+
"consumer": "${pactbroker.consumerName}",
|
|
174
|
+
"pactUrl": "${pactbroker.pactUrl}"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## CI/CD Integration
|
|
181
|
+
|
|
182
|
+
### Consumer Pipeline
|
|
183
|
+
```yaml
|
|
184
|
+
# GitHub Actions - Consumer
|
|
185
|
+
name: Consumer Contract Tests
|
|
186
|
+
|
|
187
|
+
on: [push]
|
|
188
|
+
|
|
189
|
+
jobs:
|
|
190
|
+
contract-tests:
|
|
191
|
+
runs-on: ubuntu-latest
|
|
192
|
+
steps:
|
|
193
|
+
- uses: actions/checkout@v3
|
|
194
|
+
|
|
195
|
+
- name: Run contract tests
|
|
196
|
+
run: npm run test:contract
|
|
197
|
+
|
|
198
|
+
- name: Publish contracts
|
|
199
|
+
run: |
|
|
200
|
+
pact-broker publish ./pacts \
|
|
201
|
+
--consumer-app-version=${{ github.sha }} \
|
|
202
|
+
--branch=${{ github.ref_name }} \
|
|
203
|
+
--broker-base-url=${{ secrets.PACT_BROKER_URL }} \
|
|
204
|
+
--broker-token=${{ secrets.PACT_BROKER_TOKEN }}
|
|
205
|
+
|
|
206
|
+
- name: Can I deploy?
|
|
207
|
+
run: |
|
|
208
|
+
pact-broker can-i-deploy \
|
|
209
|
+
--pacticipant=OrderService \
|
|
210
|
+
--version=${{ github.sha }} \
|
|
211
|
+
--to-environment=staging
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Provider Pipeline
|
|
215
|
+
```yaml
|
|
216
|
+
# GitHub Actions - Provider
|
|
217
|
+
name: Provider Verification
|
|
218
|
+
|
|
219
|
+
on:
|
|
220
|
+
push:
|
|
221
|
+
repository_dispatch:
|
|
222
|
+
types: [pact_changed]
|
|
223
|
+
|
|
224
|
+
jobs:
|
|
225
|
+
verify:
|
|
226
|
+
runs-on: ubuntu-latest
|
|
227
|
+
steps:
|
|
228
|
+
- uses: actions/checkout@v3
|
|
229
|
+
|
|
230
|
+
- name: Start provider
|
|
231
|
+
run: docker-compose up -d
|
|
232
|
+
|
|
233
|
+
- name: Verify contracts
|
|
234
|
+
run: npm run test:pact:verify
|
|
235
|
+
env:
|
|
236
|
+
PACT_BROKER_URL: ${{ secrets.PACT_BROKER_URL }}
|
|
237
|
+
PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
|
|
238
|
+
PROVIDER_VERSION: ${{ github.sha }}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Best Practices
|
|
242
|
+
|
|
243
|
+
1. **Consumer First**: Let consumers define expectations
|
|
244
|
+
2. **Minimal Contracts**: Only test what consumer needs
|
|
245
|
+
3. **State Management**: Proper provider state setup
|
|
246
|
+
4. **Version Everything**: Use git SHA for versions
|
|
247
|
+
5. **Automate Can-I-Deploy**: Gate deployments on verification
|
|
248
|
+
|
|
249
|
+
## Contract Design Guidelines
|
|
250
|
+
|
|
251
|
+
### What to Include
|
|
252
|
+
- Request path and method
|
|
253
|
+
- Required headers
|
|
254
|
+
- Request body structure
|
|
255
|
+
- Response status codes
|
|
256
|
+
- Response body structure
|
|
257
|
+
|
|
258
|
+
### What to Avoid
|
|
259
|
+
- Implementation details
|
|
260
|
+
- Exact values (use matchers)
|
|
261
|
+
- Optional fields unless needed
|
|
262
|
+
- Authentication details
|
|
263
|
+
|
|
264
|
+
## Anti-Patterns
|
|
265
|
+
|
|
266
|
+
- Testing every field exhaustively
|
|
267
|
+
- Coupling to specific values
|
|
268
|
+
- Ignoring provider states
|
|
269
|
+
- Skipping can-i-deploy checks
|
|
270
|
+
- Not versioning contracts
|
|
271
|
+
|
|
272
|
+
## When to Use
|
|
273
|
+
|
|
274
|
+
- Microservices with multiple consumers
|
|
275
|
+
- Independent team deployments
|
|
276
|
+
- APIs with breaking change risk
|
|
277
|
+
- Contract evolution tracking
|
|
278
|
+
|
|
279
|
+
## When NOT to Use
|
|
280
|
+
|
|
281
|
+
- Single consumer APIs
|
|
282
|
+
- Rapidly prototyping
|
|
283
|
+
- Internal implementation details
|
|
284
|
+
- UI testing
|