Skip to content

test: add Vitest unit-test flow (phase 1: pure functions) #53

test: add Vitest unit-test flow (phase 1: pure functions)

test: add Vitest unit-test flow (phase 1: pure functions) #53

Workflow file for this run

name: CI
on:
push:
branches: ['**']
tags: ['v*']
pull_request:
branches: [main]
jobs:
test:
name: Go unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.26'
cache-dependency-path: backend/go.sum
- run: cd backend && go mod download
- run: cd backend && go test ./controllers/ -timeout 30s
unit:
name: Web unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: cd web && npm ci
- run: cd web && npm run test:unit
e2e:
name: Playwright E2E
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create .env
run: |
echo "JWT_SECRET=ci-test-secret-$(openssl rand -hex 16)" >> .env
echo "PORT=80" >> .env
- uses: docker/setup-buildx-action@v3
- name: Build images with layer cache
run: |
docker buildx bake \
--set "backend.cache-from=type=gha,scope=lyftr-backend" \
--set "backend.cache-to=type=gha,scope=lyftr-backend,mode=max" \
--set "frontend.cache-from=type=gha,scope=lyftr-frontend" \
--set "frontend.cache-to=type=gha,scope=lyftr-frontend,mode=max" \
--load
- name: Start stack
run: docker compose up -d --wait
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: web/package-lock.json
- run: cd web && npm ci
- name: Cache Playwright browsers
uses: actions/cache@v4
id: playwright-cache
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ hashFiles('web/package-lock.json') }}
- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: cd web && npx playwright install chromium webkit
- name: Install Playwright system dependencies
run: cd web && npx playwright install-deps chromium webkit
- name: Wait for demo user to be seeded
run: |
timeout 90 bash -c 'until curl -sf -X POST http://localhost/api/v1/auth/login \
-H "Content-Type: application/json" \
-d "{\"email\":\"demo@lyftr.local\",\"password\":\"password123\"}" \
| grep -q "token"; do sleep 3; done'
- name: Run E2E tests
run: cd web && npm run test:e2e:docker
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
path: web/playwright-report/
retention-days: 7
version-smoke:
name: Version injection smoke test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build backend image with a known version
run: docker build --build-arg VERSION=smoke-9.9.9 -t lyftr-backend:smoke ./backend
- name: Assert /info reports the injected version
run: |
docker run -d --name lyftr-smoke -p 3000:3000 lyftr-backend:smoke
for i in $(seq 1 30); do curl -sf http://localhost:3000/health >/dev/null && break; sleep 1; done
info=$(curl -s http://localhost:3000/api/v1/info)
echo "info: $info"
echo "$info" | grep -q '"version":"smoke-9.9.9"'
- name: Cleanup
if: always()
run: docker rm -f lyftr-smoke || true
build-backend:
name: Build & push backend image
needs: [test, unit, e2e, version-smoke]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so `git describe --tags` resolves
- name: Resolve version
id: ver
run: echo "version=$(git describe --tags --always)" >> "$GITHUB_OUTPUT"
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/lyftr-backend
tags: |
type=ref,event=tag
type=raw,value=latest,enable={{is_default_branch}}
- uses: docker/build-push-action@v6
with:
context: ./backend
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
tags: ${{ steps.meta.outputs.tags }}
build-args: |
VERSION=${{ steps.ver.outputs.version }}
cache-from: type=gha,scope=lyftr-backend
cache-to: type=gha,scope=lyftr-backend,mode=max
build-frontend:
name: Build & push frontend image
needs: [test, unit, e2e]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/lyftr-frontend
tags: |
type=ref,event=tag
type=raw,value=latest,enable={{is_default_branch}}
- uses: docker/build-push-action@v6
with:
context: ./web
platforms: linux/amd64,linux/arm64,linux/arm/v7
push: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha,scope=lyftr-frontend
cache-to: type=gha,scope=lyftr-frontend,mode=max
deploy-demo:
name: Deploy to Fly.io
needs: [test, unit, e2e, version-smoke]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history so `git describe --tags` resolves
- uses: superfly/flyctl-actions/setup-flyctl@master
- name: Deploy
run: flyctl deploy --remote-only --build-arg VERSION="$(git describe --tags --always)"
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}