Skip to content

Commit

Permalink
Merge pull request #46 from Agoric/ta/import-synthetic-chain
Browse files Browse the repository at this point in the history
  • Loading branch information
turadg authored Jan 6, 2024
2 parents ab2422a + 97fe8e8 commit 003309d
Show file tree
Hide file tree
Showing 83 changed files with 5,072 additions and 1,695 deletions.
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,18 @@ jobs:
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

# The .ts scripts depend upon this
# The .ts scripts depend upon this
- run: npm install --global tsx
# Enable corepack for packageManager config
- run: corepack enable
- run: yarn install

- name: build test images
run: |
docker info
./buildTestImages.ts
node_modules/.bin/synthetic-chain build
- name: run test images
run: ./runTestImages.ts
run: node_modules/.bin/synthetic-chain test

# XXX this should be instant because all the stages were already built in the steps above
# but it's re-building the last stage. This is deemed good enough for now.
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ web_modules/

# Output of 'npm pack'
*.tgz
!agoric-synthetic-chain-*.tgz

# Yarn Integrity file
.yarn-integrity
Expand Down Expand Up @@ -134,3 +135,4 @@ dist

# build in CI
Dockerfile
/upgrade-test-scripts
File renamed without changes.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ If the proposal is _pending_ and does not yet have a number, use a letter. The p
To build the test images,

```
./buildTestImages.ts
node_modules/.bin/synthetic-chain build
```

To build the test images for particular proposals,

```
# build just upgrades
./buildTestImages.ts --match upgrade
node_modules/.bin/synthetic-chain build --match upgrade
```

To run the tests for particular proposals,

```
# build just upgrades
./runTestImages.ts --match upgrade
node_modules/.bin/synthetic-chain test --match upgrade
```

## Debugging
Expand Down
37 changes: 0 additions & 37 deletions buildTestImages.ts

This file was deleted.

35 changes: 0 additions & 35 deletions debugTestImage.ts

This file was deleted.

15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"private": true,
"workspaces": [
"packages/*"
],
"scripts": {
"build": "echo Use synthetic-chain to build proposal images",
"test": "echo Use synthetic-chain to test proposal images"
},
"dependencies": {
"@agoric/synthetic-chain": "workspace:*"
},
"license": "Apache-2.0",
"packageManager": "[email protected]"
}
29 changes: 29 additions & 0 deletions packages/synthetic-chain/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Synthetic chain tools

Utilities to build a synthetic chain and test running proposals atop it. The chain approximates agoric-3 (Mainnet) using the state from https://github.com/Agoric/agoric-3-proposals (It could trivially support other Agoric chains, if we scale horizontally.)

## Design

Builds atop the `main` image of https://ghcr.io/agoric/agoric-3-proposals to execute proposals on top of the agoric-3 chain and also test them.

It also adopts the multi-stage Docker build flow from the a3p repo. See https://github.com/Agoric/agoric-3-proposals?tab=readme-ov-file#design

One deficiency in the current design is that share code in `upgrade-test-scripts` is not versioned or packaged. Any change to it will invalidate the base image. And each layer assumes it has the latest. And now with this repo, the local copy has to be kept in sync with the base image and the a3p repo.

```sh
node_modules/.bin/synthetic-chain build

node_modules/.bin/synthetic-chain test

node_modules/.bin/synthetic-chain test --debug -m <substring of proposal name>
```

shared JS is exported from the package.
non-JS is in `files` and can be untarred out for use in a3p

To depend on `@agoric/synthetic-chain` that isn't yet published, use `npm pack` in this package and copy the tgz into the proposal. Then use the `file:` protocol in the package.json to add it. Finally `yarn install` in the package to update local node_modules for linting. E.g.,

```json
"dependencies": {
"@agoric/synthetic-chain": "file:agoric-synthetic-chain-0.0.1-alpha.tgz",
```
55 changes: 55 additions & 0 deletions packages/synthetic-chain/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env tsx

