From 6297cdd83b855f456e9d22c7c0be32a453e72729 Mon Sep 17 00:00:00 2001 From: SandObserver <260779319+SandObserver@users.noreply.github.com> Date: Sun, 18 Oct 2026 21:46:50 -0400 Subject: [PATCH] Narrow the README dependency claim State that the image has no runtime npm dependencies and adds only nginx and supervisor from Alpine to the Node base. --- README.md | 2 +- test/repo/readme-dependencies.test.js | 28 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 test/repo/readme-dependencies.test.js diff --git a/README.md b/README.md index 86f4b3ed..55964df2 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Most dashboards are a wall of numbers and charts. Stackyard is the opposite: a c - **A glance should tell you more than a number would.** Widgets are small visuals, not readouts. - **Anything can be a badge.** Point Stackyard at any API and show what it reports as a [live activity badge](https://stackyard.sandobserver.com/docs/badges/). One poll can carry several labelled values, each with its own colour and threshold. No custom widget, no code. - **Configured by clicking, not by editing files.** Everything is set up in the web UI, with config import and export. -- **No dependencies.** Review it once and stop worrying about the supply chain. +- **No runtime npm dependencies.** The image adds only nginx and supervisor, from Alpine, to the official Node base. - **Six languages, right-to-left included.** Contrast and screen-reader labels are covered by tests. - **Installs like an app.** A mobile layout that opens in its own window from a home screen. No offline mode: every tile is live. diff --git a/test/repo/readme-dependencies.test.js b/test/repo/readme-dependencies.test.js new file mode 100644 index 00000000..a9f674d3 --- /dev/null +++ b/test/repo/readme-dependencies.test.js @@ -0,0 +1,28 @@ +/* The README names what the image adds to its base. A dependency added to the + API or a package added to the image makes that sentence false. */ + +const { test } = require('node:test'); +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); + +const root = path.join(__dirname, '..', '..'); +const read = f => fs.readFileSync(path.join(root, f), 'utf8'); + +test('the README says what the image adds to its base', () => { + assert.match( + read('README.md'), + /No runtime npm dependencies\.\*\* The image adds only nginx and supervisor, from Alpine, to the official Node base\./, + ); +}); + +test('the API declares no npm dependencies', () => { + const pkg = JSON.parse(read('api/package.json')); + assert.deepEqual(pkg.dependencies || {}, {}); +}); + +test('the image installs nginx and supervisor and no other package', () => { + const adds = [...read('Dockerfile').matchAll(/apk add\s+((?:--\S+\s+)*)([^&\\\n]+)/g)].map(m => m[2].trim()); + assert.deepEqual(adds, ['nginx supervisor']); + assert.match(read('Dockerfile'), /^FROM node:\d+-alpine@sha256:[0-9a-f]{64}$/m); +});