From ff88ebd837335017a89be983f86a2ffd09c8f591 Mon Sep 17 00:00:00 2001 From: adrians5j Date: Fri, 17 Jul 2026 12:25:02 +0200 Subject: [PATCH] perf(build): promote dependency-aware cache key to default, drop flag + --rebuild-dependents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Promotes the dependency-aware build key from opt-in to default and removes the now-redundant machinery. - remove the `WEBINY_EXPERIMENTAL_DEP_AWARE_CACHE` gate + `getOwnHashes`; `getBatches` always uses the dependency-aware key - remove `--rebuild-dependents`: getBatches step 1.5, the `rebuildDependents` option, and the CI flag (WAC sources + regenerated push.yml/pullRequests.yml) A plain `yarn build` now rebuilds any changed package plus all its dependents (workspace or resolved third-party) on its own. NOTE: first build after this merges is a one-time full rebuild everywhere — stored meta holds own-source hashes (flag was off) and now mismatches the dependency-aware keys. The nightly global-cache rebuild absorbs it. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/pullRequests.yml | 14 +++--- .github/workflows/push.yml | 16 +++---- .github/workflows/wac/pullRequests.wac.ts | 3 +- .github/workflows/wac/push.wac.ts | 3 +- .../wac/steps/createInstallBuildSteps.ts | 8 ++-- scripts/buildPackages/src/buildPackages.ts | 4 +- scripts/buildPackages/src/getBatches.ts | 48 ++++--------------- .../buildPackages/src/getEffectiveHashes.ts | 27 ----------- 8 files changed, 30 insertions(+), 93 deletions(-) diff --git a/.github/workflows/pullRequests.yml b/.github/workflows/pullRequests.yml index 601f27b9b46..a34d257ad95 100644 --- a/.github/workflows/pullRequests.yml +++ b/.github/workflows/pullRequests.yml @@ -112,7 +112,7 @@ jobs: run: yarn --immutable working-directory: ${{ github.base_ref }} - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: ${{ github.base_ref }} - uses: actions/cache@v5 with: @@ -149,7 +149,7 @@ jobs: run: yarn --immutable working-directory: ${{ github.base_ref }} - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: ${{ github.base_ref }} - name: Build core run: yarn webiny build core @@ -233,7 +233,7 @@ jobs: run: yarn --immutable working-directory: ${{ github.base_ref }} - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: ${{ github.base_ref }} - name: Sync Dependencies Verification run: yarn verify-dependencies @@ -335,7 +335,7 @@ jobs: run: yarn --immutable working-directory: ${{ github.base_ref }} - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: ${{ github.base_ref }} - name: Run tests run: ${{ matrix.testCommand.cmd }} @@ -418,7 +418,7 @@ jobs: run: yarn --immutable working-directory: ${{ github.base_ref }} - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: ${{ github.base_ref }} - name: Run tests run: ${{ matrix.testCommand.cmd }} @@ -511,7 +511,7 @@ jobs: run: yarn --immutable working-directory: ${{ github.base_ref }} - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: ${{ github.base_ref }} - name: Run tests run: ${{ matrix.testCommand.cmd }} @@ -596,7 +596,7 @@ jobs: run: yarn --immutable working-directory: ${{ github.base_ref }} - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: ${{ github.base_ref }} - name: Run tests run: ${{ matrix.testCommand.cmd }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index aad293a41a0..9136dc5aac8 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -58,7 +58,7 @@ jobs: run: yarn --immutable working-directory: v6 - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: v6 - uses: actions/cache@v5 with: @@ -133,7 +133,7 @@ jobs: run: yarn --immutable working-directory: v6 - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: v6 - name: Sync Dependencies Verification run: yarn verify-dependencies @@ -226,7 +226,7 @@ jobs: run: yarn --immutable working-directory: v6 - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: v6 - name: Run tests run: ${{ matrix.testCommand.cmd }} @@ -300,7 +300,7 @@ jobs: run: yarn --immutable working-directory: v6 - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: v6 - name: Run tests run: ${{ matrix.testCommand.cmd }} @@ -382,7 +382,7 @@ jobs: run: yarn --immutable working-directory: v6 - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: v6 - name: Run tests run: ${{ matrix.testCommand.cmd }} @@ -458,7 +458,7 @@ jobs: run: yarn --immutable working-directory: v6 - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: v6 - name: Run tests run: ${{ matrix.testCommand.cmd }} @@ -534,7 +534,7 @@ jobs: run: yarn --immutable working-directory: v6 - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: v6 - name: Start Verdaccio local server working-directory: v6 @@ -695,7 +695,7 @@ jobs: run: yarn --immutable working-directory: v6 - name: Build packages - run: yarn build --rebuild-dependents + run: yarn build working-directory: v6 - name: Start Verdaccio local server working-directory: v6 diff --git a/.github/workflows/wac/pullRequests.wac.ts b/.github/workflows/wac/pullRequests.wac.ts index 459f8f00655..0340a0b6e12 100644 --- a/.github/workflows/wac/pullRequests.wac.ts +++ b/.github/workflows/wac/pullRequests.wac.ts @@ -25,8 +25,7 @@ import { const DIR_WEBINY_JS = "${{ github.base_ref }}"; const installBuildSteps = createInstallBuildSteps({ - workingDirectory: DIR_WEBINY_JS, - rebuildDependents: true + workingDirectory: DIR_WEBINY_JS }); const yarnCacheSteps = createYarnCacheSteps({ workingDirectory: DIR_WEBINY_JS }); const globalBuildCacheSteps = createGlobalBuildCacheSteps({ workingDirectory: DIR_WEBINY_JS }); diff --git a/.github/workflows/wac/push.wac.ts b/.github/workflows/wac/push.wac.ts index 41699960022..43746268e5e 100644 --- a/.github/workflows/wac/push.wac.ts +++ b/.github/workflows/wac/push.wac.ts @@ -21,8 +21,7 @@ const DIR_WEBINY_JS = "v6"; const DIR_TEST_PROJECT = "new-webiny-project"; const installBuildSteps = createInstallBuildSteps({ - workingDirectory: DIR_WEBINY_JS, - rebuildDependents: true + workingDirectory: DIR_WEBINY_JS }); const yarnCacheSteps = createYarnCacheSteps({ workingDirectory: DIR_WEBINY_JS diff --git a/.github/workflows/wac/steps/createInstallBuildSteps.ts b/.github/workflows/wac/steps/createInstallBuildSteps.ts index 647870541c1..b96d6269b66 100644 --- a/.github/workflows/wac/steps/createInstallBuildSteps.ts +++ b/.github/workflows/wac/steps/createInstallBuildSteps.ts @@ -2,17 +2,15 @@ import { withCommonParams } from "./withCommonParams.js"; interface CreateInstallBuildStepsParams { workingDirectory: string; - rebuildDependents?: boolean; } export const createInstallBuildSteps = (params: CreateInstallBuildStepsParams) => { - const rebuildDependents = params.rebuildDependents ?? false; - const buildCommand = rebuildDependents ? "yarn build --rebuild-dependents" : "yarn build"; - return withCommonParams( [ { name: "Install dependencies", run: "yarn --immutable" }, - { name: "Build packages", run: buildCommand } + // The build's dependency-aware cache key rebuilds dependents of any + // changed package on its own — no `--rebuild-dependents` needed. + { name: "Build packages", run: "yarn build" } ], { "working-directory": params.workingDirectory } ); diff --git a/scripts/buildPackages/src/buildPackages.ts b/scripts/buildPackages/src/buildPackages.ts index c4b927beeaf..ad141a212ed 100644 --- a/scripts/buildPackages/src/buildPackages.ts +++ b/scripts/buildPackages/src/buildPackages.ts @@ -33,7 +33,6 @@ interface BuildOptions { p?: string | string[]; debug?: boolean; cache?: boolean; - rebuildDependents?: boolean; buildOverrides?: string; safeReplace?: boolean; } @@ -64,8 +63,7 @@ export const buildPackages = async () => { const { batches, packagesNoCache, allPackages, buildKeys } = await getBatches({ cache: options.cache ?? true, - packagesWhitelist, - rebuildDependents: options.rebuildDependents + packagesWhitelist }); if (!packagesNoCache.length) { diff --git a/scripts/buildPackages/src/getBatches.ts b/scripts/buildPackages/src/getBatches.ts index b53ab28eb61..9c3dc5d565f 100644 --- a/scripts/buildPackages/src/getBatches.ts +++ b/scripts/buildPackages/src/getBatches.ts @@ -9,14 +9,13 @@ import { getBuildOutputFolder } from "./getBuildOutputFolder"; import { getBuildMeta } from "./getBuildMeta"; import { getPackageCacheFolderPath } from "./getPackageCacheFolderPath"; import { distMatchesCache, recordCacheHash } from "./distContentHash"; -import { getEffectiveHashes, getOwnHashes, isDepAwareKeyEnabled } from "./getEffectiveHashes"; +import { getEffectiveHashes } from "./getEffectiveHashes"; const { green } = chalk; interface GetBatchesOptions { cache?: boolean; packagesWhitelist?: string[]; - rebuildDependents?: boolean; } export async function getBatches(options: GetBatchesOptions = {}) { @@ -46,13 +45,11 @@ export async function getBatches(options: GetBatchesOptions = {}) { ignore: ["@webiny/project-utils"] }); - // Build key per package. Default: own-source hash (original behavior). - // Experimental (WEBINY_EXPERIMENTAL_DEP_AWARE_CACHE): a dependency-aware key - // that also changes when any transitive dependency changes, so dependents of - // a changed package are detected as misses without `--rebuild-dependents`. - const buildKeys = isDepAwareKeyEnabled() - ? await getEffectiveHashes(allWorkspacePackages) - : await getOwnHashes(allWorkspacePackages); + // Dependency-aware build key per package: changes when the package's own + // source, any transitive workspace dependency, or any resolved third-party + // dependency changes — so dependents of a changed package are detected as + // misses on a plain build. + const buildKeys = await getEffectiveHashes(allWorkspacePackages); // 1. Determine for which packages we can use the cached built code, and for which we need to execute build. if (!useCache) { @@ -77,36 +74,9 @@ export async function getBatches(options: GetBatchesOptions = {}) { } } - // 1.5 When using cache and --rebuild-dependents, also rebuild any package that depends on a changed package. - if (options.rebuildDependents && packagesNoCache.length > 0 && useCache) { - const dependents = workspaceGraph.getDependents(); - - const tainted = new Set(packagesNoCache.map(p => p.packageJson.name)); - const queue = [...tainted]; - while (queue.length > 0) { - const name = queue.pop()!; - for (const dependent of dependents.get(name) || []) { - if (!tainted.has(dependent)) { - tainted.add(dependent); - queue.push(dependent); - } - } - } - - for (const name of tainted) { - if (packagesNoCache.some(p => p.packageJson.name === name)) continue; - const pkg = workspacesPackages.find(p => p.packageJson.name === name); - if (pkg) { - packagesNoCache.push(pkg); - } - } - - for (let i = packagesUseCache.length - 1; i >= 0; i--) { - if (tainted.has(packagesUseCache[i].packageJson.name)) { - packagesUseCache.splice(i, 1); - } - } - } + // Dependents of a changed package no longer need explicit tainting: the + // dependency-aware key folds in dependency keys, so any dependent of a + // changed package is already a cache miss above. // 2. Let's use cached built code where possible. if (packagesUseCache.length) { diff --git a/scripts/buildPackages/src/getEffectiveHashes.ts b/scripts/buildPackages/src/getEffectiveHashes.ts index 168636c71c8..59d43715361 100644 --- a/scripts/buildPackages/src/getEffectiveHashes.ts +++ b/scripts/buildPackages/src/getEffectiveHashes.ts @@ -7,33 +7,6 @@ import { PROJECT_ROOT } from "../../utils/getPackages.js"; import { getPackageSourceHash } from "./getPackageSourceHash"; import type { Package } from "./types"; -/** - * Whether the experimental dependency-aware build key is enabled. OFF by - * default: the build key is each package's own-source hash (original behavior), - * and `--rebuild-dependents` remains the mechanism for rebuilding dependents. - * - * Enable with `WEBINY_EXPERIMENTAL_DEP_AWARE_CACHE=true` (or `1`) to make a - * plain `yarn build` rebuild dependents of any changed package automatically. - */ -export function isDepAwareKeyEnabled(): boolean { - const value = process.env.WEBINY_EXPERIMENTAL_DEP_AWARE_CACHE; - return value === "true" || value === "1"; -} - -/** - * Own-source hash per package (no dependency folding) — the original, - * non-dependency-aware build key. Used when the experimental key is disabled. - */ -export async function getOwnHashes(allPackages: Package[]): Promise> { - const map = new Map(); - await Promise.all( - allPackages.map(async pkg => { - map.set(pkg.name, await getPackageSourceHash(pkg)); - }) - ); - return map; -} - /** * Parses `yarn.lock` into a map of dependency descriptor → a token that changes * whenever the *resolved* package changes (its checksum, falling back to