Volter World

Share a world

One world for the team: everyone clones from it, everyone pushes to it.

This page supplies an executable walkthrough for packages/cli/src/journeys/tutorials.test.ts.

A shared world is a world with no app in front of it, served on a URL. It holds the team's history the way a bare repository does, and every developer's world points at it as origin. This page runs one on your machine; put it behind TLS on a hostname and nothing else changes.

The app

package.json
{ "name": "acme-web", "private": true, "type": "module", "dependencies": { "@octokit/rest": "^21" } }

The app declares the credential it reads. The World issues a throwaway token for its GitHub account, world; that account is separate from the platform org acme. The seed creates world/web through Octokit before any issue is written. It can run again without creating a second repository.

.env.example
GITHUB_TOKEN=
.volter/seed.ts
import { Octokit } from '@octokit/rest';
const github = new Octokit({ auth: process.env.GITHUB_TOKEN });
const { data: { login: owner } } = await github.users.getAuthenticated();
try {
  await github.repos.get({ owner, repo: 'web' });
} catch (error) {
  if (error.status !== 404) throw error;
  await github.repos.createForAuthenticatedUser({ name: 'web' });
}
file-issue.mjs
import { Octokit } from '@octokit/rest';
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const { data: issue } = await octokit.issues.create({ owner: 'world', repo: 'web', title: process.argv[2] ?? 'Launch checklist' });
console.log(`filed #${issue.number}`);
npm install
npm install -g @volter/world
npm install -D @volter/twin-github
volter world init
volter world up
acme-web  1 twin up, story loaded

The shared world

init --bare makes a world with no app: a name, a branch tree per twin, and nothing else. serve puts it on a port and prints the token that opens it. The token is a credential for the world, never a vendor key; keep it where you keep any team secret.

../team/.env.example
GITHUB_TOKEN=
../team/.volter/seed.ts
import '../../acme-web/.volter/seed.ts';
cd ../team
volter world init --bare acme/team --twins github
volter world up
volter world down
volter world serve --port 4300 &
serving  acme/team  http://127.0.0.1:4300/acme/team
token    tok_

Back in the app:

cd ../acme-web

Point your world at it, and push

remote add records the URL and the token, once. push sends the entries your world has that the shared world does not, as a changeset, and moves your base past them.

volter remote add origin http://127.0.0.1:4300/acme/team --token "$(cat ../team/.volter/token)"
volter world pull
volter world run -- node file-issue.mjs
volter world changeset -m "The launch checklist"
volter world push
filed #1
changeset  the-launch-checklist  2 changes
pushed  the-launch-checklist  2 changes → origin

A teammate clones

The shared World has the repository as initial data, too: local seed data is not part of a push. A second app directory stands in for a teammate's laptop. clone records the origin and brings its whole history in, so the teammate's world holds the issue you filed before they run anything.

mkdir ../acme-web-two && cp package.json file-issue.mjs .env.example ../acme-web-two/ && cd ../acme-web-two
npm install
volter world init
volter world clone http://127.0.0.1:4300/acme/team --token "$(cat ../team/.volter/token)"
volter world up
volter world log
cloned  http://127.0.0.1:4300/acme/team  16 changes
github   issue.opened   issue:1

The clone includes the shared account and repository setup. A changeset groups the application's unpushed mutations. They push too, and you pull:

volter world run -- node file-issue.mjs "Rotate the keys"
volter world changeset -m "Key rotation"
volter world push
cd ../acme-web
volter world pull
volter world log
filed #2
pushed  key-rotation  2 changes → origin
pulled  origin  2 changes
github   issue.opened   issue:1
github   issue.opened   issue:2

pull brings in what origin has that you do not and moves your base past it. Your own unpushed entries stay where they are, on top of the moved base.

The shared world's own log

The shared world is a world. Its log is the team's history, and it answers the same verbs.

cd ../team
volter world log
cd ../acme-web
github   issue.opened   issue:1
github   issue.opened   issue:2

Clean up

volter world down
kill %1

When the shared world should reach the vendor

A shared world is also where a twin's root can be set to the vendor, so that entries landing there are deployed with a credential no laptop holds. That is deploy from a shared world.

View Markdown source

On this page