Bamboohr ci integration
425 plugins, 2,810 skills, 200 agents for Claude Code. Open-source marketplace at tonsofskills.com with the ccpi CLI package manager.
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill bamboohr-ci-integrationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
What its author says it does
Copied from the file, not written here
'Configure CI/CD pipelines for BambooHR integrations with GitHub Actions,
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.2 KB, as published. Nobody here has run it
BambooHR CI Integration
Overview
Set up CI/CD pipelines for BambooHR integrations with proper secret management, unit tests with mocked API, and optional integration tests against the real BambooHR API.
Prerequisites
- GitHub repository with Actions enabled
- BambooHR test API key (sandbox company or test account)
- npm/pnpm project with test suite configured
Instructions
Step 1: Configure GitHub Secrets
# Required for integration tests
gh secret set BAMBOOHR_API_KEY --body "your-test-api-key"
gh secret set BAMBOOHR_COMPANY_DOMAIN --body "your-test-company"
# Optional: webhook testing
gh secret set BAMBOOHR_WEBHOOK_SECRET --body "your-webhook-hmac-secret"
Step 2: GitHub Actions Workflow
# .github/workflows/bamboohr-integration.yml
name: BambooHR Integration
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Run daily to catch BambooHR API changes early
- cron: '0 6 * * 1-5'
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 run typecheck
- name: Unit tests (mocked BambooHR API)
run: npm test -- --coverage --reporter=verbose
- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage
path: coverage/
integration-tests:
runs-on: ubuntu-latest
# Only run on main branch and schedule (not PRs from forks)
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
needs: unit-tests
env:
BAMBOOHR_API_KEY: ${{ secrets.BAMBOOHR_API_KEY }}
BAMBOOHR_COMPANY_DOMAIN: ${{ secrets.BAMBOOHR_COMPANY_DOMAIN }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Integration tests (real BambooHR API)
run: npm run test:integration
timeout-minutes: 5
- name: API health check
run: |
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
-u "${BAMBOOHR_API_KEY}:x" \
-H "Accept: application/json" \
"https://api.bamboohr.com/api/gateway.php/${BAMBOOHR_COMPANY_DOMAIN}/v1/employees/directory")
echo "BambooHR API status: $STATUS"
[ "$STATUS" -eq 200 ] || exit 1
Step 3: Test Structure
// tests/unit/bamboohr-client.test.ts
import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest';
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw';
import { BambooHRClient } from '../../src/bamboohr/client';
const BASE = 'https://api.bamboohr.com/api/gateway.php/testco/v1';
const handlers = [
http.get(`${BASE}/employees/directory`, () =>
HttpResponse.json({
employees: [
{ id: '1', displayName: 'Jane', jobTitle: 'Eng', department: 'Dev' },
],
}),
),
http.get(`${BASE}/employees/:id/`, () =>
HttpResponse.json({ id: '1', firstName: 'Jane', lastName: 'Smith' }),
),
http.post(`${BASE}/reports/custom`, () =>
HttpResponse.json({ title: 'Report', employees: [] }),
),
// Simulate rate limit
http.get(`${BASE}/employees/ratelimited`, () =>
new HttpResponse(null, { status: 503, headers: { 'Retry-After': '1' } }),
),
];
const server = setupServer(...handlers);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
describe('BambooHRClient', () => {
const client = new BambooHRClient({ companyDomain: 'testco', apiKey: 'fake' });
it('fetches employee directory', async () => {
const dir = await client.getDirectory();
expect(dir.employees).toHaveLength(1);
expect(dir.employees[0].displayName).toBe('Jane');
});
it('fetches single employee with fields', async () => {
const emp = await client.getEmployee(1, ['firstName', 'lastName']);
expect(emp.firstName).toBe('Jane');
});
it('runs custom reports', async () => {
const report = await client.customReport(['firstName', 'department']);
expect(report.title).toBe('Report');
});
it('handles 503 rate limit with Retry-After', async () => {
await expect(
client.request('GET', '/employees/ratelimited'),
).rejects.toThrow(/503/);
});
});
// tests/integration/bamboohr-live.test.ts
import { describe, it, expect } from 'vitest';
import { BambooHRClient } from '../../src/bamboohr/client';
const HAS_CREDS = !!process.env.BAMBOOHR_API_KEY && !!process.env.BAMBOOHR_COMPANY_DOMAIN;
describe.skipIf(!HAS_CREDS)('BambooHR Live API', () => {
const client = new BambooHRClient({
companyDomain: process.env.BAMBOOHR_COMPANY_DOMAIN!,
apiKey: process.env.BAMBOOHR_API_KEY!,
});
it('should fetch employee directory', async () => {
const dir = await client.getDirectory();
expect(dir.employees.length).toBeGreaterThan(0);
expect(dir.employees[0]).toHaveProperty('displayName');
expect(dir.employees[0]).toHaveProperty('jobTitle');
}, 15_000);
it('should run a custom report', async () => {
const report = await client.customReport(['firstName', 'lastName', 'department']);
expect(report).toHaveProperty('employees');
expect(Array.isArray(report.employees)).toBe(true);
}, 15_000);
it('should fetch time off types', async () => {
const types = await client.request('GET', '/meta/time_off/types');
expect(types).toBeTruthy();
}, 15_000);
});
Step 4: PR Status Check
# Branch protection — require these checks to pass
# Settings > Branches > Branch protection rules
required_status_checks:
- 'unit-tests'
# integration-tests is optional (may fail if API is down)
Step 5: Scheduled API Health Monitoring
# .github/workflows/bamboohr-health.yml
name: BambooHR API Health
on:
schedule:
- cron: '0 */4 * * *' # Every 4 hours
jobs:
health-check:
runs-on: ubuntu-latest
env:
BAMBOOHR_API_KEY: ${{ secrets.BAMBOOHR_API_KEY }}
BAMBOOHR_COMPANY_DOMAIN: ${{ secrets.BAMBOOHR_COMPANY_DOMAIN }}
steps:
- name: Check BambooHR API
run: |
STATUS=$(curl -s -o /tmp/response.json -w "%{http_code}" \
-u "${BAMBOOHR_API_KEY}:x" \
-H "Accept: application/json" \
"https://api.bamboohr.com/api/gateway.php/${BAMBOOHR_COMPANY_DOMAIN}/v1/employees/directory")
if [ "$STATUS" -ne 200 ]; then
echo "::error::BambooHR API returned $STATUS"
exit 1
fi
COUNT=$(cat /tmp/response.json | jq '.employees | length')
echo "BambooHR API healthy: $COUNT employees"
Output
- Unit test pipeline with mocked BambooHR API
- Integration test pipeline with real API (gated on secrets)
- Scheduled health monitoring workflow
- PR status checks configured
- Coverage reports uploaded
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Secret not available in PR | Fork PR (no secrets access) | Use if guard on integration job |
| Integration test timeout | BambooHR API slow | Set timeout-minutes: 5 |
| Flaky 503 in tests | Rate limiting in CI | Add retry logic to test helpers |
| Health check false alarm | BambooHR maintenance | Check status page before alerting |
Resources
Next Steps
For deployment patterns, see bamboohr-deploy-integration.