Skip to content

Feature/self hosted runner#326

Draft
TheDanniCraft wants to merge 17 commits into
masterfrom
feature/self-hosted-runner
Draft

Feature/self hosted runner#326
TheDanniCraft wants to merge 17 commits into
masterfrom
feature/self-hosted-runner

Conversation

@TheDanniCraft

Copy link
Copy Markdown
Owner

This pull request introduces a new "runner" build system and related infrastructure for cross-platform streaming support, along with several supporting improvements to the codebase, build scripts, and dependencies. The main focus is to enable building, packaging, and managing a standalone runner executable for Windows, Linux, and macOS, as well as to provide server actions and utilities for managing runners and stream sessions.

The most important changes are:

Runner Build System and Packaging:

  • Added a new script scripts/build-runner.ts to bundle the runner with esbuild, compile platform-specific executables using pkg, sign macOS binaries if possible, set Windows executable icons, and generate hashes for version tracking. Output binaries are placed in public/downloads/runner/ with a manifest (version.json).
  • Updated both Dockerfile and Dockerfile-preview to install the ldid tool for macOS ad-hoc signing, and to build both the app and runner in the build process. [1] [2]
  • Added new scripts in package.json for runner development and building (runner:dev, runner:build), and configured pkg assets for native modules. [1] [2]

Server Actions and Stream Session Management:

  • Added src/app/actions/runner.ts with server actions for runner creation, deletion, unlinking, stream session upserting, state management, and version manifest retrieval, including entitlement checks and editor access.

Testing, Utilities, and Extension Handling:

  • Added a script scripts/stream-test.ts to test RTMP streaming using FFmpeg.
  • Added a script scripts/bundle-extension.ts to bundle the Puppeteer extension for use with the runner.
  • Added a patch for puppeteer-stream to allow specifying a custom extension path.

Dependency and Test Configuration Updates:

  • Added/updated dependencies for streaming, browser automation, and building (@puppeteer/browsers, puppeteer, puppeteer-stream, fluent-ffmpeg, esbuild, pkg, etc.), and patched puppeteer-stream. [1] [2] [3] [4] [5]
  • Expanded Jest test matching to include tests under src/**/__tests__/.

@cranedock

cranedock Bot commented Jul 14, 2026

Copy link
Copy Markdown

The preview deployment for clipify is ready. 🟢

Open Preview | Open Build Logs | Open Application Logs

Last updated at: 2026-07-14 16:32:24 CET

Comment thread src/app/api/runner/enroll/start/route.ts Fixed
Comment thread src/runner/index.ts Fixed

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a self-hosted runner feature for Clipify, enabling users to stream overlays from their own hardware via a compiled runner executable. Key additions include runner management APIs, enrollment and heartbeat polling, a background streaming engine using Puppeteer and FFmpeg, and billing integration for the runner add-on. The review feedback highlights several critical security, performance, and reliability issues. These include a hardcoded encryption secret in production, a lack of rate limiting on the bootstrap endpoint, potential memory issues when downloading binaries, the use of an unreliable in-memory cache in serverless environments, sequential database updates, and potential resource leaks or crashes in the runner engine. Additionally, the reviewer noted missing native keyring assets in the pkg configuration, unhandled HTTP redirects in the updater, overlapping polling requests, and misplaced imports.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread src/app/lib/encryption.ts
Comment thread src/app/api/runner/bootstrap/route.ts
Comment thread src/app/api/runner/download/route.ts
Comment thread src/app/api/runner/preview/route.ts
Comment thread src/app/api/runner/heartbeat/route.ts
Comment thread src/runner/index.ts
Comment on lines +153 to +160
while (Date.now() < expiresAt) {
await sleep(pollIntervalMs);
const pollResponse = await fetch(`${apiBase}/api/runner/enroll/poll`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ deviceCode: enrollment.deviceCode }),
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the network drops or the server is temporarily unreachable during enrollment polling, the fetch call will throw an unhandled exception and crash the runner. Wrap the fetch call in a try/catch block to handle transient network errors gracefully.

		while (Date.now() < expiresAt) {
			await sleep(pollIntervalMs);
			let pollResponse;
			try {
				pollResponse = await fetch(`${apiBase}/api/runner/enroll/poll`, {
					method: "POST",
					headers: { "Content-Type": "application/json" },
					body: JSON.stringify({ deviceCode: enrollment.deviceCode }),
				});
			} catch (error) {
				console.warn("[Enrollment] Network error during polling, retrying...", error);
				continue;
			}

Comment thread package.json
Comment thread src/runner/updater.ts
Comment thread src/app/dashboard/runners/[id]/page.tsx
Comment thread src/app/actions/runner.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants