how-to-integrate-keploy-in-github-actions

How to Integrate Keploy in Github Actions?

by

in
Table of Contents

Modern teams push code multiple times a day. But how do you verify that the changes made are free from bugs? And how do you integrate testing as part of your pipelines? In this blog, let’s explore how to integrate Keploy into your CI/CD pipelines. We’ll be using GitHub Actions for the examples.

What is Keploy?

keploy logo

Keploy is an API and integration testing tool that:

  • Records real API calls along with DB and queue interactions from your application

  • Generates test cases and mocks from that traffic

  • Replays them as deterministic tests during CI/CD

You don’t need to change your application code or add SDKs – Keploy hooks into network traffic (via eBPF) and captures it.

So the basic idea is very simple:

  • Record traffic in dev or staging once

  • Commit Keploy test cases to your repository

  • Replay them on every PR or push in the CI pipeline

Note: Now that we understand what Keploy is, let’s integrate it into our pipeline. But before that, you need to have recorded test cases for the application you plan to run in the CI pipeline.

For this blog, I’ll be using a FastAPI–Postgres application.

You can view the source code of the application here: Github

How to record test cases using the Keploy CLI?

Let’s record a few test cases using the Keploy CLI.

Use the following command to install the Keploy CLI:

curl --silent -O -L https://keploy.io/install.sh && source install.sh

Keploy cli

Once you have installed the Keploy CLI, let’s start recording not a movie, but your application’s network calls. To do this, you need to run your application along with Keploy.

Now, let’s capture the test cases:

keploy record -c "uvicorn application.main:app --reload"

Use the following cURL commands to send requests to the application:

bash
curl --location 'http://127.0.0.1:8000/students/' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Eva White",
    "email": "evawhite@example.com",
    "password": "evawhite111"
    }'
bash
curl --location 'http://127.0.0.1:8000/students/'
curl --location --request PUT 'http://127.0.0.1:8000/students/1' \
--header 'Content-Type: application/json' \
--data-raw '    {
        "name": "John Dow",
        "email": "doe.john@example.com",
        "password": "johndoe123",
        "stream": "Arts"
    }'
bash
curl --location 'http://127.0.0.1:8000/students/1'
bash
curl --location --request DELETE 'http://127.0.0.1:8000/students/1'

Keploy record

You can see that Keploy has successfully captured all the test cases. Now, let’s move to the main topic of this blog: how to integrate Keploy into GitHub Actions.

How to Integrate Keploy in GitHub Actions

Since we’ve already recorded the test cases using Keploy, the next step is to create a pipeline and integrate Keploy into it.

Below is the complete GitHub Actions workflow file:

bash
name: CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v5

      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: '3.10'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          python -m pip install -r requirements.txt
          echo "PYTHON_BIN=$(which python)" >> $GITHUB_ENV

      - name: Keploy Tests
        run: |
          curl --silent -O -L https://keploy.io/install.sh && source install.sh
          sudo -E keploy test -c "$PYTHON_BIN -m uvicorn application.main:app" --delay 10

keploy ci pipeline

Keploy cli logs

You can also view the exact output in the GitHub Actions logs: Github Actions logs


How to Record and Replay Test Cases in CI/CD Using Keploy

Record and Replay test cases in CI/CD using keploy

In the first section, we integrated the already recorded test cases and then replayed them in the CI/CD pipeline. But if you want to record and replay test cases directly within your CI/CD pipeline, you can use the code below as a reference.

The script below includes both steps recording and replaying along with the GitHub Actions workflow file.

bash
name: Keploy FastAPI Tests

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  keploy-tests:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.10"

      - name: Install Keploy CLI
        run: |
          curl -L https://keploy.io/install.sh | sudo bash
          which keploy
          keploy version || true

      - name: Create keploy docker network
        run: |
          sudo docker network create keploy-network || true

      - name: Make CI script executable
        run: |
          chmod +x .github/workflows/python_script.sh

      - name: Run Keploy + FastAPI tests
        run: |
          .github/workflows/python_script.sh

The script file:

bash
#!/bin/bash

echo "root ALL=(ALL:ALL) ALL" | sudo tee -a /etc/sudoers

# Start the postgres database
sudo docker compose up -d postgres

echo "=== Docker ps ==="
sudo docker ps

echo "=== Postgres logs ==="
sudo docker logs postgres --tail 50 || true

# 🔹 Wait for Postgres on localhost:5432 to be ready
wait_for_postgres() {
  echo "Waiting for Postgres on localhost:5432..."
  for i in {1..30}; do
    if nc -z localhost 5432 2>/dev/null; then
      echo "Postgres is up!"
      return 0
    fi
    echo "Postgres not ready yet... retry $i"
    sleep 2
  done
  echo "Postgres did not become ready in time"
  exit 1
}

wait_for_postgres

# Install dependencies
pip3 install -r requirements.txt

# Setup environment

export PYTHONPATH="$(pwd)"

# Configuration and cleanup
export RECORD_BIN=/usr/local/bin/keploy
export REPLAY_BIN=/usr/local/bin/keploy

sudo $RECORD_BIN config --generate
sudo rm -rf keploy/  # Clean old test data
config_file="./keploy.yml"
sed -i 's/global: {}/global: {"header": {"Allow":[],}}/' "$config_file"
sleep 5  # Allow time for configuration changes

