From 5c6258c4c1d6946ab77f9e8218e6b1f7c1ba1869 Mon Sep 17 00:00:00 2001 From: Henrik Xavier Nepstad Date: Fri, 16 Oct 2026 21:48:20 +0200 Subject: [PATCH 1/4] Feat(deployment): Added frontend deployment feature --- Frontend/vite.config.ts | 2 ++ deploy.sh | 61 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100755 deploy.sh diff --git a/Frontend/vite.config.ts b/Frontend/vite.config.ts index d789a7c..e6cbea0 100644 --- a/Frontend/vite.config.ts +++ b/Frontend/vite.config.ts @@ -4,6 +4,8 @@ import { defineConfig } from 'vite' // https://vite.dev/config/ export default defineConfig({ + // Served from a subfolder of the web root; must match PROJECT_NAME in deploy.sh + base: '/project2/', plugins: [ react(), babel({ presets: [reactCompilerPreset()] }) diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..9a284e0 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# +# This script can be triggered with a CRON job for polling. +# This will keep the webpage always up to date. +# + +# Sets the failure mode (if one command fails, dont continue) +set -euo pipefail + + +# Set to wherever the repo is stored on the server +REPO_DIR="/IT2810/T11-Project-2" +REPO_PROJECT_DIR="$REPO_DIR/Frontend" +REPO_BUILD_RESULT="$REPO_PROJECT_DIR/dist" + +# /var/www/html is the web root. Each project is deployed to its own +# subfolder: project2 -> /var/www/html/project2 +PROJECT_NAME="project2" +DEST_DIR="/var/www/html/$PROJECT_NAME" + +cd "$REPO_DIR" + +echo "Fetching latest from main..." +git fetch origin main + +# Get local commit and Remote commit +LOCAL=$(git rev-parse HEAD) +REMOTE=$(git rev-parse origin/main) + +# Decreasing how often the script runs. An additional pull does no harm +# If they are the same, no new commits are in. Exit +#if [ "$LOCAL" = "$REMOTE" ]; then +# echo "Already up to date ($LOCAL). Nothing to deploy." +# exit 0 +#fi + +# Otherwise, pull from origin +#echo "Updating $LOCAL -> $REMOTE" +#git reset --hard origin/main + +cd "$REPO_PROJECT_DIR" + +echo "==== Frontend ====" + +echo "Do a clean NPM install..." +npm ci + +# Building the docker image from the new source code +echo "Building site..." +npm run build + +echo "Build complete." + +echo "Removing current web-page..." +rm -rf "$DEST_DIR" + +echo "Moving files..." +mv $REPO_BUILD_RESULT $DEST_DIR + +echo "Deployed $REMOTE frontend" \ No newline at end of file From 048f91c8df4cb2c32941ab3977dd1193b1b01ba9 Mon Sep 17 00:00:00 2001 From: Henrik Xavier Nepstad Date: Fri, 16 Oct 2026 22:08:25 +0200 Subject: [PATCH 2/4] Feat: Added API to deployment script --- deploy.sh | 46 +++++++++++++++++++++++++++++++++++++++++++++- docs/AI-Usage.md | 1 + 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/deploy.sh b/deploy.sh index 9a284e0..92aa256 100755 --- a/deploy.sh +++ b/deploy.sh @@ -13,6 +13,7 @@ set -euo pipefail REPO_DIR="/IT2810/T11-Project-2" REPO_PROJECT_DIR="$REPO_DIR/Frontend" REPO_BUILD_RESULT="$REPO_PROJECT_DIR/dist" +REPO_BACKEND_DIR="$REPO_DIR/backend" # /var/www/html is the web root. Each project is deployed to its own # subfolder: project2 -> /var/www/html/project2 @@ -58,4 +59,47 @@ rm -rf "$DEST_DIR" echo "Moving files..." mv $REPO_BUILD_RESULT $DEST_DIR -echo "Deployed $REMOTE frontend" \ No newline at end of file +echo "Deployed $REMOTE frontend" + +echo "==== Backend API ====" + +# The API is only deployed once backend/ exists on main. +if [ -f "$REPO_BACKEND_DIR/package.json" ]; then + cd "$REPO_BACKEND_DIR" + + echo "Do a clean NPM install..." + npm ci + + # Run the API as a systemd service so it keeps running between + # deploys and across reboots. Needs passwordless sudo for systemctl. + echo "Installing systemd service..." + NPM_BIN="$(command -v npm)" + sudo tee /etc/systemd/system/t11-api.service > /dev/null < Date: Fri, 16 Oct 2026 22:17:16 +0200 Subject: [PATCH 3/4] Fix: Fixed bug with deployment script --- deploy.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/deploy.sh b/deploy.sh index 92aa256..a79f1d2 100755 --- a/deploy.sh +++ b/deploy.sh @@ -74,6 +74,9 @@ if [ -f "$REPO_BACKEND_DIR/package.json" ]; then # deploys and across reboots. Needs passwordless sudo for systemctl. echo "Installing systemd service..." NPM_BIN="$(command -v npm)" + # systemd services get a minimal PATH, so npm's '#!/usr/bin/env node' + # shebang cannot find node. Point the service at the node this script sees. + NODE_BIN_DIR="$(dirname "$(command -v node)")" sudo tee /etc/systemd/system/t11-api.service > /dev/null < Date: Fri, 16 Oct 2026 22:36:36 +0200 Subject: [PATCH 4/4] Docs: Update the documentation with deploymnt information Related to #35 --- README.md | 6 ++ docs/AI-Usage.md | 2 +- docs/deployment.md | 60 +++++++++++++++++++ ...thub-runner-setup.md => github-runners.md} | 0 docs/technical-choices.md | 7 +++ 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 docs/deployment.md rename docs/{github-runner-setup.md => github-runners.md} (100%) diff --git a/README.md b/README.md index c201585..9e3b103 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,10 @@ For documentation in this repository, check the `docs` folder. Each file will contain a short description of what it documents. ### Website plan (submisson 1.) + For reviewing the first submisson we recommend reading PRD.md first, then the Spec.md and the rest of the docs. + +### Backend configured (submission 2.) + +The API and database are now up and running, though without any data being loaded into the frontend (for now). +In the next handin, this will be handled. diff --git a/docs/AI-Usage.md b/docs/AI-Usage.md index 4923243..8d41deb 100644 --- a/docs/AI-Usage.md +++ b/docs/AI-Usage.md @@ -25,4 +25,4 @@ Different group members use different harnesses and models, according to persona | 14.10.2026 | Anton | Microsoft Copilot | Used to help "convert" a html/css design i made based on figma sketch to react/typescript components. | | 15.10.2026 | Anton | Microsoft Copilot | Used to make the foundation for filterPanel component based on picture from Figma, but it was very bad so most was changed. | | 2026-10-16 | Henrik | Mistral Vibe Code | Improve the helper script for parsing the dataset, to get a smaller dataset with less duplicates. | -| 2026-10-16 | Henrik | Mistral Vibe Code | Improve the deployment script to also deploy the backend. | +| 2026-10-16 | Henrik | Mistral Vibe Code | Improve the deployment script to also deploy the backend. Also helped writing the docs for this. | diff --git a/docs/deployment.md b/docs/deployment.md new file mode 100644 index 0000000..2863bea --- /dev/null +++ b/docs/deployment.md @@ -0,0 +1,60 @@ +# Deployment + +The project is deployed to the NTNU VM (`it2810-11`) by `deploy.sh` in the repo root. Running the script deploys two things: + +- **Frontend** — static files built from `Frontend/`, served from `/var/www/html/project2` +- **Backend API** — the GraphQL server in `backend/`, run as the systemd service `t11-api` + +## What a deploy does + +1. `git fetch origin main` and compares local and remote commits. +2. **Frontend**: `npm ci` + `npm run build` in `Frontend/`, then replaces `/var/www/html/project2` with the fresh `dist/`. +3. **Backend** (skipped unless `backend/package.json` exists): `npm ci` in `backend/`, then installs and restarts the `t11-api` systemd service. + +## The API service + +The script writes this unit to `/etc/systemd/system/t11-api.service` (node/npm paths are resolved at deploy time): + +```ini +[Unit] +Description=T11-Project-2 GraphQL API +After=network.target postgresql.service + +[Service] +Type=simple +WorkingDirectory=/IT2810/T11-Project-2/backend +Environment="PATH=:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" +ExecStart= start +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +```bash +sudo systemctl daemon-reload +sudo systemctl enable t11-api.service +sudo systemctl restart t11-api.service +``` + +- The `PATH` line is required. systemd gives services a minimal default `PATH`, so npm's `#!/usr/bin/env node` shebang fails with `env: 'node': No such file or directory` (exit 127). The script resolves node's directory with `command -v node` in the cron environment, where node is known to be available. +- The API port comes from `backend/.env` (`GRAPHQL_PORT`, default `3001`). The deploy script does not override it. +- `enable` starts the API on boot, `Restart=on-failure` restarts it after crashes, and each deploy restarts it to pick up new code. +- The cron user needs passwordless sudo for `systemctl` and for writing the unit file. + +## Useful commands + +```bash +# Run a deploy manually +/IT2810/T11-Project-2/deploy.sh + +# API status and logs +sudo systemctl status t11-api +sudo journalctl -u t11-api -f + +# Restart the API without a full deploy +sudo systemctl restart t11-api +``` + +See also: `github-runners.md` (self-hosted runner), `postgresql-setup.md` (database on the VM). diff --git a/docs/github-runner-setup.md b/docs/github-runners.md similarity index 100% rename from docs/github-runner-setup.md rename to docs/github-runners.md diff --git a/docs/technical-choices.md b/docs/technical-choices.md index f216dbb..aab621b 100644 --- a/docs/technical-choices.md +++ b/docs/technical-choices.md @@ -38,3 +38,10 @@ The result is 12,505 releases and 268,159 tracks across 10 tables (~19 MB of SQL The subset is reproducible: one command (`bash scripts/make_subset.sh` in `Database/`) regenerates it from the raw dump and re-validates it against the schema with foreign keys enabled. The full pipeline, every decision and the pitfalls encountered are documented in `Database/AI-context.md`. There is more de-duplication that still needs to be done (e.g. the same album appearing under slightly different titles, or a 15-artist release counting towards several catalogues), but treating the different mediums of the same release (CD and Vinyl) as one already brings the data down to a workable size. + +## Deployment + +Deployment is handled by `deploy.sh` in the repo root, triggered by a cron job on the VM that polls the repository. This keeps the site up to date without a CI/CD workflow - the self-hosted runner (see `github-runners.md`) is not involved in deployment. The mechanics are documented in `deployment.md`; the choices behind them: + +- **Frontend as static files.** The Vite build output (`Frontend/dist`) is moved to `/var/www/html/project2`, where the web server serves it. The VM hosts several projects, so each gets its own subfolder of the web root. A deploy is therefore just "build, delete old, move new". +- **Backend as a systemd service.** The GraphQL API runs as the `t11-api` systemd unit, matching how PostgreSQL is already managed on the VM. `enable` starts it on boot, `Restart=on-failure` keeps it alive after crashes, and every deploy restarts it to pick up new code. We chose systemd over pm2 or Docker because the VM already uses it and it needs no extra tooling.