Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Configure Apollo.io CI/CD integration. Use when setting up automated testing, continuous integration, or deployment pipelines for Apollo integrations. Trigger with phrases like "apollo ci", "apollo github actions", "apollo pipeline", "apollo ci/cd", "apollo automated tests".
.claude/skills/jeremylongshore-apollo-ci-integration/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 61% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 35% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 29% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 57% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 61% | 0% |
Set up CI/CD pipelines for Apollo.io integrations with GitHub Actions. Uses MSW mocks for unit tests (zero API calls), sandbox tokens for staging, and live API tests gated to main branch only. Apollo's sandbox token returns dummy data without consuming credits.
bash# Master API key for integration tests (main branch only) gh secret set APOLLO_API_KEY --body "$APOLLO_API_KEY" # Sandbox token for staging tests (safe, no credits) gh secret set APOLLO_SANDBOX_KEY --body "$APOLLO_SANDBOX_KEY"
yaml# .github/workflows/apollo-ci.yml name: Apollo CI on: push: branches: [main] pull_request: branches: [main] jobs: lint-and-typecheck: 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 run lint - run: npm run typecheck unit-tests: 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 # Unit tests use MSW mocks — zero API calls integration-tests: runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' needs: [unit-tests] steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '20', cache: 'npm' } - run: npm ci - name: Apollo Health Check env: APOLLO_API_KEY: ${{ secrets.APOLLO_API_KEY }} run: | STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ -H "x-api-key: $APOLLO_API_KEY" \ "https://api.apollo.io/api/v1/auth/health") echo "Apollo API: HTTP $STATUS" [ "$STATUS" = "200" ] || exit 1 - run: npm run test:integration env: APOLLO_API_KEY: ${{ secrets.APOLLO_API_KEY }} secret-scan: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Check for hardcoded API keys run: | if grep -rn 'x-api-key.*[a-zA-Z0-9]\{20,\}' src/ --include='*.ts' --include='*.js'; then echo "Potential hardcoded API key found!" exit 1 fi echo "No hardcoded secrets"
typescript// src/__tests__/apollo.test.ts import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest'; import { setupServer } from 'msw/node'; import { http, HttpResponse } from 'msw'; const BASE = 'https://api.apollo.io/api/v1'; const mockServer = setupServer( http.post(`${BASE}/mixed_people/api_search`, () => HttpResponse.json({ people: [{ id: '1', name: 'Jane Doe', title: 'VP Sales' }], pagination: { page: 1, per_page: 25, total_entries: 1, total_pages: 1 }, }), ), http.post(`${BASE}/people/match`, () => HttpResponse.json({ person: { id: '1', name: 'Jane Doe', email: 'jane@test.com', title: 'VP Sales' }, }), ), http.get(`${BASE}/auth/health`, () => HttpResponse.json({ is_logged_in: true }), ), ); beforeAll(() => mockServer.listen()); afterEach(() => mockServer.resetHandlers()); afterAll(() => mockServer.close()); describe('People Search', () => { it('returns contacts from search', async () => { const { searchPeople } = await import('../workflows/lead-search'); const result = await searchPeople({ domains: ['test.com'] }); expect(result.people).toHaveLength(1); expect(result.people[0].name).toBe('Jane Doe'); }); it('handles 429 errors', async () => { mockServer.use( http.post(`${BASE}/mixed_people/api_search`, () => HttpResponse.json({ message: 'Rate limited' }, { status: 429 }), ), ); const { searchPeople } = await import('../workflows/lead-search'); await expect(searchPeople({ domains: ['test.com'] })).rejects.toThrow(); }); });
typescript// src/__tests__/integration/apollo-live.test.ts import { describe, it, expect } from 'vitest'; import axios from 'axios'; const SKIP = !process.env.APOLLO_API_KEY; const client = axios.create({ baseURL: 'https://api.apollo.io/api/v1', headers: { 'Content-Type': 'application/json', 'x-api-key': process.env.APOLLO_API_KEY! }, }); describe.skipIf(SKIP)('Apollo Live Integration', () => { it('searches for people at apollo.io', async () => { const { data } = await client.post('/mixed_people/api_search', { q_organization_domains_list: ['apollo.io'], per_page: 5, }); expect(data.people.length).toBeGreaterThan(0); }); it('enriches organization by domain', async () => { const { data } = await client.get('/organizations/enrich', { params: { domain: 'apollo.io' } }); expect(data.organization).toBeDefined(); expect(data.organization.name).toContain('Apollo'); }); });
| Issue | Resolution | |-------|------------| | Secret not found | gh secret list to verify, re-add with gh secret set | | Rate limited in CI | Unit tests use MSW, integration tests run only on main | | Health check fails | Check status.apollo.io; skip flaky on outage | | Hardcoded key found | Secret scan job fails the build; rotate the key immediately |
Proceed to apollo-deploy-integration for deployment configuration.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→pass | 9,601 | 5,203 | -46% | 1 | 1 | 0% | 1,849 | 2,975 | +61% | 0 | 0 | — |
case-01 | fail→pass | 14,016 | 10,116 | -28% | 1 | 1 | 0% | 3,045 | 4,100 | +35% | 0 | 0 | — |
case-02 | fail→pass | 16,661 | 12,512 | -25% | 1 | 1 | 0% | 3,962 | 5,116 | +29% | 0 | 0 | — |
case-03 | fail→pass | 12,795 | 12,296 | -4% | 1 | 1 | 0% | 3,023 | 4,737 | +57% | 0 | 0 | — |
case-05 | fail→fail | 15,380 | 15,693 | +2% | 1 | 1 | 0% | 3,018 | 5,061 | +68% | 0 | 0 | — |
case-06 | pass→pass | 9,303 | 2,498 | -73% | 1 | 1 | 0% | 1,863 | 2,404 | +29% | 0 | 0 | — |
case-07 | fail→pass | 24,868 | 8,590 | -65% | 1 | 1 | 0% | 2,352 | 3,781 | +61% | 0 | 0 | — |
case-08 | fail→fail | 6,219 | 4,755 | -24% | 1 | 1 | 0% | 1,331 | 2,885 | +117% | 0 | 0 | — |
case-09 | fail→pass | 10,815 | 7,877 | -27% | 1 | 1 | 0% | 2,306 | 3,553 | +54% | 0 | 0 | — |
case-10 | fail→pass | 12,633 | 6,070 | -52% | 1 | 1 | 0% | 2,479 | 3,015 | +22% | 0 | 0 | — |
case-11 | fail→pass | 6,503 | 2,316 | -64% | 1 | 1 | 0% | 1,351 | 2,337 | +73% | 0 | 0 | — |
case-12 | pass→pass | 9,327 | 2,784 | -70% | 1 | 1 | 0% | 1,746 | 2,461 | +41% | 0 | 0 | — |
case-13 | pass→pass | 14,714 | 10,120 | -31% | 1 | 1 | 0% | 2,813 | 3,940 | +40% | 0 | 0 | — |
case-14 | fail→pass | 6,181 | 1,821 | -71% | 1 | 1 | 0% | 1,071 | 2,256 | +111% | 0 | 0 | — |
case-15 | pass→pass | 6,740 | 2,938 | -56% | 1 | 1 | 0% | 1,336 | 2,512 | +88% | 0 | 0 | — |
case-16 | fail→pass | 11,009 | 3,956 | -64% | 1 | 1 | 0% | 2,058 | 2,509 | +22% | 0 | 0 | — |
case-17 | pass→pass | 11,808 | 6,649 | -44% | 1 | 1 | 0% | 2,137 | 3,130 | +46% | 0 | 0 | — |
case-18 | pass→pass | 7,302 | 4,099 | -44% | 1 | 1 | 0% | 1,273 | 2,594 | +104% | 0 | 0 | — |
case-19 | fail→pass | 13,579 | 7,585 | -44% | 1 | 1 | 0% | 2,276 | 3,314 | +46% | 0 | 0 | — |
case-20 | fail→fail | 13,710 | 11,485 | -16% | 1 | 1 | 0% | 2,852 | 4,457 | +56% | 0 | 0 | — |
case-21 | pass→pass | 21,792 | 19,358 | -11% | 1 | 1 | 0% | 4,725 | 6,329 | +34% | 0 | 0 | — |
case-22 | pass→pass | 10,859 | 15,104 | +39% | 1 | 1 | 0% | 2,184 | 5,435 | +149% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +50 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.