@contractspec/lib.progressive-delivery 34.0.15 → 34.0.17
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/dist/browser/index.js +1 -208
- package/dist/index.js +1 -208
- package/dist/node/index.js +1 -208
- package/package.json +6 -6
package/dist/browser/index.js
CHANGED
|
@@ -1,208 +1 @@
|
|
|
1
|
-
|
|
2
|
-
class CanaryAnalyzer {
|
|
3
|
-
defaults;
|
|
4
|
-
constructor(defaults) {
|
|
5
|
-
this.defaults = defaults;
|
|
6
|
-
}
|
|
7
|
-
evaluate(stage, metrics) {
|
|
8
|
-
const thresholds = { ...this.defaults, ...stage.thresholds };
|
|
9
|
-
const reasons = [];
|
|
10
|
-
if (metrics.errorRate > thresholds.errorRate) {
|
|
11
|
-
reasons.push(`errorRate ${metrics.errorRate.toFixed(4)} > ${thresholds.errorRate}`);
|
|
12
|
-
}
|
|
13
|
-
if (typeof thresholds.latencyP50 === "number" && metrics.latencyP50 > thresholds.latencyP50) {
|
|
14
|
-
reasons.push(`latencyP50 ${metrics.latencyP50}ms > ${thresholds.latencyP50}ms`);
|
|
15
|
-
}
|
|
16
|
-
if (typeof thresholds.latencyP95 === "number" && metrics.latencyP95 > thresholds.latencyP95) {
|
|
17
|
-
reasons.push(`latencyP95 ${metrics.latencyP95}ms > ${thresholds.latencyP95}ms`);
|
|
18
|
-
}
|
|
19
|
-
if (typeof thresholds.latencyP99 === "number" && metrics.latencyP99 > thresholds.latencyP99) {
|
|
20
|
-
reasons.push(`latencyP99 ${metrics.latencyP99}ms > ${thresholds.latencyP99}ms`);
|
|
21
|
-
}
|
|
22
|
-
if (typeof thresholds.throughputDrop === "number" && metrics.throughput < thresholds.throughputDrop) {
|
|
23
|
-
reasons.push(`throughput ${metrics.throughput} < ${thresholds.throughputDrop}`);
|
|
24
|
-
}
|
|
25
|
-
if (thresholds.customEvaluator && !thresholds.customEvaluator(metrics)) {
|
|
26
|
-
reasons.push("custom evaluator reported failure");
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
status: reasons.length === 0 ? "pass" : "fail",
|
|
30
|
-
reasons,
|
|
31
|
-
metrics
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// src/canary-controller.ts
|
|
36
|
-
var DEFAULT_STAGES = [
|
|
37
|
-
{ percentage: 1, minDurationMs: 5 * 60 * 1000, label: "1%" },
|
|
38
|
-
{ percentage: 10, minDurationMs: 5 * 60 * 1000, label: "10%" },
|
|
39
|
-
{ percentage: 50, minDurationMs: 10 * 60 * 1000, label: "50%" },
|
|
40
|
-
{ percentage: 100, minDurationMs: 15 * 60 * 1000, label: "100%" }
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
class CanaryController {
|
|
44
|
-
options;
|
|
45
|
-
stages;
|
|
46
|
-
constructor(options) {
|
|
47
|
-
this.options = options;
|
|
48
|
-
this.stages = options.strategy.stages && options.strategy.stages.length > 0 ? options.strategy.stages : DEFAULT_STAGES;
|
|
49
|
-
}
|
|
50
|
-
getStageList() {
|
|
51
|
-
return [...this.stages];
|
|
52
|
-
}
|
|
53
|
-
async runStage(stage) {
|
|
54
|
-
this.options.eventBus?.emit({
|
|
55
|
-
type: "stage_started",
|
|
56
|
-
timestamp: new Date,
|
|
57
|
-
payload: { stage }
|
|
58
|
-
});
|
|
59
|
-
const metrics = await this.options.metricsProvider(stage, stage.minDurationMs);
|
|
60
|
-
const analysis = this.options.analyzer.evaluate(stage, metrics);
|
|
61
|
-
this.options.eventBus?.emit({
|
|
62
|
-
type: analysis.status === "pass" ? "stage_passed" : "stage_failed",
|
|
63
|
-
timestamp: new Date,
|
|
64
|
-
payload: { stage, metrics, analysis }
|
|
65
|
-
});
|
|
66
|
-
return analysis;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
|
|
70
|
-
const analyzer = new CanaryAnalyzer(strategy.thresholds);
|
|
71
|
-
return new CanaryController({
|
|
72
|
-
strategy,
|
|
73
|
-
analyzer,
|
|
74
|
-
metricsProvider,
|
|
75
|
-
eventBus
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
// src/deployment-coordinator.ts
|
|
79
|
-
class DeploymentCoordinator {
|
|
80
|
-
options;
|
|
81
|
-
constructor(options) {
|
|
82
|
-
this.options = options;
|
|
83
|
-
}
|
|
84
|
-
async run() {
|
|
85
|
-
const stages = this.options.controller.getStageList();
|
|
86
|
-
for (const stage of stages) {
|
|
87
|
-
const split = this.options.trafficShifter.computeSplit(stage);
|
|
88
|
-
await this.options.applyTrafficSplit(stage, split);
|
|
89
|
-
const analysis = await this.options.controller.runStage(stage);
|
|
90
|
-
if (analysis.status === "fail") {
|
|
91
|
-
const action = await this.options.rollbackManager.execute(stage, analysis.reasons.join(", "));
|
|
92
|
-
this.options.eventBus?.emit({
|
|
93
|
-
type: "rolled_back",
|
|
94
|
-
timestamp: action.triggeredAt,
|
|
95
|
-
payload: { stage, reasons: analysis.reasons }
|
|
96
|
-
});
|
|
97
|
-
return {
|
|
98
|
-
status: "rolled_back",
|
|
99
|
-
failedStage: stage,
|
|
100
|
-
reasons: analysis.reasons
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (this.options.strategy.mode === "blue-green") {
|
|
105
|
-
this.options.eventBus?.emit({
|
|
106
|
-
type: "blue_green_swapped",
|
|
107
|
-
timestamp: new Date,
|
|
108
|
-
payload: { strategy: this.options.strategy }
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
this.options.eventBus?.emit({
|
|
112
|
-
type: "completed",
|
|
113
|
-
timestamp: new Date,
|
|
114
|
-
payload: { strategy: this.options.strategy }
|
|
115
|
-
});
|
|
116
|
-
return { status: "completed" };
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// src/events.ts
|
|
120
|
-
class DeploymentEventBus {
|
|
121
|
-
listeners = new Set;
|
|
122
|
-
on(listener) {
|
|
123
|
-
this.listeners.add(listener);
|
|
124
|
-
return () => this.listeners.delete(listener);
|
|
125
|
-
}
|
|
126
|
-
emit(event) {
|
|
127
|
-
for (const listener of this.listeners) {
|
|
128
|
-
try {
|
|
129
|
-
listener(event);
|
|
130
|
-
} catch (error) {
|
|
131
|
-
console.error("[progressive-delivery] listener error", error);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// src/feature-flags.ts
|
|
137
|
-
var ContractSpecFeatureFlags = {
|
|
138
|
-
LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
|
|
139
|
-
LIFECYCLE_ADVISOR_ALPHA: "lifecycle_advisor_alpha",
|
|
140
|
-
LIFECYCLE_MANAGED_SERVICE: "lifecycle_managed_service",
|
|
141
|
-
STUDIO_VISUAL_BUILDER: "studio_visual_builder",
|
|
142
|
-
STUDIO_AUTO_EVOLUTION: "studio_auto_evolution",
|
|
143
|
-
STUDIO_BYOK: "studio_byok",
|
|
144
|
-
STUDIO_DEDICATED_DEPLOYMENT: "studio_dedicated_deployment",
|
|
145
|
-
STUDIO_INTEGRATION_HUB: "studio_integration_hub",
|
|
146
|
-
STUDIO_KNOWLEDGE_HUB: "studio_knowledge_hub",
|
|
147
|
-
STUDIO_TEMPLATES: "studio_templates"
|
|
148
|
-
};
|
|
149
|
-
var lifecycleFlags = [
|
|
150
|
-
ContractSpecFeatureFlags.LIFECYCLE_DETECTION_ALPHA,
|
|
151
|
-
ContractSpecFeatureFlags.LIFECYCLE_ADVISOR_ALPHA,
|
|
152
|
-
ContractSpecFeatureFlags.LIFECYCLE_MANAGED_SERVICE
|
|
153
|
-
];
|
|
154
|
-
var studioFlags = [
|
|
155
|
-
ContractSpecFeatureFlags.STUDIO_VISUAL_BUILDER,
|
|
156
|
-
ContractSpecFeatureFlags.STUDIO_AUTO_EVOLUTION,
|
|
157
|
-
ContractSpecFeatureFlags.STUDIO_BYOK,
|
|
158
|
-
ContractSpecFeatureFlags.STUDIO_DEDICATED_DEPLOYMENT,
|
|
159
|
-
ContractSpecFeatureFlags.STUDIO_INTEGRATION_HUB,
|
|
160
|
-
ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
|
|
161
|
-
ContractSpecFeatureFlags.STUDIO_TEMPLATES
|
|
162
|
-
];
|
|
163
|
-
// src/rollback-manager.ts
|
|
164
|
-
class RollbackManager {
|
|
165
|
-
options;
|
|
166
|
-
constructor(options) {
|
|
167
|
-
this.options = options;
|
|
168
|
-
}
|
|
169
|
-
async execute(stage, reason) {
|
|
170
|
-
await this.options.rollback(stage, reason);
|
|
171
|
-
const action = {
|
|
172
|
-
reason,
|
|
173
|
-
stage,
|
|
174
|
-
triggeredAt: new Date
|
|
175
|
-
};
|
|
176
|
-
this.options.onRollback?.(action);
|
|
177
|
-
return action;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
// src/traffic-shifter.ts
|
|
181
|
-
class TrafficShifter {
|
|
182
|
-
mode;
|
|
183
|
-
constructor(mode) {
|
|
184
|
-
this.mode = mode;
|
|
185
|
-
}
|
|
186
|
-
computeSplit(stage) {
|
|
187
|
-
if (this.mode === "blue-green") {
|
|
188
|
-
return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
|
|
189
|
-
}
|
|
190
|
-
const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
|
|
191
|
-
return {
|
|
192
|
-
candidate,
|
|
193
|
-
stable: 1 - candidate
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
export {
|
|
198
|
-
studioFlags,
|
|
199
|
-
lifecycleFlags,
|
|
200
|
-
createDefaultCanaryController,
|
|
201
|
-
TrafficShifter,
|
|
202
|
-
RollbackManager,
|
|
203
|
-
DeploymentEventBus,
|
|
204
|
-
DeploymentCoordinator,
|
|
205
|
-
ContractSpecFeatureFlags,
|
|
206
|
-
CanaryController,
|
|
207
|
-
CanaryAnalyzer
|
|
208
|
-
};
|
|
1
|
+
class n{defaults;constructor(e){this.defaults=e}evaluate(e,t){let a={...this.defaults,...e.thresholds},r=[];if(t.errorRate>a.errorRate)r.push(`errorRate ${t.errorRate.toFixed(4)} > ${a.errorRate}`);if(typeof a.latencyP50==="number"&&t.latencyP50>a.latencyP50)r.push(`latencyP50 ${t.latencyP50}ms > ${a.latencyP50}ms`);if(typeof a.latencyP95==="number"&&t.latencyP95>a.latencyP95)r.push(`latencyP95 ${t.latencyP95}ms > ${a.latencyP95}ms`);if(typeof a.latencyP99==="number"&&t.latencyP99>a.latencyP99)r.push(`latencyP99 ${t.latencyP99}ms > ${a.latencyP99}ms`);if(typeof a.throughputDrop==="number"&&t.throughput<a.throughputDrop)r.push(`throughput ${t.throughput} < ${a.throughputDrop}`);if(a.customEvaluator&&!a.customEvaluator(t))r.push("custom evaluator reported failure");return{status:r.length===0?"pass":"fail",reasons:r,metrics:t}}}var l=[{percentage:1,minDurationMs:300000,label:"1%"},{percentage:10,minDurationMs:300000,label:"10%"},{percentage:50,minDurationMs:600000,label:"50%"},{percentage:100,minDurationMs:900000,label:"100%"}];class s{options;stages;constructor(e){this.options=e;this.stages=e.strategy.stages&&e.strategy.stages.length>0?e.strategy.stages:l}getStageList(){return[...this.stages]}async runStage(e){this.options.eventBus?.emit({type:"stage_started",timestamp:new Date,payload:{stage:e}});let t=await this.options.metricsProvider(e,e.minDurationMs),a=this.options.analyzer.evaluate(e,t);return this.options.eventBus?.emit({type:a.status==="pass"?"stage_passed":"stage_failed",timestamp:new Date,payload:{stage:e,metrics:t,analysis:a}}),a}}function g(e,t,a){let r=new n(e.thresholds);return new s({strategy:e,analyzer:r,metricsProvider:t,eventBus:a})}class p{options;constructor(e){this.options=e}async run(){let e=this.options.controller.getStageList();for(let t of e){let a=this.options.trafficShifter.computeSplit(t);await this.options.applyTrafficSplit(t,a);let r=await this.options.controller.runStage(t);if(r.status==="fail"){let i=await this.options.rollbackManager.execute(t,r.reasons.join(", "));return this.options.eventBus?.emit({type:"rolled_back",timestamp:i.triggeredAt,payload:{stage:t,reasons:r.reasons}}),{status:"rolled_back",failedStage:t,reasons:r.reasons}}}if(this.options.strategy.mode==="blue-green")this.options.eventBus?.emit({type:"blue_green_swapped",timestamp:new Date,payload:{strategy:this.options.strategy}});return this.options.eventBus?.emit({type:"completed",timestamp:new Date,payload:{strategy:this.options.strategy}}),{status:"completed"}}}class y{listeners=new Set;on(e){return this.listeners.add(e),()=>this.listeners.delete(e)}emit(e){for(let t of this.listeners)try{t(e)}catch(a){console.error("[progressive-delivery] listener error",a)}}}var o={LIFECYCLE_DETECTION_ALPHA:"lifecycle_detection_alpha",LIFECYCLE_ADVISOR_ALPHA:"lifecycle_advisor_alpha",LIFECYCLE_MANAGED_SERVICE:"lifecycle_managed_service",STUDIO_VISUAL_BUILDER:"studio_visual_builder",STUDIO_AUTO_EVOLUTION:"studio_auto_evolution",STUDIO_BYOK:"studio_byok",STUDIO_DEDICATED_DEPLOYMENT:"studio_dedicated_deployment",STUDIO_INTEGRATION_HUB:"studio_integration_hub",STUDIO_KNOWLEDGE_HUB:"studio_knowledge_hub",STUDIO_TEMPLATES:"studio_templates"},h=[o.LIFECYCLE_DETECTION_ALPHA,o.LIFECYCLE_ADVISOR_ALPHA,o.LIFECYCLE_MANAGED_SERVICE],_=[o.STUDIO_VISUAL_BUILDER,o.STUDIO_AUTO_EVOLUTION,o.STUDIO_BYOK,o.STUDIO_DEDICATED_DEPLOYMENT,o.STUDIO_INTEGRATION_HUB,o.STUDIO_KNOWLEDGE_HUB,o.STUDIO_TEMPLATES];class c{options;constructor(e){this.options=e}async execute(e,t){await this.options.rollback(e,t);let a={reason:t,stage:e,triggeredAt:new Date};return this.options.onRollback?.(a),a}}class u{mode;constructor(e){this.mode=e}computeSplit(e){if(this.mode==="blue-green")return e.percentage>=100?{stable:0,candidate:1}:{stable:1,candidate:0};let t=Math.min(Math.max(e.percentage/100,0),1);return{candidate:t,stable:1-t}}}export{_ as studioFlags,h as lifecycleFlags,g as createDefaultCanaryController,u as TrafficShifter,c as RollbackManager,y as DeploymentEventBus,p as DeploymentCoordinator,o as ContractSpecFeatureFlags,s as CanaryController,n as CanaryAnalyzer};
|
package/dist/index.js
CHANGED
|
@@ -1,209 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
|
|
3
|
-
class CanaryAnalyzer {
|
|
4
|
-
defaults;
|
|
5
|
-
constructor(defaults) {
|
|
6
|
-
this.defaults = defaults;
|
|
7
|
-
}
|
|
8
|
-
evaluate(stage, metrics) {
|
|
9
|
-
const thresholds = { ...this.defaults, ...stage.thresholds };
|
|
10
|
-
const reasons = [];
|
|
11
|
-
if (metrics.errorRate > thresholds.errorRate) {
|
|
12
|
-
reasons.push(`errorRate ${metrics.errorRate.toFixed(4)} > ${thresholds.errorRate}`);
|
|
13
|
-
}
|
|
14
|
-
if (typeof thresholds.latencyP50 === "number" && metrics.latencyP50 > thresholds.latencyP50) {
|
|
15
|
-
reasons.push(`latencyP50 ${metrics.latencyP50}ms > ${thresholds.latencyP50}ms`);
|
|
16
|
-
}
|
|
17
|
-
if (typeof thresholds.latencyP95 === "number" && metrics.latencyP95 > thresholds.latencyP95) {
|
|
18
|
-
reasons.push(`latencyP95 ${metrics.latencyP95}ms > ${thresholds.latencyP95}ms`);
|
|
19
|
-
}
|
|
20
|
-
if (typeof thresholds.latencyP99 === "number" && metrics.latencyP99 > thresholds.latencyP99) {
|
|
21
|
-
reasons.push(`latencyP99 ${metrics.latencyP99}ms > ${thresholds.latencyP99}ms`);
|
|
22
|
-
}
|
|
23
|
-
if (typeof thresholds.throughputDrop === "number" && metrics.throughput < thresholds.throughputDrop) {
|
|
24
|
-
reasons.push(`throughput ${metrics.throughput} < ${thresholds.throughputDrop}`);
|
|
25
|
-
}
|
|
26
|
-
if (thresholds.customEvaluator && !thresholds.customEvaluator(metrics)) {
|
|
27
|
-
reasons.push("custom evaluator reported failure");
|
|
28
|
-
}
|
|
29
|
-
return {
|
|
30
|
-
status: reasons.length === 0 ? "pass" : "fail",
|
|
31
|
-
reasons,
|
|
32
|
-
metrics
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
// src/canary-controller.ts
|
|
37
|
-
var DEFAULT_STAGES = [
|
|
38
|
-
{ percentage: 1, minDurationMs: 5 * 60 * 1000, label: "1%" },
|
|
39
|
-
{ percentage: 10, minDurationMs: 5 * 60 * 1000, label: "10%" },
|
|
40
|
-
{ percentage: 50, minDurationMs: 10 * 60 * 1000, label: "50%" },
|
|
41
|
-
{ percentage: 100, minDurationMs: 15 * 60 * 1000, label: "100%" }
|
|
42
|
-
];
|
|
43
|
-
|
|
44
|
-
class CanaryController {
|
|
45
|
-
options;
|
|
46
|
-
stages;
|
|
47
|
-
constructor(options) {
|
|
48
|
-
this.options = options;
|
|
49
|
-
this.stages = options.strategy.stages && options.strategy.stages.length > 0 ? options.strategy.stages : DEFAULT_STAGES;
|
|
50
|
-
}
|
|
51
|
-
getStageList() {
|
|
52
|
-
return [...this.stages];
|
|
53
|
-
}
|
|
54
|
-
async runStage(stage) {
|
|
55
|
-
this.options.eventBus?.emit({
|
|
56
|
-
type: "stage_started",
|
|
57
|
-
timestamp: new Date,
|
|
58
|
-
payload: { stage }
|
|
59
|
-
});
|
|
60
|
-
const metrics = await this.options.metricsProvider(stage, stage.minDurationMs);
|
|
61
|
-
const analysis = this.options.analyzer.evaluate(stage, metrics);
|
|
62
|
-
this.options.eventBus?.emit({
|
|
63
|
-
type: analysis.status === "pass" ? "stage_passed" : "stage_failed",
|
|
64
|
-
timestamp: new Date,
|
|
65
|
-
payload: { stage, metrics, analysis }
|
|
66
|
-
});
|
|
67
|
-
return analysis;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
|
|
71
|
-
const analyzer = new CanaryAnalyzer(strategy.thresholds);
|
|
72
|
-
return new CanaryController({
|
|
73
|
-
strategy,
|
|
74
|
-
analyzer,
|
|
75
|
-
metricsProvider,
|
|
76
|
-
eventBus
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
// src/deployment-coordinator.ts
|
|
80
|
-
class DeploymentCoordinator {
|
|
81
|
-
options;
|
|
82
|
-
constructor(options) {
|
|
83
|
-
this.options = options;
|
|
84
|
-
}
|
|
85
|
-
async run() {
|
|
86
|
-
const stages = this.options.controller.getStageList();
|
|
87
|
-
for (const stage of stages) {
|
|
88
|
-
const split = this.options.trafficShifter.computeSplit(stage);
|
|
89
|
-
await this.options.applyTrafficSplit(stage, split);
|
|
90
|
-
const analysis = await this.options.controller.runStage(stage);
|
|
91
|
-
if (analysis.status === "fail") {
|
|
92
|
-
const action = await this.options.rollbackManager.execute(stage, analysis.reasons.join(", "));
|
|
93
|
-
this.options.eventBus?.emit({
|
|
94
|
-
type: "rolled_back",
|
|
95
|
-
timestamp: action.triggeredAt,
|
|
96
|
-
payload: { stage, reasons: analysis.reasons }
|
|
97
|
-
});
|
|
98
|
-
return {
|
|
99
|
-
status: "rolled_back",
|
|
100
|
-
failedStage: stage,
|
|
101
|
-
reasons: analysis.reasons
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
if (this.options.strategy.mode === "blue-green") {
|
|
106
|
-
this.options.eventBus?.emit({
|
|
107
|
-
type: "blue_green_swapped",
|
|
108
|
-
timestamp: new Date,
|
|
109
|
-
payload: { strategy: this.options.strategy }
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
this.options.eventBus?.emit({
|
|
113
|
-
type: "completed",
|
|
114
|
-
timestamp: new Date,
|
|
115
|
-
payload: { strategy: this.options.strategy }
|
|
116
|
-
});
|
|
117
|
-
return { status: "completed" };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
// src/events.ts
|
|
121
|
-
class DeploymentEventBus {
|
|
122
|
-
listeners = new Set;
|
|
123
|
-
on(listener) {
|
|
124
|
-
this.listeners.add(listener);
|
|
125
|
-
return () => this.listeners.delete(listener);
|
|
126
|
-
}
|
|
127
|
-
emit(event) {
|
|
128
|
-
for (const listener of this.listeners) {
|
|
129
|
-
try {
|
|
130
|
-
listener(event);
|
|
131
|
-
} catch (error) {
|
|
132
|
-
console.error("[progressive-delivery] listener error", error);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
// src/feature-flags.ts
|
|
138
|
-
var ContractSpecFeatureFlags = {
|
|
139
|
-
LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
|
|
140
|
-
LIFECYCLE_ADVISOR_ALPHA: "lifecycle_advisor_alpha",
|
|
141
|
-
LIFECYCLE_MANAGED_SERVICE: "lifecycle_managed_service",
|
|
142
|
-
STUDIO_VISUAL_BUILDER: "studio_visual_builder",
|
|
143
|
-
STUDIO_AUTO_EVOLUTION: "studio_auto_evolution",
|
|
144
|
-
STUDIO_BYOK: "studio_byok",
|
|
145
|
-
STUDIO_DEDICATED_DEPLOYMENT: "studio_dedicated_deployment",
|
|
146
|
-
STUDIO_INTEGRATION_HUB: "studio_integration_hub",
|
|
147
|
-
STUDIO_KNOWLEDGE_HUB: "studio_knowledge_hub",
|
|
148
|
-
STUDIO_TEMPLATES: "studio_templates"
|
|
149
|
-
};
|
|
150
|
-
var lifecycleFlags = [
|
|
151
|
-
ContractSpecFeatureFlags.LIFECYCLE_DETECTION_ALPHA,
|
|
152
|
-
ContractSpecFeatureFlags.LIFECYCLE_ADVISOR_ALPHA,
|
|
153
|
-
ContractSpecFeatureFlags.LIFECYCLE_MANAGED_SERVICE
|
|
154
|
-
];
|
|
155
|
-
var studioFlags = [
|
|
156
|
-
ContractSpecFeatureFlags.STUDIO_VISUAL_BUILDER,
|
|
157
|
-
ContractSpecFeatureFlags.STUDIO_AUTO_EVOLUTION,
|
|
158
|
-
ContractSpecFeatureFlags.STUDIO_BYOK,
|
|
159
|
-
ContractSpecFeatureFlags.STUDIO_DEDICATED_DEPLOYMENT,
|
|
160
|
-
ContractSpecFeatureFlags.STUDIO_INTEGRATION_HUB,
|
|
161
|
-
ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
|
|
162
|
-
ContractSpecFeatureFlags.STUDIO_TEMPLATES
|
|
163
|
-
];
|
|
164
|
-
// src/rollback-manager.ts
|
|
165
|
-
class RollbackManager {
|
|
166
|
-
options;
|
|
167
|
-
constructor(options) {
|
|
168
|
-
this.options = options;
|
|
169
|
-
}
|
|
170
|
-
async execute(stage, reason) {
|
|
171
|
-
await this.options.rollback(stage, reason);
|
|
172
|
-
const action = {
|
|
173
|
-
reason,
|
|
174
|
-
stage,
|
|
175
|
-
triggeredAt: new Date
|
|
176
|
-
};
|
|
177
|
-
this.options.onRollback?.(action);
|
|
178
|
-
return action;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// src/traffic-shifter.ts
|
|
182
|
-
class TrafficShifter {
|
|
183
|
-
mode;
|
|
184
|
-
constructor(mode) {
|
|
185
|
-
this.mode = mode;
|
|
186
|
-
}
|
|
187
|
-
computeSplit(stage) {
|
|
188
|
-
if (this.mode === "blue-green") {
|
|
189
|
-
return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
|
|
190
|
-
}
|
|
191
|
-
const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
|
|
192
|
-
return {
|
|
193
|
-
candidate,
|
|
194
|
-
stable: 1 - candidate
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
export {
|
|
199
|
-
studioFlags,
|
|
200
|
-
lifecycleFlags,
|
|
201
|
-
createDefaultCanaryController,
|
|
202
|
-
TrafficShifter,
|
|
203
|
-
RollbackManager,
|
|
204
|
-
DeploymentEventBus,
|
|
205
|
-
DeploymentCoordinator,
|
|
206
|
-
ContractSpecFeatureFlags,
|
|
207
|
-
CanaryController,
|
|
208
|
-
CanaryAnalyzer
|
|
209
|
-
};
|
|
2
|
+
class n{defaults;constructor(e){this.defaults=e}evaluate(e,t){let a={...this.defaults,...e.thresholds},r=[];if(t.errorRate>a.errorRate)r.push(`errorRate ${t.errorRate.toFixed(4)} > ${a.errorRate}`);if(typeof a.latencyP50==="number"&&t.latencyP50>a.latencyP50)r.push(`latencyP50 ${t.latencyP50}ms > ${a.latencyP50}ms`);if(typeof a.latencyP95==="number"&&t.latencyP95>a.latencyP95)r.push(`latencyP95 ${t.latencyP95}ms > ${a.latencyP95}ms`);if(typeof a.latencyP99==="number"&&t.latencyP99>a.latencyP99)r.push(`latencyP99 ${t.latencyP99}ms > ${a.latencyP99}ms`);if(typeof a.throughputDrop==="number"&&t.throughput<a.throughputDrop)r.push(`throughput ${t.throughput} < ${a.throughputDrop}`);if(a.customEvaluator&&!a.customEvaluator(t))r.push("custom evaluator reported failure");return{status:r.length===0?"pass":"fail",reasons:r,metrics:t}}}var l=[{percentage:1,minDurationMs:300000,label:"1%"},{percentage:10,minDurationMs:300000,label:"10%"},{percentage:50,minDurationMs:600000,label:"50%"},{percentage:100,minDurationMs:900000,label:"100%"}];class s{options;stages;constructor(e){this.options=e;this.stages=e.strategy.stages&&e.strategy.stages.length>0?e.strategy.stages:l}getStageList(){return[...this.stages]}async runStage(e){this.options.eventBus?.emit({type:"stage_started",timestamp:new Date,payload:{stage:e}});let t=await this.options.metricsProvider(e,e.minDurationMs),a=this.options.analyzer.evaluate(e,t);return this.options.eventBus?.emit({type:a.status==="pass"?"stage_passed":"stage_failed",timestamp:new Date,payload:{stage:e,metrics:t,analysis:a}}),a}}function g(e,t,a){let r=new n(e.thresholds);return new s({strategy:e,analyzer:r,metricsProvider:t,eventBus:a})}class p{options;constructor(e){this.options=e}async run(){let e=this.options.controller.getStageList();for(let t of e){let a=this.options.trafficShifter.computeSplit(t);await this.options.applyTrafficSplit(t,a);let r=await this.options.controller.runStage(t);if(r.status==="fail"){let i=await this.options.rollbackManager.execute(t,r.reasons.join(", "));return this.options.eventBus?.emit({type:"rolled_back",timestamp:i.triggeredAt,payload:{stage:t,reasons:r.reasons}}),{status:"rolled_back",failedStage:t,reasons:r.reasons}}}if(this.options.strategy.mode==="blue-green")this.options.eventBus?.emit({type:"blue_green_swapped",timestamp:new Date,payload:{strategy:this.options.strategy}});return this.options.eventBus?.emit({type:"completed",timestamp:new Date,payload:{strategy:this.options.strategy}}),{status:"completed"}}}class y{listeners=new Set;on(e){return this.listeners.add(e),()=>this.listeners.delete(e)}emit(e){for(let t of this.listeners)try{t(e)}catch(a){console.error("[progressive-delivery] listener error",a)}}}var o={LIFECYCLE_DETECTION_ALPHA:"lifecycle_detection_alpha",LIFECYCLE_ADVISOR_ALPHA:"lifecycle_advisor_alpha",LIFECYCLE_MANAGED_SERVICE:"lifecycle_managed_service",STUDIO_VISUAL_BUILDER:"studio_visual_builder",STUDIO_AUTO_EVOLUTION:"studio_auto_evolution",STUDIO_BYOK:"studio_byok",STUDIO_DEDICATED_DEPLOYMENT:"studio_dedicated_deployment",STUDIO_INTEGRATION_HUB:"studio_integration_hub",STUDIO_KNOWLEDGE_HUB:"studio_knowledge_hub",STUDIO_TEMPLATES:"studio_templates"},h=[o.LIFECYCLE_DETECTION_ALPHA,o.LIFECYCLE_ADVISOR_ALPHA,o.LIFECYCLE_MANAGED_SERVICE],_=[o.STUDIO_VISUAL_BUILDER,o.STUDIO_AUTO_EVOLUTION,o.STUDIO_BYOK,o.STUDIO_DEDICATED_DEPLOYMENT,o.STUDIO_INTEGRATION_HUB,o.STUDIO_KNOWLEDGE_HUB,o.STUDIO_TEMPLATES];class c{options;constructor(e){this.options=e}async execute(e,t){await this.options.rollback(e,t);let a={reason:t,stage:e,triggeredAt:new Date};return this.options.onRollback?.(a),a}}class u{mode;constructor(e){this.mode=e}computeSplit(e){if(this.mode==="blue-green")return e.percentage>=100?{stable:0,candidate:1}:{stable:1,candidate:0};let t=Math.min(Math.max(e.percentage/100,0),1);return{candidate:t,stable:1-t}}}export{_ as studioFlags,h as lifecycleFlags,g as createDefaultCanaryController,u as TrafficShifter,c as RollbackManager,y as DeploymentEventBus,p as DeploymentCoordinator,o as ContractSpecFeatureFlags,s as CanaryController,n as CanaryAnalyzer};
|
package/dist/node/index.js
CHANGED
|
@@ -1,208 +1 @@
|
|
|
1
|
-
|
|
2
|
-
class CanaryAnalyzer {
|
|
3
|
-
defaults;
|
|
4
|
-
constructor(defaults) {
|
|
5
|
-
this.defaults = defaults;
|
|
6
|
-
}
|
|
7
|
-
evaluate(stage, metrics) {
|
|
8
|
-
const thresholds = { ...this.defaults, ...stage.thresholds };
|
|
9
|
-
const reasons = [];
|
|
10
|
-
if (metrics.errorRate > thresholds.errorRate) {
|
|
11
|
-
reasons.push(`errorRate ${metrics.errorRate.toFixed(4)} > ${thresholds.errorRate}`);
|
|
12
|
-
}
|
|
13
|
-
if (typeof thresholds.latencyP50 === "number" && metrics.latencyP50 > thresholds.latencyP50) {
|
|
14
|
-
reasons.push(`latencyP50 ${metrics.latencyP50}ms > ${thresholds.latencyP50}ms`);
|
|
15
|
-
}
|
|
16
|
-
if (typeof thresholds.latencyP95 === "number" && metrics.latencyP95 > thresholds.latencyP95) {
|
|
17
|
-
reasons.push(`latencyP95 ${metrics.latencyP95}ms > ${thresholds.latencyP95}ms`);
|
|
18
|
-
}
|
|
19
|
-
if (typeof thresholds.latencyP99 === "number" && metrics.latencyP99 > thresholds.latencyP99) {
|
|
20
|
-
reasons.push(`latencyP99 ${metrics.latencyP99}ms > ${thresholds.latencyP99}ms`);
|
|
21
|
-
}
|
|
22
|
-
if (typeof thresholds.throughputDrop === "number" && metrics.throughput < thresholds.throughputDrop) {
|
|
23
|
-
reasons.push(`throughput ${metrics.throughput} < ${thresholds.throughputDrop}`);
|
|
24
|
-
}
|
|
25
|
-
if (thresholds.customEvaluator && !thresholds.customEvaluator(metrics)) {
|
|
26
|
-
reasons.push("custom evaluator reported failure");
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
status: reasons.length === 0 ? "pass" : "fail",
|
|
30
|
-
reasons,
|
|
31
|
-
metrics
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// src/canary-controller.ts
|
|
36
|
-
var DEFAULT_STAGES = [
|
|
37
|
-
{ percentage: 1, minDurationMs: 5 * 60 * 1000, label: "1%" },
|
|
38
|
-
{ percentage: 10, minDurationMs: 5 * 60 * 1000, label: "10%" },
|
|
39
|
-
{ percentage: 50, minDurationMs: 10 * 60 * 1000, label: "50%" },
|
|
40
|
-
{ percentage: 100, minDurationMs: 15 * 60 * 1000, label: "100%" }
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
class CanaryController {
|
|
44
|
-
options;
|
|
45
|
-
stages;
|
|
46
|
-
constructor(options) {
|
|
47
|
-
this.options = options;
|
|
48
|
-
this.stages = options.strategy.stages && options.strategy.stages.length > 0 ? options.strategy.stages : DEFAULT_STAGES;
|
|
49
|
-
}
|
|
50
|
-
getStageList() {
|
|
51
|
-
return [...this.stages];
|
|
52
|
-
}
|
|
53
|
-
async runStage(stage) {
|
|
54
|
-
this.options.eventBus?.emit({
|
|
55
|
-
type: "stage_started",
|
|
56
|
-
timestamp: new Date,
|
|
57
|
-
payload: { stage }
|
|
58
|
-
});
|
|
59
|
-
const metrics = await this.options.metricsProvider(stage, stage.minDurationMs);
|
|
60
|
-
const analysis = this.options.analyzer.evaluate(stage, metrics);
|
|
61
|
-
this.options.eventBus?.emit({
|
|
62
|
-
type: analysis.status === "pass" ? "stage_passed" : "stage_failed",
|
|
63
|
-
timestamp: new Date,
|
|
64
|
-
payload: { stage, metrics, analysis }
|
|
65
|
-
});
|
|
66
|
-
return analysis;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
function createDefaultCanaryController(strategy, metricsProvider, eventBus) {
|
|
70
|
-
const analyzer = new CanaryAnalyzer(strategy.thresholds);
|
|
71
|
-
return new CanaryController({
|
|
72
|
-
strategy,
|
|
73
|
-
analyzer,
|
|
74
|
-
metricsProvider,
|
|
75
|
-
eventBus
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
// src/deployment-coordinator.ts
|
|
79
|
-
class DeploymentCoordinator {
|
|
80
|
-
options;
|
|
81
|
-
constructor(options) {
|
|
82
|
-
this.options = options;
|
|
83
|
-
}
|
|
84
|
-
async run() {
|
|
85
|
-
const stages = this.options.controller.getStageList();
|
|
86
|
-
for (const stage of stages) {
|
|
87
|
-
const split = this.options.trafficShifter.computeSplit(stage);
|
|
88
|
-
await this.options.applyTrafficSplit(stage, split);
|
|
89
|
-
const analysis = await this.options.controller.runStage(stage);
|
|
90
|
-
if (analysis.status === "fail") {
|
|
91
|
-
const action = await this.options.rollbackManager.execute(stage, analysis.reasons.join(", "));
|
|
92
|
-
this.options.eventBus?.emit({
|
|
93
|
-
type: "rolled_back",
|
|
94
|
-
timestamp: action.triggeredAt,
|
|
95
|
-
payload: { stage, reasons: analysis.reasons }
|
|
96
|
-
});
|
|
97
|
-
return {
|
|
98
|
-
status: "rolled_back",
|
|
99
|
-
failedStage: stage,
|
|
100
|
-
reasons: analysis.reasons
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (this.options.strategy.mode === "blue-green") {
|
|
105
|
-
this.options.eventBus?.emit({
|
|
106
|
-
type: "blue_green_swapped",
|
|
107
|
-
timestamp: new Date,
|
|
108
|
-
payload: { strategy: this.options.strategy }
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
this.options.eventBus?.emit({
|
|
112
|
-
type: "completed",
|
|
113
|
-
timestamp: new Date,
|
|
114
|
-
payload: { strategy: this.options.strategy }
|
|
115
|
-
});
|
|
116
|
-
return { status: "completed" };
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
// src/events.ts
|
|
120
|
-
class DeploymentEventBus {
|
|
121
|
-
listeners = new Set;
|
|
122
|
-
on(listener) {
|
|
123
|
-
this.listeners.add(listener);
|
|
124
|
-
return () => this.listeners.delete(listener);
|
|
125
|
-
}
|
|
126
|
-
emit(event) {
|
|
127
|
-
for (const listener of this.listeners) {
|
|
128
|
-
try {
|
|
129
|
-
listener(event);
|
|
130
|
-
} catch (error) {
|
|
131
|
-
console.error("[progressive-delivery] listener error", error);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
// src/feature-flags.ts
|
|
137
|
-
var ContractSpecFeatureFlags = {
|
|
138
|
-
LIFECYCLE_DETECTION_ALPHA: "lifecycle_detection_alpha",
|
|
139
|
-
LIFECYCLE_ADVISOR_ALPHA: "lifecycle_advisor_alpha",
|
|
140
|
-
LIFECYCLE_MANAGED_SERVICE: "lifecycle_managed_service",
|
|
141
|
-
STUDIO_VISUAL_BUILDER: "studio_visual_builder",
|
|
142
|
-
STUDIO_AUTO_EVOLUTION: "studio_auto_evolution",
|
|
143
|
-
STUDIO_BYOK: "studio_byok",
|
|
144
|
-
STUDIO_DEDICATED_DEPLOYMENT: "studio_dedicated_deployment",
|
|
145
|
-
STUDIO_INTEGRATION_HUB: "studio_integration_hub",
|
|
146
|
-
STUDIO_KNOWLEDGE_HUB: "studio_knowledge_hub",
|
|
147
|
-
STUDIO_TEMPLATES: "studio_templates"
|
|
148
|
-
};
|
|
149
|
-
var lifecycleFlags = [
|
|
150
|
-
ContractSpecFeatureFlags.LIFECYCLE_DETECTION_ALPHA,
|
|
151
|
-
ContractSpecFeatureFlags.LIFECYCLE_ADVISOR_ALPHA,
|
|
152
|
-
ContractSpecFeatureFlags.LIFECYCLE_MANAGED_SERVICE
|
|
153
|
-
];
|
|
154
|
-
var studioFlags = [
|
|
155
|
-
ContractSpecFeatureFlags.STUDIO_VISUAL_BUILDER,
|
|
156
|
-
ContractSpecFeatureFlags.STUDIO_AUTO_EVOLUTION,
|
|
157
|
-
ContractSpecFeatureFlags.STUDIO_BYOK,
|
|
158
|
-
ContractSpecFeatureFlags.STUDIO_DEDICATED_DEPLOYMENT,
|
|
159
|
-
ContractSpecFeatureFlags.STUDIO_INTEGRATION_HUB,
|
|
160
|
-
ContractSpecFeatureFlags.STUDIO_KNOWLEDGE_HUB,
|
|
161
|
-
ContractSpecFeatureFlags.STUDIO_TEMPLATES
|
|
162
|
-
];
|
|
163
|
-
// src/rollback-manager.ts
|
|
164
|
-
class RollbackManager {
|
|
165
|
-
options;
|
|
166
|
-
constructor(options) {
|
|
167
|
-
this.options = options;
|
|
168
|
-
}
|
|
169
|
-
async execute(stage, reason) {
|
|
170
|
-
await this.options.rollback(stage, reason);
|
|
171
|
-
const action = {
|
|
172
|
-
reason,
|
|
173
|
-
stage,
|
|
174
|
-
triggeredAt: new Date
|
|
175
|
-
};
|
|
176
|
-
this.options.onRollback?.(action);
|
|
177
|
-
return action;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
// src/traffic-shifter.ts
|
|
181
|
-
class TrafficShifter {
|
|
182
|
-
mode;
|
|
183
|
-
constructor(mode) {
|
|
184
|
-
this.mode = mode;
|
|
185
|
-
}
|
|
186
|
-
computeSplit(stage) {
|
|
187
|
-
if (this.mode === "blue-green") {
|
|
188
|
-
return stage.percentage >= 100 ? { stable: 0, candidate: 1 } : { stable: 1, candidate: 0 };
|
|
189
|
-
}
|
|
190
|
-
const candidate = Math.min(Math.max(stage.percentage / 100, 0), 1);
|
|
191
|
-
return {
|
|
192
|
-
candidate,
|
|
193
|
-
stable: 1 - candidate
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
export {
|
|
198
|
-
studioFlags,
|
|
199
|
-
lifecycleFlags,
|
|
200
|
-
createDefaultCanaryController,
|
|
201
|
-
TrafficShifter,
|
|
202
|
-
RollbackManager,
|
|
203
|
-
DeploymentEventBus,
|
|
204
|
-
DeploymentCoordinator,
|
|
205
|
-
ContractSpecFeatureFlags,
|
|
206
|
-
CanaryController,
|
|
207
|
-
CanaryAnalyzer
|
|
208
|
-
};
|
|
1
|
+
class n{defaults;constructor(e){this.defaults=e}evaluate(e,t){let a={...this.defaults,...e.thresholds},r=[];if(t.errorRate>a.errorRate)r.push(`errorRate ${t.errorRate.toFixed(4)} > ${a.errorRate}`);if(typeof a.latencyP50==="number"&&t.latencyP50>a.latencyP50)r.push(`latencyP50 ${t.latencyP50}ms > ${a.latencyP50}ms`);if(typeof a.latencyP95==="number"&&t.latencyP95>a.latencyP95)r.push(`latencyP95 ${t.latencyP95}ms > ${a.latencyP95}ms`);if(typeof a.latencyP99==="number"&&t.latencyP99>a.latencyP99)r.push(`latencyP99 ${t.latencyP99}ms > ${a.latencyP99}ms`);if(typeof a.throughputDrop==="number"&&t.throughput<a.throughputDrop)r.push(`throughput ${t.throughput} < ${a.throughputDrop}`);if(a.customEvaluator&&!a.customEvaluator(t))r.push("custom evaluator reported failure");return{status:r.length===0?"pass":"fail",reasons:r,metrics:t}}}var l=[{percentage:1,minDurationMs:300000,label:"1%"},{percentage:10,minDurationMs:300000,label:"10%"},{percentage:50,minDurationMs:600000,label:"50%"},{percentage:100,minDurationMs:900000,label:"100%"}];class s{options;stages;constructor(e){this.options=e;this.stages=e.strategy.stages&&e.strategy.stages.length>0?e.strategy.stages:l}getStageList(){return[...this.stages]}async runStage(e){this.options.eventBus?.emit({type:"stage_started",timestamp:new Date,payload:{stage:e}});let t=await this.options.metricsProvider(e,e.minDurationMs),a=this.options.analyzer.evaluate(e,t);return this.options.eventBus?.emit({type:a.status==="pass"?"stage_passed":"stage_failed",timestamp:new Date,payload:{stage:e,metrics:t,analysis:a}}),a}}function g(e,t,a){let r=new n(e.thresholds);return new s({strategy:e,analyzer:r,metricsProvider:t,eventBus:a})}class p{options;constructor(e){this.options=e}async run(){let e=this.options.controller.getStageList();for(let t of e){let a=this.options.trafficShifter.computeSplit(t);await this.options.applyTrafficSplit(t,a);let r=await this.options.controller.runStage(t);if(r.status==="fail"){let i=await this.options.rollbackManager.execute(t,r.reasons.join(", "));return this.options.eventBus?.emit({type:"rolled_back",timestamp:i.triggeredAt,payload:{stage:t,reasons:r.reasons}}),{status:"rolled_back",failedStage:t,reasons:r.reasons}}}if(this.options.strategy.mode==="blue-green")this.options.eventBus?.emit({type:"blue_green_swapped",timestamp:new Date,payload:{strategy:this.options.strategy}});return this.options.eventBus?.emit({type:"completed",timestamp:new Date,payload:{strategy:this.options.strategy}}),{status:"completed"}}}class y{listeners=new Set;on(e){return this.listeners.add(e),()=>this.listeners.delete(e)}emit(e){for(let t of this.listeners)try{t(e)}catch(a){console.error("[progressive-delivery] listener error",a)}}}var o={LIFECYCLE_DETECTION_ALPHA:"lifecycle_detection_alpha",LIFECYCLE_ADVISOR_ALPHA:"lifecycle_advisor_alpha",LIFECYCLE_MANAGED_SERVICE:"lifecycle_managed_service",STUDIO_VISUAL_BUILDER:"studio_visual_builder",STUDIO_AUTO_EVOLUTION:"studio_auto_evolution",STUDIO_BYOK:"studio_byok",STUDIO_DEDICATED_DEPLOYMENT:"studio_dedicated_deployment",STUDIO_INTEGRATION_HUB:"studio_integration_hub",STUDIO_KNOWLEDGE_HUB:"studio_knowledge_hub",STUDIO_TEMPLATES:"studio_templates"},h=[o.LIFECYCLE_DETECTION_ALPHA,o.LIFECYCLE_ADVISOR_ALPHA,o.LIFECYCLE_MANAGED_SERVICE],_=[o.STUDIO_VISUAL_BUILDER,o.STUDIO_AUTO_EVOLUTION,o.STUDIO_BYOK,o.STUDIO_DEDICATED_DEPLOYMENT,o.STUDIO_INTEGRATION_HUB,o.STUDIO_KNOWLEDGE_HUB,o.STUDIO_TEMPLATES];class c{options;constructor(e){this.options=e}async execute(e,t){await this.options.rollback(e,t);let a={reason:t,stage:e,triggeredAt:new Date};return this.options.onRollback?.(a),a}}class u{mode;constructor(e){this.mode=e}computeSplit(e){if(this.mode==="blue-green")return e.percentage>=100?{stable:0,candidate:1}:{stable:1,candidate:0};let t=Math.min(Math.max(e.percentage/100,0),1);return{candidate:t,stable:1-t}}}export{_ as studioFlags,h as lifecycleFlags,g as createDefaultCanaryController,u as TrafficShifter,c as RollbackManager,y as DeploymentEventBus,p as DeploymentCoordinator,o as ContractSpecFeatureFlags,s as CanaryController,n as CanaryAnalyzer};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contractspec/lib.progressive-delivery",
|
|
3
|
-
"version": "34.0.
|
|
3
|
+
"version": "34.0.17",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"dev": "contractspec-bun-build dev",
|
|
17
17
|
"clean": "rimraf dist .turbo",
|
|
18
18
|
"lint": "bun lint:fix",
|
|
19
|
-
"lint:fix": "biome check --write --unsafe --only=nursery/useSortedClasses . && biome check --write .",
|
|
20
|
-
"lint:check": "biome check .",
|
|
19
|
+
"lint:fix": "node ../../../scripts/biome.cjs check --write --unsafe --only=nursery/useSortedClasses . && node ../../../scripts/biome.cjs check --write .",
|
|
20
|
+
"lint:check": "node ../../../scripts/biome.cjs check .",
|
|
21
21
|
"prebuild": "contractspec-bun-build prebuild",
|
|
22
22
|
"typecheck": "tsc --noEmit"
|
|
23
23
|
},
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"directory": "packages/libs/progressive-delivery"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@contractspec/lib.observability": "3.7.
|
|
30
|
+
"@contractspec/lib.observability": "3.7.18"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@contractspec/tool.typescript": "3.7.
|
|
33
|
+
"@contractspec/tool.typescript": "3.7.13",
|
|
34
34
|
"typescript": "^5.9.3",
|
|
35
|
-
"@contractspec/tool.bun": "3.7.
|
|
35
|
+
"@contractspec/tool.bun": "3.7.14"
|
|
36
36
|
},
|
|
37
37
|
"exports": {
|
|
38
38
|
".": {
|