feat(setup): add gitea actions CI/CD workflows
Some checks failed
Lint / Lint Code (push) Failing after 49s
Test / Type Check (push) Failing after 2s
Build / Build Project (pull_request) Failing after 16s
Lint / Lint Code (pull_request) Failing after 2s
Test / Type Check (pull_request) Failing after 2s

This commit is contained in:
Ilia Mashkov
2025-12-30 13:06:27 +03:00
parent 509e0bd01d
commit a1f34d6942
5 changed files with 872 additions and 0 deletions

562
.gitea/README.md Normal file
View File

@@ -0,0 +1,562 @@
# 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](#overview)
- [Workflow Files](#workflow-files)
- [Workflow Triggers](#workflow-triggers)
- [Setup Instructions](#setup-instructions)
- [Self-Hosted Runner Setup](#self-hosted-runner-setup)
- [Caching Strategy](#caching-strategy)
- [Environment Variables](#environment-variables)
- [Troubleshooting](#troubleshooting)
## Overview
The CI/CD pipeline consists of four main workflows:
1. **Lint** - Code quality checks (oxlint, dprint formatting)
2. **Test** - Type checking and E2E tests (Playwright)
3. **Build** - Production build verification
4. **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 linter
- `dprint check` - Code formatting verification
**Triggers**:
- Push to `main`, `develop`, `feature/*` branches
- Pull requests to `main` or `develop`
- 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 checking
- `svelte-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 report
- `playwright-screenshots` - Screenshots from failed tests
---
### `.gitea/workflows/build.yml`
**Purpose**: Verify that the production build completes successfully.
**Steps**:
1. Checkout repository
2. Setup Node.js v20 with Yarn caching
3. Install dependencies with `--frozen-lockfile`
4. Run `svelte-kit sync` to prepare SvelteKit
5. Build the project with `NODE_ENV=production`
6. Upload build artifacts (`.svelte-kit/output`, `.svelte-kit/build`)
7. Run the preview server and verify it responds (health check)
**Triggers**:
- Push to `main` or `develop` branches
- Pull requests to `main` or `develop`
- 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**:
1. **Docker container registry** - Build and push Docker image
2. **SSH deployment** - Deploy to server via SSH
3. **Vercel** - Deploy to Vercel platform
**Triggers**:
- Push to `main` branch
- 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:
```yaml
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
1. Navigate to your Gitea instance
2. Go to **Site Administration****Actions**
3. Ensure Actions is enabled
4. Configure default runner settings if needed
### Step 2: Configure Repository Settings
1. Go to your repository in Gitea
2. Click **Settings****Actions**
3. Enable Actions for the repository if not already enabled
4. 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:
```bash
git add .gitea/workflows/
git commit -m "Add Gitea Actions CI/CD workflows"
git push origin main
```
### Step 4: Verify Workflows Run
1. Navigate to **Actions** tab in your repository
2. You should see the workflows trigger on the next push
3. Click into a workflow run to view logs and status
### Step 5: Configure Secrets (Optional - for deployment)
1. Go to repository **Settings****Secrets****Actions**
2. Click **Add New Secret**
3. 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):
```bash
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:
```bash
act_runner --version
```
#### Register the Runner
1. In Gitea, navigate to repository **Settings****Actions****Runners**
2. Click **New Runner**
3. Copy the registration token
4. Run the registration command:
```bash
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`:
```ini
[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:
```bash
sudo systemctl daemon-reload
sudo systemctl enable gitea-runner
sudo systemctl start gitea-runner
```
#### Check Runner Status
```bash
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
```bash
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:
```bash
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:
```bash
# 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:
```yaml
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
```
This caches:
- `node_modules` directory
- 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):
```yaml
- 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:
```bash
NODE_ENV=production # For build workflow
NODE_VERSION=20 # Node.js version used across all workflows
```
### Custom Environment Variables
To add custom environment variables:
1. Go to repository **Settings****Variables****Actions**
2. Click **Add New Variable**
3. Add variable name and value
4. Set scope (environment, repository, or organization)
Example for feature flags:
```
ENABLE_ANALYTICS=false
API_URL=https://api.example.com
```
Access in workflow:
```yaml
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**:
1. Verify Actions is enabled in Gitea site administration
2. Check repository Settings → Actions is enabled
3. Verify workflow files are in `.gitea/workflows/` directory
4. Check workflow YAML syntax (no indentation errors)
### Runner Offline
**Symptoms**: Runner shows as **Offline** or **Idle**
**Solutions**:
1. Check runner service status: `sudo systemctl status gitea-runner`
2. Review runner logs: `journalctl -u gitea-runner -f`
3. Verify network connectivity to Gitea instance
4. Restart runner: `sudo systemctl restart gitea-runner`
### Linting Fails with Formatting Errors
**Symptoms**: `dprint check` fails on CI but passes locally
**Solutions**:
1. Ensure dprint configuration (`dprint.json`) is committed
2. Run `yarn dprint fmt` locally before committing
3. Consider adding auto-fix workflow (see below)
### Playwright Tests Timeout
**Symptoms**: E2E tests fail with timeout errors
**Solutions**:
1. Check `playwright.config.ts` timeout settings
2. Ensure preview server starts before tests run (built into config)
3. Increase timeout in workflow:
```yaml
- 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**:
1. Increase Node.js memory limit:
```yaml
- name: Build project
run: yarn build
env:
NODE_OPTIONS: --max-old-space-size=4096
```
2. Ensure runner has sufficient RAM (minimum 2GB recommended)
### Permission Denied on Runner
**Symptoms**: Runner can't access repository or secrets
**Solutions**:
1. Verify runner has read access to repository
2. Check secret names match exactly in workflow
3. Ensure runner user has file system permissions
### Yarn Install Fails with Lockfile Conflict
**Symptoms**: `yarn install --frozen-lockfile` fails
**Solutions**:
1. Ensure `yarn.lock` is up-to-date locally
2. Run `yarn install` and commit updated `yarn.lock`
3. Do not use `--frozen-lockfile` if using different platforms (arm64 vs amd64)
### Slow Workflow Execution
**Symptoms**: Workflows take too long to complete
**Solutions**:
1. Verify caching is working (check logs for "Cache restored")
2. Use `--frozen-lockfile` for faster dependency resolution
3. Consider matrix strategy for parallel execution (not currently used)
4. Optimize Playwright tests (reduce test count, increase timeouts only if needed)
## Best Practices
### 1. Keep Dependencies Updated
Regularly update action versions:
```yaml
- 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:
```bash
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:
```bash
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:
```bash
# Pre-commit: Format code, lint staged files
# Pre-push: Full type check, format check, full lint
```
## Additional Resources
- [Gitea Actions Documentation](https://docs.gitea.com/usage/actions/overview)
- [Gitea act_runner Documentation](https://docs.gitea.com/usage/actions/act-runner)
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [SvelteKit Deployment Guide](https://kit.svelte.dev/docs/adapters)
- [Playwright CI/CD Guide](https://playwright.dev/docs/ci)
## Status Badges
Add status badges to your README.md:
```markdown
![Lint](https://your-gitea-instance.com/username/glyphdiff/actions/badges/workflow/lint.yml/badge.svg)
![Test](https://your-gitea-instance.com/username/glyphdiff/actions/badges/workflow/test.yml/badge.svg)
![Build](https://your-gitea-instance.com/username/glyphdiff/actions/badges/workflow/build.yml/badge.svg)
```
## Next Steps
1. **Customize deployment**: Modify `deploy.yml` with your deployment strategy
2. **Add notifications**: Set up workflow failure notifications
3. **Optimize caching**: Add Playwright cache if needed
4. **Add badges**: Include status badges in README
5. **Schedule tasks**: Add periodic tests or dependency updates (optional)
---
**Last Updated**: December 30, 2025
**Version**: 1.0.0

View File

@@ -0,0 +1,59 @@
name: Build
on:
push:
branches:
- main
- develop
pull_request:
branches:
- main
- develop
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Build Project
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run SvelteKit sync
run: yarn svelte-kit sync
- name: Build project
run: yarn build
env:
NODE_ENV: production
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: |
.svelte-kit/output
.svelte-kit/build
retention-days: 7
- name: Verify build (Preview)
run: |
yarn preview &
PREVIEW_PID=$!
sleep 5
curl -f http://localhost:4173 || exit 1
kill $PREVIEW_PID

127
.gitea/workflows/deploy.yml Normal file
View File

@@ -0,0 +1,127 @@
name: Deploy
on:
push:
branches:
- main
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
default: 'production'
type: choice
options:
- staging
- production
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
deploy:
name: Deploy to ${{ github.event.inputs.environment || 'production' }}
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.environment || 'production' }}
# Only deploy after successful linting, testing, and building
needs: [lint, test, build]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build project
run: yarn build
env:
NODE_ENV: production
# Example deployment step - replace with your actual deployment strategy
# Options:
# - Docker container registry
# - Cloud provider (AWS, GCP, Azure)
# - Traditional hosting (Vercel, Netlify, Cloudflare Pages)
# - SSH deployment to VPS
# Example: Docker image build and push
# - name: Set up Docker Buildx
# uses: docker/setup-buildx-action@v3
# - name: Log in to Container Registry
# uses: docker/login-action@v3
# with:
# registry: ${{ secrets.REGISTRY_URL }}
# username: ${{ secrets.REGISTRY_USERNAME }}
# password: ${{ secrets.REGISTRY_PASSWORD }}
# - name: Build and push Docker image
# uses: docker/build-push-action@v5
# with:
# context: .
# push: true
# tags: ${{ secrets.REGISTRY_URL }}/glyphdiff:latest
# cache-from: type=gha
# cache-to: type=gha,mode=max
# Example: SSH deployment to server
# - name: Deploy to server via SSH
# uses: appleboy/ssh-action@v1.0.3
# with:
# host: ${{ secrets.DEPLOY_HOST }}
# username: ${{ secrets.DEPLOY_USER }}
# key: ${{ secrets.DEPLOY_SSH_KEY }}
# script: |
# cd /path/to/app
# git pull origin main
# yarn install --frozen-lockfile
# yarn build
# pm2 restart glyphdiff
# Example: Deploy to Vercel
# - name: Deploy to Vercel
# uses: amondnet/vercel-action@v25
# with:
# vercel-token: ${{ secrets.VERCEL_TOKEN }}
# vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
# vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
# vercel-args: '--prod'
- name: Deployment placeholder
run: |
echo "Deployment step not configured yet."
echo "Uncomment and modify one of the deployment examples above."
echo "Configure the necessary secrets in your Gitea instance:"
echo " - REGISTRY_URL, REGISTRY_USERNAME, REGISTRY_PASSWORD"
echo " - DEPLOY_HOST, DEPLOY_USER, DEPLOY_SSH_KEY"
echo " - VERCEL_TOKEN, VERCEL_ORG_ID, VERCEL_PROJECT_ID"
- name: Post-deployment health check
run: |
echo "Add health check here after deployment"
# curl -f https://your-app.com || exit 1
lint:
name: Lint Check
uses: ./.gitea/workflows/lint.yml
secrets: inherit
test:
name: Test Suite
uses: ./.gitea/workflows/test.yml
secrets: inherit
build:
name: Build Verification
uses: ./.gitea/workflows/build.yml
secrets: inherit

41
.gitea/workflows/lint.yml Normal file
View File

@@ -0,0 +1,41 @@
name: Lint
on:
push:
branches:
- main
- develop
- feature/*
pull_request:
branches:
- main
- develop
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: Lint Code
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run oxlint
run: yarn oxlint .
- name: Check code formatting
run: yarn dprint check

83
.gitea/workflows/test.yml Normal file
View File

@@ -0,0 +1,83 @@
name: Test
on:
push:
branches:
- main
- develop
- feature/*
pull_request:
branches:
- main
- develop
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
type-check:
name: Type Check
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Run TypeScript type check
run: yarn tsc --noEmit
- name: Run Svelte check
run: yarn svelte-check --threshold warning
# e2e-tests:
# name: E2E Tests (Playwright)
# runs-on: ubuntu-latest
#
# steps:
# - name: Checkout repository
# uses: actions/checkout@v4
#
# - name: Setup Node.js
# uses: actions/setup-node@v4
# with:
# node-version: '20'
# cache: 'yarn'
#
# - name: Install dependencies
# run: yarn install --frozen-lockfile
#
# - name: Install Playwright browsers
# run: yarn playwright install --with-deps
#
# - name: Run Playwright tests
# run: yarn test:e2e
#
# - name: Upload Playwright report
# if: always()
# uses: actions/upload-artifact@v4
# with:
# name: playwright-report
# path: playwright-report/
# retention-days: 7
#
# - name: Upload Playwright screenshots (on failure)
# if: failure()
# uses: actions/upload-artifact@v4
# with:
# name: playwright-screenshots
# path: test-results/
# retention-days: 7
#
# Note: E2E tests are disabled until Playwright setup is complete.
# Uncomment this job section when Playwright tests are ready to run.