Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
15 changes: 7 additions & 8 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
node_modules
**/node_modules
dist
.git
.vscode
Expand All @@ -7,9 +7,7 @@ npm-debug.log*
.DS_Store

# Development files
frontend/node_modules
backend/node_modules
backend/.cache
apps/server/.cache

# Test files
**/*.test.ts
Expand All @@ -19,9 +17,10 @@ backend/.cache

# Local data and dev sandbox
snapraid/
dev/
frontend/.output
frontend/.vinxi
scripts/dev/
apps/web/.output
apps/web/.vinxi

# End-to-end tests: built tools, test data
# End-to-end tests: built tools, test data (only e2e/package.json goes in, for the workspace)
e2e/
!e2e/package.json
12 changes: 6 additions & 6 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
customType: "regex",
managerFilePatterns: [
"/^docker/(Dockerfile|README\\.md)$/",
"/^dev/setup\\.sh$/",
"/^scripts/dev/setup\\.sh$/",
"/^e2e/scripts/setup-tools\\.sh$/",
"/^scripts/install\\.sh$/",
"/^\\.github/workflows/ci\\.yml$/",
Expand All @@ -40,10 +40,10 @@
versioningTemplate: "regex:^(?<major>\\d+)\\.(?<minor>\\d+)$",
},
{
// "packageManager": "bun@x.y.z" in backend/, frontend/ and e2e/: the Bun of every CI job
// "packageManager": "bun@x.y.z" in the root package.json: the Bun of every CI job
// (bun-version-file, and the npm-installed Bun of the screenshots job in the Playwright image)
customType: "regex",
managerFilePatterns: ["/^(backend|frontend|e2e)/package\\.json$/"],
managerFilePatterns: ["/^package\\.json$/"],
matchStrings: ['"packageManager": "bun@(?<currentValue>\\d+\\.\\d+\\.\\d+)"'],
depNameTemplate: "oven-sh/bun",
datasourceTemplate: "github-releases",
Expand All @@ -62,20 +62,20 @@
sourceUrl: "https://github.com/amadvance/snapraid",
commitMessageTopic: "SnapRAID",
prBodyNotes: [
"The parsers are tested against this one release. Before merging: read SnapRAID's [HISTORY](https://github.com/amadvance/snapraid/blob/master/HISTORY) for changes to the structured log (`--log`); the end-to-end tests of this PR build and run the new release. Locally: `SNAPRAID_VERSION=<new> dev/setup.sh --reset`, then status, diff, sync, scrub, check, list, dup, touch and smart in the UI. A major version: compare the log tags with `backend/src/parsers/__tests__/fixtures/`, and the text \"SnapRAID 15\" in docs/installation.md. Check whether snapraid-daemon (`REVIEWED_DAEMON_VERSION`) needs this release; docs/automation.md names the versions the daemon mode was tested with.",
"The parsers are tested against this one release. Before merging: read SnapRAID's [HISTORY](https://github.com/amadvance/snapraid/blob/master/HISTORY) for changes to the structured log (`--log`); the end-to-end tests of this PR build and run the new release. Locally: `SNAPRAID_VERSION=<new> scripts/dev/setup.sh --reset`, then status, diff, sync, scrub, check, list, dup, touch and smart in the UI. A major version: compare the log tags with `apps/server/src/parsers/__tests__/fixtures/`, and the text \"SnapRAID 15\" in docs/installation.md. Check whether snapraid-daemon (`REVIEWED_DAEMON_VERSION`) needs this release; docs/automation.md names the versions the daemon mode was tested with.",
],
schedule: ["at any time"],
automerge: false,
dependencyDashboardApproval: false,
},
{
// Bun of the image (oven/bun) and packageManager in backend/, frontend/ and e2e/ in one PR,
// Bun of the image (oven/bun) and packageManager in package.json in one PR,
// so CI tests the Bun the image runs on
matchPackageNames: ["docker.io/oven/bun", "oven/bun", "oven-sh/bun"],
groupName: "Bun",
sourceUrl: "https://github.com/oven-sh/bun",
prBodyNotes: [
"The image (`oven/bun:<version>-slim` in docker/Dockerfile, the backend runs on it) and `packageManager` in `backend/package.json`, `frontend/package.json` and `e2e/package.json` (CI's `bun-version-file`, which also builds the standalone binary, and the screenshots job's `npm install bun@…`) move together. Bun runs the backend and its tests, installs, runs Vite and Vitest (`bun --bun`) and compiles the binary, and runs Playwright's test runner (`bun --bun playwright test`). Check the backend and frontend jobs and the end-to-end tests against the local build, the image and the binary.",
"The image (`oven/bun:<version>-slim` in docker/Dockerfile, the backend runs on it) and `packageManager` in the root `package.json` (CI's `bun-version-file`, which also builds the standalone binary, and the screenshots job's `npm install bun@…`) move together. Bun runs the backend and its tests, installs, runs Vite and Vitest (`bun --bun`) and compiles the binary, and runs Playwright's test runner (`bun --bun playwright test`). Check the backend and frontend jobs and the end-to-end tests against the local build, the image and the binary.",
],
schedule: ["at any time"],
automerge: false,
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/bump.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Bump version

# Raises the version in frontend/package.json, commits it, tags the commit vX.Y.Z and starts release.yml on it.
# Raises the version in apps/web/package.json, commits it, tags the commit vX.Y.Z and starts release.yml on it.
# Same scheme as in every project, see https://github.com/firsttris/workflows#bump-version
on:
workflow_dispatch:
Expand All @@ -15,7 +15,7 @@ jobs:
uses: firsttris/workflows/.github/workflows/bump-version.yml@v1
with:
bump: ${{ inputs.bump }}
version-file: frontend/package.json
version-file: apps/web/package.json
permissions:
contents: write
actions: write
31 changes: 13 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: backend
working-directory: apps/server
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: backend/package.json
bun-version-file: package.json
# The workspace's one bun.lock, installed from the root
- run: bun install --frozen-lockfile
working-directory: .
- run: bun run typecheck
- run: bun test

Expand All @@ -44,13 +46,14 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
working-directory: apps/web
steps:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: frontend/package.json
bun-version-file: package.json
- run: bun install --frozen-lockfile
working-directory: .
- run: bunx biome check
- run: bun run typecheck
- run: bun run test
Expand All @@ -67,11 +70,8 @@ jobs:
- run: shellcheck -s sh scripts/install.sh
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: frontend/package.json
bun-version-file: package.json
- run: bun install --frozen-lockfile
working-directory: frontend
- run: bun install --frozen-lockfile
working-directory: backend
- run: scripts/build-binary.sh
- name: Serve the binary like a release
working-directory: dist
Expand Down Expand Up @@ -141,30 +141,25 @@ jobs:
# Bun installs, builds and runs the backend, and runs Playwright's test runner (bun --bun)
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: e2e/package.json
bun-version-file: package.json
- name: Cache SnapRAID and snapraid-daemon builds
uses: actions/cache@v6
with:
path: e2e/.tools
key: e2e-tools-${{ runner.os }}-${{ hashFiles('e2e/scripts/setup-tools.sh', 'backend/src/engine/REVIEWED_DAEMON_VERSION') }}
key: e2e-tools-${{ runner.os }}-${{ hashFiles('e2e/scripts/setup-tools.sh', 'apps/server/src/engine/REVIEWED_DAEMON_VERSION') }}
# smartmontools: SnapRAID lists the disks on the SMART page with it, self-tests use a stand-in
- uses: firsttris/workflows/actions/apt-install@v1
with:
packages: autoconf automake zlib1g-dev smartmontools
recommends: "false"
- name: Build SnapRAID and snapraid-daemon
run: bun run setup
# All packages of the workspace: the tests', and the backend and frontend the tests run or
# the binary build is made of
- run: bun install --frozen-lockfile
working-directory: .
- run: bun run typecheck
- run: bun --bun playwright install --with-deps chromium
- name: Install the frontend, the tests or the binary build it
if: matrix.target != 'image'
working-directory: frontend
run: bun install --frozen-lockfile
- name: Install the backend, the tests run it or the binary build it
if: matrix.target != 'image'
working-directory: backend
run: bun install --frozen-lockfile
# The tests run the x86_64 one; arm64 is built too, so the release does not find a problem first
- name: Build the binaries
if: matrix.target == 'binary'
Expand Down
9 changes: 3 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name: Release
# the code, see https://github.com/firsttris/workflows#tested-on-main), then the shared Docker release from
# firsttris/workflows, which pushes the image as :x.y.z, :x.y and :latest, updates the Docker Hub
# description and creates the GitHub release; the standalone binaries are attached to it after.
# The tag must match the version in frontend/package.json.
# The tag must match the version in apps/web/package.json.
# Run by hand on master: the same checks, then the image as :edge, nothing is released.
on:
push:
Expand Down Expand Up @@ -34,7 +34,7 @@ jobs:
with:
image: tristanteu/snapraid-ui
description: Web UI for SnapRAID — run sync/scrub, schedule jobs, monitor disks and SMART health
version-file: frontend/package.json
version-file: apps/web/package.json
secrets: inherit
permissions:
contents: write
Expand All @@ -53,11 +53,8 @@ jobs:
- uses: actions/checkout@v7
- uses: oven-sh/setup-bun@v2
with:
bun-version-file: frontend/package.json
bun-version-file: package.json
- run: bun install --frozen-lockfile
working-directory: frontend
- run: bun install --frozen-lockfile
working-directory: backend
- run: scripts/build-binary.sh bun-linux-x64 bun-linux-arm64
- name: Checksums
working-directory: dist
Expand Down
18 changes: 8 additions & 10 deletions .github/workflows/screenshots.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- id: playwright
uses: firsttris/workflows/actions/playwright-image@v1
with:
lockfile: e2e/bun.lock
lockfile: bun.lock

screenshots:
needs: image
Expand All @@ -31,24 +31,22 @@ jobs:
contents: write
steps:
- uses: actions/checkout@v7
# dev/setup.sh builds SnapRAID for the sandbox
# scripts/dev/setup.sh builds SnapRAID for the sandbox
- name: Build tools
run: apt-get update && apt-get install -y --no-install-recommends build-essential curl
- name: Cache the SnapRAID build
uses: actions/cache@v6
with:
path: |
dev/bin
dev/.cache
key: demo-snapraid-${{ hashFiles('dev/setup.sh') }}
scripts/dev/bin
scripts/dev/.cache
key: demo-snapraid-${{ hashFiles('scripts/dev/setup.sh') }}
# The npm package brings Bun without curl or unzip; the version is packageManager in
# e2e/package.json, as setup-bun takes it in the other workflows
# package.json, as setup-bun takes it in the other workflows
- name: Install
run: |
npm install --global "bun@$(node -p "require('./e2e/package.json').packageManager.split('@')[1]")"
bun install --frozen-lockfile --cwd backend
bun install --frozen-lockfile --cwd frontend
bun install --frozen-lockfile --cwd e2e
npm install --global "bun@$(node -p "require('./package.json').packageManager.split('@')[1]")"
bun install --frozen-lockfile
- name: Take the screenshots
working-directory: e2e
# The container runs as root: the disks go to /mnt, as on a server
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/upstream-release.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: Upstream Release Check

# Opens an issue when snapraid-daemon has a newer version, so it is looked at on purpose: jobs,
# status, diff, SMART and the power state go through the SnapRAID engine (backend/src/engine/engine.ts),
# status, diff, SMART and the power state go through the SnapRAID engine (apps/server/src/engine/engine.ts),
# so they could also run on snapraid-daemon's REST API. Its API was last compared with
# backend/src/engine/REVIEWED_DAEMON_VERSION. A new SnapRAID release comes as a Renovate pull
# apps/server/src/engine/REVIEWED_DAEMON_VERSION. A new SnapRAID release comes as a Renovate pull
# request instead (.github/renovate.json5).

on:
Expand All @@ -26,7 +26,7 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
reviewed=$(tr -d '[:space:]' < backend/src/engine/REVIEWED_DAEMON_VERSION)
reviewed=$(tr -d '[:space:]' < apps/server/src/engine/REVIEWED_DAEMON_VERSION)
# Tags like v1.15, v2.0rc2 and v2.0. Release candidates count, the API changes in them.
# Sort key: 2.0rc2 -> 2.0.2, 2.0 -> 2.0.999, so a release sorts after its candidates
newest=$(git ls-remote --tags https://github.com/amadvance/snapraid-daemon.git \
Expand All @@ -48,9 +48,9 @@ jobs:
snapraid-daemon [v$newest](https://github.com/amadvance/snapraid-daemon/tree/v$newest) is out, the SnapRAID engine was last compared with v$reviewed.

- [ ] Compare the API: [snapraidd.yaml v$reviewed...v$newest](https://github.com/amadvance/snapraid-daemon/compare/v$reviewed...v$newest) and the [HISTORY](https://github.com/amadvance/snapraid-daemon/blob/v$newest/HISTORY)
- [ ] An endpoint for something CLI-only today (\`dup\`, \`list\`, \`devices\`, config, ...)? Add a method to \`SnapRaidEngine\` in \`backend/src/engine/engine.ts\`, implement it in \`cli-engine.ts\`, move the callers and extend \`backend/src/__tests__/engine-contract.ts\`
- [ ] An endpoint for something CLI-only today (\`dup\`, \`list\`, \`devices\`, config, ...)? Add a method to \`SnapRaidEngine\` in \`apps/server/src/engine/engine.ts\`, implement it in \`cli-engine.ts\`, move the callers and extend \`apps/server/src/__tests__/engine-contract.ts\`
- [ ] Update the tables in [docs/architecture.md](https://github.com/${{ github.repository }}/blob/master/docs/architecture.md#snapraid-engine)
- [ ] Put $newest into \`backend/src/engine/REVIEWED_DAEMON_VERSION\`
- [ ] Put $newest into \`apps/server/src/engine/REVIEWED_DAEMON_VERSION\`
- [ ] The end-to-end tests build and run against that version; if it needs a newer SnapRAID, raise \`SNAPRAID15_REF\` in \`e2e/scripts/setup-tools.sh\`
BODY
)"
40 changes: 20 additions & 20 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
node_modules/
dist/
.env
.env.local
*.log
.DS_Store
.vscode/
.idea/
config.json
frontend/.output/
frontend/.vinxi/
node_modules/
dist/
.env
.env.local
*.log
.DS_Store
.vscode/
.idea/
config.json
apps/web/.output/
apps/web/.vinxi/

# Dev sandbox (dev/setup.sh)
dev/bin/
dev/.cache/
dev/sandbox/
# Dev sandbox (scripts/dev/setup.sh)
scripts/dev/bin/
scripts/dev/.cache/
scripts/dev/sandbox/

# Local data of ./start.sh (configs, schedules, logs)
# Local data of scripts/start.sh (configs, schedules, logs)
/snapraid/
!backend/src/parsers/__tests__/fixtures/*.log
!apps/server/src/parsers/__tests__/fixtures/*.log

# Paraglide (generated from frontend/messages/*.json) and the inlang cache
frontend/src/paraglide/
frontend/project.inlang/cache/
# Paraglide (generated from apps/web/messages/*.json) and the inlang cache
apps/web/src/paraglide/
apps/web/project.inlang/cache/

# MkDocs build (mkdocs build)
site/
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,13 @@ December 23.

## 🛠️ Development

Requires Bun (the version in `frontend/package.json`) and the fish shell for `start.sh`;
Requires Bun (the version in `package.json`) and the fish shell for `scripts/start.sh`;
the end-to-end tests run on Bun too.

```bash
git clone https://github.com/firsttris/snapraid-ui && cd snapraid-ui
./install.sh
./start.sh --demo # sandbox with fake disks, no real array needed
bun install
bun run demo # sandbox with fake disks, no real array needed
```

The frontend runs on http://localhost:3000, the API on http://localhost:8080. Built with Bun + Hono,
Expand All @@ -260,7 +260,7 @@ project layout, tests and translations.
## 🤝 Contributing

Issues and pull requests are welcome. Please run `bunx biome check`, `bun run typecheck` and the tests
(`bun test` in `backend/`, `bun run test` in `frontend/`) before opening a pull request.
(`bun test` in `apps/server/`, `bun run test` in `apps/web/`) before opening a pull request.
Changes to jobs, schedules or the Docker image are also covered by the end-to-end tests in `e2e/`,
which CI runs against the local build and the image; see [Development](https://firsttris.github.io/snapraid-ui/development.html#end-to-end-tests) to run them locally.

Expand Down
2 changes: 1 addition & 1 deletion backend/package.json → apps/server/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"name": "snapraid-ui-backend",
"private": true,
"packageManager": "bun@1.4.4",
"type": "module",
"scripts": {
"dev": "bun --watch src/main.ts",
Expand All @@ -12,6 +11,7 @@
"dependencies": {
"@modelcontextprotocol/sdk": "^1.32.1",
"@simplewebauthn/server": "^14.0.3",
"@snapraid-ui/shared": "workspace:*",
"croner": "^11.0.0",
"hono": "^4.13.9",
"mqtt": "^5.14.1",
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// Gives the demo sandbox a past, run by dev/setup.sh after its real SnapRAID jobs:
// Gives the demo sandbox a past, run by scripts/dev/setup.sh after its real SnapRAID jobs:
// - the job logs (logs/run-<n>-<command>.log, in the order they ran) move back in time, so
// the dashboard shows the last sync and scrub, and the Logs page a history
// - usage-history.json: two months of disk usage, one disk filling up
// - schedules.json: a nightly sync with touch and scrub, a weekly scrub, a SMART check
// - maintenance.json: Docker pause and spindown, on the demo's own containers and disks
//
// bun scripts/seed-demo.ts <sandbox> (in backend/, whose packages it uses)
// bun scripts/seed-demo.ts <sandbox> (in apps/server/, whose packages it uses)
import { readdir, readFile, rm, utimes, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { Cron } from "croner";
Expand Down Expand Up @@ -123,7 +123,7 @@ const schedules: Schedule[] = [
];
await writeFile(join(sandbox, "schedules.json"), JSON.stringify({ schedules }, null, 2));

// The demo answers for Docker itself (backend/src/demo.ts), spindown watches the demo disks
// The demo answers for Docker itself (apps/server/src/demo.ts), spindown watches the demo disks
// The rest (metrics, MCP) takes its defaults when the backend loads the file
const maintenance: Pick<MaintenanceSettings, "dockerPause" | "spindown"> = {
dockerPause: {
Expand Down
Loading
Loading