Files
deploy-to-docker/action.yml
2025-05-20 00:27:37 +02:00

157 lines
6.1 KiB
YAML

name: 'Deploy to Docker (Swarm or Compose)'
description: |
Robustly deploys a processed Docker Compose file either to Docker Swarm or regular Docker Compose via SSH.
Includes detailed debug output, error handling, and cleanup.
inputs:
stack_name:
description: 'Docker stack or compose project name'
required: true
ssh_host:
description: 'SSH host'
required: true
ssh_user:
description: 'SSH username'
required: true
ssh_key:
description: 'SSH private key'
required: true
deploy_file:
description: 'Path to the processed deployment file'
required: true
deploy_mode:
description: 'Deployment mode: swarm or compose'
required: false
default: 'swarm'
remote_temp_dir:
description: 'Remote temporary directory for deployment files'
required: false
default: '/tmp'
copy_build_context:
description: 'Whether to copy Docker build context (Dockerfile and related files) to remote host'
required: false
default: 'false'
build_context_path:
description: 'Local path to Docker build context (directory containing Dockerfile). Defaults to ./build-context'
required: false
default: 'build-context'
copy_env_file:
description: 'Whether to copy .env file to remote host'
required: false
default: 'false'
env_file_path:
description: 'Local path to .env file'
required: false
default: '.env'
runs:
using: 'composite'
steps:
- id: deploy
shell: bash
run: |
set -euo pipefail
STACK_NAME="${{ inputs.stack_name }}"
SSH_HOST="${{ inputs.ssh_host }}"
SSH_USER="${{ inputs.ssh_user }}"
DEPLOY_FILE="${{ inputs.deploy_file }}"
DEPLOY_MODE="${{ inputs.deploy_mode }}"
REMOTE_TEMP_DIR="${{ inputs.remote_temp_dir }}/$STACK_NAME"
COPY_BUILD_CONTEXT="${{ inputs.copy_build_context }}"
BUILD_CONTEXT_PATH="${{ inputs.build_context_path }}"
echo "🚀 Starting deployment of '$STACK_NAME' to host '$SSH_HOST' using mode '$DEPLOY_MODE'"
# Validate deploy_mode input
if [[ "$DEPLOY_MODE" != "swarm" && "$DEPLOY_MODE" != "compose" ]]; then
echo "❌ ERROR: Invalid deploy_mode '$DEPLOY_MODE'. Must be 'swarm' or 'compose'."
exit 1
fi
# Check if deployment file exists locally
if [ ! -f "$DEPLOY_FILE" ]; then
echo "❌ ERROR: Deployment file '$DEPLOY_FILE' does not exist."
exit 1
fi
# Create temporary SSH key file
SSH_KEY_FILE=$(mktemp)
echo "${{ inputs.ssh_key }}" > "$SSH_KEY_FILE"
chmod 600 "$SSH_KEY_FILE"
echo "🔑 DEBUG: Temporary SSH key created at '$SSH_KEY_FILE'"
# Ensure remote directory exists
echo "📁 DEBUG: Creating remote directory '$REMOTE_TEMP_DIR'"
ssh -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" \
"$SSH_USER@$SSH_HOST" \
"mkdir -p '$REMOTE_TEMP_DIR' && chmod 700 '$REMOTE_TEMP_DIR'"
# Copy deployment file to remote host
echo "📤 DEBUG: Copying deployment file '$DEPLOY_FILE' to remote host at '$REMOTE_TEMP_DIR/docker-compose.yml'"
scp -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" \
"$DEPLOY_FILE" \
"$SSH_USER@$SSH_HOST:$REMOTE_TEMP_DIR/docker-compose.yml"
# Optionally copy Docker build context
if [ "$COPY_BUILD_CONTEXT" == "true" ]; then
echo "📂 DEBUG: Copying Docker build context from '$BUILD_CONTEXT_PATH' to remote host"
scp -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" -r \
"$BUILD_CONTEXT_PATH"/* \
"$SSH_USER@$SSH_HOST:$REMOTE_TEMP_DIR/"
echo "📋 DEBUG: Listing remote build context directory '$REMOTE_TEMP_DIR'"
ssh -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" \
"$SSH_USER@$SSH_HOST" \
"ls -lha '$REMOTE_TEMP_DIR'"
fi
# Optionally copy env file
COPY_ENV_FILE="${{ inputs.copy_env_file }}"
ENV_FILE_PATH="${{ inputs.env_file_path }}"
if [ "$COPY_ENV_FILE" == "true" ]; then
if [ ! -f "$ENV_FILE_PATH" ]; then
echo "❌ ERROR: .env file '$ENV_FILE_PATH' does not exist."
exit 1
fi
echo "📄 DEBUG: Copying .env file from '$ENV_FILE_PATH' to remote host"
scp -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" \
"$ENV_FILE_PATH" \
"$SSH_USER@$SSH_HOST:$REMOTE_TEMP_DIR/.env"
fi
# Validate docker-compose file remotely before deploying
echo "🔍 DEBUG: Validating Docker Compose file remotely"
ssh -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" \
"$SSH_USER@$SSH_HOST" \
"docker compose -f '$REMOTE_TEMP_DIR/docker-compose.yml' config --quiet"
echo "✅ DEBUG: Docker Compose file validation succeeded"
# Deploy based on mode
if [ "$DEPLOY_MODE" == "swarm" ]; then
echo "🚢 DEBUG: Deploying stack '$STACK_NAME' to Docker Swarm"
ssh -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" \
"$SSH_USER@$SSH_HOST" \
"docker compose pull && docker stack deploy -c '$REMOTE_TEMP_DIR/docker-compose.yml' '$STACK_NAME' --with-registry-auth"
echo "✅ DEBUG: Stack '$STACK_NAME' deployed successfully to Docker Swarm"
else
echo "🐳 DEBUG: Deploying project '$STACK_NAME' using Docker Compose"
ssh -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" \
"$SSH_USER@$SSH_HOST" \
"cd '$REMOTE_TEMP_DIR' && docker compose pull && docker compose -p '$STACK_NAME' up -d --remove-orphans"
echo "✅ DEBUG: Project '$STACK_NAME' deployed successfully using Docker Compose"
fi
# Cleanup remote temporary files
echo "🧹 DEBUG: Cleaning up remote temporary directory '$REMOTE_TEMP_DIR'"
ssh -o StrictHostKeyChecking=no -i "$SSH_KEY_FILE" \
"$SSH_USER@$SSH_HOST" \
"rm -rf '$REMOTE_TEMP_DIR'"
# Cleanup local temporary SSH key file
rm -f "$SSH_KEY_FILE"
echo "🔑 DEBUG: Temporary SSH key file '$SSH_KEY_FILE' removed"
echo "🎉 Deployment of '$STACK_NAME' completed successfully!"