From e593dbf6622495d0a744ae6ccfc2c27e9c260511 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Tue, 3 Mar 2026 12:52:29 -0600 Subject: [PATCH] ci: use Portainer API instead of SSH for deploy - Replaces SSH-based deploy with Portainer API call - Uses POST /api/stacks/{id}/git/redeploy endpoint - Requires PORTAINER_URL and PORTAINER_API_KEY secrets in Woodpecker --- .woodpecker/ci.yml | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/.woodpecker/ci.yml b/.woodpecker/ci.yml index 5b4f9f5..c43439b 100644 --- a/.woodpecker/ci.yml +++ b/.woodpecker/ci.yml @@ -338,41 +338,43 @@ steps: - security-trivy-orchestrator - security-trivy-web - # ─── Deploy to Docker Swarm (main only) ───────────────────── - - # ─── Deploy to Docker Swarm via Portainer (main only) ───────────────────── + # ─── Deploy to Docker Swarm via Portainer API (main only) ───────────────────── deploy-swarm: image: alpine:3 environment: - SSH_PRIVATE_KEY: - from_secret: ssh_private_key - SSH_KNOWN_HOSTS: - from_secret: ssh_known_hosts PORTAINER_URL: from_secret: portainer_url PORTAINER_API_KEY: from_secret: portainer_api_key + PORTAINER_STACK_ID: "121" commands: - - apk add --no-cache curl openssh-client + - apk add --no-cache curl - | set -e - echo "🚀 Deploying to Docker Swarm..." + echo "🚀 Deploying to Docker Swarm via Portainer API..." - # Setup SSH for fallback - mkdir -p ~/.ssh - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts - chmod 600 ~/.ssh/known_hosts - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519 - chmod 600 ~/.ssh/id_ed25519 + # Use Portainer API to update the stack (forces pull of new images) + RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \ + -H "X-API-Key: $PORTAINER_API_KEY" \ + -H "Content-Type: application/json" \ + "$PORTAINER_URL/api/stacks/$PORTAINER_STACK_ID/git/redeploy") - # Force service updates (images are pulled from public registry) - ssh -o StrictHostKeyChecking=no localadmin@10.1.1.45 \ - "docker service update --with-registry-auth --force mosaic-stack-api && \ - docker service update --with-registry-auth --force mosaic-stack-web && \ - docker service update --with-registry-auth --force mosaic-stack-orchestrator && \ - docker service update --with-registry-auth --force mosaic-stack-coordinator && \ - echo '✅ All services updated'" + HTTP_CODE=$(echo "$RESPONSE" | tail -1) + BODY=$(echo "$RESPONSE" | head -n -1) + + if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "202" ]; then + echo "✅ Stack update triggered successfully" + else + echo "❌ Stack update failed (HTTP $HTTP_CODE)" + echo "$BODY" + exit 1 + fi + + # Wait for services to converge + echo "⏳ Waiting for services to converge..." + sleep 30 + echo "✅ Deploy complete" when: - branch: [main] event: [push, manual, tag]