Files
wehub-resource-sync 426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
ci / test (push) Waiting to run
ci / lint-and-format (push) Waiting to run
ci / build (push) Waiting to run
ci / dev-startup (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
gitleaks / gitleaks (push) Waiting to run
Markdown Links / Relative Markdown Links (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Quality (Extended) / Homepage Build (PR smoke) (push) Waiting to run
Quality (Extended) / Comment-only diff guard (push) Waiting to run
Quality (Extended) / Format + Type Safety Ratchet (push) Waiting to run
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Waiting to run
Quality (Extended) / Develop Gate (lint) (push) Waiting to run
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
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) Waiting to run
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) Waiting to run
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) Waiting to run
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) Waiting to run
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) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

320 lines
10 KiB
JavaScript

/**
* End-to-end smoke for the packaged `elizaos` CLI: packs the workspace package,
* installs it into temporary global/local locations, and exercises create /
* upgrade flows against generated projects.
*/
import { execFileSync } from "node:child_process";
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const packageDir = path.resolve(scriptDir, "..");
const tmpBaseDir =
process.env.ELIZAOS_SMOKE_TMPDIR ||
(fs.existsSync("/tmp") ? "/tmp" : os.tmpdir());
const tmpRoot = fs.mkdtempSync(
path.join(tmpBaseDir, "elizaos-packaged-smoke-"),
);
const shouldKeepTemp = process.env.ELIZAOS_SMOKE_KEEP_TEMP === "1";
const shouldInstallGeneratedFullstack =
process.env.ELIZAOS_SMOKE_FULLSTACK_INSTALL === "1";
const shouldSmokeEject = process.env.ELIZAOS_SMOKE_EJECT === "1";
const shouldUseRemoteUpstream =
process.env.ELIZAOS_SMOKE_REMOTE_UPSTREAM === "1";
const shouldSkipGlobalInstall =
process.env.ELIZAOS_SMOKE_SKIP_GLOBAL_INSTALL === "1";
const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
const bunCommand = process.platform === "win32" ? "bun.exe" : "bun";
const elizaosBinName = process.platform === "win32" ? "elizaos.cmd" : "elizaos";
const localUpstreamRepo = path.resolve(packageDir, "..", "..");
const cliEnv =
!shouldUseRemoteUpstream &&
fs.existsSync(
path.join(localUpstreamRepo, "packages", "app-core", "package.json"),
)
? {
...process.env,
ELIZAOS_UPSTREAM_BRANCH: process.env.ELIZAOS_UPSTREAM_BRANCH ?? "",
ELIZAOS_UPSTREAM_REPO:
process.env.ELIZAOS_UPSTREAM_REPO || localUpstreamRepo,
}
: process.env;
const fullstackInstallEnv = {
...process.env,
ELIZA_NO_VISION_DEPS: process.env.ELIZA_NO_VISION_DEPS || "1",
SKIP_AVATAR_CLONE: process.env.SKIP_AVATAR_CLONE || "1",
};
function run(command, args, options = {}) {
return execFileSync(command, args, {
cwd: options.cwd,
encoding: "utf8",
env: options.env,
stdio: ["ignore", "pipe", "pipe"],
});
}
function commandExists(command) {
try {
execFileSync(process.platform === "win32" ? "where" : "which", [command]);
return true;
} catch {
return false;
}
}
function packCliPackage() {
if (commandExists(npmCommand)) {
return run(npmCommand, ["pack", packageDir, "--pack-destination", tmpRoot]);
}
if (!commandExists(bunCommand)) {
throw new Error("Neither npm nor bun is available for packaged smoke test");
}
return run(bunCommand, ["pm", "pack", "--destination", tmpRoot, "--quiet"], {
cwd: packageDir,
});
}
function installCliPackage(smokeDir, tarballPath) {
if (commandExists(npmCommand)) {
run(npmCommand, ["install", tarballPath], { cwd: smokeDir });
return;
}
run(bunCommand, ["add", tarballPath], { cwd: smokeDir });
}
function availableGlobalManagers() {
const managers = [];
if (commandExists(npmCommand)) managers.push("npm");
if (commandExists(bunCommand)) managers.push("bun");
if (managers.length === 0) {
throw new Error(
"Neither npm nor bun is available for global packaged smoke test",
);
}
return managers;
}
function installCliPackageGlobally(manager, prefixDir, tarballPath) {
if (manager === "npm") {
run(npmCommand, [
"install",
"--global",
"--prefix",
prefixDir,
"--no-audit",
"--no-fund",
tarballPath,
]);
return;
}
run(bunCommand, ["add", "--global", tarballPath], {
env: { ...process.env, BUN_INSTALL: prefixDir },
});
}
function getTarballName(output) {
const lines = output
.split(/\r?\n/)
.map((line) => line.trim())
.filter(Boolean);
const tarball = [...lines].reverse().find((line) => line.endsWith(".tgz"));
if (!tarball) {
throw new Error(
`Unable to determine tarball name from npm pack output:\n${output}`,
);
}
return tarball;
}
function getInstalledCli(smokeDir) {
return path.join(smokeDir, "node_modules", ".bin", elizaosBinName);
}
function getGloballyInstalledCli(prefixDir) {
const binPath =
process.platform === "win32"
? elizaosBinName
: path.join("bin", elizaosBinName);
return path.join(prefixDir, binPath);
}
function assertPathExists(targetPath) {
if (!fs.existsSync(targetPath)) {
throw new Error(`Expected path to exist: ${targetPath}`);
}
}
function assertPathMissing(targetPath) {
if (fs.existsSync(targetPath)) {
throw new Error(`Expected path to be absent: ${targetPath}`);
}
}
function runCli(smokeDir, cwd, args) {
return run(getInstalledCli(smokeDir), args, { cwd, env: cliEnv });
}
function availableCliRuntimes() {
// The bin's ESM imports are resolved by whatever runtime EXECUTES the bin,
// not by whatever installed it. node and bun apply the package "exports" map
// differently, so #8000 (ERR_PACKAGE_PATH_NOT_EXPORTED) can reproduce under
// one and not the other. Exercise every runtime that is on PATH.
const runtimes = [];
if (commandExists("node")) runtimes.push("node");
if (commandExists(bunCommand)) runtimes.push(bunCommand);
if (runtimes.length === 0) {
throw new Error("Neither node nor bun is available to execute the CLI");
}
return runtimes;
}
function runGlobalCli(prefixDir, cwd, args) {
// Run the installed bin under each runtime explicitly. execFileSync throws on
// a non-zero exit, so a successful return is the "exit 0" assertion.
const globalCli = getGloballyInstalledCli(prefixDir);
for (const runtime of availableCliRuntimes()) {
run(runtime, [globalCli, ...args], { cwd, env: cliEnv });
}
}
function smokeGlobalInstall(tarballPath) {
// Exercise EVERY available package manager: a global bin resolves through a
// stricter ESM path than a local install, and npm vs bun differ there. The
// ERR_PACKAGE_PATH_NOT_EXPORTED class (elizaOS/eliza#8000) only reproduces on
// global install, so testing a single manager can miss it.
for (const manager of availableGlobalManagers()) {
const prefixDir = path.join(tmpRoot, `global-${manager}`);
fs.mkdirSync(prefixDir, { recursive: true });
installCliPackageGlobally(manager, prefixDir, tarballPath);
const globalCli = getGloballyInstalledCli(prefixDir);
assertPathExists(globalCli);
// --version and --help both run the full module-init import chain (the bin
// shim's top-level imports) before commander short-circuits, so either
// would surface ERR_PACKAGE_PATH_NOT_EXPORTED. Assert both, under both
// node and bun.
runGlobalCli(prefixDir, tmpRoot, ["--version"]);
runGlobalCli(prefixDir, tmpRoot, ["--help"]);
}
}
function main() {
let passed = false;
try {
run("bun", ["run", "build"], { cwd: packageDir });
const packOutput = packCliPackage();
const tarballName = getTarballName(packOutput);
const tarballPath = path.isAbsolute(tarballName)
? tarballName
: path.join(tmpRoot, tarballName);
if (!shouldSkipGlobalInstall) {
smokeGlobalInstall(tarballPath);
}
const smokeDir = path.join(tmpRoot, "smoke");
fs.mkdirSync(smokeDir, { recursive: true });
fs.writeFileSync(
path.join(smokeDir, "package.json"),
`${JSON.stringify({ name: "elizaos-packaged-smoke", private: true }, null, 2)}\n`,
);
installCliPackage(smokeDir, tarballPath);
runCli(smokeDir, smokeDir, ["info"]);
const workspaceDir = path.join(smokeDir, "workspace");
fs.mkdirSync(workspaceDir, { recursive: true });
runCli(smokeDir, workspaceDir, [
"create",
"plugin-demo",
"--template",
"plugin",
"--language",
"typescript",
"--yes",
]);
const pluginDir = path.join(workspaceDir, "plugin-demo");
assertPathExists(path.join(pluginDir, "package.json"));
assertPathExists(path.join(pluginDir, ".elizaos", "template.json"));
if (shouldInstallGeneratedFullstack) {
run("bun", ["install"], { cwd: pluginDir });
run("bun", ["run", "typecheck"], { cwd: pluginDir });
run("bun", ["run", "build"], { cwd: pluginDir });
}
runCli(smokeDir, pluginDir, ["upgrade", "--check"]);
runCli(smokeDir, workspaceDir, [
"create",
"project-demo",
"--template",
"project",
"--yes",
]);
const projectDir = path.join(workspaceDir, "project-demo");
assertPathExists(path.join(projectDir, "package.json"));
assertPathExists(path.join(projectDir, ".elizaos", "template.json"));
assertPathExists(path.join(projectDir, "apps", "app", "package.json"));
assertPathMissing(path.join(projectDir, "eliza"));
const packageModeOutput = run(
"node",
["scripts/eliza-source-mode.mjs", "packages"],
{ cwd: projectDir },
);
if (!packageModeOutput.includes("beta")) {
throw new Error(
`Expected generated package mode to default to beta. Output:\n${packageModeOutput}`,
);
}
if (shouldInstallGeneratedFullstack) {
run("bun", ["install"], { cwd: projectDir, env: fullstackInstallEnv });
run("bun", ["run", "typecheck"], {
cwd: projectDir,
env: fullstackInstallEnv,
});
run("bun", ["run", "build"], {
cwd: projectDir,
env: fullstackInstallEnv,
});
}
runCli(smokeDir, projectDir, ["upgrade", "--check"]);
if (shouldSmokeEject) {
const currentBranch = run("git", ["branch", "--show-current"], {
cwd: localUpstreamRepo,
}).trim();
run("node", ["scripts/eliza-source-mode.mjs", "local"], {
cwd: projectDir,
env: {
...fullstackInstallEnv,
ELIZA_BRANCH: currentBranch || "develop",
ELIZA_GIT_URL: localUpstreamRepo,
},
});
assertPathExists(path.join(projectDir, "eliza", "package.json"));
assertPathExists(path.join(projectDir, ".elizaos", "source-mode"));
}
passed = true;
console.log("elizaos packaged smoke test passed");
} finally {
if (!shouldKeepTemp && passed) {
fs.rmSync(tmpRoot, { force: true, recursive: true });
} else if (!passed || shouldKeepTemp) {
console.log(`elizaos packaged smoke temp dir: ${tmpRoot}`);
}
}
}
main();