Automated build, test, and release pipeline using GitHub Actions.
Push/PR to main or develop:
┌──────────┬───────────┬────────────┬───────────┬───────────┬───────────┬───────────┐
│ Lint │ Typecheck │ Unit Tests │ E2E CLI │ E2E TUI │ E2E Web │ Storybook │
└──────────┴───────────┴────────────┴───────────┴───────────┴───────────┴───────────┘
┌──────────┬─────────┬──────────────────┐
│ Gitleaks │ Semgrep │ Security Enforce │
└──────────┴─────────┴──────────────────┘
(all run in parallel)
On PR only:
┌──────────────────────────────────────────────────────────────────────┐
│ Claude Review │ Documentation & Architecture compliance check │
└──────────────────────────────────────────────────────────────────────┘
On push to main only (after ALL jobs pass, including security):
┌───────────┐
│ Release │ → npm publish + GitHub release + `v<version>` tag
└───────────┘
On `v*` tag push (created by Release) or manual dispatch:
┌────────────────┐
│ Docker Publish │ → build image + push to ghcr.io
└────────────────┘
| Job | Description | Duration |
|---|---|---|
| Lint & Format | ESLint + Prettier + TypeSpec compile (pnpm tsp:compile) |
~30s |
| Type Check | TypeScript strict mode validation (requires TypeSpec types) | ~20s |
| Unit Tests | Vitest unit + integration tests (Linux + Windows) | ~20s |
| E2E (CLI) | CLI command execution tests (Linux + Windows) | ~30s |
| E2E (TUI) | Terminal UI interaction tests | ~20s |
| E2E (Web) | Playwright browser tests | ~25s |
| Storybook Build | Builds all stories (catches missing mocks/broken imports) | ~40s |
| Electron | Desktop installers for macOS/Windows/Linux | ~5m |
Note: Docker images are not built in the CI matrix. They are published by the separate
docker-publish.ymlworkflow, triggered by thev*release tag (see Docker Images).
Security scanners run in parallel and block releases on main:
| Scanner | Tool | Severity Filter |
|---|---|---|
| Gitleaks | Secret detection (API keys, passwords, tokens) | All findings |
| Semgrep | SAST rules (p/typescript, p/javascript, p/security-audit) |
All findings |
| Security Enforce | shep security enforce — supply-chain/governance posture |
Gates release |
Note: Gitleaks uses the CLI directly (not gitleaks-action) because the GitHub Action requires a paid license for organizations.
Automated code review using Claude Code, focusing on:
| Check Area | What It Validates |
|---|---|
| Documentation Consistency | Changes reflected in docs/, CLAUDE.md, AGENTS.md |
| Architecture Compliance | Clean Architecture layers, dependency rule, patterns |
| TDD & Testing | Test coverage for new functionality |
| Spec-Driven Workflow | Feature PRs have specs/ directory with required files |
Review Output:
- Inline comments on specific code issues
- Summary PR comment with findings and action items
Required Secret: CLAUDE_CODE_OAUTH_TOKEN (org-level)
Runs after all parallel jobs pass, including security scanners. Uses semantic-release to:
- Analyze commits - Determine version bump from conventional commits
- Generate changelog - Create release notes from commits
- Update CHANGELOG.md - Append new release section
- Publish to npm -
@shepai/clipackage - Create GitHub release - With changelog as release notes
- Commit changes -
chore(release): <version> [skip ci] - Push
v<version>tag - triggers theDocker Publishworkflow
Docker images are built and pushed by the separate
docker-publish.yml workflow,
which fires on the v* tag that semantic-release pushes (and can be run
manually via workflow dispatch).
Images are published to GitHub Container Registry (ghcr.io):
ghcr.io/shep-ai/shep
| Trigger | Tags |
|---|---|
v* tag (from release) |
latest, 1.2.3, 1.2, 1, sha-<full-commit-sha> |
| Manual dispatch (main) | latest, sha-<full-commit-sha> |
# Latest stable
docker pull ghcr.io/shep-ai/shep:latest
docker run ghcr.io/shep-ai/shep --version
# Specific version
docker pull ghcr.io/shep-ai/shep:v1.0.0
# Specific commit (for testing)
docker pull ghcr.io/shep-ai/shep:sha-abc123...- Base:
node:22-alpine(~180MB) - Final size: ~185MB
- User: Non-root
shep(UID 1001) - Entrypoint:
node dist/src/presentation/cli/index.js
Releases are fully automated based on Conventional Commits:
| Commit Type | Version Bump | Example |
|---|---|---|
feat: |
Minor (0.X.0) | feat(cli): add analyze command |
fix: |
Patch (0.0.X) | fix(agents): resolve memory leak |
perf: |
Patch | perf(db): optimize query performance |
refactor: |
Patch | refactor(core): simplify state management |
BREAKING CHANGE |
Major (X.0.0) | Footer in commit message |
Commits that don't trigger releases:
docs:,style:,test:,build:,ci:,chore:
If needed, you can trigger a release manually:
# Ensure you're on main with latest changes
git checkout main && git pull
# Run semantic-release in dry-run mode first
npx semantic-release --dry-run
# If satisfied, run actual release (requires NPM_TOKEN)
NPM_TOKEN=xxx GITHUB_TOKEN=xxx npx semantic-release| File | Purpose |
|---|---|
.github/workflows/ci.yml |
Main CI/CD workflow (build, test, security, release) |
.github/workflows/docker-publish.yml |
Build & push the image to ghcr.io on v* tags |
.github/workflows/pr-check.yml |
PR-specific checks (commitlint, PR title) |
.github/workflows/claude-review.yml |
Claude Code automated review |
release.config.mjs |
semantic-release plugins and settings |
Dockerfile |
Multi-stage build for production image |
.dockerignore |
Files excluded from Docker build context |
commitlint.config.mjs |
Commit message validation rules |
- PR builds: Use GitHub Actions cache (
type=gha) for layer caching - Release builds: No cache sharing with PR builds (semantic-release uses standard
docker build) - Workaround: Release builds are optimized via multi-stage Dockerfile caching
- PRs cancel previous runs on the same branch
- Main branch runs are never cancelled
- Release job has exclusive access via
[skip ci]in release commits
| Secret | Purpose | Where to Set |
|---|---|---|
GITHUB_TOKEN |
Automatic, provided by GitHub Actions | Built-in |
NPM_TOKEN |
Publishing to npm registry | Repository secrets |
CLAUDE_CODE_OAUTH_TOKEN |
Claude Code automated PR review | Organization secrets |
Recommended settings for main:
- Require status checks:
Lint & Format,Type Check,Unit Tests, all E2E jobs, all Security jobs - Require branches to be up to date
- Require linear history (optional, for cleaner git log)
- Check commit messages follow conventional format
- Ensure push is to
mainbranch - Verify commit doesn't contain
[skip ci] - Check if commit type triggers a release (see table above)
- Check
.dockerignoreisn't excluding required files - Verify
pnpm-lock.yamlis committed - Check Node.js version matches
package.jsonengines
- Verify
NPM_TOKENsecret is set and valid - Check package name isn't taken on npm
- Ensure version in
package.jsonwasn't manually bumped
docker build -t shep-cli .
docker run shep-cli --versionnpx semantic-release --dry-runecho "feat(cli): add new command" | npx commitlintUpdate when:
- CI/CD workflow changes
- New jobs are added
- Docker configuration changes
- Release process modifications
Related files: