fix: probe direct docker registry via host network
This commit is contained in:
@@ -159,10 +159,12 @@ assertCondition(ciSource.includes('type CiPublishTransport = "auto" | "tekton" |
|
||||
assertCondition(ciSource.includes('options.transport === "direct-docker"'), "ci publish-user-service should support direct-docker artifact publish");
|
||||
assertCondition(ciSource.includes('options.transport === "auto" && options.serviceId === "code-queue"'), "auto transport should select direct-docker for Code Queue artifacts");
|
||||
assertCondition(ciSource.includes("dependsOnLocalUnideskDatabase: false"), "direct-docker publish must not depend on local unidesk-database dispatch");
|
||||
assertCondition(ciSource.includes("CODE_QUEUE_BASE_IMAGE=unidesk-code-queue:d601"), "direct-docker Code Queue publish must use the warmed D601 base image");
|
||||
assertCondition(ciSource.includes("codeQueueDirectDockerBaseImage") && ciSource.includes("CODE_QUEUE_BASE_IMAGE"), "direct-docker Code Queue publish must use the warmed D601 base image");
|
||||
assertCondition(ciSource.includes("directDockerBuildNetworkArgs"), "direct-docker Code Queue publish must own scoped build network args");
|
||||
assertCondition(ciSource.includes('"--network"') && ciSource.includes('"host"'), "direct-docker Code Queue publish must use host networking for the D601 provider proxy");
|
||||
assertCondition(ciSource.includes("providerGatewayWsEgressProxyUrl") && ciSource.includes("HTTP_PROXY") && ciSource.includes("HTTPS_PROXY"), "direct-docker Code Queue publish must pass scoped provider-gateway proxy build args");
|
||||
assertCondition(ciSource.includes("directDockerRegistryCurl"), "direct-docker Code Queue publish must probe the registry through the Docker host namespace when needed");
|
||||
assertCondition(ciSource.includes('"--pull"') && ciSource.includes('"never"'), "direct-docker registry probe must not pull helper images");
|
||||
assertCondition(ciSource.includes("code-queue-base-image-missing"), "direct-docker Code Queue publish should fail fast when the warmed base image is missing");
|
||||
assertCondition(ciSource.includes("no deploy apply, no rollout, no Code Queue restart, no active task mutation"), "direct-docker publish boundary should forbid runtime mutation");
|
||||
assertCondition(ciSource.includes("repo-owned Docker artifact publish without backend-core/database dispatch"), "ci help should describe the repo-owned direct-docker delivery path");
|
||||
@@ -177,5 +179,6 @@ process.stdout.write(`${JSON.stringify({
|
||||
"artifact-registry dev dry-run is non-mutating while prod remains unsupported",
|
||||
"ci publish-user-service exposes direct-docker Code Queue artifact publish without local database dispatch",
|
||||
"direct-docker Code Queue artifact publish uses scoped provider-gateway build proxy args",
|
||||
"direct-docker Code Queue artifact publish probes the loopback registry through Docker host networking",
|
||||
],
|
||||
}, null, 2)}\n`);
|
||||
|
||||
+26
-6
@@ -25,6 +25,7 @@ const tektonTriggersReleaseUrl = `https://infra.tekton.dev/tekton-releases/trigg
|
||||
const tektonTriggersInterceptorsUrl = `https://infra.tekton.dev/tekton-releases/triggers/previous/${tektonTriggersVersion}/interceptors.yaml`;
|
||||
const providerGatewayWsEgressProxyUrl = "http://127.0.0.1:18789";
|
||||
const ciCodeQueueImage = "unidesk-code-queue:dev";
|
||||
const codeQueueDirectDockerBaseImage = "unidesk-code-queue:d601";
|
||||
const providerDispatchCompletionLagMs = 45_000;
|
||||
const ciRuntimeImages = [
|
||||
"rancher/mirrored-pause:3.6",
|
||||
@@ -1498,18 +1499,37 @@ function dockerArtifactDigest(repository: string, imageRef: string): string | nu
|
||||
return null;
|
||||
}
|
||||
|
||||
function directDockerRegistryCurl(args: string[], timeoutMs = 30_000): ReturnType<typeof runCommand> {
|
||||
const local = runCommand(["curl", ...args], repoRoot, { timeoutMs });
|
||||
if (local.exitCode === 0 && !local.timedOut) return local;
|
||||
const basePresent = runCommand(["docker", "image", "inspect", codeQueueDirectDockerBaseImage], repoRoot, { timeoutMs: 30_000 });
|
||||
if (basePresent.exitCode !== 0) return local;
|
||||
return runCommand([
|
||||
"docker",
|
||||
"run",
|
||||
"--rm",
|
||||
"--network",
|
||||
"host",
|
||||
"--pull",
|
||||
"never",
|
||||
"--entrypoint",
|
||||
"curl",
|
||||
codeQueueDirectDockerBaseImage,
|
||||
...args,
|
||||
], repoRoot, { timeoutMs });
|
||||
}
|
||||
|
||||
function registryManifestDigest(repository: string, tag: string): string | null {
|
||||
const registry = "127.0.0.1:5000";
|
||||
if (!repository.startsWith(`${registry}/`)) return null;
|
||||
const repositoryPath = repository.slice(`${registry}/`.length);
|
||||
if (repositoryPath.length === 0 || repositoryPath.includes("..") || tag.length === 0) return null;
|
||||
const result = runCommand([
|
||||
"curl",
|
||||
const result = directDockerRegistryCurl([
|
||||
"-fsSI",
|
||||
"-H",
|
||||
"Accept: application/vnd.docker.distribution.manifest.v2+json",
|
||||
`http://${registry}/v2/${repositoryPath}/manifests/${tag}`,
|
||||
], repoRoot, { timeoutMs: 30_000 });
|
||||
], 30_000);
|
||||
if (result.exitCode !== 0) return null;
|
||||
const match = /^Docker-Content-Digest:\s*(sha256:[0-9a-f]{64})\s*$/imu.exec(result.stdout);
|
||||
return match?.[1] ?? null;
|
||||
@@ -1609,8 +1629,8 @@ async function publishUserServiceArtifactDirectDocker(options: CiPublishUserServ
|
||||
const localImage = `${options.imageRepository}:${options.commit}`;
|
||||
const buildContext = buildContextForService(options.serviceId, options.dockerfile);
|
||||
const networkArgs = directDockerBuildNetworkArgs(options.serviceId);
|
||||
const baseArgs = options.serviceId === "code-queue" && runCommand(["docker", "image", "inspect", "unidesk-code-queue:d601"], repoRoot, { timeoutMs: 30_000 }).exitCode === 0
|
||||
? ["--build-arg", "CODE_QUEUE_BASE_IMAGE=unidesk-code-queue:d601"]
|
||||
const baseArgs = options.serviceId === "code-queue" && runCommand(["docker", "image", "inspect", codeQueueDirectDockerBaseImage], repoRoot, { timeoutMs: 30_000 }).exitCode === 0
|
||||
? ["--build-arg", `CODE_QUEUE_BASE_IMAGE=${codeQueueDirectDockerBaseImage}`]
|
||||
: [];
|
||||
try {
|
||||
if (options.serviceId === "code-queue" && baseArgs.length === 0) {
|
||||
@@ -1662,7 +1682,7 @@ async function publishUserServiceArtifactDirectDocker(options: CiPublishUserServ
|
||||
const inspectLabels = runCommand(["docker", "image", "inspect", planned.imageRef, "--format", "{{ index .Config.Labels \"unidesk.ai/service-id\" }} {{ index .Config.Labels \"unidesk.ai/source-commit\" }}"], repoRoot, { timeoutMs: 30_000 });
|
||||
assertCommandOk(inspectLabels, "inspect built image labels");
|
||||
if (!inspectLabels.stdout.includes(`${options.serviceId} ${options.commit}`)) throw new Error(`direct docker image labels did not match ${options.serviceId}/${options.commit}`);
|
||||
const registryCheck = runCommand(["curl", "-fsS", "http://127.0.0.1:5000/v2/"], repoRoot, { timeoutMs: 15_000 });
|
||||
const registryCheck = directDockerRegistryCurl(["-fsS", "http://127.0.0.1:5000/v2/"], 15_000);
|
||||
assertCommandOk(registryCheck, "D601 loopback artifact registry health");
|
||||
const push = runCommand(["docker", "push", planned.imageRef], repoRoot, { timeoutMs: Math.max(options.waitMs, 10 * 60_000) });
|
||||
assertCommandOk(push, "direct docker push");
|
||||
|
||||
Reference in New Issue
Block a user