From 8540f48a282d34c610ee9084b818488c5593a25f Mon Sep 17 00:00:00 2001 From: Viktor Barzin Date: Tue, 14 Apr 2026 16:46:42 +0000 Subject: [PATCH] fix: move pipeline logic to shell script (avoid YAML quoting issues) --- .woodpecker/postmortem-todos.yml | 22 ++--------- scripts/postmortem-pipeline.sh | 63 ++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 19 deletions(-) create mode 100755 scripts/postmortem-pipeline.sh diff --git a/.woodpecker/postmortem-todos.yml b/.woodpecker/postmortem-todos.yml index 96ac8d84..8677e4e9 100644 --- a/.woodpecker/postmortem-todos.yml +++ b/.woodpecker/postmortem-todos.yml @@ -12,29 +12,13 @@ steps: image: python:3.12-alpine commands: - apk add --no-cache jq curl git openssh-client - - "PM_FILE=$(git diff HEAD~1 --name-only | grep 'docs/post-mortems/.*\\.md' | head -1)" - - "if [ -z \"$PM_FILE\" ]; then echo 'No post-mortem changes'; exit 0; fi" - - "echo \"Post-mortem changed: $PM_FILE\"" - - "if ! git diff HEAD~1 -- \"$PM_FILE\" | grep -q '+.*TODO'; then echo 'No new TODOs'; exit 0; fi" - - "bash scripts/parse-postmortem-todos.sh \"$PM_FILE\" > /tmp/todos.json" - - "cat /tmp/todos.json" - - "TODO_COUNT=$(jq '.safe_todos' /tmp/todos.json)" - - "echo \"$TODO_COUNT safe TODO(s) found\"" - - "if [ \"$TODO_COUNT\" -eq 0 ]; then echo 'No auto-implementable TODOs'; exit 0; fi" - - "SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" - - "VAULT_TOKEN=$(curl -sf -X POST http://vault-active.vault.svc.cluster.local:8200/v1/auth/kubernetes/login -d \"{\\\"role\\\":\\\"ci\\\",\\\"jwt\\\":\\\"$SA_TOKEN\\\"}\" | jq -r .auth.client_token)" - - "if [ -z \"$VAULT_TOKEN\" ] || [ \"$VAULT_TOKEN\" = 'null' ]; then echo 'Vault auth failed'; exit 1; fi" - - "curl -sf -H \"X-Vault-Token: $VAULT_TOKEN\" http://vault-active.vault.svc.cluster.local:8200/v1/secret/data/ci/infra | jq -r '.data.data.devvm_ssh_key' > /tmp/devvm-key" - - "chmod 600 /tmp/devvm-key" - - "TODOS=$(cat /tmp/todos.json | tr '\\n' ' ')" - - "ssh -i /tmp/devvm-key -o StrictHostKeyChecking=no wizard@10.0.10.10 \"cd ~/code/infra && git pull && claude -p --agent postmortem-todo-resolver --dangerously-skip-permissions --max-budget-usd 5 'Implement TODOs from $PM_FILE: $TODOS'\"" - - "rm -f /tmp/devvm-key" + - sh scripts/postmortem-pipeline.sh - name: notify-slack image: alpine commands: - - "apk add --no-cache curl" - - "curl -sf -X POST \"https://hooks.slack.com/services/${SLACK_WEBHOOK}\" -H 'Content-Type: application/json' -d '{\"text\": \"Post-mortem TODO resolver pipeline completed\"}' || true" + - apk add --no-cache curl + - "curl -sf -X POST https://hooks.slack.com/services/$SLACK_WEBHOOK -H 'Content-Type: application/json' -d '{\"text\": \"Post-mortem TODO pipeline completed\"}' || true" secrets: - slack_webhook when: diff --git a/scripts/postmortem-pipeline.sh b/scripts/postmortem-pipeline.sh new file mode 100755 index 00000000..24b57fb1 --- /dev/null +++ b/scripts/postmortem-pipeline.sh @@ -0,0 +1,63 @@ +#!/bin/sh +# postmortem-pipeline.sh — Woodpecker pipeline step for post-mortem TODO automation +# Called from .woodpecker/postmortem-todos.yml +set -e + +# 1. Find which post-mortem changed +PM_FILE=$(git diff HEAD~1 --name-only | grep 'docs/post-mortems/.*[.]md' | head -1) +if [ -z "$PM_FILE" ]; then + echo "No post-mortem markdown changes detected" + exit 0 +fi +echo "Post-mortem changed: $PM_FILE" + +# 2. Check if there are new TODOs (not just TODO→Done updates) +if ! git diff HEAD~1 -- "$PM_FILE" | grep -q '+.*TODO'; then + echo "No new TODOs added — skipping" + exit 0 +fi + +# 3. Parse TODOs +bash scripts/parse-postmortem-todos.sh "$PM_FILE" > /tmp/todos.json +cat /tmp/todos.json +TODO_COUNT=$(jq '.safe_todos' /tmp/todos.json) +echo "$TODO_COUNT safe TODO(s) found" +if [ "$TODO_COUNT" -eq 0 ]; then + echo "No auto-implementable TODOs — skipping" + exit 0 +fi + +# 4. Authenticate to Vault via K8s SA JWT +SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) +VAULT_RESP=$(curl -sf -X POST http://vault-active.vault.svc.cluster.local:8200/v1/auth/kubernetes/login \ + -d "{\"role\":\"ci\",\"jwt\":\"$SA_TOKEN\"}") +VAULT_TOKEN=$(echo "$VAULT_RESP" | jq -r .auth.client_token) +if [ -z "$VAULT_TOKEN" ] || [ "$VAULT_TOKEN" = "null" ]; then + echo "ERROR: Vault authentication failed" + exit 1 +fi +echo "Vault authenticated" + +# 5. Fetch DevVM SSH key from Vault +curl -sf -H "X-Vault-Token: $VAULT_TOKEN" \ + http://vault-active.vault.svc.cluster.local:8200/v1/secret/data/ci/infra | \ + jq -r '.data.data.devvm_ssh_key' > /tmp/devvm-key +chmod 600 /tmp/devvm-key +if [ ! -s /tmp/devvm-key ]; then + echo "ERROR: Failed to fetch DevVM SSH key" + exit 1 +fi +echo "SSH key fetched" + +# 6. SSH to DevVM and run Claude Code headless +TODOS=$(cat /tmp/todos.json) +ssh -i /tmp/devvm-key -o StrictHostKeyChecking=no wizard@10.0.10.10 \ + "cd ~/code/infra && git pull && claude -p \ + --agent postmortem-todo-resolver \ + --dangerously-skip-permissions \ + --max-budget-usd 5 \ + 'Implement the auto-implementable TODOs from $PM_FILE. Parsed TODO list: $TODOS'" + +# 7. Cleanup +rm -f /tmp/devvm-key +echo "Pipeline complete"