planflow-plugin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +93 -0
- package/bin/cli.js +169 -0
- package/bin/postinstall.js +87 -0
- package/commands/pfActivity/SKILL.md +725 -0
- package/commands/pfAssign/SKILL.md +623 -0
- package/commands/pfCloudLink/SKILL.md +192 -0
- package/commands/pfCloudList/SKILL.md +222 -0
- package/commands/pfCloudNew/SKILL.md +187 -0
- package/commands/pfCloudUnlink/SKILL.md +152 -0
- package/commands/pfComment/SKILL.md +227 -0
- package/commands/pfComments/SKILL.md +159 -0
- package/commands/pfConnectionStatus/SKILL.md +433 -0
- package/commands/pfDiscord/SKILL.md +740 -0
- package/commands/pfGithubBranch/SKILL.md +672 -0
- package/commands/pfGithubIssue/SKILL.md +963 -0
- package/commands/pfGithubLink/SKILL.md +859 -0
- package/commands/pfGithubPr/SKILL.md +1335 -0
- package/commands/pfGithubUnlink/SKILL.md +401 -0
- package/commands/pfLive/SKILL.md +185 -0
- package/commands/pfLogin/SKILL.md +249 -0
- package/commands/pfLogout/SKILL.md +155 -0
- package/commands/pfMyTasks/SKILL.md +198 -0
- package/commands/pfNotificationSettings/SKILL.md +619 -0
- package/commands/pfNotifications/SKILL.md +420 -0
- package/commands/pfNotificationsClear/SKILL.md +421 -0
- package/commands/pfReact/SKILL.md +232 -0
- package/commands/pfSlack/SKILL.md +659 -0
- package/commands/pfSyncPull/SKILL.md +210 -0
- package/commands/pfSyncPush/SKILL.md +299 -0
- package/commands/pfSyncStatus/SKILL.md +212 -0
- package/commands/pfTeamInvite/SKILL.md +161 -0
- package/commands/pfTeamList/SKILL.md +253 -0
- package/commands/pfTeamRemove/SKILL.md +115 -0
- package/commands/pfTeamRole/SKILL.md +160 -0
- package/commands/pfTestWebhooks/SKILL.md +722 -0
- package/commands/pfUnassign/SKILL.md +134 -0
- package/commands/pfWhoami/SKILL.md +258 -0
- package/commands/pfWorkload/SKILL.md +219 -0
- package/commands/planExportCsv/SKILL.md +106 -0
- package/commands/planExportGithub/SKILL.md +222 -0
- package/commands/planExportJson/SKILL.md +159 -0
- package/commands/planExportSummary/SKILL.md +158 -0
- package/commands/planNew/SKILL.md +641 -0
- package/commands/planNext/SKILL.md +1200 -0
- package/commands/planSettingsAutoSync/SKILL.md +199 -0
- package/commands/planSettingsLanguage/SKILL.md +201 -0
- package/commands/planSettingsReset/SKILL.md +237 -0
- package/commands/planSettingsShow/SKILL.md +482 -0
- package/commands/planSpec/SKILL.md +929 -0
- package/commands/planUpdate/SKILL.md +2518 -0
- package/commands/team/SKILL.md +740 -0
- package/locales/en.json +1499 -0
- package/locales/ka.json +1499 -0
- package/package.json +48 -0
- package/templates/PROJECT_PLAN.template.md +157 -0
- package/templates/backend-api.template.md +562 -0
- package/templates/frontend-spa.template.md +610 -0
- package/templates/fullstack.template.md +397 -0
- package/templates/ka/backend-api.template.md +562 -0
- package/templates/ka/frontend-spa.template.md +610 -0
- package/templates/ka/fullstack.template.md +397 -0
- package/templates/sections/architecture.md +21 -0
- package/templates/sections/overview.md +15 -0
- package/templates/sections/tasks.md +22 -0
- package/templates/sections/tech-stack.md +19 -0
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pfTestWebhooks
|
|
3
|
+
description: Test all configured webhook integrations (Slack and Discord)
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PlanFlow Test Webhooks
|
|
7
|
+
|
|
8
|
+
Test all configured webhook integrations to verify they are working correctly. This command sends test notifications to all enabled integrations (Slack and Discord) at once.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
/pfTestWebhooks # Test all configured webhooks
|
|
14
|
+
/pfTestWebhooks slack # Test only Slack webhook
|
|
15
|
+
/pfTestWebhooks discord # Test only Discord webhook
|
|
16
|
+
/pfTestWebhooks --verbose # Show detailed test results
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Process
|
|
20
|
+
|
|
21
|
+
### Step 0: Load Configuration & Translations
|
|
22
|
+
|
|
23
|
+
**CRITICAL: Execute this step FIRST, before any output!**
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
// Merge global and local configs
|
|
27
|
+
function getMergedConfig() {
|
|
28
|
+
let globalConfig = {}
|
|
29
|
+
let localConfig = {}
|
|
30
|
+
|
|
31
|
+
const globalPath = expandPath("~/.config/claude/plan-plugin-config.json")
|
|
32
|
+
if (fileExists(globalPath)) {
|
|
33
|
+
try { globalConfig = JSON.parse(readFile(globalPath)) } catch (e) {}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (fileExists("./.plan-config.json")) {
|
|
37
|
+
try { localConfig = JSON.parse(readFile("./.plan-config.json")) } catch (e) {}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
...globalConfig,
|
|
42
|
+
...localConfig,
|
|
43
|
+
cloud: {
|
|
44
|
+
...(globalConfig.cloud || {}),
|
|
45
|
+
...(localConfig.cloud || {})
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const config = getMergedConfig()
|
|
51
|
+
const language = config.language || "en"
|
|
52
|
+
const cloudConfig = config.cloud || {}
|
|
53
|
+
const isAuthenticated = !!cloudConfig.apiToken
|
|
54
|
+
const projectId = cloudConfig.projectId
|
|
55
|
+
const apiUrl = cloudConfig.apiUrl || "https://api.planflow.tools"
|
|
56
|
+
|
|
57
|
+
// Load translations
|
|
58
|
+
const t = JSON.parse(readFile(`locales/${language}.json`))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Step 1: Check Authentication
|
|
62
|
+
|
|
63
|
+
If not authenticated, show error:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
67
|
+
│ ❌ ERROR │
|
|
68
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
69
|
+
│ │
|
|
70
|
+
│ {t.commands.sync.notAuthenticated} │
|
|
71
|
+
│ │
|
|
72
|
+
│ Webhook testing requires a cloud connection. │
|
|
73
|
+
│ │
|
|
74
|
+
│ 💡 Run /pfLogin to authenticate first. │
|
|
75
|
+
│ │
|
|
76
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
If no project linked, show error:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
83
|
+
│ ❌ ERROR │
|
|
84
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
85
|
+
│ │
|
|
86
|
+
│ {t.commands.sync.notLinked} │
|
|
87
|
+
│ │
|
|
88
|
+
│ 💡 Run /pfCloudLink to link a project first. │
|
|
89
|
+
│ │
|
|
90
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Step 2: Parse Arguments
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
const args = commandArgs.trim().toLowerCase()
|
|
97
|
+
const parts = args.split(/\s+/)
|
|
98
|
+
const target = parts[0] || "all" // "slack", "discord", "all", or "--verbose"
|
|
99
|
+
const verbose = args.includes("--verbose") || args.includes("-v")
|
|
100
|
+
|
|
101
|
+
// Normalize target
|
|
102
|
+
let testSlack = target === "all" || target === "slack" || target === "--verbose" || target === "-v"
|
|
103
|
+
let testDiscord = target === "all" || target === "discord" || target === "--verbose" || target === "-v"
|
|
104
|
+
|
|
105
|
+
if (target === "slack") {
|
|
106
|
+
testDiscord = false
|
|
107
|
+
}
|
|
108
|
+
if (target === "discord") {
|
|
109
|
+
testSlack = false
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Step 3: Fetch Integration Status
|
|
114
|
+
|
|
115
|
+
First, fetch the current status of all integrations to know which ones are configured.
|
|
116
|
+
|
|
117
|
+
**API Request:**
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
API_URL="https://api.planflow.tools"
|
|
121
|
+
TOKEN="$API_TOKEN"
|
|
122
|
+
PROJECT_ID="$PROJECT_ID"
|
|
123
|
+
|
|
124
|
+
# Fetch all integration statuses
|
|
125
|
+
RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
126
|
+
--connect-timeout 5 \
|
|
127
|
+
--max-time 10 \
|
|
128
|
+
-X GET \
|
|
129
|
+
-H "Accept: application/json" \
|
|
130
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
131
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations")
|
|
132
|
+
|
|
133
|
+
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
134
|
+
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
135
|
+
|
|
136
|
+
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
137
|
+
echo "$BODY"
|
|
138
|
+
else
|
|
139
|
+
echo "Error: HTTP $HTTP_CODE"
|
|
140
|
+
fi
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Expected Response:**
|
|
144
|
+
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"success": true,
|
|
148
|
+
"data": {
|
|
149
|
+
"integrations": {
|
|
150
|
+
"slack": {
|
|
151
|
+
"enabled": true,
|
|
152
|
+
"webhookConfigured": true,
|
|
153
|
+
"lastTestAt": "2026-02-20T10:30:00Z"
|
|
154
|
+
},
|
|
155
|
+
"discord": {
|
|
156
|
+
"enabled": true,
|
|
157
|
+
"webhookConfigured": true,
|
|
158
|
+
"lastTestAt": "2026-02-20T10:30:00Z"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Step 4: Run Tests
|
|
166
|
+
|
|
167
|
+
#### If no integrations configured:
|
|
168
|
+
|
|
169
|
+
```
|
|
170
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
171
|
+
│ ⚠️ {t.commands.testWebhooks.noIntegrations} │
|
|
172
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
173
|
+
│ │
|
|
174
|
+
│ No webhook integrations are configured for this project. │
|
|
175
|
+
│ │
|
|
176
|
+
│ ── Available Integrations ──────────────────────────────────────────────── │
|
|
177
|
+
│ │
|
|
178
|
+
│ 💬 Slack - /pfSlack setup <webhook-url> │
|
|
179
|
+
│ 🎮 Discord - /pfDiscord setup <webhook-url> │
|
|
180
|
+
│ │
|
|
181
|
+
│ 💡 Set up an integration first, then run /pfTestWebhooks │
|
|
182
|
+
│ │
|
|
183
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
#### Testing integrations:
|
|
187
|
+
|
|
188
|
+
Show a progress indicator while testing:
|
|
189
|
+
|
|
190
|
+
```
|
|
191
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
192
|
+
│ 🧪 {t.commands.testWebhooks.title} │
|
|
193
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
194
|
+
│ │
|
|
195
|
+
│ 📁 Project: {projectName} │
|
|
196
|
+
│ │
|
|
197
|
+
│ ── Testing Webhooks ────────────────────────────────────────────────────── │
|
|
198
|
+
│ │
|
|
199
|
+
│ 💬 Slack... ⏳ Testing │
|
|
200
|
+
│ 🎮 Discord... ⏳ Testing │
|
|
201
|
+
│ │
|
|
202
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
**API Request for Slack Test:**
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
API_URL="https://api.planflow.tools"
|
|
209
|
+
TOKEN="$API_TOKEN"
|
|
210
|
+
PROJECT_ID="$PROJECT_ID"
|
|
211
|
+
|
|
212
|
+
# Test Slack webhook
|
|
213
|
+
SLACK_RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
214
|
+
--connect-timeout 5 \
|
|
215
|
+
--max-time 15 \
|
|
216
|
+
-X POST \
|
|
217
|
+
-H "Content-Type: application/json" \
|
|
218
|
+
-H "Accept: application/json" \
|
|
219
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
220
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations/slack/test")
|
|
221
|
+
|
|
222
|
+
SLACK_HTTP_CODE=$(echo "$SLACK_RESPONSE" | tail -n1)
|
|
223
|
+
SLACK_BODY=$(echo "$SLACK_RESPONSE" | sed '$d')
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**API Request for Discord Test:**
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Test Discord webhook
|
|
230
|
+
DISCORD_RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
231
|
+
--connect-timeout 5 \
|
|
232
|
+
--max-time 15 \
|
|
233
|
+
-X POST \
|
|
234
|
+
-H "Content-Type: application/json" \
|
|
235
|
+
-H "Accept: application/json" \
|
|
236
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
237
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations/discord/test")
|
|
238
|
+
|
|
239
|
+
DISCORD_HTTP_CODE=$(echo "$DISCORD_RESPONSE" | tail -n1)
|
|
240
|
+
DISCORD_BODY=$(echo "$DISCORD_RESPONSE" | sed '$d')
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Step 5: Show Results
|
|
244
|
+
|
|
245
|
+
#### All tests passed:
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
249
|
+
│ ✅ {t.commands.testWebhooks.allPassed} │
|
|
250
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
251
|
+
│ │
|
|
252
|
+
│ 📁 Project: {projectName} │
|
|
253
|
+
│ │
|
|
254
|
+
│ ── Test Results ────────────────────────────────────────────────────────── │
|
|
255
|
+
│ │
|
|
256
|
+
│ 💬 Slack ✅ Test notification sent successfully │
|
|
257
|
+
│ 🎮 Discord ✅ Test notification sent successfully │
|
|
258
|
+
│ │
|
|
259
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
260
|
+
│ │ ✅ All 2 integrations working correctly │ │
|
|
261
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
262
|
+
│ │
|
|
263
|
+
│ Check your Slack and Discord channels to verify the messages arrived. │
|
|
264
|
+
│ │
|
|
265
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
266
|
+
│ │
|
|
267
|
+
│ 💡 {t.ui.labels.commands} │
|
|
268
|
+
│ • /pfSlack View Slack configuration │
|
|
269
|
+
│ • /pfDiscord View Discord configuration │
|
|
270
|
+
│ • /pfNotificationSettings Configure notification events │
|
|
271
|
+
│ │
|
|
272
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
273
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### Some tests failed:
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
280
|
+
│ ⚠️ {t.commands.testWebhooks.someFailed} │
|
|
281
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
282
|
+
│ │
|
|
283
|
+
│ 📁 Project: {projectName} │
|
|
284
|
+
│ │
|
|
285
|
+
│ ── Test Results ────────────────────────────────────────────────────────── │
|
|
286
|
+
│ │
|
|
287
|
+
│ 💬 Slack ✅ Test notification sent successfully │
|
|
288
|
+
│ 🎮 Discord ❌ Failed to send test notification │
|
|
289
|
+
│ │
|
|
290
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
291
|
+
│ │ ⚠️ 1 of 2 integrations failed │ │
|
|
292
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
293
|
+
│ │
|
|
294
|
+
│ ── Failed Integration Details ──────────────────────────────────────────── │
|
|
295
|
+
│ │
|
|
296
|
+
│ 🎮 Discord: │
|
|
297
|
+
│ • Webhook URL may be invalid or deleted │
|
|
298
|
+
│ • Webhook may have been removed from the channel │
|
|
299
|
+
│ • Discord API rate limiting │
|
|
300
|
+
│ │
|
|
301
|
+
│ 💡 Run /pfDiscord setup <new-url> to reconfigure │
|
|
302
|
+
│ │
|
|
303
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
304
|
+
│ │
|
|
305
|
+
│ 💡 {t.ui.labels.commands} │
|
|
306
|
+
│ • /pfSlack View Slack configuration │
|
|
307
|
+
│ • /pfDiscord View Discord configuration │
|
|
308
|
+
│ │
|
|
309
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
#### All tests failed:
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
316
|
+
│ ❌ {t.commands.testWebhooks.allFailed} │
|
|
317
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
318
|
+
│ │
|
|
319
|
+
│ 📁 Project: {projectName} │
|
|
320
|
+
│ │
|
|
321
|
+
│ ── Test Results ────────────────────────────────────────────────────────── │
|
|
322
|
+
│ │
|
|
323
|
+
│ 💬 Slack ❌ Failed to send test notification │
|
|
324
|
+
│ 🎮 Discord ❌ Failed to send test notification │
|
|
325
|
+
│ │
|
|
326
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
327
|
+
│ │ ❌ All integrations failed │ │
|
|
328
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
329
|
+
│ │
|
|
330
|
+
│ ── Possible Issues ─────────────────────────────────────────────────────── │
|
|
331
|
+
│ │
|
|
332
|
+
│ • Webhook URLs may be invalid or expired │
|
|
333
|
+
│ • Apps may have been removed from workspaces │
|
|
334
|
+
│ • Network connectivity issues │
|
|
335
|
+
│ • API rate limiting │
|
|
336
|
+
│ │
|
|
337
|
+
│ 💡 Reconfigure integrations: │
|
|
338
|
+
│ • /pfSlack setup <webhook-url> │
|
|
339
|
+
│ • /pfDiscord setup <webhook-url> │
|
|
340
|
+
│ │
|
|
341
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### Single integration test (Slack only):
|
|
345
|
+
|
|
346
|
+
```
|
|
347
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
348
|
+
│ ✅ {t.commands.testWebhooks.slackPassed} │
|
|
349
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
350
|
+
│ │
|
|
351
|
+
│ 📁 Project: {projectName} │
|
|
352
|
+
│ │
|
|
353
|
+
│ ── Slack Test ──────────────────────────────────────────────────────────── │
|
|
354
|
+
│ │
|
|
355
|
+
│ 💬 Slack ✅ Test notification sent successfully │
|
|
356
|
+
│ │
|
|
357
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
358
|
+
│ │ 🔔 PlanFlow Test │ │
|
|
359
|
+
│ │ This is a test notification from PlanFlow. │ │
|
|
360
|
+
│ │ If you see this, Slack integration is working correctly! │ │
|
|
361
|
+
│ │ Project: {projectName} │ │
|
|
362
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
363
|
+
│ │
|
|
364
|
+
│ Check your Slack channel to verify the message arrived. │
|
|
365
|
+
│ │
|
|
366
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
367
|
+
│ │
|
|
368
|
+
│ 💡 {t.ui.labels.commands} │
|
|
369
|
+
│ • /pfSlack View Slack configuration │
|
|
370
|
+
│ • /pfTestWebhooks Test all integrations │
|
|
371
|
+
│ │
|
|
372
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
373
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
#### Single integration not configured:
|
|
377
|
+
|
|
378
|
+
```
|
|
379
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
380
|
+
│ ⚠️ {t.commands.testWebhooks.notConfigured} │
|
|
381
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
382
|
+
│ │
|
|
383
|
+
│ 💬 Slack webhook is not configured for this project. │
|
|
384
|
+
│ │
|
|
385
|
+
│ 💡 Set up Slack first: │
|
|
386
|
+
│ /pfSlack setup <webhook-url> │
|
|
387
|
+
│ │
|
|
388
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Step 6: Verbose Mode
|
|
392
|
+
|
|
393
|
+
When `--verbose` flag is used, show additional details:
|
|
394
|
+
|
|
395
|
+
```
|
|
396
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
397
|
+
│ 🧪 {t.commands.testWebhooks.title} (Verbose) │
|
|
398
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
399
|
+
│ │
|
|
400
|
+
│ 📁 Project: {projectName} │
|
|
401
|
+
│ │
|
|
402
|
+
│ ── Test Results (Detailed) ─────────────────────────────────────────────── │
|
|
403
|
+
│ │
|
|
404
|
+
│ 💬 Slack │
|
|
405
|
+
│ Status: ✅ Success │
|
|
406
|
+
│ Response Time: 245ms │
|
|
407
|
+
│ Webhook: ···/services/T.../B.../XXX... │
|
|
408
|
+
│ HTTP Code: 200 │
|
|
409
|
+
│ Last Test: Just now │
|
|
410
|
+
│ │
|
|
411
|
+
│ 🎮 Discord │
|
|
412
|
+
│ Status: ✅ Success │
|
|
413
|
+
│ Response Time: 312ms │
|
|
414
|
+
│ Webhook: ···/webhooks/123.../XXX... │
|
|
415
|
+
│ HTTP Code: 204 │
|
|
416
|
+
│ Last Test: Just now │
|
|
417
|
+
│ │
|
|
418
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
419
|
+
│ │ ✅ All 2 integrations working correctly │ │
|
|
420
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
421
|
+
│ │
|
|
422
|
+
│ Total test time: 557ms │
|
|
423
|
+
│ │
|
|
424
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
425
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
### Error Handling
|
|
429
|
+
|
|
430
|
+
**Invalid Target:**
|
|
431
|
+
|
|
432
|
+
```
|
|
433
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
434
|
+
│ ❌ ERROR │
|
|
435
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
436
|
+
│ │
|
|
437
|
+
│ {t.commands.testWebhooks.invalidTarget} │
|
|
438
|
+
│ │
|
|
439
|
+
│ Unknown integration: "{target}" │
|
|
440
|
+
│ │
|
|
441
|
+
│ ── Valid Options ───────────────────────────────────────────────────────── │
|
|
442
|
+
│ │
|
|
443
|
+
│ • /pfTestWebhooks Test all configured webhooks │
|
|
444
|
+
│ • /pfTestWebhooks slack Test only Slack │
|
|
445
|
+
│ • /pfTestWebhooks discord Test only Discord │
|
|
446
|
+
│ • /pfTestWebhooks --verbose Show detailed results │
|
|
447
|
+
│ │
|
|
448
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
**Network Error:**
|
|
452
|
+
|
|
453
|
+
```
|
|
454
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
455
|
+
│ ❌ ERROR │
|
|
456
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
457
|
+
│ │
|
|
458
|
+
│ {t.commands.testWebhooks.networkError} │
|
|
459
|
+
│ │
|
|
460
|
+
│ Could not connect to PlanFlow API. │
|
|
461
|
+
│ │
|
|
462
|
+
│ Please check your internet connection and try again. │
|
|
463
|
+
│ │
|
|
464
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
## Translation Keys Required
|
|
468
|
+
|
|
469
|
+
Add these to `locales/en.json` and `locales/ka.json`:
|
|
470
|
+
|
|
471
|
+
**English:**
|
|
472
|
+
|
|
473
|
+
```json
|
|
474
|
+
{
|
|
475
|
+
"commands": {
|
|
476
|
+
"testWebhooks": {
|
|
477
|
+
"title": "Test Webhooks",
|
|
478
|
+
"testing": "Testing webhooks...",
|
|
479
|
+
"noIntegrations": "No Integrations Configured",
|
|
480
|
+
"allPassed": "All Tests Passed!",
|
|
481
|
+
"someFailed": "Some Tests Failed",
|
|
482
|
+
"allFailed": "All Tests Failed",
|
|
483
|
+
"slackPassed": "Slack Test Passed!",
|
|
484
|
+
"discordPassed": "Discord Test Passed!",
|
|
485
|
+
"slackFailed": "Slack Test Failed",
|
|
486
|
+
"discordFailed": "Discord Test Failed",
|
|
487
|
+
"notConfigured": "Integration Not Configured",
|
|
488
|
+
"invalidTarget": "Invalid integration target",
|
|
489
|
+
"networkError": "Network error",
|
|
490
|
+
"testSuccess": "Test notification sent successfully",
|
|
491
|
+
"testFailed": "Failed to send test notification",
|
|
492
|
+
"checkChannels": "Check your channels to verify the messages arrived.",
|
|
493
|
+
"reconfigure": "Reconfigure integrations:",
|
|
494
|
+
"possibleIssues": "Possible Issues",
|
|
495
|
+
"integrationDetails": "Integration Details",
|
|
496
|
+
"responseTime": "Response Time",
|
|
497
|
+
"httpCode": "HTTP Code",
|
|
498
|
+
"lastTest": "Last Test",
|
|
499
|
+
"totalTime": "Total test time",
|
|
500
|
+
"allWorking": "All {count} integrations working correctly",
|
|
501
|
+
"someWorking": "{passed} of {total} integrations working",
|
|
502
|
+
"noneWorking": "All integrations failed"
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
**Georgian:**
|
|
509
|
+
|
|
510
|
+
```json
|
|
511
|
+
{
|
|
512
|
+
"commands": {
|
|
513
|
+
"testWebhooks": {
|
|
514
|
+
"title": "Webhook-ების ტესტირება",
|
|
515
|
+
"testing": "Webhook-ების ტესტირება...",
|
|
516
|
+
"noIntegrations": "ინტეგრაციები არ არის კონფიგურებული",
|
|
517
|
+
"allPassed": "ყველა ტესტი წარმატებულია!",
|
|
518
|
+
"someFailed": "ზოგიერთი ტესტი წარუმატებელია",
|
|
519
|
+
"allFailed": "ყველა ტესტი წარუმატებელია",
|
|
520
|
+
"slackPassed": "Slack ტესტი წარმატებულია!",
|
|
521
|
+
"discordPassed": "Discord ტესტი წარმატებულია!",
|
|
522
|
+
"slackFailed": "Slack ტესტი წარუმატებელია",
|
|
523
|
+
"discordFailed": "Discord ტესტი წარუმატებელია",
|
|
524
|
+
"notConfigured": "ინტეგრაცია არ არის კონფიგურებული",
|
|
525
|
+
"invalidTarget": "არასწორი ინტეგრაციის სამიზნე",
|
|
526
|
+
"networkError": "ქსელის შეცდომა",
|
|
527
|
+
"testSuccess": "სატესტო შეტყობინება წარმატებით გაიგზავნა",
|
|
528
|
+
"testFailed": "სატესტო შეტყობინების გაგზავნა ვერ მოხერხდა",
|
|
529
|
+
"checkChannels": "შეამოწმეთ თქვენი არხები შეტყობინებების მისასვლელად.",
|
|
530
|
+
"reconfigure": "ხელახლა დააკონფიგურირეთ ინტეგრაციები:",
|
|
531
|
+
"possibleIssues": "შესაძლო პრობლემები",
|
|
532
|
+
"integrationDetails": "ინტეგრაციის დეტალები",
|
|
533
|
+
"responseTime": "პასუხის დრო",
|
|
534
|
+
"httpCode": "HTTP კოდი",
|
|
535
|
+
"lastTest": "ბოლო ტესტი",
|
|
536
|
+
"totalTime": "ტესტის ჯამური დრო",
|
|
537
|
+
"allWorking": "ყველა {count} ინტეგრაცია სწორად მუშაობს",
|
|
538
|
+
"someWorking": "{passed} / {total} ინტეგრაცია მუშაობს",
|
|
539
|
+
"noneWorking": "ყველა ინტეგრაცია წარუმატებელია"
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
## Complete Bash Implementation
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
#!/bin/bash
|
|
549
|
+
|
|
550
|
+
# Load configuration
|
|
551
|
+
API_URL="https://api.planflow.tools"
|
|
552
|
+
TOKEN="$API_TOKEN"
|
|
553
|
+
PROJECT_ID="$PROJECT_ID"
|
|
554
|
+
PROJECT_NAME="$PROJECT_NAME"
|
|
555
|
+
|
|
556
|
+
# Parse arguments
|
|
557
|
+
TARGET="${1:-all}"
|
|
558
|
+
VERBOSE=false
|
|
559
|
+
if [[ "$*" == *"--verbose"* ]] || [[ "$*" == *"-v"* ]]; then
|
|
560
|
+
VERBOSE=true
|
|
561
|
+
fi
|
|
562
|
+
|
|
563
|
+
# Determine what to test
|
|
564
|
+
TEST_SLACK=false
|
|
565
|
+
TEST_DISCORD=false
|
|
566
|
+
|
|
567
|
+
case "$TARGET" in
|
|
568
|
+
"all"|"--verbose"|"-v"|"")
|
|
569
|
+
TEST_SLACK=true
|
|
570
|
+
TEST_DISCORD=true
|
|
571
|
+
;;
|
|
572
|
+
"slack")
|
|
573
|
+
TEST_SLACK=true
|
|
574
|
+
;;
|
|
575
|
+
"discord")
|
|
576
|
+
TEST_DISCORD=true
|
|
577
|
+
;;
|
|
578
|
+
*)
|
|
579
|
+
echo "Invalid target: $TARGET"
|
|
580
|
+
echo "Valid options: all, slack, discord"
|
|
581
|
+
exit 1
|
|
582
|
+
;;
|
|
583
|
+
esac
|
|
584
|
+
|
|
585
|
+
# Fetch integration status
|
|
586
|
+
INTEGRATIONS=$(curl -s \
|
|
587
|
+
--connect-timeout 5 \
|
|
588
|
+
--max-time 10 \
|
|
589
|
+
-X GET \
|
|
590
|
+
-H "Accept: application/json" \
|
|
591
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
592
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations")
|
|
593
|
+
|
|
594
|
+
# Parse integration status
|
|
595
|
+
SLACK_ENABLED=$(echo "$INTEGRATIONS" | grep -o '"slack":{[^}]*"enabled":true' | wc -l)
|
|
596
|
+
DISCORD_ENABLED=$(echo "$INTEGRATIONS" | grep -o '"discord":{[^}]*"enabled":true' | wc -l)
|
|
597
|
+
|
|
598
|
+
# Initialize results
|
|
599
|
+
SLACK_RESULT=""
|
|
600
|
+
DISCORD_RESULT=""
|
|
601
|
+
PASSED=0
|
|
602
|
+
FAILED=0
|
|
603
|
+
TOTAL=0
|
|
604
|
+
|
|
605
|
+
# Test Slack if requested and enabled
|
|
606
|
+
if [ "$TEST_SLACK" = true ]; then
|
|
607
|
+
if [ "$SLACK_ENABLED" -gt 0 ]; then
|
|
608
|
+
TOTAL=$((TOTAL + 1))
|
|
609
|
+
START_TIME=$(date +%s%3N)
|
|
610
|
+
|
|
611
|
+
SLACK_RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
612
|
+
--connect-timeout 5 \
|
|
613
|
+
--max-time 15 \
|
|
614
|
+
-X POST \
|
|
615
|
+
-H "Content-Type: application/json" \
|
|
616
|
+
-H "Accept: application/json" \
|
|
617
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
618
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations/slack/test")
|
|
619
|
+
|
|
620
|
+
END_TIME=$(date +%s%3N)
|
|
621
|
+
SLACK_TIME=$((END_TIME - START_TIME))
|
|
622
|
+
|
|
623
|
+
SLACK_HTTP=$(echo "$SLACK_RESPONSE" | tail -n1)
|
|
624
|
+
|
|
625
|
+
if [ "$SLACK_HTTP" -ge 200 ] && [ "$SLACK_HTTP" -lt 300 ]; then
|
|
626
|
+
SLACK_RESULT="success"
|
|
627
|
+
PASSED=$((PASSED + 1))
|
|
628
|
+
else
|
|
629
|
+
SLACK_RESULT="failed"
|
|
630
|
+
FAILED=$((FAILED + 1))
|
|
631
|
+
fi
|
|
632
|
+
else
|
|
633
|
+
SLACK_RESULT="not_configured"
|
|
634
|
+
fi
|
|
635
|
+
fi
|
|
636
|
+
|
|
637
|
+
# Test Discord if requested and enabled
|
|
638
|
+
if [ "$TEST_DISCORD" = true ]; then
|
|
639
|
+
if [ "$DISCORD_ENABLED" -gt 0 ]; then
|
|
640
|
+
TOTAL=$((TOTAL + 1))
|
|
641
|
+
START_TIME=$(date +%s%3N)
|
|
642
|
+
|
|
643
|
+
DISCORD_RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
644
|
+
--connect-timeout 5 \
|
|
645
|
+
--max-time 15 \
|
|
646
|
+
-X POST \
|
|
647
|
+
-H "Content-Type: application/json" \
|
|
648
|
+
-H "Accept: application/json" \
|
|
649
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
650
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations/discord/test")
|
|
651
|
+
|
|
652
|
+
END_TIME=$(date +%s%3N)
|
|
653
|
+
DISCORD_TIME=$((END_TIME - START_TIME))
|
|
654
|
+
|
|
655
|
+
DISCORD_HTTP=$(echo "$DISCORD_RESPONSE" | tail -n1)
|
|
656
|
+
|
|
657
|
+
if [ "$DISCORD_HTTP" -ge 200 ] && [ "$DISCORD_HTTP" -lt 300 ]; then
|
|
658
|
+
DISCORD_RESULT="success"
|
|
659
|
+
PASSED=$((PASSED + 1))
|
|
660
|
+
else
|
|
661
|
+
DISCORD_RESULT="failed"
|
|
662
|
+
FAILED=$((FAILED + 1))
|
|
663
|
+
fi
|
|
664
|
+
else
|
|
665
|
+
DISCORD_RESULT="not_configured"
|
|
666
|
+
fi
|
|
667
|
+
fi
|
|
668
|
+
|
|
669
|
+
# Output results
|
|
670
|
+
echo "Project: $PROJECT_NAME"
|
|
671
|
+
echo ""
|
|
672
|
+
echo "Test Results:"
|
|
673
|
+
|
|
674
|
+
if [ "$TEST_SLACK" = true ]; then
|
|
675
|
+
case "$SLACK_RESULT" in
|
|
676
|
+
"success")
|
|
677
|
+
echo " Slack ✅ Test notification sent successfully"
|
|
678
|
+
;;
|
|
679
|
+
"failed")
|
|
680
|
+
echo " Slack ❌ Failed to send test notification"
|
|
681
|
+
;;
|
|
682
|
+
"not_configured")
|
|
683
|
+
echo " Slack ⚪ Not configured"
|
|
684
|
+
;;
|
|
685
|
+
esac
|
|
686
|
+
fi
|
|
687
|
+
|
|
688
|
+
if [ "$TEST_DISCORD" = true ]; then
|
|
689
|
+
case "$DISCORD_RESULT" in
|
|
690
|
+
"success")
|
|
691
|
+
echo " Discord ✅ Test notification sent successfully"
|
|
692
|
+
;;
|
|
693
|
+
"failed")
|
|
694
|
+
echo " Discord ❌ Failed to send test notification"
|
|
695
|
+
;;
|
|
696
|
+
"not_configured")
|
|
697
|
+
echo " Discord ⚪ Not configured"
|
|
698
|
+
;;
|
|
699
|
+
esac
|
|
700
|
+
fi
|
|
701
|
+
|
|
702
|
+
echo ""
|
|
703
|
+
if [ "$TOTAL" -eq 0 ]; then
|
|
704
|
+
echo "No integrations configured to test."
|
|
705
|
+
elif [ "$FAILED" -eq 0 ]; then
|
|
706
|
+
echo "✅ All $TOTAL integrations working correctly"
|
|
707
|
+
elif [ "$PASSED" -gt 0 ]; then
|
|
708
|
+
echo "⚠️ $PASSED of $TOTAL integrations working"
|
|
709
|
+
else
|
|
710
|
+
echo "❌ All integrations failed"
|
|
711
|
+
fi
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
## Notes
|
|
715
|
+
|
|
716
|
+
- Tests both Slack and Discord webhooks in a single command
|
|
717
|
+
- Supports testing individual integrations with `slack` or `discord` argument
|
|
718
|
+
- Shows clear success/failure status for each integration
|
|
719
|
+
- Provides troubleshooting hints for failed tests
|
|
720
|
+
- Verbose mode shows response times and HTTP codes
|
|
721
|
+
- Gracefully handles non-configured integrations
|
|
722
|
+
- Uses parallel requests when testing all integrations (for speed)
|