Skip to content

Commit 2928bbb

Browse files
committed
refactor: initial upgrades and styling improvements
Signed-off-by: Jan Lauber <jan.lauber@protonmail.ch>
1 parent 5708ca1 commit 2928bbb

File tree

247 files changed

+13886
-7331
lines changed

Some content is hidden

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

247 files changed

+13886
-7331
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
working-directory: kubelab-backend
1717
strategy:
1818
matrix:
19-
goVer: [1.22]
19+
goVer: [1.24]
2020

2121
steps:
2222
- name: Set up Go ${{ matrix.goVer }}
@@ -50,6 +50,8 @@ jobs:
5050
steps:
5151
- uses: actions/checkout@v4
5252
- uses: actions/setup-node@v4
53+
with:
54+
node-version: 'lts/*'
5355
- name: Install dependencies
5456
run: npm install --legacy-peer-deps
5557
- name: Build

.github/workflows/docker-release.yml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,32 @@ jobs:
1919
- name: Checkout repository
2020
uses: actions/checkout@v4
2121

22+
- name: Set up QEMU
23+
uses: docker/setup-qemu-action@v3
24+
25+
- name: Set up Docker Buildx
26+
uses: docker/setup-buildx-action@v3
27+
2228
- name: Log in to the Container registry
23-
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
29+
uses: docker/login-action@v3
2430
with:
2531
registry: ${{ env.REGISTRY }}
2632
username: ${{ github.actor }}
2733
password: ${{ secrets.GITHUB_TOKEN }}
2834

2935
- name: Extract metadata (tags, labels) for Docker
3036
id: meta
31-
uses: docker/metadata-action@60a0d343a0d8a18aedee9d34e62251f752153bdb
37+
uses: docker/metadata-action@v5
3238
with:
3339
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
3440

3541
- name: Build and push Docker image
36-
uses: docker/build-push-action@5176d81f87c23d6fc96624dfdbcd9f3830bbe445
42+
uses: docker/build-push-action@v6
3743
with:
3844
context: .
45+
platforms: linux/amd64,linux/arm64
3946
push: true
4047
tags: ${{ steps.meta.outputs.tags }}
4148
labels: ${{ steps.meta.outputs.labels }}
49+
cache-from: type=gha
50+
cache-to: type=gha,mode=max

Dockerfile

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM golang:1.22-alpine AS backend-builder
1+
FROM golang:1.24-alpine AS backend-builder
22
WORKDIR /build
33
COPY kubelab-backend/go.mod kubelab-backend/go.sum kubelab-backend/main.go ./
44
COPY kubelab-backend/hooks ./hooks
@@ -9,16 +9,17 @@ RUN apk --no-cache add upx make git gcc libtool musl-dev ca-certificates dumb-in
99
&& CGO_ENABLED=0 go build \
1010
&& upx kubelab
1111

12-
FROM node:lts-slim as ui-builder
12+
FROM node:22-alpine AS ui-builder
1313
WORKDIR /build
14+
# Install build dependencies for native modules
15+
RUN apk add --no-cache python3 make g++
1416
COPY ./kubelab-ui/package*.json ./
15-
RUN rm -rf ./node_modules
16-
RUN rm -rf ./build
1717
COPY ./kubelab-ui .
18-
RUN npm install --legacy-peer-deps
18+
# Clean install to ensure optional dependencies are properly resolved
19+
RUN npm ci --legacy-peer-deps || npm install --legacy-peer-deps
1920
RUN npm run build
2021

21-
FROM alpine as runtime
22+
FROM alpine AS runtime
2223
WORKDIR /app/kubelab
2324
COPY --from=backend-builder /build/kubelab /app/kubelab/kubelab
2425
COPY --from=backend-builder /build/vcluster-values.yaml /app/kubelab/vcluster-values.yaml

