# Woodpecker CI Configuration for better-argo-tunnels # # SYNTAX NOTES: # - Environment variables from secrets MUST use $${VAR} syntax (double dollar) # - Single $ will be interpreted literally and won't expand variables labels: location: manager clone: git: image: woodpeckerci/plugin-git settings: partial: false depth: 1 steps: # Build and test Go binaries test: name: test image: golang:1.24-alpine commands: - go version | cat - go vet ./... - go build ./cmd/server/ - go build ./cmd/client/ - echo "Build and vet passed" when: branch: main event: [push, pull_request] # Build and Push Docker images for production (x86) build-push-production: name: build-push-production image: woodpeckerci/plugin-docker-buildx depends_on: ["test"] environment: REGISTRY_USER: from_secret: REGISTRY_USER REGISTRY_PASSWORD: from_secret: REGISTRY_PASSWORD volumes: - /var/run/docker.sock:/var/run/docker.sock commands: - echo "nameserver 1.1.1.1" > /etc/resolv.conf - echo "nameserver 1.0.0.1" >> /etc/resolv.conf - HOSTNAME=$(docker info --format "{{.Name}}") - echo "Building on $HOSTNAME" - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us - apk add --no-cache git || true - export GIT_COMMIT=$${CI_COMMIT_SHA} - export GIT_COMMIT_DATE=$(git log -1 --format=%ci HEAD 2>/dev/null || echo "unknown") - echo "Building GIT_COMMIT=$GIT_COMMIT" # Build server image - docker build --target server -t git.nixc.us/colin/better-argo-tunnels:production . - docker push git.nixc.us/colin/better-argo-tunnels:production # Build client image - docker build --target client -t git.nixc.us/colin/better-argo-tunnels:client-production . - docker push git.nixc.us/colin/better-argo-tunnels:client-production when: branch: main event: [push, cron] # Smoke test - verify server binary starts smoke-production: name: smoke-production image: woodpeckerci/plugin-docker-buildx depends_on: ["build-push-production"] environment: REGISTRY_USER: from_secret: REGISTRY_USER REGISTRY_PASSWORD: from_secret: REGISTRY_PASSWORD volumes: - /var/run/docker.sock:/var/run/docker.sock commands: - echo "nameserver 1.1.1.1" > /etc/resolv.conf - echo "nameserver 1.0.0.1" >> /etc/resolv.conf - echo "$${REGISTRY_PASSWORD}" | docker login git.nixc.us -u "$${REGISTRY_USER}" --password-stdin - docker pull git.nixc.us/colin/better-argo-tunnels:production - docker rm -f tunnel-smoke || true # Smoke: just verify the binary runs and prints startup log - mkdir -p /tmp/smoke-keys - ssh-keygen -t ed25519 -f /tmp/smoke-keys/host_key -N "" -q - ssh-keygen -t ed25519 -f /tmp/smoke-keys/client_key -N "" -q - cat /tmp/smoke-keys/client_key.pub > /tmp/smoke-keys/authorized_keys - | docker run -d --name tunnel-smoke \ -e SSH_PORT=2222 \ -e SSH_HOST_KEY=/keys/host_key \ -e AUTHORIZED_KEYS=/keys/authorized_keys \ -e TRAEFIK_SSH_HOST=127.0.0.1 \ -e TRAEFIK_SSH_KEY=/keys/host_key \ -e TRAEFIK_CONFIG_DIR=/tmp/dynamic \ -v /tmp/smoke-keys:/keys:ro \ git.nixc.us/colin/better-argo-tunnels:production - sleep 3 - docker logs tunnel-smoke 2>&1 | head -20 - docker rm -f tunnel-smoke || true - rm -rf /tmp/smoke-keys - echo "Smoke test passed" when: branch: main event: [push, cron] # Deploy to Swarm deploy-production: name: deploy-production image: woodpeckerci/plugin-docker-buildx depends_on: ["test", "build-push-production", "smoke-production"] environment: REGISTRY_USER: from_secret: REGISTRY_USER REGISTRY_PASSWORD: from_secret: REGISTRY_PASSWORD TUNNEL_SSH_HOST_KEY: from_secret: tunnel_ssh_host_key TUNNEL_AUTHORIZED_KEYS: from_secret: tunnel_authorized_keys TUNNEL_TRAEFIK_DEPLOY_KEY: from_secret: tunnel_traefik_deploy_key volumes: - /var/run/docker.sock:/var/run/docker.sock commands: - echo "nameserver 1.1.1.1" > /etc/resolv.conf - echo "nameserver 1.0.0.1" >> /etc/resolv.conf - HOSTNAME=$(docker info --format "{{.Name}}") - echo "Deploying on $HOSTNAME" - echo "$${REGISTRY_PASSWORD}" | docker login -u "$${REGISTRY_USER}" --password-stdin git.nixc.us # Remove old stack - echo "Removing old stack..." - docker stack rm $${CI_REPO_NAME} || true - sleep 10 # Refresh secrets - | echo "Refreshing Docker secrets"; \ if [ -z "$${TUNNEL_SSH_HOST_KEY}" ] || [ -z "$${TUNNEL_AUTHORIZED_KEYS}" ] || [ -z "$${TUNNEL_TRAEFIK_DEPLOY_KEY}" ]; then \ echo "ERROR: Required secrets are empty. Aborting."; exit 1; \ fi; \ docker secret rm tunnel_ssh_host_key 2>/dev/null || true; \ docker secret rm tunnel_authorized_keys 2>/dev/null || true; \ docker secret rm tunnel_traefik_deploy_key 2>/dev/null || true; \ sleep 3; \ echo "$${TUNNEL_SSH_HOST_KEY}" | docker secret create tunnel_ssh_host_key -; \ echo "$${TUNNEL_AUTHORIZED_KEYS}" | docker secret create tunnel_authorized_keys -; \ echo "$${TUNNEL_TRAEFIK_DEPLOY_KEY}" | docker secret create tunnel_traefik_deploy_key -; \ echo "Secrets created:"; \ docker secret ls | grep tunnel_ # Deploy stack - echo "Deploying stack..." - docker stack deploy --with-registry-auth -c ./stack.production.yml $${CI_REPO_NAME} when: branch: main event: [push, cron]