WonderTwin in CircleCI
WonderTwin in CircleCI
Section titled “WonderTwin in CircleCI”Run a twin against your test suite in a CircleCI workflow. Capture replay artifacts on every run, including failures.
Snippet
Section titled “Snippet”Drop this into .circleci/config.yml (or merge into your existing config):
version: 2.1
jobs: test-with-twin: docker: - image: cimg/base:current environment: WT_TWIN_URL: http://127.0.0.1:<TWIN_PORT> steps: - checkout
- run: name: Install wt command: | curl -sSL "https://github.com/wondertwin-ai/wondertwin/releases/latest/download/wt-linux-amd64" -o /usr/local/bin/wt chmod +x /usr/local/bin/wt
- run: name: Install WonderTwin license command: | if [ -n "$WONDERTWIN_LICENSE" ]; then printf '%s' "$WONDERTWIN_LICENSE" > /tmp/license.json wt license install /tmp/license.json rm /tmp/license.json fi
- run: name: Start twin-<TWIN> background: true command: | wt install <TWIN>@<TWIN_VERSION> wt up
- run: name: Wait for twin command: | for i in $(seq 1 30); do curl -sf "$WT_TWIN_URL/admin/state" > /dev/null && exit 0 sleep 0.2 done echo "twin did not become healthy in 6s" exit 1
- run: name: Start run environment: CI: "true" command: | wt runs start \ --twin "$WT_TWIN_URL" \ --seed 42 \ --run-id "${CIRCLE_WORKFLOW_ID}-${CIRCLE_BUILD_NUM}"
- run: name: Test command: <TEST_COMMAND>
- run: name: Finish run + export replay when: always command: | mkdir -p /tmp/wondertwin-artifacts wt runs finish \ --twin "$WT_TWIN_URL" \ --run-id "${CIRCLE_WORKFLOW_ID}-${CIRCLE_BUILD_NUM}" \ --export /tmp/wondertwin-artifacts/replay.jsonl.gz
- store_artifacts: path: /tmp/wondertwin-artifacts destination: wondertwin-replay
workflows: build-test: jobs: - test-with-twinSetup checklist
Section titled “Setup checklist”- Pick your twin and version. Replace
<TWIN>(e.g.stripe,twilio),<TWIN_VERSION>(e.g.0.1.0), and<TWIN_PORT>(twin-stripe:4111). - Replace
<TEST_COMMAND>with your actual test invocation. - Set the license environment variable. In CircleCI: Project Settings → Environment Variables → Add Variable. Name:
WONDERTWIN_LICENSE. Value: the full contents of the license JSON file (paste it as-is; do not base64-encode). Or use a Context if you want to share the secret across multiple projects. - Tell your test code where the twin is. The job exports
WT_TWIN_URL. Most SDKs let you override the base URL via env var or config — see your SDK’s docs. - Choose a Docker image.
cimg/base:currentworks for most cases. If your tests need a specific runtime (Node, Go, Python), usecimg/node:20,cimg/go:1.22, etc.
Variations
Section titled “Variations”With BYO synthetic fixtures
Section titled “With BYO synthetic fixtures”- run: name: Start run with fixtures command: | wt runs start \ --twin "$WT_TWIN_URL" \ --seed 42 \ --fixtures fixtures/stripe-snapshot.json \ --run-id "${CIRCLE_WORKFLOW_ID}-${CIRCLE_BUILD_NUM}"Without an explicit run lifecycle (using wt runs wrap)
Section titled “Without an explicit run lifecycle (using wt runs wrap)”- run: name: Test with wrap environment: CI: "true" command: | wt runs wrap \ --twin "$WT_TWIN_URL" \ --seed 42 \ --run-id "${CIRCLE_WORKFLOW_ID}-${CIRCLE_BUILD_NUM}" \ --export /tmp/wondertwin-artifacts/replay.jsonl.gz \ -- <TEST_COMMAND>- store_artifacts: path: /tmp/wondertwin-artifacts destination: wondertwin-replayMultiple twins in one job
Section titled “Multiple twins in one job”Use separate background: true steps with different ports:
- run: name: Start twin-stripe background: true command: | wt install stripe@0.1.0 PORT=4111 wt up- run: name: Start twin-twilio background: true command: | wt install twilio@0.1.0 PORT=4112 wt upFor most use cases, one twin per job is simpler.
Pin both wt and the twin version
Section titled “Pin both wt and the twin version”- run: | curl -sSL "https://github.com/wondertwin-ai/wondertwin/releases/download/v0.4.2/wt-linux-amd64" -o /usr/local/bin/wt chmod +x /usr/local/bin/wt- run: wt install stripe@0.1.0Troubleshooting
Section titled “Troubleshooting”background: true steps that fail silently
Section titled “background: true steps that fail silently”CircleCI background steps don’t fail the job if the command exits non-zero. The Wait for twin step is the gate — if the twin never becomes healthy, that step exits non-zero and the job fails clearly.
My replay step doesn’t run when tests fail
Section titled “My replay step doesn’t run when tests fail”CircleCI’s when: always is the equivalent of GitHub’s if: always(). Make sure the Finish run + export replay and store_artifacts steps both have when: always set.
The Docker image doesn’t have curl
Section titled “The Docker image doesn’t have curl”cimg/base:current includes curl. If you’re using a custom image, install curl first or use the wget form:
- run: | wget -O /usr/local/bin/wt "https://github.com/wondertwin-ai/wondertwin/releases/latest/download/wt-linux-amd64" chmod +x /usr/local/bin/wtLicense doesn’t validate
Section titled “License doesn’t validate”See the GitHub Actions guide’s troubleshooting — the causes are platform-agnostic.
Reference
Section titled “Reference”wt runs --helpfor full CLI optionsconcepts.md— twins, runs, replay, licensestrategy.md— why docs first- CircleCI artifacts documentation