fix: scope Go envreuse packages to Go services (#1131)

This commit is contained in:
Lyon
2026-06-13 16:22:21 +08:00
committed by GitHub
parent 0edcf9e588
commit ea3b26b895
4 changed files with 36 additions and 3 deletions
+9 -1
View File
@@ -890,8 +890,12 @@ function envReuseDockerfile(baseImage, labels = [], recipe, service = null) {
const goReadiness = goCacheEnabled
? `; mkdir -p ${shellQuote(normalizedRecipe.runtimeGoModCachePath)} ${shellQuote(normalizedRecipe.runtimeGoBuildCachePath)}; command -v go >/dev/null; go version >/tmp/hwlab-env-go-version.txt`
: "";
const osPackages = uniquePreserveOrder([
...normalizedRecipe.osPackages,
...(goCacheEnabled ? normalizedRecipe.goOsPackages : [])
]);
const downloadDependencyScript = `set -eu; ${npmConfigScript}; if [ -f package-lock.json ]; then npm ci --omit=dev --include=optional --ignore-scripts; else npm install --omit=dev --include=optional --ignore-scripts; fi; if command -v bun >/dev/null 2>&1; then bun_path="$(command -v bun)"; if [ "$bun_path" != "/usr/local/bin/bun" ]; then ln -sf "$bun_path" /usr/local/bin/bun; fi; fi; if [ ! -x /usr/local/bin/bun ]; then bun_pkg=""; case "$(uname -m)" in x86_64|amd64) bun_pkg="${normalizedRecipe.downloadStack.bunPackages.x64}@${normalizedRecipe.bunVersion}" ;; aarch64|arm64) bun_pkg="${normalizedRecipe.downloadStack.bunPackages.arm64}@${normalizedRecipe.bunVersion}" ;; *) echo "unsupported bun architecture: $(uname -m)" >&2; false ;; esac; npm install --no-save --omit=dev --include=optional --ignore-scripts "$bun_pkg"; bun_bin="node_modules/\${bun_pkg%@*}/bin/bun"; test -x "$bun_bin"; ln -sf "${runtimeRoot}/$bun_bin" /usr/local/bin/bun; fi`;
const osPackageScript = `set -eu; apt-get update; apt-get install -y --no-install-recommends ${normalizedRecipe.osPackages.map(shellQuote).join(" ")}; rm -rf /var/lib/apt/lists/*`;
const osPackageScript = `set -eu; apt-get update; apt-get install -y --no-install-recommends ${osPackages.map(shellQuote).join(" ")}; rm -rf /var/lib/apt/lists/*`;
const aliasScript = normalizedRecipe.hwpodAliases.map((alias) => `printf '%s\\n' '#!/usr/bin/env sh' 'exec node /workspace/hwlab-boot/repo/scripts/run-bun.mjs /workspace/hwlab-boot/repo/${alias.script} \"$@\"' > /usr/local/bin/${alias.command}; chmod 755 /usr/local/bin/${alias.command}`).join("; ");
const readinessScript = `set -eu; command -v node >/dev/null; command -v npm >/dev/null; command -v git >/dev/null; command -v sh >/dev/null; test -d ${shellQuote(normalizedRecipe.runtimeNodeModulesPath)}; test -x /usr/local/bin/bun; /usr/local/bin/bun --version >/tmp/hwlab-env-bun-version.txt${goReadiness}; ${aliasScript}`;
return [
@@ -919,6 +923,7 @@ function normalizeEnvReuseRecipe(recipe) {
assert.ok(recipe && typeof recipe === "object", "envRecipe must be provided by deploy.lanes.<lane>.envRecipe");
const normalized = {
osPackages: normalizeStringList(recipe.osPackages),
goOsPackages: normalizeStringList(recipe.goOsPackages),
bunVersion: String(recipe.bunVersion ?? "").trim(),
launcherPath: normalizeRepoPath(recipe.launcherPath),
runtimeNodeModulesPath: normalizeAbsolutePath(recipe.runtimeNodeModulesPath),
@@ -929,6 +934,9 @@ function normalizeEnvReuseRecipe(recipe) {
hwpodAliases: normalizeHwpodAliases(recipe.hwpodAliases)
};
assert.ok(normalized.osPackages.length > 0, "envRecipe.osPackages must not be empty");
if (normalized.runtimeGoModCachePath || normalized.runtimeGoBuildCachePath) {
assert.ok(normalized.goOsPackages.length > 0, "envRecipe.goOsPackages must not be empty when Go cache paths are configured");
}
assert.match(normalized.bunVersion, /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/u, "envRecipe.bunVersion must be a semver-like version");
assert.ok(normalized.launcherPath && !normalized.launcherPath.split("/").includes(".."), "envRecipe.launcherPath must be repo-relative");
assert.ok(normalized.runtimeNodeModulesPath, "envRecipe.runtimeNodeModulesPath must be absolute");
+21 -2
View File
@@ -97,6 +97,7 @@ export async function createCiPlan(options = {}) {
const buildSystemMatches = matchingPaths(normalizedChangedPaths, model.buildSystemPaths);
const envReuse = envReuseServices.has(model.serviceId);
const bootSh = envReuse ? bootShForService(deployJson, model.serviceId, lane) : null;
const serviceEnvReuseRecipe = envReuse ? envReuseRecipeForService(envReuseRecipe.publicRecipe, model) : null;
const envInputPaths = envReuse ? uniqueSorted([
...model.runtimeDeps,
...envReuseRecipe.launcherInputPaths
@@ -120,7 +121,7 @@ export async function createCiPlan(options = {}) {
...buildSystemMatches
].filter((item) => !isTestOnlyPath(item) && !isDocsOnlyPath(item)));
const catalogRecord = catalogByServiceId.get(model.serviceId) ?? null;
const environmentInputHash = envReuse ? await hashEnvReuseInputs(repoRoot, targetRef, envInputPaths, envReuseRecipe.publicRecipe, {
const environmentInputHash = envReuse ? await hashEnvReuseInputs(repoRoot, targetRef, envInputPaths, serviceEnvReuseRecipe, {
skipPath: (filePath) => isTestOnlyPath(filePath) || isDocsOnlyPath(filePath),
semanticPackageJson: true
}) : null;
@@ -202,7 +203,7 @@ export async function createCiPlan(options = {}) {
sharedPaths: model.sharedPaths,
runtimeDeps: model.runtimeDeps,
buildSystemPaths: model.buildSystemPaths,
envReuseRecipe: envReuse ? envReuseRecipe.publicRecipe : null,
envReuseRecipe: serviceEnvReuseRecipe,
componentCommitId,
componentInputHash,
catalogSourceCommitId: catalogSourceCommitId || null,
@@ -363,6 +364,7 @@ function envReuseRecipeForLaneConfig(laneConfig, lane = "v02") {
const configured = laneConfig?.envRecipe;
if (!configured) throw new Error(`deploy.lanes.${lane}.envRecipe is required`);
const osPackages = normalizeStringList(configured.osPackages, []);
const goOsPackages = normalizeStringList(configured.goOsPackages, []);
const bunVersion = requireDeclarationString(configured.bunVersion, lane, "envRecipe.bunVersion");
const launcherPath = normalizeRepoPath(requireDeclarationString(configured.launcherPath, lane, "envRecipe.launcherPath"));
const runtimeNodeModulesPath = normalizeAbsolutePath(configured.runtimeNodeModulesPath);
@@ -378,10 +380,14 @@ function envReuseRecipeForLaneConfig(laneConfig, lane = "v02") {
const hwpodAliases = normalizeHwpodAliases(configured.hwpodAliases);
const downloadStack = normalizeDownloadStack(configured.downloadStack, lane);
if (osPackages.length === 0) throw new Error(`deploy.lanes.${lane}.envRecipe.osPackages is required`);
if ((runtimeGoModCachePath || runtimeGoBuildCachePath) && goOsPackages.length === 0) {
throw new Error(`deploy.lanes.${lane}.envRecipe.goOsPackages is required when Go cache paths are configured`);
}
if (additionalEnvPaths.length === 0) throw new Error(`deploy.lanes.${lane}.envRecipe.additionalEnvPaths is required`);
if (hwpodAliases.length === 0) throw new Error(`deploy.lanes.${lane}.envRecipe.hwpodAliases is required`);
return {
osPackages,
goOsPackages,
bunVersion,
launcherPath,
runtimeNodeModulesPath,
@@ -394,6 +400,7 @@ function envReuseRecipeForLaneConfig(laneConfig, lane = "v02") {
hwpodAliases,
publicRecipe: {
osPackages,
goOsPackages,
bunVersion,
launcherPath,
runtimeNodeModulesPath,
@@ -407,6 +414,18 @@ function envReuseRecipeForLaneConfig(laneConfig, lane = "v02") {
};
}
function envReuseRecipeForService(recipe, model) {
if (model?.runtimeKind === "go-service" || model?.artifactKind === "go-service") return recipe;
const {
goOsPackages: _goOsPackages,
runtimeGoModCachePath: _runtimeGoModCachePath,
runtimeGoBuildCachePath: _runtimeGoBuildCachePath,
goToolchain: _goToolchain,
...nodeRecipe
} = recipe;
return nodeRecipe;
}
function normalizeDownloadStack(value, lane) {
const configured = effectiveDownloadStackConfig(value, process.env);
if (!configured) throw new Error(`deploy.lanes.${lane}.envRecipe.downloadStack is required`);