diff --git a/Dockerfile b/Dockerfile index dac2be8..33a0451 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/test/dockerfile.test.js b/test/dockerfile.test.js new file mode 100644 index 0000000..4327071 --- /dev/null +++ b/test/dockerfile.test.js @@ -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`); +});