Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7df1727
feat: progress percentage, download retry, fallback chain tests, Cres…
sunnylqm Jun 26, 2026
82b0cbd
fix(e2e): resolve CLI entry from package.json instead of hardcoded li…
sunnylqm Jun 27, 2026
1f715b4
fix(e2e): add verbose logging to prepare script, inline diff calls
sunnylqm Jun 27, 2026
1152e8c
fix(e2e): use CLI subprocess for diff instead of in-process require
sunnylqm Jun 27, 2026
8e5579d
fix(e2e): install node-hdiffpatch to project dir for CLI subprocess
sunnylqm Jun 27, 2026
1f32fa5
fix(ci): trust wix/brew tap before installing applesimutils
sunnylqm Jun 27, 2026
d45a060
debug(e2e): add logging to diagnose warmServer artifact 404
sunnylqm Jun 27, 2026
e1ee479
debug(e2e): log resolved path and file existence in e2e server
sunnylqm Jun 27, 2026
47110ed
chore(e2e): remove debug logging from globalSetup and local-e2e-server
sunnylqm Jun 27, 2026
3834477
debug(e2e): add diagnostics for warmServer artifact 404
sunnylqm Jun 27, 2026
e4597e9
fix(e2e): add project node_modules to NODE_PATH for pushy hdiff
sunnylqm Jun 27, 2026
f73350c
debug(e2e): capture pushy hdiff stdout/stderr to diagnose silent failure
sunnylqm Jun 27, 2026
bafb393
fix(e2e): bypass CLI bin.ts for hdiff commands, call diff handlers di…
sunnylqm Jun 27, 2026
1e5201c
fix(e2e): improve hdiff wrapper with direct require, better logging
sunnylqm Jun 27, 2026
3c6202b
fix(e2e): resolve wrapper script from source dir, not __dirname
sunnylqm Jun 27, 2026
6cc460e
fix(e2e): pass customHdiffModule to bypass loadModule resolution
sunnylqm Jun 27, 2026
bb57cd4
fix(ci): remove accidental invalid e2e filename
sunnylqm Jun 27, 2026
40018c7
fix(ci): use cli hdiff path for e2e artifacts
sunnylqm Jun 27, 2026
c19a7db
fix(e2e): invoke hdiff commands directly
sunnylqm Jun 27, 2026
364a678
fix(e2e): load hdiff from cli dependencies
sunnylqm Jun 27, 2026
43bf268
fix(progress): clamp computed percentage
sunnylqm Jun 27, 2026
cff08d0
fix(e2e): install hdiff with bun
sunnylqm Jun 27, 2026
21fe062
fix(e2e): log and bound hdiff generation
sunnylqm Jun 27, 2026
b083d06
fix(e2e): run hdiff in child process
sunnylqm Jun 27, 2026
cce4b16
fix(e2e): fallback to full packages on linux android
sunnylqm Jun 27, 2026
975f258
fix(e2e): keep ios hdiff format compatible
sunnylqm Jun 27, 2026
8d20eee
fix(download): normalize retries and cover progress callback
sunnylqm Jun 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/e2e_ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
xcode-version: '26.4'

- name: Install applesimutils
run: HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew && HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils
run: brew trust wix/brew && HOMEBREW_NO_AUTO_UPDATE=1 brew install wix/brew/applesimutils

- name: Install e2etest dependencies
run: cd Example/e2etest && bun install --frozen-lockfile
Expand Down
17 changes: 17 additions & 0 deletions Example/e2etest/e2e/globalSetup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@ function ensurePreparedArtifacts(platform: string) {
}
}

function usesFullFallbackArtifacts(platform: string) {
const manifestPath = path.join(artifactsRoot, platform, 'manifest.json');
try {
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as {
fullFallback?: unknown;
};
return manifest.fullFallback === true;
} catch {
return false;
}
}

