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 published GitHub Release (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:
Required Secret: CLAUDE_CODE_OAUTH_TOKEN (org-level)
Runs after all parallel jobs pass, including security scanners. Uses semantic-release to:
@shepai/cli packageDocker Publish)chore(release): <version> [skip ci]v<version> tag - versioned tag pointing at the release commitDocker images are built and pushed by the separate
docker-publish.yml workflow,
which fires on the published GitHub Release (and can be run manually via
workflow dispatch). It is deliberately NOT triggered by the v* tag push:
semantic-release tags the chore(release): β¦ [skip ci] commit, and GitHub
Actions skips workflows for tags pointing at a [skip ci] commit. The
release event is immune to [skip ci], so it fires reliably.
Images are published to GitHub Container Registry (ghcr.io):
ghcr.io/shep-ai/shep
| Trigger | Tags |
|---|---|
Published Release (v* tag) |
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...
node:22-alpine (~180MB)shep (UID 1001)node dist/src/presentation/cli/index.jsReleases 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 |
type=gha) for layer cachingdocker build)[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:
Lint & Format, Type Check, Unit Tests, all E2E jobs, all Security jobsmain branch[skip ci].dockerignore isnβt excluding required filespnpm-lock.yaml is committedpackage.json enginesNPM_TOKEN secret is set and validpackage.json wasnβt manually bumpeddocker build -t shep-cli .
docker run shep-cli --version
npx semantic-release --dry-run
echo "feat(cli): add new command" | npx commitlint
Update when:
Related files: