Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/docker-compose.ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ services:
- "9138:9138"
- "50019:50019"
- "6473:6473"
- "4001:4001"
- "4001:4001/udp"
volumes:
- bitsocial-data:/data
- bitsocial-logs:/logs
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ ENV XDG_STATE_HOME=/logs
ENV KUBO_RPC_URL="http://0.0.0.0:50019/api/v0"
ENV IPFS_GATEWAY_URL="http://0.0.0.0:6473"

EXPOSE 9138 50019 6473
EXPOSE 9138 50019 6473 4001

VOLUME ["/data", "/logs"]

Expand Down
8 changes: 5 additions & 3 deletions docker-compose.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ services:
container_name: bitsocial
restart: unless-stopped
ports:
- "9138:9138" # Plebbit RPC + Web UI
- "50019:50019" # Kubo IPFS API
- "6473:6473" # IPFS Gateway
- "9138:9138" # Plebbit RPC + Web UI
- "50019:50019" # Kubo IPFS API
- "6473:6473" # IPFS Gateway
- "4001:4001" # Kubo Swarm (TCP)
- "4001:4001/udp" # Kubo Swarm (QUIC + WebTransport + WebRTC-direct)
volumes:
- bitsocial-data:/data
- bitsocial-logs:/logs
Expand Down
8 changes: 5 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@ services:
restart: unless-stopped
stop_grace_period: 30s
ports:
- "9138:9138" # Plebbit RPC + Web UI
- "50019:50019" # Kubo IPFS API
- "6473:6473" # IPFS Gateway
- "9138:9138" # Plebbit RPC + Web UI
- "50019:50019" # Kubo IPFS API
- "6473:6473" # IPFS Gateway
- "4001:4001" # Kubo Swarm (TCP)
- "4001:4001/udp" # Kubo Swarm (QUIC + WebTransport + WebRTC-direct)
volumes:
- bitsocial-data:/data
- bitsocial-logs:/logs
Expand Down
10 changes: 1 addition & 9 deletions src/ipfs/startIpfs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,7 @@ export async function mergeCliDefaultsIntoIpfsConfig(log: any, ipfsConfigPath: s
Addresses: {
...(currentIpfsConfigFile["Addresses"] ?? {}),
Gateway: `/ip4/${gatewayUrl.hostname}/tcp/${gatewayUrl.port}`,
API: `/ip4/${apiUrl.hostname}/tcp/${apiUrl.port}`,
Swarm: [
"/ip4/0.0.0.0/tcp/0",
"/ip6/::/tcp/0",
"/ip4/0.0.0.0/udp/0/quic-v1",
"/ip4/0.0.0.0/udp/0/quic-v1/webtransport",
"/ip6/::/udp/0/quic-v1",
"/ip6/::/udp/0/quic-v1/webtransport"
]
API: `/ip4/${apiUrl.hostname}/tcp/${apiUrl.port}`
},
AutoTLS: {
...(currentIpfsConfigFile["AutoTLS"] ?? {}),
Expand Down
17 changes: 16 additions & 1 deletion test/helpers/daemon-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { ChildProcess, spawn } from "child_process";
import net from "net";
import path from "path";
import { directory as randomDirectory } from "tempy";
import WebSocket from "ws";
import defaults from "../../dist/common-utils/defaults.js";
import { preInitKuboWithEphemeralSwarm } from "./kubo-helpers.js";

export type ManagedChildProcess = ChildProcess & { kuboRpcUrl?: URL; capturedStdout?: string; capturedStderr?: string };

Expand Down Expand Up @@ -72,7 +74,20 @@ export const startPkcDaemon = (args: string[], env?: Record<string, string>): Pr
const hasCustomDataPath = args.some((arg) => arg.startsWith("--pkcOptions.dataPath"));
const hasCustomLogPath = args.some((arg) => arg === "--logPath");
const logPathArgs = hasCustomLogPath ? [] : ["--logPath", randomDirectory()];
const daemonArgs = hasCustomDataPath ? args : ["--pkcOptions.dataPath", randomDirectory(), ...args];
const dataPath = hasCustomDataPath
? (args[args.findIndex((a) => a.startsWith("--pkcOptions.dataPath")) + 1] as string)
: randomDirectory();
const daemonArgs = hasCustomDataPath ? args : ["--pkcOptions.dataPath", dataPath, ...args];

// Pre-init kubo so parallel test daemons don't collide on swarm port 4001.
const apiUrl = new URL(env?.KUBO_RPC_URL ?? defaults.KUBO_RPC_URL.toString());
const gatewayUrl = new URL(env?.IPFS_GATEWAY_URL ?? defaults.IPFS_GATEWAY_URL.toString());
try {
await preInitKuboWithEphemeralSwarm(path.join(dataPath, ".bitsocial-cli.ipfs"), apiUrl, gatewayUrl);
} catch (error) {
return reject(error);
}

const daemonProcess = spawn("node", ["./bin/run", "daemon", ...logPathArgs, ...daemonArgs], {
stdio: ["pipe", "pipe", "pipe"],
env: env ? { ...process.env, ...env } : undefined
Expand Down
39 changes: 39 additions & 0 deletions test/helpers/kubo-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as fs from "fs/promises";
import path from "path";
import { execFile } from "child_process";
import { promisify } from "util";
import { path as resolveKuboBinary } from "kubo";
import { mergeCliDefaultsIntoIpfsConfig } from "../../src/ipfs/startIpfs.js";

const execFileAsync = promisify(execFile);

const EPHEMERAL_SWARM_ADDRESSES = [
"/ip4/0.0.0.0/tcp/0",
"/ip6/::/tcp/0",
"/ip4/0.0.0.0/udp/0/quic-v1",
"/ip4/0.0.0.0/udp/0/quic-v1/webtransport",
"/ip6/::/udp/0/quic-v1",
"/ip6/::/udp/0/quic-v1/webtransport"
];

// Pre-init a kubo repo so each parallel test daemon gets its own kernel-assigned
// swarm port instead of fighting over the default 4001. Mirrors what
// startKuboNode does on a fresh config (init + server profile + merge defaults),
// then overrides Swarm to ephemeral addresses. When the bitsocial daemon later
// runs `ipfs init` against this dir it'll bail with "configuration file already
// exists", skip mergeCliDefaultsIntoIpfsConfig, and spawn kubo with our Swarm.
export const preInitKuboWithEphemeralSwarm = async (ipfsDataPath: string, apiUrl: URL, gatewayUrl: URL) => {
await fs.mkdir(ipfsDataPath, { recursive: true });
const kuboBinaryPath = await resolveKuboBinary();
const env = { ...process.env, IPFS_PATH: ipfsDataPath };

await execFileAsync(kuboBinaryPath, ["init"], { env });
await execFileAsync(kuboBinaryPath, ["config", "profile", "apply", "server"], { env });

const configPath = path.join(ipfsDataPath, "config");
await mergeCliDefaultsIntoIpfsConfig(() => {}, configPath, apiUrl, gatewayUrl);

const config = JSON.parse(await fs.readFile(configPath, "utf-8"));
config.Addresses = { ...(config.Addresses ?? {}), Swarm: EPHEMERAL_SWARM_ADDRESSES };
await fs.writeFile(configPath, JSON.stringify(config, null, 4));
};
3 changes: 3 additions & 0 deletions test/kubo/kuboRpcGateway.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { directory as tempDirectory } from "tempy";
import { setTimeout as delay } from "timers/promises";
import { promisify } from "util";
import { startKuboNode } from "../../src/ipfs/startIpfs.js";
import { preInitKuboWithEphemeralSwarm } from "../helpers/kubo-helpers.js";

const execFileAsync = promisify(execFile);

Expand Down Expand Up @@ -184,6 +185,8 @@ describe("kubo RPC + gateway integration", { timeout: 120_000 }, () => {
apiUrl = new URL(`http://127.0.0.1:${apiPort}`);
gatewayUrl = new URL(`http://127.0.0.1:${gatewayPort}`);

await preInitKuboWithEphemeralSwarm(ipfsRepoPath, apiUrl, gatewayUrl);

kuboProcess = await startKuboNode(apiUrl, gatewayUrl, dataPath);

await waitForOkResponse(() => fetch(new URL("/api/v0/version", apiUrl), { method: "POST" }));
Expand Down
21 changes: 12 additions & 9 deletions test/kubo/mergeCliDefaultsIntoIpfsConfig.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,19 @@ const writeConfigToTempFile = async (config: Record<string, any>) => {

describe("mergeCliDefaultsIntoIpfsConfig", () => {
it("overrides core defaults on freshly initialized config", async () => {
const kuboDefaultSwarm = [
"/ip4/0.0.0.0/tcp/4001",
"/ip6/::/tcp/4001",
"/ip4/0.0.0.0/udp/4001/webrtc-direct",
"/ip4/0.0.0.0/udp/4001/quic-v1",
"/ip4/0.0.0.0/udp/4001/quic-v1/webtransport",
"/ip6/::/udp/4001/webrtc-direct",
"/ip6/::/udp/4001/quic-v1",
"/ip6/::/udp/4001/quic-v1/webtransport"
];
Comment on lines +20 to +29
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
npm run test:cli

Repository: bitsocialnet/bitsocial-cli

Length of output: 1321


Verify the test suite passes in your local environment before merging.

The npm run test:cli command failed to execute in the verification environment due to missing dependencies (decompress package). Please ensure you have run npm run test:cli in your local environment and that all tests pass before committing.

Per coding guidelines: "**/*.test.ts: MUST run tests with npm run test:cli to verify all tests pass before committing"

Also applies to: lines 32-32, 43-43

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/kubo/mergeCliDefaultsIntoIpfsConfig.test.ts` around lines 20 - 29, The
test suite failure is caused by missing test dependency "decompress" when
running npm run test:cli; run npm run test:cli locally, add the missing package
to devDependencies (install "decompress") and re-run the tests until all tests
in mergeCliDefaultsIntoIpfsConfig.test.ts (which defines kuboDefaultSwarm) pass,
then commit the updated package.json/package-lock.json so CI verification
succeeds.

const initialConfig = {
Addresses: {
Swarm: ["/ip4/0.0.0.0/tcp/4001"],
Swarm: kuboDefaultSwarm,
Gateway: "/ip4/0.0.0.0/tcp/8080"
}
};
Expand All @@ -30,14 +40,7 @@ describe("mergeCliDefaultsIntoIpfsConfig", () => {
const mergedConfig = JSON.parse(await fs.readFile(configPath, "utf-8"));
expect(mergedConfig.Addresses.API).toBe("/ip4/127.0.0.1/tcp/5001");
expect(mergedConfig.Addresses.Gateway).toBe("/ip4/127.0.0.1/tcp/8080");
expect(mergedConfig.Addresses.Swarm).toEqual([
"/ip4/0.0.0.0/tcp/0",
"/ip6/::/tcp/0",
"/ip4/0.0.0.0/udp/0/quic-v1",
"/ip4/0.0.0.0/udp/0/quic-v1/webtransport",
"/ip6/::/udp/0/quic-v1",
"/ip6/::/udp/0/quic-v1/webtransport"
]);
expect(mergedConfig.Addresses.Swarm).toEqual(kuboDefaultSwarm);
expect(mergedConfig.AutoTLS.Enabled).toBe(true);
});

Expand Down
Loading