diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90c802b490..1a5e20b97d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,52 @@ jobs: - run: npm run build:esm - run: npm run test:browser + build_rln_tree: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + repository: waku-org/js-waku + - uses: actions/setup-node@v3 + with: + node-version: ${{ env.NODE_JS }} + - name: Check for existing RLN tree artifact + id: check-artifact + uses: actions/github-script@v6 + with: + script: | + const artifact = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.runId + }); + console.log(artifact); + const foundArtifact = artifact.data.artifacts.find(art => art.name === 'rln_tree.tar.gz'); + if (foundArtifact) { + core.setOutput('artifact_id', foundArtifact.id); + core.setOutput('artifact_found', 'true'); + } else { + core.setOutput('artifact_found', 'false'); + } + - name: Download RLN tree artifact + if: steps.check-artifact.outputs.artifact_found == 'true' + uses: actions/download-artifact@v3 + with: + name: rln_tree.tar.gz + path: /tmp + - uses: ./.github/actions/npm + - name: Sync rln tree and save artifact + run: | + mkdir -p /tmp/rln_tree.db + npm run build:esm + npm run sync-rln-tree + tar -czf rln_tree.tar.gz -C /tmp/rln_tree.db . + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: rln_tree.tar.gz + path: rln_tree.tar.gz + node: uses: ./.github/workflows/test-node.yml secrets: inherit diff --git a/package.json b/package.json index 0602ff90b6..9c61e50df1 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "doc": "run-s doc:*", "doc:html": "typedoc --options typedoc.cjs", "doc:cname": "echo 'js.waku.org' > docs/CNAME", - "publish": "node ./ci/publish.js" + "publish": "node ./ci/publish.js", + "sync-rln-tree": "node ./packages/tests/src/sync-rln-tree.js" }, "devDependencies": { "@size-limit/preset-big-lib": "^11.0.2", diff --git a/packages/tests/src/constants.ts b/packages/tests/src/constants.ts index bba66ecc84..4e444a8777 100644 --- a/packages/tests/src/constants.ts +++ b/packages/tests/src/constants.ts @@ -62,3 +62,6 @@ export const TEST_TIMESTAMPS = [ ]; export const MOCHA_HOOK_MAX_TIMEOUT = 50_000; + +export const SEPOLIA_RPC_URL = + process.env.SEPOLIA_RPC_URL || "https://sepolia.gateway.tenderly.co"; diff --git a/packages/tests/src/lib/dockerode.ts b/packages/tests/src/lib/dockerode.ts index 8254b6ba14..fb28652fd5 100644 --- a/packages/tests/src/lib/dockerode.ts +++ b/packages/tests/src/lib/dockerode.ts @@ -115,7 +115,17 @@ export default class Dockerode { ...(args?.peerExchange && { [`${discv5UdpPort}/udp`]: [{ HostPort: discv5UdpPort.toString() }] }) - } + }, + Mounts: args.rlnRelayEthClientAddress + ? [ + { + Type: "bind", + ReadOnly: false, + Source: "/tmp/rln_tree.db", + Target: "/rln_tree.db" + } + ] + : [] }, ExposedPorts: { [`${restPort}/tcp`]: {}, diff --git a/packages/tests/src/lib/service_node.ts b/packages/tests/src/lib/service_node.ts index db9b620ee6..7dc4f95561 100644 --- a/packages/tests/src/lib/service_node.ts +++ b/packages/tests/src/lib/service_node.ts @@ -87,6 +87,10 @@ export class ServiceNode { return isGoWaku ? "go-waku" : "nwaku"; } + get containerName(): string | undefined { + return this.docker?.container?.id; + } + async start( args: Args = {}, options: { @@ -229,6 +233,17 @@ export class ServiceNode { ); } + async healthy(): Promise { + this.checkProcess(); + + return this.restCall( + "/health", + "GET", + undefined, + async (response) => response.status === 200 + ); + } + async ensureSubscriptions( pubsubTopics: string[] = [DefaultPubsubTopic] ): Promise { diff --git a/packages/tests/src/sync-rln-tree.js b/packages/tests/src/sync-rln-tree.js new file mode 100644 index 0000000000..19b9ce0b0f --- /dev/null +++ b/packages/tests/src/sync-rln-tree.js @@ -0,0 +1,56 @@ +import { exec } from "child_process"; +import { setTimeout } from "timers"; +import { promisify } from "util"; + +import { SEPOLIA_RPC_URL } from "../dist/constants.js"; +import { ServiceNode } from "../dist/lib/service_node.js"; + +const execAsync = promisify(exec); + +const WAKUNODE_IMAGE = process.env.WAKUNODE_IMAGE || "wakuorg/nwaku:v0.27.0"; +const containerName = "rln_tree"; + +async function syncRlnTree() { + try { + await execAsync(`docker inspect ${WAKUNODE_IMAGE}`); + console.log(`Using local image ${WAKUNODE_IMAGE}`); + } catch (error) { + console.log(`Pulling image ${WAKUNODE_IMAGE}`); + await execAsync(`docker pull ${WAKUNODE_IMAGE}`); + console.log("Image pulled"); + } + + const nwaku = new ServiceNode(containerName); + await nwaku.start( + { + store: false, + lightpush: false, + relay: true, + filter: false, + rest: true, + clusterId: 1, + rlnRelayEthClientAddress: SEPOLIA_RPC_URL + }, + { retries: 3 } + ); + let healthy = false; + while (!healthy) { + healthy = await nwaku.healthy(); + await new Promise((resolve) => setTimeout(resolve, 500)); + } + + await execAsync( + `docker cp ${nwaku.containerName}:/rln_tree.db /tmp/rln_tree.db` + ); + await nwaku.stop(); +} + +syncRlnTree() + .then(() => { + console.log("Synced RLN tree"); + process.exit(0); + }) + .catch((err) => { + console.error(`Error syncing RLN tree: ${err}`); + process.exit(1); + }); diff --git a/packages/tests/src/types.ts b/packages/tests/src/types.ts index 33bb757475..5932c9d458 100644 --- a/packages/tests/src/types.ts +++ b/packages/tests/src/types.ts @@ -25,6 +25,7 @@ export interface Args { // `legacyFilter` is required to enable filter v1 with go-waku legacyFilter?: boolean; clusterId?: number; + rlnRelayEthClientAddress?: string; } export interface Ports {