fix: seed opencode runtime image with git

This commit is contained in:
Codex
2026-06-30 13:11:56 +00:00
parent b92ceffda9
commit 94165a3d6a
3 changed files with 90 additions and 15 deletions
+15
View File
@@ -476,6 +476,11 @@ lanes:
builderImage: golang:1.25-bookworm
goProxy: https://goproxy.cn,direct
dockerNetworkMode: host
- id: opencode-git
kind: opencode-git
target: 127.0.0.1:5000/hwlab/opencode:1.17.7-git
sourceImage: ghcr.io/anomalyco/opencode:1.17.7
dockerNetworkMode: host
public:
webUrl: https://hwlab.pikapython.com
apiUrl: https://hwlab.pikapython.com
@@ -750,6 +755,11 @@ lanes:
builderImage: golang:1.25-bookworm
goProxy: https://goproxy.cn,direct
dockerNetworkMode: host
- id: opencode-git
kind: opencode-git
target: 127.0.0.1:5000/hwlab/opencode:1.17.7-git
sourceImage: ghcr.io/anomalyco/opencode:1.17.7
dockerNetworkMode: host
public:
webUrl: https://hwlab.pikapython.com
apiUrl: https://hwlab.pikapython.com
@@ -1101,6 +1111,11 @@ lanes:
builderImage: golang:1.25-bookworm
goProxy: https://goproxy.cn,direct
dockerNetworkMode: host
- id: opencode-git
kind: opencode-git
target: 127.0.0.1:5000/hwlab/opencode:1.17.7-git
sourceImage: ghcr.io/anomalyco/opencode:1.17.7
dockerNetworkMode: host
public:
webUrl: https://hwlab.pikapython.com
apiUrl: https://hwlab.pikapython.com
+16 -6
View File
@@ -313,12 +313,13 @@ export interface HwlabRuntimeImageRewriteSpec {
export interface HwlabRuntimeImageBuildSpec {
readonly id: string;
readonly kind: "moonbridge";
readonly kind: "moonbridge" | "opencode-git";
readonly target: string;
readonly sourceRepo: string;
readonly sourceRef: string;
readonly builderImage: string;
readonly goProxy: string;
readonly sourceImage?: string;
readonly sourceRepo?: string;
readonly sourceRef?: string;
readonly builderImage?: string;
readonly goProxy?: string;
readonly dockerNetworkMode: "default" | "host";
}
@@ -1569,7 +1570,16 @@ function runtimeImageBuildsConfig(value: unknown, path: string): HwlabRuntimeIma
const itemPath = `${path}[${index}]`;
const raw = asRecord(item, itemPath);
const kind = stringField(raw, "kind", itemPath);
if (kind !== "moonbridge") throw new Error(`${itemPath}.kind must be moonbridge`);
if (kind !== "moonbridge" && kind !== "opencode-git") throw new Error(`${itemPath}.kind must be moonbridge or opencode-git`);
if (kind === "opencode-git") {
return {
id: stringField(raw, "id", itemPath),
kind,
target: stringField(raw, "target", itemPath),
sourceImage: stringField(raw, "sourceImage", itemPath),
dockerNetworkMode: enumStringField(raw, "dockerNetworkMode", itemPath, ["default", "host"]),
};
}
return {
id: stringField(raw, "id", itemPath),
kind,
+59 -9
View File
@@ -847,7 +847,7 @@ interface NodeRuntimeImageDependency {
id: string;
target: string;
source: string;
mode: "pull" | "build-moonbridge";
mode: "pull" | "build-moonbridge" | "build-opencode-git";
sourceRepo?: string;
sourceRef?: string;
builderImage?: string;
@@ -866,15 +866,25 @@ function nodeRuntimeImageDependencies(spec: HwlabRuntimeLaneSpec): NodeRuntimeIm
images.push({ id: `rewrite-${index + 1}`, target: rewrite.target, source: rewrite.source, mode: "pull" });
});
spec.runtimeImageBuilds.forEach((build) => {
if (build.kind === "moonbridge") {
images.push({
id: build.id,
target: build.target,
source: `${build.sourceRepo}#${build.sourceRef}`,
mode: "build-moonbridge",
sourceRepo: build.sourceRepo,
sourceRef: build.sourceRef,
builderImage: build.builderImage,
goProxy: build.goProxy,
dockerNetworkMode: build.dockerNetworkMode,
});
return;
}
images.push({
id: build.id,
target: build.target,
source: `${build.sourceRepo}#${build.sourceRef}`,
mode: "build-moonbridge",
sourceRepo: build.sourceRepo,
sourceRef: build.sourceRef,
builderImage: build.builderImage,
goProxy: build.goProxy,
source: build.sourceImage ?? "",
mode: "build-opencode-git",
dockerNetworkMode: build.dockerNetworkMode,
});
});
@@ -1051,7 +1061,7 @@ export function ensureNodeBaseImage(spec: HwlabRuntimeLaneSpec, dryRun: boolean,
" if [ \"$present\" = false ]; then",
" action=seed",
" if [ \"$dry_run\" = false ]; then",
" if [ \"$mode\" = build-moonbridge ]; then",
" if [ \"$mode\" = build-moonbridge ]; then",
" action=build",
" source_present_before=build-source",
" effective_build_container_http_proxy=\"$build_container_http_proxy\"",
@@ -1106,6 +1116,46 @@ export function ensureNodeBaseImage(spec: HwlabRuntimeLaneSpec, dryRun: boolean,
" failed=true",
" fi",
" rm -rf \"$tmpdir\"",
" elif [ \"$mode\" = build-opencode-git ]; then",
" action=build",
" source_present_before=false",
" if [ -n \"$source\" ] && docker image inspect \"$source\" >/dev/null 2>&1; then source_present_before=true; fi",
" effective_build_container_http_proxy=\"$build_container_http_proxy\"",
" effective_build_container_https_proxy=\"$build_container_https_proxy\"",
" effective_build_container_all_proxy=\"$build_container_all_proxy\"",
" effective_docker_build_add_host_args=\"$docker_build_add_host_args\"",
" if [ \"$docker_network_mode\" = host ]; then",
" effective_build_container_http_proxy=\"$build_http_proxy\"",
" effective_build_container_https_proxy=\"$build_https_proxy\"",
" effective_build_container_all_proxy=\"$build_all_proxy\"",
" effective_docker_build_add_host_args=\"\"",
" fi",
" tmpdir=$(mktemp -d /tmp/hwlab-node-runtime-image-$id.XXXXXX)",
" dockerfile=\"$tmpdir/Dockerfile\"",
" cat > \"$dockerfile\" <<'DOCKERFILE'",
"ARG SOURCE_IMAGE",
"FROM ${SOURCE_IMAGE}",
"ARG HTTP_PROXY",
"ARG HTTPS_PROXY",
"ARG ALL_PROXY",
"ARG NO_PROXY",
"ENV HTTP_PROXY=${HTTP_PROXY}",
"ENV HTTPS_PROXY=${HTTPS_PROXY}",
"ENV ALL_PROXY=${ALL_PROXY}",
"ENV NO_PROXY=${NO_PROXY}",
"ENV http_proxy=${HTTP_PROXY}",
"ENV https_proxy=${HTTPS_PROXY}",
"ENV all_proxy=${ALL_PROXY}",
"ENV no_proxy=${NO_PROXY}",
"RUN apk add --no-cache git",
"DOCKERFILE",
" if env HTTP_PROXY=\"$build_http_proxy\" HTTPS_PROXY=\"$build_https_proxy\" ALL_PROXY=\"$build_all_proxy\" NO_PROXY=\"$build_no_proxy\" http_proxy=\"$build_http_proxy\" https_proxy=\"$build_https_proxy\" all_proxy=\"$build_all_proxy\" no_proxy=\"$build_no_proxy\" docker build $effective_docker_build_add_host_args --network \"$docker_network_mode\" --build-arg SOURCE_IMAGE=\"$source\" --build-arg HTTP_PROXY=\"$effective_build_container_http_proxy\" --build-arg HTTPS_PROXY=\"$effective_build_container_https_proxy\" --build-arg ALL_PROXY=\"$effective_build_container_all_proxy\" --build-arg NO_PROXY=\"$build_no_proxy\" --build-arg http_proxy=\"$effective_build_container_http_proxy\" --build-arg https_proxy=\"$effective_build_container_https_proxy\" --build-arg all_proxy=\"$effective_build_container_all_proxy\" --build-arg no_proxy=\"$build_no_proxy\" -t \"$target\" -f \"$dockerfile\" \"$tmpdir\" >/tmp/hwlab-node-runtime-image-$id-build.out 2>&1; then",
" docker push \"$target\" >/tmp/hwlab-node-runtime-image-$id-push.out 2>&1 || { cat /tmp/hwlab-node-runtime-image-$id-push.out >&2 2>/dev/null || true; failed=true; }",
" else",
" cat /tmp/hwlab-node-runtime-image-$id-build.out >&2 2>/dev/null || true",
" failed=true",
" fi",
" rm -rf \"$tmpdir\"",
" else",
" source_present_before=true",
" if ! docker image inspect \"$source\" >/dev/null 2>&1; then",
@@ -1147,7 +1197,7 @@ export function ensureNodeBaseImage(spec: HwlabRuntimeLaneSpec, dryRun: boolean,
nodeRuntimeImageCalls(spec, "ensure_image"),
"if [ \"$failed\" = true ]; then exit 1; fi",
].join("\n");
const hasBuild = nodeRuntimeImageDependencies(spec).some((image) => image.mode === "build-moonbridge");
const hasBuild = nodeRuntimeImageDependencies(spec).some((image) => image.mode === "build-moonbridge" || image.mode === "build-opencode-git");
const result = hasBuild && !dryRun
? runNodeHostScriptAsync(spec, script, Math.min(timeoutSeconds, 600), "runtime-image-build")
: runNodeHostScript(spec, script, Math.min(timeoutSeconds, 300));