Automating Python Testing and Deployment with GitHub Actions and SSH

GitHub Actions is a powerful workflow automation tool that allows you to automate your software development workflows directly in your GitHub repository. In this guide, we’ll walk through the process of setting up automated testing and deployment for a Python project using GitHub Actions and SSH.

Table of Contents

Prerequisites

Before you start, ensure you have the following:

Setting up the remote server

First, we’ll need to set up the remote server. We’ll be using a VPS running Ubuntu for this guide, but the steps should be similar for other Linux distributions.

Installing Dependencies

First, we’ll need to install the dependencies for our project. We’ll be using Python 3.10 for this guide, but you can use any version of Python that your project supports.

sudo apt update  # Update the package index
sudo apt install python3 python3-venv python3-pip tmux  # Install Python 3, venv, pip, and tmux

Cloning the project

Now, we’ll clone the project from GitHub. Make sure you replace the URL with the URL of your project and PROJECT_NAME with the name of your project.

git clone [URL]  # Clone the project from GitHub
cd [PROJECT_NAME]  # Change into the project directory

Creating a virtual environment

Next, we’ll create a virtual environment for our project. This will allow us to install our project’s dependencies without affecting the rest of the system.

python3 -m venv venv  # Create a virtual environment named "venv"
source venv/bin/activate  # Activate the virtual environment

Deployment Script

Next, we’ll create a deployment script. This script will be run by GitHub Actions to deploy the project to the remote server. Make sure you replace PROJECT_NAME with the name of your project.

cd ..  # Change into the parent directory (leaving the project directory)
touch deploy.sh  # Create the deployment script
chmod +x deploy.sh  # Make the deployment script executable

Then, open the deployment script in your favorite text editor and add the following code:

#!/bin/bash

cd [PROJECT_NAME]  # Change into the project directory
source venv/bin/activate  # Activate the virtual environment

git pull  # Pull the latest changes from GitHub

pip install -r requirements.txt  # Install the project's dependencies
python -m pytest  # Run the project's tests

tmux kill-session -t [PROJECT_NAME]  # Kill the existing tmux session
tmux new-session -d -s [PROJECT_NAME]  # Create a new tmux session
tmux send-keys -t [PROJECT_NAME] "python3 main.py" ENTER  # Start the project

The deployment script will do the following: 1) Change into the project directory 2) Activate the virtual environment 3) Pull the latest changes from GitHub 4) Install the project’s dependencies 5) Run the project’s tests 6) Kill the existing tmux session 7) Create a new tmux session 8) Start the project

What is tmux and why do we need it?

tmux is a terminal multiplexer that allows you to run multiple terminal sessions in a single window. We’ll be using tmux to run the project in the background so that we can close the SSH connection without stopping the project.

Setting up the GitHub repository

Now that we’ve set up the remote server, we’ll need to set up the GitHub repository. We’ll be using the GitHub web interface for this guide, but you can also use the GitHub CLI if you prefer.

Secrets

First, we’ll need to add our SSH credentials to the repository as secrets. This will allow us to access the remote server without exposing our credentials in the workflow file. To do this, go to the repository settings and click on “Secrets” in the sidebar. Then, click on “New repository secret” and add the following secrets:

Workflow

Next, we’ll need to create a workflow file. This is a YAML file that tells GitHub Actions what to do when certain events occur. To do this, create a new file named .github/workflows/main.yml and add the following code:

name: Test and Deploy

on:
  push:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up Python 3.10
      uses: actions/setup-python@v3
      with:
        python-version: "3.10"
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        python -m pip install pytest
        python -m pip install -r requirements.txt
    - name: Test with pytest
      run: |
        python -m pytest
    - name: Deploy
      uses: appleboy/ssh-action@v1.0.0
      with:
        host: $
        username: $
        key: $
        port: $
        script: sh deploy.sh

This workflow will run the following steps when we push to the main branch: 1) Install Python 3.10 in a temporary environment 2) Install the project’s dependencies from requirements.txt 3) Run the project’s tests using pytest 4) Run the deploy.sh script on the remote server using SSH if the tests pass.

Testing the workflow

Now that we’ve set up the workflow, we’ll need to test it to make sure it works. To do this, push a commit to the main branch and check the Actions tab in the repository. If everything worked correctly, you should see a green checkmark next to the commit message like in this image. If not, check the logs for the workflow to see what went wrong by clicking the commit message and then build.

Further Reading

If you’d like to learn more about GitHub Actions, check out the official documentation.

Conclusion

In this guide, we walked through the process of setting up automated testing and deployment for a Python project using GitHub Actions and SSH. We also tested the workflow to make sure it works correctly.