send_request(){
    sleep 10
    app_started=false
    while [ "$app_started" = false ]; do
        if curl -X GET http://127.0.0.1:8000/; then
            app_started=true
        fi
        sleep 3 # wait for 3 seconds before checking again.
    done
    echo "App started"
    # Start making curl calls to record the testcases and mocks.
    curl --location 'http://127.0.0.1:8000/students/' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Eva White",
    "email": "evawhite@example.com",
    "password": "evawhite111"
    }'
    curl --location 'http://127.0.0.1:8000/students/'

    curl --location --request PUT 'http://127.0.0.1:8000/students/1' \
--header 'Content-Type: application/json' \
--data-raw '    {
        "name": "John Dow",
        "email": "doe.john@example.com",
        "password": "johndoe123",
        "stream": "Arts"
    }'

    curl --location 'http://127.0.0.1:8000/students/1'

    curl --location --request DELETE 'http://127.0.0.1:8000/students/1'

    # Wait for 10 seconds for keploy to record the tcs and mocks.
    sleep 10
    REC_PID="$(pgrep -n -f 'keploy record' || true)"
    echo "$REC_PID Keploy PID"
    echo "Killing keploy"
    sudo kill -INT "$REC_PID" 2>/dev/null || true
}

# Record and Test cycles
for i in {1..2}; do
    app_name="flaskApp_${i}"
    send_request &
    sudo -E env PATH="$PATH" $RECORD_BIN record -c "python -m uvicorn application.main:app" 2>&1 | tee "${app_name}.txt"

    if grep "ERROR" "${app_name}.txt"; then
        echo "Error found in pipeline..."
        cat "${app_name}.txt"
        exit 1
    fi
    if grep "WARNING: DATA RACE" "${app_name}.txt"; then
        echo "Race condition detected in recording, stopping pipeline..."
        cat "${app_name}.txt"
        exit 1
    fi
    sleep 5
    wait
    echo "Recorded test case and mocks for iteration ${i}"
done

# Shutdown postgres before test mode - Keploy should use mocks for database interactions
echo "Shutting down postgres before test mode..."
sudo docker compose down
echo "Postgres stopped - Keploy should now use mocks for database interactions"

# Testing phase
sudo -E env PATH="$PATH" $REPLAY_BIN test -c "python -m uvicorn application.main:app" --delay 10 2>&1 test_logs.txt

if grep "ERROR" "test_logs.txt"; then
        echo "Error found in pipeline..."
        cat "test_logs.txt"
        exit 1
fi
if grep "WARNING: DATA RACE" "test_logs.txt"; then
    echo "Race condition detected in test, stopping pipeline..."
    cat "test_logs.txt"
    exit 1
fi

all_passed=true

for i in {0..1}
do
    # Define the report file for each test set
    report_file="./keploy/reports/test-run-0/test-set-$i-report.yaml"

    # Extract the test status
    test_status=$(grep 'status:' "$report_file" | head -n 1 | awk '{print $2}')

    # Print the status for debugging
    echo "Test status for test-set-$i: $test_status"

    # Check if any test set did not pass
    if [ "$test_status" != "PASSED" ]; then
        all_passed=false
        echo "Test-set-$i did not pass."
        break # Exit the loop early as all tests need to pass
    fi
done

# Check the overall test status and exit accordingly
if [ "$all_passed" = true ]; then
    echo "All tests passed"
    exit 0
else
    cat "test_logs.txt"
    exit 1
fi

Recording the test cases using Keploy in the CI Pipeline:

keploy record

Replaying the test cases using Keploy in the CI Pipeline:

Keploy replay

You can view the GitHub Actions logs at the provided URL. The workflow will perform both record and replay steps: Github Actions logs

Conclusion

In this blog, we explored how to integrate Keploy into a CI/CD pipeline. The example we used was based on GitHub Actions, but the same approach can be applied using shell scripts on any CI/CD platform.

We also learned how to record and replay test cases in CI/CD using Keploy. If you want to customize the workflow, you can easily modify the configuration for example, replace Postgres with any other database or update the cURL commands to match your application’s APIs.

Adding an automated testing phase to your CI/CD pipeline helps you catch bugs early and ensures that every change pushed to production is reliable.

FAQs:

  1. Does Keploy work only with GitHub Actions?

No. Keploy is platform-agnostic. You can use the same scripts with GitLab CI, Jenkins, CircleCI, Bitbucket, or any platform that supports running shell commands.

  1. Can I run both record and replay inside the same CI/CD workflow?

Yes. Your pipeline can first record fresh test cases and then replay them in the same workflow to validate the new build.

  1. How does integrating Keploy improve DevOps productivity?

It reduces manual testing effort, increases confidence in deployments, speeds up delivery, and catches regressions early, making CI/CD pipelines more reliable.

  1. Can I customize which test cases Keploy replays?

Yes. You can filter test cases, organize them into folders, or selectively run tests using flags in your CI/CD scripts.

5. Can Keploy be used for microservices-based applications?

Yes. Keploy works well with microservices because it captures interactions between services and mocks them during replay, ensuring isolated and consistent testing.

Author

  • Achanandhi M

    Hi friends! I’m a Developer Advocate at Keploy, passionate about cloud-native technologies, CNCF, testing, and GenAI. I love diving into cutting-edge tools and exploring how they shape the future of software development. I’m always curious to learn, try new things, and share my experiences with the community. Outside of tech, you’ll find me on the badminton court or with a book in hand. I’m an athlete at heart, and some of my favorites books are “The Alchemist” and “Think Like a Monk” — both inspiring me to push my limits and stay curious. Always up for a chat about tech, community building, or a good book! 😊


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *