mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-11-10 04:46:07 -08:00
* refactor(main): drop mining/anki main-deps builders * refactor(anilist): drop main-deps builders * refactor(jellyfin): drop main-deps builders * refactor(overlay): drop overlay and shortcut main-deps builders * refactor(main): drop ipc, tray, and osd main-deps builders * refactor(startup): drop startup main-deps builders * test(scripts): ignore stray local requests in AUR download test Also apply prettier to launcher/mpv.test.ts so format:check:src passes. * fix(shortcuts): forward overlay numeric selection hooks through the composer composeShortcutRuntimes only passed the digit callbacks, so the visible-overlay selection added in #78 never ran from the multi-copy/mine-sentence shortcuts. * fix(stats): skip mpv auto-connect when stats starts the immersion tracker The immersion-startup main-deps builder never forwarded shouldAutoConnectMpv, so background stats and stats CLI startup always connected to mpv. Drop the builder and pass the deps straight to the handler. * build(deps): bump follow-redirects override to 1.16.2 Resolves GHSA-mrwp-f3q8-3g9p (high), which fails the quality-gate bun audit --audit-level high step. * test(subtitles): cover the null-tokenization settle path in prefetch test The mock ignored the value the test resolved, so the null case never ran. * test(e2e): surface mpv crashes and install current mpv on macOS CI The harness IPC client never handled socket close, so a crashed mpv left commands pending until the 120s test timeout with an empty mpv.log. Reject pending commands on close, write mpv's own log via --log-file, and refresh Homebrew on macOS CI so the installed mpv build no longer depends on the runner image. * test(e2e): render mpv through cocoa-cb OpenGL on macOS mpv 0.41.0_12 with libplacebo 7.387.0 segfaults in gpu-next's MoltenVK path on GitHub's paravirtual macOS GPU on the first frame, so the E2E session never started. * test(e2e): name mpv-stdio.log in the mpv close diagnostic
98 lines
3.6 KiB
TypeScript
98 lines
3.6 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { test } from 'bun:test';
|
|
|
|
test.each([false, true])(
|
|
'AUR downloads handle empty release metadata, unavailable=%s',
|
|
async (unavailable) => {
|
|
const workflow = await readFile(
|
|
new URL('../.github/workflows/release.yml', import.meta.url),
|
|
'utf8',
|
|
);
|
|
const step = workflow
|
|
.split(' - name: Download release assets for AUR\n')[1]
|
|
?.split('\n - name:')[0];
|
|
const script = step?.split(' run: |\n')[1]?.replace(/^ /gm, '');
|
|
assert.ok(script, 'AUR download step must have a shell script');
|
|
|
|
const workspace = await mkdtemp(path.join(os.tmpdir(), 'subminer-aur-download-'));
|
|
const requests: string[] = [];
|
|
const files = new Map([
|
|
['SubMiner-0.20.0.AppImage', 'appimage bytes'],
|
|
['subminer', 'launcher bytes'],
|
|
['subminer-assets.tar.gz', 'optional assets bytes'],
|
|
]);
|
|
const server = Bun.serve({
|
|
hostname: '127.0.0.1',
|
|
port: 0,
|
|
fetch(request) {
|
|
const pathname = new URL(request.url).pathname;
|
|
// Ignore stray local probes of the ephemeral port; only count the script's downloads.
|
|
if (!pathname.startsWith('/ksyasuda/SubMiner/releases/download/')) {
|
|
return new Response('not found', { status: 404 });
|
|
}
|
|
requests.push(pathname);
|
|
if (unavailable || requests.length === 1) return new Response('try again', { status: 503 });
|
|
const name = pathname.split('/').at(-1);
|
|
const body = name ? files.get(name) : undefined;
|
|
return new Response(body ?? 'not found', { status: body ? 200 : 404 });
|
|
},
|
|
});
|
|
|
|
try {
|
|
const bin = path.join(workspace, 'bin');
|
|
await mkdir(bin);
|
|
await writeFile(
|
|
path.join(bin, 'gh'),
|
|
'#!/bin/sh\necho "no assets to download" >&2\nexit 1\n',
|
|
{ mode: 0o755 },
|
|
);
|
|
const output = path.join(workspace, 'output');
|
|
const proc = Bun.spawn(['bash', '-c', script], {
|
|
cwd: workspace,
|
|
env: {
|
|
...process.env,
|
|
PATH: `${bin}${path.delimiter}${process.env.PATH}`,
|
|
RELEASE_VERSION: 'v0.20.0',
|
|
GITHUB_SERVER_URL: server.url.origin,
|
|
GITHUB_REPOSITORY: 'ksyasuda/SubMiner',
|
|
GITHUB_OUTPUT: output,
|
|
},
|
|
stdout: 'pipe',
|
|
stderr: 'pipe',
|
|
});
|
|
const [status, stderr, stdout] = await Promise.all([
|
|
proc.exited,
|
|
new Response(proc.stderr).text(),
|
|
new Response(proc.stdout).text(),
|
|
]);
|
|
assert.equal(status, 0, stderr);
|
|
if (unavailable) {
|
|
assert.equal(requests.length, 4, 'failed downloads stop after three retries');
|
|
assert.match(await readFile(output, 'utf8'), /^skip=true$/m);
|
|
assert.match(stdout, /::warning::Unable to download/);
|
|
await assert.rejects(
|
|
readFile(path.join(workspace, '.tmp/aur-release-assets/SubMiner-0.20.0.AppImage')),
|
|
{ code: 'ENOENT' },
|
|
);
|
|
return;
|
|
}
|
|
for (const [name, body] of files) {
|
|
assert.equal(
|
|
await readFile(path.join(workspace, '.tmp/aur-release-assets', name), 'utf8'),
|
|
body,
|
|
);
|
|
assert.ok(requests.includes(`/ksyasuda/SubMiner/releases/download/v0.20.0/${name}`));
|
|
}
|
|
assert.equal(requests.length, 4, 'the first failed download must be retried');
|
|
assert.match(await readFile(output, 'utf8'), /^skip=false$/m);
|
|
} finally {
|
|
server.stop(true);
|
|
await rm(workspace, { recursive: true, force: true });
|
|
}
|
|
},
|
|
15_000,
|
|
);
|