Skip to content

Commit 366dc1c

Browse files
authored
Add wetterdienst frontend (#1561)
Frontend: Modern Nuxt.js-based web application providing interactive data exploration, comprehensive settings interface for all API parameters, climate stripes visualization, theme customization, and enhanced user experience
1 parent 1d307f7 commit 366dc1c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+18253
-2
lines changed

.github/workflows/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,31 @@ Check out the guide that was used to create the CI environment including setting
66
- https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action
77
- https://docs.github.com/en/actions/creating-actions/dockerfile-support-for-github-actions
88
- https://docs.github.com/en/actions/guides/publishing-docker-images
9+
10+
## Frontend CI
11+
12+
The frontend has its own dedicated workflow:
13+
14+
### `frontend-tests.yml`
15+
16+
Runs on changes to `frontend/**` directory.
17+
18+
**Jobs:**
19+
1. **lint** - ESLint and Oxlint checks
20+
2. **unit-tests** - Vitest unit and component tests (63 tests)
21+
3. **e2e-tests** - Playwright E2E tests with real backend (32 tests)
22+
23+
**E2E Test Flow:**
24+
1. Install Node.js, pnpm, and Playwright with Firefox
25+
2. Setup Python and install backend with uv
26+
3. Start backend API server on port 3000
27+
4. Run E2E tests against live backend
28+
5. Upload test artifacts (Playwright report)
29+
6. Cleanup backend process
30+
31+
**Caching:**
32+
- pnpm store cached for faster installs
33+
- Playwright browsers cached automatically
34+
35+
**Artifacts:**
36+
- Playwright HTML report (retained for 7 days)

.github/workflows/docker-publish.yml

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ concurrency:
2727
# The name for the produced image at ghcr.io.
2828
env:
2929
IMAGE_NAME: "${{ github.repository }}"
30-
PYTHON: "3.13"
30+
IMAGE_NAME_FRONTEND: "${{ github.repository }}-frontend"
31+
PYTHON: "3.14"
3132

3233
jobs:
3334
build_and_test:
@@ -61,6 +62,20 @@ jobs:
6162
docker build . -t wd
6263
docker run wd wetterdienst info
6364
65+
build_and_test_frontend:
66+
runs-on: ubuntu-latest
67+
steps:
68+
- name: Acquire sources
69+
uses: actions/checkout@v6
70+
with:
71+
persist-credentials: false
72+
73+
- name: Build frontend image
74+
run: |
75+
export DOCKER_BUILDKIT=1
76+
export BUILDKIT_PROGRESS=plain
77+
docker build -f frontend.Dockerfile -t wd-frontend .
78+
6479
docker:
6580
needs: build_and_test
6681
runs-on: ubuntu-latest
@@ -155,3 +170,90 @@ jobs:
155170
set -x
156171
git describe --tags
157172
git status
173+
174+
docker_frontend:
175+
needs: build_and_test_frontend
176+
runs-on: ubuntu-latest
177+
permissions:
178+
packages: write
179+
if: ${{ ! (startsWith(github.actor, 'dependabot') || github.event.pull_request.head.repo.fork ) }}
180+
181+
steps:
182+
- name: Acquire sources
183+
uses: actions/checkout@v6
184+
with:
185+
fetch-depth: 0
186+
persist-credentials: true
187+
188+
- name: Docker meta
189+
id: meta
190+
uses: docker/metadata-action@v5
191+
with:
192+
images: |
193+
ghcr.io/${{ env.IMAGE_NAME_FRONTEND }}
194+
tags: |
195+
type=schedule,pattern=nightly
196+
type=ref,event=pr
197+
type=semver,pattern={{version}}
198+
type=semver,pattern={{major}}.{{minor}}
199+
200+
- name: Inspect meta # zizmor: ignore[template-injection]
201+
run: |
202+
echo "Tags: ${{ steps.meta.outputs.tags }}"
203+
echo "Labels: ${{ steps.meta.outputs.labels }}"
204+
205+
- name: Set up QEMU
206+
uses: docker/setup-qemu-action@v3
207+
with:
208+
platforms: linux/amd64,linux/arm64
209+
210+
- name: Set up Docker Buildx
211+
id: buildx
212+
uses: docker/setup-buildx-action@v3 # zizmor: ignore[cache-poisoning]
213+
214+
- name: Cache Docker layers
215+
uses: actions/cache@v4 # zizmor: ignore[cache-poisoning]
216+
with:
217+
path: /tmp/.buildx-cache-frontend
218+
key: ${{ runner.os }}-buildx-frontend-${{ github.sha }}
219+
restore-keys: |
220+
${{ runner.os }}-buildx-frontend-
221+
222+
- name: Inspect builder # zizmor: ignore[template-injection]
223+
run: |
224+
echo "Name: ${{ steps.buildx.outputs.name }}"
225+
echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}"
226+
echo "Status: ${{ steps.buildx.outputs.status }}"
227+
echo "Flags: ${{ steps.buildx.outputs.flags }}"
228+
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
229+
230+
- name: Login to GHCR
231+
uses: docker/login-action@v3
232+
with:
233+
registry: ghcr.io
234+
username: ${{ github.repository_owner }}
235+
password: ${{ github.token }}
236+
237+
- name: Build and push
238+
uses: docker/build-push-action@v6
239+
with:
240+
context: .
241+
file: frontend.Dockerfile
242+
platforms: linux/amd64,linux/arm64
243+
tags: ${{ steps.meta.outputs.tags }}
244+
labels: ${{ steps.meta.outputs.labels }}
245+
push: true
246+
cache-from: type=local,src=/tmp/.buildx-cache-frontend
247+
cache-to: type=local,dest=/tmp/.buildx-cache-frontend-new
248+
provenance: false
249+
250+
- name: Move cache
251+
run: |
252+
rm -rf /tmp/.buildx-cache-frontend
253+
mv /tmp/.buildx-cache-frontend-new /tmp/.buildx-cache-frontend
254+
255+
- name: Display git status
256+
run: |
257+
set -x
258+
git describe --tags
259+
git status
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
name: Frontend Tests
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'frontend/**'
7+
- '.github/workflows/frontend-tests.yml'
8+
push:
9+
branches: [ main ]
10+
paths:
11+
- 'frontend/**'
12+
- '.github/workflows/frontend-tests.yml'
13+
14+
# Allow job to be triggered manually
15+
workflow_dispatch:
16+
17+
# Cancel in-progress jobs when pushing to the same branch
18+
concurrency:
19+
cancel-in-progress: true
20+
group: ${{ github.workflow }}-${{ github.ref }}
21+
22+
permissions: {}
23+
24+
jobs:
25+
typecheck:
26+
name: Type Check
27+
runs-on: ubuntu-latest
28+
29+
defaults:
30+
run:
31+
working-directory: frontend
32+
33+
steps:
34+
- name: Checkout code
35+
uses: actions/checkout@v4
36+
37+
- name: Setup Node.js
38+
uses: actions/setup-node@v4
39+
with:
40+
node-version: '20'
41+
42+
- name: Setup pnpm
43+
uses: pnpm/action-setup@v4
44+
with:
45+
version: 10
46+
47+
- name: Install dependencies
48+
run: pnpm install --frozen-lockfile
49+
50+
- name: Run type check
51+
run: pnpm run typecheck
52+
53+
lint:
54+
name: Lint Frontend
55+
runs-on: ubuntu-latest
56+
needs: typecheck
57+
58+
defaults:
59+
run:
60+
working-directory: frontend
61+
62+
steps:
63+
- name: Checkout code
64+
uses: actions/checkout@v4
65+
66+
- name: Setup Node.js
67+
uses: actions/setup-node@v4
68+
with:
69+
node-version: '20'
70+
71+
- name: Setup pnpm
72+
uses: pnpm/action-setup@v4
73+
with:
74+
version: 10
75+
76+
- name: Install dependencies
77+
run: pnpm install --frozen-lockfile
78+
79+
- name: Run linter
80+
run: pnpm run lint
81+
82+
unit-tests:
83+
name: Unit & Component Tests
84+
runs-on: ubuntu-latest
85+
needs: lint
86+
87+
defaults:
88+
run:
89+
working-directory: frontend
90+
91+
steps:
92+
- name: Checkout code
93+
uses: actions/checkout@v4
94+
95+
- name: Setup Node.js
96+
uses: actions/setup-node@v4
97+
with:
98+
node-version: '20'
99+
100+
- name: Setup pnpm
101+
uses: pnpm/action-setup@v4
102+
with:
103+
version: 10
104+
105+
- name: Get pnpm store directory
106+
id: pnpm-cache
107+
shell: bash
108+
run: |
109+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
110+
111+
- name: Setup pnpm cache
112+
uses: actions/cache@v4
113+
with:
114+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
115+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
116+
restore-keys: |
117+
${{ runner.os }}-pnpm-store-
118+
119+
- name: Install dependencies
120+
run: pnpm install --frozen-lockfile
121+
122+
- name: Run unit and component tests
123+
run: pnpm run test:ci
124+
125+
e2e-tests:
126+
name: E2E Tests
127+
runs-on: ubuntu-latest
128+
needs: unit-tests
129+
130+
defaults:
131+
run:
132+
working-directory: frontend
133+
134+
steps:
135+
- name: Checkout code
136+
uses: actions/checkout@v4
137+
138+
- name: Setup Node.js
139+
uses: actions/setup-node@v4
140+
with:
141+
node-version: '20'
142+
143+
- name: Setup pnpm
144+
uses: pnpm/action-setup@v4
145+
with:
146+
version: 10
147+
148+
- name: Get pnpm store directory
149+
id: pnpm-cache
150+
shell: bash
151+
run: |
152+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
153+
154+
- name: Setup pnpm cache
155+
uses: actions/cache@v4
156+
with:
157+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
158+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
159+
restore-keys: |
160+
${{ runner.os }}-pnpm-store-
161+
162+
- name: Install dependencies
163+
run: pnpm install --frozen-lockfile
164+
165+
- name: Install Playwright browsers
166+
run: npx playwright install --with-deps firefox
167+
168+
- name: Setup uv
169+
uses: astral-sh/setup-uv@v7
170+
with:
171+
python-version: '3.14'
172+
173+
- name: Install backend dependencies
174+
working-directory: .
175+
run: |
176+
uv sync --no-dev --extra restapi
177+
uv pip list
178+
179+
- name: Verify wetterdienst installation
180+
working-directory: .
181+
run: |
182+
uv run wetterdienst --version
183+
uv run wetterdienst info
184+
185+
- name: Start backend
186+
working-directory: .
187+
run: |
188+
uv run wetterdienst restapi --listen 0.0.0.0:3000 > backend.log 2>&1 &
189+
echo $! > backend.pid
190+
echo "Backend started with PID $(cat backend.pid)"
191+
192+
- name: Wait for backend to be ready
193+
run: |
194+
echo "Waiting for backend to start..."
195+
for i in {1..30}; do
196+
if curl -f http://localhost:3000/health > /dev/null 2>&1; then
197+
echo "✅ Backend is ready!"
198+
exit 0
199+
fi
200+
echo "Attempt $i/30: Backend not ready yet, waiting..."
201+
sleep 2
202+
done
203+
echo "❌ Backend failed to start within 60 seconds"
204+
echo "Backend logs:"
205+
cat backend.log || echo "No backend logs found"
206+
exit 1
207+
208+
- name: Run E2E tests
209+
run: pnpm run test:e2e
210+
env:
211+
BACKEND_URL: http://localhost:3000
212+
CI: true
213+
214+
- name: Upload test results
215+
if: always()
216+
uses: actions/upload-artifact@v4
217+
with:
218+
name: playwright-report
219+
path: frontend/playwright-report/
220+
retention-days: 7
221+
222+
- name: Upload backend logs
223+
if: failure()
224+
uses: actions/upload-artifact@v4
225+
with:
226+
name: backend-logs
227+
path: backend.log
228+
retention-days: 3
229+
230+
- name: Stop backend
231+
if: always()
232+
working-directory: .
233+
run: |
234+
if [ -f backend.pid ]; then
235+
echo "Stopping backend process $(cat backend.pid)"
236+
kill $(cat backend.pid) || true
237+
rm backend.pid
238+
fi
239+
# Also try to kill any remaining wetterdienst processes
240+
pkill -f "wetterdienst restapi" || true

0 commit comments

Comments
 (0)