From c24c0fac45fbc78621d40053a0bde577410921d8 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Sun, 1 Mar 2026 21:21:23 -0800 Subject: [PATCH] Refactor env vars: rename DATA_DIR to DATA_ROOT, add APP_URL --- apps/git/index.tsx | 8 ++-- scripts/deploy.sh | 5 +- scripts/migrate.ts | 111 --------------------------------------------- src/server/apps.ts | 4 +- 4 files changed, 8 insertions(+), 120 deletions(-) delete mode 100644 scripts/migrate.ts diff --git a/apps/git/index.tsx b/apps/git/index.tsx index e2ca0a2..5868d3e 100644 --- a/apps/git/index.tsx +++ b/apps/git/index.tsx @@ -6,11 +6,12 @@ import { mkdir, readdir, rename, rm, stat } from 'fs/promises' import { join, resolve } from 'path' import type { Child } from 'hono/jsx' +const APP_URL = process.env.APP_URL! const APPS_DIR = process.env.APPS_DIR! -const DATA_DIR = process.env.DATA_DIR! +const DATA_ROOT = process.env.DATA_ROOT! const TOES_URL = process.env.TOES_URL! -const REPOS_DIR = resolve(DATA_DIR, 'repos') +const REPOS_DIR = resolve(DATA_ROOT, 'repos') const VALID_NAME = /^[a-zA-Z0-9_-]+$/ const app = new Hype({ prettyHTML: false, layout: false }) @@ -633,8 +634,7 @@ app.on('POST', ['/:repo{.+\\.git}/git-receive-pack', '/:repo/git-receive-pack'], app.get('/', async c => { const appName = c.req.query('app') - const host = c.req.header('host') ?? 'git.toes.local' - const baseUrl = `http://${host}` + const baseUrl = APP_URL // When viewing a specific app, only show that app's repo if (appName) { diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 9f286b5..8b6e956 100755 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -21,9 +21,6 @@ REPOS_DIR="$DATA_DIR/repos" cd "$DEST" && git checkout -- bun.lock && git pull origin main && bun install && rm -rf dist && bun run build -echo "=> Migrating apps to flat structure..." -bun run scripts/migrate.ts - echo "=> Syncing default apps..." for app_dir in "$DEST"/apps/*/; do app=$(basename "$app_dir") @@ -35,7 +32,7 @@ for app_dir in "$DEST"/apps/*/; do (cd "$target" && bun install --frozen-lockfile 2>/dev/null || bun install) done -echo "=> Initializing bare repos for shipped apps..." +echo "=> Initializing bare repos..." mkdir -p "$REPOS_DIR" for app_dir in "$DEST"/apps/*/; do app=$(basename "$app_dir") diff --git a/scripts/migrate.ts b/scripts/migrate.ts deleted file mode 100644 index 6249e9f..0000000 --- a/scripts/migrate.ts +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env bun - -// Migration script: converts apps from versioned directory structure -// (apps/// with `current` symlink) to flat structure (apps//). -// -// Usage: bun run remote:migrate -// -// What it does: -// 1. Scans APPS_DIR for apps with a `current` symlink -// 2. Resolves the symlink to find the active version directory -// 3. Moves files from the active version into the app root (preserving node_modules/logs) -// 4. Removes old version directories and the symlink -// -// Safe to run multiple times -- skips apps already in flat structure. - -import { existsSync, mkdirSync, readdirSync, renameSync, lstatSync, readlinkSync, rmSync } from 'fs' -import { join, resolve } from 'path' - -const APPS_DIR = process.env.APPS_DIR ?? join(process.env.HOME!, 'apps') -const VERSION_RE = /^\d{8}-\d{6}$/ - -if (!existsSync(APPS_DIR)) { - console.error(`APPS_DIR does not exist: ${APPS_DIR}`) - process.exit(1) -} - -const apps = readdirSync(APPS_DIR, { withFileTypes: true }) - .filter(e => e.isDirectory()) - .map(e => e.name) - -let migrated = 0 -let skipped = 0 - -for (const name of apps) { - const appDir = join(APPS_DIR, name) - const currentLink = join(appDir, 'current') - - // Already flat -- has package.json at root with no current symlink - if (!existsSync(currentLink)) { - if (existsSync(join(appDir, 'package.json'))) { - skipped++ - } - continue - } - - // Verify it's actually a symlink - let stat - try { - stat = lstatSync(currentLink) - } catch { - continue - } - - if (!stat.isSymbolicLink()) { - console.warn(` [skip] ${name}: 'current' exists but is not a symlink`) - skipped++ - continue - } - - // Resolve the symlink to get the active version directory - const target = readlinkSync(currentLink) - const activeDir = resolve(appDir, target) - - if (!existsSync(activeDir)) { - console.warn(` [skip] ${name}: symlink target does not exist: ${target}`) - skipped++ - continue - } - - console.log(` [migrate] ${name} (active version: ${target})`) - - // Collect all version directories and other entries - const entries = readdirSync(appDir, { withFileTypes: true }) - const versionDirs = entries - .filter(e => e.isDirectory() && VERSION_RE.test(e.name) && e.name !== target) - .map(e => e.name) - - // Remove old (non-active) version directories first - for (const ver of versionDirs) { - const verPath = join(appDir, ver) - rmSync(verPath, { recursive: true, force: true }) - console.log(` removed old version: ${ver}`) - } - - // Remove the current symlink - rmSync(currentLink) - - // Move files from active version directory into app root - const activeEntries = readdirSync(activeDir) - for (const entry of activeEntries) { - const src = join(activeDir, entry) - const dest = join(appDir, entry) - - // Skip if destination already exists (e.g. node_modules, logs at root level) - if (existsSync(dest)) { - console.log(` skip (exists): ${entry}`) - continue - } - - renameSync(src, dest) - } - - // Clean up the now-empty active version directory - rmSync(activeDir, { recursive: true, force: true }) - - migrated++ - console.log(` done`) -} - -console.log() -console.log(`Migration complete: ${migrated} migrated, ${skipped} skipped`) diff --git a/src/server/apps.ts b/src/server/apps.ts index 856e9b4..b8a4c8e 100644 --- a/src/server/apps.ts +++ b/src/server/apps.ts @@ -16,6 +16,8 @@ export type { AppState } from '@types' export const APPS_DIR = process.env.APPS_DIR ?? resolve(join(process.env.DATA_DIR ?? '.', 'apps')) export const TOES_DIR = process.env.TOES_DIR ?? join(process.env.DATA_DIR ?? '.', 'toes') +const dataRoot = process.env.DATA_DIR ?? '.' + const defaultHost = process.env.NODE_ENV === 'production' ? LOCAL_HOST : 'localhost' export const TOES_URL = process.env.TOES_URL ?? `http://${defaultHost}:${process.env.PORT || 3000}` @@ -622,7 +624,7 @@ async function runApp(dir: string, port: number) { const proc = Bun.spawn(['bun', 'run', 'toes'], { cwd, - env: { ...process.env, ...appEnv, PORT: String(port), NO_AUTOPORT: 'true', APP_URL: buildAppUrl(dir, TOES_URL), APPS_DIR, DATA_DIR: dataDir, TOES_DIR, TOES_URL }, + env: { ...process.env, ...appEnv, PORT: String(port), NO_AUTOPORT: 'true', APP_URL: buildAppUrl(dir, TOES_URL), APPS_DIR, DATA_DIR: dataDir, DATA_ROOT: dataRoot, TOES_DIR, TOES_URL }, stdout: 'pipe', stderr: 'pipe', })