fix: route claudeqq notifications through k3s

This commit is contained in:
Codex
2026-05-16 18:06:06 +00:00
parent 919bdb6b4b
commit 611f287c12
15 changed files with 414 additions and 65 deletions
+88 -13
View File
@@ -94,6 +94,7 @@ const providerGatewayWsEgressProxyUrl = "http://127.0.0.1:18789";
const nativeK3sInstallVersion = "v1.34.1+k3s1";
const nativeK3sImage = "rancher/k3s:v1.34.1-k3s1";
const nativeK3sCtrAddress = "/run/k3s/containerd/containerd.sock";
const unideskRepoUrl = "https://github.com/pikasTech/unidesk";
function isHelpArg(value: string | undefined): boolean {
return value === "help" || value === "--help" || value === "-h";
@@ -180,6 +181,16 @@ function repoSlug(repo: string): string | null {
return null;
}
function isFullGitSha(value: string): boolean {
return /^[0-9a-f]{40}$/iu.test(value);
}
function isUnideskRepo(repo: string): boolean {
const desiredSlug = repoSlug(repo);
const unideskSlug = repoSlug(unideskRepoUrl);
return desiredSlug !== null && desiredSlug === unideskSlug;
}
function sshUrlForSlug(slug: string | null): string | null {
if (slug === null) return null;
const [host = "", ...pathParts] = slug.split("/");
@@ -208,7 +219,7 @@ function providerSourceRepoUrl(repo: string): string {
function localResolvedCommitForDesired(desired: DeployManifestService): string | null {
const desiredSlug = repoSlug(desired.repo);
if (desiredSlug === null || desired.commitId.length !== 40) return null;
if (desiredSlug === null || !isFullGitSha(desired.commitId)) return null;
const localOrigin = runCommand(["git", "remote", "get-url", "origin"], repoRoot);
const localOriginUrl = localOrigin.exitCode === 0 ? localOrigin.stdout.trim() : "";
if (localOriginUrl.length === 0 || repoSlug(localOriginUrl) !== desiredSlug) return null;
@@ -235,6 +246,7 @@ function runResolveGit(args: string[], cwd: string): ReturnType<typeof runComman
function resolveDesiredCommit(desired: DeployManifestService): DeployManifestService {
const localCommit = localResolvedCommitForDesired(desired);
if (localCommit !== null) return { ...desired, commitId: localCommit };
if (isFullGitSha(desired.commitId) && !isUnideskRepo(desired.repo)) return { ...desired, commitId: desired.commitId.toLowerCase() };
const cacheDir = repoResolveCacheDir(desired.repo);
mkdirSync(cacheDir, { recursive: true });
@@ -412,12 +424,32 @@ function targetExportDir(service: UniDeskMicroserviceConfig, runId: string): str
function targetWorkDir(service: UniDeskMicroserviceConfig): string {
if (service.deployment.mode === "k3sctl-managed") return k3sDeployDir;
if (targetIsMain(service) && service.repository.url === "https://github.com/pikasTech/unidesk") {
if (targetIsMain(service) && service.repository.url === unideskRepoUrl) {
return rootPath(".state", "deploy", "work", safeId(service.id));
}
return service.development.worktreePath;
}
function sourceWorkDir(service: UniDeskMicroserviceConfig): string {
if (service.deployment.mode === "k3sctl-managed" && service.repository.url !== unideskRepoUrl) {
return `${remoteDeployRoot}/work/${safeId(service.id)}`;
}
return targetWorkDir(service);
}
function sourceRootSubdir(service: UniDeskMicroserviceConfig): string {
const claudeqqPrefix = "claudeqq/";
if (service.id === "claudeqq" && service.repository.url !== unideskRepoUrl && service.repository.dockerfile.startsWith(claudeqqPrefix)) {
return "claudeqq";
}
return "";
}
function sourceBuildContext(service: UniDeskMicroserviceConfig): string {
const subdir = sourceRootSubdir(service);
return subdir.length > 0 ? `${sourceWorkDir(service)}/${subdir}` : sourceWorkDir(service);
}
function buildImageTag(service: UniDeskMicroserviceConfig): string {
if (service.deployment.mode === "k3sctl-managed") return `unidesk-${service.id}:d601`;
if (targetIsMain(service)) {
@@ -438,12 +470,12 @@ function directComposeEnvFile(service: UniDeskMicroserviceConfig): string {
}
function directBuildContextOverride(service: UniDeskMicroserviceConfig): string {
if (targetIsMain(service) && service.repository.url === "https://github.com/pikasTech/unidesk") return targetWorkDir(service);
if (targetIsMain(service) && service.repository.url === unideskRepoUrl) return targetWorkDir(service);
return "";
}
function directDockerfileOverride(service: UniDeskMicroserviceConfig): string {
if (targetIsMain(service) && service.repository.url === "https://github.com/pikasTech/unidesk") return service.repository.dockerfile;
if (targetIsMain(service) && service.repository.url === unideskRepoUrl) return service.repository.dockerfile;
return "";
}
@@ -453,8 +485,17 @@ function k8sManifestPath(service: UniDeskMicroserviceConfig): string {
return composeFile.replace(/\.k3s\.json$/u, ".k8s.yaml");
}
function sourceDockerfilePath(service: UniDeskMicroserviceConfig): string {
const claudeqqPrefix = "claudeqq/";
if (service.id === "claudeqq" && service.repository.url !== unideskRepoUrl && service.repository.dockerfile.startsWith(claudeqqPrefix)) {
return service.repository.dockerfile.slice(claudeqqPrefix.length);
}
return service.repository.dockerfile;
}
function sourceProxyPrelude(service: UniDeskMicroserviceConfig): string {
if (targetIsMain(service)) return "";
const strictHostKeyChecking = isUnideskRepo(service.repository.url) ? "yes" : "accept-new";
return [
`build_proxy=${shellQuote(providerGatewayWsEgressProxyUrl)}`,
"export HTTP_PROXY=\"$build_proxy\" HTTPS_PROXY=\"$build_proxy\" ALL_PROXY=\"$build_proxy\"",
@@ -521,7 +562,7 @@ while True:
"UNIDESK_GIT_SSH_PROXY",
"chmod 700 \"$git_ssh_proxy\"",
"export UNIDESK_GIT_SSH_HTTP_PROXY=\"$build_proxy\"",
"export GIT_SSH_COMMAND=\"ssh -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=$HOME/.ssh/known_hosts -i $HOME/.ssh/id_ed25519 -o 'ProxyCommand=$git_ssh_proxy %h %p'\"",
`export GIT_SSH_COMMAND="ssh -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=${strictHostKeyChecking} -o UserKnownHostsFile=$HOME/.ssh/known_hosts -i $HOME/.ssh/id_ed25519 -o 'ProxyCommand=$git_ssh_proxy %h %p'"`,
"curl -fsSI --max-time 20 -x \"$build_proxy\" https://github.com >/dev/null",
"echo target_source_proxy=provider-gateway-ws-egress:$build_proxy",
"echo target_build_proxy=provider-gateway-ws-egress:$build_proxy",
@@ -541,7 +582,7 @@ function buildCachePrelude(dockerfileVariable: string): string[] {
}
function prepareSourceScript(service: UniDeskMicroserviceConfig, desired: DeployManifestService, exportDir: string): string {
if (targetIsMain(service) && desired.repo === "https://github.com/pikasTech/unidesk") {
if (targetIsMain(service) && desired.repo === unideskRepoUrl) {
return [
"set -euo pipefail",
`repo=${shellQuote(repoRoot)}`,
@@ -577,11 +618,15 @@ function prepareSourceScript(service: UniDeskMicroserviceConfig, desired: Deploy
}
function syncSourceScript(service: UniDeskMicroserviceConfig, exportDir: string): string {
const workDir = targetWorkDir(service);
const workDir = sourceWorkDir(service);
const buildContext = sourceBuildContext(service);
const dockerfilePath = sourceDockerfilePath(service);
return [
"set -euo pipefail",
`export_dir=${shellQuote(exportDir)}`,
`work_dir=${shellQuote(workDir)}`,
`build_context=${shellQuote(buildContext)}`,
`dockerfile_path=${shellQuote(dockerfilePath)}`,
"mkdir -p \"$work_dir\"",
[
"rsync -a --delete",
@@ -593,27 +638,51 @@ function syncSourceScript(service: UniDeskMicroserviceConfig, exportDir: string)
"\"$export_dir/\"",
"\"$work_dir/\"",
].join(" "),
`test -f "$work_dir/${service.repository.dockerfile}"`,
"printf 'synced deploy worktree to %s\\n' \"$work_dir\"",
"test -f \"$build_context/$dockerfile_path\"",
"printf 'synced deploy worktree to %s\\nbuild_context=%s\\n' \"$work_dir\" \"$build_context\"",
].join("\n");
}
function syncK8sControlManifestsScript(service: UniDeskMicroserviceConfig): string {
if (service.deployment.mode !== "k3sctl-managed" || isUnideskRepo(service.repository.url)) return "";
const manifests = [service.repository.composeFile, k8sManifestPath(service)];
const commands = [
"set -euo pipefail",
`target_root=${shellQuote(targetWorkDir(service))}`,
"mkdir -p \"$target_root\"",
];
for (const relativePath of manifests) {
const absolutePath = rootPath(relativePath);
if (!existsSync(absolutePath)) throw new Error(`${service.id} k3s control manifest missing: ${relativePath}`);
const encoded = Buffer.from(readFileSync(absolutePath, "utf8"), "utf8").toString("base64");
commands.push(
`relative_path=${shellQuote(relativePath)}`,
`target_file="$target_root/$relative_path"`,
"mkdir -p \"$(dirname \"$target_file\")\"",
`printf %s ${shellQuote(encoded)} | base64 -d > "$target_file"`,
"printf 'synced_k3s_control_manifest=%s\\n' \"$target_file\"",
);
}
return commands.join("\n");
}
function buildImageScript(service: UniDeskMicroserviceConfig, desired: DeployManifestService, resolvedCommit: string): string {
const image = buildImageTag(service);
const workDir = targetWorkDir(service);
const dockerfile = `${workDir}/${service.repository.dockerfile}`;
const buildContext = sourceBuildContext(service);
const dockerfilePath = sourceDockerfilePath(service);
const dockerfile = `${buildContext}/${dockerfilePath}`;
const labelArgs = [
"--label", `unidesk.ai/service-id=${service.id}`,
"--label", `unidesk.ai/source-repo=${desired.repo}`,
"--label", `unidesk.ai/source-commit=${resolvedCommit}`,
"--label", `unidesk.ai/dockerfile=${service.repository.dockerfile}`,
"--label", `unidesk.ai/dockerfile=${dockerfilePath}`,
];
const commonArgs = [
"--progress=plain",
...labelArgs,
"-t", image,
"-f", dockerfile,
workDir,
buildContext,
];
const proxyBuildArgs = targetIsMain(service)
? []
@@ -1399,6 +1468,12 @@ async function applyOneService(config: UniDeskConfig, service: UniDeskMicroservi
const sync = await step(config, service, "sync-source", syncSourceScript(service, exportDir), targetIsMain(service) ? repoRoot : "/home/ubuntu", 90_000, false);
if (!pushStep(steps, sync)) return { ok: false, serviceId: service.id, startedAt, finishedAt: nowIso(), resolvedCommit, before, steps };
const controlManifestSyncScript = syncK8sControlManifestsScript(service);
if (controlManifestSyncScript.length > 0) {
const controlManifestSync = await step(config, service, "sync-k3s-control-manifests", controlManifestSyncScript, targetIsMain(service) ? repoRoot : "/home/ubuntu", 90_000, !targetIsMain(service));
if (!pushStep(steps, controlManifestSync)) return { ok: false, serviceId: service.id, startedAt, finishedAt: nowIso(), resolvedCommit, before, steps };
}
const buildScript = service.deployment.mode === "unidesk-direct"
? buildDirectImageScript(service, desired, resolvedCommit)
: buildImageScript(service, desired, resolvedCommit);