Documentation

Git Workflow & Automated Testing

Complete guide to branching strategy, commit conventions, automated testing with Bun and Playwright, and semantic releases with GitHub Actions.

Last updated: 11/21/2025

Git Workflow & Automated Testing

Introduction

SveltyCMS uses a comprehensive Git workflow with automated testing and semantic versioning to ensure code quality and streamline the release process. Understanding this workflow is essential for all contributors.

Our CI/CD pipeline uses:

  • Bun Tests for fast unit & integration testing (~575 tests)
  • Playwright for comprehensive E2E testing (~40 tests)
  • Semantic Release for automated versioning
  • GitHub Actions for CI/CD automation
  • Test Gating to ensure releases only happen when tests pass
  • Future: Matrix testing across multiple databases (MongoDB, PostgreSQL, MariaDB, MySQL)

Table of Contents

  1. Branching Strategy
  2. Commit Message Convention
  3. GitHub Actions Workflows
  4. Automated Testing
  5. Release Process
  6. Development Workflow
  7. Best Practices

Branching Strategy

We have two primary, long-lived branches: main and next.

main Branch (Production)

  • Purpose: Production-ready, stable code. This branch represents the latest official release.
  • Protection:
    • Protected branch requiring pull request reviews
    • All code must first be merged into next
    • Promoted to main only after thorough testing
    • Tests must pass before any release is created
  • Automated Actions:
    • ✅ Runs full Playwright + Bun test suite
    • ✅ Only releases if tests pass
    • ✅ Creates stable semantic version (e.g., v1.3.0)
    • ✅ Automatically cleans /config/collections directory
    • ✅ Generates changelog and release notes
  • Key Rule: This branch must never contain test configurations. The /config/collections directory is automatically removed during the release process.

next Branch (Development)

  • Purpose: Development and staging. This is the primary branch for all new features, bug fixes, and ongoing work.
  • Pull Requests: All contributions should be made to feature branches and then submitted as pull requests targeting next.
  • Automated Actions:
    • ✅ Runs full test suite on every push
    • ✅ Tests both dev and preview modes
    • ✅ Matrix testing across multiple browsers
    • ✅ No automatic releases (tests only)
  • Testing Strategy:
    • Every push triggers comprehensive E2E and unit tests
    • Tests run in both development and production build modes
    • MongoDB service container for database testing
    • Automated database seeding before tests

Commit Message Convention

Our automated release process depends on a strict commit message format. We use the Conventional Commits specification. The release automation analyzes these messages to determine if a new version should be released and what the version number should be.

Format

Each commit message consists of a type, a scope (optional), and a subject:

<type>(<scope>): <subject>

[optional body]

[optional footer]

Common Commit Types

Type Description Version Impact Example
feat A new feature MINOR (1.2.0 → 1.3.0) feat(auth): add OAuth2 login
fix A bug fix PATCH (1.2.0 → 1.2.1) fix(api): resolve memory leak
docs Documentation only None docs: update installation guide
style Code style changes None style: fix indentation
refactor Code refactoring None refactor: simplify auth logic
perf Performance improvements PATCH perf(db): optimize query speed
test Adding or updating tests None test: add collection tests
chore Build/tooling changes None chore: update dependencies
ci CI/CD configuration None ci: update GitHub Actions
BREAKING CHANGE Breaking API change MAJOR (1.2.0 → 2.0.0) See below

Breaking Changes

To trigger a MAJOR version release, use one of these methods:

Method 1: Add ! after type

feat!: redesign collection API

Method 2: Add BREAKING CHANGE: footer

feat(api): redesign collection endpoints

BREAKING CHANGE: The collection API now uses different parameter names

⚠️ IMPORTANT: If your commit doesn’t use feat, fix, or BREAKING CHANGE, the automated system will not create a new version.


GitHub Actions Workflows

SveltyCMS uses two main workflows for CI/CD automation.

Workflow 1: Playwright Tests

File: .github/workflows/playwright.yml

Triggers:

  • Push to main or next
  • Pull requests to main
  • Called by auto-release workflow

What it does:

  1. Unit Tests Job: Runs Bun unit tests (~350 tests, ~2s)
  2. Integration Tests Job:
    • Starts MongoDB service container
    • Cleans config/ directory for fresh state
    • Starts dev server
    • Seeds test database via scripts/seed-test-db.ts
    • Runs Bun integration tests (~225 tests, ~15s)
  3. E2E Tests Job:
    • Starts MongoDB service container
    • Cleans config/ directory
    • Installs Playwright browsers
    • Starts dev server
    • Seeds test database
    • Runs Playwright E2E tests (~40 tests, ~60s)
    • Uploads test results and artifacts on failure

