pi-cicd 1.0.4 → 1.0.6

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.
@@ -0,0 +1,27 @@
1
+ # US-001: Intelligent Deploy Tool
2
+
3
+ ## User Story
4
+ As an agent, I want to monitor CI/CD pipelines, manage canary deployments, and track landing queues so that I can safely deploy changes to production.
5
+
6
+ ## Status
7
+ - [x] Implemented
8
+
9
+ ## Commands
10
+ - `/ci` - CI status command
11
+
12
+ ## Features
13
+ - CI run tracking
14
+ - Canary deployment support
15
+ - Landing queue management
16
+ - Exit code resolution
17
+
18
+ ## Triggers
19
+ - "deploy", "canary", "rollout", "landing queue", "production"
20
+
21
+ ## Acceptance Criteria
22
+ - [x] CI status command shows run information
23
+ - [x] Exit codes are properly resolved
24
+ - [x] Can track deployment progress
25
+
26
+ ## Notes
27
+ See `skills/intelligent-deploy/SKILL.md` for detailed usage.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cicd",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Extension for Pi coding agent",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -1,229 +1,133 @@
1
1
  ---
2
2
  name: intelligent-deploy
3
- description: Canary deployment with monitoring and landing queue management
3
+ description: CI/CD pipeline monitoring, canary deployment management, and landing queue orchestration
4
4
  triggers:
5
5
  - deploy
6
6
  - canary
7
7
  - rollout
8
8
  - landing queue
9
9
  - production
10
+ - CI status
11
+ - pipeline
12
+ - release
13
+ - build
10
14
  requirements:
11
15
  tools: [bash]
12
- context: [deployment target]
16
+ context: [CI configuration, deployment scripts]
13
17
  ---
14
18
 
15
19
  # Intelligent Deploy Skill
16
20
 
17
21
  ## Objective
18
- Execute safe deployments with canary monitoring, automatic rollback, and landing queue management.
22
+ Monitor CI/CD pipelines, manage canary deployments, and track landing queues for safe production releases.
19
23
 
20
- ## When to Use
21
- - When user asks to "deploy" or "ship to production"
22
- - When running CI/CD pipelines
23
- - When managing multiple deployments
24
- - When requiring gradual rollouts with monitoring
25
-
26
- ## Workflow
27
-
28
- ### Step 1: Canary Deployment
29
- ```typescript
30
- import { CanaryDeploy } from '../../src/deploy/canary-deploy';
31
-
32
- const canary = new CanaryDeploy({
33
- initialPercentage: 10,
34
- incrementPercentage: 10,
35
- stepInterval: 60000, // 1 minute
36
- totalDuration: 300000, // 5 minutes
37
- metrics: {
38
- successRate: { min: 95 },
39
- latency: { max: 500 },
40
- errorRate: { max: 5 },
41
- },
42
- });
43
-
44
- const result = await canary.deploy({
45
- name: 'production',
46
- url: 'https://api.example.com',
47
- healthy: true,
48
- });
49
-
50
- console.log(canary.formatReport(result));
51
- ```
52
-
53
- ### Step 2: Landing Queue
54
- ```typescript
55
- import { LandingQueue } from '../../src/deploy/landing-queue';
24
+ ## Commands Available
25
+ - `/ci` - Show CI status
56
26
 
57
- const queue = new LandingQueue();
27
+ ## When to Use
28
+ - When deploying to production
29
+ - When monitoring CI/CD pipelines
30
+ - When managing canary releases
31
+ - When tracking landing queues
32
+ - When investigating build failures
58
33
 
59
- // Add to queue
60
- queue.enqueue('v1.2.0', 'production', 'New feature release');
61
- queue.enqueue('v1.2.1', 'production', 'Bug fix');
34
+ ## CI Status Command
62
35
 
63
- // Process queue
64
- while (true) {
65
- const next = await queue.startNext();
66
- if (!next) break;
67
-
68
- // Deploy
69
- const success = await deploy(next);
70
-
71
- // Mark complete
72
- queue.complete(next.id, success);
73
-
74
- if (!success) break; // Stop on failure
75
- }
36
+ ### Usage
76
37
  ```
