CI Pipelines for Payment Code
Configure your GitHub Actions CI pipeline with two jobs: (1) unit-tests — runs fast, no network, uses mocked Paystack; (2) integration-tests — uses PAYSTACK_TEST_KEY secret, calls real Paystack test API, runs only on PRs to main. Add a coverage step that fails the workflow if coverage drops below threshold. Never store live Paystack keys in CI — test keys only.
GitHub Actions Workflow for Payment Code
# .github/workflows/payment-tests.yml
name: Payment Tests
on:
push:
branches: ['*']
pull_request:
branches: [main]
jobs:
unit-tests:
name: Unit Tests (fast, no network)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm test -- --testPathPattern="unit|webhook" --coverage
env:
PAYSTACK_SECRET_KEY: sk_test_fake_for_unit_tests
NODE_ENV: test
- name: Upload coverage report
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
integration-tests:
name: Integration Tests (real Paystack test API)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
services:
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: testpass
POSTGRES_DB: testdb
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run db:migrate:test
env:
DATABASE_URL: postgres://postgres:testpass@localhost:5432/testdb
- run: npm test -- --testPathPattern="integration"
env:
PAYSTACK_SECRET_KEY: ${{ secrets.PAYSTACK_TEST_KEY }}
DATABASE_URL: postgres://postgres:testpass@localhost:5432/testdb
NODE_ENV: test
Learn More
This guide is part of the Paystack testing guide.
Key Takeaways
- ✓Store your Paystack test key as a GitHub Actions secret (PAYSTACK_TEST_KEY) — never commit it to the repo.
- ✓Separate unit tests (fast, no network) from integration tests (Paystack test API) into different CI jobs.
- ✓Run unit tests on every push; run integration tests only on PRs targeting main to save CI time.
- ✓Add a coverage check step — fail the workflow if payment-critical files drop below coverage threshold.
- ✓Block deploys to production unless all test jobs pass — especially integration tests that verify the real Paystack API contract.
- ✓Use a separate test database for integration tests in CI — inject DATABASE_URL as a CI secret or use an ephemeral in-memory DB.
Frequently Asked Questions
- Is it safe to use a real Paystack test key in GitHub Actions?
- Yes — test keys (sk_test_...) do not move real money. Store the test key as a GitHub Actions secret (never in the repo). Test mode API calls are harmless. What you must never put in CI is a live key (sk_live_...). Add a validation step: if PAYSTACK_SECRET_KEY starts with "sk_live_", fail the build immediately.
- Should integration tests run on every push or only on PRs?
- Integration tests against the real Paystack test API are slower (network dependent) and should run only on PRs to main — not on every push to feature branches. Unit tests should run on every push. This balance keeps CI fast for development while ensuring thorough testing before merging.
- How do I prevent production deployment if payment tests fail?
- In GitHub Actions, configure your deploy job with needs: [unit-tests, integration-tests]. The deploy job will not run unless both test jobs pass. For Vercel, configure the GitHub integration to require checks to pass before deploying preview or production environments.
- Can I run integration tests without a real database in CI?
- For pure API integration tests (testing your Paystack API call logic), you can use SQLite in-memory. For full integration tests that verify database state changes, use a real PostgreSQL service in your CI workflow (shown above using GitHub Actions services). SQLite has different SQL behavior from PostgreSQL — use real PostgreSQL for payment integration tests.
Ready to build real-world apps?
Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.
Apply to the McTaba Marathon