Fix Flood 4.7 Node runtime compatibility and gate publishing on startup

This commit is contained in:
k2patel committed 2026-09-30 21:14:48 -04:00
1 parent 1c113788ed
commit de75459e97
4 files changed
+62 -2

No files matched your search

+1
View File
@@ -32,6 +32,7 @@ jobs:
git -C flood-repo fetch --depth=1 https://github.com/jesec/flood.git "refs/tags/$FLOOD_VERSION"
git -C flood-repo checkout --detach FETCH_HEAD
cp Dockerfile.client flood-repo/Dockerfile.client
cp tests/startup.cjs flood-repo/.ci-startup.cjs
printf '\n.git\n.github\n.env\n' >> flood-repo/.dockerignore
- name: Install Docker CLI
+4 -1
View File
@@ -2,7 +2,7 @@
# Build from a clean upstream release checkout using the Gitea workflow.
ARG BUILDPLATFORM=amd64
ARG NODE_IMAGE=docker.io/node:24-alpine3.24
ARG NODE_IMAGE=docker.io/node:22-alpine3.24
FROM --platform=$BUILDPLATFORM ${NODE_IMAGE} as nodebuild
@@ -48,5 +48,8 @@ RUN apk add coreutils
# System local configuration
VOLUME /server/db/
# Fail the build before publication if the actual server cannot start.
RUN node .ci-startup.cjs && rm .ci-startup.cjs
# Flood server in development mode
ENTRYPOINT ["npm", "--prefix=/usr/src/app/", "run", "start:development:server", "--", "--host=0.0.0.0", "--rundir=/server/"]
+5 -1
View File
@@ -24,5 +24,9 @@ runner image store, and the temporary builder and cache are removed afterward.
No image archives or build records are uploaded to Gitea, and no local container
builds are required.
Base image: Node.js 24 on Alpine Linux 3.24 stable (`node:24-alpine3.24`),
Base image: Node.js 22 on Alpine Linux 3.24 stable (`node:22-alpine3.24`),
including the latest patch updates in those release series.
Flood 4.7 requires Node 22 because its legacy SPDY dependency uses an internal
HTTP parser removed in Node 24. The image build starts the actual Flood server
and requires HTTP 200 before publishing; it does not start a torrent daemon.
+52
View File
@@ -0,0 +1,52 @@
const {spawn} = require('node:child_process');
const http = require('node:http');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const runDir = fs.mkdtempSync(path.join(os.tmpdir(), 'flood-smoke-'));
const child = spawn('npm', ['run', 'start:development:server', '--',
'--host=127.0.0.1', '--port=3000', `--rundir=${runDir}`],
{stdio: 'inherit', detached: true});
let startupError;
child.on('error', error => { startupError = error; });
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
const check = () => new Promise(resolve => {
const req = http.get('http://127.0.0.1:3000/', response => {
let bytes = 0;
response.on('data', chunk => { bytes += chunk.length; });
response.on('end', () => resolve(response.statusCode === 200 && bytes > 0));
});
req.setTimeout(1000, () => req.destroy());
req.on('error', () => resolve(false));
});
(async () => {
try {
const deadline = Date.now() + 60000;
while (Date.now() < deadline) {
if (startupError) throw startupError;
if (child.exitCode !== null || child.signalCode !== null) {
throw new Error(`Flood exited before serving HTTP: ${child.exitCode ?? child.signalCode}`);
}
if (await check()) {
console.log('Flood startup smoke test passed: HTTP 200 with response body');
return;
}
await sleep(500);
}
throw new Error('Flood did not serve HTTP within 60 seconds');
} catch (error) {
console.error(error);
process.exitCode = 1;
} finally {
if (child.pid) {
try { process.kill(-child.pid, 'SIGTERM'); } catch (error) {
if (error.code !== 'ESRCH') throw error;
}
await sleep(500);
try { process.kill(-child.pid, 'SIGKILL'); } catch (error) {
if (error.code !== 'ESRCH') throw error;
}
}
fs.rmSync(runDir, {recursive: true, force: true});
}
})();