feat: add opencode embedded webui
This commit is contained in:
@@ -982,6 +982,7 @@ function secretNameForProfile(secretName, profile) {
|
||||
if (secretName === "hwlab-cloud-api-dev-db") return `hwlab-cloud-api-${profile}-db`;
|
||||
if (secretName === "hwlab-code-agent-provider") return `hwlab-${profile}-code-agent-provider`;
|
||||
if (secretName === "hwlab-code-agent-codex-auth") return `hwlab-${profile}-code-agent-codex-auth`;
|
||||
if (secretName === "hwlab-opencode-server-auth") return `hwlab-${profile}-opencode-server-auth`;
|
||||
if (secretName === "hwlab-bootstrap-admin") return `hwlab-${profile}-bootstrap-admin`;
|
||||
return secretName;
|
||||
}
|
||||
@@ -5637,6 +5638,98 @@ function secretPlaneIssueLabelValue(issueRef) {
|
||||
return label;
|
||||
}
|
||||
|
||||
function opencodeServerManifest({ profile = "v03", source }) {
|
||||
assert.ok(isRuntimeLane(profile), `opencode-server profile must be a runtime lane, got ${profile}`);
|
||||
const namespace = namespaceNameForProfile(profile);
|
||||
const name = "opencode-server";
|
||||
const selector = {
|
||||
"app.kubernetes.io/name": name,
|
||||
"app.kubernetes.io/part-of": "hwlab",
|
||||
"hwlab.pikastech.local/environment": profile,
|
||||
"hwlab.pikastech.local/profile": profile
|
||||
};
|
||||
const labels = {
|
||||
...selector,
|
||||
"hwlab.pikastech.local/component": "opencode",
|
||||
"hwlab.pikastech.local/gitops-target": profile,
|
||||
"hwlab.pikastech.local/service-id": name,
|
||||
"hwlab.pikastech.local/source-commit": source.full
|
||||
};
|
||||
const annotations = { "hwlab.pikastech.local/rendered-by": "scripts/gitops-render.mjs" };
|
||||
const authSecretName = secretNameForProfile("hwlab-opencode-server-auth", profile);
|
||||
const configContent = JSON.stringify({ autoupdate: false, share: "disabled" });
|
||||
return {
|
||||
apiVersion: "v1",
|
||||
kind: "List",
|
||||
items: [
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "ServiceAccount",
|
||||
metadata: { name, namespace, labels, annotations }
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "PersistentVolumeClaim",
|
||||
metadata: { name: `${name}-data`, namespace, labels, annotations },
|
||||
spec: {
|
||||
accessModes: ["ReadWriteOnce"],
|
||||
resources: { requests: { storage: "8Gi" } }
|
||||
}
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Service",
|
||||
metadata: { name, namespace, labels, annotations },
|
||||
spec: {
|
||||
type: "ClusterIP",
|
||||
selector,
|
||||
ports: [{ name: "http", port: 4096, targetPort: "http" }]
|
||||
}
|
||||
},
|
||||
{
|
||||
apiVersion: "apps/v1",
|
||||
kind: "Deployment",
|
||||
metadata: { name, namespace, labels, annotations },
|
||||
spec: {
|
||||
replicas: 1,
|
||||
strategy: { type: "Recreate" },
|
||||
selector: { matchLabels: selector },
|
||||
template: {
|
||||
metadata: { labels, annotations },
|
||||
spec: {
|
||||
serviceAccountName: name,
|
||||
securityContext: { fsGroup: 1000, fsGroupChangePolicy: "OnRootMismatch" },
|
||||
containers: [{
|
||||
name,
|
||||
image: "ghcr.io/anomalyco/opencode:1.17.7",
|
||||
imagePullPolicy: "IfNotPresent",
|
||||
command: ["opencode"],
|
||||
args: ["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" },
|
||||
{ name: "OPENCODE_CONFIG_CONTENT", value: configContent },
|
||||
{ name: "OPENCODE_SERVER_USERNAME", valueFrom: { secretKeyRef: { name: authSecretName, key: "username" } } },
|
||||
{ name: "OPENCODE_SERVER_PASSWORD", valueFrom: { secretKeyRef: { name: authSecretName, key: "password" } } }
|
||||
],
|
||||
ports: [{ name: "http", containerPort: 4096 }],
|
||||
startupProbe: { tcpSocket: { port: "http" }, periodSeconds: 5, failureThreshold: 60 },
|
||||
readinessProbe: { tcpSocket: { port: "http" }, periodSeconds: 10, failureThreshold: 3 },
|
||||
livenessProbe: { tcpSocket: { port: "http" }, periodSeconds: 20, failureThreshold: 3 },
|
||||
resources: { requests: { cpu: "100m", memory: "256Mi" }, limits: { cpu: "1", memory: "1Gi" } },
|
||||
volumeMounts: [{ name: "workspace", mountPath: "/workspace" }]
|
||||
}],
|
||||
volumes: [{ name: "workspace", persistentVolumeClaim: { claimName: `${name}-data` } }]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
function requiredSecretPlaneString(value, label) {
|
||||
assert.equal(typeof value, "string", `${label} must be a string`);
|
||||
const trimmed = value.trim();
|
||||
@@ -5653,7 +5746,7 @@ function runtimeKustomization({ profile = "dev", includeDeviceAgent = profile ==
|
||||
if (externalPostgres) resources.push("external-postgres.yaml");
|
||||
else resources.push("postgres.yaml");
|
||||
if (workbenchRedis) resources.push("workbench-redis.yaml");
|
||||
resources.push("openfga.yaml", "observability.yaml");
|
||||
resources.push("openfga.yaml", "observability.yaml", "opencode.yaml");
|
||||
}
|
||||
if (includeDeviceAgent) resources.push("device-agent-71-freq.yaml");
|
||||
resources.push("node-frpc.yaml");
|
||||
@@ -5812,6 +5905,7 @@ async function plannedFiles(args) {
|
||||
if (workbenchRedis) putJson(`${runtimePath}/workbench-redis.yaml`, workbenchRuntimeRedisManifest({ profile, config: workbenchRedis, source }));
|
||||
if (isRuntimeLane(profile)) putJson(`${runtimePath}/openfga.yaml`, v02OpenFgaManifest({ profile, source }));
|
||||
if (isRuntimeLane(profile)) putJson(`${runtimePath}/observability.yaml`, observabilityManifest({ deploy, profile, namespace, labels: profileLabels, annotations, metricsSidecarScript }));
|
||||
if (isRuntimeLane(profile)) putJson(`${runtimePath}/opencode.yaml`, opencodeServerManifest({ profile, source }));
|
||||
if (includeDeviceAgent) putJson(`${runtimePath}/device-agent-71-freq.yaml`, deviceAgent71FreqManifest({ profile, source, registryPrefix: args.registryPrefix, catalog: artifactCatalog, useDeployImages: args.useDeployImages }));
|
||||
putJson(`${runtimePath}/node-frpc.yaml`, nodeFrpcManifest({ profile, source }));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user