feat: add GitHub Releases fallback for binary downloads

If cloakbrowser.dev is unreachable, automatically retry download
from GitHub Releases. Applies to both Python and JS wrappers.
This commit is contained in:
CloakHQ
2026-03-02 02:59:17 +01:00
parent 0bbc170747
commit 2f1f592b3a
5 changed files with 57 additions and 5 deletions
+6
View File
@@ -535,6 +535,12 @@ Set a custom download URL or use a local binary:
export CLOAKBROWSER_BINARY_PATH=/path/to/your/chrome export CLOAKBROWSER_BINARY_PATH=/path/to/your/chrome
``` ```
**macOS: "App is damaged" or Gatekeeper blocks launch**
The binary is ad-hoc signed. macOS quarantines downloaded files. Run once to clear it:
```bash
xattr -cr ~/.cloakbrowser/chromium-*/Chromium.app
```
**"playwright install" vs CloakBrowser binary** **"playwright install" vs CloakBrowser binary**
You do NOT need `playwright install chromium`. CloakBrowser downloads its own binary. You only need Playwright's system deps: You do NOT need `playwright install chromium`. CloakBrowser downloads its own binary. You only need Playwright's system deps:
```bash ```bash
+11
View File
@@ -179,6 +179,10 @@ DOWNLOAD_BASE_URL = os.environ.get(
GITHUB_API_URL = "https://api.github.com/repos/CloakHQ/cloakbrowser/releases" GITHUB_API_URL = "https://api.github.com/repos/CloakHQ/cloakbrowser/releases"
GITHUB_DOWNLOAD_BASE_URL = (
"https://github.com/CloakHQ/cloakbrowser/releases/download"
)
def get_download_url(version: str | None = None) -> str: def get_download_url(version: str | None = None) -> str:
"""Return the full download URL for the current platform's binary archive.""" """Return the full download URL for the current platform's binary archive."""
@@ -187,6 +191,13 @@ def get_download_url(version: str | None = None) -> str:
return f"{DOWNLOAD_BASE_URL}/chromium-v{v}/cloakbrowser-{tag}.tar.gz" return f"{DOWNLOAD_BASE_URL}/chromium-v{v}/cloakbrowser-{tag}.tar.gz"
def get_fallback_download_url(version: str | None = None) -> str:
"""Return the GitHub Releases fallback URL for the binary archive."""
v = version or CHROMIUM_VERSION
tag = get_platform_tag()
return f"{GITHUB_DOWNLOAD_BASE_URL}/chromium-v{v}/cloakbrowser-{tag}.tar.gz"
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Local binary override (skip download, use your own build) # Local binary override (skip download, use your own build)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
+18 -3
View File
@@ -30,6 +30,7 @@ from .config import (
get_cache_dir, get_cache_dir,
get_download_url, get_download_url,
get_effective_version, get_effective_version,
get_fallback_download_url,
get_local_binary_override, get_local_binary_override,
get_platform_tag, get_platform_tag,
) )
@@ -102,8 +103,13 @@ def ensure_binary() -> str:
def _download_and_extract(version: str | None = None) -> None: def _download_and_extract(version: str | None = None) -> None:
"""Download the binary archive and extract to cache directory.""" """Download the binary archive and extract to cache directory.
url = get_download_url(version)
Tries the primary server (cloakbrowser.dev) first, falls back to
GitHub Releases if the primary is unreachable or returns an error.
"""
primary_url = get_download_url(version)
fallback_url = get_fallback_download_url(version)
binary_dir = get_binary_dir(version) binary_dir = get_binary_dir(version)
binary_path = get_binary_path(version) binary_path = get_binary_path(version)
@@ -115,7 +121,16 @@ def _download_and_extract(version: str | None = None) -> None:
tmp_path = Path(tmp.name) tmp_path = Path(tmp.name)
try: try:
_download_file(url, tmp_path) # Try primary, fall back to GitHub Releases
try:
_download_file(primary_url, tmp_path)
except Exception as primary_err:
logger.warning(
"Primary download failed (%s), trying GitHub Releases...",
primary_err,
)
_download_file(fallback_url, tmp_path)
_extract_archive(tmp_path, binary_dir, binary_path) _extract_archive(tmp_path, binary_dir, binary_path)
logger.info("Visit https://cloakbrowser.dev for docs and release notifications.") logger.info("Visit https://cloakbrowser.dev for docs and release notifications.")
logger.info("Issues? https://github.com/CloakHQ/CloakBrowser/issues") logger.info("Issues? https://github.com/CloakHQ/CloakBrowser/issues")
+9
View File
@@ -91,12 +91,21 @@ export const DOWNLOAD_BASE_URL =
export const GITHUB_API_URL = export const GITHUB_API_URL =
"https://api.github.com/repos/CloakHQ/cloakbrowser/releases"; "https://api.github.com/repos/CloakHQ/cloakbrowser/releases";
export const GITHUB_DOWNLOAD_BASE_URL =
"https://github.com/CloakHQ/cloakbrowser/releases/download";
export function getDownloadUrl(version?: string): string { export function getDownloadUrl(version?: string): string {
const v = version || CHROMIUM_VERSION; const v = version || CHROMIUM_VERSION;
const tag = getPlatformTag(); const tag = getPlatformTag();
return `${DOWNLOAD_BASE_URL}/chromium-v${v}/cloakbrowser-${tag}.tar.gz`; return `${DOWNLOAD_BASE_URL}/chromium-v${v}/cloakbrowser-${tag}.tar.gz`;
} }
export function getFallbackDownloadUrl(version?: string): string {
const v = version || CHROMIUM_VERSION;
const tag = getPlatformTag();
return `${GITHUB_DOWNLOAD_BASE_URL}/chromium-v${v}/cloakbrowser-${tag}.tar.gz`;
}
export function getEffectiveVersion(): string { export function getEffectiveVersion(): string {
const marker = path.join(getCacheDir(), "latest_version"); const marker = path.join(getCacheDir(), "latest_version");
try { try {
+13 -2
View File
@@ -21,6 +21,7 @@ import {
getCacheDir, getCacheDir,
getDownloadUrl, getDownloadUrl,
getEffectiveVersion, getEffectiveVersion,
getFallbackDownloadUrl,
getLocalBinaryOverride, getLocalBinaryOverride,
getPlatformTag, getPlatformTag,
versionNewer, versionNewer,
@@ -135,7 +136,8 @@ export async function checkForUpdate(): Promise<string | null> {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function downloadAndExtract(version?: string): Promise<void> { async function downloadAndExtract(version?: string): Promise<void> {
const url = getDownloadUrl(version); const primaryUrl = getDownloadUrl(version);
const fallbackUrl = getFallbackDownloadUrl(version);
const binaryDir = getBinaryDir(version); const binaryDir = getBinaryDir(version);
const binaryPath = getBinaryPath(version); const binaryPath = getBinaryPath(version);
@@ -149,7 +151,16 @@ async function downloadAndExtract(version?: string): Promise<void> {
); );
try { try {
await downloadFile(url, tmpPath); // Try primary server, fall back to GitHub Releases
try {
await downloadFile(primaryUrl, tmpPath);
} catch (primaryErr) {
console.warn(
`[cloakbrowser] Primary download failed (${primaryErr instanceof Error ? primaryErr.message : primaryErr}), trying GitHub Releases...`
);
await downloadFile(fallbackUrl, tmpPath);
}
await extractArchive(tmpPath, binaryDir, binaryPath); await extractArchive(tmpPath, binaryDir, binaryPath);
console.log( console.log(
`[cloakbrowser] Visit https://cloakbrowser.dev for docs and release notifications.` `[cloakbrowser] Visit https://cloakbrowser.dev for docs and release notifications.`