diff --git a/scripts/artifact-publish.mjs b/scripts/artifact-publish.mjs index ebbb9f8b..159f2140 100644 --- a/scripts/artifact-publish.mjs +++ b/scripts/artifact-publish.mjs @@ -930,6 +930,33 @@ function envReuseDockerfile(baseImage, labels = [], recipe, service = null) { ].join("\n"); } +async function copyRepoFileToContext(contextDir, repoRelativePath, { required = true } = {}) { + const sourcePath = path.join(repoRoot, repoRelativePath); + const targetPath = path.join(contextDir, repoRelativePath); + try { + const content = await readFile(sourcePath); + await mkdir(path.dirname(targetPath), { recursive: true }); + await writeFile(targetPath, content); + return true; + } catch (error) { + if (!required && error?.code === "ENOENT") return false; + throw error; + } +} + +async function prepareEnvReuseBuildContext(tmpDir, normalizedRecipe, goCacheEnabled) { + const contextDir = path.join(tmpDir, "context"); + await mkdir(contextDir, { recursive: true }); + await copyRepoFileToContext(contextDir, "package.json"); + await copyRepoFileToContext(contextDir, "package-lock.json", { required: false }); + if (goCacheEnabled) { + await copyRepoFileToContext(contextDir, "go.mod"); + await copyRepoFileToContext(contextDir, "go.sum", { required: false }); + } + await copyRepoFileToContext(contextDir, normalizedRecipe.launcherPath); + return contextDir; +} + function normalizeEnvReuseRecipe(recipe) { assert.ok(recipe && typeof recipe === "object", "envRecipe must be provided by deploy.lanes..envRecipe"); const normalized = { @@ -1283,6 +1310,10 @@ async function buildEnvReuseService({ args, repo, commitId, service, buildCreate async function buildEnvReuseServiceWithBuildkit({ args, service, ref, buildCreatedAt, buildSource, labels }) { const tmpDir = await mkdtemp(path.join(os.tmpdir(), `hwlab-env-reuse-${service.serviceId}-`)); + const normalizedRecipe = normalizeEnvReuseRecipe(service.envReuseRecipe); + const goService = service?.runtimeKind === "go-service" || service?.artifactKind === "go-service"; + const goCacheEnabled = Boolean(goService && normalizedRecipe.runtimeGoModCachePath && normalizedRecipe.runtimeGoBuildCachePath); + const contextDir = await prepareEnvReuseBuildContext(tmpDir, normalizedRecipe, goCacheEnabled); const metadataPath = path.join(tmpDir, "metadata.json"); const dockerfilePath = path.join(tmpDir, "Dockerfile"); const cacheRef = envReuseCacheRef(args.registryPrefix, service.serviceId); @@ -1290,12 +1321,12 @@ async function buildEnvReuseServiceWithBuildkit({ args, service, ref, buildCreat const buildkitAddrArgs = args.buildkitAddr ? ["--addr", args.buildkitAddr] : []; const startedAt = Date.now(); try { - await writeFile(dockerfilePath, envReuseDockerfile(args.baseImage, labels, service.envReuseRecipe, service)); + await writeFile(dockerfilePath, envReuseDockerfile(args.baseImage, labels, normalizedRecipe, service)); const argsList = [ ...buildkitAddrArgs, "build", "--frontend", "dockerfile.v0", - "--local", `context=${repoRoot}`, + "--local", `context=${contextDir}`, "--local", `dockerfile=${tmpDir}`, "--opt", "filename=Dockerfile", "--metadata-file", metadataPath,