Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions docs/ci-cd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# CI/CD

This page explains how our continuous integration (CI) works.

## Summary

- **CI is automated.** A GitHub Actions workflow checks every pull request and
every push to `main`.
- **CD is not automated yet.** Deploying to the VM is a manual step for now. We might add
automated CD later.

## Continuous integration

The workflow is defined in [`.github/workflows/ci.yml`](../.github/workflows/ci.yml).

### When it runs

- On every pull request that targets `main`.
- On every push to `main`

When a new commit is pushed to a branch that has an ongoing older run, the older run gets cancelled. (`concurrency` in the workflow). This saves runner time
and energy, and only the latest commit matters anyway.

### What it does

The workflow has one job, `checks`. It runs on our
[self-hosted runner](#the-self-hosted-runner) and performs these steps in order. The job stops at the first step that fails.

| Step | What it checks |
| ---------------------- | ----------------------------------------------------- |
| `actions/checkout` | Fetches the code. |
| `actions/setup-node` | Installs Node.js 22 and caches npm downloads. |
| `npm ci` | Installs exactly the versions in `package-lock.json`. |
| `npm run lint` | ESLint for the frontend and the backend. |
| `npm run format:check` | Prettier formatting for the whole repository. |
| `npm test` | Vitest unit and component tests. |
| `npm run build` | Type-checks and builds the frontend and the backend. |

### The self-hosted runner

NTNU's GitHub Enterprise (`https://git.ntnu.no`) provides no hosted runners, so
the jobs run on a runner installed on our group's VM.

**Setup.** A repository admin adds the runner under _Settings > Actions >
Runners > New self-hosted runner_ and runs the commands GitHub shows on the VM.
The registration token is single-use and must never be committed. The runner
lives in `~/actions-runner` and runs as a systemd service, so it survives
reboots (`sudo ./svc.sh install` and `sudo ./svc.sh start`).

**If a CI run never starts**, the runner is probably down, because jobs stay
queued instead of failing. Check that the VM is on, then run
`sudo ./svc.sh status` in `~/actions-runner`.

**Good to know.** Node.js is not preinstalled on the runner, which is why the
workflow uses `actions/setup-node`. Old builds pile up in
`~/actions-runner/_work`, so clear it if the disk fills up.

### What it does not do yet

- There are no end-to-end tests or API tests, because we have not chosen the
tools yet. The backend has no `test` script, so `npm test` skips it.
- It does not run against a database. The Python import script in
`backend/data` is not tested by CI.

## Merging

CI is one of two gates before a pull request can be merged into `main`. The
other is review. A pull request cannot be merged while CI is failing.

If CI fails, open the failed run from the pull request page, read the log of
the failed step, and fix it on your branch. Pushing a new commit starts a new
run, and also dismisses existing approvals.

## Continuous delivery

Nothing is deployed automatically. After a merge to `main`, someone has to
update the VM by hand for now.