Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/Documents/DEVELOPMENT.md
blob: 4781e76e2e4286948607a9924000bb2621deb84f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
<!-- SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com> -->
<!-- SPDX-License-Identifier: AGPL-3.0-or-later WITH AdditionRef-Progmasoft-Patent-Grant-1.1 -->

# Development

## Requirements

| Tool | Version | Used for |
| --- | --- | --- |
| Node.js | 22.18 or newer; CI uses 24 | the frontend and all JavaScript tests |
| npm | the one that ships with Node.js | frontend dependencies |
| Temurin JDK | 25 | the backend |
| Gradle | 9.6.0, the version CI installs | the backend build; the repository has no Gradle wrapper |

## Frontend

```text
cd frontend
npm ci
npm run dev            # development server
npm run check          # vue-tsc type check
npm test               # Node tests
npm run format:check   # Prettier, also over ../forum
npm run build          # type check and production build into dist/
```

`npm run format` rewrites the files Prettier checks. The development server proxies `/api` to
`http://127.0.0.1:5080`, the default port of a locally started backend.

`.npmrc` refuses install scripts of dependencies that were not reviewed. A new dependency with an install script
fails `npm ci` until its exact version is allowed in `package.json`.

## Backend

```text
cd backend
gradle test bootJar dokkaGenerate --no-daemon
gradle bootRun --no-daemon      # serves on 127.0.0.1:5080
```

- `test` runs the Spring tests.
- `bootJar` builds `build/libs/visual-xsharp-website-api-1.0.0.jar`.
- `dokkaGenerate` builds the API documentation and is a gate: a public declaration without KDoc, a broken link or an
  unresolved reference fails the build.

### Dependency locks and checksums

The backend pins every resolved version in `gradle.lockfile` and the SHA-256 of every downloaded file in
`gradle/verification-metadata.xml`. After changing a dependency or a plugin, regenerate both and review the diff:

```text
gradle dependencies --write-locks --no-daemon
gradle --refresh-dependencies --write-verification-metadata sha256 help test jacocoTestReport bootJar dokkaGenerate --no-daemon
```

`--refresh-dependencies` matters. With a warm local cache Gradle does not download every metadata file again and so
does not record it; the build then passes locally and fails verification on a clean CI machine.

A checksum is an integrity pin, not a trust review. Confirm the version and the repository of an artifact before
accepting its checksum.

## Forum page

`forum/` has no build step. Open `forum/index.html` through any static file server, for example:

```text
python -m http.server 3022 --bind 127.0.0.1 --directory forum
```

Its script is tested by `frontend/tests/forum.test.mjs`, which runs it against a minimal fake document. To see the
notice in another language, change the preferred language of the browser.

## Tests

All JavaScript tests run with `npm test` in `frontend/`.

| File | Asserts |
| --- | --- |
| `locales.test.mjs` | the published locales, browser-language selection, the English fallback, that a stored choice wins, text direction, and when a change is remembered |
| `seo.test.mjs` | the title, description and canonical URL of every route in every language |
| `forum.test.mjs` | the notice in each language, the fallback, the absence of a language menu, and the theme button |
| `site-integrity.test.mjs` | sitemap and router agreement, forum non-indexing, logo and social image shape, absence of retired links, pinned workflow actions, and that the Nginx and systemd files agree with each other |

Two tests in `site-integrity.test.mjs` compare the site with a checkout of the compiler repository next to this one
and skip themselves when it is absent.

The backend tests assert the content of `/api/v1/site`, the empty health response, that the API is read-only, and
that account and registry routes do not exist.

A change to a page is not verified by these tests alone. Look at it in a browser: all four languages, both themes, a
narrow window, and keyboard focus.

## Continuous integration

| Job | Enforces |
| --- | --- |
| `frontend` | `npm ci`, `npm audit` at moderate severity, type check, tests with coverage, format check, build |
| `backend` | tests with coverage, the jar, and the Dokka documentation gate |
| `frontend-coverage`, `backend-coverage` | upload coverage to Codecov |
| `dependency-review` | reviews dependency changes of a pull request |
| CodeQL | static analysis of the workflows, TypeScript and Kotlin |

Only the coverage jobs receive an OIDC token; the jobs that install and build do not, and pull requests from forks
skip the upload. Workflow actions are pinned to commit hashes, and a test fails when one is not.

`main` is protected: changes arrive through pull requests with green checks.

## Conventions

- Public documents, comments, commit messages and pull request text are written in American English.
- Every file carries the SPDX header of the repository; `REUSE.toml` covers the formats that cannot hold a comment.
- A user-visible string is added to every locale in the same change. See [Localization](LOCALIZATION.md).
- What the pages may claim about the language is governed by the [content contract](CONTENT.md).