Glean CI Integration

SkillSearch

'CI/CD for Glean connectors with automated indexing tests and search

Use Glean CI Integration in Claude, ChatGPT or Ahel Desktop

Free. Sign in, add Glean CI Integration and connect your AI. About a minute.

Also: Claude Code · Cursor · Codex

Then ask your AI: use the Glean CI Integration skill

Details

Instructions available. Your AI can read the instructions. Execution depends on the setup they require.

Add Ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.

Glean CI IntegrationStart free

What this skill tells your AI

The instructions your AI receives, as published by jeremylongshore/tons-of-skills-marketplace in skills/.curated/glean-ci-integration/SKILL.md and read by Ahel’s review.

Overview

Set up CI/CD for Glean enterprise search integrations: run unit tests with mocked search and indexing responses on every PR, validate connector document transforms and search quality against a staging Glean instance on merge to main. Glean indexes content across SaaS tools, so CI pipelines focus on connector data transforms, indexing API calls, and search relevance regression testing.

Prerequisites

  • A CI secret reference rather than a literal token and a sandbox endpoint accepting only fictitious tenant and datasource IDs.
  • Fixtures with no employee names, customer content, or production URLs; redact headers and bodies from logs.
  • A protected branch and an approved rollback mechanism for any deployment or connector configuration the pipeline can influence.

Instructions

  1. Run mocked unit tests first, including deny-by-default ACL and malformed-response cases.
  2. Run a bounded sandbox batch with an idempotency key; prohibit production destinations in CI configuration.
  3. Emit only aggregate counts, correlation IDs, and policy versions, and fail on an unexpected destination, expanded ACL, or unredacted log assertion.
  4. Promote through a canary datasource after review, test both allow and deny identities, and restore the last known-good revision on failure.

GitHub Actions Workflow

# .github/workflows/glean-ci.yml
name: Glean CI
on:
  pull_request:
    paths: ['src/connectors/**', 'tests/**']
  push:
    branches: [main]

jobs:
  unit-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci
      - run: npm test -- --reporter=verbose

  integration-tests:
    if: github.ref == 'refs/heads/main'
    needs: unit-tests
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci
      - run: npm run test:integration
        env:
          GLEAN_API_KEY: ${{ secrets.GLEAN_API_KEY }}
          GLEAN_DOMAIN: ${{ secrets.GLEAN_DOMAIN }}

Mock-Based Unit Tests

// tests/glean-service.test.ts
import { describe, it, expect, vi } from 'vitest';
import { indexDocuments, searchDocuments } from '../src/glean-service';

vi.mock('../src/glean-client', () => ({
  GleanClient: vi.fn().mockImplementation(() => ({
    indexDocuments: vi.fn().mockResolvedValue({ indexed: 3, failed: 0 }),
    search: vi.fn().mockResolvedValue({
      results: [
        { title: 'Onboarding Guide', datasource: 'confluence', url: 'https://wiki.co/onboard' },
        { title: 'Deploy Process', datasource: 'notion', url: 'https://notion.so/deploy' },
      ],
      totalResults: 2,
    }),
    getDatasources: vi.fn().mockResolvedValue(['confluence', 'notion', 'gdrive']),
  })),
}));

describe('Glean Service', () => {
  it('indexes documents and returns count', async () => {
    const result = await indexDocuments([
      { title: 'Doc 1', body: 'Content', datasource: 'custom' },
    ]);
    expect(result.indexed).toBe(3);
    expect(result.failed).toBe(0);
  });

  it('searches across datasources', async () => {
    const results = await searchDocuments('onboarding');
    expect(results.totalResults).toBe(2);
    expect(results.results[0].datasource).toBe('confluence');
  });
});

Integration Tests

// tests/integration/glean.integration.test.ts
import { describe, it, expect } from 'vitest';

const hasKey = !!process.env.GLEAN_API_KEY;

describe.skipIf(!hasKey)('Glean Live API', () => {
  it('searches enterprise content', async () => {
    const res = await fetch(`https://${process.env.GLEAN_DOMAIN}-be.glean.com/api/v1/search`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.GLEAN_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ query: 'test', pageSize: 1 }),
    });
    expect(res.status).toBe(200);
    const body = await res.json();
    expect(body).toHaveProperty('results');
  });
});

Error Handling

CI IssueCauseFix
401 UnauthorizedInvalid API token or wrong domainVerify token at admin.glean.com
Indexing returns 0 documentsDocument format doesn't match schemaValidate document structure against Glean connector spec
Search quality regressionIndex not yet updatedAdd wait between indexing and search quality checks
Datasource not foundConnector not configured in stagingSet up test datasource in Glean admin before CI runs
Rate limit (429)Too many indexing callsBatch documents (max 100 per call) and add throttling

Output

Publish a CI receipt with commit SHA, fixture revision, sandbox datasource, test totals, policy checks, canary outcome, and rollback reference. Exclude secrets, payloads, and real search queries.

Examples

sha=abc123; fixtures=v5; sandbox=ci-synthetic; tests=18/18; acl_allow=pass; acl_deny=pass; canary=not-promoted is a valid pre-production receipt.

Resources

Next Steps

For deployment patterns, see glean-deploy-integration.

Signals

GitHub stars
3k
Forks
415
Last commit
Oct 2026
Advanced
Item type
skill
Key
glean-ci-integration
Source
github.com/jeremylongshore/tons-of-skills-marketplace