Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Configure Gamma CI/CD integration with GitHub Actions and testing. Use when setting up automated testing, configuring CI pipelines, or integrating Gamma tests into your build process. Trigger with phrases like "gamma CI", "gamma GitHub Actions", "gamma automated tests", "CI gamma", "gamma pipeline".
.claude/skills/jeremylongshore-gamma-ci-integration/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 12% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 19% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 6% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 40% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 19% | 0% |
Set up continuous integration for Gamma-powered applications with automated testing and deployment.
yaml# .github/workflows/gamma-ci.yml name: Gamma CI on: push: branches: [main, develop] pull_request: branches: [main] env: GAMMA_API_KEY: ${{ secrets.GAMMA_API_KEY }} jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - name: Install dependencies run: npm ci - name: Run unit tests run: npm test - name: Run Gamma integration tests run: npm run test:gamma env: GAMMA_MOCK: ${{ github.event_name == 'pull_request' }} - name: Upload coverage uses: codecov/codecov-action@v4 with: files: ./coverage/lcov.info
json// package.json { "scripts": { "test": "vitest run", "test:gamma": "vitest run --config vitest.gamma.config.ts", "test:gamma:live": "GAMMA_MOCK=false vitest run --config vitest.gamma.config.ts" } }
typescript// vitest.gamma.config.ts import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { include: ['tests/gamma/**/*.test.ts'], testTimeout: 60000, // Gamma API can be slow # 60000: 1 minute in ms hookTimeout: 30000, # 30000: 30 seconds in ms setupFiles: ['./tests/gamma/setup.ts'], }, });
typescript// tests/gamma/setup.ts import { beforeAll } from 'vitest'; import { createGammaClient, type GammaClient } from '../../src/client'; const useMock = process.env.GAMMA_MOCK === 'true'; export let gamma: ReturnType<typeof createGammaClient>; beforeAll(() => { if (useMock) { gamma = createMockGammaClient(); } else { gamma = createGammaClient({ apiKey: process.env.GAMMA_API_KEY!, }); } }); function createMockGammaClient() { return { generate: vi.fn().mockResolvedValue({ generationId: 'mock-gen-id' }), poll: vi.fn().mockResolvedValue({ status: 'completed', gammaUrl: 'https://gamma.app/docs/mock-test', exportUrl: 'https://export.gamma.app/mock.pdf', creditsUsed: 10, }), listThemes: vi.fn().mockResolvedValue([{ id: 'theme_1', name: 'Default' }]), listFolders: vi.fn().mockResolvedValue([]), }; }
typescript// tests/gamma/generation.test.ts import { describe, it, expect } from 'vitest'; import { gamma } from './setup'; describe('Gamma Generation', () => { it('should start a generation', async () => { const result = await gamma.generate({ content: 'CI Test: 1-card overview of testing', outputFormat: 'presentation', }); expect(result.generationId).toBeDefined(); }); it('should list workspace themes', async () => { const themes = await gamma.listThemes(); expect(Array.isArray(themes)).toBe(true); }); });
bash# Using GitHub CLI gh secret set GAMMA_API_KEY --body "your-test-api-key" # Verify secrets gh secret list
| Error | Cause | Solution | |-------|-------|----------| | Secret not found | Missing GitHub secret | Add GAMMA_API_KEY secret | | Test timeout | Slow API response | Increase testTimeout | | Mock mismatch | Mock out of sync | Update mock responses | | Rate limit in CI | Too many test runs | Use mock mode for PRs |
Proceed to gamma-deploy-integration for deployment workflows.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 18,880 | 13,875 | -27% | 1 | 1 | 0% | 2,791 | 3,130 | +12% | 0 | 0 | — |
case-02 | fail→pass | 20,441 | 16,020 | -22% | 1 | 1 | 0% | 3,033 | 3,603 | +19% | 0 | 0 | — |
case-03 | fail→pass | 12,098 | 11,667 | -4% | 1 | 1 | 0% | 2,474 | 2,624 | +6% | 0 | 0 | — |
case-04 | fail→fail | 15,916 | 9,195 | -42% | 1 | 1 | 0% | 2,069 | 3,090 | +49% | 0 | 0 | — |
case-05 | pass→pass | 13,763 | 20,472 | +49% | 1 | 1 | 0% | 2,705 | 4,334 | +60% | 0 | 0 | — |
case-06 | pass→pass | 24,245 | 25,677 | +6% | 1 | 1 | 0% | 3,702 | 5,488 | +48% | 0 | 0 | — |
case-07 | fail→pass | 7,150 | 9,472 | +32% | 1 | 1 | 0% | 1,385 | 1,939 | +40% | 0 | 0 | — |
case-08 | fail→pass | 13,394 | 8,541 | -36% | 1 | 1 | 0% | 1,602 | 1,910 | +19% | 0 | 0 | — |
case-09 | fail→pass | 15,269 | 8,480 | -44% | 1 | 1 | 0% | 1,794 | 1,978 | +10% | 0 | 0 | — |
case-10 | fail→pass | 12,075 | 3,066 | -75% | 1 | 1 | 0% | 1,266 | 1,826 | +44% | 0 | 0 | — |
case-11 | pass→pass | 7,779 | 6,124 | -21% | 1 | 1 | 0% | 1,443 | 2,381 | +65% | 0 | 0 | — |
case-12 | pass→pass | 9,799 | 1,901 | -81% | 1 | 1 | 0% | 920 | 1,534 | +67% | 0 | 0 | — |
case-13 | fail→pass | 12,018 | 9,644 | -20% | 1 | 1 | 0% | 2,374 | 2,033 | -14% | 0 | 0 | — |
case-14 | pass→pass | 15,106 | 3,477 | -77% | 1 | 1 | 0% | 1,916 | 1,884 | -2% | 0 | 0 | — |
case-15 | fail→pass | 15,422 | 2,157 | -86% | 1 | 1 | 0% | 1,811 | 1,525 | -16% | 0 | 0 | — |
case-16 | fail→pass | 13,017 | 5,282 | -59% | 1 | 1 | 0% | 1,422 | 2,259 | +59% | 0 | 0 | — |
case-17 | fail→pass | 12,023 | 2,101 | -83% | 1 | 1 | 0% | 2,241 | 1,716 | -23% | 0 | 0 | — |
case-18 | fail→pass | 14,444 | 8,708 | -40% | 1 | 1 | 0% | 2,005 | 2,029 | +1% | 0 | 0 | — |
case-19 | pass→pass | 7,649 | 1,876 | -75% | 1 | 1 | 0% | 1,591 | 1,587 | -0% | 0 | 0 | — |
case-20 | fail→pass | 14,104 | 3,043 | -78% | 1 | 1 | 0% | 1,648 | 1,860 | +13% | 0 | 0 | — |
case-21 | pass→pass | 15,689 | 15,249 | -3% | 1 | 1 | 0% | 2,064 | 3,403 | +65% | 0 | 0 | — |
case-22 | pass→pass | 2,336 | 1,000 | -57% | 1 | 1 | 0% | 504 | 1,439 | +186% | 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 +59 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
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.