- Moved unifiedFontStore creation from Page.svelte to Layout.svelte - Layout now creates store instance and provides it via setContext() - Page.svelte now receives store via getContext() instead of creating it - Fixes context accessibility issue where FiltersSidebar and FontSearch (siblings of Page) could not access the store - All child components now share the same store instance at Layout level This resolves the architectural issue where context only flows downward, not sideways. All components (FiltersSidebar, FontSearch, Page) are now children of Layout and can access the unifiedFontStore context.
Gitea Actions CI/CD Setup
This document describes the CI/CD pipeline configuration for the GlyphDiff project using Gitea Actions (GitHub Actions compatible).
Table of Contents
- Overview
- Workflow Files
- Workflow Triggers
- Setup Instructions
- Self-Hosted Runner Setup
- Caching Strategy
- Environment Variables
- Troubleshooting
Overview
The CI/CD pipeline consists of four main workflows:
- Lint - Code quality checks (oxlint, dprint formatting)
- Test - Type checking and E2E tests (Playwright)
- Build - Production build verification
- Deploy - Deployment automation (optional/template)
All workflows are designed to run on both push and pull request events, with appropriate branch filtering and concurrency controls.
Workflow Files
.gitea/workflows/lint.yml
Purpose: Run code quality checks to ensure code style and formatting standards.
Checks performed:
oxlint- Fast JavaScript/TypeScript linterdprint check- Code formatting verification
Triggers:
- Push to
main,develop,feature/*branches - Pull requests to
mainordevelop - Manual workflow dispatch
Cache: Node modules and Yarn cache
Concurrency: Cancels in-progress runs for the same branch when a new commit is pushed.
.gitea/workflows/test.yml
Purpose: Run type checking and end-to-end tests.
Jobs:
1. type-check job
tsc --noEmit- TypeScript type checkingsvelte-check --threshold warning- Svelte component type checking
2. e2e-tests job
- Installs Playwright browsers with system dependencies
- Runs E2E tests using Playwright
- Uploads test report artifacts (retained for 7 days)
- Uploads screenshots on test failure for debugging
Triggers: Same as lint workflow
Cache: Node modules and Yarn cache
Artifacts:
playwright-report- Test execution reportplaywright-screenshots- Screenshots from failed tests
.gitea/workflows/build.yml
Purpose: Verify that the production build completes successfully.
Steps:
- Checkout repository
- Setup Node.js v20 with Yarn caching
- Install dependencies with
--frozen-lockfile - Run
svelte-kit syncto prepare SvelteKit - Build the project with
NODE_ENV=production - Upload build artifacts (
.svelte-kit/output,.svelte-kit/build) - Run the preview server and verify it responds (health check)
Triggers:
- Push to
mainordevelopbranches - Pull requests to
mainordevelop - Manual workflow dispatch
Cache: Node modules and Yarn cache
Artifacts:
build-artifacts- Compiled SvelteKit output (retained for 7 days)
.gitea/workflows/deploy.yml
Purpose: Automated deployment pipeline (template configuration).
Current state: Placeholder configuration. Uncomment and customize one of the deployment examples.
Pre-deployment checks:
- Must pass linting workflow
- Must pass testing workflow
- Must pass build workflow
Deployment examples included:
- Docker container registry - Build and push Docker image
- SSH deployment - Deploy to server via SSH
- Vercel - Deploy to Vercel platform
Triggers:
- Push to
mainbranch - Manual workflow dispatch with environment selection (staging/production)
Secrets required (configure in Gitea):
- For Docker:
REGISTRY_URL,REGISTRY_USERNAME,REGISTRY_PASSWORD - For SSH:
DEPLOY_HOST,DEPLOY_USER,DEPLOY_SSH_KEY - For Vercel:
VERCEL_TOKEN,VERCEL_ORG_ID,VERCEL_PROJECT_ID
Workflow Triggers
Branch-Specific Behavior
| Workflow | Push Triggers | PR Triggers | Runs on Merge |
|---|---|---|---|
| Lint | main, develop, feature/* |
To main, develop |
Yes |
| Test | main, develop, feature/* |
To main, develop |
Yes |
| Build | main, develop |
To main, develop |
Yes |
| Deploy | main only |
None | Yes |
Concurrency Strategy
All workflows use concurrency groups based on the workflow name and branch reference:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # or false for deploy workflow
This ensures:
- For lint/test/build: New commits cancel in-progress runs (saves resources)
- For deploy: Prevents concurrent deployments (ensures safety)
Setup Instructions
Step 1: Verify Gitea Actions is Enabled
- Navigate to your Gitea instance
- Go to Site Administration → Actions
- Ensure Actions is enabled
- Configure default runner settings if needed
Step 2: Configure Repository Settings
- Go to your repository in Gitea
- Click Settings → Actions
- Enable Actions for the repository if not already enabled
- Set appropriate permissions for read/write access
Step 3: Push Workflows to Repository
The workflow files are already in .gitea/workflows/. Commit and push them:
git add .gitea/workflows/
git commit -m "Add Gitea Actions CI/CD workflows"
git push origin main
Step 4: Verify Workflows Run
- Navigate to Actions tab in your repository
- You should see the workflows trigger on the next push
- Click into a workflow run to view logs and status
Step 5: Configure Secrets (Optional - for deployment)
- Go to repository Settings → Secrets → Actions
- Click Add New Secret
- Add secrets required for your deployment method
Example secrets for SSH deployment:
DEPLOY_HOST=your-server.com
DEPLOY_USER=deploy
DEPLOY_SSH_KEY=-----BEGIN OPENSSH PRIVATE KEY-----
...
-----END OPENSSH PRIVATE KEY-----
Self-Hosted Runner Setup
Option 1: Using Gitea's Built-in Act Runner (Recommended)
Gitea provides act_runner (compatible with GitHub Actions runner).
Install act_runner
On Linux (Debian/Ubuntu):
wget -O /usr/local/bin/act_runner https://gitea.com/act_runner/releases/download/v0.2.11/act_runner-0.2.11-linux-amd64
chmod +x /usr/local/bin/act_runner
Verify installation:
act_runner --version
Register the Runner
- In Gitea, navigate to repository Settings → Actions → Runners
- Click New Runner
- Copy the registration token
- Run the registration command:
act_runner register \
--instance https://your-gitea-instance.com \
--token YOUR_REGISTRATION_TOKEN \
--name "linux-runner-1" \
--labels ubuntu-latest,linux,docker \
--no-interactive
Start the Runner as a Service
Create a systemd service file at /etc/systemd/system/gitea-runner.service:
[Unit]
Description=Gitea Actions Runner
After=network.target
[Service]
Type=simple
User=git
WorkingDirectory=/var/lib/gitea-runner
ExecStart=/usr/local/bin/act_runner daemon
Restart=always
RestartSec=5s
[Install]
WantedBy=multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable gitea-runner
sudo systemctl start gitea-runner
Check Runner Status
sudo systemctl status gitea-runner
Verify in Gitea: The runner should appear as Online with the ubuntu-latest label.
Option 2: Using Self-Hosted Runners with Docker
If you prefer Docker-based execution:
Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
Configure Runner to Use Docker
Ensure the runner has access to the Docker socket:
sudo usermod -aG docker act_runner_user
The workflows will now run containers inside the runner's Docker environment.
Option 3: Using External Runners (GitHub Actions Runner Compatible)
If you want to use standard GitHub Actions runners:
# Download and configure GitHub Actions runner
mkdir actions-runner && cd actions-runner
curl -o actions-runner-linux-x64-2.311.0.tar.gz -L https://github.com/actions/runner/releases/download/v2.311.0/actions-runner-linux-x64-2.311.0.tar.gz
tar xzf ./actions-runner-linux-x64-2.311.0.tar.gz
# Configure to point to Gitea instance
./config.sh --url https://your-gitea-instance.com --token YOUR_TOKEN
Caching Strategy
Node.js and Yarn Cache
All workflows use actions/setup-node@v4 with built-in caching:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
This caches:
node_modulesdirectory- Yarn cache directory (
~/.yarn/cache) - Reduces installation time from minutes to seconds on subsequent runs
Playwright Cache
Playwright browsers are installed fresh each time. To cache Playwright (optional optimization):
- name: Cache Playwright binaries
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-playwright-
Environment Variables
Default Environment Variables
The workflows use the following environment variables:
NODE_ENV=production # For build workflow
NODE_VERSION=20 # Node.js version used across all workflows
Custom Environment Variables
To add custom environment variables:
- Go to repository Settings → Variables → Actions
- Click Add New Variable
- Add variable name and value
- Set scope (environment, repository, or organization)
Example for feature flags:
ENABLE_ANALYTICS=false
API_URL=https://api.example.com
Access in workflow:
env:
API_URL: ${{ vars.API_URL }}
ENABLE_ANALYTICS: ${{ vars.ENABLE_ANALYTICS }}
Troubleshooting
Workflows Not Running
Symptoms: Workflows don't appear or don't trigger
Solutions:
- Verify Actions is enabled in Gitea site administration
- Check repository Settings → Actions is enabled
- Verify workflow files are in
.gitea/workflows/directory - Check workflow YAML syntax (no indentation errors)
Runner Offline
Symptoms: Runner shows as Offline or Idle
Solutions:
- Check runner service status:
sudo systemctl status gitea-runner - Review runner logs:
journalctl -u gitea-runner -f - Verify network connectivity to Gitea instance
- Restart runner:
sudo systemctl restart gitea-runner
Linting Fails with Formatting Errors
Symptoms: dprint check fails on CI but passes locally
Solutions:
- Ensure dprint configuration (
dprint.json) is committed - Run
yarn dprint fmtlocally before committing - Consider adding auto-fix workflow (see below)
Playwright Tests Timeout
Symptoms: E2E tests fail with timeout errors
Solutions:
- Check
playwright.config.tstimeout settings - Ensure preview server starts before tests run (built into config)
- Increase timeout in workflow:
- name: Run Playwright tests run: yarn test:e2e env: PLAYWRIGHT_TIMEOUT: 60000
Build Fails with Out of Memory
Symptoms: Build fails with memory allocation errors
Solutions:
- Increase Node.js memory limit:
- name: Build project run: yarn build env: NODE_OPTIONS: --max-old-space-size=4096 - Ensure runner has sufficient RAM (minimum 2GB recommended)
Permission Denied on Runner
Symptoms: Runner can't access repository or secrets
Solutions:
- Verify runner has read access to repository
- Check secret names match exactly in workflow
- Ensure runner user has file system permissions
Yarn Install Fails with Lockfile Conflict
Symptoms: yarn install --frozen-lockfile fails
Solutions:
- Ensure
yarn.lockis up-to-date locally - Run
yarn installand commit updatedyarn.lock - Do not use
--frozen-lockfileif using different platforms (arm64 vs amd64)
Slow Workflow Execution
Symptoms: Workflows take too long to complete
Solutions:
- Verify caching is working (check logs for "Cache restored")
- Use
--frozen-lockfilefor faster dependency resolution - Consider matrix strategy for parallel execution (not currently used)
- Optimize Playwright tests (reduce test count, increase timeouts only if needed)
Best Practices
1. Keep Dependencies Updated
Regularly update action versions:
- uses: actions/checkout@v4 # Update from v3 to v4 when available
- uses: actions/setup-node@v4
2. Use Frozen Lockfile
Always use --frozen-lockfile in CI to ensure reproducible builds:
yarn install --frozen-lockfile
3. Monitor Workflow Status
Set up notifications for workflow failures:
- Email notifications in Gitea user settings
- Integrate with Slack/Mattermost for team alerts
- Use status badges in README
4. Test Locally Before Pushing
Run the same checks locally:
yarn lint # oxlint
yarn dprint check # Formatting check
yarn tsc --noEmit # Type check
yarn test:e2e # E2E tests
yarn build # Build
5. Leverage Git Hooks
The project uses lefthook for pre-commit/pre-push checks. This catches issues before they reach CI:
# Pre-commit: Format code, lint staged files
# Pre-push: Full type check, format check, full lint
Additional Resources
- Gitea Actions Documentation
- Gitea act_runner Documentation
- GitHub Actions Documentation
- SvelteKit Deployment Guide
- Playwright CI/CD Guide
Status Badges
Add status badges to your README.md:



Next Steps
- Customize deployment: Modify
deploy.ymlwith your deployment strategy - Add notifications: Set up workflow failure notifications
- Optimize caching: Add Playwright cache if needed
- Add badges: Include status badges in README
- Schedule tasks: Add periodic tests or dependency updates (optional)
Last Updated: December 30, 2025 Version: 1.0.0