技能 编程开发 Lindy Webhook CI/CD 集成测试

Lindy Webhook CI/CD 集成测试

v20260423
lindy-ci-integration
本指南提供配置持续集成/持续部署(CI/CD)流程的框架,用于自动化测试 Lindy AI 代理的集成代码。它指导用户使用 GitHub Actions 和 Node.js,实现对 Webhook 接收器、数据负载处理以及身份验证的自动化测试,确保系统部署的高可靠性。
获取技能
118 次下载
概览

Lindy CI Integration

Overview

Lindy agents run on Lindy's managed platform — CI/CD tests your integration code: webhook receivers, callback handlers, and application logic that interacts with Lindy agents. Test webhook signature verification, payload processing, and error handling without hitting live Lindy endpoints.

Prerequisites

  • GitHub repository with Actions enabled
  • Lindy API key and webhook secret stored as GitHub secrets
  • Node.js project with webhook receiver code
  • Completed lindy-install-auth setup

Instructions

Step 1: Store Secrets in GitHub

gh secret set LINDY_API_KEY --body "lnd_live_xxxxxxxxxxxx"
gh secret set LINDY_WEBHOOK_SECRET --body "whsec_xxxxxxxxxxxx"

Step 2: Create GitHub Actions Workflow

# .github/workflows/lindy-integration.yml
name: Lindy Integration Tests

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'

      - run: npm ci

      - name: Run unit tests
        run: npm test
        env:
          LINDY_WEBHOOK_SECRET: ${{ secrets.LINDY_WEBHOOK_SECRET }}

      - name: Validate webhook handler
        run: npm run test:webhook

      - name: Connectivity check (non-blocking)
        continue-on-error: true
        run: |
          curl -s -o /dev/null -w "%{http_code}" \
            -X POST "https://public.lindy.ai/api/v1/webhooks/health" \
            -H "Authorization: Bearer ${{ secrets.LINDY_API_KEY }}"

Step 3: Write Webhook Handler Tests

// __tests__/webhook-handler.test.ts
import { describe, it, expect, vi } from 'vitest';
import request from 'supertest';
import { app } from '../src/server';

describe('Lindy Webhook Handler', () => {
  const VALID_SECRET = process.env.LINDY_WEBHOOK_SECRET || 'test-secret';

  it('rejects requests without auth header', async () => {
    const res = await request(app)
      .post('/lindy/callback')
      .send({ event: 'test' });
    expect(res.status).toBe(401);
  });

  it('rejects requests with wrong auth token', async () => {
    const res = await request(app)
      .post('/lindy/callback')
      .set('Authorization', 'Bearer wrong-token')
      .send({ event: 'test' });
    expect(res.status).toBe(401);
  });

  it('accepts requests with valid auth token', async () => {
    const res = await request(app)
      .post('/lindy/callback')
      .set('Authorization', `Bearer ${VALID_SECRET}`)
      .set('Content-Type', 'application/json')
      .send({
        taskId: 'task_123',
        status: 'completed',
        result: { summary: 'Test result' },
      });
    expect(res.status).toBe(200);
    expect(res.body.received).toBe(true);
  });

  it('handles malformed payload gracefully', async () => {
    const res = await request(app)
      .post('/lindy/callback')
      .set('Authorization', `Bearer ${VALID_SECRET}`)
      .set('Content-Type', 'application/json')
      .send('not-json');
    expect(res.status).toBeLessThan(500);
  });

  it('processes webhook payload fields correctly', async () => {
    const payload = {
      taskId: 'task_456',
      status: 'completed',
      result: {
        classification: 'billing',
        sentiment: 'neutral',
        summary: 'Customer asks about invoice #789',
      },
    };

    const res = await request(app)
      .post('/lindy/callback')
      .set('Authorization', `Bearer ${VALID_SECRET}`)
      .set('Content-Type', 'application/json')
      .send(payload);

    expect(res.status).toBe(200);
  });
});

Step 4: Add Smoke Test for Live Connectivity

// __tests__/connectivity.test.ts
import { describe, it, expect } from 'vitest';

describe('Lindy Connectivity (smoke)', () => {
  it('can reach Lindy webhook endpoint', async () => {
    const webhookUrl = process.env.LINDY_WEBHOOK_URL;
    if (!webhookUrl) {
      console.warn('LINDY_WEBHOOK_URL not set, skipping connectivity test');
      return;
    }

    const response = await fetch(webhookUrl, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.LINDY_WEBHOOK_SECRET}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ test: true, ci: true }),
    });

    expect(response.ok).toBe(true);
  });
});

Step 5: PR Status Check

# Add to existing workflow
      - name: Post test results
        if: always()
        uses: actions/github-script@v7
        with:
          script: |
            const status = '${{ job.status }}' === 'success' ? 'Passed' : 'Failed';
            if (context.payload.pull_request) {
              github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: context.payload.pull_request.number,
                body: `Lindy Integration Tests: **${status}**`
              });
            }

Test Categories

Category What It Tests Requires Live Lindy?
Auth verification Webhook signature checking No
Payload processing Data extraction and transformation No
Error handling Malformed input, edge cases No
Connectivity Webhook endpoint reachability Yes (non-blocking)
End-to-end Full trigger -> callback cycle Yes

Error Handling

Issue Cause Solution
Secret not found in CI Not configured gh secret set LINDY_WEBHOOK_SECRET
Connectivity test fails Lindy endpoint unreachable in CI Mark as continue-on-error: true
Tests timeout Network latency Set timeout-minutes: 10 on job
Flaky live tests Lindy processing delay Add retry logic or mock external calls

Resources

Next Steps

Proceed to lindy-deploy-integration for deployment automation.

信息
Category 编程开发
Name lindy-ci-integration
版本 v20260423
大小 4.44KB
更新时间 2026-04-28
语言