77
-
78
- ### Step 3: Monitor and Rollback
79
- ```typescript
80
- // Automatic rollback on issues
81
- if (result.rolledBack) {
82
- console.log('Deployment rolled back due to issues');
83
- await canary.rollback(target);
84
- }
38
+ /ci [run-id]
85
39
  ```
86
40
 
87
- ## Canary Configuration
41
+ Shows:
42
+ - Current/last CI run status
43
+ - Exit codes
44
+ - Duration
45
+ - Events
88
46
 
89
- | Parameter | Default | Description |
90
- |-----------|---------|-------------|
91
- | initialPercentage | 10% | Starting traffic |
92
- | incrementPercentage | 10% | Traffic increase per step |
93
- | stepInterval | 1 min | Time between increments |
94
- | totalDuration | 5 min | Total deployment time |
47
+ ### Exit Codes
48
+ | Code | Meaning |
49
+ |------|---------|
50
+ | 0 | Success |
51
+ | 1 | General failure |
52
+ | 2 | Misuse/Invalid input |
53
+ | 3 | Configuration error |
54
+ | 124 | Timeout |
55
+ | 137 | SIGKILL (OOM) |
95
56
 
96
- ### Metrics Thresholds
57
+ ## Deployment Strategies
97
58
 
98
- | Metric | Threshold | Action |
99
- |--------|-----------|--------|
100
- | Success Rate | > 95% | Continue |
101
- | Latency | < 500ms | Continue |
102
- | Error Rate | < 5% | Continue |
59
+ ### Canary Deployment
60
+ 1. Deploy to small percentage
61
+ 2. Monitor metrics
62
+ 3. Gradually increase
63
+ 4. Full rollout or rollback
103
64
 
104
- If metrics drop below thresholds:
105
- - Warning at threshold
106
- - Auto-rollback at critical level (90% success, 10% errors)
65
+ ### Landing Queue
66
+ - Queue changes for controlled rollout
67
+ - Automatic promotion
68
+ - Manual gates for risky changes
107
69
 
108
- ## Landing Queue Commands
70
+ ## Pipeline Monitoring
109
71
 
110
- ### Enqueue Deployment
111
- ```typescript
112
- queue.enqueue('v1.2.0', 'production', 'Feature release');
72
+ ### Status Check
113
73
  ```
114
-
115
- ### Process Queue
116
- ```typescript
117
- while (const next = queue.startNext()) {
118
- await deploy(next);
119
- queue.complete(next.id, success);
120
- }
74
+ /ci
121
75
  ```
122
76
 
123
- ### View Status
124
- ```typescript
125
- console.log(queue.formatReport());
126
- ```
77
+ Returns:
78
+ - Run ID
79
+ - Start time
80
+ - Events (pass/fail)
81
+ - Exit code
82
+ - Duration
83
+
84
+ ### Historical Analysis
85
+ Track patterns in:
86
+ - Build times
87
+ - Failure rates
88
+ - Flaky tests
127
89
 
128
90
  ## Examples
129
91
 
130
- ### Deploy with Canary
92
+ ### Check CI Status
131
93
  ```
132
- User: Deploy v1.2.0 to production with canary
94
+ User: What's the CI status?
133
95
  Agent:
134
- const result = await canary.deploy({ name: 'production', url: '...', healthy: true });
135
- if (result.success) {
136
- console.log('Deployment successful!');
137
- } else {
138
- console.log('Rolled back - check issues');
139
- }
96
+ /ci
140
97
  ```
141
98
 
142
- ### Process Landing Queue
99
+ ### Check Specific Run
143
100
  ```
144
- User: Queue these deployments: v1.2.0, v1.2.1, v1.2.2
145
101
  Agent:
146
- queue.enqueue('v1.2.0', 'production');
147
- queue.enqueue('v1.2.1', 'production');
148
- queue.enqueue('v1.2.2', 'staging');
149
-
150
- const result = await queue.processAll();
102
+ /ci run-123
151
103
  ```
152
104
 
153
- ### View Queue Status
105
+ ### Analyze Failure
154
106
  ```
155
- User: Show me the current deployment queue
107
+ User: Why did the build fail?
156
108
  Agent:
157
- console.log(queue.formatReport());
109
+ /ci
110
+ # Analyze events and exit code
158
111
  ```
