2025-09-09 19:18:50 +00:00
|
|
|
import { existsSync } from "node:fs";
|
test: 🐳 Add docker support for datahaven nodes (#71)
> [!NOTE]
> This is `Part 3` of the ongoing _Docker Series._
## New Additions:
- Launching Datahaven network will spin up containers, as opposed to
native binaries
- `stop:docker` script to kill all dh containers
- `e2e` test suite for datahaven solochain network
- Contains reference test file that uses papi for storage queries,
submitting exts, runtime calls (good job on that facu and tobi)
- Added new utils:
- `waitForLog()` to wait for log lines in docker container logs
- `createPapiConnectors()` helper for test cases to build and connect to
dh network
- `getPapiSigner()` helper to return a papi compatible signer using our
prefunded accounts (alith by default)
- `sendTxn()` helper to submit txn and wait for block inclusion, instead
of finalization, which std library provides
## Changes:
> [!CAUTION]
> Launching native binaries for datahaven no longer supported.
- Datahaven binary location cli option changed to `-i,
--datahaven-image-tag`
- To locally run this you'll need a datahaven docker image handy, you'll
need to either:
- Point to remote dockerhub e.g. `moonsonglabs/datahaven:main` (must be
logged in and have permission)
- Build this locally with `bun build:docker:operator`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added end-to-end tests for the Datahaven solochain, including runtime
API queries, storage lookups, extrinsic submissions, and event
listening.
- Introduced CLI option to specify the Datahaven Docker image tag, with
a default value.
- Added CLI option to disable the Relayer.
- Provided new scripts to stop Docker containers associated with
Datahaven.
- Added utility functions for Docker log monitoring and container
startup checks.
- Introduced utilities for interacting with the Datahaven Polkadot API.
- **Improvements**
- Switched Datahaven network launch from local binaries to Docker
containers.
- Enhanced cache accuracy in build workflows by including Rust source
files in cache keys.
- Improved build performance with TypeScript incremental build options.
- Increased timeout for end-to-end tests for better reliability.
- Updated CLI version to 0.2.0.
- Modified Dockerfile build to enable the `fast-runtime` feature.
- Extended network launch summary to include relayer and container
details.
- **Bug Fixes**
- Fixed cleanup logic by tracking and preparing for forced removal of
Docker containers after tests.
- **Chores**
- Updated workflow steps for Docker image handling and network checks.
- Adjusted scripts and workflow logic for improved Docker and test
management.
- Removed top-level disk usage summaries from cleanup workflow for
streamlined reporting.
- Enhanced shell command utility to support asynchronous wait during
execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-05-16 14:17:05 +00:00
|
|
|
import { type Duplex, PassThrough, Transform } from "node:stream";
|
2025-04-08 15:42:45 +00:00
|
|
|
import Docker from "dockerode";
|
2025-04-14 19:22:43 +00:00
|
|
|
import invariant from "tiny-invariant";
|
2025-05-19 22:28:43 +00:00
|
|
|
import { logger, type ServiceInfo, StandardServiceMappings } from "utils";
|
2025-04-08 15:42:45 +00:00
|
|
|
|
2025-09-09 19:18:50 +00:00
|
|
|
function createDockerConnection(): Docker {
|
|
|
|
|
const dockerHost = process.env.DOCKER_HOST;
|
|
|
|
|
|
|
|
|
|
if (dockerHost) {
|
|
|
|
|
logger.debug(`Using DOCKER_HOST: ${dockerHost}`);
|
|
|
|
|
if (dockerHost.startsWith("unix://")) {
|
|
|
|
|
return new Docker({ socketPath: dockerHost.replace("unix://", "") });
|
|
|
|
|
}
|
|
|
|
|
if (dockerHost.startsWith("tcp://")) {
|
|
|
|
|
const url = new URL(dockerHost);
|
|
|
|
|
return new Docker({
|
|
|
|
|
host: url.hostname,
|
|
|
|
|
port: Number.parseInt(url.port) || 2375,
|
|
|
|
|
protocol: "http"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const socketPaths = [
|
|
|
|
|
"/var/run/docker.sock",
|
|
|
|
|
"/run/user/1000/docker.sock",
|
|
|
|
|
`${process.env.HOME}/.docker/run/docker.sock`
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
for (const socketPath of socketPaths) {
|
|
|
|
|
try {
|
|
|
|
|
if (existsSync(socketPath)) {
|
|
|
|
|
logger.debug(`Using Docker socket: ${socketPath}`);
|
|
|
|
|
return new Docker({ socketPath });
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.debug(`Failed to access socket ${socketPath}:`, error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logger.debug("Falling back to default Docker configuration");
|
|
|
|
|
return new Docker({});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const docker = createDockerConnection();
|
|
|
|
|
|
|
|
|
|
async function testDockerConnection(): Promise<void> {
|
|
|
|
|
try {
|
|
|
|
|
await docker.ping();
|
|
|
|
|
logger.debug("Docker connection successful");
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error("Docker connection failed:", error);
|
|
|
|
|
throw new Error(
|
|
|
|
|
`Failed to connect to Docker daemon: ${error instanceof Error ? error.message : String(error)}`
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-04-08 15:42:45 +00:00
|
|
|
|
test: 🐳 Add docker support for datahaven nodes (#71)
> [!NOTE]
> This is `Part 3` of the ongoing _Docker Series._
## New Additions:
- Launching Datahaven network will spin up containers, as opposed to
native binaries
- `stop:docker` script to kill all dh containers
- `e2e` test suite for datahaven solochain network
- Contains reference test file that uses papi for storage queries,
submitting exts, runtime calls (good job on that facu and tobi)
- Added new utils:
- `waitForLog()` to wait for log lines in docker container logs
- `createPapiConnectors()` helper for test cases to build and connect to
dh network
- `getPapiSigner()` helper to return a papi compatible signer using our
prefunded accounts (alith by default)
- `sendTxn()` helper to submit txn and wait for block inclusion, instead
of finalization, which std library provides
## Changes:
> [!CAUTION]
> Launching native binaries for datahaven no longer supported.
- Datahaven binary location cli option changed to `-i,
--datahaven-image-tag`
- To locally run this you'll need a datahaven docker image handy, you'll
need to either:
- Point to remote dockerhub e.g. `moonsonglabs/datahaven:main` (must be
logged in and have permission)
- Build this locally with `bun build:docker:operator`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added end-to-end tests for the Datahaven solochain, including runtime
API queries, storage lookups, extrinsic submissions, and event
listening.
- Introduced CLI option to specify the Datahaven Docker image tag, with
a default value.
- Added CLI option to disable the Relayer.
- Provided new scripts to stop Docker containers associated with
Datahaven.
- Added utility functions for Docker log monitoring and container
startup checks.
- Introduced utilities for interacting with the Datahaven Polkadot API.
- **Improvements**
- Switched Datahaven network launch from local binaries to Docker
containers.
- Enhanced cache accuracy in build workflows by including Rust source
files in cache keys.
- Improved build performance with TypeScript incremental build options.
- Increased timeout for end-to-end tests for better reliability.
- Updated CLI version to 0.2.0.
- Modified Dockerfile build to enable the `fast-runtime` feature.
- Extended network launch summary to include relayer and container
details.
- **Bug Fixes**
- Fixed cleanup logic by tracking and preparing for forced removal of
Docker containers after tests.
- **Chores**
- Updated workflow steps for Docker image handling and network checks.
- Adjusted scripts and workflow logic for improved Docker and test
management.
- Removed top-level disk usage summaries from cleanup workflow for
streamlined reporting.
- Enhanced shell command utility to support asynchronous wait during
execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-05-16 14:17:05 +00:00
|
|
|
export const getServicesFromDocker = async (): Promise<ServiceInfo[]> => {
|
2025-09-09 19:18:50 +00:00
|
|
|
let containers: Docker.ContainerInfo[];
|
|
|
|
|
try {
|
|
|
|
|
containers = await docker.listContainers();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
logger.error("Failed to list containers:", error);
|
|
|
|
|
await testDockerConnection();
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-08 15:42:45 +00:00
|
|
|
const services: ServiceInfo[] = [];
|
|
|
|
|
|
test: ⚙️ Parse & Generate Relayer Configs (#54)
## Human Written Description
This PR adds the following to the E2E CLI:
- Relayer config generation for: `beacon-relay` `beefy-relay`
- The other two relayer types to be added later
- Relayers don't actually work yet
- By default turned off, this requires a binary to be present in:
`<repo_root>/operator/target/release` dir
- Datahaven network launching
- DH network is using default `local` network chain spec
- Launched with 5 nodes since our authority set is 6 large (and you need
2/3 + 1 of set size
> [!NOTE]
> Both the relayer and the DH node binaries are being run as local
processes TEMPORARILY. This means that logging is done in a very
rudimentary way (we pipe to a file whilst the CLI is running).
>
> This means that when the CLI finishes **the log files will no longer
be written to**.
> This is temporary since spawning binaries is a stop gap solution until
docker images available.
---
> [!IMPORTANT]
> The following is AI generated slop describing this PR's changes:
**Key Changes:**
* **CLI Enhancements (`test/cli/index.ts`):**
* Added options `--datahaven` and `--datahaven-bin-path` to enable
launching local DataHaven nodes.
* Added options `--relayer` and `--relayer-bin-path` to enable launching
Snowbridge relayers (Beefy and Beacon).
* Added negation flags (`--no-fund-validators`, `--no-setup-validators`,
`--no-update-validator-set`) for more granular control over validator
setup steps.
* Added `--skip-cleaning` option to preserve Kurtosis state between
runs.
* Added a pre-action hook (`launchPreActionHook`) to validate flag
combinations (e.g., `--verified` requires `--blockscout`).
* **New CLI Handlers (`test/cli/handlers/launch/`):**
* `datahaven.ts`: Logic for spawning DataHaven node processes using the
specified binary. Manages ports and process cleanup.
* `relayer.ts`: Logic for configuring and spawning Snowbridge relayer
processes (Beefy and Beacon). Reads contract deployment addresses,
updates relayer config templates, and uses specified private keys.
Manages log files and process cleanup.
* `summary.ts`: Generates and displays the table of running services
(including dynamically launched DataHaven nodes) and their endpoints.
* `validator.ts`: Extracted validator funding, setup, and set update
logic into its own handler.
* `index.ts`: Orchestrates the launch sequence based on CLI options,
calling the appropriate handlers. Includes a `LaunchedNetwork` class to
track spawned processes, file descriptors, and node ports for cleanup.
* **Updated `package.json` Scripts:**
* Added `start:e2e:minrelayer` script for a minimal setup including
relayers and DataHaven nodes.
* Modified `stop:e2e` to include `pkill datahaven` for proper cleanup.
* Added `stop:e2e:quick` to only stop the Kurtosis enclave without full
cleaning.
* **Updated `launch-kurtosis.ts`:** Modified to use new Kurtosis utility
functions and added a `skipCleaning` option.
* **New Utility Functions:**
* `test/utils/kurtosis.ts`: Functions to inspect Kurtosis services
(`getServiceFromKurtosis`, `getPortFromKurtosis`,
`getServicesFromKurtosis`).
* `test/utils/parser.ts`: Zod schemas and parsing functions for
Snowbridge relayer configurations.
* **Constants & Minor Updates:**
* Added `SUBSTRATE_FUNDED_ACCOUNTS` to `test/utils/constants.ts`.
* Updated `tsconfig.json` include paths.
* Refactored `test/utils/docker.ts` (though now largely superseded by
Kurtosis utils).
* Updated logging in `test/scripts/send-txn.ts`.
**Reasoning:**
This PR significantly expands the E2E testing capabilities by allowing
developers to easily launch and integrate local DataHaven nodes and
Snowbridge relayers into the test network, facilitating more
comprehensive integration testing. The CLI refactoring makes managing
these complex setups more robust and user-friendly.
2025-04-29 12:24:00 +00:00
|
|
|
for (const mapping of StandardServiceMappings) {
|
2025-04-08 15:42:45 +00:00
|
|
|
try {
|
|
|
|
|
const container = containers.find((container) =>
|
|
|
|
|
container.Names.some((name) => name.includes(mapping.containerPattern))
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!container) {
|
2025-04-14 19:22:43 +00:00
|
|
|
logger.warn(`Container with pattern "${mapping.containerPattern}" not found.`);
|
2025-04-08 15:42:45 +00:00
|
|
|
services.push({
|
|
|
|
|
service: mapping.service,
|
|
|
|
|
port: "Not found",
|
|
|
|
|
url: "N/A"
|
|
|
|
|
});
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const portMappings = container.Ports.filter(
|
|
|
|
|
(port) => port.PrivatePort === mapping.internalPort && port.Type === mapping.protocol
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let selectedMapping = portMappings.find((port) => port.IP === "0.0.0.0" || port.IP === ":::");
|
|
|
|
|
|
|
|
|
|
if (!selectedMapping && portMappings.length > 0) {
|
|
|
|
|
selectedMapping = portMappings[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!selectedMapping || !selectedMapping.PublicPort) {
|
2025-04-14 19:22:43 +00:00
|
|
|
logger.warn(
|
2025-04-08 15:42:45 +00:00
|
|
|
`Port mapping not found for ${mapping.service} (${mapping.internalPort}/${mapping.protocol}).`
|
|
|
|
|
);
|
|
|
|
|
services.push({
|
|
|
|
|
service: mapping.service,
|
|
|
|
|
port: "Not found",
|
|
|
|
|
url: "N/A"
|
|
|
|
|
});
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
services.push({
|
|
|
|
|
service: mapping.service,
|
|
|
|
|
port: selectedMapping.PublicPort.toString(),
|
|
|
|
|
url: `http://127.0.0.1:${selectedMapping.PublicPort}`
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
2025-04-14 19:22:43 +00:00
|
|
|
logger.error(`Error getting info for ${mapping.service}:`, error);
|
2025-04-08 15:42:45 +00:00
|
|
|
services.push({
|
|
|
|
|
service: mapping.service,
|
|
|
|
|
port: "Error",
|
|
|
|
|
url: "N/A"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return services;
|
2025-04-15 14:01:24 +00:00
|
|
|
};
|
2025-04-14 19:22:43 +00:00
|
|
|
|
2025-05-22 20:02:12 +00:00
|
|
|
export const getContainersMatchingImage = async (imageName: string) => {
|
2025-05-29 13:14:46 +00:00
|
|
|
const containers = await docker.listContainers({ all: true });
|
2025-05-22 20:02:12 +00:00
|
|
|
const matches = containers.filter((container) => container.Image.includes(imageName));
|
|
|
|
|
return matches;
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-16 16:51:07 +00:00
|
|
|
export const getContainersByPrefix = async (prefix: string) => {
|
|
|
|
|
const containers = await docker.listContainers({ all: true });
|
|
|
|
|
const matches = containers.filter((container) =>
|
|
|
|
|
container.Names.some((name) => name.startsWith(`/${prefix}`))
|
|
|
|
|
);
|
|
|
|
|
return matches;
|
|
|
|
|
};
|
|
|
|
|
|
2025-04-14 19:22:43 +00:00
|
|
|
export const getPublicPort = async (
|
|
|
|
|
containerName: string,
|
|
|
|
|
internalPort: number
|
|
|
|
|
): Promise<number> => {
|
|
|
|
|
const containers = await docker.listContainers();
|
|
|
|
|
const container = containers.find((container) =>
|
|
|
|
|
container.Names.some((name) => name.includes(containerName))
|
|
|
|
|
);
|
|
|
|
|
invariant(container, `❌ container ${container} cannot be found in running container list`);
|
|
|
|
|
|
|
|
|
|
const portMappings = container.Ports.find(
|
|
|
|
|
(port) => port.PrivatePort === internalPort && port.Type === "tcp"
|
|
|
|
|
);
|
|
|
|
|
logger.debug(`Port mappings for ${containerName}:${internalPort}`, portMappings);
|
|
|
|
|
invariant(portMappings, `❌ port mapping not found for ${containerName}:${internalPort}`);
|
|
|
|
|
return portMappings.PublicPort;
|
|
|
|
|
};
|
test: 🐳 Add docker support for datahaven nodes (#71)
> [!NOTE]
> This is `Part 3` of the ongoing _Docker Series._
## New Additions:
- Launching Datahaven network will spin up containers, as opposed to
native binaries
- `stop:docker` script to kill all dh containers
- `e2e` test suite for datahaven solochain network
- Contains reference test file that uses papi for storage queries,
submitting exts, runtime calls (good job on that facu and tobi)
- Added new utils:
- `waitForLog()` to wait for log lines in docker container logs
- `createPapiConnectors()` helper for test cases to build and connect to
dh network
- `getPapiSigner()` helper to return a papi compatible signer using our
prefunded accounts (alith by default)
- `sendTxn()` helper to submit txn and wait for block inclusion, instead
of finalization, which std library provides
## Changes:
> [!CAUTION]
> Launching native binaries for datahaven no longer supported.
- Datahaven binary location cli option changed to `-i,
--datahaven-image-tag`
- To locally run this you'll need a datahaven docker image handy, you'll
need to either:
- Point to remote dockerhub e.g. `moonsonglabs/datahaven:main` (must be
logged in and have permission)
- Build this locally with `bun build:docker:operator`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added end-to-end tests for the Datahaven solochain, including runtime
API queries, storage lookups, extrinsic submissions, and event
listening.
- Introduced CLI option to specify the Datahaven Docker image tag, with
a default value.
- Added CLI option to disable the Relayer.
- Provided new scripts to stop Docker containers associated with
Datahaven.
- Added utility functions for Docker log monitoring and container
startup checks.
- Introduced utilities for interacting with the Datahaven Polkadot API.
- **Improvements**
- Switched Datahaven network launch from local binaries to Docker
containers.
- Enhanced cache accuracy in build workflows by including Rust source
files in cache keys.
- Improved build performance with TypeScript incremental build options.
- Increased timeout for end-to-end tests for better reliability.
- Updated CLI version to 0.2.0.
- Modified Dockerfile build to enable the `fast-runtime` feature.
- Extended network launch summary to include relayer and container
details.
- **Bug Fixes**
- Fixed cleanup logic by tracking and preparing for forced removal of
Docker containers after tests.
- **Chores**
- Updated workflow steps for Docker image handling and network checks.
- Adjusted scripts and workflow logic for improved Docker and test
management.
- Removed top-level disk usage summaries from cleanup workflow for
streamlined reporting.
- Enhanced shell command utility to support asynchronous wait during
execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-05-16 14:17:05 +00:00
|
|
|
|
|
|
|
|
export async function waitForLog(opts: {
|
|
|
|
|
search: string | RegExp;
|
|
|
|
|
containerName: string;
|
|
|
|
|
timeoutSeconds?: number;
|
|
|
|
|
}): Promise<string> {
|
|
|
|
|
const container = docker.getContainer(opts.containerName);
|
|
|
|
|
await container.inspect();
|
|
|
|
|
const timeoutMs = (opts.timeoutSeconds ?? 10) * 1_000;
|
|
|
|
|
|
|
|
|
|
const rawStream = (await container.logs({
|
|
|
|
|
stdout: true,
|
|
|
|
|
stderr: true,
|
|
|
|
|
follow: true,
|
|
|
|
|
since: 0
|
|
|
|
|
})) as Duplex;
|
|
|
|
|
const pass = new PassThrough();
|
|
|
|
|
container.modem.demuxStream(rawStream, pass, pass);
|
|
|
|
|
|
|
|
|
|
const { readable } = Transform.toWeb(pass);
|
|
|
|
|
const decoder = new TextDecoder();
|
|
|
|
|
const timer = setTimeout(
|
|
|
|
|
() =>
|
|
|
|
|
pass.destroy(
|
|
|
|
|
new Error(
|
2025-05-18 23:31:46 +00:00
|
|
|
`Timed out after ${timeoutMs} ms waiting for "${opts.search}" in ${opts.containerName}`
|
test: 🐳 Add docker support for datahaven nodes (#71)
> [!NOTE]
> This is `Part 3` of the ongoing _Docker Series._
## New Additions:
- Launching Datahaven network will spin up containers, as opposed to
native binaries
- `stop:docker` script to kill all dh containers
- `e2e` test suite for datahaven solochain network
- Contains reference test file that uses papi for storage queries,
submitting exts, runtime calls (good job on that facu and tobi)
- Added new utils:
- `waitForLog()` to wait for log lines in docker container logs
- `createPapiConnectors()` helper for test cases to build and connect to
dh network
- `getPapiSigner()` helper to return a papi compatible signer using our
prefunded accounts (alith by default)
- `sendTxn()` helper to submit txn and wait for block inclusion, instead
of finalization, which std library provides
## Changes:
> [!CAUTION]
> Launching native binaries for datahaven no longer supported.
- Datahaven binary location cli option changed to `-i,
--datahaven-image-tag`
- To locally run this you'll need a datahaven docker image handy, you'll
need to either:
- Point to remote dockerhub e.g. `moonsonglabs/datahaven:main` (must be
logged in and have permission)
- Build this locally with `bun build:docker:operator`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added end-to-end tests for the Datahaven solochain, including runtime
API queries, storage lookups, extrinsic submissions, and event
listening.
- Introduced CLI option to specify the Datahaven Docker image tag, with
a default value.
- Added CLI option to disable the Relayer.
- Provided new scripts to stop Docker containers associated with
Datahaven.
- Added utility functions for Docker log monitoring and container
startup checks.
- Introduced utilities for interacting with the Datahaven Polkadot API.
- **Improvements**
- Switched Datahaven network launch from local binaries to Docker
containers.
- Enhanced cache accuracy in build workflows by including Rust source
files in cache keys.
- Improved build performance with TypeScript incremental build options.
- Increased timeout for end-to-end tests for better reliability.
- Updated CLI version to 0.2.0.
- Modified Dockerfile build to enable the `fast-runtime` feature.
- Extended network launch summary to include relayer and container
details.
- **Bug Fixes**
- Fixed cleanup logic by tracking and preparing for forced removal of
Docker containers after tests.
- **Chores**
- Updated workflow steps for Docker image handling and network checks.
- Adjusted scripts and workflow logic for improved Docker and test
management.
- Removed top-level disk usage summaries from cleanup workflow for
streamlined reporting.
- Enhanced shell command utility to support asynchronous wait during
execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-05-16 14:17:05 +00:00
|
|
|
)
|
|
|
|
|
),
|
|
|
|
|
timeoutMs
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
for await (const chunk of readable) {
|
|
|
|
|
const text = decoder.decode(chunk as Uint8Array, { stream: false });
|
|
|
|
|
|
|
|
|
|
const hit =
|
|
|
|
|
typeof opts.search === "string" ? text.includes(opts.search) : opts.search.test(text);
|
|
|
|
|
|
|
|
|
|
if (hit) return text.trim();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new Error(
|
2025-05-18 23:31:46 +00:00
|
|
|
`Log stream ended before "${opts.search}" appeared for container ${opts.containerName}`
|
test: 🐳 Add docker support for datahaven nodes (#71)
> [!NOTE]
> This is `Part 3` of the ongoing _Docker Series._
## New Additions:
- Launching Datahaven network will spin up containers, as opposed to
native binaries
- `stop:docker` script to kill all dh containers
- `e2e` test suite for datahaven solochain network
- Contains reference test file that uses papi for storage queries,
submitting exts, runtime calls (good job on that facu and tobi)
- Added new utils:
- `waitForLog()` to wait for log lines in docker container logs
- `createPapiConnectors()` helper for test cases to build and connect to
dh network
- `getPapiSigner()` helper to return a papi compatible signer using our
prefunded accounts (alith by default)
- `sendTxn()` helper to submit txn and wait for block inclusion, instead
of finalization, which std library provides
## Changes:
> [!CAUTION]
> Launching native binaries for datahaven no longer supported.
- Datahaven binary location cli option changed to `-i,
--datahaven-image-tag`
- To locally run this you'll need a datahaven docker image handy, you'll
need to either:
- Point to remote dockerhub e.g. `moonsonglabs/datahaven:main` (must be
logged in and have permission)
- Build this locally with `bun build:docker:operator`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
- **New Features**
- Added end-to-end tests for the Datahaven solochain, including runtime
API queries, storage lookups, extrinsic submissions, and event
listening.
- Introduced CLI option to specify the Datahaven Docker image tag, with
a default value.
- Added CLI option to disable the Relayer.
- Provided new scripts to stop Docker containers associated with
Datahaven.
- Added utility functions for Docker log monitoring and container
startup checks.
- Introduced utilities for interacting with the Datahaven Polkadot API.
- **Improvements**
- Switched Datahaven network launch from local binaries to Docker
containers.
- Enhanced cache accuracy in build workflows by including Rust source
files in cache keys.
- Improved build performance with TypeScript incremental build options.
- Increased timeout for end-to-end tests for better reliability.
- Updated CLI version to 0.2.0.
- Modified Dockerfile build to enable the `fast-runtime` feature.
- Extended network launch summary to include relayer and container
details.
- **Bug Fixes**
- Fixed cleanup logic by tracking and preparing for forced removal of
Docker containers after tests.
- **Chores**
- Updated workflow steps for Docker image handling and network checks.
- Adjusted scripts and workflow logic for improved Docker and test
management.
- Removed top-level disk usage summaries from cleanup workflow for
streamlined reporting.
- Enhanced shell command utility to support asynchronous wait during
execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-05-16 14:17:05 +00:00
|
|
|
);
|
|
|
|
|
} finally {
|
|
|
|
|
if (timer) {
|
|
|
|
|
clearTimeout(timer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pass && typeof pass.destroy === "function" && !pass.destroyed) {
|
|
|
|
|
pass.destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rawStream) {
|
|
|
|
|
if (typeof rawStream.destroy === "function" && !rawStream.destroyed) {
|
|
|
|
|
rawStream.destroy();
|
|
|
|
|
}
|
|
|
|
|
const socket = (rawStream as any).socket;
|
|
|
|
|
if (socket && typeof socket.destroy === "function" && !socket.destroyed) {
|
|
|
|
|
socket.destroy();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const waitForContainerToStart = async (
|
|
|
|
|
containerName: string,
|
|
|
|
|
options?: { timeoutSeconds?: number }
|
|
|
|
|
) => {
|
|
|
|
|
logger.debug(`Waiting for container ${containerName} to start...`);
|
|
|
|
|
const seconds = options?.timeoutSeconds ?? 30;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < seconds; i++) {
|
|
|
|
|
const containers = await docker.listContainers();
|
|
|
|
|
const container = containers.find((container) =>
|
|
|
|
|
container.Names.some((name) => name.includes(containerName))
|
|
|
|
|
);
|
|
|
|
|
if (container) {
|
|
|
|
|
logger.debug(`Container ${containerName} started after ${i} seconds`);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await Bun.sleep(1000);
|
|
|
|
|
}
|
|
|
|
|
invariant(
|
|
|
|
|
false,
|
|
|
|
|
`❌ container ${containerName} cannot be found in running container list after ${seconds} seconds`
|
|
|
|
|
);
|
|
|
|
|
};
|
2025-05-18 23:31:46 +00:00
|
|
|
|
2025-07-16 16:51:07 +00:00
|
|
|
export const killExistingContainers = async (prefix: string) => {
|
|
|
|
|
logger.debug(`Searching for containers with image ${prefix}...`);
|
|
|
|
|
const containerInfos = await getContainersByPrefix(prefix);
|
2025-05-18 23:31:46 +00:00
|
|
|
|
|
|
|
|
if (containerInfos.length === 0) {
|
2025-07-16 16:51:07 +00:00
|
|
|
logger.debug(`No containers found with name starting with "${prefix}"`);
|
2025-05-18 23:31:46 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const promises = containerInfos.map(({ Id }) => docker.getContainer(Id).remove({ force: true }));
|
|
|
|
|
await Promise.all(promises);
|
|
|
|
|
|
2025-07-16 16:51:07 +00:00
|
|
|
logger.debug(`${containerInfos.length} containers with name starting with "${prefix}" killed`);
|
2025-05-18 23:31:46 +00:00
|
|
|
};
|