fix: fix testing torrents container
This commit is contained in:
parent
a0fc4c04d9
commit
1fca69fa66
@ -3,6 +3,11 @@ name: Build and Push Testing Torrents Container
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
ORG: dumtruck
|
||||||
|
PROJECT: konobangu
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-container:
|
build-container:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -23,6 +28,6 @@ jobs:
|
|||||||
context: 'packages/testing-torrents'
|
context: 'packages/testing-torrents'
|
||||||
file: './Dockerfile'
|
file: './Dockerfile'
|
||||||
push: true
|
push: true
|
||||||
tags: 'ghcr.io/${{ env.ORG }}/konobangu-testing-torrents:latest'
|
tags: 'ghcr.io/${{ env.ORG }}/${{ env.PROJECT }}-testing-torrents:latest'
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -5,7 +5,6 @@
|
|||||||
"unifiedjs.vscode-mdx",
|
"unifiedjs.vscode-mdx",
|
||||||
"mikestead.dotenv",
|
"mikestead.dotenv",
|
||||||
"christian-kohler.npm-intellisense",
|
"christian-kohler.npm-intellisense",
|
||||||
"skellock.just",
|
"skellock.just"
|
||||||
"charliermarsh.ruff"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -28,8 +28,5 @@
|
|||||||
"emmet.showExpandedAbbreviation": "never",
|
"emmet.showExpandedAbbreviation": "never",
|
||||||
"prettier.enable": false,
|
"prettier.enable": false,
|
||||||
"typescript.tsdk": "node_modules/typescript/lib",
|
"typescript.tsdk": "node_modules/typescript/lib",
|
||||||
"rust-analyzer.cargo.features": ["testcontainers"],
|
"rust-analyzer.cargo.features": ["testcontainers"]
|
||||||
"[python]": {
|
|
||||||
"editor.defaultFormatter": "charliermarsh.ruff"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
14
biome.json
14
biome.json
@ -10,7 +10,9 @@
|
|||||||
"noNonNullAssertion": "off"
|
"noNonNullAssertion": "off"
|
||||||
},
|
},
|
||||||
"suspicious": {
|
"suspicious": {
|
||||||
"noExplicitAny": "off"
|
"noExplicitAny": "off",
|
||||||
|
"noConsole": "off",
|
||||||
|
"noConsoleLog": "off"
|
||||||
},
|
},
|
||||||
"a11y": {
|
"a11y": {
|
||||||
"noSvgWithoutTitle": "off"
|
"noSvgWithoutTitle": "off"
|
||||||
@ -27,14 +29,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"ignore": [
|
"ignore": [".vscode/*.json"]
|
||||||
"packages/design-system/components/ui/**",
|
|
||||||
"packages/design-system/lib/**",
|
|
||||||
"packages/design-system/hooks/**",
|
|
||||||
"packages/collaboration/config.ts",
|
|
||||||
"apps/docs/**/*.json",
|
|
||||||
"apps/email/.react-email/**",
|
|
||||||
".vscode/*.json"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
services:
|
|
||||||
webui:
|
|
||||||
image: node:22-alpine
|
|
||||||
ports:
|
|
||||||
- '5000:5000'
|
|
||||||
volumes:
|
|
||||||
- ./apps/webui:/home/node/app
|
|
||||||
- node_modules:/home/node/app/node_modules
|
|
||||||
working_dir: /home/node/app/
|
|
||||||
command: sh -c "yarn install && yarn dev"
|
|
||||||
depends_on:
|
|
||||||
- mongo
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
|
|
||||||
mongo:
|
|
||||||
image: mongo:latest
|
|
||||||
ports:
|
|
||||||
- '27017:27017'
|
|
||||||
command:
|
|
||||||
- --storageEngine=wiredTiger
|
|
||||||
volumes:
|
|
||||||
- data:/data/db
|
|
||||||
logging:
|
|
||||||
driver: none
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
data:
|
|
||||||
node_modules:
|
|
@ -1,11 +1,14 @@
|
|||||||
FROM node:23-slim AS nodebt
|
FROM node:23-slim AS nodebt
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
ENV PNPM_HOME="/pnpm"
|
||||||
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
|
|
||||||
FROM nodebt AS deps
|
FROM nodebt AS deps
|
||||||
|
|
||||||
RUN mkdir -p /app/workspace
|
RUN mkdir -p /app/workspace
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package.json /app/
|
COPY package.json /app/
|
||||||
RUN npm install
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --no-frozen-lockfile
|
||||||
|
|
||||||
FROM deps AS app
|
FROM deps AS app
|
||||||
|
|
||||||
|
@ -1,28 +1,30 @@
|
|||||||
import Fastify from 'fastify';
|
|
||||||
import fastifyStatic from '@fastify/static';
|
import fastifyStatic from '@fastify/static';
|
||||||
import { join } from 'node:path';
|
import Fastify from 'fastify';
|
||||||
|
|
||||||
import WebTorrent, { Torrent } from 'webtorrent';
|
import fs from 'node:fs';
|
||||||
import createTorrent from 'create-torrent'
|
import fsp from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import TrackerServer from 'bittorrent-tracker/server'
|
import TrackerServer from 'bittorrent-tracker/server';
|
||||||
import fs, { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
import createTorrent from 'create-torrent';
|
||||||
|
import WebTorrent, { type Torrent } from 'webtorrent';
|
||||||
|
|
||||||
// Configuration
|
// Configuration
|
||||||
const API_PORT = 6080;
|
const API_PORT = 6080;
|
||||||
const TRACKER_PORT = 6081;
|
const TRACKER_PORT = 6081;
|
||||||
// Get local IP address for broader accessibility
|
const STATIC_API_PATH = '/api/static';
|
||||||
const LOCAL_IP = '127.0.0.1';
|
const LOCAL_IP = '127.0.0.1';
|
||||||
|
const WORKSPACE_PATH = 'workspace';
|
||||||
const TRACKER_URL = `http://${LOCAL_IP}:${TRACKER_PORT}/announce`;
|
const TRACKER_URL = `http://${LOCAL_IP}:${TRACKER_PORT}/announce`;
|
||||||
const API_BASE_URL = `http://${LOCAL_IP}:${API_PORT}/api/static/`;
|
const API_BASE_URL = `http://${LOCAL_IP}:${API_PORT}/${STATIC_API_PATH}/`;
|
||||||
|
|
||||||
// Initialize Fastify instance
|
// Initialize Fastify instance
|
||||||
const app = Fastify({ logger: true });
|
const app = Fastify({ logger: true });
|
||||||
|
|
||||||
// Mount static file service, mapping ./workspace directory to /api/static route
|
// Mount static file service, mapping ./workspace directory to /api/static route
|
||||||
app.register(fastifyStatic, {
|
app.register(fastifyStatic, {
|
||||||
root: join(process.cwd(), 'workspace'),
|
root: path.join(process.cwd(), WORKSPACE_PATH),
|
||||||
prefix: '/api/static',
|
prefix: STATIC_API_PATH,
|
||||||
});
|
});
|
||||||
|
|
||||||
const tracker = new TrackerServer({
|
const tracker = new TrackerServer({
|
||||||
@ -33,7 +35,6 @@ const tracker = new TrackerServer({
|
|||||||
trustProxy: true, // enable trusting x-forwarded-for header for remote IP [default=false]
|
trustProxy: true, // enable trusting x-forwarded-for header for remote IP [default=false]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Define request and response type definitions
|
// Define request and response type definitions
|
||||||
interface FileItem {
|
interface FileItem {
|
||||||
path: string;
|
path: string;
|
||||||
@ -53,23 +54,20 @@ interface ResponseSchema {
|
|||||||
// Start local Tracker
|
// Start local Tracker
|
||||||
async function startTracker(): Promise<void> {
|
async function startTracker(): Promise<void> {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
tracker.listen(TRACKER_PORT, "localhost", () => {
|
tracker.listen(TRACKER_PORT, 'localhost', () => {
|
||||||
console.log(`Tracker listening on port ${TRACKER_PORT}`);
|
console.log(`Tracker listening on port ${TRACKER_PORT}`);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
tracker.on('error', (err: any) => {
|
tracker.on('error', (err: any) => {
|
||||||
console.error(`Tracker error: ${err}`)
|
|
||||||
reject(`Tracker error: ${err}`);
|
reject(`Tracker error: ${err}`);
|
||||||
});
|
});
|
||||||
tracker.on('warning', (warn: any) => console.warn(`Tracker warning: ${warn}`));
|
tracker.on('warning', (warn: any) =>
|
||||||
|
console.warn(`Tracker warning: ${warn}`)
|
||||||
|
);
|
||||||
// Log tracked torrents
|
// Log tracked torrents
|
||||||
tracker.on('update', (addr: any, params: any) => {
|
tracker.on('update', (addr: any, params: any) => {
|
||||||
console.log(`Tracker update: ${params.info_hash} from ${addr}`);
|
console.log(`Tracker update: ${params.info_hash} from ${addr}`);
|
||||||
});
|
});
|
||||||
tracker.on('stop', function () {
|
|
||||||
reject(`Tracker stopped`);
|
|
||||||
})
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,18 +76,17 @@ const webTorrent = new WebTorrent({});
|
|||||||
|
|
||||||
// Generate mock file
|
// Generate mock file
|
||||||
async function generateMockFile(filePath: string, size: number) {
|
async function generateMockFile(filePath: string, size: number) {
|
||||||
const dir = join(filePath, '..');
|
const dir = path.dirname(filePath);
|
||||||
if (!existsSync(dir)) {
|
if (!fs.existsSync(dir)) {
|
||||||
mkdirSync(dir, { recursive: true })
|
await fsp.mkdir(dir, { recursive: true });
|
||||||
};
|
}
|
||||||
|
|
||||||
fs.writeFileSync(filePath, 'w');
|
await fsp.truncate(filePath, size);
|
||||||
fs.truncateSync(filePath, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate torrent file
|
// Generate torrent file
|
||||||
function generateTorrent(folderPath: string, torrentPath: string): Promise<void> {
|
function generateTorrent(folderPath: string, torrentPath: string) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
createTorrent(
|
createTorrent(
|
||||||
folderPath,
|
folderPath,
|
||||||
{
|
{
|
||||||
@ -97,15 +94,15 @@ function generateTorrent(folderPath: string, torrentPath: string): Promise<void>
|
|||||||
private: false,
|
private: false,
|
||||||
createdBy: 'WebTorrent',
|
createdBy: 'WebTorrent',
|
||||||
comment: 'Generated by WebTorrent server',
|
comment: 'Generated by WebTorrent server',
|
||||||
urlList: [API_BASE_URL]
|
urlList: [API_BASE_URL],
|
||||||
},
|
},
|
||||||
(err, torrent) => {
|
async (err, torrent) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(new Error(`Failed to create torrent: ${err}`));
|
reject(new Error(`Failed to create torrent: ${err}`));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
writeFileSync(torrentPath, torrent);
|
await fsp.writeFile(torrentPath, torrent);
|
||||||
if (!existsSync(torrentPath)) {
|
if (!fs.existsSync(torrentPath)) {
|
||||||
reject(new Error(`Torrent file ${torrentPath} was not created`));
|
reject(new Error(`Torrent file ${torrentPath} was not created`));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -114,37 +111,45 @@ function generateTorrent(folderPath: string, torrentPath: string): Promise<void>
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add torrent and seed
|
// Add torrent and seed
|
||||||
async function seedTorrent(torrentPath: string): Promise<Torrent> {
|
async function seedTorrent(torrentPath: string): Promise<Torrent> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const torrent = webTorrent.seed(torrentPath, {
|
const torrent = webTorrent.seed(
|
||||||
|
torrentPath,
|
||||||
|
{
|
||||||
announce: [TRACKER_URL],
|
announce: [TRACKER_URL],
|
||||||
}, (t) => {
|
},
|
||||||
|
(t) => {
|
||||||
resolve(t);
|
resolve(t);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
torrent.on('error', (err) => console.error(`Torrent error: ${err}`));
|
torrent.on('error', (err) => console.error(`Torrent error: ${err}`));
|
||||||
torrent.on('wire', (wire) => console.log(`Connected to peer: ${wire.peerId}`));
|
torrent.on('wire', (wire) =>
|
||||||
torrent.on('done', () => console.log(`Torrent ${torrent.infoHash} fully seeded`));
|
console.log(`Connected to peer: ${wire.peerId}`)
|
||||||
})
|
);
|
||||||
|
torrent.on('done', () =>
|
||||||
|
console.log(`Torrent ${torrent.infoHash} fully seeded`)
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle POST request to /api/torrents/mock
|
// Handle POST request to /api/torrents/mock
|
||||||
app.post<{ Body: RequestSchema }>('/api/torrents/mock', async (req, _reply) => {
|
app.post<{ Body: RequestSchema }>('/api/torrents/mock', async (req, _reply) => {
|
||||||
const { id, fileList } = req.body;
|
const { id, fileList } = req.body;
|
||||||
|
|
||||||
const idFolder = join('./workspace', id);
|
const idFolder = path.join(WORKSPACE_PATH, id);
|
||||||
if (!existsSync(idFolder)) {
|
if (!fs.existsSync(idFolder)) {
|
||||||
mkdirSync(idFolder, { recursive: true })
|
await fsp.mkdir(idFolder, { recursive: true });
|
||||||
};
|
}
|
||||||
|
|
||||||
for (const fileItem of fileList) {
|
for (const fileItem of fileList) {
|
||||||
const filePath = join(idFolder, fileItem.path);
|
const filePath = path.join(idFolder, fileItem.path);
|
||||||
await generateMockFile(filePath, fileItem.size);
|
await generateMockFile(filePath, fileItem.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
const torrentPath = join('./workspace', `${id}.torrent`);
|
const torrentPath = path.join(WORKSPACE_PATH, `${id}.torrent`);
|
||||||
await generateTorrent(idFolder, torrentPath);
|
await generateTorrent(idFolder, torrentPath);
|
||||||
|
|
||||||
const torrent = await seedTorrent(torrentPath);
|
const torrent = await seedTorrent(torrentPath);
|
||||||
@ -160,8 +165,7 @@ app.post<{ Body: RequestSchema }>('/api/torrents/mock', async (req, _reply) => {
|
|||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
await startTracker();
|
await startTracker();
|
||||||
await app.listen({ port: API_PORT, host: '0.0.0.0' });
|
await app.listen({ port: API_PORT, host: LOCAL_IP });
|
||||||
console.log(`Fastify running on http://0.0.0.0:${API_PORT}`);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Startup error:', err);
|
console.error('Startup error:', err);
|
||||||
webTorrent.destroy();
|
webTorrent.destroy();
|
||||||
|
@ -18,5 +18,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/create-torrent": "^5.0.2",
|
"@types/create-torrent": "^5.0.2",
|
||||||
"@types/webtorrent": "^0.110.0"
|
"@types/webtorrent": "^0.110.0"
|
||||||
|
},
|
||||||
|
"pnpm": {
|
||||||
|
"onlyBuiltDependencies": [
|
||||||
|
"utf-8-validate",
|
||||||
|
"node-datachannel",
|
||||||
|
"utp-native"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
1567
pnpm-lock.yaml
generated
1567
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
|||||||
packages:
|
packages:
|
||||||
- packages/*
|
- packages/*
|
||||||
- apps/*
|
- apps/*
|
||||||
|
- '!packages/testing-torrents'
|
||||||
onlyBuiltDependencies:
|
onlyBuiltDependencies:
|
||||||
- '@biomejs/biome'
|
- '@biomejs/biome'
|
||||||
- bufferutil
|
- bufferutil
|
||||||
|
Loading…
Reference in New Issue
Block a user