@essential-apps/shopify-test-runner 1.0.12 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/guestVnc.d.ts +31 -0
- package/dist/lib/guestVnc.d.ts.map +1 -0
- package/dist/lib/guestVnc.js +111 -0
- package/dist/lib/guestVnc.js.map +1 -0
- package/dist/probes/runProbe.js +0 -0
- package/dist/scripts/addStore.js +0 -0
- package/dist/scripts/buildImage.d.ts +3 -0
- package/dist/scripts/buildImage.d.ts.map +1 -0
- package/dist/scripts/{buildDockerImage.js → buildImage.js} +12 -10
- package/dist/scripts/buildImage.js.map +1 -0
- package/dist/scripts/captureAuth.js +0 -0
- package/dist/scripts/captureContracts.js +0 -0
- package/dist/scripts/captureRestContracts.js +0 -0
- package/dist/scripts/captureSharedContracts.d.ts +3 -0
- package/dist/scripts/captureSharedContracts.d.ts.map +1 -0
- package/dist/scripts/captureSharedContracts.js +209 -0
- package/dist/scripts/captureSharedContracts.js.map +1 -0
- package/dist/scripts/checkOperationCoverage.js +0 -0
- package/dist/scripts/cleanupStores.js +0 -0
- package/dist/scripts/createStores.js +0 -0
- package/dist/scripts/deployAppVersion.js +0 -0
- package/dist/scripts/devOnlineBackend.js +0 -0
- package/dist/scripts/installApp.js +0 -0
- package/dist/scripts/listStores.js +0 -0
- package/dist/scripts/runOffline.js +78 -1
- package/dist/scripts/runOffline.js.map +1 -1
- package/dist/scripts/runOfflineFullTests.js +49 -21
- package/dist/scripts/runOfflineFullTests.js.map +1 -1
- package/dist/scripts/runTests.js +0 -0
- package/dist/scripts/runVm.js +0 -0
- package/dist/scripts/runVmAuth.js +0 -0
- package/dist/scripts/setupTestDb.js +0 -0
- package/dist/scripts/verifyContracts.js +20 -29
- package/dist/scripts/verifyContracts.js.map +1 -1
- package/dist/scripts/verifyRestContracts.js +17 -30
- package/dist/scripts/verifyRestContracts.js.map +1 -1
- package/package.json +11 -9
- package/src/lib/guestVnc.ts +147 -0
- package/src/scripts/{buildDockerImage.ts → buildImage.ts} +11 -9
- package/src/scripts/captureSharedContracts.ts +228 -0
- package/src/scripts/runOffline.ts +82 -1
- package/src/scripts/runOfflineFullTests.ts +56 -21
- package/src/scripts/verifyContracts.ts +22 -38
- package/src/scripts/verifyRestContracts.ts +23 -42
- package/dist/edge/nodeShim.d.ts +0 -2
- package/dist/edge/nodeShim.d.ts.map +0 -1
- package/dist/edge/nodeShim.js +0 -217
- package/dist/edge/nodeShim.js.map +0 -1
- package/dist/scripts/_probeSourceUrl.d.ts +0 -3
- package/dist/scripts/_probeSourceUrl.d.ts.map +0 -1
- package/dist/scripts/_probeSourceUrl.js +0 -119
- package/dist/scripts/_probeSourceUrl.js.map +0 -1
- package/dist/scripts/buildDockerImage.d.ts +0 -3
- package/dist/scripts/buildDockerImage.d.ts.map +0 -1
- package/dist/scripts/buildDockerImage.js.map +0 -1
- package/dist/scripts/devE2eBackend.d.ts +0 -3
- package/dist/scripts/devE2eBackend.d.ts.map +0 -1
- package/dist/scripts/devE2eBackend.js +0 -117
- package/dist/scripts/devE2eBackend.js.map +0 -1
- package/dist/scripts/runDocker.d.ts +0 -3
- package/dist/scripts/runDocker.d.ts.map +0 -1
- package/dist/scripts/runDocker.js +0 -88
- package/dist/scripts/runDocker.js.map +0 -1
- package/dist/scripts/runDockerAuth.d.ts +0 -3
- package/dist/scripts/runDockerAuth.d.ts.map +0 -1
- package/dist/scripts/runDockerAuth.js +0 -108
- package/dist/scripts/runDockerAuth.js.map +0 -1
- package/dist/scripts/runDockerOffline.d.ts +0 -3
- package/dist/scripts/runDockerOffline.d.ts.map +0 -1
- package/dist/scripts/runDockerOffline.js +0 -129
- package/dist/scripts/runDockerOffline.js.map +0 -1
- package/dist/scripts/runDockerOfflineExplore.d.ts +0 -3
- package/dist/scripts/runDockerOfflineExplore.d.ts.map +0 -1
- package/dist/scripts/runDockerOfflineExplore.js +0 -116
- package/dist/scripts/runDockerOfflineExplore.js.map +0 -1
- package/dist/scripts/runIsolatedDockerOffline.d.ts +0 -3
- package/dist/scripts/runIsolatedDockerOffline.d.ts.map +0 -1
- package/dist/scripts/runIsolatedDockerOffline.js +0 -351
- package/dist/scripts/runIsolatedDockerOffline.js.map +0 -1
- package/dist/scripts/runOfflineE2e.d.ts +0 -3
- package/dist/scripts/runOfflineE2e.d.ts.map +0 -1
- package/dist/scripts/runOfflineE2e.js +0 -408
- package/dist/scripts/runOfflineE2e.js.map +0 -1
- package/dist/scripts/runSupermachine.d.ts +0 -3
- package/dist/scripts/runSupermachine.d.ts.map +0 -1
- package/dist/scripts/runSupermachine.js +0 -474
- package/dist/scripts/runSupermachine.js.map +0 -1
- package/dist/scripts/runSupermachineAuth.d.ts +0 -3
- package/dist/scripts/runSupermachineAuth.d.ts.map +0 -1
- package/dist/scripts/runSupermachineAuth.js +0 -454
- package/dist/scripts/runSupermachineAuth.js.map +0 -1
- package/dist/vite/offlineConfig.d.ts +0 -34
- package/dist/vite/offlineConfig.d.ts.map +0 -1
- package/dist/vite/offlineConfig.js +0 -61
- package/dist/vite/offlineConfig.js.map +0 -1
- package/src/scripts/runDockerAuth.ts +0 -120
|
@@ -1,454 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* One-time interactive Shopify auth capture inside a supermachine VM.
|
|
4
|
-
*
|
|
5
|
-
* Why this exists: live e2e tests run inside a supermachine HVF arm64
|
|
6
|
-
* microVM with chromium under a virtual Xvfb display. There's no way
|
|
7
|
-
* to interactively log in to Shopify from outside the VM, but the
|
|
8
|
-
* captured storage state (cookies — Partners session AND, crucially,
|
|
9
|
-
* Cloudflare's `cf_clearance` Turnstile-bypass cookie) needs to be
|
|
10
|
-
* captured INSIDE that same VM so the browser fingerprint matches at
|
|
11
|
-
* test time. Captures from the macOS host (different UA, different
|
|
12
|
-
* canvas/WebGL hashes) trigger CF re-challenge.
|
|
13
|
-
*
|
|
14
|
-
* Flow:
|
|
15
|
-
* 1. Bake / acquire the same VM the e2e suite uses (same image,
|
|
16
|
-
* same warmupTag → reuses the snapshot — warm acquires are
|
|
17
|
-
* ~3 s instead of ~4 min cold bake).
|
|
18
|
-
* 2. Mount the workspace so storageState.json writes land on the
|
|
19
|
-
* host filesystem.
|
|
20
|
-
* 3. Start x11vnc inside the guest, bound to 0.0.0.0:5900.
|
|
21
|
-
* 4. Forward host 127.0.0.1:5900 → guest:5900 via vm.exposeTcp.
|
|
22
|
-
* 5. Open macOS Screen Sharing pointed at vnc://localhost:5900.
|
|
23
|
-
* 6. Spawn captureAuth.js inside the guest. It opens chrome on
|
|
24
|
-
* DISPLAY=:99, navigates to accounts.shopify.com/lookup, and
|
|
25
|
-
* waits for a host-side Enter keystroke.
|
|
26
|
-
* 7. User logs in via VNC, ALSO visits the test store admin to
|
|
27
|
-
* pass any Turnstile (so cf_clearance gets captured), then
|
|
28
|
-
* hits Enter in the host terminal.
|
|
29
|
-
* 8. captureAuth writes storageState.json (via the mounted
|
|
30
|
-
* workspace → host disk), then exits. We release the VM.
|
|
31
|
-
*
|
|
32
|
-
* Usage (one-time per developer machine, or when cf_clearance / the
|
|
33
|
-
* Partner session expires):
|
|
34
|
-
*
|
|
35
|
-
* npm run test:online:capture-live-auth
|
|
36
|
-
*
|
|
37
|
-
* macOS Screen Sharing opens automatically. If it doesn't, run
|
|
38
|
-
* `open vnc://localhost:5900` manually. VNC password is "e2e" by
|
|
39
|
-
* default; override with TEST_ONLINE_VNC_PASSWORD.
|
|
40
|
-
*
|
|
41
|
-
* Supersedes runDockerAuth.ts (libkrun-based; we no longer use
|
|
42
|
-
* libkrun for any test path).
|
|
43
|
-
*/
|
|
44
|
-
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
45
|
-
import { homedir, platform as osPlatform } from 'node:os';
|
|
46
|
-
import { resolve } from 'node:path';
|
|
47
|
-
import { spawn as nodeSpawn } from 'node:child_process';
|
|
48
|
-
import { setTimeout as sleep } from 'node:timers/promises';
|
|
49
|
-
import { prepareOciArchive } from '@essential-apps/shopify-test-core';
|
|
50
|
-
const repoRoot = process.cwd();
|
|
51
|
-
const VNC_PORT = 5900;
|
|
52
|
-
/**
|
|
53
|
-
* Resolve the supermachine image source the same way runSupermachine.ts
|
|
54
|
-
* does. Without this, supermachine treats TEST_ONLINE_SUPERMACHINE_IMAGE as
|
|
55
|
-
* a Docker Hub registry ref and tries to pull it — which 401s for
|
|
56
|
-
* locally-built `container build` images that never went to a
|
|
57
|
-
* registry. oci-archive mode is the only one that works for the
|
|
58
|
-
* Apple-`container`-built images we actually use.
|
|
59
|
-
*/
|
|
60
|
-
async function imageSourceOptions() {
|
|
61
|
-
const mode = process.env['TEST_ONLINE_SUPERMACHINE_IMAGE_SOURCE'] ?? 'oci-archive';
|
|
62
|
-
if (mode === 'registry')
|
|
63
|
-
return {};
|
|
64
|
-
const ref = process.env['TEST_ONLINE_SUPERMACHINE_IMAGE'] ??
|
|
65
|
-
'essential-apps/shopify-test-supermachine:latest';
|
|
66
|
-
if (mode === 'oci-archive') {
|
|
67
|
-
const prep = await prepareOciArchive(ref);
|
|
68
|
-
if (prep.freshlySaved) {
|
|
69
|
-
console.error(`[runSupermachineAuth] saved ${ref} → ${prep.archivePath} (${(prep.sizeBytes / 1024 / 1024).toFixed(1)} MB)`);
|
|
70
|
-
}
|
|
71
|
-
return { source: 'oci-archive', sourcePath: prep.archivePath };
|
|
72
|
-
}
|
|
73
|
-
if (mode === 'oci-layout') {
|
|
74
|
-
const sourcePath = process.env['TEST_ONLINE_SUPERMACHINE_IMAGE_LAYOUT_PATH'];
|
|
75
|
-
if (!sourcePath) {
|
|
76
|
-
throw new Error(`TEST_ONLINE_SUPERMACHINE_IMAGE_SOURCE=oci-layout requires TEST_ONLINE_SUPERMACHINE_IMAGE_LAYOUT_PATH`);
|
|
77
|
-
}
|
|
78
|
-
return { source: 'oci-layout', sourcePath };
|
|
79
|
-
}
|
|
80
|
-
throw new Error(`TEST_ONLINE_SUPERMACHINE_IMAGE_SOURCE=${mode} not recognised. Valid: oci-archive | oci-layout | registry`);
|
|
81
|
-
}
|
|
82
|
-
function readAppName() {
|
|
83
|
-
const pkgPath = resolve(repoRoot, 'package.json');
|
|
84
|
-
if (!existsSync(pkgPath)) {
|
|
85
|
-
throw new Error(`No package.json at ${pkgPath}. Run this from the consuming app's repo root.`);
|
|
86
|
-
}
|
|
87
|
-
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
88
|
-
if (!pkg.name)
|
|
89
|
-
throw new Error(`package.json at ${pkgPath} has no \`name\` field.`);
|
|
90
|
-
return pkg.name.replace(/^@[^/]+\//, '');
|
|
91
|
-
}
|
|
92
|
-
async function main() {
|
|
93
|
-
const appName = readAppName();
|
|
94
|
-
// Same node_modules volume + tarball-manifest extraFile as
|
|
95
|
-
// runSupermachine.ts. Sharing both means auth-capture and live
|
|
96
|
-
// e2e use the SAME snapshot (same warmupTag), so a single bake
|
|
97
|
-
// serves both flows.
|
|
98
|
-
const linuxModulesVolume = process.env['TEST_LINUX_NODE_MODULES_VOLUME'] ??
|
|
99
|
-
resolve(homedir(), `.cache/${appName}-e2e/node_modules.img`);
|
|
100
|
-
mkdirSync(resolve(linuxModulesVolume, '..'), { recursive: true });
|
|
101
|
-
const tarballManifest = resolve(repoRoot, 'vendor/essential-apps-shopify-test/.tarball-manifest');
|
|
102
|
-
const tarballManifestExists = existsSync(tarballManifest);
|
|
103
|
-
const vncPassword = process.env['TEST_ONLINE_VNC_PASSWORD'] ?? 'e2e';
|
|
104
|
-
const ref = process.env['TEST_ONLINE_SUPERMACHINE_IMAGE'] ?? 'essential-apps/shopify-test-supermachine:latest';
|
|
105
|
-
// amd64+Rosetta is the only path that has real Google Chrome
|
|
106
|
-
// installed (the Dockerfile installs google-chrome-stable amd64);
|
|
107
|
-
// we want real Chrome here so the captured fingerprint matches
|
|
108
|
-
// what e2e tests use (channel: 'chrome' via TEST_FORCE_REAL_CHROME,
|
|
109
|
-
// OR patchright bundled chromium — both run on this image).
|
|
110
|
-
const platform = process.env['TEST_ONLINE_SUPERMACHINE_PLATFORM'] ?? 'linux/arm64';
|
|
111
|
-
console.error(`[runSupermachineAuth] baking image…`);
|
|
112
|
-
const tBake = performance.now();
|
|
113
|
-
const { Image } = await import('@supermachine/core');
|
|
114
|
-
const imageOpts = await imageSourceOptions();
|
|
115
|
-
// Same warmup pattern as runSupermachine.ts so this bake hits the
|
|
116
|
-
// existing snapshot (warmupTag must match). If runSupermachine has
|
|
117
|
-
// never run cold yet, this will trigger that warmup — ~4 min once.
|
|
118
|
-
const image = await Image.build({
|
|
119
|
-
ref,
|
|
120
|
-
memoryMib: Number(process.env['TEST_ONLINE_SUPERMACHINE_MEMORY_MIB'] ?? 8192),
|
|
121
|
-
vcpus: Number(process.env['TEST_ONLINE_SUPERMACHINE_VCPUS'] ?? 4),
|
|
122
|
-
cmd: ['sleep', 'infinity'],
|
|
123
|
-
env: { SKIP_OFFLINE_HOST_HIJACK: '1' },
|
|
124
|
-
platform,
|
|
125
|
-
mounts: [
|
|
126
|
-
// supermachine 0.7.28+ requires explicit guestPath and
|
|
127
|
-
// auto-mounts at boot before warmup fires.
|
|
128
|
-
{ hostPath: repoRoot, guestTag: 'workspace', guestPath: '/workspace' },
|
|
129
|
-
],
|
|
130
|
-
volumes: [
|
|
131
|
-
{
|
|
132
|
-
hostPath: linuxModulesVolume,
|
|
133
|
-
guestPath: '/workspace/node_modules',
|
|
134
|
-
sizeMib: 4096,
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
extraFiles: tarballManifestExists
|
|
138
|
-
? [
|
|
139
|
-
{ hostPath: tarballManifest, guestPath: '/etc/.shopify-test-tarball-manifest' },
|
|
140
|
-
]
|
|
141
|
-
: [],
|
|
142
|
-
// SHARED with runSupermachine.ts — same warmup script, same tag,
|
|
143
|
-
// so a single snapshot serves both flows.
|
|
144
|
-
warmupTag: 'live-e2e-v2',
|
|
145
|
-
warmup: async (vm) => {
|
|
146
|
-
const r = await vm.exec({
|
|
147
|
-
argv: [
|
|
148
|
-
'sh',
|
|
149
|
-
'-c',
|
|
150
|
-
`
|
|
151
|
-
echo "[warmup] >>> ENTERED warmup callback at \$(date +%H:%M:%S.%N)"
|
|
152
|
-
set -e
|
|
153
|
-
# supermachine 0.7.28+ auto-mounts /workspace +
|
|
154
|
-
# /workspace/node_modules BEFORE warmup fires. Keep the
|
|
155
|
-
# defence-in-depth virtiofs check so a future auto-mount
|
|
156
|
-
# regression can't let rm-rf nuke the host bind.
|
|
157
|
-
NM_FS=\$(stat -f -c %T /workspace/node_modules 2>/dev/null || stat --file-system --format=%T /workspace/node_modules)
|
|
158
|
-
echo "[warmup] /workspace/node_modules FS type: \$NM_FS"
|
|
159
|
-
if [ "\$NM_FS" = "virtiofs" ] || [ "\$NM_FS" = "fuse.virtiofs" ]; then
|
|
160
|
-
echo "FATAL: /workspace/node_modules is \$NM_FS — auto-mount broken"
|
|
161
|
-
grep ' /workspace' /proc/mounts
|
|
162
|
-
exit 1
|
|
163
|
-
fi
|
|
164
|
-
chown -R postgres:postgres /var/lib/postgresql/data
|
|
165
|
-
chmod 700 /var/lib/postgresql/data
|
|
166
|
-
mkdir -p /var/run/postgresql
|
|
167
|
-
chown postgres:postgres /var/run/postgresql
|
|
168
|
-
chmod 775 /var/run/postgresql
|
|
169
|
-
cd /workspace
|
|
170
|
-
# Fresh install every rebake (tarball-manifest hash
|
|
171
|
-
# invalidates the snapshot when tarballs change). Wiping
|
|
172
|
-
# before install ensures stale tarballs can't linger.
|
|
173
|
-
rm -rf node_modules/* node_modules/.[!.]* 2>/dev/null || true
|
|
174
|
-
npm install --legacy-peer-deps --engine-strict=false 2>&1 | tail -30
|
|
175
|
-
if ! grep -q "^127.0.0.1.*localhost" /etc/hosts; then
|
|
176
|
-
echo "127.0.0.1 localhost" >> /etc/hosts
|
|
177
|
-
echo "::1 localhost" >> /etc/hosts
|
|
178
|
-
fi
|
|
179
|
-
`,
|
|
180
|
-
],
|
|
181
|
-
timeoutMs: 15 * 60 * 1000,
|
|
182
|
-
});
|
|
183
|
-
if (r.exitCode !== 0) {
|
|
184
|
-
console.error('[runSupermachineAuth.warmup] failed:', r.stdout.toString(), r.stderr.toString());
|
|
185
|
-
throw new Error(`warmup failed (exit ${r.exitCode})`);
|
|
186
|
-
}
|
|
187
|
-
},
|
|
188
|
-
...imageOpts,
|
|
189
|
-
});
|
|
190
|
-
console.error(`[runSupermachineAuth] bake: ${((performance.now() - tBake) / 1000).toFixed(1)} s`);
|
|
191
|
-
const pool = await image.pool({ min: 1, max: 1, restoreOnRelease: false });
|
|
192
|
-
const vm = await pool.acquire();
|
|
193
|
-
// Loose typing so we can call signal/writeStdin/readStdout/etc.
|
|
194
|
-
// without re-importing the full @supermachine/core types tree.
|
|
195
|
-
let forwarder = null;
|
|
196
|
-
let captureChild = null;
|
|
197
|
-
// Idempotent cleanup. Two design constraints:
|
|
198
|
-
// 1. SIGINT may fire multiple times (user hammers Ctrl-C), and
|
|
199
|
-
// cleanup() is async — a second invocation would otherwise
|
|
200
|
-
// race the first, calling signal/wait on already-disposed
|
|
201
|
-
// handles ("agent closed connection before sending EXIT").
|
|
202
|
-
// 2. Each step may throw on second call (already-closed sockets,
|
|
203
|
-
// already-released vm, etc.) — wrap individually so a later
|
|
204
|
-
// step still runs even if an earlier one's idempotency check
|
|
205
|
-
// threw something the catch missed.
|
|
206
|
-
// Implementation: a singleton promise — first caller does the
|
|
207
|
-
// work, every subsequent caller awaits the same promise.
|
|
208
|
-
let cleanupPromise = null;
|
|
209
|
-
const cleanup = () => {
|
|
210
|
-
if (cleanupPromise)
|
|
211
|
-
return cleanupPromise;
|
|
212
|
-
cleanupPromise = (async () => {
|
|
213
|
-
// Null each handle out after using it so a stray reference
|
|
214
|
-
// elsewhere can't be re-used.
|
|
215
|
-
const child = captureChild;
|
|
216
|
-
captureChild = null;
|
|
217
|
-
if (child)
|
|
218
|
-
await child.signal(15).catch(() => undefined);
|
|
219
|
-
const fwd = forwarder;
|
|
220
|
-
forwarder = null;
|
|
221
|
-
if (fwd)
|
|
222
|
-
await fwd.stop().catch(() => undefined);
|
|
223
|
-
await vm.release().catch(() => undefined);
|
|
224
|
-
await pool.shutdown().catch(() => undefined);
|
|
225
|
-
})();
|
|
226
|
-
return cleanupPromise;
|
|
227
|
-
};
|
|
228
|
-
// SIGINT / SIGTERM teardown — without these, Ctrl-C leaves the VM
|
|
229
|
-
// pinned and the next bake hits "snapshot in use" errors.
|
|
230
|
-
// First signal triggers cleanup + clean exit; second signal escalates
|
|
231
|
-
// to immediate process.exit so the user can always bail out.
|
|
232
|
-
let signalCount = 0;
|
|
233
|
-
const onSignal = (sig) => {
|
|
234
|
-
signalCount += 1;
|
|
235
|
-
if (signalCount >= 2) {
|
|
236
|
-
console.error(`\n[runSupermachineAuth] received ${sig} again — forcing exit`);
|
|
237
|
-
process.exit(130);
|
|
238
|
-
}
|
|
239
|
-
console.error(`\n[runSupermachineAuth] received ${sig}, cleaning up…`);
|
|
240
|
-
cleanup()
|
|
241
|
-
.catch(() => undefined)
|
|
242
|
-
.finally(() => process.exit(130));
|
|
243
|
-
};
|
|
244
|
-
process.on('SIGINT', onSignal);
|
|
245
|
-
process.on('SIGTERM', onSignal);
|
|
246
|
-
try {
|
|
247
|
-
// 0) Post-restore sanity. supermachine 0.7.28+ captures the
|
|
248
|
-
// auto-mount tree in the snapshot, so /workspace and
|
|
249
|
-
// /workspace/node_modules are already mounted on restore.
|
|
250
|
-
// Assert + bail if anything's off.
|
|
251
|
-
const mountR = await vm.exec({
|
|
252
|
-
argv: ['sh', '-c', `
|
|
253
|
-
mountpoint -q /workspace || { echo "FATAL: /workspace not mounted"; exit 1; }
|
|
254
|
-
mountpoint -q /workspace/node_modules || { echo "FATAL: /workspace/node_modules not mounted"; exit 1; }
|
|
255
|
-
NM_FS=\$(stat -f -c %T /workspace/node_modules 2>/dev/null)
|
|
256
|
-
if [ "\$NM_FS" = "virtiofs" ] || [ "\$NM_FS" = "fuse.virtiofs" ]; then
|
|
257
|
-
echo "FATAL: /workspace/node_modules is \$NM_FS — auto-mount layering broken"
|
|
258
|
-
exit 1
|
|
259
|
-
fi
|
|
260
|
-
ls /workspace/node_modules/@essential-apps/shopify-test-runner/dist/scripts/captureAuth.js >/dev/null \
|
|
261
|
-
|| { echo "FATAL: captureAuth.js missing in volume — snapshot/volume out of sync"; exit 1; }
|
|
262
|
-
`],
|
|
263
|
-
timeoutMs: 10_000,
|
|
264
|
-
});
|
|
265
|
-
if (mountR.exitCode !== 0) {
|
|
266
|
-
console.error(`[runSupermachineAuth] mount failed:\n${mountR.stdout.toString()}${mountR.stderr.toString()}`);
|
|
267
|
-
throw new Error('mount setup failed');
|
|
268
|
-
}
|
|
269
|
-
// 1) Start x11vnc inside the guest. The image's entrypoint.sh
|
|
270
|
-
// has the same logic gated on TEST_ONLINE_VNC=1, but that env is
|
|
271
|
-
// bake-time only (already snapshotted). Running x11vnc here
|
|
272
|
-
// sidesteps the need for a separate baked snapshot.
|
|
273
|
-
console.error(`[runSupermachineAuth] starting x11vnc on guest :5900…`);
|
|
274
|
-
const vncStart = await vm.exec({
|
|
275
|
-
argv: [
|
|
276
|
-
'bash',
|
|
277
|
-
'-c',
|
|
278
|
-
`
|
|
279
|
-
# No set -e — too many of these commands have valid nonzero
|
|
280
|
-
# exits (pkill matching 0 procs, rm-of-missing-file, etc.) and
|
|
281
|
-
# masking them all with || true was both noisy and unreliable.
|
|
282
|
-
# We explicitly check exit conditions on the things that
|
|
283
|
-
# matter (Xvfb socket present, x11vnc listening).
|
|
284
|
-
# Restart Xvfb on :99 with -ac (disable X access control)
|
|
285
|
-
# so x11vnc — which runs in a fresh shell here, separate from
|
|
286
|
-
# the entrypoint shell that started the original Xvfb — can
|
|
287
|
-
# attach without an Xauthority cookie. The entrypoint's Xvfb
|
|
288
|
-
# is fine for Playwright (which sets DISPLAY=:99 and inherits
|
|
289
|
-
# the auth context from the same shell), but x11vnc launched
|
|
290
|
-
# via a separate vm.exec doesn't have that.
|
|
291
|
-
echo "[xvfb] stopping any existing Xvfb on :99…"
|
|
292
|
-
# IMPORTANT: do NOT use 'pkill -f' here — the -f flag matches
|
|
293
|
-
# the full command line, and our own bash script's argv
|
|
294
|
-
# contains the literal string we'd search for (it's an
|
|
295
|
-
# embedded heredoc), so pkill would kill its own parent
|
|
296
|
-
# shell. Match by process name only.
|
|
297
|
-
pkill -x Xvfb 2>/dev/null || true
|
|
298
|
-
rm -f /tmp/.X11-unix/X99 /tmp/.X99-lock
|
|
299
|
-
sleep 0.3
|
|
300
|
-
# -ac: disable access control (no auth required). Safe inside
|
|
301
|
-
# the VM — only x11vnc here is going to connect, and x11vnc's
|
|
302
|
-
# own VNC auth (-rfbauth) gates external access.
|
|
303
|
-
# -nolisten tcp: still no TCP listener on Xvfb itself.
|
|
304
|
-
echo "[xvfb] starting Xvfb :99 -ac …"
|
|
305
|
-
nohup Xvfb :99 -screen 0 1600x1000x24 -nolisten tcp -ac \
|
|
306
|
-
>/var/log/xvfb.log 2>&1 &
|
|
307
|
-
for _ in $(seq 1 50); do
|
|
308
|
-
[ -e /tmp/.X11-unix/X99 ] && break
|
|
309
|
-
sleep 0.1
|
|
310
|
-
done
|
|
311
|
-
if [ ! -e /tmp/.X11-unix/X99 ]; then
|
|
312
|
-
echo "[xvfb] FAILED to bind /tmp/.X11-unix/X99 within 5s"
|
|
313
|
-
cat /var/log/xvfb.log
|
|
314
|
-
exit 1
|
|
315
|
-
fi
|
|
316
|
-
echo "[xvfb] up."
|
|
317
|
-
|
|
318
|
-
mkdir -p /root/.vnc
|
|
319
|
-
x11vnc -storepasswd "${vncPassword}" /root/.vnc/passwd >/dev/null 2>&1
|
|
320
|
-
# Background via shell (&) not x11vnc's -bg (which has been
|
|
321
|
-
# observed to fork before the accept loop binds). nohup so
|
|
322
|
-
# the listener survives this exec call returning.
|
|
323
|
-
echo "[x11vnc] starting on :${VNC_PORT}…"
|
|
324
|
-
nohup x11vnc -display :99 -forever -shared \
|
|
325
|
-
-rfbauth /root/.vnc/passwd -rfbport ${VNC_PORT} -quiet \
|
|
326
|
-
>/var/log/x11vnc.log 2>&1 &
|
|
327
|
-
VNC_PID=$!
|
|
328
|
-
echo "[x11vnc] pid $VNC_PID"
|
|
329
|
-
# Verify the listener actually bound. Use netstat (from
|
|
330
|
-
# net-tools — installed in both the supermachine and libkrun
|
|
331
|
-
# images per the Dockerfiles). bash /dev/tcp was tried first
|
|
332
|
-
# but ubuntu/jammy bash sometimes ships without the
|
|
333
|
-
# /dev/tcp/* virtual device enabled, leading to silent probe
|
|
334
|
-
# failures even when x11vnc IS listening.
|
|
335
|
-
for _ in $(seq 1 30); do
|
|
336
|
-
if netstat -ltn 2>/dev/null | grep -q ":${VNC_PORT} "; then
|
|
337
|
-
exit 0
|
|
338
|
-
fi
|
|
339
|
-
sleep 0.1
|
|
340
|
-
done
|
|
341
|
-
echo "x11vnc didn't bind :${VNC_PORT} within 3s"
|
|
342
|
-
echo "--- netstat output ---"
|
|
343
|
-
netstat -ltn 2>&1 || echo "(netstat unavailable)"
|
|
344
|
-
echo "--- x11vnc log ---"
|
|
345
|
-
cat /var/log/x11vnc.log
|
|
346
|
-
exit 1
|
|
347
|
-
`,
|
|
348
|
-
],
|
|
349
|
-
timeoutMs: 15_000,
|
|
350
|
-
});
|
|
351
|
-
if (vncStart.exitCode !== 0) {
|
|
352
|
-
console.error('[runSupermachineAuth] x11vnc failed:', vncStart.stdout.toString(), vncStart.stderr.toString());
|
|
353
|
-
throw new Error('x11vnc startup failed');
|
|
354
|
-
}
|
|
355
|
-
// 2) Forward host 127.0.0.1:5900 → guest :5900 so the macOS
|
|
356
|
-
// Screen Sharing client can reach the VNC server.
|
|
357
|
-
forwarder = await vm.exposeTcp(VNC_PORT, VNC_PORT);
|
|
358
|
-
console.error(`[runSupermachineAuth] forwarding host 127.0.0.1:${VNC_PORT} → guest :${VNC_PORT}`);
|
|
359
|
-
// 3) Open macOS Screen Sharing pointed at the forwarder. Detach
|
|
360
|
-
// so the parent process can carry on.
|
|
361
|
-
if (osPlatform() === 'darwin') {
|
|
362
|
-
console.error(`[runSupermachineAuth] VNC password (paste into Screen Sharing): ${vncPassword}`);
|
|
363
|
-
// Tiny delay so x11vnc accept-loop is warm before the client
|
|
364
|
-
// dials; otherwise Screen Sharing sometimes shows "connection
|
|
365
|
-
// refused" and the user has to retry.
|
|
366
|
-
await sleep(500);
|
|
367
|
-
console.error(`[runSupermachineAuth] Opening macOS Screen Sharing → vnc://localhost:${VNC_PORT}`);
|
|
368
|
-
console.error(`[runSupermachineAuth] (If nothing opens: open vnc://localhost:${VNC_PORT})`);
|
|
369
|
-
nodeSpawn('open', [`vnc://localhost:${VNC_PORT}`], {
|
|
370
|
-
stdio: 'ignore',
|
|
371
|
-
detached: true,
|
|
372
|
-
}).unref();
|
|
373
|
-
}
|
|
374
|
-
else {
|
|
375
|
-
console.error(`[runSupermachineAuth] Connect any VNC viewer to localhost:${VNC_PORT} (password: ${vncPassword}).`);
|
|
376
|
-
}
|
|
377
|
-
// 4) Spawn captureAuth.js inside the guest. It opens Chrome on
|
|
378
|
-
// DISPLAY=:99, prompts for Enter on stdin, then writes
|
|
379
|
-
// storageState.json (which lands on host disk via the
|
|
380
|
-
// workspace mount). We bridge host stdin to the guest child
|
|
381
|
-
// so the user's Enter keystroke reaches captureAuth's
|
|
382
|
-
// readline prompt.
|
|
383
|
-
console.error('');
|
|
384
|
-
console.error('━'.repeat(72));
|
|
385
|
-
console.error('Inside Screen Sharing:');
|
|
386
|
-
console.error(' 1. Log in to Shopify Partners (accounts.shopify.com/lookup).');
|
|
387
|
-
console.error(' 2. Then visit your test store admin');
|
|
388
|
-
console.error(' (e.g. https://admin.shopify.com/store/<your-store>).');
|
|
389
|
-
console.error(' If a Cloudflare "Verify you are human" page appears,');
|
|
390
|
-
console.error(' click through it. Without this step, cf_clearance');
|
|
391
|
-
console.error(' never lands in storageState and tests will still hit');
|
|
392
|
-
console.error(' Turnstile.');
|
|
393
|
-
console.error(' 3. Return here and press Enter to save & exit.');
|
|
394
|
-
console.error('━'.repeat(72));
|
|
395
|
-
console.error('');
|
|
396
|
-
captureChild = await vm.spawn({
|
|
397
|
-
argv: [
|
|
398
|
-
'sh',
|
|
399
|
-
'-c',
|
|
400
|
-
// tty=false here (no PTY) because we want the readline prompt
|
|
401
|
-
// to read from a plain stdin pipe — Chrome doesn't care, it
|
|
402
|
-
// reads DISPLAY from env.
|
|
403
|
-
`cd /workspace && DISPLAY=:99 node --env-file=.env.test node_modules/@essential-apps/shopify-test-runner/dist/scripts/captureAuth.js`,
|
|
404
|
-
],
|
|
405
|
-
env: { DISPLAY: ':99' },
|
|
406
|
-
});
|
|
407
|
-
// Bridge host stdin → guest captureAuth stdin (for the Enter
|
|
408
|
-
// prompt). Forwarder runs until the guest child exits.
|
|
409
|
-
process.stdin.setEncoding('utf8');
|
|
410
|
-
process.stdin.on('data', (chunk) => {
|
|
411
|
-
const buf = typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : chunk;
|
|
412
|
-
captureChild.writeStdin(buf).catch(() => undefined);
|
|
413
|
-
});
|
|
414
|
-
process.stdin.resume();
|
|
415
|
-
// Stream guest stdout/stderr to host for visibility.
|
|
416
|
-
const streamGuest = async (reader, out) => {
|
|
417
|
-
if (!reader)
|
|
418
|
-
return;
|
|
419
|
-
// eslint-disable-next-line no-constant-condition
|
|
420
|
-
while (true) {
|
|
421
|
-
const chunk = await reader().catch(() => null);
|
|
422
|
-
if (!chunk || chunk.length === 0)
|
|
423
|
-
return;
|
|
424
|
-
out.write(chunk);
|
|
425
|
-
}
|
|
426
|
-
};
|
|
427
|
-
// captureChild has readStdout / readStderr — both Promise<Buffer>
|
|
428
|
-
// chunks until EOF (zero-length).
|
|
429
|
-
const childAny = captureChild;
|
|
430
|
-
void streamGuest(childAny.readStdout, process.stdout);
|
|
431
|
-
void streamGuest(childAny.readStderr, process.stderr);
|
|
432
|
-
const result = await (childAny.wait?.() ?? Promise.resolve({ exitCode: 0 }));
|
|
433
|
-
if (result.exitCode === 0) {
|
|
434
|
-
console.error('');
|
|
435
|
-
console.error('[runSupermachineAuth] ✓ captureAuth completed successfully.');
|
|
436
|
-
console.error('[runSupermachineAuth] storageState.json written via workspace mount.');
|
|
437
|
-
}
|
|
438
|
-
else {
|
|
439
|
-
console.error(`[runSupermachineAuth] captureAuth exited with code ${result.exitCode}`);
|
|
440
|
-
}
|
|
441
|
-
await cleanup();
|
|
442
|
-
process.exit(result.exitCode);
|
|
443
|
-
}
|
|
444
|
-
catch (err) {
|
|
445
|
-
console.error('[runSupermachineAuth] fatal:', err.message);
|
|
446
|
-
await cleanup();
|
|
447
|
-
process.exit(1);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
main().catch(async (err) => {
|
|
451
|
-
console.error(err);
|
|
452
|
-
process.exit(1);
|
|
453
|
-
});
|
|
454
|
-
//# sourceMappingURL=runSupermachineAuth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"runSupermachineAuth.js","sourceRoot":"","sources":["../../src/scripts/runSupermachineAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { type ConfigEnv, type UserConfig } from 'vite';
|
|
2
|
-
/**
|
|
3
|
-
* Vite config used to serve a consuming app's backend for the
|
|
4
|
-
* OFFLINE-FULL suite via `vite dev` (instead of a prod build +
|
|
5
|
-
* remix-serve). `runOfflineFullTests` boots `vite --config <this>`.
|
|
6
|
-
*
|
|
7
|
-
* This is what makes offline onboarding zero-app-touch on the build
|
|
8
|
-
* side. A prod build runs the app's own vite.config, which for Vercel-
|
|
9
|
-
* hosted apps applies `vercelPreset()` and shards the server build so
|
|
10
|
-
* `remix-serve` can't boot it (the "vanilla build" problem). Build-only
|
|
11
|
-
* presets are INERT in dev, so serving via `vite dev` sidesteps it
|
|
12
|
-
* with no change to the app's vite.config.
|
|
13
|
-
*
|
|
14
|
-
* It loads the app's OWN config and overlays the offline necessities:
|
|
15
|
-
* - `server.hmr = false`: Vite dev injects HMR <script>/<link> tags
|
|
16
|
-
* that aren't in the SSR HTML → breaks React-18 hydration. Disabling
|
|
17
|
-
* HMR is what historically forced offline onto a prod build; turning
|
|
18
|
-
* it off here lets us serve via dev safely.
|
|
19
|
-
* - strip `basic-ssl`: the offline edge proxy + mocks expect a plain
|
|
20
|
-
* HTTP backend. Apps that add basicSsl in test mode would otherwise
|
|
21
|
-
* serve HTTPS. basic-ssl is a top-level plugin, so it's filterable
|
|
22
|
-
* (the Vercel preset isn't — it lives inside the remix() plugin —
|
|
23
|
-
* but it's build-only, so dev doesn't care). Dropping the plugin
|
|
24
|
-
* means no `server.https` is set, so the dev server is plain HTTP.
|
|
25
|
-
* - `optimizeDeps.entries`: pre-bundle every route's deps at startup
|
|
26
|
-
* so the first in-test navigation doesn't trigger Vite's on-demand
|
|
27
|
-
* re-optimize + iframe reload (same fix as the online suite).
|
|
28
|
-
*
|
|
29
|
-
* Generic + additive: never rewrites the app's plugins beyond dropping
|
|
30
|
-
* basic-ssl. Override the optimize glob with
|
|
31
|
-
* TEST_OFFLINE_VITE_OPTIMIZE_ENTRIES for apps with an unusual layout.
|
|
32
|
-
*/
|
|
33
|
-
export default function viteOfflineConfig(configEnv: ConfigEnv): Promise<UserConfig>;
|
|
34
|
-
//# sourceMappingURL=offlineConfig.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"offlineConfig.d.ts","sourceRoot":"","sources":["../../src/vite/offlineConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAA8B,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAgCzF"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { loadConfigFromFile, mergeConfig } from 'vite';
|
|
2
|
-
/**
|
|
3
|
-
* Vite config used to serve a consuming app's backend for the
|
|
4
|
-
* OFFLINE-FULL suite via `vite dev` (instead of a prod build +
|
|
5
|
-
* remix-serve). `runOfflineFullTests` boots `vite --config <this>`.
|
|
6
|
-
*
|
|
7
|
-
* This is what makes offline onboarding zero-app-touch on the build
|
|
8
|
-
* side. A prod build runs the app's own vite.config, which for Vercel-
|
|
9
|
-
* hosted apps applies `vercelPreset()` and shards the server build so
|
|
10
|
-
* `remix-serve` can't boot it (the "vanilla build" problem). Build-only
|
|
11
|
-
* presets are INERT in dev, so serving via `vite dev` sidesteps it
|
|
12
|
-
* with no change to the app's vite.config.
|
|
13
|
-
*
|
|
14
|
-
* It loads the app's OWN config and overlays the offline necessities:
|
|
15
|
-
* - `server.hmr = false`: Vite dev injects HMR <script>/<link> tags
|
|
16
|
-
* that aren't in the SSR HTML → breaks React-18 hydration. Disabling
|
|
17
|
-
* HMR is what historically forced offline onto a prod build; turning
|
|
18
|
-
* it off here lets us serve via dev safely.
|
|
19
|
-
* - strip `basic-ssl`: the offline edge proxy + mocks expect a plain
|
|
20
|
-
* HTTP backend. Apps that add basicSsl in test mode would otherwise
|
|
21
|
-
* serve HTTPS. basic-ssl is a top-level plugin, so it's filterable
|
|
22
|
-
* (the Vercel preset isn't — it lives inside the remix() plugin —
|
|
23
|
-
* but it's build-only, so dev doesn't care). Dropping the plugin
|
|
24
|
-
* means no `server.https` is set, so the dev server is plain HTTP.
|
|
25
|
-
* - `optimizeDeps.entries`: pre-bundle every route's deps at startup
|
|
26
|
-
* so the first in-test navigation doesn't trigger Vite's on-demand
|
|
27
|
-
* re-optimize + iframe reload (same fix as the online suite).
|
|
28
|
-
*
|
|
29
|
-
* Generic + additive: never rewrites the app's plugins beyond dropping
|
|
30
|
-
* basic-ssl. Override the optimize glob with
|
|
31
|
-
* TEST_OFFLINE_VITE_OPTIMIZE_ENTRIES for apps with an unusual layout.
|
|
32
|
-
*/
|
|
33
|
-
export default async function viteOfflineConfig(configEnv) {
|
|
34
|
-
const root = process.cwd();
|
|
35
|
-
const loaded = await loadConfigFromFile(configEnv, undefined, root);
|
|
36
|
-
if (!loaded?.config) {
|
|
37
|
-
throw new Error(`viteOfflineConfig: could not load the app's Vite config from ${root}. ` +
|
|
38
|
-
`Expected a vite.config.{ts,js,mjs,mts,…} at the repo root.`);
|
|
39
|
-
}
|
|
40
|
-
const appConfig = loaded.config;
|
|
41
|
-
// Drop basic-ssl (→ plain HTTP). Flatten one level since plugin
|
|
42
|
-
// entries can be nested arrays; keep everything that isn't basic-ssl
|
|
43
|
-
// (incl. falsy/Promise entries, which Vite tolerates).
|
|
44
|
-
const plugins = (appConfig.plugins ?? [])
|
|
45
|
-
.flat(Infinity)
|
|
46
|
-
.filter((p) => {
|
|
47
|
-
const name = p?.name;
|
|
48
|
-
return !(name && name.includes('basic-ssl'));
|
|
49
|
-
});
|
|
50
|
-
const entries = process.env['TEST_OFFLINE_VITE_OPTIMIZE_ENTRIES']
|
|
51
|
-
? process.env['TEST_OFFLINE_VITE_OPTIMIZE_ENTRIES']
|
|
52
|
-
.split(',')
|
|
53
|
-
.map((s) => s.trim())
|
|
54
|
-
.filter(Boolean)
|
|
55
|
-
: ['app/**/*.{ts,tsx,jsx,js}', '!app/**/*.server.*'];
|
|
56
|
-
return mergeConfig({ ...appConfig, plugins }, {
|
|
57
|
-
optimizeDeps: { entries },
|
|
58
|
-
server: { hmr: false },
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=offlineConfig.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"offlineConfig.js","sourceRoot":"","sources":["../../src/vite/offlineConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAmC,MAAM,MAAM,CAAC;AAExF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,CAAC,OAAO,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAoB;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC;IACpE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CACb,gEAAgE,IAAI,IAAI;YACtE,4DAA4D,CAC/D,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;IAEhC,gEAAgE;IAChE,qEAAqE;IACrE,uDAAuD;IACvD,MAAM,OAAO,GAAI,CAAC,SAAS,CAAC,OAAO,IAAI,EAAE,CAAe;SACrD,IAAI,CAAC,QAAa,CAAC;SACnB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACZ,MAAM,IAAI,GAAI,CAA0C,EAAE,IAAI,CAAC;QAC/D,OAAO,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/C,CAAC,CAA0B,CAAC;IAE9B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC;QAC/D,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC;aAC9C,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC;QACpB,CAAC,CAAC,CAAC,0BAA0B,EAAE,oBAAoB,CAAC,CAAC;IAEvD,OAAO,WAAW,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,EAAE;QAC5C,YAAY,EAAE,EAAE,OAAO,EAAE;QACzB,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE;KACF,CAAC,CAAC;AAC1B,CAAC"}
|