proagents 1.6.16 → 1.6.18
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/.claude/settings.local.json +169 -0
- package/COMMANDS.md +595 -0
- package/README.md +22 -64
- package/bin/proagents.js +0 -2
- package/lib/commands/init.js +4 -174
- package/package.json +2 -7
- package/.proagents/ai-models/README.md +0 -141
- package/.proagents/ai-models/cost-management.md +0 -362
- package/.proagents/ai-models/fallbacks.md +0 -342
- package/.proagents/ai-models/model-config.md +0 -318
- package/.proagents/ai-models/task-routing.md +0 -503
- package/.proagents/ai-training/README.md +0 -155
- package/.proagents/ai-training/continuous-learning.md +0 -413
- package/.proagents/ai-training/domain-knowledge.md +0 -378
- package/.proagents/ai-training/pattern-learning.md +0 -455
- package/.proagents/ai-training/training-data.md +0 -337
- package/.proagents/ai-training/user-preferences.md +0 -346
- package/.proagents/approval-workflows/README.md +0 -146
- package/.proagents/approval-workflows/approval-config.md +0 -332
- package/.proagents/approval-workflows/approval-stages.md +0 -503
- package/.proagents/approval-workflows/emergency-bypass.md +0 -351
- package/.proagents/approval-workflows/examples.md +0 -859
- package/.proagents/approval-workflows/notifications.md +0 -320
- package/.proagents/compliance/README.md +0 -206
- package/.proagents/compliance/access-control.md +0 -310
- package/.proagents/compliance/audit-logging.md +0 -444
- package/.proagents/compliance/compliance-frameworks.md +0 -429
- package/.proagents/compliance/reports.md +0 -491
- package/.proagents/compliance/retention-policies.md +0 -454
- package/.proagents/config-versioning/README.md +0 -120
- package/.proagents/config-versioning/changelog.md +0 -300
- package/.proagents/config-versioning/rollback.md +0 -283
- package/.proagents/config-versioning/versioning.md +0 -330
- package/.proagents/contract-testing/README.md +0 -223
- package/.proagents/contract-testing/contract-testing.md +0 -614
- package/.proagents/contract-testing/pact-integration.md +0 -507
- package/.proagents/contract-testing/schema-validation.md +0 -565
- package/.proagents/dependency-management/README.md +0 -140
- package/.proagents/dependency-management/automation.md +0 -363
- package/.proagents/dependency-management/compatibility.md +0 -319
- package/.proagents/dependency-management/security-scanning.md +0 -413
- package/.proagents/dependency-management/update-policies.md +0 -374
- package/.proagents/disaster-recovery/README.md +0 -247
- package/.proagents/disaster-recovery/automation.md +0 -366
- package/.proagents/disaster-recovery/backup-recovery.md +0 -571
- package/.proagents/disaster-recovery/incident-response.md +0 -565
- package/.proagents/disaster-recovery/rollback-procedures.md +0 -499
- package/.proagents/disaster-recovery/runbooks.md +0 -603
- package/.proagents/disaster-recovery/scenarios.md +0 -892
- package/.proagents/disaster-recovery/testing.md +0 -438
- package/.proagents/environments/README.md +0 -244
- package/.proagents/environments/configuration.md +0 -437
- package/.proagents/environments/promotion.md +0 -434
- package/.proagents/environments/setup.md +0 -420
- package/.proagents/examples/README.md +0 -55
- package/.proagents/examples/backend-nodejs/README.md +0 -188
- package/.proagents/examples/backend-nodejs/complete-conversation.md +0 -601
- package/.proagents/examples/backend-nodejs/proagents.config.yaml +0 -415
- package/.proagents/examples/backend-nodejs/workflow-example.md +0 -909
- package/.proagents/examples/fullstack-nextjs/README.md +0 -155
- package/.proagents/examples/fullstack-nextjs/complete-conversation.md +0 -604
- package/.proagents/examples/fullstack-nextjs/proagents.config.yaml +0 -287
- package/.proagents/examples/fullstack-nextjs/workflow-example.md +0 -553
- package/.proagents/examples/mobile-react-native/README.md +0 -171
- package/.proagents/examples/mobile-react-native/complete-conversation.md +0 -825
- package/.proagents/examples/mobile-react-native/proagents.config.yaml +0 -330
- package/.proagents/examples/mobile-react-native/workflow-example.md +0 -723
- package/.proagents/examples/web-frontend-react/README.md +0 -125
- package/.proagents/examples/web-frontend-react/complete-conversation.md +0 -556
- package/.proagents/examples/web-frontend-react/proagents.config.yaml +0 -183
- package/.proagents/examples/web-frontend-react/workflow-example.md +0 -603
- package/.proagents/existing-projects/README.md +0 -65
- package/.proagents/existing-projects/challenges.md +0 -861
- package/.proagents/existing-projects/coexistence-mode.md +0 -483
- package/.proagents/existing-projects/compatibility-assessment.md +0 -541
- package/.proagents/existing-projects/gradual-adoption.md +0 -515
- package/.proagents/existing-projects/migration-strategies.md +0 -788
- package/.proagents/existing-projects/pattern-reconciliation.md +0 -489
- package/.proagents/existing-projects/team-onboarding.md +0 -617
- package/.proagents/existing-projects/technical-debt-handling.md +0 -644
- package/.proagents/feature-flags/README.md +0 -263
- package/.proagents/feature-flags/ab-testing.md +0 -413
- package/.proagents/feature-flags/configuration.md +0 -420
- package/.proagents/feature-flags/kill-switches.md +0 -444
- package/.proagents/feature-flags/rollout-strategies.md +0 -392
- package/.proagents/history.log +0 -12
- package/.proagents/i18n/README.md +0 -133
- package/.proagents/i18n/extraction.md +0 -433
- package/.proagents/i18n/tms-integration.md +0 -332
- package/.proagents/i18n/translation-workflow.md +0 -413
- package/.proagents/i18n/validation.md +0 -355
- package/.proagents/logging/README.md +0 -276
- package/.proagents/logging/aggregation.md +0 -475
- package/.proagents/logging/log-levels.md +0 -376
- package/.proagents/logging/sensitive-data.md +0 -423
- package/.proagents/logging/structured-logging.md +0 -406
- package/.proagents/metrics/README.md +0 -69
- package/.proagents/metrics/code-quality-kpis.md +0 -461
- package/.proagents/metrics/deployment-metrics.md +0 -517
- package/.proagents/metrics/developer-productivity.md +0 -368
- package/.proagents/metrics/learning-effectiveness.md +0 -478
- package/.proagents/migrations/README.md +0 -77
- package/.proagents/migrations/from-claude-projects.md +0 -313
- package/.proagents/migrations/from-cursor-rules.md +0 -345
- package/.proagents/migrations/from-custom-workflows.md +0 -410
- package/.proagents/monitoring/README.md +0 -308
- package/.proagents/monitoring/alerting.md +0 -449
- package/.proagents/monitoring/dashboards.md +0 -454
- package/.proagents/monitoring/health-checks.md +0 -436
- package/.proagents/monitoring/metrics.md +0 -434
- package/.proagents/multi-project/README.md +0 -170
- package/.proagents/multi-project/coordinated-deploy.md +0 -510
- package/.proagents/multi-project/cross-project-deps.md +0 -395
- package/.proagents/multi-project/unified-changelog.md +0 -477
- package/.proagents/multi-project/walkthroughs/monorepo-setup.md +0 -787
- package/.proagents/multi-project/workspace-config.md +0 -408
- package/.proagents/notifications/README.md +0 -151
- package/.proagents/notifications/channels.md +0 -457
- package/.proagents/notifications/preferences.md +0 -415
- package/.proagents/notifications/routing.md +0 -449
- package/.proagents/notifications/scheduling.md +0 -425
- package/.proagents/notifications/templates.md +0 -446
- package/.proagents/offline-mode/README.md +0 -145
- package/.proagents/offline-mode/caching.md +0 -344
- package/.proagents/offline-mode/offline-operations.md +0 -312
- package/.proagents/offline-mode/queue-specifications.md +0 -679
- package/.proagents/offline-mode/sync.md +0 -475
- package/.proagents/parallel-features/README.md +0 -85
- package/.proagents/parallel-features/conflict-detection.md +0 -226
- package/.proagents/parallel-features/dependency-management.md +0 -392
- package/.proagents/parallel-features/merge-coordination.md +0 -506
- package/.proagents/parallel-features/tracking-system.md +0 -416
- package/.proagents/performance/README.md +0 -59
- package/.proagents/performance/bundle-analysis.md +0 -375
- package/.proagents/performance/load-testing.md +0 -563
- package/.proagents/performance/runtime-metrics.md +0 -489
- package/.proagents/performance/web-vitals.md +0 -425
- package/.proagents/plugins/README.md +0 -139
- package/.proagents/plugins/creating-plugins.md +0 -504
- package/.proagents/plugins/plugin-api.md +0 -467
- package/.proagents/plugins/plugin-registry.md +0 -276
- package/.proagents/reporting/README.md +0 -158
- package/.proagents/reporting/dashboards.md +0 -366
- package/.proagents/reporting/exports.md +0 -524
- package/.proagents/reporting/quality-metrics.md +0 -385
- package/.proagents/reporting/templates/README.md +0 -56
- package/.proagents/reporting/templates/dashboard-config.json +0 -187
- package/.proagents/reporting/templates/metrics-queries.md +0 -427
- package/.proagents/reporting/templates/react-dashboard.tsx +0 -544
- package/.proagents/reporting/templates/widgets.md +0 -451
- package/.proagents/reporting/velocity-metrics.md +0 -340
- package/.proagents/reverse-engineering/README.md +0 -151
- package/.proagents/reverse-engineering/architecture-extraction.md +0 -325
- package/.proagents/reverse-engineering/code-analysis.md +0 -377
- package/.proagents/reverse-engineering/dependency-mapping.md +0 -567
- package/.proagents/reverse-engineering/diagram-generation.md +0 -586
- package/.proagents/reverse-engineering/documentation-generation.md +0 -468
- package/.proagents/reverse-engineering/pattern-detection.md +0 -569
- package/.proagents/reverse-engineering/quality-assessment.md +0 -733
- package/.proagents/secrets/README.md +0 -278
- package/.proagents/secrets/access-control.md +0 -443
- package/.proagents/secrets/rotation.md +0 -403
- package/.proagents/secrets/scanning.md +0 -487
- package/.proagents/secrets/storage.md +0 -394
- package/.proagents/webhooks/README.md +0 -126
- package/.proagents/webhooks/endpoints.md +0 -298
- package/.proagents/webhooks/events.md +0 -316
- package/.proagents/webhooks/payloads.md +0 -325
- package/.proagents/webhooks/reliability.md +0 -363
- package/.proagents/webhooks/security.md +0 -380
|
@@ -1,507 +0,0 @@
|
|
|
1
|
-
# Pact Integration
|
|
2
|
-
|
|
3
|
-
Using Pact for consumer-driven contract testing.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Overview
|
|
8
|
-
|
|
9
|
-
Pact is the most popular contract testing tool, enabling consumer-driven contract testing between services.
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
## Installation
|
|
14
|
-
|
|
15
|
-
### Node.js
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npm install --save-dev @pact-foundation/pact
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### Other Languages
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
# Ruby
|
|
25
|
-
gem install pact
|
|
26
|
-
|
|
27
|
-
# Python
|
|
28
|
-
pip install pact-python
|
|
29
|
-
|
|
30
|
-
# Go
|
|
31
|
-
go get github.com/pact-foundation/pact-go
|
|
32
|
-
|
|
33
|
-
# JVM
|
|
34
|
-
implementation 'au.com.dius.pact.consumer:junit5:4.5.0'
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## Consumer Testing
|
|
40
|
-
|
|
41
|
-
### Basic Setup
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
import { PactV3, MatchersV3 } from '@pact-foundation/pact';
|
|
45
|
-
import { UserClient } from '../src/clients/user-client';
|
|
46
|
-
|
|
47
|
-
const provider = new PactV3({
|
|
48
|
-
consumer: 'WebApp',
|
|
49
|
-
provider: 'UserService',
|
|
50
|
-
dir: './pacts',
|
|
51
|
-
logLevel: 'info',
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
describe('UserClient', () => {
|
|
55
|
-
describe('getUser', () => {
|
|
56
|
-
it('returns user when found', async () => {
|
|
57
|
-
// Arrange: Define the expected interaction
|
|
58
|
-
await provider
|
|
59
|
-
.given('a user with ID 123 exists')
|
|
60
|
-
.uponReceiving('a request to get user 123')
|
|
61
|
-
.withRequest({
|
|
62
|
-
method: 'GET',
|
|
63
|
-
path: '/api/users/123',
|
|
64
|
-
headers: {
|
|
65
|
-
Accept: 'application/json',
|
|
66
|
-
},
|
|
67
|
-
})
|
|
68
|
-
.willRespondWith({
|
|
69
|
-
status: 200,
|
|
70
|
-
headers: {
|
|
71
|
-
'Content-Type': 'application/json',
|
|
72
|
-
},
|
|
73
|
-
body: {
|
|
74
|
-
id: MatchersV3.string('123'),
|
|
75
|
-
name: MatchersV3.string('John Doe'),
|
|
76
|
-
email: MatchersV3.email('john@example.com'),
|
|
77
|
-
createdAt: MatchersV3.datetime('yyyy-MM-dd\'T\'HH:mm:ss.SSSXXX'),
|
|
78
|
-
},
|
|
79
|
-
})
|
|
80
|
-
.executeTest(async (mockServer) => {
|
|
81
|
-
// Act: Call the client against mock server
|
|
82
|
-
const client = new UserClient(mockServer.url);
|
|
83
|
-
const user = await client.getUser('123');
|
|
84
|
-
|
|
85
|
-
// Assert: Verify the response
|
|
86
|
-
expect(user.id).toBe('123');
|
|
87
|
-
expect(user.name).toBe('John Doe');
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('returns 404 when user not found', async () => {
|
|
92
|
-
await provider
|
|
93
|
-
.given('no user exists with ID 999')
|
|
94
|
-
.uponReceiving('a request for non-existent user')
|
|
95
|
-
.withRequest({
|
|
96
|
-
method: 'GET',
|
|
97
|
-
path: '/api/users/999',
|
|
98
|
-
})
|
|
99
|
-
.willRespondWith({
|
|
100
|
-
status: 404,
|
|
101
|
-
body: {
|
|
102
|
-
error: MatchersV3.string('User not found'),
|
|
103
|
-
code: 'USER_NOT_FOUND',
|
|
104
|
-
},
|
|
105
|
-
})
|
|
106
|
-
.executeTest(async (mockServer) => {
|
|
107
|
-
const client = new UserClient(mockServer.url);
|
|
108
|
-
|
|
109
|
-
await expect(client.getUser('999')).rejects.toThrow('User not found');
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
describe('createUser', () => {
|
|
115
|
-
it('creates a new user', async () => {
|
|
116
|
-
const newUser = {
|
|
117
|
-
name: 'Jane Doe',
|
|
118
|
-
email: 'jane@example.com',
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
await provider
|
|
122
|
-
.uponReceiving('a request to create a user')
|
|
123
|
-
.withRequest({
|
|
124
|
-
method: 'POST',
|
|
125
|
-
path: '/api/users',
|
|
126
|
-
headers: {
|
|
127
|
-
'Content-Type': 'application/json',
|
|
128
|
-
},
|
|
129
|
-
body: newUser,
|
|
130
|
-
})
|
|
131
|
-
.willRespondWith({
|
|
132
|
-
status: 201,
|
|
133
|
-
body: {
|
|
134
|
-
id: MatchersV3.uuid(),
|
|
135
|
-
...newUser,
|
|
136
|
-
createdAt: MatchersV3.datetime(),
|
|
137
|
-
},
|
|
138
|
-
})
|
|
139
|
-
.executeTest(async (mockServer) => {
|
|
140
|
-
const client = new UserClient(mockServer.url);
|
|
141
|
-
const created = await client.createUser(newUser);
|
|
142
|
-
|
|
143
|
-
expect(created.name).toBe('Jane Doe');
|
|
144
|
-
expect(created.id).toBeDefined();
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Using Matchers
|
|
152
|
-
|
|
153
|
-
```typescript
|
|
154
|
-
import { MatchersV3 as M } from '@pact-foundation/pact';
|
|
155
|
-
|
|
156
|
-
// String matchers
|
|
157
|
-
M.string('example') // Any string, example value shown
|
|
158
|
-
M.regex(/^[A-Z]{3}$/, 'ABC') // Regex match
|
|
159
|
-
|
|
160
|
-
// Number matchers
|
|
161
|
-
M.number(42) // Any number
|
|
162
|
-
M.integer(42) // Any integer
|
|
163
|
-
M.decimal(3.14) // Any decimal
|
|
164
|
-
|
|
165
|
-
// Boolean
|
|
166
|
-
M.boolean(true) // Any boolean
|
|
167
|
-
|
|
168
|
-
// Special formats
|
|
169
|
-
M.email('test@example.com') // Valid email format
|
|
170
|
-
M.uuid() // Valid UUID
|
|
171
|
-
M.datetime() // ISO datetime
|
|
172
|
-
M.date('2024-01-15') // Date format
|
|
173
|
-
M.time('14:30:00') // Time format
|
|
174
|
-
M.ipv4Address() // IPv4 address
|
|
175
|
-
|
|
176
|
-
// Collections
|
|
177
|
-
M.eachLike({ id: M.string() }) // Array with at least one element
|
|
178
|
-
M.atLeastOneLike({ id: M.string() }, 3) // At least 3 elements
|
|
179
|
-
|
|
180
|
-
// Objects
|
|
181
|
-
M.like({ // Match structure, not values
|
|
182
|
-
id: M.string(),
|
|
183
|
-
name: M.string(),
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
// Nullable
|
|
187
|
-
M.nullValue() // Null value
|
|
188
|
-
M.or(M.string(), M.nullValue()) // String or null
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### Request/Response Examples
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
// Query parameters
|
|
195
|
-
.withRequest({
|
|
196
|
-
method: 'GET',
|
|
197
|
-
path: '/api/users',
|
|
198
|
-
query: {
|
|
199
|
-
page: '1',
|
|
200
|
-
limit: '10',
|
|
201
|
-
sort: 'name',
|
|
202
|
-
},
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
// Headers
|
|
206
|
-
.withRequest({
|
|
207
|
-
method: 'GET',
|
|
208
|
-
path: '/api/users',
|
|
209
|
-
headers: {
|
|
210
|
-
Authorization: MatchersV3.regex(/^Bearer .+$/, 'Bearer token123'),
|
|
211
|
-
'X-Request-ID': MatchersV3.uuid(),
|
|
212
|
-
},
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
// Array response
|
|
216
|
-
.willRespondWith({
|
|
217
|
-
status: 200,
|
|
218
|
-
body: {
|
|
219
|
-
data: MatchersV3.eachLike({
|
|
220
|
-
id: MatchersV3.string(),
|
|
221
|
-
name: MatchersV3.string(),
|
|
222
|
-
}),
|
|
223
|
-
pagination: {
|
|
224
|
-
page: MatchersV3.integer(1),
|
|
225
|
-
total: MatchersV3.integer(100),
|
|
226
|
-
},
|
|
227
|
-
},
|
|
228
|
-
})
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
|
-
## Provider Verification
|
|
234
|
-
|
|
235
|
-
### Basic Verification
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
import { Verifier } from '@pact-foundation/pact';
|
|
239
|
-
|
|
240
|
-
describe('UserService Provider', () => {
|
|
241
|
-
// Start your real service before tests
|
|
242
|
-
beforeAll(async () => {
|
|
243
|
-
await startServer(3000);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
afterAll(async () => {
|
|
247
|
-
await stopServer();
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('validates the contract', async () => {
|
|
251
|
-
const verifier = new Verifier({
|
|
252
|
-
providerBaseUrl: 'http://localhost:3000',
|
|
253
|
-
pactUrls: [
|
|
254
|
-
'./pacts/webapp-userservice.json',
|
|
255
|
-
],
|
|
256
|
-
stateHandlers: {
|
|
257
|
-
'a user with ID 123 exists': async () => {
|
|
258
|
-
// Set up the required state
|
|
259
|
-
await db.users.create({
|
|
260
|
-
id: '123',
|
|
261
|
-
name: 'John Doe',
|
|
262
|
-
email: 'john@example.com',
|
|
263
|
-
});
|
|
264
|
-
},
|
|
265
|
-
'no user exists with ID 999': async () => {
|
|
266
|
-
// Ensure user doesn't exist
|
|
267
|
-
await db.users.deleteAll();
|
|
268
|
-
},
|
|
269
|
-
},
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
await verifier.verifyProvider();
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
### State Handlers
|
|
278
|
-
|
|
279
|
-
```typescript
|
|
280
|
-
const stateHandlers = {
|
|
281
|
-
// Simple state
|
|
282
|
-
'user exists': async () => {
|
|
283
|
-
await db.users.create({ id: '123', name: 'Test User' });
|
|
284
|
-
},
|
|
285
|
-
|
|
286
|
-
// State with parameters
|
|
287
|
-
'user exists': async (params: { userId: string }) => {
|
|
288
|
-
await db.users.create({ id: params.userId, name: 'Test User' });
|
|
289
|
-
},
|
|
290
|
-
|
|
291
|
-
// State teardown
|
|
292
|
-
'user exists': {
|
|
293
|
-
setup: async () => {
|
|
294
|
-
await db.users.create({ id: '123', name: 'Test User' });
|
|
295
|
-
},
|
|
296
|
-
teardown: async () => {
|
|
297
|
-
await db.users.delete('123');
|
|
298
|
-
},
|
|
299
|
-
},
|
|
300
|
-
|
|
301
|
-
// No-op state
|
|
302
|
-
'default state': async () => {
|
|
303
|
-
// Nothing to set up
|
|
304
|
-
},
|
|
305
|
-
};
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
### Using Pact Broker
|
|
309
|
-
|
|
310
|
-
```typescript
|
|
311
|
-
const verifier = new Verifier({
|
|
312
|
-
providerBaseUrl: 'http://localhost:3000',
|
|
313
|
-
|
|
314
|
-
// Use Pact Broker
|
|
315
|
-
pactBrokerUrl: 'https://your-broker.pactflow.io',
|
|
316
|
-
pactBrokerToken: process.env.PACT_BROKER_TOKEN,
|
|
317
|
-
provider: 'UserService',
|
|
318
|
-
|
|
319
|
-
// Which pacts to verify
|
|
320
|
-
consumerVersionSelectors: [
|
|
321
|
-
{ mainBranch: true }, // Main branch
|
|
322
|
-
{ deployedOrReleased: true }, // Deployed versions
|
|
323
|
-
{ matchingBranch: true }, // Same branch as provider
|
|
324
|
-
],
|
|
325
|
-
|
|
326
|
-
// Publish verification results
|
|
327
|
-
publishVerificationResult: true,
|
|
328
|
-
providerVersion: process.env.GIT_COMMIT,
|
|
329
|
-
providerVersionBranch: process.env.GIT_BRANCH,
|
|
330
|
-
|
|
331
|
-
stateHandlers,
|
|
332
|
-
});
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
---
|
|
336
|
-
|
|
337
|
-
## Pact Broker
|
|
338
|
-
|
|
339
|
-
### Publishing Contracts
|
|
340
|
-
|
|
341
|
-
```typescript
|
|
342
|
-
import { Publisher } from '@pact-foundation/pact';
|
|
343
|
-
|
|
344
|
-
const publisher = new Publisher({
|
|
345
|
-
pactBroker: 'https://your-broker.pactflow.io',
|
|
346
|
-
pactBrokerToken: process.env.PACT_BROKER_TOKEN,
|
|
347
|
-
pactFilesOrDirs: ['./pacts'],
|
|
348
|
-
consumerVersion: process.env.GIT_COMMIT,
|
|
349
|
-
branch: process.env.GIT_BRANCH,
|
|
350
|
-
tags: ['main'],
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
await publisher.publish();
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
### Can-I-Deploy
|
|
357
|
-
|
|
358
|
-
```bash
|
|
359
|
-
# Check if consumer can deploy
|
|
360
|
-
pact-broker can-i-deploy \
|
|
361
|
-
--pacticipant WebApp \
|
|
362
|
-
--version $GIT_COMMIT \
|
|
363
|
-
--to-environment production
|
|
364
|
-
|
|
365
|
-
# Check if provider can deploy
|
|
366
|
-
pact-broker can-i-deploy \
|
|
367
|
-
--pacticipant UserService \
|
|
368
|
-
--version $GIT_COMMIT \
|
|
369
|
-
--to-environment production
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
### Recording Deployments
|
|
373
|
-
|
|
374
|
-
```bash
|
|
375
|
-
# Record deployment to environment
|
|
376
|
-
pact-broker record-deployment \
|
|
377
|
-
--pacticipant UserService \
|
|
378
|
-
--version $GIT_COMMIT \
|
|
379
|
-
--environment production
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
---
|
|
383
|
-
|
|
384
|
-
## CI/CD Integration
|
|
385
|
-
|
|
386
|
-
### GitHub Actions
|
|
387
|
-
|
|
388
|
-
```yaml
|
|
389
|
-
name: Contract Tests
|
|
390
|
-
|
|
391
|
-
on:
|
|
392
|
-
push:
|
|
393
|
-
branches: [main, develop]
|
|
394
|
-
pull_request:
|
|
395
|
-
|
|
396
|
-
jobs:
|
|
397
|
-
consumer-tests:
|
|
398
|
-
runs-on: ubuntu-latest
|
|
399
|
-
steps:
|
|
400
|
-
- uses: actions/checkout@v3
|
|
401
|
-
|
|
402
|
-
- name: Setup Node.js
|
|
403
|
-
uses: actions/setup-node@v3
|
|
404
|
-
with:
|
|
405
|
-
node-version: '18'
|
|
406
|
-
|
|
407
|
-
- name: Install dependencies
|
|
408
|
-
run: npm ci
|
|
409
|
-
|
|
410
|
-
- name: Run consumer contract tests
|
|
411
|
-
run: npm run test:contract:consumer
|
|
412
|
-
|
|
413
|
-
- name: Publish pacts
|
|
414
|
-
if: github.ref == 'refs/heads/main'
|
|
415
|
-
run: |
|
|
416
|
-
npm run pact:publish
|
|
417
|
-
env:
|
|
418
|
-
PACT_BROKER_URL: ${{ secrets.PACT_BROKER_URL }}
|
|
419
|
-
PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
|
|
420
|
-
GIT_COMMIT: ${{ github.sha }}
|
|
421
|
-
GIT_BRANCH: ${{ github.ref_name }}
|
|
422
|
-
|
|
423
|
-
provider-tests:
|
|
424
|
-
runs-on: ubuntu-latest
|
|
425
|
-
steps:
|
|
426
|
-
- uses: actions/checkout@v3
|
|
427
|
-
|
|
428
|
-
- name: Setup Node.js
|
|
429
|
-
uses: actions/setup-node@v3
|
|
430
|
-
with:
|
|
431
|
-
node-version: '18'
|
|
432
|
-
|
|
433
|
-
- name: Install dependencies
|
|
434
|
-
run: npm ci
|
|
435
|
-
|
|
436
|
-
- name: Start provider service
|
|
437
|
-
run: npm run start:test &
|
|
438
|
-
env:
|
|
439
|
-
PORT: 3000
|
|
440
|
-
|
|
441
|
-
- name: Run provider verification
|
|
442
|
-
run: npm run test:contract:provider
|
|
443
|
-
env:
|
|
444
|
-
PACT_BROKER_URL: ${{ secrets.PACT_BROKER_URL }}
|
|
445
|
-
PACT_BROKER_TOKEN: ${{ secrets.PACT_BROKER_TOKEN }}
|
|
446
|
-
|
|
447
|
-
can-i-deploy:
|
|
448
|
-
runs-on: ubuntu-latest
|
|
449
|
-
needs: [consumer-tests, provider-tests]
|
|
450
|
-
steps:
|
|
451
|
-
- name: Can I Deploy
|
|
452
|
-
run: |
|
|
453
|
-
docker run --rm \
|
|
454
|
-
pactfoundation/pact-cli:latest \
|
|
455
|
-
broker can-i-deploy \
|
|
456
|
-
--pacticipant ${{ github.event.repository.name }} \
|
|
457
|
-
--version ${{ github.sha }} \
|
|
458
|
-
--to-environment production \
|
|
459
|
-
--broker-base-url ${{ secrets.PACT_BROKER_URL }} \
|
|
460
|
-
--broker-token ${{ secrets.PACT_BROKER_TOKEN }}
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
---
|
|
464
|
-
|
|
465
|
-
## Commands Reference
|
|
466
|
-
|
|
467
|
-
```bash
|
|
468
|
-
# Consumer tests
|
|
469
|
-
npm run test:contract:consumer
|
|
470
|
-
|
|
471
|
-
# Provider verification
|
|
472
|
-
npm run test:contract:provider
|
|
473
|
-
|
|
474
|
-
# Publish pacts
|
|
475
|
-
npm run pact:publish
|
|
476
|
-
|
|
477
|
-
# Can-I-Deploy check
|
|
478
|
-
pact-broker can-i-deploy \
|
|
479
|
-
--pacticipant MyApp \
|
|
480
|
-
--version $(git rev-parse HEAD) \
|
|
481
|
-
--to production
|
|
482
|
-
|
|
483
|
-
# Record deployment
|
|
484
|
-
pact-broker record-deployment \
|
|
485
|
-
--pacticipant MyApp \
|
|
486
|
-
--version $(git rev-parse HEAD) \
|
|
487
|
-
--environment production
|
|
488
|
-
|
|
489
|
-
# Create webhook
|
|
490
|
-
pact-broker create-or-update-webhook \
|
|
491
|
-
--uuid my-webhook \
|
|
492
|
-
--url https://api.example.com/pact-changed \
|
|
493
|
-
--contract-content-changed
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
---
|
|
497
|
-
|
|
498
|
-
## Best Practices
|
|
499
|
-
|
|
500
|
-
1. **Consumer-first**: Write consumer tests before implementing provider
|
|
501
|
-
2. **Minimal contracts**: Only include fields you actually use
|
|
502
|
-
3. **Use matchers**: Don't hardcode exact values
|
|
503
|
-
4. **Meaningful states**: Make state names descriptive
|
|
504
|
-
5. **Clean state**: Reset database between tests
|
|
505
|
-
6. **Version properly**: Use git commit SHA for versions
|
|
506
|
-
7. **Automate publishing**: Publish contracts in CI
|
|
507
|
-
8. **Block deployments**: Use can-i-deploy as gate
|