diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index c74f9964115..c0ab3e57d25 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -10,6 +10,9 @@ jobs: # It should be kept in sync with https://agoric.com/documentation/getting-started/ getting-started: runs-on: ubuntu-latest + strategy: + matrix: + cli: [ link-cli, local-npm ] steps: - uses: actions/checkout@v2 @@ -51,12 +54,46 @@ jobs: # cross-package symlinks - run: yarn install - run: yarn build - - run: yarn link-cli ~/bin/agoric + + - name: Link Agoric CLI from SDK + if: ${{ matrix.cli == 'link-cli' }} + run: | + yarn link-cli "$HOME/bin/agoric" + echo "AGORIC_CMD=[\"$HOME/bin/agoric\"]" >> $GITHUB_ENV + + - name: Start local NPM registry + if: ${{ matrix.cli == 'local-npm' }} + run: | + tmp_registry_log=`mktemp` + nohup npx verdaccio@^5.4.0 &>$tmp_registry_log & + # Wait for `verdaccio` to boot + grep -q 'http address' <(tail -f $tmp_registry_log) + + # Set registry to local registry + npm set registry http://localhost:4873 + yarn config set registry http://localhost:4873 + + # Login so we can publish packages + npx npm-cli-login@^1.0.0 -u user -p password -e user@example.com \ + -r http://localhost:4873 --quotes + + npm whoami + + yarn lerna publish --conventional-prerelease --canary --exact \ + --dist-tag=blah --preid=dev-$(git rev-parse --short=7 HEAD) \ + --no-push --no-verify-access --yes + + yarn global add agoric@blah > $GITHUB_ENV + echo 'AGORIC_START_OPTIONS=["--rebuild"]' >> $GITHUB_ENV + echo 'AGORIC_CMD=["agoric"]' >> $GITHUB_ENV - name: run agoric-cli integration-test working-directory: ./packages/agoric-cli - run: PATH="$PATH:$HOME/bin" yarn integration-test + run: yarn integration-test env: AGORIC_INIT_OPTIONS: '["--dapp-branch=${{steps.get-branch.outputs.result}}"]' # Try to avoid hitting a pessimal Actions output rate-limitation. - SOLO_MAX_DEBUG_LENGTH: '1024' \ No newline at end of file + SOLO_MAX_DEBUG_LENGTH: '1024' diff --git a/packages/agoric-cli/package.json b/packages/agoric-cli/package.json index 66b6e6a804f..bdca38f570b 100644 --- a/packages/agoric-cli/package.json +++ b/packages/agoric-cli/package.json @@ -4,13 +4,13 @@ "description": "Manage the Agoric Javascript smart contract platform", "type": "module", "main": "src/main.js", - "bin": "bin/agoric", + "bin": "src/entrypoint.js", "files": [ - "lib", + "src", "exported.js" ], "scripts": { - "build": "exit 0", + "build": "./scripts/get-sdk-package-names.js > src/sdk-package-names.js", "test": "ava", "test:c8": "c8 $C8_OPTIONS ava --config=ava-nesm.config.js", "test:xs": "exit 0", diff --git a/packages/agoric-cli/scripts/get-sdk-package-names.js b/packages/agoric-cli/scripts/get-sdk-package-names.js new file mode 100755 index 00000000000..df4ba4fb2a3 --- /dev/null +++ b/packages/agoric-cli/scripts/get-sdk-package-names.js @@ -0,0 +1,34 @@ +#! /usr/bin/env node +/* global process, Buffer */ +import { spawn } from 'child_process'; +import { basename } from 'path'; + +const ps = spawn('yarn', ['workspaces', '--silent', 'info'], { + stdio: ['ignore', 'pipe', 'inherit'], +}); + +// Get Buffers of output. +const chunks = []; +ps.stdout.on('data', data => chunks.push(data)); + +// Wait for the process to exit. +ps.on('close', code => { + if (code !== 0) { + throw Error(`yarn info exited with code ${code}`); + } + + // Get the output. + const json = Buffer.concat(chunks).toString('utf8'); + // process.stderr.write(json); + + // Write the module. + const workspaces = Object.keys(JSON.parse(json)).sort(); + process.stdout.write(`\ +// DO NOT EDIT - automatically generated by ${basename( + new URL(import.meta.url).pathname, + )} +/* eslint-disable comma-dangle,quotes */ +// prettier-ignore +export default ${JSON.stringify(workspaces, null, 2)}; +`); +}); diff --git a/packages/agoric-cli/src/helpers.js b/packages/agoric-cli/src/helpers.js index 501e633d07b..3e281cb9697 100644 --- a/packages/agoric-cli/src/helpers.js +++ b/packages/agoric-cli/src/helpers.js @@ -3,13 +3,21 @@ /** @typedef {import('child_process').ChildProcess} ChildProcess */ -export const getSDKBinaries = () => { +export const getSDKBinaries = ({ + jsPfx = '../..', + goPfx = `${jsPfx}/../golang`, +} = {}) => { const myUrl = import.meta.url; + const cosmosBuild = ['make', '-C', `${goPfx}/cosmos`, 'all']; + const xsnap = new URL(`${jsPfx}/xsnap`, myUrl).pathname; return { - agSolo: new URL('../../solo/src/entrypoint.js', myUrl).pathname, - cosmosChain: new URL('../../cosmic-swingset/bin/ag-chain-cosmos', myUrl) + agSolo: new URL(`${jsPfx}/solo/src/entrypoint.js`, myUrl).pathname, + agSoloBuild: ['yarn', '--cwd', xsnap, `build:from-env`], + cosmosChain: new URL(`${jsPfx}/cosmic-swingset/bin/ag-chain-cosmos`, myUrl) .pathname, - cosmosHelper: new URL('../../../golang/cosmos/build/agd', myUrl).pathname, + cosmosChainBuild: cosmosBuild, + cosmosClientBuild: cosmosBuild, + cosmosHelper: new URL(`${goPfx}/cosmos/build/agd`, myUrl).pathname, }; }; diff --git a/packages/agoric-cli/src/install.js b/packages/agoric-cli/src/install.js index 1e4be328a09..7d0b9b80d11 100644 --- a/packages/agoric-cli/src/install.js +++ b/packages/agoric-cli/src/install.js @@ -2,6 +2,12 @@ import path from 'path'; import chalk from 'chalk'; import { makePspawn } from './helpers.js'; +import DEFAULT_SDK_PACKAGE_NAMES from './sdk-package-names.js'; + +const REQUIRED_AGORIC_START_PACKAGES = [ + '@agoric/solo', + '@agoric/cosmic-swingset', +]; const filename = new URL(import.meta.url).pathname; const dirname = path.dirname(filename); @@ -24,7 +30,7 @@ export default async function installMain(progname, rawArgs, powers, opts) { const rimraf = file => pspawn('rm', ['-rf', file]); - async function workspaceDirectories(cwd = '.') { + async function getWorktreePackagePaths(cwd = '.', map = new Map()) { // run `yarn workspaces info` to get the list of directories to // use, instead of a hard-coded list const p = pspawn('yarn', ['workspaces', '--silent', 'info'], { @@ -35,14 +41,17 @@ export default async function installMain(progname, rawArgs, powers, opts) { p.childProcess.stdout.on('data', out => stdout.push(out)); await p; const d = JSON.parse(Buffer.concat(stdout).toString('utf-8')); - const subdirs = Object.values(d).map(v => v.location); - return subdirs; + Object.entries(d).forEach(([name, { location }]) => + map.set(name, path.resolve(cwd, location)), + ); + return map; } let subdirs; const workTrees = ['.']; let sdkWorktree; - const versions = new Map(); + /** @type {Map} */ + const sdkPackageToPath = new Map(); const linkFolder = path.resolve(`_agstate/yarn-links`); const linkFlags = []; if (opts.sdk) { @@ -95,7 +104,7 @@ export default async function installMain(progname, rawArgs, powers, opts) { const prunedDeps = { ...updatedDeps }; prunedPackageDescriptor[depSection] = prunedDeps; for (const pkg of Object.keys(updatedDeps)) { - if (versions.has(pkg)) { + if (sdkPackageToPath.has(pkg)) { if (updatedDeps[pkg] === forceVersion) { // We need to remove the old package and `yarn install` to // prune the old dependencies both from disk and also the @@ -109,6 +118,18 @@ export default async function installMain(progname, rawArgs, powers, opts) { } } } + // Ensure the top-level package has the `agoric start` dependencies. + if (subdir === '.') { + for (const pkg of REQUIRED_AGORIC_START_PACKAGES) { + const updatedDevDeps = + updatedPackageDescriptor.devDependencies || {}; + if (!updatedDevDeps[pkg]) { + updatedDevDeps[pkg] = forceVersion; + updatedPackageDescriptor.devDependencies = updatedDevDeps; + } + } + } + // Ensure we update the package.json before exiting. const updatePackageJson = async () => { // Don't update on exit anymore. @@ -187,13 +208,19 @@ export default async function installMain(progname, rawArgs, powers, opts) { throw err; }); if (dappPackageJSON.useWorkspaces) { - const workdirs = await workspaceDirectories(); + const workdirs = await getWorktreePackagePaths().then(pp => [ + ...pp.values(), + ]); sdkWorktree = workdirs.find(subd => subd === 'agoric-sdk'); subdirs = ['.', ...workdirs.filter(subd => subd !== 'agoric-sdk')]; // Add 'ui' directory by default, if it exists. if (!subdirs.find(subd => subd === 'ui')) { - if (await fs.stat(`ui/package.json`).catch(_ => false)) { + const uiPackageJSON = await fs.readFile(`ui/package.json`, 'utf-8').then( + data => JSON.parse(data), + _err => ({}), + ); + if (uiPackageJSON.name) { subdirs.push('ui'); workTrees.push('ui'); } @@ -212,34 +239,10 @@ export default async function installMain(progname, rawArgs, powers, opts) { subdirs = existingSubdirs.filter(subd => subd); } - /** @type {Map} */ - const packages = new Map(); - - const sdkRoot = path.resolve(dirname, `../../..`); - const sdkDirs = await workspaceDirectories(sdkRoot); - await Promise.all( - sdkDirs.map(async location => { - const dir = `${sdkRoot}/${location}`; - const packageJSON = await fs - .readFile(`${dir}/package.json`, 'utf-8') - .catch(err => log('error reading', `${dir}/package.json`, err)); - if (!packageJSON) { - return; - } - - const pj = JSON.parse(packageJSON); - if (pj.private) { - log('not linking private package', pj.name); - return; - } - - // Save our metadata. - packages.set(dir, pj.name); - versions.set(pj.name, pj.version); - }), - ); - if (opts.sdk) { + const sdkRoot = path.resolve(dirname, `../../..`); + await getWorktreePackagePaths(sdkRoot, sdkPackageToPath); + // We remove all the links to prevent `yarn install` below from corrupting // them. log('removing', linkFolder); @@ -261,12 +264,14 @@ export default async function installMain(progname, rawArgs, powers, opts) { // This is needed to prevent yarn errors when installing new versions of // linked modules (like `@agoric/zoe`). await Promise.all( - [...packages.values()].map(async pjName => + [...sdkPackageToPath.keys()].map(async pjName => fs.unlink(`${nm}/${pjName}`).catch(_ => {}), ), ); }), ); + } else { + DEFAULT_SDK_PACKAGE_NAMES.forEach(name => sdkPackageToPath.set(name, null)); } if (forceSdkVersion !== undefined) { @@ -283,7 +288,7 @@ export default async function installMain(progname, rawArgs, powers, opts) { // Create symlinks to the SDK packages. await Promise.all( - [...packages.entries()].map(async ([dir, pjName]) => { + [...sdkPackageToPath.entries()].map(async ([pjName, dir]) => { const SUBOPTIMAL = false; if (SUBOPTIMAL) { // This use of yarn is noisy and slow. @@ -304,7 +309,7 @@ export default async function installMain(progname, rawArgs, powers, opts) { }), ); - const sdkPackages = [...packages.values()].sort(); + const sdkPackages = [...sdkPackageToPath.keys()].sort(); for (const subdir of subdirs) { // eslint-disable-next-line no-await-in-loop const exists = await fs.stat(`${subdir}/package.json`).catch(_ => false); diff --git a/packages/agoric-cli/src/main.js b/packages/agoric-cli/src/main.js index df92019ff58..9dca81b920b 100644 --- a/packages/agoric-cli/src/main.js +++ b/packages/agoric-cli/src/main.js @@ -52,11 +52,7 @@ const main = async (progname, rawArgs, powers) => { program .option('--sdk', 'use the Agoric SDK containing this program') .option('--no-sdk', 'do not use the Agoric SDK containing this program') - .option( - '--docker-tag ', - 'image tag to use for Docker containers', - 'latest', - ) + .option('--docker-tag ', 'image tag to use for Docker containers') .option( '-v, --verbose', 'verbosity that can be increased', @@ -201,6 +197,7 @@ const main = async (progname, rawArgs, powers) => { .option('--reset', 'clear all VM state before starting') .option('--no-restart', 'do not actually start the VM') .option('--pull', 'for Docker-based VM, pull the image before running') + .option('--rebuild', 'rebuild VM dependencies before running') .option( '--delay [seconds]', 'delay for simulated chain to process messages', diff --git a/packages/agoric-cli/src/sdk-package-names.js b/packages/agoric-cli/src/sdk-package-names.js new file mode 100644 index 00000000000..dbcc75fe03c --- /dev/null +++ b/packages/agoric-cli/src/sdk-package-names.js @@ -0,0 +1,47 @@ +// DO NOT EDIT - automatically generated by get-sdk-package-names.js +/* eslint-disable comma-dangle,quotes */ +// prettier-ignore +export default [ + "@agoric/access-token", + "@agoric/assert", + "@agoric/bundle-source", + "@agoric/captp", + "@agoric/cosmic-swingset", + "@agoric/cosmos", + "@agoric/deploy-script-support", + "@agoric/deployment", + "@agoric/ertp", + "@agoric/eslint-config", + "@agoric/eventual-send", + "@agoric/far", + "@agoric/governance", + "@agoric/import-bundle", + "@agoric/import-manager", + "@agoric/install-ses", + "@agoric/lockdown", + "@agoric/marshal", + "@agoric/notifier", + "@agoric/pegasus", + "@agoric/promise-kit", + "@agoric/run-protocol", + "@agoric/same-structure", + "@agoric/sharing-service", + "@agoric/solo", + "@agoric/sparse-ints", + "@agoric/spawner", + "@agoric/stat-logger", + "@agoric/store", + "@agoric/swing-store", + "@agoric/swingset-runner", + "@agoric/swingset-vat", + "@agoric/ui-components", + "@agoric/vats", + "@agoric/wallet", + "@agoric/wallet-backend", + "@agoric/wallet-connection", + "@agoric/wallet-ui", + "@agoric/web-components", + "@agoric/xsnap", + "@agoric/zoe", + "agoric" +]; diff --git a/packages/agoric-cli/src/start.js b/packages/agoric-cli/src/start.js index 362f7626f30..665b8f2d112 100644 --- a/packages/agoric-cli/src/start.js +++ b/packages/agoric-cli/src/start.js @@ -1,6 +1,7 @@ /* global process setTimeout */ import chalk from 'chalk'; import { createHash } from 'crypto'; +import path from 'path'; import { CENTRAL_DENOM, @@ -60,9 +61,16 @@ export default async function startMain(progname, rawArgs, powers, opts) { nodeDebugEnv.SWINGSET_WORKER_TYPE = 'local'; } + const agServersPrefix = opts.sdk + ? undefined + : path.resolve(`node_modules/@agoric`); + const getBinaries = opts.sdk + ? getSDKBinaries + : () => getSDKBinaries({ goPfx: agServersPrefix, jsPfx: agServersPrefix }); + let keysSpawn; - if (opts.sdk) { - const { cosmosHelper } = getSDKBinaries(); + if (!opts.dockerTag) { + const { cosmosHelper } = getBinaries(); keysSpawn = (args, ...rest) => pspawn(cosmosHelper, [`--home=_agstate/keys`, ...args], ...rest); } else { @@ -129,10 +137,11 @@ export default async function startMain(progname, rawArgs, powers, opts) { }; let agSolo; - if (opts.sdk) { - ({ agSolo } = getSDKBinaries()); - } else { + let agSoloBuild; + if (opts.dockerTag) { agSolo = `ag-solo`; + } else { + ({ agSolo, agSoloBuild } = getBinaries()); } async function startFakeChain(profileName, _startArgs, popts) { @@ -147,16 +156,22 @@ export default async function startMain(progname, rawArgs, powers, opts) { await pspawn('rm', ['-rf', agServer]); } - if (!opts.sdk) { - if ( - !(await exists('node_modules/@agoric/solo')) && - !(await exists('_agstate/agoric-servers/node_modules/@agoric/solo')) - ) { + if (!opts.dockerTag) { + if (!(await exists('node_modules/@agoric/solo'))) { log.error(`you must first run '${progname} install'`); return 1; } } + if (opts.pull || opts.rebuild) { + if (!opts.dockerTag && agSoloBuild) { + const exitStatus = await pspawn(agSoloBuild[0], agSoloBuild.slice(1)); + if (exitStatus) { + return exitStatus; + } + } + } + const fakeGCI = 'sim-chain'; if (!(await exists(agServer))) { log(chalk.yellow(`initializing ${profileName}`)); @@ -200,10 +215,21 @@ export default async function startMain(progname, rawArgs, powers, opts) { return 1; } - if (popts.pull) { - const exitStatus = await pspawn('docker', ['pull', SDK_IMAGE]); - if (exitStatus) { - return exitStatus; + const { cosmosChain, cosmosChainBuild } = getBinaries(); + if (popts.pull || popts.rebuild) { + if (popts.dockerTag) { + const exitStatus = await pspawn('docker', ['pull', SDK_IMAGE]); + if (exitStatus !== 0) { + return exitStatus; + } + } else { + const exitStatus = await pspawn( + cosmosChainBuild[0], + cosmosChainBuild.slice(1), + ); + if (exitStatus !== 0) { + return exitStatus; + } } } @@ -215,8 +241,7 @@ export default async function startMain(progname, rawArgs, powers, opts) { } let chainSpawn; - if (popts.sdk) { - const { cosmosChain } = getSDKBinaries(); + if (!popts.dockerTag) { chainSpawn = (args, spawnOpts = undefined) => { return pspawn(cosmosChain, [...args, `--home=${agServer}`], spawnOpts); }; @@ -294,9 +319,9 @@ export default async function startMain(progname, rawArgs, powers, opts) { return exitStatus; } - const keysHome = opts.sdk - ? `_agstate/keys` - : `/usr/src/dapp/_agstate/keys`; + const keysHome = opts.dockerTag + ? `/usr/src/dapp/_agstate/keys` + : `_agstate/keys`; exitStatus = await chainSpawn([ 'gentx', 'delegate0', @@ -382,7 +407,25 @@ export default async function startMain(progname, rawArgs, powers, opts) { const agServer = `_agstate/agoric-servers/${profileName}-${portNum}`; - if (popts.pull) { + const { cosmosClientBuild } = getBinaries(); + if (popts.pull || popts.rebuild) { + if (popts.dockerTag) { + const exitStatus = await pspawn('docker', ['pull', SDK_IMAGE]); + if (exitStatus !== 0) { + return exitStatus; + } + } else { + const exitStatus = await pspawn( + cosmosClientBuild[0], + cosmosClientBuild.slice(1), + ); + if (exitStatus !== 0) { + return exitStatus; + } + } + } + + if (popts.dockerTag && popts.pull) { const exitStatus = await pspawn('docker', ['pull', SDK_IMAGE]); if (exitStatus) { return exitStatus; @@ -396,7 +439,7 @@ export default async function startMain(progname, rawArgs, powers, opts) { } let soloSpawn; - if (popts.sdk) { + if (!popts.dockerTag) { soloSpawn = (args, spawnOpts = undefined) => pspawn(agSolo, args, spawnOpts); } else { @@ -447,7 +490,7 @@ export default async function startMain(progname, rawArgs, powers, opts) { // Initialise the solo directory and key. if (!(await exists(agServer))) { const initArgs = [`--webport=${portNum}`]; - if (!opts.sdk) { + if (opts.dockerTag) { initArgs.push(`--webhost=0.0.0.0`); } const exitStatus = await soloSpawn( @@ -461,12 +504,12 @@ export default async function startMain(progname, rawArgs, powers, opts) { } const spawnOpts = {}; - if (popts.sdk) { + if (!popts.dockerTag) { spawnOpts.cwd = agServer; } const rpcAddrs = [`localhost:${CHAIN_PORT}`]; - if (!popts.sdk) { + if (popts.dockerTag) { rpcAddrs.push(`host.docker.internal:${CHAIN_PORT}`); } @@ -578,7 +621,7 @@ export default async function startMain(progname, rawArgs, powers, opts) { } async function startTestnetDocker(profileName, startArgs, popts) { - if (popts.pull) { + if (popts.dockerTag && popts.pull) { const exitStatus = await pspawn('docker', ['pull', SOLO_IMAGE]); if (exitStatus) { return exitStatus; @@ -635,7 +678,7 @@ export default async function startMain(progname, rawArgs, powers, opts) { dev: startFakeChain, 'local-chain': startLocalChain, 'local-solo': startLocalSolo, - testnet: opts.sdk ? startTestnetSdk : startTestnetDocker, + testnet: opts.dockerTag ? startTestnetDocker : startTestnetSdk, }; const popts = opts; diff --git a/packages/agoric-cli/tools/getting-started.js b/packages/agoric-cli/tools/getting-started.js index 9bb410d164b..f912da0fb0d 100644 --- a/packages/agoric-cli/tools/getting-started.js +++ b/packages/agoric-cli/tools/getting-started.js @@ -27,7 +27,12 @@ const dirname = new URL('./', import.meta.url).pathname; // cd ui && yarn start export const gettingStartedWorkflowTest = async (t, options = {}) => { - const { init: initOptions = [], testUnsafePlugins = false } = options; + const { + init: initOptions = [], + install: installOptions = [], + start: startOptions = [], + testUnsafePlugins = false, + } = options; // FIXME: Do a search for an unused port or allow specification. const PORT = '7999'; process.env.PORT = PORT; @@ -46,14 +51,19 @@ export const gettingStartedWorkflowTest = async (t, options = {}) => { return ps; } - // Run all main programs with the '--sdk' flag if we are in agoric-sdk. - const extraArgs = fs.existsSync(`${dirname}/../../cosmic-swingset`) - ? ['--sdk'] - : []; - const agoricCli = path.join(dirname, '..', 'bin', 'agoric'); + const defaultAgoricCmd = () => { + // Run all main programs with the '--sdk' flag if we are in agoric-sdk. + const extraArgs = fs.existsSync(`${dirname}/../../cosmic-swingset`) + ? ['--sdk'] + : []; + const localCli = path.join(dirname, '..', 'bin', 'agoric'); + return [localCli, ...extraArgs]; + }; + const { AGORIC_CMD = JSON.stringify(defaultAgoricCmd()) } = process.env; + const agoricCmd = JSON.parse(AGORIC_CMD); function myMain(args, opts = {}) { // console.error('running agoric-cli', ...extraArgs, ...args); - return pspawnStdout(agoricCli, [...extraArgs, ...args], { + return pspawnStdout(agoricCmd[0], [...agoricCmd.slice(1), ...args], { stdio: ['ignore', 'pipe', 'inherit'], env: { ...process.env, DEBUG: 'agoric' }, detached: true, @@ -103,14 +113,23 @@ export const gettingStartedWorkflowTest = async (t, options = {}) => { // ============== // agoric install - t.is(await myMain(['install']), 0, 'install works'); + if (process.env.AGORIC_INSTALL_OPTIONS) { + const opts = JSON.parse(process.env.AGORIC_INSTALL_OPTIONS); + installOptions.push(...opts); + } + t.is(await myMain(['install', ...installOptions]), 0, 'install works'); // ============== // agoric start --reset const startResult = makePromiseKit(); + if (process.env.AGORIC_START_OPTIONS) { + const opts = JSON.parse(process.env.AGORIC_START_OPTIONS); + startOptions.push(...opts); + } + // TODO: Allow this to work even if the port is already used. - const startP = myMain(['start', '--reset']); + const startP = myMain(['start', '--reset', ...startOptions]); finalizers.push(() => pkill(startP.childProcess, 'SIGINT')); let stdoutStr = ''; @@ -123,6 +142,9 @@ export const gettingStartedWorkflowTest = async (t, options = {}) => { } }); } + startP.childProcess.on('close', code => + startResult.reject(Error(`early termination: ${code}`)), + ); const timeout = setTimeout( startResult.reject, diff --git a/packages/install-ses/package.json b/packages/install-ses/package.json index c8dce2d16ce..492c5f785dd 100644 --- a/packages/install-ses/package.json +++ b/packages/install-ses/package.json @@ -15,7 +15,7 @@ "devDependencies": { "ava": "^3.12.1" }, - "peerDependencies": { + "dependencies": { "@agoric/babel-standalone": "^7.14.3", "@agoric/eventual-send": "^0.14.0", "@agoric/lockdown": "^0.1.0" diff --git a/packages/solo/package.json b/packages/solo/package.json index 245e3999b77..281aaf5893b 100644 --- a/packages/solo/package.json +++ b/packages/solo/package.json @@ -42,6 +42,7 @@ "@agoric/vats": "^0.5.1", "@agoric/wallet": "^0.11.7", "@agoric/xsnap": "^0.11.0", + "agoric": "^0.13.21", "anylogger": "^0.21.0", "deterministic-json": "^1.0.5", "esm": "agoric-labs/esm#Agoric-built", diff --git a/packages/solo/src/start.js b/packages/solo/src/start.js index 968ac28843e..c2744172df0 100644 --- a/packages/solo/src/start.js +++ b/packages/solo/src/start.js @@ -45,7 +45,6 @@ let swingSetRunning = false; const fsWrite = promisify(fs.write); const fsClose = promisify(fs.close); const rename = promisify(fs.rename); -const symlink = promisify(fs.symlink); const unlink = promisify(fs.unlink); async function atomicReplaceFile(filename, contents) { @@ -337,7 +336,7 @@ export default async function start(basedir, argv) { // Remove wallet traces. await unlink('html/wallet').catch(_ => {}); - // Symlink the wallet. + // Find the wallet. const pjs = new URL( await importMetaResolve(`${wallet}/package.json`, import.meta.url), ).pathname; @@ -350,9 +349,6 @@ export default async function start(basedir, argv) { const agWallet = path.dirname(pjs); const agWalletHtml = path.resolve(agWallet, htmlBasedir); - symlink(agWalletHtml, 'html/wallet', 'junction').catch(e => { - console.error('Cannot link html/wallet:', e); - }); let hostport; await Promise.all( @@ -394,6 +390,7 @@ export default async function start(basedir, argv) { c.port, c.host, deliverInboundCommand, + agWalletHtml, ); break; default: @@ -418,7 +415,7 @@ export default async function start(basedir, argv) { .join(' '); const agoricCli = new URL( - await importMetaResolve('agoric/bin/agoric', import.meta.url), + await importMetaResolve('agoric/src/entrypoint.js', import.meta.url), ).pathname; // Use the same verbosity as our caller did for us. diff --git a/packages/solo/src/web.js b/packages/solo/src/web.js index 99128a9a166..d3aed3f0304 100644 --- a/packages/solo/src/web.js +++ b/packages/solo/src/web.js @@ -61,7 +61,13 @@ const verifyToken = (actual, expected) => { return !failed; }; -export async function makeHTTPListener(basedir, port, host, rawInboundCommand) { +export async function makeHTTPListener( + basedir, + port, + host, + rawInboundCommand, + walletHtmlDir = undefined, +) { // Enrich the inbound command with some metadata. const inboundCommand = ( body, @@ -122,9 +128,15 @@ export async function makeHTTPListener(basedir, port, host, rawInboundCommand) { app.use(express.static(htmldir)); app.use(express.static(new URL('../public', import.meta.url).pathname)); - app.get('/wallet/*', (_, res) => - res.sendFile(path.resolve('html', 'wallet', 'index.html')), - ); + if (walletHtmlDir) { + // Serve the wallet directory. + app.use('/wallet', express.static(walletHtmlDir)); + + // Default GETs to /wallet/index.html for history routing. + app.get('/wallet/*', (_, res) => + res.sendFile(path.resolve(walletHtmlDir, 'index.html')), + ); + } // The rules for validation: // diff --git a/packages/spawner/package.json b/packages/spawner/package.json index 9cdddf4a804..dd93feb50f6 100644 --- a/packages/spawner/package.json +++ b/packages/spawner/package.json @@ -45,6 +45,7 @@ }, "files": [ "src/", + "bundles/", "NEWS.md" ], "eslintConfig": { diff --git a/packages/wallet/ui/package.json b/packages/wallet/ui/package.json index e6df73edf31..737ed0e369f 100644 --- a/packages/wallet/ui/package.json +++ b/packages/wallet/ui/package.json @@ -111,6 +111,9 @@ ".cache", "node_modules" ], + "files": [ + "build/" + ], "staticFiles": { "staticPath": [ { diff --git a/packages/xsnap/package.json b/packages/xsnap/package.json index d22ddc66e59..d40ce879bea 100644 --- a/packages/xsnap/package.json +++ b/packages/xsnap/package.json @@ -14,7 +14,9 @@ "repl": "node src/xsrepl.js", "build:bundle": "rollup --config rollup.config.js", "build:bin": "node src/build.js", - "build": "yarn build:bin && yarn build:bundle", + "build:env": "node src/build.js --show-env > dist/build-env", + "build:from-env": "{ cat dist/build-env; echo node src/build.js; } | xargs env", + "build": "yarn build:bin && yarn build:bundle && yarn build:env", "clean": "rm -rf xsnap-native/xsnap/build", "lint": "yarn lint:js && yarn lint:types", "lint:js": "eslint 'src/**/*.js' 'lib/**/*.js' api.js", @@ -46,7 +48,7 @@ "LICENSE*", "lib", "api.js", - "makefiles", + "dist", "src" ], "publishConfig": {