Skip to main content
AI/MLjeremylongshore

elevenlabs-ci-integration

'Configure CI/CD pipelines for ElevenLabs with mocked unit tests and

Stars
2,267
Source
jeremylongshore/claude-code-plugins-plus-skills
Updated
2026-05-31
Slug
jeremylongshore--claude-code-plugins-plus-skills--elevenlabs-ci-integration
View on GitHubRaw SKILL.md

// install — copy + paste into any project

mkdir -p .claude/skills && curl -fsSL https://raw.githubusercontent.com/jeremylongshore/claude-code-plugins-plus-skills/HEAD/plugins/saas-packs/elevenlabs-pack/skills/elevenlabs-ci-integration/SKILL.md -o .claude/skills/elevenlabs-ci-integration.md

Drops the SKILL.md into .claude/skills/elevenlabs-ci-integration.md. Works with Claude Code, Cursor, and any agent that loads SKILL.md files from .claude/skills/.

ElevenLabs CI Integration

Overview

Set up CI/CD pipelines that test ElevenLabs integrations without burning character quota on every PR. Uses a two-tier strategy: mocked unit tests on every push (no API key, zero quota), and gated integration tests that hit the real API only on main or a manual dispatch, behind a quota guard.

The full workflow YAML and secret setup live in references/implementation.md; the complete test code lives in references/examples.md. This file walks the strategy end to end, then drills into either reference for copy-paste source.

Prerequisites

  • GitHub repository with Actions enabled
  • ElevenLabs API key for integration tests (use a test/dev key, not production)
  • npm/pnpm project with vitest configured

Instructions

Step 1: Add the two-tier workflow

Create .github/workflows/elevenlabs-tests.yml with two jobs. unit-tests runs on every push/PR with a mock key. integration-tests runs only on main or workflow_dispatch, needs: unit-tests, and checks remaining quota before spending any:

jobs:
  unit-tests:                       # every push/PR — mock key, 0 quota
    runs-on: ubuntu-latest
    steps: [checkout, setup-node, npm ci, npm test -- --coverage]
    # env: ELEVENLABS_API_KEY: "sk_test_mock_key_for_ci"

  integration-tests:                # main / manual only — real key
    if: github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch'
    needs: unit-tests
    # 1) GET /v1/user → skip if remaining characters < 5000
    # 2) npm run test:integration behind that guard

Copy the complete, runnable workflow from references/implementation.md.

Step 2: Store the API key as a repository secret

gh secret set ELEVENLABS_API_KEY --body "sk_your_test_key_here"
# optional, for webhook tests:
gh secret set ELEVENLABS_WEBHOOK_SECRET --body "whsec_your_secret_here"

Step 3: Write mocked unit tests

Mock the entire SDK so unit tests never call the API or spend quota. Minimal skeleton:

vi.mock("@elevenlabs/elevenlabs-js", () => ({
  ElevenLabsClient: vi.fn().mockImplementation(() => ({
    textToSpeech: { convert: vi.fn().mockResolvedValue(/* mock MP3 stream */) },
    voices: { getAll: vi.fn().mockResolvedValue({ voices: [/* Rachel */] }) },
  })),
}));

Full mock (streaming, voices, user/subscription) and assertions: references/examples.md.

Step 4: Write gated integration tests

Skip integration tests unless ELEVENLABS_INTEGRATION is set, and keep them cheap — Flash model, short text, low bitrate:

const SKIP = !process.env.ELEVENLABS_INTEGRATION;
describe.skipIf(SKIP)("ElevenLabs Integration", () => { /* smoke tests */ });

Full smoke suite: references/examples.md.

Step 5: Wire the package scripts

Add test, test:integration, and test:ci scripts so CI and local runs share one entry point. See references/examples.md.

Output

Once configured, the pipeline produces:

  • .github/workflows/elevenlabs-tests.yml — two-tier CI pipeline
  • ELEVENLABS_API_KEY (and optional webhook secret) stored in GitHub secrets
  • tests/unit/ mocked tests that run on every push at 0 character cost
  • tests/integration/ smoke tests gated to main/manual behind a quota guard
  • npm scripts (test, test:integration, test:ci) shared by CI and local

CI Strategy Summary

Tier When API Key Quota Cost Coverage
Unit tests Every push/PR Mock key 0 characters SDK integration patterns
Integration Main + manual Real test key ~50 chars End-to-end TTS verification
Quota check Before integration Real test key 0 (GET only) Prevents surprise billing

Error Handling

Issue Cause Solution
Secret not found in CI Missing repository secret gh secret set ELEVENLABS_API_KEY
Integration tests timeout Slow TTS generation Increase test timeout to 30s; use Flash model
Quota depleted in CI Too many integration runs Use quota guard; limit to main branch only
Mock drift SDK API changed Update mocks when upgrading SDK

Examples

Run only the cheap tier locally (no API key, no quota):

npm test -- --coverage

Trigger the gated integration tier by hand (from the Actions tab or CLI):

gh workflow run elevenlabs-tests.yml

Run integration tests locally against a real test key:

ELEVENLABS_INTEGRATION=1 npm run test:integration

Full worked examples — complete SDK mock, gated smoke suite, and package scripts — are in references/examples.md.

Resources

Next Steps

For deployment patterns, see the elevenlabs-deploy-integration skill, which covers promoting validated TTS builds through staging and production.