kubelab-backend/.air.toml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
root = "."
2+
testdata_dir = "testdata"
3+
tmp_dir = "tmp"
4+
5+
[build]
6+
bin = "./dev.sh"
7+
cmd = "go build -o ./tmp/main ."
8+
delay = 1000
9+
exclude_dir = ["assets", "tmp", "vendor", "testdata", "pb_data", "pb_migrations"]
10+
exclude_file = []
11+
exclude_regex = ["_test.go"]
12+
exclude_unchanged = false
13+
follow_symlink = false
14+
full_bin = ""
15+
include_dir = []
16+
include_ext = ["go", "tpl", "tmpl", "html"]
17+
include_file = []
18+
kill_delay = "0s"
19+
log = "build-errors.log"
20+
poll = false
21+
poll_interval = 0
22+
post_cmd = []
23+
pre_cmd = []
24+
rerun = false
25+
rerun_delay = 500
26+
send_interrupt = false
27+
stop_on_error = false
28+
29+
[color]
30+
app = ""
31+
build = "yellow"
32+
main = "magenta"
33+
runner = "green"
34+
watcher = "cyan"
35+
36+
[log]
37+
main_only = false
38+
time = false
39+
40+
[misc]
41+
clean_on_exit = false
42+
43+
[screen]
44+
clear_on_rebuild = false
45+
keep_scroll = true
46+

kubelab-backend/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
/pocketbase*.zip
44
/pb_data
55
/pb_data_old
6+
/pb_data_backup_*
7+
/pb_migrations_old
68
/tmp
79
/bin
810
./pocketbase
911
kubelab
12+
# Air build artifacts
13+
build-errors.log

