Files
rengine/.github/workflows/test.yml
T
Yogesh OjhaandClaude Opus 5 42b82b2faf refactor(frontend): one relative-time arithmetic, and a place to test it
relativeTime and formatDistanceToNow computed the same elapsed time twice and
diverged three ways:

- formatDistanceToNow deliberately omitted "ago", so the caller had to append
  it — and three of its five call sites did not. The Targets list's Updated
  column read a bare "2 days", and the engine and context cards read "used 3
  hours", which is a duration, not a point in time.
- relativeTime had no years bucket, so a three-year-old timestamp read
  "36mo ago".
- formatDistanceToNow was not null-safe: new Date(null) is the epoch, so a
  missing date read "56 years".

One `elapsed()` now picks the bucket and two renderings print it —
`relativeTime` ("3h ago") and `relativeTimeLong` ("3 hours ago"), both
null-safe. formatDistanceToNow is gone. The unit table runs largest-first and
takes the first count >= 1, which removes the 360-to-365-day gap the two
30-day-month / 365-day-year ladders had between them and makes a clock running
ahead of ours read "just now" rather than a negative count.

The bug was a copy error in a pure function, which is the kind a test catches,
and the frontend had no test runner at all. Add vitest: `npm run test`, its own
config (sveltekit() wants a running kit), node environment, `src/**/*.test.ts`,
and a CI step beside lint and check. 34 tests on the clock-frozen table, each
proven to fail against a mutation — including a clamp the tests showed was dead
code, since the `count >= 1` guard already rejects a future timestamp.

node_modules is baked into the frontend image, so this needs
`docker compose build frontend`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013dKUV96WkQQETZBMoAG98C
2026-09-11 07:56:28 +05:30

114 lines
2.8 KiB
YAML

name: 🧪 Tests
on:
push:
branches:
- master
- release/*
pull_request:
branches:
- master
- release/*
concurrency:
group: tests-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
name: 🧹 Lint
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout the git repo
uses: actions/checkout@v4
- name: 🐍 Install uv
uses: astral-sh/setup-uv@v5
- name: 🧹 ruff check
run: uvx ruff@0.14.14 check api shared reports worker interest connectors mcp toolbox stages tools
- name: 🎨 ruff format
run: uvx ruff@0.14.14 format --check api shared reports worker interest connectors mcp toolbox stages tools tests
frontend:
name: 🎨 Frontend checks
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
steps:
- name: 📥 Checkout the git repo
uses: actions/checkout@v4
- name: 🟢 Set up Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: frontend/package-lock.json
- name: 📦 Install
run: npm ci
- name: 🧹 Lint
run: npm run lint
- name: 🔎 Type check
run: npm run check
- name: 🧪 Unit tests
run: npm run test
pytest:
name: 🐍 Python tests
runs-on: ubuntu-latest
steps:
- name: 📥 Checkout the git repo
uses: actions/checkout@v4
- name: 🔑 Write a throwaway environment
run: |
cat > .env <<'ENV'
DEBUG=true
POSTGRES_USER=rengine
POSTGRES_PASSWORD=rengine
POSTGRES_DB=rengine
POSTGRES_HOST=db
POSTGRES_PORT=5432
POSTGRES_SHARED_BUFFERS=256MB
POSTGRES_EFFECTIVE_CACHE_SIZE=1GB
POSTGRES_WORK_MEM=16MB
POSTGRES_MAINTENANCE_WORK_MEM=128MB
REDIS_HOST=redis
REDIS_PORT=6379
SECRET_KEY=ci-only-not-a-secret-0000000000000000
ADMIN_EMAIL=admin@rengine.local
ADMIN_USERNAME=rengine
ADMIN_PASSWORD=ci-only-not-a-secret
ENV
- name: 🏗️ Build the api image
run: docker compose build api
- name: 🐘 Start postgres and redis
run: |
docker compose up -d db redis
for _ in $(seq 1 60); do
docker compose exec -T db pg_isready -U rengine && break
sleep 2
done
- name: 🧪 pytest
run: >
docker compose run --rm --no-deps api
sh -lc 'cd /app && /app/.venv/bin/python -m pytest tests -q --tb=short'
- name: 📜 Service logs on failure
if: failure()
run: docker compose logs --tail 200 db api
- name: 🧹 Tear down
if: always()
run: docker compose down -v