426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
92 lines
3.9 KiB
Markdown
92 lines
3.9 KiB
Markdown
# Hetzner Agent E2E
|
||
|
||
Nightly end-to-end smoke that provisions a real Hetzner cpx11 server,
|
||
deploys a trivial agent via the Eliza Cloud staging API, runs a
|
||
bridge-ping healthcheck plus one real chat turn (a `message.send`
|
||
JSON-RPC through the production Worker bridge path, requiring a reply
|
||
that echoes a per-run proof token and carries no fabrication flag),
|
||
and tears everything down. A reaper
|
||
workflow sweeps any servers older than 60 minutes every half hour as a
|
||
safety net.
|
||
|
||
The workflow gracefully skips when secrets are unset, so it can land
|
||
on `develop` and be activated later by adding secrets. Once secrets
|
||
are present, the Cloud API auth preflight is a real gate: a 401/403
|
||
from `CLOUD_E2E_API_KEY` fails the run instead of reporting a skip,
|
||
because an invalid key would otherwise hide provisioning regressions.
|
||
|
||
## One-time setup
|
||
|
||
### 1. Create a CI-scoped Hetzner project + token
|
||
|
||
1. Create a separate Hetzner Cloud project (so a leaked token can't
|
||
touch production servers).
|
||
2. Issue a read-write API token in that project.
|
||
3. Generate a fresh `ed25519` SSH keypair locally (not your dev key):
|
||
```bash
|
||
ssh-keygen -t ed25519 -f /tmp/hetzner-e2e-key -N ""
|
||
```
|
||
4. Upload the public key to the Hetzner project (Hetzner Console →
|
||
Security → SSH Keys) and record the **numeric key id** from the
|
||
URL.
|
||
|
||
### 2. Create the GitHub environment
|
||
|
||
In the repo settings, create a new environment named
|
||
`ci-hetzner-e2e`. (Restricting to `develop` is recommended.)
|
||
|
||
### 3. Add environment secrets
|
||
|
||
| Secret | Value |
|
||
|---|---|
|
||
| `HCLOUD_TOKEN_CI` | The Hetzner API token from step 1.2 |
|
||
| `CLOUD_E2E_API_KEY` | A long-lived Eliza Cloud staging bearer token |
|
||
| `CI_SSH_PRIVATE_KEY` | Contents of `/tmp/hetzner-e2e-key` (private) |
|
||
| `CI_SSH_PUBLIC_KEY_ID` | Numeric Hetzner SSH key id from step 1.4 |
|
||
|
||
## Estimated cost
|
||
|
||
Default `cx22` in `fsn1` is roughly €0.006/hr (cpx11's deprecated
|
||
successor — comparable 2 vCPU / 4 GB footprint). A nightly run that
|
||
lives ~10 minutes is **about $0.30–$1.00/month** depending on
|
||
healthcheck duration. The reaper enforces a 60-minute upper bound so
|
||
the worst case (a stuck workflow) is bounded at one server-hour per
|
||
run.
|
||
|
||
If the requested `HETZNER_E2E_SERVER_TYPE` is deprecated or not
|
||
offered at `HETZNER_E2E_LOCATION`, the provisioner falls back through
|
||
a short list of known-good shared-cpu combos (cx22 in fsn1/nbg1, cax11
|
||
ARM in fsn1/hel1/nbg1) before giving up.
|
||
|
||
## Manual trigger / dry run
|
||
|
||
```bash
|
||
gh workflow run hetzner-e2e.yml
|
||
```
|
||
|
||
To test locally without touching Hetzner, run only the helpers that
|
||
don't make real API calls (e.g. typecheck them with `tsc --noEmit`).
|
||
**Do not** invoke `hetzner-e2e-provision.ts` outside of CI unless you
|
||
intend to create a real billable server.
|
||
|
||
## Files
|
||
|
||
- `.github/workflows/hetzner-e2e.yml` — provision + deploy + healthcheck + teardown
|
||
- `.github/workflows/hetzner-e2e-reaper.yml` — scheduled label-selector sweep
|
||
- `hetzner-e2e-provision.ts` — `HetznerCloudClient.createServer()`
|
||
- `hetzner-e2e-wait-ready.ts` — SSH-poll for cloud-init + Docker
|
||
- `hetzner-e2e-deploy-agent.ts` — create + provision a trivial agent
|
||
- `hetzner-e2e-healthcheck.ts` — single `status.get` bridge ping
|
||
- `hetzner-e2e-chat.ts` — one real `message.send` chat turn, judged by
|
||
`../bridge-reply-verdict.ts` (#15616): the reply must echo the
|
||
per-run proof token within the retry budget and must not be
|
||
bridge-fabricated (`fallback: true`), runtime-canned (`failureKind`,
|
||
known canned strings), or an `[echo]` parroting — so "provisioned
|
||
but chat dead-ends" regressions (#15347) go red. Logs which bridge
|
||
rung (conversation REST / OpenAI-compat / central-channel / …)
|
||
produced the reply
|
||
- `hetzner-e2e-teardown.ts` — delete the server (idempotent, falls
|
||
back to label sweep if state artifact missing)
|
||
- `hetzner-e2e-reaper.ts` — list+delete servers older than 60min
|
||
- `state-file.ts` — atomic JSON state shared between steps
|