tlc-claude-code 1.5.3 → 1.5.4
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/commands/tlc/audit.md +129 -0
- package/.claude/commands/tlc/autofix.md +217 -0
- package/.claude/commands/tlc/bug.md +255 -0
- package/.claude/commands/tlc/build.md +731 -0
- package/.claude/commands/tlc/checklist.md +212 -0
- package/.claude/commands/tlc/ci.md +414 -0
- package/.claude/commands/tlc/claim.md +189 -0
- package/.claude/commands/tlc/cleanup.md +187 -0
- package/.claude/commands/tlc/complete.md +160 -0
- package/.claude/commands/tlc/config.md +395 -0
- package/.claude/commands/tlc/coverage.md +222 -0
- package/.claude/commands/tlc/deploy.md +723 -0
- package/.claude/commands/tlc/discuss.md +185 -0
- package/.claude/commands/tlc/docs.md +194 -0
- package/.claude/commands/tlc/edge-cases.md +241 -0
- package/.claude/commands/tlc/export.md +456 -0
- package/.claude/commands/tlc/help.md +169 -0
- package/.claude/commands/tlc/import-project.md +246 -0
- package/.claude/commands/tlc/init.md +443 -0
- package/.claude/commands/tlc/issues.md +376 -0
- package/.claude/commands/tlc/llm.md +111 -0
- package/.claude/commands/tlc/new-milestone.md +172 -0
- package/.claude/commands/tlc/new-project.md +399 -0
- package/.claude/commands/tlc/next.md +129 -0
- package/.claude/commands/tlc/outdated.md +200 -0
- package/.claude/commands/tlc/plan.md +224 -0
- package/.claude/commands/tlc/progress.md +153 -0
- package/.claude/commands/tlc/quality.md +185 -0
- package/.claude/commands/tlc/quick.md +52 -0
- package/.claude/commands/tlc/refactor.md +190 -0
- package/.claude/commands/tlc/release.md +135 -0
- package/.claude/commands/tlc/review-pr.md +184 -0
- package/.claude/commands/tlc/review.md +200 -0
- package/.claude/commands/tlc/security.md +195 -0
- package/.claude/commands/tlc/server.md +19 -0
- package/.claude/commands/tlc/start.md +137 -0
- package/.claude/commands/tlc/status.md +65 -0
- package/.claude/commands/tlc/sync.md +652 -0
- package/.claude/commands/tlc/tlc.md +279 -0
- package/.claude/commands/tlc/verify.md +159 -0
- package/.claude/commands/tlc/who.md +151 -0
- package/bin/postinstall.js +54 -0
- package/package.json +3 -1
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
# /tlc:deploy - TLC Dev Server
|
|
2
|
+
|
|
3
|
+
Deploy your TLC project to a remote dev server for team collaboration.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
/tlc:deploy [command]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Commands:
|
|
12
|
+
- `setup` - Generate server config and setup instructions
|
|
13
|
+
- `push` - Deploy current branch
|
|
14
|
+
- `status` - Check deployment status
|
|
15
|
+
- `logs` - View deployment logs
|
|
16
|
+
- `users` - Manage server users
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Quick Setup (Terminal)
|
|
21
|
+
|
|
22
|
+
Run `/tlc:deploy setup` to generate your server config:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
TLC Dev Server Setup
|
|
26
|
+
════════════════════════════════════════════════════════════════════
|
|
27
|
+
|
|
28
|
+
Project Configuration
|
|
29
|
+
─────────────────────
|
|
30
|
+
Name: my-awesome-app
|
|
31
|
+
Repo: git@github.com:myorg/my-awesome-app.git
|
|
32
|
+
Domain: (enter your domain)
|
|
33
|
+
|
|
34
|
+
Domain for dev server: myapp.example.com
|
|
35
|
+
|
|
36
|
+
Generating config...
|
|
37
|
+
|
|
38
|
+
════════════════════════════════════════════════════════════════════
|
|
39
|
+
STEP 1: Run this on your Ubuntu server
|
|
40
|
+
════════════════════════════════════════════════════════════════════
|
|
41
|
+
|
|
42
|
+
┌────────────────────────────────────────────────────────────────────┐
|
|
43
|
+
│ │
|
|
44
|
+
│ curl -fsSL https://tlc.dev/install | bash -s -- \ │
|
|
45
|
+
│ --project "my-awesome-app" \ │
|
|
46
|
+
│ --repo "git@github.com:myorg/my-awesome-app.git" \ │
|
|
47
|
+
│ --domain "myapp.example.com" \ │
|
|
48
|
+
│ --webhook-secret "a1b2c3d4e5f6g7h8" │
|
|
49
|
+
│ │
|
|
50
|
+
└────────────────────────────────────────────────────────────────────┘
|
|
51
|
+
[Copy to clipboard]
|
|
52
|
+
|
|
53
|
+
════════════════════════════════════════════════════════════════════
|
|
54
|
+
STEP 2: Configure DNS
|
|
55
|
+
════════════════════════════════════════════════════════════════════
|
|
56
|
+
|
|
57
|
+
Add these DNS records pointing to your server IP:
|
|
58
|
+
|
|
59
|
+
*.myapp.example.com → YOUR_SERVER_IP
|
|
60
|
+
dashboard.myapp.example.com → YOUR_SERVER_IP
|
|
61
|
+
|
|
62
|
+
════════════════════════════════════════════════════════════════════
|
|
63
|
+
STEP 3: Add GitHub Webhook
|
|
64
|
+
════════════════════════════════════════════════════════════════════
|
|
65
|
+
|
|
66
|
+
Go to: https://github.com/myorg/my-awesome-app/settings/hooks/new
|
|
67
|
+
|
|
68
|
+
Payload URL: https://dashboard.myapp.example.com/api/webhook
|
|
69
|
+
Content type: application/json
|
|
70
|
+
Secret: a1b2c3d4e5f6g7h8
|
|
71
|
+
Events: Just the push event
|
|
72
|
+
|
|
73
|
+
════════════════════════════════════════════════════════════════════
|
|
74
|
+
STEP 4: Done!
|
|
75
|
+
════════════════════════════════════════════════════════════════════
|
|
76
|
+
|
|
77
|
+
Once server setup completes, you'll get:
|
|
78
|
+
|
|
79
|
+
Dashboard: https://dashboard.myapp.example.com
|
|
80
|
+
Main branch: https://main.myapp.example.com
|
|
81
|
+
Feature branches: https://{branch}.myapp.example.com
|
|
82
|
+
|
|
83
|
+
Admin credentials will be shown after server setup.
|
|
84
|
+
|
|
85
|
+
────────────────────────────────────────────────────────────────────
|
|
86
|
+
Config saved to .tlc.json
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Process
|
|
90
|
+
|
|
91
|
+
1. **Detect project state**:
|
|
92
|
+
- New project? Use info from `/tlc:new-project` or `/tlc:init`
|
|
93
|
+
- Existing TLC project? Read from `.tlc.json`
|
|
94
|
+
- Legacy project? Read from `package.json` + git remote
|
|
95
|
+
2. **Ask for domain** if not configured
|
|
96
|
+
3. **Generate webhook secret** (random 16 chars)
|
|
97
|
+
4. **Output setup command** with all config embedded
|
|
98
|
+
5. **Save/update config** in `.tlc.json`
|
|
99
|
+
|
|
100
|
+
### Upgrading Existing Projects
|
|
101
|
+
|
|
102
|
+
For projects already using TLC but without team features:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
> /tlc:deploy setup
|
|
106
|
+
|
|
107
|
+
TLC Dev Server Setup
|
|
108
|
+
════════════════════════════════════════════════════════════════════
|
|
109
|
+
|
|
110
|
+
Detected existing TLC project: my-awesome-app
|
|
111
|
+
✓ .tlc.json found
|
|
112
|
+
✓ .planning/ directory exists
|
|
113
|
+
✗ No deploy config yet
|
|
114
|
+
|
|
115
|
+
Adding team collaboration features...
|
|
116
|
+
|
|
117
|
+
Project: my-awesome-app
|
|
118
|
+
Repo: git@github.com:myorg/my-awesome-app.git
|
|
119
|
+
|
|
120
|
+
Enter your server domain: _
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The setup continues with the same flow - generates config, shows server command, DNS instructions, webhook config.
|
|
124
|
+
|
|
125
|
+
### Enable Team Coordination
|
|
126
|
+
|
|
127
|
+
After domain setup, ask about team coordination model:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
───────────────────────────────────────────────────────────────
|
|
131
|
+
Team Coordination
|
|
132
|
+
───────────────────────────────────────────────────────────────
|
|
133
|
+
|
|
134
|
+
Enable task claiming and multi-user coordination?
|
|
135
|
+
|
|
136
|
+
This adds:
|
|
137
|
+
• Task markers: [ ], [>@alice], [x@bob]
|
|
138
|
+
• /tlc:claim - reserve a task before working
|
|
139
|
+
• /tlc:release - release a task if blocked
|
|
140
|
+
• /tlc:who - see who's working on what
|
|
141
|
+
• Git-based sync (push/pull shares claims)
|
|
142
|
+
|
|
143
|
+
Enable team coordination? [Y/n]: _
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**If Yes:**
|
|
147
|
+
|
|
148
|
+
1. Add team config to `.tlc.json`
|
|
149
|
+
2. Migrate existing PLAN.md files to add `[ ]` markers
|
|
150
|
+
3. Show coordination workflow
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
✓ Team coordination enabled
|
|
154
|
+
|
|
155
|
+
Existing plans updated:
|
|
156
|
+
.planning/phases/1-PLAN.md - 3 tasks marked as available
|
|
157
|
+
.planning/phases/2-PLAN.md - 4 tasks marked as available
|
|
158
|
+
|
|
159
|
+
Team Workflow:
|
|
160
|
+
───────────────────────────────────────────────────────────────
|
|
161
|
+
1. git pull ← Get latest claims
|
|
162
|
+
2. /tlc:claim ← Reserve your task
|
|
163
|
+
3. git push ← Share your claim
|
|
164
|
+
4. ... work on task ...
|
|
165
|
+
5. git commit & push ← Task auto-marked complete
|
|
166
|
+
───────────────────────────────────────────────────────────────
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Plan Migration
|
|
170
|
+
|
|
171
|
+
Existing task headings are updated:
|
|
172
|
+
|
|
173
|
+
**Before:**
|
|
174
|
+
```markdown
|
|
175
|
+
### Task 1: Create user schema
|
|
176
|
+
### Task 2: Add validation
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**After:**
|
|
180
|
+
```markdown
|
|
181
|
+
### Task 1: Create user schema [ ]
|
|
182
|
+
### Task 2: Add validation [ ]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
This makes tasks claimable without changing any other content.
|
|
186
|
+
|
|
187
|
+
**What gets added to .tlc.json:**
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"project": "my-awesome-app",
|
|
192
|
+
"testFrameworks": { ... }, // existing config preserved
|
|
193
|
+
"team": { // NEW: team coordination
|
|
194
|
+
"enabled": true,
|
|
195
|
+
"model": "git-based"
|
|
196
|
+
},
|
|
197
|
+
"deploy": { // NEW: dev server
|
|
198
|
+
"domain": "myapp.example.com",
|
|
199
|
+
"webhookSecret": "x7k9m2p4q8r1s5t3",
|
|
200
|
+
"dashboardUrl": "https://dashboard.myapp.example.com",
|
|
201
|
+
"configured": false
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
// Config generation
|
|
208
|
+
const config = {
|
|
209
|
+
project: packageJson.name,
|
|
210
|
+
repo: getGitRemoteUrl(),
|
|
211
|
+
domain: userInput.domain,
|
|
212
|
+
webhookSecret: crypto.randomBytes(16).toString('hex')
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// Generate one-liner
|
|
216
|
+
const command = `curl -fsSL https://tlc.dev/install | bash -s -- \\
|
|
217
|
+
--project "${config.project}" \\
|
|
218
|
+
--repo "${config.repo}" \\
|
|
219
|
+
--domain "${config.domain}" \\
|
|
220
|
+
--webhook-secret "${config.webhookSecret}"`;
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Architecture
|
|
226
|
+
|
|
227
|
+
```
|
|
228
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
229
|
+
│ TLC Dev Server │
|
|
230
|
+
│ │
|
|
231
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
232
|
+
│ │ Branch │ │ Branch │ │ Branch │ │
|
|
233
|
+
│ │ main │ │ feat-auth │ │ fix-bug │ │
|
|
234
|
+
│ │ :3000 │ │ :3001 │ │ :3002 │ │
|
|
235
|
+
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
|
|
236
|
+
│ │ │ │ │
|
|
237
|
+
│ └────────────────┼────────────────┘ │
|
|
238
|
+
│ │ │
|
|
239
|
+
│ ┌───────────────────────┴───────────────────────┐ │
|
|
240
|
+
│ │ TLC Deploy Server │ │
|
|
241
|
+
│ │ :3147 │ │
|
|
242
|
+
│ │ - Dashboard (auth required) │ │
|
|
243
|
+
│ │ - API for deployments │ │
|
|
244
|
+
│ │ - Webhook receiver │ │
|
|
245
|
+
│ │ - Slack notifications │ │
|
|
246
|
+
│ └───────────────────────────────────────────────┘ │
|
|
247
|
+
│ │ │
|
|
248
|
+
│ ┌───────────────────────┴───────────────────────┐ │
|
|
249
|
+
│ │ Reverse Proxy (nginx) │ │
|
|
250
|
+
│ │ │ │
|
|
251
|
+
│ │ main.project.example.com → :3000 │ │
|
|
252
|
+
│ │ feat-auth.project.example.com → :3001 │ │
|
|
253
|
+
│ │ dashboard.project.example.com → :3147 │ │
|
|
254
|
+
│ └───────────────────────────────────────────────┘ │
|
|
255
|
+
└─────────────────────────────────────────────────────────────┘
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
## Setup
|
|
259
|
+
|
|
260
|
+
### 1. Server Requirements
|
|
261
|
+
|
|
262
|
+
- Ubuntu 22.04+ or similar
|
|
263
|
+
- Docker installed
|
|
264
|
+
- Node.js 20+
|
|
265
|
+
- nginx (reverse proxy)
|
|
266
|
+
- PostgreSQL (user database)
|
|
267
|
+
|
|
268
|
+
### 2. Configure Server
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
> /tlc:deploy setup
|
|
272
|
+
|
|
273
|
+
TLC Deployment Server Setup
|
|
274
|
+
|
|
275
|
+
Dev Server Configuration:
|
|
276
|
+
Host: deploy.example.com
|
|
277
|
+
SSH Key: ~/.ssh/id_rsa (detected)
|
|
278
|
+
|
|
279
|
+
Testing connection...
|
|
280
|
+
✓ Connected to deploy.example.com
|
|
281
|
+
|
|
282
|
+
Installing TLC Deploy Server...
|
|
283
|
+
✓ Dependencies installed
|
|
284
|
+
✓ Database created
|
|
285
|
+
✓ nginx configured
|
|
286
|
+
|
|
287
|
+
Domain Configuration:
|
|
288
|
+
Base domain: project.example.com
|
|
289
|
+
Branches will be: {branch}.project.example.com
|
|
290
|
+
|
|
291
|
+
Configure DNS:
|
|
292
|
+
*.project.example.com → SERVER_IP
|
|
293
|
+
|
|
294
|
+
Admin User:
|
|
295
|
+
Email: admin@example.com
|
|
296
|
+
Password: (generated) K8x#mP2$nQ
|
|
297
|
+
|
|
298
|
+
Slack Integration (optional):
|
|
299
|
+
Webhook URL: https://hooks.slack.com/services/XXX
|
|
300
|
+
|
|
301
|
+
Configuration saved to .tlc.json
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### 3. Local Configuration
|
|
305
|
+
|
|
306
|
+
In `.tlc.json`:
|
|
307
|
+
|
|
308
|
+
```json
|
|
309
|
+
{
|
|
310
|
+
"deploy": {
|
|
311
|
+
"server": "deploy.example.com",
|
|
312
|
+
"domain": "project.example.com",
|
|
313
|
+
"sshKey": "~/.ssh/id_rsa",
|
|
314
|
+
"slack": {
|
|
315
|
+
"webhookUrl": "https://hooks.slack.com/services/XXX/YYY/ZZZ",
|
|
316
|
+
"channel": "#deployments"
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
## User Management
|
|
323
|
+
|
|
324
|
+
### Authentication
|
|
325
|
+
|
|
326
|
+
Users table (PostgreSQL):
|
|
327
|
+
|
|
328
|
+
```sql
|
|
329
|
+
CREATE TABLE users (
|
|
330
|
+
id SERIAL PRIMARY KEY,
|
|
331
|
+
email VARCHAR(255) UNIQUE NOT NULL,
|
|
332
|
+
password_hash VARCHAR(255) NOT NULL,
|
|
333
|
+
name VARCHAR(255),
|
|
334
|
+
role VARCHAR(50) DEFAULT 'engineer',
|
|
335
|
+
created_at TIMESTAMP DEFAULT NOW(),
|
|
336
|
+
last_login TIMESTAMP
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
-- Roles: admin, engineer, qa, po
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### User Commands
|
|
343
|
+
|
|
344
|
+
```
|
|
345
|
+
> /tlc:deploy users add
|
|
346
|
+
|
|
347
|
+
Email: bob@example.com
|
|
348
|
+
Name: Bob Smith
|
|
349
|
+
Role: engineer
|
|
350
|
+
Password: (generated) Qw3$rTy9
|
|
351
|
+
|
|
352
|
+
User created! They can login at:
|
|
353
|
+
https://dashboard.project.example.com
|
|
354
|
+
|
|
355
|
+
> /tlc:deploy users list
|
|
356
|
+
|
|
357
|
+
Users:
|
|
358
|
+
admin@example.com (admin) - Last login: today
|
|
359
|
+
alice@example.com (engineer) - Last login: 2h ago
|
|
360
|
+
bob@example.com (engineer) - Last login: never
|
|
361
|
+
qa@example.com (qa) - Last login: 1d ago
|
|
362
|
+
|
|
363
|
+
> /tlc:deploy users remove bob@example.com
|
|
364
|
+
|
|
365
|
+
User bob@example.com removed.
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### JWT Authentication
|
|
369
|
+
|
|
370
|
+
```javascript
|
|
371
|
+
// Server generates JWT on login
|
|
372
|
+
const token = jwt.sign(
|
|
373
|
+
{ userId: user.id, email: user.email, role: user.role },
|
|
374
|
+
process.env.JWT_SECRET,
|
|
375
|
+
{ expiresIn: '7d' }
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
// Protected routes check role
|
|
379
|
+
app.get('/api/admin/*', requireRole('admin'));
|
|
380
|
+
app.post('/api/deploy', requireRole(['admin', 'engineer']));
|
|
381
|
+
app.get('/api/status', requireRole(['admin', 'engineer', 'qa', 'po']));
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Deployment
|
|
385
|
+
|
|
386
|
+
### Push to Deploy
|
|
387
|
+
|
|
388
|
+
```
|
|
389
|
+
> /tlc:deploy push
|
|
390
|
+
|
|
391
|
+
Deploying branch: feat-auth
|
|
392
|
+
|
|
393
|
+
Pushing to dev server...
|
|
394
|
+
✓ Code uploaded
|
|
395
|
+
✓ Dependencies installed
|
|
396
|
+
✓ Tests passed (23/23)
|
|
397
|
+
✓ Container started
|
|
398
|
+
|
|
399
|
+
Deployment complete!
|
|
400
|
+
URL: https://feat-auth.project.example.com
|
|
401
|
+
|
|
402
|
+
Slack notification sent: #deployments
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Automatic Deployment
|
|
406
|
+
|
|
407
|
+
With webhook, pushing to GitHub triggers deployment:
|
|
408
|
+
|
|
409
|
+
```yaml
|
|
410
|
+
# GitHub Action
|
|
411
|
+
on:
|
|
412
|
+
push:
|
|
413
|
+
branches: ['**']
|
|
414
|
+
|
|
415
|
+
jobs:
|
|
416
|
+
deploy:
|
|
417
|
+
runs-on: ubuntu-latest
|
|
418
|
+
steps:
|
|
419
|
+
- name: Trigger deployment
|
|
420
|
+
run: |
|
|
421
|
+
curl -X POST https://dashboard.project.example.com/api/webhook/deploy \
|
|
422
|
+
-H "X-Webhook-Secret: ${{ secrets.DEPLOY_SECRET }}" \
|
|
423
|
+
-d '{"branch": "${{ github.ref_name }}", "sha": "${{ github.sha }}"}'
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Deployment Status
|
|
427
|
+
|
|
428
|
+
```
|
|
429
|
+
> /tlc:deploy status
|
|
430
|
+
|
|
431
|
+
Active Deployments:
|
|
432
|
+
|
|
433
|
+
| Branch | URL | Status | Last Deploy |
|
|
434
|
+
|--------|-----|--------|-------------|
|
|
435
|
+
| main | main.project.example.com | ✓ Running | 2h ago |
|
|
436
|
+
| feat-auth | feat-auth.project.example.com | ✓ Running | 30m ago |
|
|
437
|
+
| fix-bug | fix-bug.project.example.com | ✗ Failed | 15m ago |
|
|
438
|
+
|
|
439
|
+
Total: 3 deployments (2 healthy, 1 failed)
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
### View Logs
|
|
443
|
+
|
|
444
|
+
```
|
|
445
|
+
> /tlc:deploy logs feat-auth
|
|
446
|
+
|
|
447
|
+
[2024-01-15 10:30:45] Container started
|
|
448
|
+
[2024-01-15 10:30:46] Listening on :3001
|
|
449
|
+
[2024-01-15 10:31:02] GET /api/users 200 12ms
|
|
450
|
+
[2024-01-15 10:31:15] POST /api/login 200 45ms
|
|
451
|
+
[2024-01-15 10:32:00] GET /api/users/123 404 8ms
|
|
452
|
+
|
|
453
|
+
[Press Ctrl+C to stop streaming]
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
## Slack Integration
|
|
457
|
+
|
|
458
|
+
### Notifications
|
|
459
|
+
|
|
460
|
+
```json
|
|
461
|
+
{
|
|
462
|
+
"deploy": {
|
|
463
|
+
"slack": {
|
|
464
|
+
"webhookUrl": "https://hooks.slack.com/...",
|
|
465
|
+
"channel": "#deployments",
|
|
466
|
+
"events": {
|
|
467
|
+
"deploy_start": true,
|
|
468
|
+
"deploy_success": true,
|
|
469
|
+
"deploy_fail": true,
|
|
470
|
+
"tests_fail": true,
|
|
471
|
+
"bug_created": true
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
### Message Examples
|
|
479
|
+
|
|
480
|
+
**Deploy Success:**
|
|
481
|
+
```
|
|
482
|
+
🚀 Deployment Successful
|
|
483
|
+
Branch: feat-auth
|
|
484
|
+
URL: https://feat-auth.project.example.com
|
|
485
|
+
Tests: 23/23 passing
|
|
486
|
+
Deployed by: Alice
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
**Deploy Failed:**
|
|
490
|
+
```
|
|
491
|
+
❌ Deployment Failed
|
|
492
|
+
Branch: fix-bug
|
|
493
|
+
Error: Tests failed (3 failing)
|
|
494
|
+
See logs: https://dashboard.project.example.com/logs/fix-bug
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**Bug Created:**
|
|
498
|
+
```
|
|
499
|
+
🐛 New Bug Reported
|
|
500
|
+
BUG-015: Login button not responding
|
|
501
|
+
Severity: high
|
|
502
|
+
Reporter: QA Team
|
|
503
|
+
View: https://dashboard.project.example.com/bugs/15
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
### Custom Webhooks
|
|
507
|
+
|
|
508
|
+
```javascript
|
|
509
|
+
// In deploy server
|
|
510
|
+
async function notifySlack(event, data) {
|
|
511
|
+
const messages = {
|
|
512
|
+
deploy_start: `🔄 Deploying ${data.branch}...`,
|
|
513
|
+
deploy_success: `🚀 ${data.branch} deployed to ${data.url}`,
|
|
514
|
+
deploy_fail: `❌ ${data.branch} deployment failed: ${data.error}`,
|
|
515
|
+
tests_fail: `⚠️ Tests failing on ${data.branch}: ${data.failCount} failures`,
|
|
516
|
+
bug_created: `🐛 ${data.bugId}: ${data.title}`
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
await fetch(config.slack.webhookUrl, {
|
|
520
|
+
method: 'POST',
|
|
521
|
+
headers: { 'Content-Type': 'application/json' },
|
|
522
|
+
body: JSON.stringify({
|
|
523
|
+
channel: config.slack.channel,
|
|
524
|
+
text: messages[event],
|
|
525
|
+
attachments: buildAttachments(event, data)
|
|
526
|
+
})
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
## Dashboard Features
|
|
532
|
+
|
|
533
|
+
### For Engineers
|
|
534
|
+
|
|
535
|
+
- View all branch deployments
|
|
536
|
+
- Check logs and status
|
|
537
|
+
- Trigger manual deploys
|
|
538
|
+
- View test results
|
|
539
|
+
|
|
540
|
+
### For QA
|
|
541
|
+
|
|
542
|
+
- Access preview URLs
|
|
543
|
+
- Submit bugs with screenshots
|
|
544
|
+
- View task board
|
|
545
|
+
- Track bug status
|
|
546
|
+
|
|
547
|
+
### For PO
|
|
548
|
+
|
|
549
|
+
- View project progress
|
|
550
|
+
- Access previews
|
|
551
|
+
- Review completed features
|
|
552
|
+
- Track milestones
|
|
553
|
+
|
|
554
|
+
## Docker Configuration
|
|
555
|
+
|
|
556
|
+
Each branch runs in isolated container:
|
|
557
|
+
|
|
558
|
+
```dockerfile
|
|
559
|
+
# Generated per deployment
|
|
560
|
+
FROM node:20-alpine
|
|
561
|
+
|
|
562
|
+
WORKDIR /app
|
|
563
|
+
COPY package*.json ./
|
|
564
|
+
RUN npm ci --production
|
|
565
|
+
COPY . .
|
|
566
|
+
|
|
567
|
+
ENV PORT=3000
|
|
568
|
+
EXPOSE 3000
|
|
569
|
+
|
|
570
|
+
CMD ["npm", "start"]
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### docker-compose.yml (on dev server)
|
|
574
|
+
|
|
575
|
+
```yaml
|
|
576
|
+
version: '3.8'
|
|
577
|
+
|
|
578
|
+
services:
|
|
579
|
+
main:
|
|
580
|
+
build:
|
|
581
|
+
context: ./deployments/main
|
|
582
|
+
ports:
|
|
583
|
+
- "3000:3000"
|
|
584
|
+
restart: unless-stopped
|
|
585
|
+
|
|
586
|
+
feat-auth:
|
|
587
|
+
build:
|
|
588
|
+
context: ./deployments/feat-auth
|
|
589
|
+
ports:
|
|
590
|
+
- "3001:3000"
|
|
591
|
+
restart: unless-stopped
|
|
592
|
+
|
|
593
|
+
# Added dynamically per branch
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
## nginx Configuration
|
|
597
|
+
|
|
598
|
+
```nginx
|
|
599
|
+
# /etc/nginx/sites-enabled/tlc-deploy
|
|
600
|
+
|
|
601
|
+
# Dashboard
|
|
602
|
+
server {
|
|
603
|
+
listen 443 ssl;
|
|
604
|
+
server_name dashboard.project.example.com;
|
|
605
|
+
|
|
606
|
+
ssl_certificate /etc/letsencrypt/live/project.example.com/fullchain.pem;
|
|
607
|
+
ssl_certificate_key /etc/letsencrypt/live/project.example.com/privkey.pem;
|
|
608
|
+
|
|
609
|
+
location / {
|
|
610
|
+
proxy_pass http://localhost:3147;
|
|
611
|
+
proxy_http_version 1.1;
|
|
612
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
613
|
+
proxy_set_header Connection "upgrade";
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
# Branch deployments (wildcard)
|
|
618
|
+
server {
|
|
619
|
+
listen 443 ssl;
|
|
620
|
+
server_name ~^(?<branch>.+)\.project\.example\.com$;
|
|
621
|
+
|
|
622
|
+
ssl_certificate /etc/letsencrypt/live/project.example.com/fullchain.pem;
|
|
623
|
+
ssl_certificate_key /etc/letsencrypt/live/project.example.com/privkey.pem;
|
|
624
|
+
|
|
625
|
+
location / {
|
|
626
|
+
# Port mapping from branch name
|
|
627
|
+
set $port 3000;
|
|
628
|
+
# Dynamic port resolution handled by deploy server
|
|
629
|
+
proxy_pass http://localhost:$port;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
## Security
|
|
635
|
+
|
|
636
|
+
### SSH Key Deployment
|
|
637
|
+
|
|
638
|
+
```
|
|
639
|
+
> /tlc:deploy setup --ssh
|
|
640
|
+
|
|
641
|
+
Generating deployment SSH key...
|
|
642
|
+
✓ Key generated: ~/.ssh/tlc_deploy
|
|
643
|
+
|
|
644
|
+
Add this to server authorized_keys:
|
|
645
|
+
ssh-rsa AAAA... tlc-deploy
|
|
646
|
+
|
|
647
|
+
Add to GitHub deploy keys (read-only):
|
|
648
|
+
https://github.com/org/repo/settings/keys
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
### Environment Variables
|
|
652
|
+
|
|
653
|
+
Secrets stored on dev server:
|
|
654
|
+
|
|
655
|
+
```bash
|
|
656
|
+
# /opt/tlc-deploy/.env
|
|
657
|
+
JWT_SECRET=your-secret-here
|
|
658
|
+
DATABASE_URL=postgres://user:pass@localhost/tlc
|
|
659
|
+
GITHUB_WEBHOOK_SECRET=webhook-secret
|
|
660
|
+
SLACK_WEBHOOK_URL=https://hooks.slack.com/...
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
## Cleanup
|
|
664
|
+
|
|
665
|
+
### Remove old deployments
|
|
666
|
+
|
|
667
|
+
```
|
|
668
|
+
> /tlc:deploy cleanup
|
|
669
|
+
|
|
670
|
+
Stale deployments (no activity 7+ days):
|
|
671
|
+
- feat-old (14 days)
|
|
672
|
+
- test-branch (21 days)
|
|
673
|
+
|
|
674
|
+
Remove these? (Y/n) y
|
|
675
|
+
|
|
676
|
+
Removed 2 deployments.
|
|
677
|
+
Freed 1.2GB disk space.
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
## Example Workflow
|
|
681
|
+
|
|
682
|
+
```
|
|
683
|
+
# Engineer pushes code
|
|
684
|
+
git push origin feat-auth
|
|
685
|
+
|
|
686
|
+
# GitHub webhook triggers deploy
|
|
687
|
+
# Slack: "🔄 Deploying feat-auth..."
|
|
688
|
+
|
|
689
|
+
# Tests run, deployment starts
|
|
690
|
+
# Slack: "🚀 feat-auth deployed to https://feat-auth.project.example.com"
|
|
691
|
+
|
|
692
|
+
# QA tests the feature
|
|
693
|
+
# Opens dashboard, tests in preview
|
|
694
|
+
# Finds bug, submits via form
|
|
695
|
+
# Slack: "🐛 BUG-015: Login timeout on slow connection"
|
|
696
|
+
|
|
697
|
+
# Engineer sees notification, fixes
|
|
698
|
+
git commit -m "fix: increase login timeout"
|
|
699
|
+
git push
|
|
700
|
+
|
|
701
|
+
# New deployment triggers
|
|
702
|
+
# Slack: "🚀 feat-auth updated"
|
|
703
|
+
|
|
704
|
+
# QA re-tests, marks bug fixed
|
|
705
|
+
# PO reviews, approves feature
|
|
706
|
+
|
|
707
|
+
# Merge to main
|
|
708
|
+
git checkout main
|
|
709
|
+
git merge feat-auth
|
|
710
|
+
git push
|
|
711
|
+
|
|
712
|
+
# Main deployment updates
|
|
713
|
+
# Slack: "🚀 main deployed - includes feat-auth"
|
|
714
|
+
```
|
|
715
|
+
|
|
716
|
+
## Notes
|
|
717
|
+
|
|
718
|
+
- Each branch gets isolated container
|
|
719
|
+
- Automatic cleanup of merged branches
|
|
720
|
+
- SSL via Let's Encrypt (wildcard cert)
|
|
721
|
+
- All actions logged for audit
|
|
722
|
+
- Role-based access control
|
|
723
|
+
- Webhook secrets required
|