From d10b02e2731f9b5b2ffa181deede76061e31e541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 12 Apr 2023 13:43:27 +0200 Subject: [PATCH 01/25] feat: install Zinnia runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add another post-install step to download `zinniad` for running Zinnia modules. Signed-off-by: Miroslav Bajtoš --- scripts/post-install.js | 89 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 8 deletions(-) diff --git a/scripts/post-install.js b/scripts/post-install.js index f4ab593a..c7532a0c 100755 --- a/scripts/post-install.js +++ b/scripts/post-install.js @@ -14,11 +14,23 @@ import { platform, arch } from 'node:os' import assert from 'node:assert' const SATURN_DIST_TAG = 'v0.5.0' +const ZINNIA_DIST_TAG = 'v0.6.0' + const githubToken = process.env.GITHUB_TOKEN const authorization = githubToken ? `Bearer ${githubToken}` : undefined console.log('GitHub client:', authorization ? 'authorized' : 'anonymous') + +const outDir = join( + dirname(fileURLToPath(import.meta.url)), + '..', + 'modules' +) +await mkdir(outDir, { recursive: true }) + +//=== Saturn L2 ===// + const targets = [ { platform: 'darwin', arch: 'x64', url: 'Darwin_x86_64', archive: 'zip' }, { platform: 'linux', arch: 'arm64', url: 'Linux_arm64', archive: 'tar.gz' }, @@ -32,14 +44,7 @@ const target = targets.find(target => target.platform === platform() && target.arch === archOverwritten ) -assert(target, `Unsupported platform: ${platform} ${arch}`) - -const outDir = join( - dirname(fileURLToPath(import.meta.url)), - '..', - 'modules' -) -await mkdir(outDir, { recursive: true }) +assert(target, `Unsupported Saturn L2 platform: ${platform} ${arch}`) const outName = `saturn-L2-node-${platform()}-${archOverwritten}` const outFile = join(outDir, outName) @@ -92,3 +97,71 @@ if (target.archive === 'tar.gz') { } console.log(' ✓ %s', outFile) + +//=== Zinnia runtime ===// + +await downloadZinnia(); + +async function downloadZinnia() { + const targets = [ + { platform: 'darwin', arch: 'arm64', fileSuffix: 'macos-arm64', archive: 'zip' }, + { platform: 'darwin', arch: 'x64', fileSuffix: 'macos-x64', archive: 'zip' }, + { platform: 'linux', arch: 'arm64', fileSuffix: 'linux-arm64', archive: 'tar.gz' }, + { platform: 'linux', arch: 'x64', fileSuffix: 'linux-x64', archive: 'tar.gz' }, + { platform: 'win32', arch: 'x64', fileSuffix: 'windows-x64', archive: '.zip' } + ] + + const target = targets.find(target => + target.platform === platform() && + target.arch === arch() + ) + + + console.log(' ⇣ downloading zinniad-%s', target.fileSuffix) + const url = `https://github.com/filecoin-station/zinnia/releases/download/${ZINNIA_DIST_TAG}/zinniad-${target.fileSuffix}.${target.archive}` + const res = await fetch(url, { + headers: { + ...(authorization ? { authorization } : {}) + }, + redirect: 'follow' + }) + + if (res.status >= 300) { + throw new Error( + `Cannot fetch Zinnia binary for ${target.fileSuffix}: ${res.status}\n` + + await res.text() + ) + } + + if (!res.body) { + throw new Error( + `Cannot fetch Zinnia binary for ${target.fileSuffix}: ${res.status}: no response body` + ) + } + + let outFile; + if (target.archive === 'tar.gz') { + outFile = join(outDir, 'zinniad') + await pipeline(res.body, gunzip(), tar.extract(outDir)) + } else { + const parser = unzip.Parse() + await Promise.all([ + (async () => { + while (true) { + const [entry] = + /** @type {[UnzipStreamEntry]} */ + (await once(parser, 'entry')) + if (entry.path === 'zinniad' || entry.path === 'zinniad.exe') { + outFile = join(outDir, entry.path) + await pipeline(entry, createWriteStream(outFile)) + await chmod(outFile, 0o755) + return + } + } + })(), + pipeline(res.body, parser) + ]) + } + + console.log(' ✓ %s', outFile) +} From e6d458942ed744f84b49958cdd55d4ea6e296877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 12 Apr 2023 13:57:38 +0200 Subject: [PATCH 02/25] feat: install mod-peer-checker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- scripts/post-install.js | 51 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/scripts/post-install.js b/scripts/post-install.js index c7532a0c..2a1956d6 100755 --- a/scripts/post-install.js +++ b/scripts/post-install.js @@ -15,6 +15,13 @@ import assert from 'node:assert' const SATURN_DIST_TAG = 'v0.5.0' const ZINNIA_DIST_TAG = 'v0.6.0' +const ZINNIA_MODULES = [ + { + name: 'peer-checker', + repo: 'github.com/filecoin-station/mod-peer-checker', + tag: 'v1.0.0' + } +] const githubToken = process.env.GITHUB_TOKEN const authorization = githubToken ? `Bearer ${githubToken}` : undefined @@ -100,9 +107,9 @@ console.log(' ✓ %s', outFile) //=== Zinnia runtime ===// -await downloadZinnia(); +await downloadZinniaRuntime(); -async function downloadZinnia() { +async function downloadZinniaRuntime() { const targets = [ { platform: 'darwin', arch: 'arm64', fileSuffix: 'macos-arm64', archive: 'zip' }, { platform: 'darwin', arch: 'x64', fileSuffix: 'macos-x64', archive: 'zip' }, @@ -165,3 +172,43 @@ async function downloadZinnia() { console.log(' ✓ %s', outFile) } + +//=== Zinnia modules ===// + +await downloadZinniaModules(); + +async function downloadZinniaModules() { + for (const mod of ZINNIA_MODULES) { + await downloadModule(mod) + } +} + +async function downloadModule({name, repo, tag}) { + console.log(' ⇣ downloading module %s', name) + + const url = `https://${repo}/archive/refs/tags/${tag}.tar.gz` + const res = await fetch(url, { + headers: { + ...(authorization ? { authorization } : {}) + }, + redirect: 'follow' + }) + + if (res.status >= 300) { + throw new Error( + `Cannot fetch ${name} archive for tag ${tag}: ${res.status}\n` + + await res.text() + ) + } + + if (!res.body) { + throw new Error( + `Cannot fetch ${name} archive for tag ${tag}: no response body` + ) + } + + const outPath = join(outDir, name) + // `{ strip: 1}` tells tar to remove the top-level directory (e.g. `mod-peer-checker-v1.0.0`) + await pipeline(res.body, gunzip(), tar.extract(outPath, { strip: 1 })) + console.log(' ✓ %s', outPath) +} From 1ae29dd699ca361649bebcb5a166b8a0948b1f87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 12 Apr 2023 14:46:12 +0200 Subject: [PATCH 03/25] feat: run peer checker module via Zinnia MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- bin/station.js | 9 +++- commands/station.js | 32 +++++++---- lib/zinnia.js | 129 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 4 files changed, 161 insertions(+), 10 deletions(-) create mode 100644 lib/zinnia.js diff --git a/bin/station.js b/bin/station.js index 2217e73c..60f8b39a 100755 --- a/bin/station.js +++ b/bin/station.js @@ -22,6 +22,8 @@ Sentry.init({ await fs.mkdir(join(paths.moduleCache, 'saturn-L2-node'), { recursive: true }) await fs.mkdir(join(paths.moduleState, 'saturn-L2-node'), { recursive: true }) +await fs.mkdir(join(paths.moduleCache, 'zinnia'), { recursive: true }) +await fs.mkdir(join(paths.moduleState, 'zinnia'), { recursive: true }) await fs.mkdir(paths.moduleLogs, { recursive: true }) await maybeCreateMetricsFile() await maybeCreateActivityFile() @@ -41,7 +43,12 @@ yargs(hideBin(process.argv)) commands.activity ) .command('logs [module]', 'Show module logs', () => {}, commands.logs) - .choices('module', ['saturn-l2-node']) + .choices('module', [ + 'saturn-l2-node', + // TODO: find a way how to access logs of individual zinnia modules, + // in addition to Zinnia runtime + 'zinnia' + ]) .command('events', 'Events stream', () => {}, commands.events) .version(`${pkg.name}: ${pkg.version}`) .alias('v', 'version') diff --git a/commands/station.js b/commands/station.js index 725bf75a..8e93ef72 100644 --- a/commands/station.js +++ b/commands/station.js @@ -1,6 +1,7 @@ import { join } from 'node:path' import { paths } from '../lib/paths.js' import * as saturnNode from '../lib/saturn-node.js' +import * as zinniaRuntime from '../lib/zinnia.js' import { createLogStream } from '../lib/log.js' import { createMetricsStream } from '../lib/metrics.js' import { createActivityStream } from '../lib/activity.js' @@ -27,13 +28,26 @@ export const station = async () => { startPingLoop().unref() - await saturnNode.start({ - FIL_WALLET_ADDRESS, - MAX_DISK_SPACE, - storagePath: join(paths.moduleCache, 'saturn-L2-node'), - binariesPath: paths.moduleBinaries, - metricsStream: createMetricsStream(paths.metrics), - activityStream: createActivityStream('Saturn'), - logStream: createLogStream(join(paths.moduleLogs, 'saturn-L2-node.log')) - }) + await Promise.all([ + saturnNode.start({ + FIL_WALLET_ADDRESS, + MAX_DISK_SPACE, + storagePath: join(paths.moduleCache, 'saturn-L2-node'), + binariesPath: paths.moduleBinaries, + metricsStream: createMetricsStream(paths.metrics), + activityStream: createActivityStream('Saturn'), + logStream: createLogStream(join(paths.moduleLogs, 'saturn-L2-node.log')) + }), + + zinniaRuntime.start({ + FIL_WALLET_ADDRESS, + STATE_ROOT: join(paths.moduleState, 'zinnia'), + CACHE_ROOT: join(paths.moduleCache, 'zinnia'), + moduleBinaries: paths.moduleBinaries, + // FIXME(bajtos) We need to merge metrics reported by different modules + metricsStream: createMetricsStream(paths.metrics.replace(/\.log$/, '-zinnia.log')), + activityStream: createActivityStream('Runtime'), + logStream: createLogStream(join(paths.moduleLogs, 'zinnia.log')) + }) + ]) } diff --git a/lib/zinnia.js b/lib/zinnia.js new file mode 100644 index 00000000..74e7c606 --- /dev/null +++ b/lib/zinnia.js @@ -0,0 +1,129 @@ +import timers from 'node:timers/promises' +import { execa } from 'execa' +import { join } from 'node:path' +import { arch, platform } from 'node:os' +import { fetch } from 'undici' +import * as Sentry from '@sentry/node' + +function forwardChunkFromZinnia (chunk, log) { + const lines = chunk.trimEnd().split(/\n/g) + for (const ln of lines) { + log('[ZINNIA] %s', ln) + } +} + +async function start ({ + FIL_WALLET_ADDRESS, + STATE_ROOT, + CACHE_ROOT, + moduleBinaries, + metricsStream, + activityStream, + logStream +}) { + console.log('Starting Zinnia runtime...') + logStream.write('Starting Zinnia runtime') + + const zinniadExe = join(moduleBinaries, `zinniad${platform() === 'win32' ? '.exe' : ''}`) + const modules = [ + // all paths are relative to `moduleBinaries` + 'peer-checker/peer-checker.js' + ] + const childProcess = execa(zinniadExe, modules, { + cwd: moduleBinaries, + env: { + WALLET_ADDRESS: FIL_WALLET_ADDRESS, + STATE_ROOT, + CACHE_ROOT, + } + }) + + const readyPromise = new Promise((resolve, reject) => { + childProcess.stdout.setEncoding('utf-8') + childProcess.stdout.on('data', data => { + forwardChunkFromZinnia(data, console.log) + logStream.write(data) + handleEvents({activityStream, metricsStream}, data) + }) + + childProcess.stderr.setEncoding('utf-8') + childProcess.stderr.on('data', data => { + forwardChunkFromZinnia(data, console.error) + logStream.write(data) + }) + + childProcess.stdout.once('data', _data => { + // This is based on an implicit assumption that zinniad reports an info activity + // after it starts + resolve() + }) + childProcess.catch(reject) + }) + + childProcess.on('close', code => { + console.log(`Zinnia Runtime closed all stdio with code ${code ?? ''}`) + childProcess.stderr.removeAllListeners() + childProcess.stdout.removeAllListeners() + Sentry.captureException('Zinnia runtime exited') + }) + + childProcess.on('exit', (code, signal) => { + const reason = signal ? `via signal ${signal}` : `with code: ${code}` + const msg = `Zinnia Runtime exited ${reason}` + console.log(msg) + logStream.write(msg) + activityStream.write({ type: 'info', message: msg }) + }) + + try { + await Promise.race([ + readyPromise, + timers.setTimeout(500) + ]) + } catch (err) { + const errorMsg = err instanceof Error ? err.message : '' + err + const message = `Cannot start Zinnia Runtime: ${errorMsg}` + logStream.write(message) + console.error('Cannot start Zinnia Runtime:', err) + activityStream.write({ type: 'error', message }) + } +} + +function handleEvents ({activityStream, metricsStream}, text) { + text + .trimEnd() + .split(/\n/g) + .forEach(line => { + try { + const event = JSON.parse(line); + switch (event.type) { + case 'activity:info': + activityStream.write({ + type: 'info', + message: event.message, + source: event.module ?? 'Runtime' + }) + break + + case 'activity:error': + activityStream.write({ + type: 'error', + message: event.message, + source: event.module ?? 'Runtime' + }) + break + + case 'jobs-completed': + metricsStream.write({ totalJobsCompleted: event.total, totalEarnings: '0' }) + break + + default: + console.error('Ignoring Zinnia event of unknown type:', event) + } + } catch (err) { + console.error("Ignoring malformed Zinnia event:", line) + } + }) +} + +export { start } diff --git a/package.json b/package.json index d162f17b..d358b0be 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "scripts": { "format": "prettier --write .", + "start": "node ./bin/station.js", "test": "npm run test:lint && npm run test:unit", "test:lint": "prettier --check . && standard", "test:unit": "mocha --timeout 5000", From 6606423b605a7064c5ba88bdc3042354d3d3e73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 12 Apr 2023 14:53:08 +0200 Subject: [PATCH 04/25] fix formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- lib/zinnia.js | 13 ++++++------- scripts/post-install.js | 28 +++++++++++++--------------- 2 files changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/zinnia.js b/lib/zinnia.js index 74e7c606..c971fe3c 100644 --- a/lib/zinnia.js +++ b/lib/zinnia.js @@ -1,8 +1,7 @@ import timers from 'node:timers/promises' import { execa } from 'execa' import { join } from 'node:path' -import { arch, platform } from 'node:os' -import { fetch } from 'undici' +import { platform } from 'node:os' import * as Sentry from '@sentry/node' function forwardChunkFromZinnia (chunk, log) { @@ -34,7 +33,7 @@ async function start ({ env: { WALLET_ADDRESS: FIL_WALLET_ADDRESS, STATE_ROOT, - CACHE_ROOT, + CACHE_ROOT } }) @@ -43,7 +42,7 @@ async function start ({ childProcess.stdout.on('data', data => { forwardChunkFromZinnia(data, console.log) logStream.write(data) - handleEvents({activityStream, metricsStream}, data) + handleEvents({ activityStream, metricsStream }, data) }) childProcess.stderr.setEncoding('utf-8') @@ -89,13 +88,13 @@ async function start ({ } } -function handleEvents ({activityStream, metricsStream}, text) { +function handleEvents ({ activityStream, metricsStream }, text) { text .trimEnd() .split(/\n/g) .forEach(line => { try { - const event = JSON.parse(line); + const event = JSON.parse(line) switch (event.type) { case 'activity:info': activityStream.write({ @@ -121,7 +120,7 @@ function handleEvents ({activityStream, metricsStream}, text) { console.error('Ignoring Zinnia event of unknown type:', event) } } catch (err) { - console.error("Ignoring malformed Zinnia event:", line) + console.error('Ignoring malformed Zinnia event:', line) } }) } diff --git a/scripts/post-install.js b/scripts/post-install.js index 2a1956d6..094b9029 100755 --- a/scripts/post-install.js +++ b/scripts/post-install.js @@ -28,7 +28,6 @@ const authorization = githubToken ? `Bearer ${githubToken}` : undefined console.log('GitHub client:', authorization ? 'authorized' : 'anonymous') - const outDir = join( dirname(fileURLToPath(import.meta.url)), '..', @@ -36,7 +35,7 @@ const outDir = join( ) await mkdir(outDir, { recursive: true }) -//=== Saturn L2 ===// +//= == Saturn L2 ===// const targets = [ { platform: 'darwin', arch: 'x64', url: 'Darwin_x86_64', archive: 'zip' }, @@ -105,11 +104,11 @@ if (target.archive === 'tar.gz') { console.log(' ✓ %s', outFile) -//=== Zinnia runtime ===// +//= == Zinnia runtime ===// -await downloadZinniaRuntime(); +await downloadZinniaRuntime() -async function downloadZinniaRuntime() { +async function downloadZinniaRuntime () { const targets = [ { platform: 'darwin', arch: 'arm64', fileSuffix: 'macos-arm64', archive: 'zip' }, { platform: 'darwin', arch: 'x64', fileSuffix: 'macos-x64', archive: 'zip' }, @@ -123,7 +122,6 @@ async function downloadZinniaRuntime() { target.arch === arch() ) - console.log(' ⇣ downloading zinniad-%s', target.fileSuffix) const url = `https://github.com/filecoin-station/zinnia/releases/download/${ZINNIA_DIST_TAG}/zinniad-${target.fileSuffix}.${target.archive}` const res = await fetch(url, { @@ -146,7 +144,7 @@ async function downloadZinniaRuntime() { ) } - let outFile; + let outFile if (target.archive === 'tar.gz') { outFile = join(outDir, 'zinniad') await pipeline(res.body, gunzip(), tar.extract(outDir)) @@ -173,25 +171,25 @@ async function downloadZinniaRuntime() { console.log(' ✓ %s', outFile) } -//=== Zinnia modules ===// +//= == Zinnia modules ===// -await downloadZinniaModules(); +await downloadZinniaModules() -async function downloadZinniaModules() { +async function downloadZinniaModules () { for (const mod of ZINNIA_MODULES) { await downloadModule(mod) } } -async function downloadModule({name, repo, tag}) { +async function downloadModule ({ name, repo, tag }) { console.log(' ⇣ downloading module %s', name) const url = `https://${repo}/archive/refs/tags/${tag}.tar.gz` const res = await fetch(url, { - headers: { - ...(authorization ? { authorization } : {}) - }, - redirect: 'follow' + headers: { + ...(authorization ? { authorization } : {}) + }, + redirect: 'follow' }) if (res.status >= 300) { From 45c90746b7e26d35967fbaef5e1cce3ab19a6a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 12 Apr 2023 15:04:18 +0200 Subject: [PATCH 05/25] fixup! windows zinniad extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- scripts/post-install.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/post-install.js b/scripts/post-install.js index 094b9029..a4e56338 100755 --- a/scripts/post-install.js +++ b/scripts/post-install.js @@ -114,7 +114,7 @@ async function downloadZinniaRuntime () { { platform: 'darwin', arch: 'x64', fileSuffix: 'macos-x64', archive: 'zip' }, { platform: 'linux', arch: 'arm64', fileSuffix: 'linux-arm64', archive: 'tar.gz' }, { platform: 'linux', arch: 'x64', fileSuffix: 'linux-x64', archive: 'tar.gz' }, - { platform: 'win32', arch: 'x64', fileSuffix: 'windows-x64', archive: '.zip' } + { platform: 'win32', arch: 'x64', fileSuffix: 'windows-x64', archive: 'zip' } ] const target = targets.find(target => From f5cfb105ffa24a186f8eeb4101496aab35e1de15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 12 Apr 2023 15:11:58 +0200 Subject: [PATCH 06/25] test: fix never ending test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- test/test.js | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/test/test.js b/test/test.js index 17407758..2a9aa342 100644 --- a/test/test.js +++ b/test/test.js @@ -76,16 +76,19 @@ describe('Station', () => { station, { env: { CACHE_ROOT, STATE_ROOT, FIL_WALLET_ADDRESS } } ) - assert.strictEqual( - (await once(ps.stdout, 'data'))[0].toString(), - 'Starting Saturn node...\n' - ) - ps.stderr.pipe(process.stderr) - assert.strictEqual( - (await once(ps.stdout, 'data'))[0].toString(), - '[SATURN] INFO: Saturn Node will try to connect to the Saturn Orchestrator...\n' - ) - ps.kill() + try { + assert.strictEqual( + (await once(ps.stdout, 'data'))[0].toString(), + 'Starting Saturn node...\n' + ) + ps.stderr.pipe(process.stderr) + assert.strictEqual( + (await once(ps.stdout, 'data'))[0].toString(), + '[SATURN] INFO: Saturn Node will try to connect to the Saturn Orchestrator...\n' + ) + } finally { + ps.kill() + } }) }) From 305d766bf60bdb99c8e44c89583ab4d19af71250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 19 Apr 2023 20:44:43 +0200 Subject: [PATCH 07/25] upgrade zinniad to v0.7.0 --- lib/zinnia.js | 2 +- scripts/post-install.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/zinnia.js b/lib/zinnia.js index c971fe3c..57965922 100644 --- a/lib/zinnia.js +++ b/lib/zinnia.js @@ -31,7 +31,7 @@ async function start ({ const childProcess = execa(zinniadExe, modules, { cwd: moduleBinaries, env: { - WALLET_ADDRESS: FIL_WALLET_ADDRESS, + FIL_WALLET_ADDRESS, STATE_ROOT, CACHE_ROOT } diff --git a/scripts/post-install.js b/scripts/post-install.js index a4e56338..dc3ae977 100755 --- a/scripts/post-install.js +++ b/scripts/post-install.js @@ -14,7 +14,7 @@ import { platform, arch } from 'node:os' import assert from 'node:assert' const SATURN_DIST_TAG = 'v0.5.0' -const ZINNIA_DIST_TAG = 'v0.6.0' +const ZINNIA_DIST_TAG = 'v0.7.0' const ZINNIA_MODULES = [ { name: 'peer-checker', From c7c070a4053aab8575f970186ce99d9b291162b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 25 Apr 2023 17:42:11 +0200 Subject: [PATCH 08/25] Update commands/station.js Co-authored-by: Julian Gruber --- commands/station.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/station.js b/commands/station.js index 8e93ef72..2ea16e88 100644 --- a/commands/station.js +++ b/commands/station.js @@ -45,7 +45,7 @@ export const station = async () => { CACHE_ROOT: join(paths.moduleCache, 'zinnia'), moduleBinaries: paths.moduleBinaries, // FIXME(bajtos) We need to merge metrics reported by different modules - metricsStream: createMetricsStream(paths.metrics.replace(/\.log$/, '-zinnia.log')), + metricsStream: createMetricsStream('zinnia'), activityStream: createActivityStream('Runtime'), logStream: createLogStream(join(paths.moduleLogs, 'zinnia.log')) }) From e31bb4dc47debd4de09af75ec52e25f6a467e0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 26 Apr 2023 11:17:07 +0200 Subject: [PATCH 09/25] update tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- lib/zinnia.js | 14 +------------- test/station.js | 40 ++++++++++++++++++++++++++++++++++------ test/storage.js | 5 +++++ 3 files changed, 40 insertions(+), 19 deletions(-) diff --git a/lib/zinnia.js b/lib/zinnia.js index 57965922..37fc2800 100644 --- a/lib/zinnia.js +++ b/lib/zinnia.js @@ -4,13 +4,6 @@ import { join } from 'node:path' import { platform } from 'node:os' import * as Sentry from '@sentry/node' -function forwardChunkFromZinnia (chunk, log) { - const lines = chunk.trimEnd().split(/\n/g) - for (const ln of lines) { - log('[ZINNIA] %s', ln) - } -} - async function start ({ FIL_WALLET_ADDRESS, STATE_ROOT, @@ -20,7 +13,6 @@ async function start ({ activityStream, logStream }) { - console.log('Starting Zinnia runtime...') logStream.write('Starting Zinnia runtime') const zinniadExe = join(moduleBinaries, `zinniad${platform() === 'win32' ? '.exe' : ''}`) @@ -40,14 +32,12 @@ async function start ({ const readyPromise = new Promise((resolve, reject) => { childProcess.stdout.setEncoding('utf-8') childProcess.stdout.on('data', data => { - forwardChunkFromZinnia(data, console.log) logStream.write(data) handleEvents({ activityStream, metricsStream }, data) }) childProcess.stderr.setEncoding('utf-8') childProcess.stderr.on('data', data => { - forwardChunkFromZinnia(data, console.error) logStream.write(data) }) @@ -60,7 +50,7 @@ async function start ({ }) childProcess.on('close', code => { - console.log(`Zinnia Runtime closed all stdio with code ${code ?? ''}`) + logStream.write(`Zinnia Runtime closed all stdio with code ${code ?? ''}`) childProcess.stderr.removeAllListeners() childProcess.stdout.removeAllListeners() Sentry.captureException('Zinnia runtime exited') @@ -69,7 +59,6 @@ async function start ({ childProcess.on('exit', (code, signal) => { const reason = signal ? `via signal ${signal}` : `with code: ${code}` const msg = `Zinnia Runtime exited ${reason}` - console.log(msg) logStream.write(msg) activityStream.write({ type: 'info', message: msg }) }) @@ -83,7 +72,6 @@ async function start ({ const errorMsg = err instanceof Error ? err.message : '' + err const message = `Cannot start Zinnia Runtime: ${errorMsg}` logStream.write(message) - console.error('Cannot start Zinnia Runtime:', err) activityStream.write({ type: 'error', message }) } } diff --git a/test/station.js b/test/station.js index f7b036dd..a0c86f11 100644 --- a/test/station.js +++ b/test/station.js @@ -7,20 +7,30 @@ import { randomUUID } from 'node:crypto' import { join } from 'node:path' describe('Station', () => { - it('runs Saturn', async () => { + it('runs Saturn and Zinnia', async () => { const CACHE_ROOT = join(tmpdir(), randomUUID()) const STATE_ROOT = join(tmpdir(), randomUUID()) const ps = execa( station, { env: { CACHE_ROOT, STATE_ROOT, FIL_WALLET_ADDRESS } } ) + ps.stderr.pipe(process.stderr) assert.strictEqual( (await once(ps.stdout, 'data'))[0].toString().trim(), JSON.stringify({ totalJobsCompleted: 0, totalEarnings: '0' }, 0, 2) ) - ps.stderr.pipe(process.stderr) + const messages = [] + for await (const line of ps.stdout) { + messages.push(line.toString().trim()) + if (messages.length === 2) break + } + assert.match( - (await once(ps.stdout, 'data'))[0].toString().trim(), + messages[0], + /^\[.+\] INFO {2}Module Runtime started.$/ + ) + assert.match( + messages[1], /^\[.+\] INFO {2}Saturn Node will try to connect to the Saturn Orchestrator\.\.\.$/ ) ps.kill() @@ -36,11 +46,15 @@ describe('Station', () => { const events = [] for await (const line of ps.stdout) { events.push(line.toString().trim()) - if (events.length === 2) break + if (events.length === 3) break } ps.kill() assert.strictEqual(events[0], '{\n "totalJobsCompleted": 0,\n "totalEarnings": "0"\n}') - assert.match(events[1], /^\[.+\] INFO {2}Saturn Node will try to connect to the Saturn Orchestrator\.\.\.$/) + const logs = events.slice(1) + logs.sort() + + assert.match(logs[0], /^\[.+\] INFO {2}Module Runtime started.$/) + assert.match(logs[1], /^\[.+\] INFO {2}Saturn Node will try to connect to the Saturn Orchestrator\.\.\.$/) }) it('outputs events json', async () => { const CACHE_ROOT = join(tmpdir(), randomUUID()) @@ -53,15 +67,29 @@ describe('Station', () => { const events = [] for await (const line of ps.stdout) { events.push(JSON.parse(line.toString())) - if (events.length === 2) break + if (events.length === 3) break } ps.kill() assert(events[1].timestamp) delete events[1].timestamp assert(events[1].id) delete events[1].id + assert(events[2].timestamp) + delete events[2].timestamp + assert(events[2].id) + delete events[2].id + events.sort((a, b) => { + const left = `${a.type}:${a.module ?? ''}:${a.message}` + const right = `${a.type}:${a.module ?? ''}:${a.message}` + return left > right ? 1 : left < right ? -1 : 0 + }) assert.deepStrictEqual(events, [ { type: 'jobs-completed', total: 0 }, + { + type: 'activity:info', + module: 'Runtime', + message: 'Module Runtime started.' + }, { type: 'activity:info', module: 'Saturn', diff --git a/test/storage.js b/test/storage.js index f268ef8f..66874ed9 100644 --- a/test/storage.js +++ b/test/storage.js @@ -22,6 +22,11 @@ describe('Storage', async () => { STATE_ROOT, 'logs', 'modules', 'saturn-L2-node.log' ) ) + await fs.stat( + join( + STATE_ROOT, 'logs', 'modules', 'runtime.log' + ) + ) break } catch {} } From 7341f74c72cf14268e34f8c9264ea18529d316f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 26 Apr 2023 11:34:52 +0200 Subject: [PATCH 10/25] ci: execute Docker image and test activity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- .github/workflows/docker.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 1d653f8b..da1c14c4 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -36,6 +36,7 @@ jobs: id: package-version - name: Build and optionally push Docker image + id: docker_build uses: docker/build-push-action@v4 with: context: . @@ -46,3 +47,19 @@ jobs: platforms: linux/amd64,linux/arm64 cache-from: type=registry,ref=ghcr.io/filecoin-station/core cache-to: type=inline + + - name: Start Station Core container + run: | + docker run \ + --name station \ + --detach \ + --env FIL_WALLET_ADDRESS=f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za \ + ${{ steps.docker_build.outputs.imageid }} + + - name: Verify container activity + run: | + LOGS=$(docker exec station bin/station.js activity) + echo $LOGS + echo $LOGS | grep "Saturn module started" + echo $LOGS | grep "Module Runtime started" + From e9504fc8cf78847887a195a0c588f5915f8b7545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 26 Apr 2023 11:38:06 +0200 Subject: [PATCH 11/25] fixup! fix failing tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- test/station.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/station.js b/test/station.js index a0c86f11..4b92bacb 100644 --- a/test/station.js +++ b/test/station.js @@ -24,6 +24,7 @@ describe('Station', () => { messages.push(line.toString().trim()) if (messages.length === 2) break } + messages.sort() assert.match( messages[0], @@ -80,7 +81,7 @@ describe('Station', () => { delete events[2].id events.sort((a, b) => { const left = `${a.type}:${a.module ?? ''}:${a.message}` - const right = `${a.type}:${a.module ?? ''}:${a.message}` + const right = `${b.type}:${b.module ?? ''}:${b.message}` return left > right ? 1 : left < right ? -1 : 0 }) assert.deepStrictEqual(events, [ From 9821d35a414e024781fa11fb348a1c570e582f33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 26 Apr 2023 11:44:25 +0200 Subject: [PATCH 12/25] fixup! docker CI workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- .github/workflows/docker.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index da1c14c4..202b0dfe 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -54,7 +54,9 @@ jobs: --name station \ --detach \ --env FIL_WALLET_ADDRESS=f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za \ - ${{ steps.docker_build.outputs.imageid }} + $IMAGEID + env: + IMAGEID: ${{ steps.docker_build.outputs.imageid }} - name: Verify container activity run: | From 11a56e706756d008cd1aea16a334ab973b254467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 26 Apr 2023 11:51:06 +0200 Subject: [PATCH 13/25] troubleshoot docker CI not running MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- .github/workflows/docker.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 202b0dfe..411bb411 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -48,20 +48,20 @@ jobs: cache-from: type=registry,ref=ghcr.io/filecoin-station/core cache-to: type=inline - - name: Start Station Core container - run: | - docker run \ - --name station \ - --detach \ - --env FIL_WALLET_ADDRESS=f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za \ - $IMAGEID - env: - IMAGEID: ${{ steps.docker_build.outputs.imageid }} + # - name: Start Station Core container + # run: | + # docker run \ + # --name station \ + # --detach \ + # --env FIL_WALLET_ADDRESS=f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za \ + # $IMAGEID + # env: + # IMAGEID: ${{ steps.docker_build.outputs.imageid }} - - name: Verify container activity - run: | - LOGS=$(docker exec station bin/station.js activity) - echo $LOGS - echo $LOGS | grep "Saturn module started" - echo $LOGS | grep "Module Runtime started" + # - name: Verify container activity + # run: | + # LOGS=$(docker exec station bin/station.js activity) + # echo $LOGS + # echo $LOGS | grep "Saturn module started" + # echo $LOGS | grep "Module Runtime started" From d35197c1bb49aaf610c73d822e05402430af2e88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 26 Apr 2023 11:54:23 +0200 Subject: [PATCH 14/25] enable Docker workflow for all pushes --- .github/workflows/docker.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 411bb411..3f5cbc88 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -1,8 +1,5 @@ name: Docker build -on: - push: - tags: ["*"] - branches: ["*"] +on: [push] env: REGISTRY: ghcr.io From 4de0921ea25e955c24d80bfe8084e96b2cd2fc76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 26 Apr 2023 11:54:45 +0200 Subject: [PATCH 15/25] Revert "troubleshoot docker CI not running" This reverts commit 11a56e706756d008cd1aea16a334ab973b254467. --- .github/workflows/docker.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 3f5cbc88..afd4ec29 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -45,20 +45,20 @@ jobs: cache-from: type=registry,ref=ghcr.io/filecoin-station/core cache-to: type=inline - # - name: Start Station Core container - # run: | - # docker run \ - # --name station \ - # --detach \ - # --env FIL_WALLET_ADDRESS=f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za \ - # $IMAGEID - # env: - # IMAGEID: ${{ steps.docker_build.outputs.imageid }} + - name: Start Station Core container + run: | + docker run \ + --name station \ + --detach \ + --env FIL_WALLET_ADDRESS=f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za \ + $IMAGEID + env: + IMAGEID: ${{ steps.docker_build.outputs.imageid }} - # - name: Verify container activity - # run: | - # LOGS=$(docker exec station bin/station.js activity) - # echo $LOGS - # echo $LOGS | grep "Saturn module started" - # echo $LOGS | grep "Module Runtime started" + - name: Verify container activity + run: | + LOGS=$(docker exec station bin/station.js activity) + echo $LOGS + echo $LOGS | grep "Saturn module started" + echo $LOGS | grep "Module Runtime started" From 164dd703c3b9f73ece821db436a99f9a91e394ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 26 Apr 2023 12:13:13 +0200 Subject: [PATCH 16/25] more docker tweaks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- .github/workflows/ci.yml | 40 ++++++++++++++++++++++++++++++++++++ .github/workflows/docker.yml | 19 ----------------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c56b3b93..c1bf2392 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,3 +17,43 @@ jobs: - run: npm run test:lint if: matrix.os != 'windows-latest' - run: npm run test:unit + + test-docker: + runs-on: ubuntu-latest + permissions: + contents: read + env: + REGISTRY: ghcr.io + + steps: + - uses: actions/checkout@v3 + + - uses: docker/login-action@v2 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build Docker image for local use + id: docker_build + run: | + docker build --iidfile imageid . + IMAGEID=$(cat imageid) + echo "imageid=$IMAGEID" >> "$GITHUB_OUTPUT" + + - name: Start Station Core container + run: | + docker run \ + --name station \ + --detach \ + --env FIL_WALLET_ADDRESS=f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za \ + $IMAGEID + env: + IMAGEID: ${{ steps.docker_build.outputs.imageid }} + + - name: Verify container activity + run: | + LOGS=$(docker exec station bin/station.js activity) + echo $LOGS + echo $LOGS | grep "Saturn module started" + echo $LOGS | grep "Module Runtime started" diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index afd4ec29..5121aac6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -33,7 +33,6 @@ jobs: id: package-version - name: Build and optionally push Docker image - id: docker_build uses: docker/build-push-action@v4 with: context: . @@ -44,21 +43,3 @@ jobs: platforms: linux/amd64,linux/arm64 cache-from: type=registry,ref=ghcr.io/filecoin-station/core cache-to: type=inline - - - name: Start Station Core container - run: | - docker run \ - --name station \ - --detach \ - --env FIL_WALLET_ADDRESS=f1abjxfbp274xpdqcpuaykwkfb43omjotacm2p3za \ - $IMAGEID - env: - IMAGEID: ${{ steps.docker_build.outputs.imageid }} - - - name: Verify container activity - run: | - LOGS=$(docker exec station bin/station.js activity) - echo $LOGS - echo $LOGS | grep "Saturn module started" - echo $LOGS | grep "Module Runtime started" - From 61e049e90da2b8ae2a635225731ee1714b09d6a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 2 May 2023 18:45:54 +0200 Subject: [PATCH 17/25] feat: switch base Docker image to full `node:18` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We cannot use `node:18-alpine` because Zinnia does not support that yet. I tried to use `node:18-slim`, but Saturn L2 was not able to start in that system. The Node.js project recommends to use `node:18`, so we should be fine. See https://github.com/nodejs/docker-node#image-variants Signed-off-by: Miroslav Bajtoš --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 972075e2..148e685a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:18-alpine +FROM node:18 LABEL org.opencontainers.image.source https://github.com/filecoin-station/core USER node WORKDIR /usr/src/app From bef48a8792af88725f3d08bf914ad1eadb4d5659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 2 May 2023 18:51:17 +0200 Subject: [PATCH 18/25] fixup! standard coding style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- commands/station.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/station.js b/commands/station.js index c345c328..8ba29fa3 100644 --- a/commands/station.js +++ b/commands/station.js @@ -47,7 +47,7 @@ export const station = async ({ core, json, experimental }) => { logStream: core.logs.createWriteStream( join(core.paths.moduleLogs, 'runtime.log') ) - }), + }) ] if (experimental) { From a3bd223a6c55d70968ca6972fe858d3dcef5103a Mon Sep 17 00:00:00 2001 From: Julian Gruber Date: Wed, 3 May 2023 09:56:09 +0200 Subject: [PATCH 19/25] fix zip assets on windows --- lib/modules.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/modules.js b/lib/modules.js index 4378508f..8a1607e9 100644 --- a/lib/modules.js +++ b/lib/modules.js @@ -21,10 +21,14 @@ export const getBinaryModuleExecutable = ({ return join( moduleBinaries, module, - `${executable}${os.platform() === 'win32' ? '.exe' : ''}` + getExecutableFileName(executable) ) } +const getExecutableFileName = executable => { + return `${executable}${os.platform() === 'win32' ? '.exe' : ''}` +} + export const installBinaryModule = async ({ module, repo, @@ -79,8 +83,9 @@ export const installBinaryModule = async ({ const [entry] = /** @type {[UnzipStreamEntry]} */ (await once(parser, 'entry')) - if (entry.path === executable) { - const outPath = join(moduleBinaries, module, executable) + const executableFileName = getExecutableFileName(executable) + if (entry.path === executableFileName) { + const outPath = join(moduleBinaries, module, executableFileName) await pipeline(entry, createWriteStream(outPath)) await chmod(outPath, 0o755) return From f85c4a64ec03666a788bf1386aadabd0ade269d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 3 May 2023 10:19:36 +0200 Subject: [PATCH 20/25] fixup! remove github from zinnia module repo name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- lib/modules.js | 2 +- lib/zinnia.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/modules.js b/lib/modules.js index 8a1607e9..7b3ef05f 100644 --- a/lib/modules.js +++ b/lib/modules.js @@ -104,7 +104,7 @@ export async function downloadSourceFiles ({ module, repo, distTag }) { console.log(`[${module}] ⇣ downloading source files`) - const url = `https://${repo}/archive/refs/tags/${distTag}.tar.gz` + const url = `https://github.com/${repo}/archive/refs/tags/${distTag}.tar.gz` const res = await fetch(url, { headers: { ...(authorization ? { authorization } : {}) diff --git a/lib/zinnia.js b/lib/zinnia.js index fc3a79e0..278c8004 100644 --- a/lib/zinnia.js +++ b/lib/zinnia.js @@ -8,7 +8,7 @@ const ZINNIA_DIST_TAG = 'v0.7.0' const ZINNIA_MODULES = [ { module: 'peer-checker', - repo: 'github.com/filecoin-station/mod-peer-checker', + repo: 'filecoin-station/mod-peer-checker', distTag: 'v1.0.0' } ] From 9f41802f4de10d730cc86e0c53e7765398059965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 3 May 2023 17:08:07 +0200 Subject: [PATCH 21/25] bump zinnia to 0.8.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- lib/zinnia.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/zinnia.js b/lib/zinnia.js index 278c8004..477291c7 100644 --- a/lib/zinnia.js +++ b/lib/zinnia.js @@ -4,7 +4,7 @@ import * as Sentry from '@sentry/node' import { installBinaryModule, downloadSourceFiles, getBinaryModuleExecutable } from './modules.js' import { moduleBinaries } from './paths.js' -const ZINNIA_DIST_TAG = 'v0.7.0' +const ZINNIA_DIST_TAG = 'v0.8.0' const ZINNIA_MODULES = [ { module: 'peer-checker', From f45ccb845b550275df8c548667da10dc8414cbd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 3 May 2023 17:21:28 +0200 Subject: [PATCH 22/25] rename Module Runtime to Zinnia MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- .github/workflows/ci.yml | 2 +- bin/station.js | 2 +- commands/station.js | 10 +++++----- lib/zinnia.js | 22 +++++++++++----------- test/station.js | 6 +++--- test/storage.js | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f49660ea..81e5c12d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,4 +95,4 @@ jobs: run: docker exec station bin/station.js activity | grep "Saturn module started" - name: Check | Zinnia started - run: docker exec station bin/station.js activity | grep "Module Runtime started" + run: docker exec station bin/station.js activity | grep "Zinnia started" diff --git a/bin/station.js b/bin/station.js index 6fdde058..d1a37660 100755 --- a/bin/station.js +++ b/bin/station.js @@ -21,7 +21,7 @@ Sentry.init({ const core = new Core(getDefaultRootDirs()) const modules = [ - 'runtime', + 'zinnia', 'saturn-L2-node', 'bacalhau' ] diff --git a/commands/station.js b/commands/station.js index 8ba29fa3..1efb476c 100644 --- a/commands/station.js +++ b/commands/station.js @@ -40,12 +40,12 @@ export const station = async ({ core, json, experimental }) => { }), zinniaRuntime.start({ FIL_WALLET_ADDRESS, - STATE_ROOT: join(core.paths.moduleState, 'runtime'), - CACHE_ROOT: join(core.paths.moduleCache, 'runtime'), - metricsStream: await core.metrics.createWriteStream('runtime'), - activityStream: core.activity.createWriteStream('Runtime'), + STATE_ROOT: join(core.paths.moduleState, 'zinnia'), + CACHE_ROOT: join(core.paths.moduleCache, 'zinnia'), + metricsStream: await core.metrics.createWriteStream('zinnia'), + activityStream: core.activity.createWriteStream('Zinnia'), logStream: core.logs.createWriteStream( - join(core.paths.moduleLogs, 'runtime.log') + join(core.paths.moduleLogs, 'zinnia.log') ) }) ] diff --git a/lib/zinnia.js b/lib/zinnia.js index 477291c7..1960d3b8 100644 --- a/lib/zinnia.js +++ b/lib/zinnia.js @@ -16,7 +16,7 @@ const ZINNIA_MODULES = [ export async function install () { await Promise.all([ installBinaryModule({ - module: 'runtime', + module: 'zinnia', repo: 'filecoin-station/zinnia', distTag: ZINNIA_DIST_TAG, executable: 'zinniad', @@ -41,9 +41,9 @@ async function start ({ activityStream, logStream }) { - logStream.write('Starting Zinnia runtime') + logStream.write('Starting Zinnia') - const zinniadExe = getBinaryModuleExecutable({ module: 'runtime', executable: 'zinniad' }) + const zinniadExe = getBinaryModuleExecutable({ module: 'zinnia', executable: 'zinniad' }) const modules = [ // all paths are relative to `moduleBinaries` 'peer-checker/peer-checker.js' @@ -78,15 +78,15 @@ async function start ({ }) childProcess.on('close', code => { - logStream.write(`Zinnia Runtime closed all stdio with code ${code ?? ''}`) + logStream.write(`Zinnia closed all stdio with code ${code ?? ''}`) childProcess.stderr.removeAllListeners() childProcess.stdout.removeAllListeners() - Sentry.captureException('Zinnia runtime exited') + Sentry.captureException('Zinnia exited') }) childProcess.on('exit', (code, signal) => { const reason = signal ? `via signal ${signal}` : `with code: ${code}` - const msg = `Zinnia Runtime exited ${reason}` + const msg = `Zinnia exited ${reason}` logStream.write(msg) activityStream.write({ type: 'info', message: msg }) }) @@ -98,7 +98,7 @@ async function start ({ ]) } catch (err) { const errorMsg = err instanceof Error ? err.message : '' + err - const message = `Cannot start Zinnia Runtime: ${errorMsg}` + const message = `Cannot start Zinnia: ${errorMsg}` logStream.write(message) activityStream.write({ type: 'error', message }) } @@ -115,16 +115,16 @@ function handleEvents ({ activityStream, metricsStream }, text) { case 'activity:info': activityStream.write({ type: 'info', - message: event.message, - source: event.module ?? 'Runtime' + message: event.message.replace(/Module Runtime/, 'Zinnia'), + source: event.module ?? 'Zinnia' }) break case 'activity:error': activityStream.write({ type: 'error', - message: event.message, - source: event.module ?? 'Runtime' + message: event.message.replace(/Module Runtime/, 'Zinnia'), + source: event.module ?? 'Zinnia' }) break diff --git a/test/station.js b/test/station.js index acd0ccf5..f92a16ec 100644 --- a/test/station.js +++ b/test/station.js @@ -15,7 +15,7 @@ describe('Station', () => { ) await Promise.all([ streamMatch(ps.stdout, 'totalJobsCompleted'), - streamMatch(ps.stdout, 'Module Runtime started'), + streamMatch(ps.stdout, 'Zinnia started'), streamMatch(ps.stdout, 'Saturn Node will try to connect') ]) ps.kill() @@ -43,7 +43,7 @@ describe('Station', () => { ) await Promise.all([ streamMatch(ps.stdout, 'totalJobsCompleted'), - streamMatch(ps.stdout, 'Module Runtime started'), + streamMatch(ps.stdout, 'Zinnia started'), streamMatch(ps.stdout, 'Saturn Node will try to connect') ]) ps.kill() @@ -59,7 +59,7 @@ describe('Station', () => { await Promise.all([ streamMatch(ps.stdout, 'jobs-completed'), - streamMatch(ps.stdout, /activity:info.*(Module Runtime started)/), + streamMatch(ps.stdout, /activity:info.*(Zinnia started)/), streamMatch(ps.stdout, /activity:info.*(Saturn Node will try to connect)/) ]) diff --git a/test/storage.js b/test/storage.js index 66874ed9..867b209b 100644 --- a/test/storage.js +++ b/test/storage.js @@ -24,7 +24,7 @@ describe('Storage', async () => { ) await fs.stat( join( - STATE_ROOT, 'logs', 'modules', 'runtime.log' + STATE_ROOT, 'logs', 'modules', 'zinnia.log' ) ) break From d629dc4a8d232553cec8927ad3467d1e954a63d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Thu, 4 May 2023 08:53:46 +0200 Subject: [PATCH 23/25] move mocha config to config file and add --exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- .mocharc.yaml | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .mocharc.yaml diff --git a/.mocharc.yaml b/.mocharc.yaml new file mode 100644 index 00000000..9cdc99ee --- /dev/null +++ b/.mocharc.yaml @@ -0,0 +1,2 @@ +timeout: 15000 +exit: true diff --git a/package.json b/package.json index d5fc2e7a..0f213d2f 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "start": "node ./bin/station.js", "test": "npm run build && npm run test:lint && npm run test:unit", "test:lint": "prettier --check . && standard", - "test:unit": "mocha --timeout 15000", + "test:unit": "mocha", "version": "npm run build && node ./scripts/version.js", "postinstall": "node ./scripts/post-install.js", "postpublish": "node ./scripts/post-publish.js", From b587b2629a4b1280c7bb28a29c7942dc91e577f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Thu, 4 May 2023 09:10:40 +0200 Subject: [PATCH 24/25] make test/station easier to troubleshoot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- package-lock.json | 1 + package.json | 1 + test/station.js | 71 +++++++++++++++++++++++++++-------------------- 3 files changed, 43 insertions(+), 30 deletions(-) diff --git a/package-lock.json b/package-lock.json index 77457fa6..c17dd1bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "station": "bin/station.js" }, "devDependencies": { + "get-stream": "^6.0.1", "mocha": "^10.2.0", "np": "^7.6.3", "prettier": "^2.8.4", diff --git a/package.json b/package.json index 0f213d2f..ca0325ed 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ ] }, "devDependencies": { + "get-stream": "^6.0.1", "mocha": "^10.2.0", "np": "^7.6.3", "prettier": "^2.8.4", diff --git a/test/station.js b/test/station.js index f92a16ec..62983582 100644 --- a/test/station.js +++ b/test/station.js @@ -1,61 +1,40 @@ +import assert from 'node:assert' import { execa } from 'execa' import { station, FIL_WALLET_ADDRESS } from './util.js' import { tmpdir } from 'node:os' import { randomUUID } from 'node:crypto' import { join } from 'node:path' import streamMatch from 'stream-match' +import getStream from 'get-stream' describe('Station', () => { it('runs Saturn and Zinnia', async () => { - const CACHE_ROOT = join(tmpdir(), randomUUID()) - const STATE_ROOT = join(tmpdir(), randomUUID()) - const ps = execa( - station, - { env: { CACHE_ROOT, STATE_ROOT, FIL_WALLET_ADDRESS } } - ) + const ps = startStation() await Promise.all([ streamMatch(ps.stdout, 'totalJobsCompleted'), streamMatch(ps.stdout, 'Zinnia started'), streamMatch(ps.stdout, 'Saturn Node will try to connect') ]) - ps.kill() + stopStation() }) it('runs experimental modules', () => { it('runs Bacalhau', async () => { - const CACHE_ROOT = join(tmpdir(), randomUUID()) - const STATE_ROOT = join(tmpdir(), randomUUID()) - const ps = execa( - station, - ['--experimental'], - { env: { CACHE_ROOT, STATE_ROOT, FIL_WALLET_ADDRESS } } - ) + const ps = startStation(['--experimental']) await streamMatch(ps.stdout, 'Bacalhau module started.') - ps.kill() + stopStation() }) }) it('outputs events', async () => { - const CACHE_ROOT = join(tmpdir(), randomUUID()) - const STATE_ROOT = join(tmpdir(), randomUUID()) - const ps = execa( - station, - [], - { env: { CACHE_ROOT, STATE_ROOT, FIL_WALLET_ADDRESS } } - ) + const ps = startStation() await Promise.all([ streamMatch(ps.stdout, 'totalJobsCompleted'), streamMatch(ps.stdout, 'Zinnia started'), streamMatch(ps.stdout, 'Saturn Node will try to connect') ]) - ps.kill() + stopStation() }) it('outputs events json', async () => { - const CACHE_ROOT = join(tmpdir(), randomUUID()) - const STATE_ROOT = join(tmpdir(), randomUUID()) - const ps = execa( - station, - ['--json'], - { env: { CACHE_ROOT, STATE_ROOT, FIL_WALLET_ADDRESS } } - ) + const ps = startStation(['--json']) await Promise.all([ streamMatch(ps.stdout, 'jobs-completed'), @@ -63,6 +42,38 @@ describe('Station', () => { streamMatch(ps.stdout, /activity:info.*(Saturn Node will try to connect)/) ]) + stopStation() + }) + + let ps, stdout, stderr + function startStation (cliArgs = []) { + assert(!ps, 'Station is already running') + + const CACHE_ROOT = join(tmpdir(), randomUUID()) + const STATE_ROOT = join(tmpdir(), randomUUID()) + ps = execa( + station, + cliArgs, + { env: { CACHE_ROOT, STATE_ROOT, FIL_WALLET_ADDRESS } } + ) + stdout = getStream(ps.stdout) + stderr = getStream(ps.stderr) + return ps + } + + function stopStation () { ps.kill() + ps = undefined + } + + afterEach(async () => { + if (!ps) return + // The test failed and did not stop the Station process + // Let's stop the process and print stdout & stderr for troubleshooting + stopStation() + + console.log('== STATION STDOUT ==\n%s', await stdout) + console.log('== STATION STDERR ==\n%s', await stderr) + console.log('== END ==') }) }) From 77b2369eb2af572d814f3048b950ebe1af848973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Thu, 4 May 2023 09:22:03 +0200 Subject: [PATCH 25/25] fix expected Saturn messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- test/station.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/station.js b/test/station.js index 62983582..f43678f3 100644 --- a/test/station.js +++ b/test/station.js @@ -13,7 +13,7 @@ describe('Station', () => { await Promise.all([ streamMatch(ps.stdout, 'totalJobsCompleted'), streamMatch(ps.stdout, 'Zinnia started'), - streamMatch(ps.stdout, 'Saturn Node will try to connect') + streamMatch(ps.stdout, 'Saturn module started') ]) stopStation() }) @@ -29,7 +29,7 @@ describe('Station', () => { await Promise.all([ streamMatch(ps.stdout, 'totalJobsCompleted'), streamMatch(ps.stdout, 'Zinnia started'), - streamMatch(ps.stdout, 'Saturn Node will try to connect') + streamMatch(ps.stdout, 'Saturn module started') ]) stopStation() }) @@ -39,7 +39,7 @@ describe('Station', () => { await Promise.all([ streamMatch(ps.stdout, 'jobs-completed'), streamMatch(ps.stdout, /activity:info.*(Zinnia started)/), - streamMatch(ps.stdout, /activity:info.*(Saturn Node will try to connect)/) + streamMatch(ps.stdout, /activity:info.*(Saturn module started)/) ]) stopStation()