diff --git a/scripts/gitops-render.mjs b/scripts/gitops-render.mjs index dc471763..11c13555 100644 --- a/scripts/gitops-render.mjs +++ b/scripts/gitops-render.mjs @@ -5678,6 +5678,22 @@ function opencodePositiveInteger(value, fallback, label) { return value; } +function opencodeEgressProxyUrlForProfile(deploy, profile) { + const proxy = deploy?.lanes?.[profile]?.gitMirror?.egressProxy; + if (!proxy || proxy.required === false) return ""; + const serviceName = configString(proxy.serviceName); + const namespace = configString(proxy.namespace) || "platform-infra"; + const port = Number(proxy.port); + if (!serviceName || !Number.isInteger(port) || port <= 0) return ""; + return `http://${serviceName}.${namespace}.svc.cluster.local:${port}`; +} + +function opencodeEgressNoProxyForProfile(deploy, profile) { + const proxy = deploy?.lanes?.[profile]?.gitMirror?.egressProxy; + const entries = Array.isArray(proxy?.noProxy) ? proxy.noProxy.map(configString).filter(Boolean) : []; + return entries.length > 0 ? entries.join(",") : "localhost,127.0.0.1,::1,.svc,.svc.cluster.local,.cluster.local"; +} + function opencodeApiKeyEnvName(providerId) { const normalized = String(providerId || "provider").toUpperCase().replace(/[^A-Z0-9]+/gu, "_").replace(/^_+|_+$/gu, ""); return `OPENCODE_${normalized || "PROVIDER"}_API_KEY`; @@ -5747,6 +5763,8 @@ function opencodeServerManifest({ profile = "v03", source, deploy = null, catalo const configContent = opencodeConfigContent(opencodeConfig); const configSha256 = createHash("sha256").update(configContent).digest("hex"); const apiKeySecretRef = secretRefObjectForProfile(opencodeConfig.apiKeySecretRef, profile); + const opencodeApkProxyUrl = opencodeEgressProxyUrlForProfile(deploy, profile); + const opencodeApkNoProxy = opencodeEgressNoProxyForProfile(deploy, profile); const annotations = { "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs", "hwlab.pikastech.local/opencode-provider-profile": opencodeConfig.providerProfile, @@ -5816,12 +5834,20 @@ function opencodeServerManifest({ profile = "v03", source, deploy = null, catalo image: "ghcr.io/anomalyco/opencode:1.17.7", imagePullPolicy: "IfNotPresent", command: ["/bin/sh", "-ec"], - args: ["if ! command -v git >/dev/null 2>&1; then apk add --no-cache git; fi\nexec opencode serve --hostname 0.0.0.0 --port 4096"], + args: ["if ! command -v git >/dev/null 2>&1; then\n n=1\n until timeout 180s apk add --no-cache git; do\n if [ \"$n\" -ge 3 ]; then exit 1; fi\n n=$((n + 1))\n sleep 5\n done\nfi\nexec opencode serve --hostname 0.0.0.0 --port 4096"], workingDir: "/workspace", env: [ { name: "HOME", value: "/workspace" }, { name: "XDG_CONFIG_HOME", value: "/workspace/.config" }, { name: "XDG_DATA_HOME", value: "/workspace/.local/share" }, + ...(opencodeApkProxyUrl ? [ + { name: "HTTP_PROXY", value: opencodeApkProxyUrl }, + { name: "HTTPS_PROXY", value: opencodeApkProxyUrl }, + { name: "http_proxy", value: opencodeApkProxyUrl }, + { name: "https_proxy", value: opencodeApkProxyUrl }, + { name: "NO_PROXY", value: opencodeApkNoProxy }, + { name: "no_proxy", value: opencodeApkNoProxy } + ] : []), { name: "OPENCODE_CONFIG_CONTENT", value: configContent }, { name: opencodeConfig.apiKeyEnv, valueFrom: { secretKeyRef: apiKeySecretRef } }, { name: "OPENCODE_SERVER_USERNAME", valueFrom: { secretKeyRef: { name: authSecretName, key: "username" } } }, diff --git a/scripts/gitops-render.test.ts b/scripts/gitops-render.test.ts index 3c1677b4..2411912c 100644 --- a/scripts/gitops-render.test.ts +++ b/scripts/gitops-render.test.ts @@ -730,8 +730,10 @@ test("v03 render includes D518 secret-plane smoke on D518 gitops root", async () assert.match(opencodeDeployment.spec?.template?.metadata?.annotations?.["hwlab.pikastech.local/opencode-config-sha256"] ?? "", /^[a-f0-9]{64}$/u); const opencodeContainer = collectContainersFromItem(opencodeDeployment).find((container) => container.name === "opencode-server"); assert.deepEqual(opencodeContainer?.command, ["/bin/sh", "-ec"]); - assert.match(opencodeContainer?.args?.[0] ?? "", /apk add --no-cache git/u); + assert.match(opencodeContainer?.args?.[0] ?? "", /timeout 180s apk add --no-cache git/u); const opencodeEnvEntries = new Map((opencodeContainer?.env ?? []).map((entry) => [entry.name, entry])); + assert.equal(opencodeEnvEntries.get("HTTPS_PROXY")?.value, "http://sub2api-egress-proxy.platform-infra.svc.cluster.local:10808"); + assert.match(opencodeEnvEntries.get("NO_PROXY")?.value ?? "", /\.svc\.cluster\.local/u); assert.deepEqual(opencodeEnvEntries.get("OPENCODE_DSFLASH_GO_API_KEY")?.valueFrom?.secretKeyRef, { name: "hwlab-v03-code-agent-provider", key: "opencode-api-key", optional: true }); const opencodeConfig = JSON.parse(opencodeEnvEntries.get("OPENCODE_CONFIG_CONTENT")?.value ?? "{}"); assert.equal(opencodeConfig.model, "dsflash-go/deepseek-v4-flash");