function startServer() {
const serverScript = path.join(projectRoot, 'scripts/local-e2e-server.ts');
fs.mkdirSync(artifactsRoot, { recursive: true });
Expand Down Expand Up @@ -202,12 +214,17 @@ async function warmServer(platform: 'ios' | 'android') {
'Local artifacts checkUpdate route',
);

const fullFallback = usesFullFallbackArtifacts(platform);
const artifactFiles = [
LOCAL_UPDATE_FILES.full,
LOCAL_UPDATE_FILES.ppkDiff,
...(fullFallback ? [LOCAL_UPDATE_FILES.ppkFull] : []),
...(platform === 'android'
? [LOCAL_UPDATE_FILES.apk, LOCAL_UPDATE_FILES.packageDiff]
: []),
...(platform === 'android' && fullFallback
? [LOCAL_UPDATE_FILES.packageFull]
: []),
];

for (const fileName of artifactFiles) {
Expand Down
31 changes: 1 addition & 30 deletions Example/e2etest/e2e/local-merge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ const RETRYABLE_RELOAD_TIMEOUT = 45000;
const MARK_SUCCESS_TIMEOUT = 30000;
const MARK_SUCCESS_SETTLE_MS = 1500;
const DOWNLOAD_SUCCESS_TIMEOUT = 120000;
const TRANSIENT_ERROR_TIMEOUT = 5000;
const MAX_CHECK_UPDATE_ATTEMPTS = 2;

function getDetoxLaunchArgs() {
Expand Down Expand Up @@ -47,30 +46,6 @@ async function waitForBundleLabel(
.withTimeout(timeoutMs);
}

async function matchesText(
testId: string,
text: string,
timeoutMs = TRANSIENT_ERROR_TIMEOUT,
) {
try {
await waitFor(element(by.id(testId)))
.toHaveText(text)
.withTimeout(timeoutMs);
return true;
} catch {
return false;
}
}

async function didHitTransientCheckError() {
const [hasCheckError, hasErrorEvent] = await Promise.all([
matchesText('last-check-status', 'lastCheckStatus: error'),
matchesText('last-event', 'lastEvent: errorChecking'),
]);

return hasCheckError && hasErrorEvent;
}

async function tapCheckUpdateAndWaitForBundleLabel(expectedLabel: string) {
let lastError: unknown;

Expand All @@ -88,11 +63,7 @@ async function tapCheckUpdateAndWaitForBundleLabel(expectedLabel: string) {
} catch (error) {
lastError = error;

const shouldRetry =
attempt < MAX_CHECK_UPDATE_ATTEMPTS &&
(await didHitTransientCheckError());

if (!shouldRetry) {
if (attempt >= MAX_CHECK_UPDATE_ATTEMPTS) {
throw error;
}

Expand Down
2 changes: 2 additions & 0 deletions Example/e2etest/e2e/localUpdateConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ export const LOCAL_UPDATE_LABELS = {

export const LOCAL_UPDATE_FILES = {
full: 'v1.ppk',
ppkFull: 'v2.ppk',
ppkDiff: 'v1-to-v2.ppk.patch',
packageFull: 'v3.ppk',
packageDiff: 'base-to-v3.apk.patch',
apk: 'app-release.apk',
} as const;
Expand Down
15 changes: 15 additions & 0 deletions Example/e2etest/scripts/local-e2e-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ const contentTypes: Record<string, string> = {
'.apk': 'application/vnd.android.package-archive',
};

function usesFullFallback(platform: string) {
const manifestPath = path.join(artifactsRoot, platform, 'manifest.json');
try {
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) as {
fullFallback?: unknown;
};
return manifest.fullFallback === true;
} catch {
return false;
}
}

function json(body: unknown, status = 200) {
return new Response(JSON.stringify(body), {
status,
Expand Down Expand Up @@ -57,6 +69,7 @@ function buildUpdateResponse(
origin: string,
) {
const assetBasePath = `${origin}/artifacts/${platform}`;
const fullFallback = usesFullFallback(platform);

if (!currentHash) {
return {
Expand All @@ -79,6 +92,7 @@ function buildUpdateResponse(
metaInfo: JSON.stringify({ stage: 'diff', platform }),
paths: [assetBasePath],
diff: LOCAL_UPDATE_FILES.ppkDiff,
...(fullFallback ? { full: LOCAL_UPDATE_FILES.ppkFull } : {}),
};
}

Expand All @@ -91,6 +105,7 @@ function buildUpdateResponse(
metaInfo: JSON.stringify({ stage: 'pdiff', platform }),
paths: [assetBasePath],
pdiff: LOCAL_UPDATE_FILES.packageDiff,
...(fullFallback ? { full: LOCAL_UPDATE_FILES.packageFull } : {}),
};
}

Expand Down
Loading
Loading