name: 'Setup SSH Client' description: 'Configure SSH client for running remote commands with custom shell wrapper' author: 'Karolis Kundrotas' branding: icon: 'terminal' color: 'blue' inputs: ssh-private-key: description: 'SSH private key for authentication' required: true ssh-host: description: 'SSH host to connect to' required: true ssh-user: description: 'SSH username' required: true ssh-port: description: 'SSH port' required: false default: '22' ssh-known-hosts: description: 'Known hosts content (optional, will use ssh-keyscan if not provided)' required: false default: '' strict-host-key-checking: description: 'Enable strict host key checking (yes/no/accept-new)' required: false default: 'accept-new' use-shell-wrapper: description: 'Create shell wrapper for remote execution (enables shell: ssh-remote)' required: false default: 'true' remote-shell: description: 'Shell to use on remote server (bash, sh, zsh, etc.)' required: false default: 'bash' outputs: ssh-config-path: description: 'Path to the SSH config file' value: ${{ steps.setup-ssh.outputs.ssh-config-path }} ssh-key-path: description: 'Path to the SSH private key' value: ${{ steps.setup-ssh.outputs.ssh-key-path }} shell-wrapper-path: description: 'Path to the SSH remote shell wrapper script' value: ${{ steps.setup-shell-wrapper.outputs.shell-wrapper-path }} runs: using: 'composite' steps: - name: Setup SSH id: setup-ssh shell: bash run: | # Create SSH directory mkdir -p ~/.ssh chmod 700 ~/.ssh # Setup SSH private key SSH_KEY_PATH="$HOME/.ssh/github_action_key" echo "${{ inputs.ssh-private-key }}" > "$SSH_KEY_PATH" chmod 600 "$SSH_KEY_PATH" echo "ssh-key-path=$SSH_KEY_PATH" >> $GITHUB_OUTPUT # Setup known hosts if [ -n "${{ inputs.ssh-known-hosts }}" ]; then echo "${{ inputs.ssh-known-hosts }}" > ~/.ssh/known_hosts chmod 644 ~/.ssh/known_hosts else if [ "${{ inputs.strict-host-key-checking }}" = "yes" ]; then echo "❌ strict-host-key-checking is 'yes' but no ssh-known-hosts provided. Refusing to auto-add host key via ssh-keyscan." >&2 echo "Provide the host's key (e.g. from a trusted source) via 'ssh-known-hosts' input." >&2 exit 1 fi echo "Scanning host keys for ${{ inputs.ssh-host }}..." ssh-keyscan -p ${{ inputs.ssh-port }} -H "${{ inputs.ssh-host }}" >> ~/.ssh/known_hosts 2>/dev/null || true chmod 644 ~/.ssh/known_hosts fi # Create SSH config SSH_CONFIG_PATH="$HOME/.ssh/config" cat >> "$SSH_CONFIG_PATH" << EOF Host github-action-host HostName ${{ inputs.ssh-host }} User ${{ inputs.ssh-user }} Port ${{ inputs.ssh-port }} IdentityFile $SSH_KEY_PATH StrictHostKeyChecking ${{ inputs.strict-host-key-checking }} UserKnownHostsFile ~/.ssh/known_hosts EOF chmod 600 "$SSH_CONFIG_PATH" echo "ssh-config-path=$SSH_CONFIG_PATH" >> $GITHUB_OUTPUT echo "✅ SSH client configured successfully" echo "Connect using: ssh github-action-host" - name: Test SSH Connection shell: bash run: | echo "Testing SSH connection..." if ssh -o ConnectTimeout=10 -o BatchMode=yes github-action-host "echo 'SSH connection successful'" 2>&1; then echo "✅ SSH connection test passed" else echo "⚠️ SSH connection test failed - please verify your credentials and host" exit 1 fi - name: Create SSH Remote Shell Wrapper id: setup-shell-wrapper if: inputs.use-shell-wrapper == 'true' shell: bash run: | # Create a unique temporary wrapper script. Prefer RUNNER_TEMP if set. WRAPPER_DIR="${RUNNER_TEMP:-/tmp}" mkdir -p "$WRAPPER_DIR" WRAPPER_PATH="$(mktemp "$WRAPPER_DIR/ssh-remote-shell-XXXXXX.sh")" cat << 'WRAPPER_EOF' > "$WRAPPER_PATH" #!/bin/bash set -e # Check if input file is provided if [ -z "$1" ]; then echo "Error: No script file provided" >&2 exit 1 fi SCRIPT_FILE="$1" # Check if script file exists if [ ! -f "$SCRIPT_FILE" ]; then echo "Error: Script file '$SCRIPT_FILE' not found" >&2 exit 1 fi # Execute script on remote server # Use BatchMode to prevent interactive prompts # ConnectTimeout to fail fast if connection issues ssh -o BatchMode=yes \ -o ConnectTimeout=10 \ github-action-host \ "${{ inputs.remote-shell }} -s" < "$SCRIPT_FILE" WRAPPER_EOF chmod +x "$WRAPPER_PATH" echo "shell-wrapper-path=$WRAPPER_PATH" >> $GITHUB_OUTPUT echo "✅ SSH remote shell wrapper created at $WRAPPER_PATH" echo "" echo "To use the remote shell in subsequent steps, add:" echo " shell: ssh-remote" echo "" echo "The 'ssh-remote' shell is now available for use." - name: Register Custom Shell if: inputs.use-shell-wrapper == 'true' shell: bash run: | echo "ssh-remote=${{ steps.setup-shell-wrapper.outputs.shell-wrapper-path }} {0}" >> "$GITHUB_ENV" echo "✅ Custom shell 'ssh-remote' registered for this job"