331 lines
12 KiB
Markdown
331 lines
12 KiB
Markdown
---
|
|
phase: 11-update-all-callback-limits
|
|
plan: 02
|
|
type: execute
|
|
wave: 2
|
|
depends_on: ["11-01"]
|
|
files_modified:
|
|
- n8n-status.json
|
|
- n8n-workflow.json
|
|
autonomous: false
|
|
|
|
must_haves:
|
|
truths:
|
|
- "User can tap 'Update All :latest' button in container list inline keyboard"
|
|
- "Tapping the button shows a confirmation dialog listing all :latest containers"
|
|
- "User can type 'update all' to trigger the same confirmation flow"
|
|
- "Confirming update-all triggers batch update execution for all :latest containers"
|
|
artifacts:
|
|
- path: "n8n-status.json"
|
|
provides: "Container list keyboard with Update All button"
|
|
contains: "uall:start"
|
|
- path: "n8n-workflow.json"
|
|
provides: "uall:start callback routing to existing update-all flow"
|
|
contains: "isUpdateAllStart"
|
|
key_links:
|
|
- from: "n8n-status.json Build Container List"
|
|
to: "Telegram inline keyboard"
|
|
via: "uall:start callback_data button"
|
|
pattern: "uall:start"
|
|
- from: "n8n-workflow.json Parse Callback Data"
|
|
to: "n8n-workflow.json Route Callback"
|
|
via: "isUpdateAllStart flag"
|
|
pattern: "isUpdateAllStart"
|
|
- from: "n8n-workflow.json Route Callback"
|
|
to: "n8n-workflow.json Get All Containers For Update All"
|
|
via: "updateallstart route"
|
|
pattern: "updateallstart"
|
|
---
|
|
|
|
<objective>
|
|
Add "Update All :latest" inline keyboard button to the container list and wire its callback to the existing update-all confirmation flow. Then deploy all modified workflows and verify end-to-end functionality.
|
|
|
|
Purpose: BATCH-05 requires inline keyboard entry point for update-all. The text command path (BATCH-04) already works. This plan adds the inline button, routes its callback to the existing confirmation flow, deploys all changes (including Plan 01's bitmap encoding), and verifies everything works.
|
|
|
|
Output: Modified n8n-status.json with Update All button, modified n8n-workflow.json with uall:start routing, all workflows deployed and verified.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/home/luc/.claude/get-shit-done/workflows/execute-plan.md
|
|
@/home/luc/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/PROJECT.md
|
|
@.planning/ROADMAP.md
|
|
@.planning/STATE.md
|
|
@.planning/phases/11-update-all-callback-limits/11-01-SUMMARY.md
|
|
@n8n-status.json
|
|
@n8n-workflow.json
|
|
@CLAUDE.md
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Add Update All button to container list and wire callback routing</name>
|
|
<files>n8n-status.json, n8n-workflow.json</files>
|
|
<action>
|
|
**1. n8n-status.json -- Build Container List node:**
|
|
|
|
Add an "Update All :latest" button row to the container list keyboard. Place it AFTER the navigation row and BEFORE the "Select Multiple" button. This button should appear on EVERY page of the container list.
|
|
|
|
In the Build Container List code node, after the navigation row block and before the "Select Multiple" button, add:
|
|
|
|
```javascript
|
|
// Add Update All button
|
|
keyboard.push([{
|
|
text: '\u{1F504} Update All :latest',
|
|
callback_data: 'uall:start'
|
|
}]);
|
|
```
|
|
|
|
The callback_data `uall:start` is only 10 bytes, well within the 64-byte limit.
|
|
|
|
Also add the same button to the Build Paginated List code node (used when paginating from an existing list view), in the same position relative to nav and Select Multiple.
|
|
|
|
Do NOT add to Build Container Submenu -- that is for single container actions only.
|
|
|
|
**2. n8n-workflow.json -- Parse Callback Data node:**
|
|
|
|
Add a parser for `uall:start` callback. Place it near the existing `uall:confirm` and `uall:cancel` parsers:
|
|
|
|
```javascript
|
|
if (rawData === 'uall:start') {
|
|
return {
|
|
json: {
|
|
queryId,
|
|
chatId,
|
|
messageId,
|
|
isUpdateAllStart: true,
|
|
isSelect: false,
|
|
isList: false,
|
|
isAction: false,
|
|
isCancel: false,
|
|
isBatch: false,
|
|
isConfirm: false,
|
|
expired: false
|
|
}
|
|
};
|
|
}
|
|
```
|
|
|
|
**3. n8n-workflow.json -- Route Callback switch node:**
|
|
|
|
Add a new rule for `isUpdateAllStart` that routes to the update-all flow. Insert after the existing `updateallcancel` rule (index 1), before the `cancel` rule:
|
|
|
|
```json
|
|
{
|
|
"id": "is-update-all-start",
|
|
"conditions": {
|
|
"options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
|
|
"conditions": [{
|
|
"id": "update-all-start-true",
|
|
"leftValue": "={{ $json.isUpdateAllStart }}",
|
|
"rightValue": true,
|
|
"operator": { "type": "boolean", "operation": "equals" }
|
|
}],
|
|
"combinator": "and"
|
|
},
|
|
"renameOutput": true,
|
|
"outputKey": "updateallstart"
|
|
}
|
|
```
|
|
|
|
**4. n8n-workflow.json -- Add Answer Update All Start node:**
|
|
|
|
Add a new Telegram answerCallbackQuery node to acknowledge the button press before fetching containers. Use the same pattern as existing Answer nodes (e.g., Answer Batch UI Keyboard):
|
|
|
|
```json
|
|
{
|
|
"name": "Answer Update All Start",
|
|
"type": "n8n-nodes-base.telegram",
|
|
"typeVersion": 1.2,
|
|
"parameters": {
|
|
"operation": "callback",
|
|
"callbackQueryId": "={{ $json.queryId }}",
|
|
"additionalFields": {
|
|
"text": "Checking for updates..."
|
|
}
|
|
},
|
|
"credentials": {
|
|
"telegramApi": {
|
|
"id": "I0xTTiASl7C1NZhJ",
|
|
"name": "Telegram account"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Wire: Route Callback [updateallstart output] -> Answer Update All Start -> Get All Containers For Update All
|
|
|
|
**5. n8n-workflow.json -- Fix Check Available Updates for dual origin:**
|
|
|
|
The Check Available Updates code node currently reads chatId from `$('Keyword Router').first().json.message.chat.id` which fails when coming from the callback path. Update it to handle both origins:
|
|
|
|
```javascript
|
|
let chatId, messageId;
|
|
try {
|
|
const kwData = $('Keyword Router').first().json;
|
|
chatId = kwData.message.chat.id;
|
|
messageId = kwData.message.message_id;
|
|
} catch(e) {
|
|
// Inline keyboard origin -- data from Parse Callback Data
|
|
const cbData = $('Parse Callback Data').first().json;
|
|
chatId = cbData.chatId;
|
|
messageId = cbData.messageId;
|
|
}
|
|
```
|
|
|
|
Keep the rest of the Check Available Updates logic unchanged (container filtering, :latest detection).
|
|
|
|
**6. Update connections in Route Callback:**
|
|
|
|
Add the new output connection at the correct index in the Route Callback connections array. The new `updateallstart` rule is inserted at index 2, so all existing connection indices after position 1 shift by 1. The new index 2 connection targets Answer Update All Start.
|
|
|
|
**Summary of changes:**
|
|
- n8n-status.json: Add `uall:start` button to Build Container List and Build Paginated List
|
|
- n8n-workflow.json: Add `uall:start` parser to Parse Callback Data
|
|
- n8n-workflow.json: Add `updateallstart` rule to Route Callback (index 2, shifting existing rules)
|
|
- n8n-workflow.json: Add "Answer Update All Start" Telegram node
|
|
- n8n-workflow.json: Wire Route Callback [updateallstart] -> Answer Update All Start -> Get All Containers For Update All
|
|
- n8n-workflow.json: Fix Check Available Updates to support callback origin (try/catch for Keyword Router)
|
|
- n8n-workflow.json: Update connections array for Route Callback to include the new output
|
|
</action>
|
|
<verify>
|
|
1. `python3 -c "import json; wf=json.load(open('n8n-status.json')); [print(n['name']) for n in wf['nodes']]"` shows same 11 nodes
|
|
2. Build Container List code contains `uall:start`
|
|
3. `python3 -c "import json; wf=json.load(open('n8n-workflow.json')); print(len(wf['nodes']), 'nodes')"` shows 172 nodes (171 from Plan 01 + 1 Answer Update All Start)
|
|
4. Parse Callback Data contains `uall:start` parser
|
|
5. Route Callback has `updateallstart` rule
|
|
6. Connections exist: Route Callback -> Answer Update All Start -> Get All Containers For Update All
|
|
</verify>
|
|
<done>
|
|
Container list keyboard shows "Update All :latest" button. Tapping it answers the callback, fetches containers, filters :latest, shows confirmation dialog. Existing confirmation/cancel/expired flows handle the rest. Check Available Updates works for both text and callback origins.
|
|
</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Deploy all workflows to n8n and run smoke test</name>
|
|
<files>n8n-batch-ui.json, n8n-status.json, n8n-workflow.json</files>
|
|
<action>
|
|
Push all 3 modified workflow files to n8n using the push_workflow recipe from CLAUDE.md:
|
|
|
|
```bash
|
|
. .env.n8n-api
|
|
|
|
push_workflow() {
|
|
local FILE=$1 WF_ID=$2 WF_NAME=$3
|
|
python3 -c "
|
|
import json
|
|
with open('$FILE') as f:
|
|
wf = json.load(f)
|
|
payload = {'name': wf.get('name', '$WF_NAME'), 'nodes': wf['nodes'], 'connections': wf['connections'], 'settings': wf.get('settings', {})}
|
|
if wf.get('staticData'): payload['staticData'] = wf['staticData']
|
|
with open('/tmp/n8n-push-payload.json', 'w') as f:
|
|
json.dump(payload, f)
|
|
"
|
|
local CODE=$(curl -s -o /tmp/n8n-push-result.txt -w "%{http_code}" \
|
|
-X PUT "${N8N_HOST}/api/v1/workflows/${WF_ID}" \
|
|
-H "X-N8N-API-KEY: ${N8N_API_KEY}" \
|
|
-H "Content-Type: application/json" \
|
|
-d @/tmp/n8n-push-payload.json)
|
|
echo " ${WF_NAME}: HTTP ${CODE}"
|
|
}
|
|
|
|
push_workflow "n8n-workflow.json" "HmiXBlJefBRPMS0m4iNYc" "Main"
|
|
push_workflow "n8n-batch-ui.json" "ZJhnGzJT26UUmW45" "Batch UI"
|
|
push_workflow "n8n-status.json" "lqpg2CqesnKE2RJQ" "Status"
|
|
```
|
|
|
|
All three should return HTTP 200.
|
|
|
|
After deployment, verify the main workflow is still active:
|
|
```bash
|
|
. .env.n8n-api; curl -s -o /tmp/n8n-result.txt -w "%{http_code}" \
|
|
"${N8N_HOST}/api/v1/workflows/HmiXBlJefBRPMS0m4iNYc" \
|
|
-H "X-N8N-API-KEY: ${N8N_API_KEY}" \
|
|
&& python3 -c "
|
|
import json
|
|
with open('/tmp/n8n-result.txt') as f:
|
|
wf = json.load(f)
|
|
print(f'Active: {wf[\"active\"]}')
|
|
print(f'Nodes: {len(wf[\"nodes\"])}')
|
|
"
|
|
```
|
|
|
|
If not active, activate:
|
|
```bash
|
|
. .env.n8n-api; curl -s -X POST "${N8N_HOST}/api/v1/workflows/HmiXBlJefBRPMS0m4iNYc/activate" \
|
|
-H "X-N8N-API-KEY: ${N8N_API_KEY}"
|
|
```
|
|
</action>
|
|
<verify>All three workflows deploy with HTTP 200. Main workflow is active.</verify>
|
|
<done>All modified workflows pushed to n8n. Main workflow active and running.</done>
|
|
</task>
|
|
|
|
<task type="checkpoint:human-verify" gate="blocking">
|
|
<name>Task 3: User acceptance testing of all Phase 11 features</name>
|
|
<action>
|
|
User verifies all four BATCH requirements via Telegram bot interaction. See verification steps below.
|
|
</action>
|
|
<verify>
|
|
**Test 1 - Batch selection with 5+ containers (BATCH-06):**
|
|
1. Send "status" to the bot
|
|
2. Tap "Select Multiple" in the container list
|
|
3. Select 5 or more containers by tapping them (checkmarks should appear)
|
|
4. Verify you can navigate pages while selection is preserved
|
|
5. Expected: All selections work, no "Maximum selection reached" errors
|
|
|
|
**Test 2 - Long container names (BATCH-07):**
|
|
1. In batch selection mode, select containers with names 20+ characters
|
|
2. Expected: Selection works without errors
|
|
|
|
**Test 3 - Batch execution:**
|
|
1. Select 2-3 containers in batch mode
|
|
2. Tap "Start (N)" or "Stop (N)"
|
|
3. Expected: Stop shows confirmation, Start executes immediately
|
|
4. Verify the actions complete successfully
|
|
|
|
**Test 4 - Update All from keyboard (BATCH-05):**
|
|
1. Send "status" to the bot
|
|
2. Look for "Update All :latest" button below the container list
|
|
3. Tap the button
|
|
4. Expected: Confirmation dialog showing :latest containers with Confirm/Cancel buttons
|
|
5. Tap Cancel to verify cancel works
|
|
|
|
**Test 5 - Update All from text (BATCH-04):**
|
|
1. Send "update all" to the bot
|
|
2. Expected: Same confirmation dialog as Test 4
|
|
|
|
**Test 6 - Regression: single container actions:**
|
|
1. Send "status", tap a container, tap Stop/Start/Restart
|
|
2. Expected: All actions work as before
|
|
</verify>
|
|
<done>All six test scenarios pass. BATCH-04 through BATCH-07 requirements satisfied. No regressions in existing functionality.</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
1. All four success criteria from ROADMAP met:
|
|
- User can type "update all" (BATCH-04, pre-existing + verified)
|
|
- User can tap "Update All" in keyboard (BATCH-05, new button + routing)
|
|
- Batch selection supports 5+ containers (BATCH-06, bitmap encoding)
|
|
- Long container names work (BATCH-07, bitmap encoding)
|
|
2. No regression to existing functionality (single actions, batch stop/start, pagination, etc.)
|
|
3. All workflows deployed and active in n8n
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
- Container list inline keyboard shows "Update All :latest" button
|
|
- Tapping the button triggers confirmation dialog with :latest container list
|
|
- Batch selection works with 5+ containers (no callback limit error)
|
|
- Containers with long names selectable in batch mode
|
|
- All existing bot functionality unaffected
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/11-update-all-callback-limits/11-02-SUMMARY.md`
|
|
</output>
|