[!NOTE] Future Enhancement: Matrix testing across multiple databases

strategy:
  matrix:
    database: [mongodb, postgresql, mariadb, mysql]

This will ensure SveltyCMS works with all supported databases via Drizzle ORM.

Test Matrix:

strategy:
  matrix:
    browser: [chromium, firefox, webkit]
    mode: [dev, preview]

Workflow 2: Auto-Release

File: .github/workflows/auto-release.yaml

Triggers:

  • Push to main branch only

What it does:

  1. Runs tests first (calls playwright.yml)
  2. Only releases if tests pass
  3. Cleans /config/collections directory
  4. Runs semantic-release (version bump, changelog, GitHub release)

Test Gating:

jobs:
  test:
    # Run all tests
  release:
    needs: test # Only runs if tests pass
    if: success()

Automated Testing

SveltyCMS uses a dual-testing strategy combining fast unit tests with comprehensive E2E testing.

Testing Architecture

🧪 Bun Tests (Unit & Integration)

  • Speed: ⚡ Lightning fast (<5s for full suite)
  • Purpose: Business logic, services, widgets, security, API endpoints
  • Location: tests/bun/
  • Run: bun test tests/bun
  • Framework: Bun Test v1.3.1

🎭 Playwright Tests (E2E)

  • Speed: Thorough (30-60s per suite)
  • Purpose: User flows, UI interactions, cross-browser
  • Location: tests/playwright/
  • Run: bun x playwright test
  • Browsers: Chromium, Firefox, WebKit

Current Test Status (November 21, 2025)

  • 403 passing tests (~65%)
  • 172 failing tests (API/Setup integration)
  • ⏭️ 40 skipped tests (placeholders)
  • 📊 615 total tests
  • Unit tests: ~2s | Integration: ~15s | E2E: ~60s

Recently Fixed:

  • authorization.test.ts (22 tests) - Fixed mock database adapter
  • theme.test.ts (40 tests) - Fixed mockResolve signature
  • firewall.test.ts (27 tests) - Fixed logger import
  • user.test.ts (Integration) - Fixed auth flow & helpers
  • collections.test.ts (Integration) - Fixed dynamic config cleanup
  • setup.test.ts (Hooks) - Fixed mocking of node:fs & redirects

Fully Passing Test Suites:

  • ✅ Security (8/8 tests) - XSS detection, HTML sanitization
  • ✅ Widget Validation (8/8 tests) - RichText, form validation
  • ✅ Cache System (17/17 tests) - Redis, metrics, multi-tenant
  • ✅ UI Components (5/5 tests) - Store management
  • ✅ Content Utilities (6/6 tests) - Normalization, helpers
  • ✅ Server Hooks (89/89 tests) - All middleware hooks passing

⚠️ API Endpoints (Mixed) - Some integration test failures ❌ Setup Middleware (0/45 tests) - Requires fixes

See full test report

Running Tests Locally

Quick feedback (recommended):

# Fast unit tests
bun test tests/bun

# Specific test file
bun test tests/bun/services/SecurityResponseService.test.ts
bun test tests/bun/api/user.test.ts

# Specific test suite
bun test tests/bun/api/user.test.ts -t "createUser"

E2E testing:

# All E2E tests
bun x playwright test

# Interactive mode
bun x playwright test --ui

# Specific browser
bun x playwright test --project=chromium

Complete test suite:

# Bun + Playwright
bun run test:all

Test Infrastructure

Test Configuration:

  • bunfig.toml - Bun test configuration with Svelte preload
  • tests/bun/svelte-loader.js - Svelte component loader
  • tests/bun/mocks/setup.ts - Environment mocks (500+ lines)
  • playwright.config.ts - E2E test configuration

Test Helpers:

  • tests/bun/helpers/testSetup.ts - Fixtures, database cleanup, role resolution
  • tests/bun/helpers/server.ts - Server wait utility (prevents timeouts)
  • tests/bun/helpers/auth.ts - Real authentication helpers (FormData support)
  • tests/bun/helpers/db-helper.ts - API-based verification (no direct DB access)
  • tests/bun/mocks/setup.ts - Comprehensive environment mocking

Mocked Services:

  • SvelteKit environment ($app/environment)
  • Global settings (publicEnv, privateEnv)
  • Svelte 5 runes ($state, $derived, $effect)
  • Widget factory with 30+ widgets
  • Paraglide i18n messages (100+ translations)
  • Setup wizard store
  • Skeleton UI components

CI Integration:

  • Tests run on every push to main and next
  • Release blocked if tests fail
  • Matrix testing across 3 browsers × 2 modes = 6 configurations
  • MongoDB service container for E2E tests
  • Automatic database seeding