kubelab-backend/COLLECTIONS.md

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# Kubelab Collections Structure
2+
3+
This document describes the PocketBase collections used in Kubelab.
4+
5+
## Collections Overview
6+
7+
All collections are created programmatically in `pkg/collections/collections.go` on application bootstrap. No manual migration files are needed.
8+
9+
### 1. **users** (Auth Collection)
10+
The main user authentication collection.
11+
12+
**Custom Fields:**
13+
- `role` (text, required) - User role: "user" or "admin"
14+
- `plan` (text) - Associated plan ID
15+
- `company` (text) - Company name
16+
- `workshop` (boolean) - Workshop participant flag
17+
18+
**Access Rules:**
19+
- List/View: Authenticated users only
20+
- Update/Delete: Own record or admin
21+
22+
---
23+
24+
### 2. **labs**
25+
Lab courses that contain multiple exercises.
26+
27+
**Fields:**
28+
- `name` (text, required) - Lab name
29+
- `description` (editor) - Lab description
30+
- `icon` (text) - Icon identifier
31+
- `order` (number) - Display order
32+
- `active` (boolean) - Active status
33+
- `difficulty` (text) - Difficulty level
34+
35+
**Access Rules:**
36+
- List/View: Authenticated users
37+
- Create/Update/Delete: Admins only
38+
39+
---
40+
41+
### 3. **exercises**
42+
Individual exercises within labs.
43+
44+
**Fields:**
45+
- `name` (text, required) - Exercise name
46+
- `description` (editor) - Exercise description
47+
- `lab` (relation, required) - Parent lab
48+
- `bootstrap` (URL) - Bootstrap script URL
49+
- `check` (URL) - Validation script URL
50+
- `order` (number) - Display order
51+
- `maxScore` (number) - Maximum achievable score
52+
- `active` (boolean) - Active status
53+
54+
**Access Rules:**
55+
- List/View: Authenticated users
56+
- Create/Update/Delete: Admins only
57+
58+
---
59+
60+
### 4. **lab_sessions**
61+
User progress for labs (manages vcluster lifecycle).
62+
63+
**Fields:**
64+
- `user` (relation, required) - User ID
65+
- `lab` (relation, required) - Lab ID
66+
- `clusterRunning` (boolean) - vcluster status
67+
- `lastClusterStart` (date) - Last start timestamp
68+
- `lastClusterStop` (date) - Last stop timestamp
69+
70+
**Access Rules:**
71+
- List/View: Own records or admin
72+
- Create: Authenticated users
73+
- Update/Delete: Own records or admin
74+
75+
---
76+
77+
### 5. **exercise_sessions**
78+
User progress for individual exercises.
79+
80+
**Fields:**
81+
- `user` (relation, required) - User ID
82+
- `exercise` (relation, required) - Exercise ID
83+
- `agentRunning` (boolean) - Agent deployment status
84+
- `score` (number) - Current score
85+
- `lastAgentStart` (date) - Last start timestamp
86+
- `lastAgentStop` (date) - Last stop timestamp
87+
- `solved` (boolean) - Completion status
88+
- `solvedAt` (date) - Completion timestamp
89+
90+
**Access Rules:**
91+
- List/View: Own records or admin
92+
- Create: Authenticated users
93+
- Update/Delete: Own records or admin
94+
95+
---
96+
97+
### 6. **exercise_session_logs**
98+
Logs for exercise session events.
99+
100+
**Fields:**
101+
- `user` (relation, required) - User ID
102+
- `exercise_session` (relation, required) - Exercise session ID
103+
- `message` (text, required) - Log message
104+
- `type` (text, required) - Log type/severity
105+
106+
**Access Rules:**
107+
- List/View: Own records or admin
108+
- Create: Authenticated users
109+
- Delete: Admins only (no updates)
110+
111+
---
112+
113+
### 7. **hooks**
114+
Configurable event hooks for automation.
115+
116+
**Fields:**
117+
- `table` (text, required) - Target collection
118+
- `event` (text, required) - Event type (insert/update/delete)
119+
- `actionType` (text, required) - Action to perform
120+
- `actionMeta` (text) - Additional action metadata
121+
- `disabled` (boolean) - Enable/disable hook
122+
123+
**Access Rules:**
124+
- All operations: Admins only
125+
126+
---
127+
128+
### 8. **plans**
129+
Subscription/pricing plans.
130+
131+
**Fields:**
132+
- `name` (text, required) - Plan name
133+
- `description` (text) - Plan description
134+
- `price` (number) - Plan price
135+
- `active` (boolean) - Active status
136+
137+
**Access Rules:**
138+
- List/View: Authenticated users
139+
- Create/Update/Delete: Admins only
140+
141+
---
142+
143+
### 9. **features**
144+
Features associated with plans.
145+
146+
**Fields:**
147+
- `name` (text, required) - Feature name
148+
- `plan` (relation) - Associated plan
149+
150+
**Access Rules:**
151+
- List/View: Authenticated users
152+
- Create/Update/Delete: Admins only
153+
154+
---
155+
156+
### 10. **faqs**
157+
Frequently asked questions.
158+
159+
**Fields:**
160+
- `question` (text, required) - Question text
161+
- `answer` (text, required) - Answer text
162+
- `order` (number) - Display order
163+
164+
**Access Rules:**
165+
- List/View: Public (no auth required)
166+
- Create/Update/Delete: Admins only
167+
168+
---
169+
170+
### 11. **companies**
171+
Company logos for landing page.
172+
173+
**Fields:**
174+
- `name` (text, required) - Company name
175+
- `logo` (file, max 5MB) - Company logo image
176+
- `order` (number) - Display order
177+
178+
**Access Rules:**
179+
- List/View: Public (no auth required)
180+
- Create/Update/Delete: Admins only
181+
182+
---
183+
184+
### 12. **notifications**
185+
User notifications.
186+
187+
**Fields:**
188+
- `user` (relation, required) - User ID
189+
- `message` (text, required) - Notification message
190+
- `type` (text, required) - Notification type
191+
- `read` (boolean) - Read status
192+
193+
**Access Rules:**
194+
- List/View: Own records or admin
195+
- Create: Authenticated users
196+
- Update/Delete: Own records or admin
197+
198+
---
199+
200+
## Initialization
201+
202+
Collections are automatically created on application bootstrap via `collections.InitializeCollections()` in `main.go`. If a collection already exists, it's skipped - no data is lost.
203+
204+
## First Run Setup
205+
206+
1. Start the backend: `npm run dev:backend` (from kubelab-ui directory)
207+
2. Open the admin dashboard: http://localhost:8090/_/
208+
3. Create your first admin account
209+
4. Collections will be automatically created on first bootstrap
210+
211+
## Notes
212+
213+
- Old JS migrations in `pb_migrations_old/` are kept for reference but not used
214+
- All schema changes should now be done in `pkg/collections/collections.go`
215+
- For production, you may want to add collection schema versioning
216+

kubelab-backend/dev.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
LOCAL=true ./tmp/main serve --http 0.0.0.0:8090 --publicDir ../kubelab-ui/build
3+

0 commit comments

Comments
 (0)