From documenso-pack
Configure CI/CD pipelines for Documenso integrations. Use when setting up automated testing, deployment pipelines, or continuous integration for Documenso projects. Trigger with phrases like "documenso CI", "documenso GitHub Actions", "documenso pipeline", "documenso automated testing".
How this skill is triggered — by the user, by Claude, or both
Slash command
/documenso-pack:documenso-ci-integrationThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Configure CI/CD pipelines for Documenso integrations with GitHub Actions. Covers unit testing with mocks, integration testing against staging, and deployment workflows with secret management.
Configure CI/CD pipelines for Documenso integrations with GitHub Actions. Covers unit testing with mocks, integration testing against staging, and deployment workflows with secret management.
documenso-local-dev-loop)# .github/workflows/documenso-ci.yml
name: Documenso CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
NODE_ENV: test
jobs:
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 mocks — no API key needed
integration-tests:
runs-on: ubuntu-latest
if: github.event_name == 'push' # Only on push to main/develop
needs: unit-tests
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- run: npm run test:integration
env:
DOCUMENSO_API_KEY: ${{ secrets.DOCUMENSO_STAGING_API_KEY }}
- run: npm run test:cleanup # Remove test documents
env:
DOCUMENSO_API_KEY: ${{ secrets.DOCUMENSO_STAGING_API_KEY }}
if: always()
// tests/unit/document-service.test.ts
import { describe, it, expect, vi, beforeEach } from "vitest";
import { createMockClient } from "../mocks/documenso";
import { DocumentService } from "../../src/services/document-service";
describe("DocumentService", () => {
let service: DocumentService;
let mockClient: ReturnType<typeof createMockClient>;
beforeEach(() => {
mockClient = createMockClient();
service = new DocumentService(mockClient as any);
});
it("creates document with recipients and sends", async () => {
const result = await service.createAndSend({
title: "Test Contract",
pdfPath: "./fixtures/test.pdf",
signers: [{ email: "[email protected]", name: "Test User" }],
});
expect(mockClient.documents.createV0).toHaveBeenCalledWith({ title: "Test Contract" });
expect(mockClient.documentsRecipients.createV0).toHaveBeenCalled();
expect(mockClient.documents.sendV0).toHaveBeenCalled();
expect(result.documentId).toBe(1);
});
it("handles API errors gracefully", async () => {
mockClient.documents.createV0.mockRejectedValue(
Object.assign(new Error("Unauthorized"), { statusCode: 401 })
);
await expect(service.createAndSend({
title: "Test",
pdfPath: "./fixtures/test.pdf",
signers: [],
})).rejects.toThrow("Unauthorized");
});
});
// tests/integration/document-lifecycle.test.ts
import { describe, it, expect, afterAll } from "vitest";
import { Documenso } from "@documenso/sdk-typescript";
const client = new Documenso({ apiKey: process.env.DOCUMENSO_API_KEY! });
const testDocIds: number[] = [];
describe("Document Lifecycle (Integration)", () => {
it("creates a document", async () => {
const doc = await client.documents.createV0({
title: "[CI-TEST] Integration Test",
});
testDocIds.push(doc.documentId);
expect(doc.documentId).toBeGreaterThan(0);
}, 30000);
it("lists documents", async () => {
const { documents } = await client.documents.findV0({ page: 1, perPage: 5 });
expect(documents.length).toBeGreaterThan(0);
}, 15000);
afterAll(async () => {
// Cleanup: delete test documents
for (const id of testDocIds) {
try {
await client.documents.deleteV0(id);
} catch {
console.warn(`Cleanup: could not delete document ${id}`);
}
}
});
});
# Using GitHub CLI
gh secret set DOCUMENSO_STAGING_API_KEY --body "api_stg_xxxxxxxxxxxx"
gh secret set DOCUMENSO_WEBHOOK_SECRET --body "whsec_xxxxxxxxxxxx"
# Verify secrets exist
gh secret list
{
"scripts": {
"test": "vitest run tests/unit/",
"test:integration": "vitest run tests/integration/ --timeout 60000",
"test:cleanup": "tsx scripts/cleanup-test-docs.ts",
"test:all": "npm test && npm run test:integration"
}
}
# .husky/pre-commit
npm test -- --run
This runs unit tests (with mocks) before every commit, catching issues early without needing API access.
| Test Type | Runs On | API Key Needed? | Speed |
|---|---|---|---|
| Unit tests (mocks) | Every push + PR | No | Fast (~5s) |
| Integration tests | Push to main/develop only | Yes (staging) | Slow (~30s) |
| Cleanup | After integration tests | Yes (staging) | Fast |
| CI Issue | Cause | Solution |
|---|---|---|
| Integration test timeout | Slow API | Increase vitest timeout to 60s |
| Rate limit in CI | Too many test runs | Use mocks for PRs, live API only on main |
| Secret not found | Missing GitHub secret | Add via gh secret set |
| Stale test data | Cleanup didn't run | Run npm run test:cleanup manually |
For deployment strategies, see documenso-deploy-integration.
npx claudepluginhub flight505/skill-forge --plugin documenso-packCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.