159
112
 
160
- ## Output Format
161
-
162
- ### Canary Report
163
- ```markdown
164
- ## Canary Deployment Report
165
- **Status:** ✅ SUCCESS
166
- **Final Traffic:** 100%
167
- **Rolled Back:** No
168
-
169
- ### Metrics History
170
- | Time | Success | Latency | Error Rate |
171
- |------|---------|---------|------------|
172
- | 0min | 98.5% | 120ms | 1.2% |
173
- | 1min | 99.1% | 115ms | 0.8% |
174
- | 2min | 99.3% | 110ms | 0.5% |
175
- ```
176
-
177
- ### Landing Queue Report
178
- ```markdown
179
- ## Landing Queue Report
180
- **Total:** 5 | **Pending:** 2 | **Deploying:** 1 | **Deployed:** 2 | **Failed:** 0
181
-
182
- ### Currently Deploying
183
- **v1.2.1** -> production
184
- Status: deploying
113
+ ## Configuration
185
114
 
186
- ### Queue
187
- | # | Version | Environment | Message |
188
- |---|--------|------------|---------|
189
- | 1 | v1.2.2 | production | Hotfix |
190
- | 2 | v1.2.3 | staging | New feature |
115
+ ### Pipeline Config
116
+ ```yaml
117
+ ci:
118
+ timeout: 300
119
+ retry: 2
120
+ parallel: true
121
+
122
+ deploy:
123
+ strategy: canary
124
+ canary:
125
+ initial: 5%
126
+ increment: 10%
127
+ pause: 5m
191
128
  ```
192
129
 
193
130
  ## Integration
194
-
195
- ### With pi-pipeline
196
- ```typescript
197
- // Run as part of ship workflow
198
- const gates = new QualityGates();
199
- const gatesResult = await gates.run('pre-push');
200
-
201
- if (gatesResult.passed) {
202
- const result = await canary.deploy(target);
203
- if (!result.success) {
204
- throw new Error('Deployment failed');
205
- }
206
- }
207
- ```
208
-
209
- ### With pi-audit
210
- ```typescript
211
- // Security scan before deploy
212
- const shield = new AgentShield();
213
- const scan = shield.scan(deploymentCode);
214
-
215
- if (!scan.passed) {
216
- console.log('Security issues must be fixed');
217
- process.exit(1);
218
- }
219
- ```
220
-
221
- ### With pi-recollect
222
- ```typescript
223
- // Remember deployment
224
- await memory.remember(
225
- 'deployment',
226
- `Deployed ${version} to ${environment}`,
227
- 'observation'
228
- );
229
- ```
131
+ - With pi-pipeline for verification gates
132
+ - With pi-debug for error investigation
133
+ - With pi-render for status display
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Command Registry Pattern
3
+ *
4
+ * Registry for command handlers with validation and aliases.
5
+ *
6
+ * Inspired by gstack and pi-hermes-memory patterns.
7
+ */
8
+
9
+ export interface CommandDefinition<T = unknown> {
10
+ /** Command name (e.g., "deploy", "ci-status") */
11
+ name: string;
12
+ /** Short description */
13
+ description?: string;
14
+ /** Longer description */
15
+ help?: string;
16
+ /** Aliases for the command */
17
+ aliases?: string[];
18
+ /** Parameter schema */
19
+ params?: T;
20
+ /** Examples for help */
21
+ examples?: Array<{ cmd: string; desc: string }>;
22
+ }
23
+
24
+ export interface CommandHandler<T = unknown> {
25
+ /** Execute the command */
26
+ execute(params: T, context: CommandContext): Promise<CommandResult>;
27
+ /** Validate parameters before execution */
28
+ validate?(params: T): ValidationResult;
29
+ }
30
+
31
+ export interface CommandContext {
32
+ /** Current working directory */
33
+ cwd: string;
34
+ /** User environment */
35
+ env: Record<string, string>;
36
+ /** Logger */
37
+ log: Logger;
38
+ /** Config store */
39
+ config: ConfigStore;
40
+ }
41
+
42
+ export interface CommandResult {
43
+ /** Exit code (0 = success) */
44
+ code: number;
45
+ /** Output to stdout */
46
+ output?: string;
47
+ /** Output to stderr */
48
+ error?: string;
49
+ }
50
+
51
+ export interface ValidationResult {
52
+ valid: boolean;
53
+ errors?: string[];
54
+ }
55
+
56
+ export interface Logger {
57
+ info(msg: string): void;
58
+ warn(msg: string): void;
59
+ error(msg: string): void;
60
+ debug(msg: string): void;
61
+ }
62
+
63
+ export interface ConfigStore {
64
+ get<T>(key: string, defaultValue?: T): T | undefined;
65
+ set<T>(key: string, value: T): void;
66
+ }
67
+
68
+ /**
69
+ * Command registry for managing available commands.
70
+ */
71
+ export class CommandRegistry {
72
+ private commands = new Map<string, CommandHandler>();
73
+ private definitions = new Map<string, CommandDefinition>();
74
+ private aliases = new Map<string, string>();
75
+
76
+ /**
77
+ * Register a command.
78
+ */
79
+ register<T = unknown>(
80
+ definition: CommandDefinition<T>,
81
+ handler: CommandHandler<T>
82
+ ): void {
83
+ this.commands.set(definition.name, handler as CommandHandler);
84
+ this.definitions.set(definition.name, definition);
85
+
86
+ // Register aliases
87
+ for (const alias of definition.aliases ?? []) {
88
+ this.aliases.set(alias, definition.name);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Execute a command by name.
94
+ */
95
+ async execute(
96
+ name: string,
97
+ params: unknown,
98
+ context: CommandContext
99
+ ): Promise<CommandResult> {
100
+ // Resolve alias
101
+ const resolved = this.aliases.get(name) ?? name;
102
+
103
+ // Find command
104
+ const handler = this.commands.get(resolved);
105
+ if (!handler) {
106
+ return {
107
+ code: 1,
108
+ error: `Unknown command: ${name}`,
109
+ };
110
+ }
111
+
112
+ // Validate
113
+ if (handler.validate) {
114
+ const validation = handler.validate(params);
115
+ if (!validation.valid) {
116
+ return {
117
+ code: 1,
118
+ error: `Validation failed: ${validation.errors?.join(", ")}`,
119
+ };
120
+ }
121
+ }
122
+
123
+ // Execute
124
+ try {
125
+ return await handler.execute(params, context);
126
+ } catch (error) {
127
+ return {
128
+ code: 1,
129
+ error: error instanceof Error ? error.message : String(error),
130
+ };
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Get command definition.
136
+ */
137
+ getDefinition(name: string): CommandDefinition | undefined {
138
+ const resolved = this.aliases.get(name) ?? name;
139
+ return this.definitions.get(resolved);
140
+ }
141
+
142
+ /**
143
+ * List all command names.
144
+ */
145
+ listCommands(): string[] {
146
+ return Array.from(this.definitions.keys()).sort();
147
+ }
148
+
149
+ /**
150
+ * Get help text for a command.
151
+ */
152
+ getHelp(name: string): string | undefined {
153
+ const def = this.getDefinition(name);
154
+ if (!def) return undefined;
155
+
156
+ let help = `# ${def.name}`;
157
+ if (def.aliases?.length) {
158
+ help += ` (alias: ${def.aliases.join(", ")})`;
159
+ }
160
+ help += "\n\n";
161
+
162
+ if (def.description) {
163
+ help += `${def.description}\n\n`;
164
+ }
165
+
166
+ if (def.help) {
167
+ help += `${def.help}\n\n`;
168
+ }
169
+
170
+ if (def.examples?.length) {
171
+ help += "## Examples\n\n";
172
+ for (const ex of def.examples) {
173
+ help += `\`${ex.cmd}\`\n${ex.desc}\n\n`;
174
+ }
175
+ }
176
+
177
+ return help;
178
+ }
179
+ }
180
+
181
+ /**
182
+ * Create a command registry.
183
+ */
184
+ export function createCommandRegistry(): CommandRegistry {
185
+ return new CommandRegistry();
186
+ }