Fix Flood 4.7 Node runtime compatibility and gate publishing on startup
This commit is contained in:
1 parent
1c113788ed
commit
de75459e97
4 files changed
+62
-2
No files matched your search
@@ -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 fetch --depth=1 https://github.com/jesec/flood.git "refs/tags/$FLOOD_VERSION"
|
||||||
git -C flood-repo checkout --detach FETCH_HEAD
|
git -C flood-repo checkout --detach FETCH_HEAD
|
||||||
cp Dockerfile.client flood-repo/Dockerfile.client
|
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
|
printf '\n.git\n.github\n.env\n' >> flood-repo/.dockerignore
|
||||||
|
|
||||||
- name: Install Docker CLI
|
- name: Install Docker CLI
|
||||||
|
|||||||
+4
-1
@@ -2,7 +2,7 @@
|
|||||||
# Build from a clean upstream release checkout using the Gitea workflow.
|
# Build from a clean upstream release checkout using the Gitea workflow.
|
||||||
|
|
||||||
ARG BUILDPLATFORM=amd64
|
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
|
FROM --platform=$BUILDPLATFORM ${NODE_IMAGE} as nodebuild
|
||||||
|
|
||||||
@@ -48,5 +48,8 @@ RUN apk add coreutils
|
|||||||
# System local configuration
|
# System local configuration
|
||||||
VOLUME /server/db/
|
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
|
# Flood server in development mode
|
||||||
ENTRYPOINT ["npm", "--prefix=/usr/src/app/", "run", "start:development:server", "--", "--host=0.0.0.0", "--rundir=/server/"]
|
ENTRYPOINT ["npm", "--prefix=/usr/src/app/", "run", "start:development:server", "--", "--host=0.0.0.0", "--rundir=/server/"]
|
||||||
@@ -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
|
No image archives or build records are uploaded to Gitea, and no local container
|
||||||
builds are required.
|
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.
|
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.
|
||||||
@@ -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});
|
||||||
|
}
|
||||||
|
})();
|
||||||
Reference in new issue
Block a user