import { parseArgs } from 'node:util';
import path from 'node:path';
import { execSync } from 'node:child_process';
import { buildProposalSubmissions, buildTestImages } from './src/cli/build.js';
import { refreshDockerfile } from './src/cli/dockerfileGen.js';
import { matchOneProposal, readProposals } from './src/cli/proposals.js';
import { debugTestImage, runTestImages } from './src/cli/run.js';

const { positionals, values } = parseArgs({
options: {
match: { short: 'm', type: 'string' },
dry: { type: 'boolean' },
debug: { type: 'boolean' },
},
allowPositionals: true,
});

const allProposals = readProposals(path.resolve('.'));

const { match } = values;
const proposals = match
? allProposals.filter(p => p.proposalName.includes(match))
: allProposals;

const [cmd] = positionals;

// TODO consider a lib like Commander for auto-gen help
const usage = `USAGE:
build
test [--debug]
`;

switch (cmd) {
case 'build':
execSync(
// XXX very brittle
'cp -r node_modules/@agoric/synthetic-chain/upgrade-test-scripts .',
);
refreshDockerfile(allProposals);
buildProposalSubmissions(proposals);
buildTestImages(proposals, values.dry);
break;
case 'test':
if (values.debug) {
debugTestImage(matchOneProposal(proposals, match!));
} else {
runTestImages(proposals);
}
break;
default:
console.log(usage);
}
34 changes: 34 additions & 0 deletions packages/synthetic-chain/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@agoric/synthetic-chain",
"version": "0.0.1-alpha",
"description": "Utilities to build a chain and test proposals atop it",
"bin": "./cli.ts",
"main": "index.js",
"type": "module",
"files": [
"index.js",
"cli.ts",
"src",
"upgrade-test-scripts"
],
"scripts": {
"build": "echo No build step",
"test": "NODE_OPTIONS='--loader=tsx --no-warnings' ava",
"test:xs": "exit 0"
},
"dependencies": {
"tsx": "^3.12.8",
"typescript": "^5.3.3"
},
"devDependencies": {
"@types/node": "^18.11.9",
"ava": "^5.3.0"
},
"ava": {
"extensions": {
"js": true,
"ts": "module"
}
},
"license": "Apache-2.0"
}
48 changes: 48 additions & 0 deletions packages/synthetic-chain/src/cli/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { execSync } from 'node:child_process';
import path from 'node:path';
import { ProposalInfo, imageNameForProposal } from './proposals.js';

export const buildProposalSubmissions = (proposals: ProposalInfo[]) => {
for (const proposal of proposals) {
if (!('source' in proposal && proposal.source === 'build')) continue;

console.log(
'Refreshing submission for',
proposal.proposalIdentifier,
proposal.proposalName,
);
const { buildScript } = proposal;
const proposalPath = `proposals/${proposal.proposalIdentifier}:${proposal.proposalName}`;
const submissionPath = `${proposalPath}/submission`;
const relativeBuildScript = path.relative(submissionPath, buildScript);

execSync(`mkdir -p ${submissionPath}`);
// Generate files only in submission path.
execSync(`agoric run ${relativeBuildScript}`, {
cwd: submissionPath,
env: { ...process.env, HOME: '.' },
});
// UNTIL https://github.com/Agoric/agoric-sdk/pull/8559 is merged
// Move bundles from submission subdir to submission path.
execSync(`mv ${submissionPath}/.agoric/cache/* ${submissionPath}`);
}
};

export const buildTestImages = (proposals: ProposalInfo[], dry = false) => {
for (const proposal of proposals) {
if (!dry) {
console.log(
`\nBuilding test image for proposal ${proposal.proposalName}`,
);
}
const { name, target } = imageNameForProposal(proposal, 'test');
// 'load' to ensure the images are output to the Docker client. Seems to be necessary
// for the CI docker/build-push-action to re-use the cached stages.
const cmd = `docker buildx build --load --tag ${name} --target ${target} .`;
console.log(cmd);
if (!dry) {
// `time` to output how long each build takes
execSync(`time ${cmd}`, { stdio: 'inherit' });
}
}
};
Loading

0 comments on commit 003309d

Please sign in to comment.