Guide: CI/CD Integration

Run email tests in your CI/CD pipeline. This guide covers secrets management, project setup, and example configurations for popular CI providers.

Setup

  1. Create a dedicated project (or one per environment) in the Receiver.email dashboard.
  2. Generate an API key in the project settings.
  3. Store the API key as a secret in your CI provider (never commit it to source control).
  4. Install the SDK as a dev dependency in your project.

GitHub Actions

.github/workflows/test.yml
name: Email Tests

on:
  push:
    branches: [main]
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - run: npm ci

      - run: npm test
        env:
          RECEIVER_API_KEY: ${{ secrets.RECEIVER_API_KEY }}
        timeout-minutes: 5

Add RECEIVER_API_KEY to your repository secrets at Settings > Secrets and variables > Actions.

GitLab CI

.gitlab-ci.yml
email-tests:
  image: node:20
  stage: test
  variables:
    RECEIVER_API_KEY: $RECEIVER_API_KEY
  script:
    - npm ci
    - npm test
  timeout: 5 minutes

Add RECEIVER_API_KEY as a CI/CD variable at Settings > CI/CD > Variables (mark it as masked).

Jenkins

Jenkinsfile
pipeline {
    agent any

    environment {
        RECEIVER_API_KEY = credentials('receiver-api-key')
    }

    stages {
        stage('Test') {
            steps {
                sh 'npm ci'
                sh 'npm test'
            }
        }
    }
}

Generic CI (Environment Variable)

For any CI provider, the pattern is the same:

  1. Set RECEIVER_API_KEY as an environment variable / secret.
  2. Install dependencies: npm ci or pip install -r requirements.txt.
  3. Run tests: npm test or pytest.

Parallel Testing

Running email tests in parallel is straightforward because inboxes are unlimited and catch-all:

  • Unique addresses per test: Use timestamps or UUIDs in the local part (e.g. test-${Date.now()}[email protected]).
  • Filter by recipient: Each test waits for its own unique address, so parallel tests never interfere.
  • Separate projects per environment: Use different projects for staging, CI, and production if needed.
TypeScript
// Each parallel test uses a unique address
const uniqueAddr = `test-${Date.now()}-${Math.random().toString(36).slice(2)}[email protected]`;

// Trigger your app to send to this address
await app.sendWelcomeEmail(uniqueAddr);

// Only this test will receive this specific email
const email = await receiver.emails.waitFor({
  projectId: "proj_abc",
  recipient: uniqueAddr,
  timeout: 30,
});

Test Timeouts

Email tests involve network I/O and long-polling. Configure your test framework accordingly:

TypeScript
// Jest: increase timeout per test
it("receives email", async () => {
  // test code...
}, 60_000); // 60 second timeout

// Or globally in jest.config.js
module.exports = {
  testTimeout: 60_000,
};
Python
# pytest: use asyncio timeout
@pytest.mark.asyncio
@pytest.mark.timeout(60)
async def test_email_flow():
    # test code...
    pass

# Or in pytest.ini
# [pytest]
# timeout = 60

Next Steps