From 16c16f6c233ac6ebecda247d224236eb7719a495 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 2 Jun 2026 21:08:08 +0100 Subject: [PATCH] fix: route ssh push for knot1.tangled.sh --- server/utils/sync-push.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/server/utils/sync-push.ts b/server/utils/sync-push.ts index 0f0162a..9096e9e 100644 --- a/server/utils/sync-push.ts +++ b/server/utils/sync-push.ts @@ -91,7 +91,7 @@ export async function syncPush(payload: PushPayload): Promise { const { gitSshCommand, cleanup } = await loadSshCommandForInstall(payload.installationId) sshCleanup = cleanup - const knotUrl = `ssh://git@${row.knot}/${row.tangledRepoDid}` + const knotUrl = `ssh://git@${sshHostForKnot(row.knot)}/${row.tangledRepoDid}` const pushRefspec = lastSynced ? `--force-with-lease=${payload.ref}:${lastSynced} ${payload.after}:${payload.ref}` : `+${payload.after}:${payload.ref}` @@ -145,6 +145,22 @@ function jsonbPath(ref: string): string { return `"${ref.replaceAll('"', '\\"')}"` } +/** + * Map a knot hostname (as stored on `sh.tangled.repo`) to the SSH host we + * actually push to. For the appview-hosted knot, the HTTPS XRPC endpoint is + * `knot1.tangled.sh` (Cloudflare-fronted) but SSH lives on `tangled.org`. + * Self-hosted knots serve both on the same host (their `knot` value may + * include a `:port` suffix for non-default SSH; git URL parsing handles it). + * + * The official UI does this same mapping in + * `appview/pages/templates/repo/empty.html`. If tangled adds more + * appview-hosted knots in future this'll need updating. + */ +function sshHostForKnot(knot: string): string { + if (knot === 'knot1.tangled.sh') return 'tangled.org' + return knot +} + async function markMappingError(mappingId: number, message: string): Promise { const db = useDb() await db.update(repoMapping) -- 2.51.2