Dockerfile: copy moments.js; guard test for required top-level modules

The 5497e8b image lacked moments.js, so the reader crashed at start on
docker-01. test/dockerfile.test.js follows server.js requires and fails
when a top-level module is not copied into the image.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
MaashkinoozheandClaude Opus 5.5 committed 2026-10-27 12:56:07 +01:00
1 parent 5497e8bfbc
commit f38f218ae0
2 files changed
+23 -1

No files matched your search

+1 -1
View File
@@ -3,7 +3,7 @@ RUN apk add --no-cache tzdata openssl
WORKDIR /app
ARG VCS_REF=development
LABEL org.opencontainers.image.title="MangaCircus" org.opencontainers.image.revision=$VCS_REF
COPY package.json server.js library.js reading-direction.js chapter-identity.js chapter-dates.js reading-analytics.js reading-access.js catalog.js backup.js ./
COPY package.json server.js library.js reading-direction.js chapter-identity.js chapter-dates.js reading-analytics.js reading-access.js catalog.js backup.js moments.js ./
COPY public ./public
COPY greatest ./greatest
COPY discovery ./discovery
+22
View File
@@ -0,0 +1,22 @@
'use strict';
// The image copies top-level modules by name; a new module missing there crashes the reader at start.
const test = require('node:test'), assert = require('node:assert/strict');
const fs = require('fs'), path = require('path');
const root = path.resolve(__dirname, '..');
test('every top-level module the reader requires is copied into the image', () => {
const dockerfile = fs.readFileSync(path.join(root, 'Dockerfile'), 'utf8');
const copied = new Set(dockerfile.split('\n').filter(line => line.startsWith('COPY ')).flatMap(line => line.split(/\s+/).slice(1, -1)));
const pending = ['server.js'], seen = new Set();
while (pending.length) {
const file = pending.pop();
if (seen.has(file)) continue;
seen.add(file);
for (const [, name] of fs.readFileSync(path.join(root, file), 'utf8').matchAll(/require\('\.\/([\w.-]+?)(?:\.js)?'\)/g)) {
// A folder (e.g. ./greatest) is copied as a whole; only single files need their own name in COPY.
if (fs.existsSync(path.join(root, name)) && fs.statSync(path.join(root, name)).isDirectory()) assert.ok(copied.has(name), `${name}/ is not copied`);
else pending.push(name + '.js');
}
}
for (const file of seen) assert.ok(copied.has(file), `${file} is required but not copied by the Dockerfile`);
});