Local downloading of optimization statistics for the build - #1186
Local downloading of optimization statistics for the build#1186mu-hun wants to merge 115 commits into
Conversation
Strip volatile metadata lines (Checksum, Diff-Path, TimeUpdated, Version) from compiled filter files after build. Reduces noise when comparing outputs between compiler versions.
- one-liner => helper function - .txt extension to the constant in strip_generated_meta.js
6507dd5 to
3bcca2e
Compare
df6f136 to
424e89f
Compare
Please specify how to perform the test.I have just aligned with the flags you created (#1181). In the PR description,
|
e04f297 to
867ab88
Compare
Crash fixed7691c68. The cache dir is wiped with |
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <copilot@github.com>
|
If there are no further suggestions or change requests, I'm ready to merge 👀 |
maximtop
left a comment
There was a problem hiding this comment.
Mostly small stuff inline. The one I'd genuinely chase is the e2e percent.json mock — it doesn't intercept the compiler's fetch, so the new CI workflow hits the live network on every PR. The beta compiler pin and the script placement are already tracked in open threads.
|
|
||
| // compile() always fetches percent.json remotely, even under use(). Mock only | ||
| // that call so the suite below stays offline; everything else passes through. | ||
| vi.mock('child_process', async (importOriginal) => { |
There was a problem hiding this comment.
Worth another look at the offline claim here: the compiler's ESM build fetches percent.json via createRequire(import.meta.url)('child_process').execFileSync('curl', ...) (checked the pinned 3.3.0-beta.1 dist, index.js:1000/1025), and since vitest externalizes @adguard/filters-compiler, this vi.mock('child_process') never intercepts that call — the real curl runs. So every yarn test (both Node legs of the new test.yaml on every PR) curls the live chrome.adtidy.org/optimization_config/percent.json and depends on it listing filterId 1. On a network hiccup the compiler's curl --retry 5 backoff (~31s) also blows past the 30s beforeAll timeout and fails the whole file. Inlining the compiler into vitest's transform pipeline (server.deps.inline), having the compiler accept a local percent.json, or stubbing curl via PATH would each fix it.
There was a problem hiding this comment.
Including #1186 (comment), I'll take this issue as adding an option to load percent.json locally from #1222.
But I want to finalize this PR with no more additional patches, so I'd like to handle that issue after this feature is released. Therefore, I just dropped the "offline" keyword from the PR body and main issue description as follows:
Enables local download and reuse of optimization stats, supporting filter creation based on a pinned stats snapshot.
| `template.txt` with a single `@include "./filter.txt"` directive, and compiles | ||
| from that copy. The original `filters/` directory is never modified. | ||
|
|
||
| Optimization stats are picked up automatically: if `temp/optimization/stats` |
There was a problem hiding this comment.
This says the local stats are "used as-is", but getOptimizableFilterIds() in the pinned compiler always fetches percent.json via curl, even after localOptimizationStatistics.use() — only the per-filter stats.json content comes from disk. So yarn build:local still needs network (offline it hangs through curl retries and dies with a raw curl error, no --download-stats hint), and the snapshot isn't fully pinned since the live percent.json decides which filters get optimized. Either document the remaining network dependency here (and drop "offline" from the PR body), or have the compiler read percent.json from the cache dir under use().
| echo "Branch (reference): master @ $MASTER_SHA" | ||
| echo "Branch (feature): $CHANGED_BRANCH @ $CHANGED_SHA" | ||
| if [ "${BUILD_LOCAL:-false}" = "true" ]; then | ||
| BUILD_CMD="generate-cache && yarn build:local --no-patches-prepare --strip-generated-meta" |
There was a problem hiding this comment.
This script uses 2-space indentation and no shebang, while the repo's other shell scripts (scripts/auto_build.sh, the translations scripts) start with #!/bin/bash and use 4-space indentation. Harmless at runtime since DEVELOPMENT.md invokes it via bash, but worth matching when it moves in the child PR.
There was a problem hiding this comment.
Okay, I'll update to use 4-space indent in one-level child PR.
| }; | ||
| } | ||
|
|
||
| if (flags.useCache && flags.downloadStats) { |
There was a problem hiding this comment.
The three mutual-exclusion blocks here are identical except for flag names, and this PR adds the second and third. The neighboring incompatibility checks were just deduplicated via buildIncompatibilityError; the same treatment fits (a buildMutualExclusionError(a, b) helper or a small table of exclusive pairs), so a wording tweak isn't edited three times.
| }); | ||
| }); | ||
|
|
||
| it('--download-stats: downloads stats for all filters, compile skipped', async () => { |
There was a problem hiding this comment.
The three --download-stats tests below are line-for-line identical (~17 lines each) — set argv, import build.js, destructure the mocked compiler, vi.waitFor the same download assertion; only the extra flag and expected include/exclude arrays differ. A single it.each keeps the coverage without the copy-paste and would also absorb the repeated mock destructure recurring in nearly every test of this block.
Document that --download-stats swaps the entire local stats directory rather than merging per-filter, so scoped downloads must be paired with an equally scoped build. I've removed description "--include or --skip are not both at once." in AGENTS.md and add description rejects --report flag in both files. Also, "scoped downloads must be paired with an eqaully scoped build — sholud I mentioned the same for the `--generate-cache` flag? Commented in - #1186 (comment) - #1186 (comment) - #1186 (comment) - #1186 (comment)
Suggested in #1186 (comment) This reverts commit ec47a3a.
The top-level buildFilters() call had no .catch, so any rejection surfaced as an UnhandledPromiseRejection trace where the actionable hint (e.g. "run --download-stats") is easy to miss. Now matches the arg-validation error pattern: print the message in red and exit(1). Commented in #1186 (comment)
The top-level buildFilters() call had no .catch, so any rejection surfaced as an UnhandledPromiseRejection trace where the actionable hint (e.g. "run --download-stats") is easy to miss. Now matches the arg-validation error pattern: print the message in red and exit(1). Commented in #1186 (comment) About updated test case: The missing-stats.json case previously asserted on an unhandledRejection. Now that buildFilters() catches rejections and exits 1, the test spies console.error and process.exit, waits for exit(1), and checks the printed output contains the --download-stats hint plus the original error message.
b902864 to
5cc9a45
Compare
'optimization_config' base path name to 'optimization/stats': build.js now uses optimizationStatsDir = path.join(tempDir, 'optimization', 'stats'). Mirror that. Suggested in #1186 (comment)
--use-cache, --generate-cache, and --download-stats are one mutually exclusive group. Replace the three near-identical pairwise blocks with a single table + count check, so the wording lives in one place. Suggested in #1186 (comment)
mu-hun
left a comment
There was a problem hiding this comment.
I've reviewed and applied all of your suggestions.
| yarn build --download-stats --skip=12,24 | ||
| # Scoped download replaces the cache with just these filters — pair with a matching scoped build | ||
| yarn build --download-stats --include=1,2,3 && yarn build:local --include=1,2,3 | ||
| yarn build --download-stats --skip=12,24 && yarn build:local --skip=12,24 |
There was a problem hiding this comment.
Scoped downloads must be paired with an equally scoped build
Should I also mentioned above for the --generate-cache flag?
AS-IS
FiltersRegistry/DEVELOPMENT.md
Lines 248 to 252 in a7a1007
TO-BE
# Cache generation with filter selection
yarn build --generate-cache
# Scoped download replaces the cache with just these filters — pair with a matching scoped build
yarn build --generate-cache --include=1,2,3 && yarn build:local --include=1,2,3
...
|
|
||
| const filtersDir = path.join(tmpDir, 'filters'); | ||
| optimizationDir = path.join(tmpDir, 'optimization_config'); | ||
| optimizationStatsBasePath = path.join(tmpDir, 'optimization', 'stats'); |
There was a problem hiding this comment.
I've updated the outdated optimization_config base path name to optimization/stats:
Enables local download and reuse of optimization stats, supporting filter creation based on a pinned stats snapshot.
This feature is managed entirely through build flags in FiltersRegistry.
The workflow
yarn download-stats(--download-stats) downloads per-filterstats.jsonfiles totemp/optimization/stats/filters/<filterId>/stats.json. Use--includeor--skipto scope which filters are downloaded.yarn build:local: If downloaded optimization stats exist, stats are read from there; if any required filter is missing itsstats.json, the build fails with a message pointing toyarn download-stats. Ifstatsdoesn't exist, stats are fetched live from the remote server instead.