Logo
Loading...
Published on

How to run SSH commands on GitHub Actions

Author

Often you need some simple bash script or set of commands to deploy your application using GitHub Actions.

I've found appleboy/ssh-action, but under the hood it's running docker, which is not perfect for my use cases and slow, also it makes splitting job into logical steps quite hard.

So i've decided to run SSH directly.

To configure SSH connection you will need username, host and ssh key. You can store them in your repository actions secrets.

Here's simple example of workflow:

name: CI
on: [push]
jobs:
  #   ...
  deploy:
    name: "Deploy to test"
    runs-on: ubuntu-latest
    steps:
      - name: Configure SSH
        run: |
          mkdir -p ~/.ssh/
          echo "$SSH_KEY" > ~/.ssh/test.key
          chmod 600 ~/.ssh/test.key
          cat >>~/.ssh/config <<END
          Host test
            HostName $SSH_HOST
            User $SSH_USER
            IdentityFile ~/.ssh/test.key
            StrictHostKeyChecking no
          END
        env:
          SSH_USER: ${{ secrets.TEST_SSH_USER }}
          SSH_KEY: ${{ secrets.TEST_SSH_KEY }}
          SSH_HOST: ${{ secrets.TEST_SSH_HOST }}

      - name: Stop service
        run: ssh test 'sudo systemctl stop my-application'

      - name: Make pull
        run: ssh test 'cd my-application && git pull'

      - name: Start service
        if: ${{ always() }}
        run: ssh test 'sudo systemctl start my-application'

So we are creating host config test for our ssh connection and executing our commands.

Running commands in non interactive mode

Be aware that we are running commands in non interactive mode, and if you have something inside your PATH (like npm or go for example), most likely you will not be able to use it.

In non interactive mode most likely you will be sourcing .bashrc file, but it has this at start

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

So the easiest way to get your npm etc. get added to path would be to move them to the top of .bashrc file.

I think not all systems even read .bashrc file in non interactive mode (like ArchLinux), if that's the case you would need to check PermitUserEnvironment in sshd config and try to set PATH at ~/.ssh/environment.