Skip to content

Latest commit

 

History

History
119 lines (95 loc) · 5.5 KB

CONTRIBUTING.md

File metadata and controls

119 lines (95 loc) · 5.5 KB

Contributing

The full contributor guide is at stackyard.sandobserver.com/docs/contributing.

Contributions are welcome within the constraints that keep Stackyard small and auditable. A change that breaks one of these will not be merged:

  • One container: Nginx and the Node API run together under supervisord. No extra services, no database.
  • No runtime dependencies: the API ships zero npm runtime packages; the frontend is vanilla HTML/CSS/JS with no framework and no build step.
  • Server-side is CommonJS, the frontend is ES modules.

If a feature seems to need a dependency or a build step, open an issue first.

Development

Run Stackyard from the working tree with Docker Compose 2.23 or later:

docker compose -f docker-compose.dev.yml watch

It serves http://127.0.0.1:8701. A saved file reaches the container within a few seconds. A change under api/src or ui/widgets, or to a module the API shares with the frontend, restarts the container. A change to the Dockerfile, nginx or supervisord config rebuilds the image. Data is kept in .dev/.

Unit tests use Node's built-in runner and need nothing installed; coverage and the browser tests use the dev tooling in the root package.json.

An export whose name starts with _ exists for the tests and is not part of what the module offers: _internals for functions reached directly, _reset* for the hooks that clear state between tests. Anything else exported is API, and is exported under the name it is defined with.

Tests

A change to behaviour lands with its tests, in the same pull request. New functionality needs tests for that functionality. A bug fix needs a test that fails without the fix. The coverage floor below enforces part of this rule; it is not the whole of it.

Before opening a PR

These are the checks CI runs, in the order it runs them. They are defined once, in .github/actions/checks/action.yml, so the list here is the whole of that action:

npm ci
node scripts/changelog-check.js
node scripts/bump-cache-busting.js --check
npm run paths:check
cd api && npm test
cd api && npx c8 check-coverage --lines 92
cd ui/test && node --test
cd test/repo && node --test
npm run lint
npm run format:check
npm run typecheck
npm run typecheck:ui
docker build -t stackyard:ci .

The end-to-end suite is a separate required check, in .github/workflows/e2e.yml. It starts the image on a local port and runs the browser specs against it:

npx playwright install chromium webkit
BASE_URL=http://127.0.0.1:<port> npx playwright test

CodeQL also runs on every pull request. A finding it reports has to be resolved before merge.

Trivy also scans the image built above. A HIGH or CRITICAL finding with a fix available fails the run. The threshold is in SECURITY.md.

  • changelog-check.js verifies the structure of CHANGELOG.md: the Keep a Changelog header, the six section names, a real date on every released version, descending versions, and a compare link per version. Structure fails the check. Style problems in [Unreleased], such as a rationale clause or a three-sentence entry, print as warnings on the pull request and do not fail it. Releasing is documented at Releasing.

  • Changelog entries go in the pull request description, under Changelog, as - lines below a ### Fixed, ### Added or other Keep a Changelog heading. Do not edit CHANGELOG.md in a pull request. On merge, a workflow adds the entries to [Unreleased]. A pull request with no user-visible change leaves the section empty.

  • bump-cache-busting.js --check verifies that every /css/ and /js/ reference carries a ?v= stamp. The release build recomputes the hashes, so write ?v=1 and never edit a stamp by hand.

  • npm run typecheck:ui typechecks every module under ui/js from its JSDoc, with no build step and nothing emitted. It has to stay clean. A new module needs two entries in tsconfig.frontend.json, the plain path and the ?v=* form, because TypeScript allows one wildcard per pattern.

  • Test code is linted and formatted along with everything else, with a few rules relaxed for api/test, api/test-support, ui/test and test/repo in biome.json: a stub whose signature has to match a real one keeps its unused parameter, a scanner keeps while ((m = re.exec(s))), and 'use strict' stays where a test depends on strict-mode semantics.

    They are not typechecked. checkJs over api/test reports 131 errors, almost all narrowing around Node's server.address() in test harnesses. Changing that is its own piece of work, not a side effect of something else.

  • npm run lint is Biome, from node_modules. Run it through npm: a bare npx biome resolves to an unrelated package that exits 0 without checking anything. A warning fails the run. Fix it or relax the rule in biome.json; leaving it outstanding is not an option CI allows.

More