Skillshub algolia-ci-integration
install
source · Clone the upstream repo
git clone https://github.com/ComeOnOliver/skillshub
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/ComeOnOliver/skillshub "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/jeremylongshore/claude-code-plugins-plus-skills/algolia-ci-integration" ~/.claude/skills/comeonoliver-skillshub-algolia-ci-integration && rm -rf "$T"
manifest:
skills/jeremylongshore/claude-code-plugins-plus-skills/algolia-ci-integration/SKILL.mdsource content
Algolia CI Integration
Overview
Set up CI/CD pipelines for Algolia: run integration tests against a test index, validate index settings before deploy, and trigger reindexing on release.
Prerequisites
- GitHub repository with Actions enabled
- Algolia App ID and Admin key (stored as GitHub secrets)
- npm/pnpm project with
v5algoliasearch
Instructions
Step 1: Store Algolia Secrets
gh secret set ALGOLIA_APP_ID --body "YourApplicationID" gh secret set ALGOLIA_ADMIN_KEY --body "your_admin_api_key" gh secret set ALGOLIA_SEARCH_KEY --body "your_search_only_key"
Step 2: GitHub Actions — Test & Validate
# .github/workflows/algolia-ci.yml name: Algolia CI on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest env: ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} ALGOLIA_ADMIN_KEY: ${{ secrets.ALGOLIA_ADMIN_KEY }} steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - run: npm ci - name: Unit tests (mocked Algolia) run: npm test - name: Integration tests (real Algolia) if: env.ALGOLIA_APP_ID != '' run: npm run test:integration env: # Use timestamped index to avoid cross-PR collision ALGOLIA_TEST_INDEX: ci_test_${{ github.run_id }}_products validate-settings: runs-on: ubuntu-latest if: github.event_name == 'pull_request' env: ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} ALGOLIA_ADMIN_KEY: ${{ secrets.ALGOLIA_ADMIN_KEY }} steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '20', cache: 'npm' } - run: npm ci - name: Validate index settings match config run: npx tsx scripts/validate-algolia-settings.ts
Step 3: Index Settings Validation Script
// scripts/validate-algolia-settings.ts import { algoliasearch } from 'algoliasearch'; import expectedSettings from '../config/algolia-settings.json' assert { type: 'json' }; const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!); async function validateSettings() { const actual = await client.getSettings({ indexName: 'products' }); const errors: string[] = []; // Check critical settings match const checks: [string, any, any][] = [ ['searchableAttributes', actual.searchableAttributes, expectedSettings.searchableAttributes], ['attributesForFaceting', actual.attributesForFaceting, expectedSettings.attributesForFaceting], ['customRanking', actual.customRanking, expectedSettings.customRanking], ]; for (const [field, actual, expected] of checks) { if (JSON.stringify(actual) !== JSON.stringify(expected)) { errors.push(`${field}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`); } } if (errors.length > 0) { console.error('Settings drift detected:'); errors.forEach(e => console.error(` - ${e}`)); process.exit(1); } console.log('All Algolia settings match expected configuration.'); } validateSettings().catch(e => { console.error(e); process.exit(1); });
Step 4: Integration Test Pattern
// tests/integration/algolia.integration.test.ts import { describe, it, expect, afterAll } from 'vitest'; import { algoliasearch } from 'algoliasearch'; const client = algoliasearch(process.env.ALGOLIA_APP_ID!, process.env.ALGOLIA_ADMIN_KEY!); const testIndex = process.env.ALGOLIA_TEST_INDEX || `test_${Date.now()}`; describe.skipIf(!process.env.ALGOLIA_APP_ID)('Algolia Integration', () => { afterAll(async () => { // Clean up test index try { await client.deleteIndex({ indexName: testIndex }); } catch {} }); it('indexes records and searches', async () => { const { taskID } = await client.saveObjects({ indexName: testIndex, objects: [ { objectID: '1', name: 'Test Widget', category: 'tools' }, { objectID: '2', name: 'Test Gadget', category: 'electronics' }, ], }); await client.waitForTask({ indexName: testIndex, taskID }); const { hits, nbHits } = await client.searchSingleIndex({ indexName: testIndex, searchParams: { query: 'widget' }, }); expect(nbHits).toBe(1); expect(hits[0].name).toBe('Test Widget'); }); it('applies filters correctly', async () => { await client.setSettings({ indexName: testIndex, indexSettings: { attributesForFaceting: ['category'] }, }); // Wait for settings propagation await new Promise(r => setTimeout(r, 2000)); const { hits } = await client.searchSingleIndex({ indexName: testIndex, searchParams: { query: '', filters: 'category:tools' }, }); expect(hits.every(h => h.category === 'tools')).toBe(true); }); });
Step 5: Deploy-Triggered Reindex
# .github/workflows/algolia-deploy.yml name: Algolia Reindex on Deploy on: push: tags: ['v*'] jobs: reindex: runs-on: ubuntu-latest env: ALGOLIA_APP_ID: ${{ secrets.ALGOLIA_APP_ID }} ALGOLIA_ADMIN_KEY: ${{ secrets.ALGOLIA_ADMIN_KEY }} steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: '20', cache: 'npm' } - run: npm ci - name: Full reindex from data source run: npx tsx scripts/full-reindex.ts - name: Verify index health run: npx tsx scripts/verify-index-health.ts
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Secret not available | Secrets not set or wrong name | to verify |
| Test index collision | Parallel CI runs | Use in index name |
| Integration test timeout | Network latency to Algolia | Increase vitest timeout: |
| Settings drift | Manual dashboard change | Run settings validation in CI |
Resources
Next Steps
For deployment patterns, see
algolia-deploy-integration.