This document describes the automated testing, building, and release processes for LobeChat. It covers the GitHub Actions workflows that handle continuous integration, semantic versioning, changelog generation, and multi-platform desktop application distribution.
For information about deployment options after release, see Deployment Options. For build configuration details, see Build System and Development Setup.
LobeChat employs a comprehensive CI/CD system built on GitHub Actions, with separate workflows for web application releases, desktop application builds, automated testing, and content management.
Sources: .github/workflows/release.yml1-87 .github/workflows/test.yml1-267 .github/workflows/release-desktop-beta.yml1-252 .github/workflows/auto-i18n.yml1-72 .github/workflows/sync.yml1-55
The test workflow runs on every push and pull request, implementing duplicate detection, sharded test execution, and comprehensive coverage reporting.
Sources: .github/workflows/test.yml13-267
The test-packages job tests multiple workspace packages sequentially in a single runner to optimize resource usage:
| Package Tested | Coverage Output |
|---|---|
@lobechat/file-loaders | packages/file-loaders/coverage/lcov.info |
@lobechat/prompts | packages/prompts/coverage/lcov.info |
@lobechat/model-runtime | packages/model-runtime/coverage/lcov.info |
@lobechat/web-crawler | packages/web-crawler/coverage/lcov.info |
@lobechat/agent-runtime | packages/agent-runtime/coverage/lcov.info |
@lobechat/conversation-flow | packages/conversation-flow/coverage/lcov.info |
model-bank | packages/model-bank/coverage/lcov.info |
The workflow uses a bash loop to test each package with bun run --filter <package> test:coverage and uploads individual coverage reports to Codecov with package-specific flags.
Sources: .github/workflows/test.yml28-101
App tests are split across 2 parallel runners using Vitest's sharding feature to reduce total execution time:
# Shard 1
vitest --coverage --silent='passed-only' --reporter=default --reporter=blob --shard=1/2
# Shard 2
vitest --coverage --silent='passed-only' --reporter=default --reporter=blob --shard=2/2
Both shards generate blob reports stored in .vitest-reports, which are later merged by vitest --merge-reports --coverage to produce a unified coverage report.
Sources: .github/workflows/test.yml103-173
The desktop test job runs pnpm test in the apps/desktop directory with pnpm package manager (distinct from the root workspace's bun usage).
The database test job spins up a PostgreSQL service container (paradedb/paradedb:latest) and runs database-specific tests with these environment variables:
DATABASE_TEST_URL: postgresql://postgres:postgres@localhost:5432/postgresDATABASE_DRIVER: nodeKEY_VAULTS_SECRET: Test encryption secretS3_PUBLIC_DOMAIN: Mock S3 domainAPP_URL: Mock app URLSources: .github/workflows/test.yml174-267 .github/workflows/release.yml23-33
The release workflow executes on every push to main or next branches, performing quality checks before triggering semantic versioning.
Sources: .github/workflows/release.yml18-87
The release process uses semantic-release (configured via package.json and .releaserc if present) with these environment variables:
GH_TOKEN: GitHub token for creating releasesNPM_TOKEN: NPM token for package publishingThe release script at package.json85 executes semantic-release, which:
Pre-build (package.json35):
Post-build (package.json37-38):
The build-sitemap script runs scripts/buildSitemapIndex/index.ts to generate sitemap XML files, while build-migrate-db executes database migrations via scripts/migrateServerDB/index.ts
Sources: .github/workflows/release.yml68-86 package.json35-43
Desktop builds are triggered by published GitHub releases with pre-release tags (beta, alpha, rc, nightly, next) and produce native installers for macOS, Windows, and Linux.
Sources: .github/workflows/release-desktop-beta.yml1-252
macOS Builds require code signing and notarization:
| Environment Variable | Purpose |
|---|---|
CSC_LINK | Base64-encoded Apple certificate |
CSC_KEY_PASSWORD | Certificate password |
APPLE_ID | Apple ID for notarization |
APPLE_APP_SPECIFIC_PASSWORD | App-specific password |
APPLE_TEAM_ID | Apple Developer Team ID |
All Platforms use these common variables:
| Variable | Value | Purpose |
|---|---|---|
UPDATE_CHANNEL | beta | Update channel identifier |
APP_URL | http://localhost:3015 | Local app URL |
DATABASE_URL | postgresql://postgres@localhost:5432/postgres | Local DB URL |
KEY_VAULTS_SECRET | Test secret | Encryption key |
Sources: .github/workflows/release-desktop-beta.yml88-149
The workflow merges separate latest-mac.yml files from Intel and ARM builds into a single unified update manifest using scripts/electronWorkflow/mergeMacReleaseFiles.js This script:
latest-mac.ymlSources: .github/workflows/release-desktop-beta.yml161-215
The desktop build process uses these npm scripts:
The complete flow is orchestrated by desktop:build which chains these commands.
Sources: package.json49-54
LobeChat maintains a sophisticated changelog system with JSON indices, MDX content files, and automated CDN optimization for images.
Sources: docs/changelog/index.json1-181 scripts/changelogWorkflow/const.ts1-13 src/server/services/changelog/index.ts1-221
The docs/changelog/index.json file contains two arrays:
Each entry maps to an MDX file at docs/changelog/{id}.mdx (with optional .zh-CN.mdx for Chinese).
Sources: docs/changelog/index.json1-181
The ChangelogService class at src/server/services/changelog/index.ts provides:
Key Methods:
| Method | Purpose |
|---|---|
getChangelogIndex() | Fetches and merges cloud/community indices |
getPostById(id, {locale}) | Fetches MDX content with locale support |
getLatestChangelogId() | Returns most recent changelog ID |
mergeChangelogs() | Combines cloud and community entries |
The service uses these configuration defaults:
urlTemplate: URL_TEMPLATE or env CHANGELOG_URL_TEMPLATEbranch: env DOCS_BRANCH or 'main'user: 'lobehub'repo: 'lobe-chat'changelogPath: 'changelog'docsPath: 'docs/changelog'Sources: src/server/services/changelog/index.ts28-221
The scripts/cdnWorkflow/index.ts script automatically uploads changelog images to S3:
Supported source CDNs:
https://github.com/lobehub/lobe-chat/assets/https://cdn.nlark.com/yuque/0/https://github.com/user-attachments/assetsSources: scripts/cdnWorkflow/index.ts36-230
The changelog workflow scripts transform semantic-release output into structured documentation:
Sources: scripts/changelogWorkflow/const.ts1-13 scripts/cdnWorkflow/index.ts1-230 package.json100
LobeChat uses scheduled workflows to maintain forks, update translations, sync database schemas, and monitor performance.
The .github/workflows/sync.yml workflow runs every 6 hours to keep forks synchronized:
Workflow Steps:
actions-cool/issues-helper to close issues with label 🚨 Sync Failaormsby/Fork-Sync-With-Upstream-action to sync from lobehub/lobe-chat:nextThis workflow only runs if github.event.repository.fork is true.
Sources: .github/workflows/sync.yml1-55
The .github/workflows/auto-i18n.yml workflow runs daily to update translations:
Process:
bun run i18n with OpenAI API credentialsstyle/auto-i18ni18n, automated, styleEnvironment variables required:
OPENAI_API_KEY: For translation API callsOPENAI_PROXY_URL: Optional proxyGH_TOKEN: For creating PRsThe i18n script at package.json66 runs:
Sources: .github/workflows/auto-i18n.yml1-72 package.json66-68
If the i18n workflow fails, .github/scripts/create-failure-issue.js creates or updates a GitHub issue with:
priority-high label if recurringSources: .github/scripts/create-failure-issue.js1-257
The .github/workflows/sync-database-schema.yml workflow updates dbdocs.io when the DBML file changes:
It runs npm run db:visualize which executes:
The DBML file is generated by npm run workflow:dbml which runs scripts/dbmlWorkflow/index.ts using drizzle-dbml-generator to convert Drizzle schema to DBML format.
Sources: .github/workflows/sync-database-schema.yml1-30 scripts/dbmlWorkflow/index.ts1-12 package.json48
The .github/workflows/lighthouse.yml workflow runs daily to monitor web performance:
Test Matrix:
| Test Name | URL | Output |
|---|---|---|
| LobeChat | Chat | https://lobechat.com/chat | lighthouse/chat |
| LobeChat | Market | https://lobechat.com/discover | lighthouse/discover |
Uses myactionway/lighthouse-badger-action to:
lobehub/lobe-chat lighthouse branchSources: .github/workflows/lighthouse.yml1-65
LobeChat follows semantic versioning with conventional commits to automate version bumping and changelog generation.
| Version Pattern | Example | Release Type |
|---|---|---|
2.0.0-next.389 | Current development | Pre-release (next) |
2.0.0-beta.1 | Desktop beta | Pre-release (beta) |
2.0.0-alpha.1 | Early testing | Pre-release (alpha) |
2.0.0-rc.1 | Release candidate | Pre-release (rc) |
2.0.0 | Production stable | Stable release |
1.143.0 | Legacy v1 branch | Stable release |
The current version is stored in package.json3 as "2.0.0-next.389".
Sources: package.json3 changelog/v2.json1-10
Semantic-release analyzes commit messages to determine version bumps:
| Commit Prefix | Version Impact | Example |
|---|---|---|
feat: | Minor bump | feat: Add MCP marketplace support |
fix: | Patch bump | fix: Resolve desktop auth countdown |
perf: | Patch bump | perf: Optimize message rendering |
BREAKING CHANGE: | Major bump | BREAKING CHANGE: Remove NextAuth |
docs:, style:, refactor: | No version bump | Documentation/code cleanup |
Sources: CHANGELOG.md9-21
| Branch | Purpose | Workflow Trigger |
|---|---|---|
main | Stable releases (2.x) | .github/workflows/release.yml |
next | Development releases (2.0.0-next.*) | .github/workflows/release.yml |
v1 | Legacy maintenance (1.x) | Separate release workflow |
Desktop beta releases trigger on any pre-release tag matching patterns: beta, alpha, rc, nightly, next.
Sources: .github/workflows/release.yml9-12 .github/workflows/release-desktop-beta.yml36-50
changelog/
├── CHANGELOG.v0.md # Archive: v0.x versions
├── CHANGELOG.v1.md # Archive: v1.x versions
└── v2.json # Structured v2.x index
CHANGELOG.md # Current v2.x markdown (root)
docs/changelog/
├── index.json # Community + cloud entries
├── 2025-12-20-mcp.mdx # Feature release posts
├── 2025-12-20-mcp.zh-CN.mdx # Localized versions
└── __statics__/ # Images and assets
The scripts/changelogWorkflow scripts parse CHANGELOG.md and generate:
Sources: scripts/changelogWorkflow/const.ts4-12
All workflows use concurrency groups to prevent duplicate runs:
This cancels in-progress workflows when new commits are pushed to the same branch.
Sources: .github/workflows/release.yml14-16 .github/workflows/test.yml9-11
The test workflow uses fkirc/skip-duplicate-actions to avoid redundant test runs:
This skips runs if identical content has been tested, except for manual triggers and scheduled runs.
Sources: .github/workflows/test.yml14-26
Workflows use these caching mechanisms:
| Tool | Cache Strategy | Configuration |
|---|---|---|
| bun | Built-in via oven-sh/setup-bun | Automatic global cache |
| pnpm | Version-specific | pnpm/action-setup@v2 with lockfile |
| Node modules | Disabled in setup-node | package-manager-cache: false |
The explicit package-manager-cache: false prevents conflicting caches between package managers.
Sources: .github/workflows/release.yml39-43 .github/workflows/test.yml40-45
| Artifact Type | Retention Period | Purpose |
|---|---|---|
| Blob test reports | 1 day | Temporary sharded test results |
| Desktop build artifacts | 1 day | Temporary multi-platform builds |
| Merged desktop release | 1 day | Final combined artifacts |
| Debug logs (i18n failures) | 7 days | Troubleshooting automation issues |
Sources: .github/workflows/test.yml136-138 .github/workflows/release-desktop-beta.yml214
The codecov.yml1-41 configures coverage reporting with component-based tracking:
Component Definitions:
Coverage Flags:
| Flag | Source | Threshold |
|---|---|---|
database | Database package tests | 0.5% |
app | Main app tests | 0.5% |
packages/* | Individual package tests | - |
desktop | Desktop app tests | - |
The threshold of 0.5% allows for gradual coverage improvement without blocking PRs.
Sources: codecov.yml1-41
Coverage data flows through multiple stages:
Package coverage uses a manual upload script with the Codecov CLI to support multiple flag uploads in a loop, while other test types use the codecov/codecov-action.
Sources: .github/workflows/test.yml62-101 .github/workflows/test.yml167-173
The project uses Husky for Git hooks (configured via npm run prepare which runs husky). Pre-commit hooks trigger lint-staged.
Sources: package.json79
Configured in package.json110-136:
| File Pattern | Commands |
|---|---|
*.md | remark --silent --output --prettier --write |
*.mdx | remark -r ./.remarkrc.mdx.js --silent --output --eslint --quiet --fix |
*.json | prettier --write |
*.{js,jsx} | prettier --writestylelint --fixeslint --fix |
*.{ts,tsx} | prettier --parser=typescript --writestylelint --fixeslint --fix |
This ensures code quality before commits enter the repository.
Sources: package.json110-136
| Secret | Used By | Purpose |
|---|---|---|
GH_TOKEN | release.yml, auto-i18n.yml | Create releases and PRs |
NPM_TOKEN | release.yml | Publish to npm registry |
OPENAI_API_KEY | auto-i18n.yml | Translation API calls |
OPENAI_PROXY_URL | auto-i18n.yml | Optional API proxy |
BUN_VERSION | Various workflows | Specific bun version |
CODECOV_TOKEN | test.yml | Upload coverage reports |
DBDOCS_TOKEN | sync-database-schema.yml | Update database docs |
Desktop Build Secrets:
| Secret | Platform | Purpose |
|---|---|---|
APPLE_CERTIFICATE_BASE64 | macOS | Code signing certificate |
APPLE_CERTIFICATE_PASSWORD | macOS | Certificate password |
APPLE_ID | macOS | Notarization Apple ID |
APPLE_APP_SPECIFIC_PASSWORD | macOS | App-specific password |
APPLE_TEAM_ID | macOS | Developer team ID |
UMAMI_BETA_DESKTOP_PROJECT_ID | All | Analytics project ID |
UMAMI_BETA_DESKTOP_BASE_URL | All | Analytics base URL |
Sources: .github/workflows/release.yml70-72 .github/workflows/auto-i18n.yml38-40 .github/workflows/release-desktop-beta.yml110-117
Test Failures:
Release Failures:
Desktop Build Failures:
i18n Failures:
The i18n workflow creates detailed failure issues with categorized troubleshooting steps when automated translation fails.
Sources: .github/scripts/create-failure-issue.js186-236
All scheduled workflows support manual triggering via workflow_dispatch:
Use this for testing workflow changes or forcing updates outside the schedule.
Sources: .github/workflows/auto-i18n.yml6 .github/workflows/sync.yml11
Refresh this wiki