Release Process

Complete Flow

Development (→ next):

  1. Create feature branch from ‘next’
    git checkout -b feat/my-feature next
  2. Make changes with conventional commits
    git commit -m "feat(auth): add OAuth2 support"
  3. Push and create PR to ‘next’
    git push origin feat/my-feature
  4. Tests run automatically (Bun + Playwright)
  5. Merge after approval
    • Tests must pass
    • PR requires approval
  6. Tests run on ‘next’ (no release created)

Release (→ main):

  1. Create PR from ‘next’ to ‘main’
    • Ensure all features are stable
    • Review CHANGELOG
  2. Tests run automatically
    • Full Playwright suite
    • All Bun tests
    • Matrix testing
  3. Merge after approval
    • Requires maintainer approval
    • All checks must pass
  4. Tests run on ‘main’
    • Complete test suite
    • Database seeding
    • Cross-browser testing
  5. If tests pass:
    • ✅ semantic-release analyzes commits
    • ✅ Determines version bump
    • ✅ Updates package.json
    • ✅ Generates CHANGELOG.md
    • ✅ Creates GitHub release
    • ✅ Cleans /config/collections
  6. If tests fail:
    • ❌ No release created
    • ❌ Maintainers notified
    • ❌ Fix required before retry

Version Determination

Based on commit messages since last release:

Commits Version Change Example
fix: only PATCH 1.2.0 → 1.2.1
feat: present MINOR 1.2.0 → 1.3.0
BREAKING CHANGE: or ! MAJOR 1.2.0 → 2.0.0
No feat/fix/BREAKING No release -

Development Workflow

Step-by-Step Guide

1. Start a new feature:

# Update local next branch
git checkout next
git pull origin next

# Create feature branch
git checkout -b feat/my-feature

# Or for bug fix
git checkout -b fix/bug-description

2. Make changes:

# Write code
# Add tests

# Run tests locally
bun test
bun x playwright test

# Commit with conventional format
git add .
git commit -m "feat(auth): add OAuth2 support"

3. Push and create PR:

# Push to remote
git push origin feat/my-feature

# Create PR to 'next' on GitHub
# - Fill in PR template
# - Link related issues
# - Request reviewers

4. Address review comments:

# Make changes
git add .
git commit -m "fix(auth): address review comments"

# Push updates
git push origin feat/my-feature

5. Merge and cleanup:

# After PR is merged
git checkout next
git pull origin next

# Delete feature branch
git branch -d feat/my-feature
git push origin --delete feat/my-feature

Best Practices

Commit Messages

Good Examples:

  • feat(auth): add OAuth2 support
  • fix(api): resolve memory leak in user endpoint
  • docs: update testing guide
  • test(user): add avatar upload tests
  • perf(cache): optimize Redis queries
  • refactor(widget): simplify factory logic

Bad Examples:

  • fixed stuff
  • WIP
  • changes
  • update
  • asdf

Pull Requests

Before creating a PR:

  • ✅ Run tests locally (bun test)
  • ✅ Update relevant documentation
  • ✅ Add tests for new features
  • ✅ Follow code style guidelines
  • ✅ Use conventional commit messages

PR Guidelines:

  • Keep PRs focused and small (< 500 lines preferred)
  • Write clear descriptions
  • Link related issues
  • Respond to reviews promptly
  • Ensure CI passes before requesting review

Testing

Test-Driven Development:

# 1. Write failing test
bun test tests/bun/api/my-feature.test.ts

# 2. Implement feature
# ... code ...

# 3. Verify test passes
bun test tests/bun/api/my-feature.test.ts

# 4. Run full suite
bun test

Before pushing:

# Run all tests
bun test tests/bun

# Run E2E tests for affected features
bun x playwright test tests/my-feature.spec.ts

# Check for linting errors
bun run lint

Troubleshooting

Tests Failing in CI but Passing Locally

Common causes:

  • Different Node/Bun versions
    • Solution: Use .nvmrc or check CI version
  • Missing environment variables
    • Solution: Check GitHub Secrets configuration
  • Database state issues
    • Solution: Ensure tests clean up properly
  • Timing issues
    • Solution: Use waitForServer() helper

Release Not Created

Check:

  1. Did tests pass?
    • View GitHub Actions logs
  2. Did commits use conventional format?
    • Must have feat:, fix:, or BREAKING CHANGE:
  3. Are you on main branch?
    • Releases only happen on main
  4. Is semantic-release configured?
    • Check .releaserc configuration

Related Documentation

Follow these workflows for smooth development and reliable releases! 🚀

gitworkflowtestingci-cdreleasedevelopment