From 424e89f2854022b262cdc047516e7fa6ee21a2fa Mon Sep 17 00:00:00 2001 From: Mu hun Date: Fri, 3 Apr 2026 20:35:31 +0900 Subject: [PATCH 1/8] Add the ability to cache and use local optimization config Adds support for downloading and reusing optimization config locally, so the optimization result can be checked before changes are deployed to the server. - `percent.json` is saved under `temp/optimization_config_cache/` and read from there when `--use-cache` is active. Both `--generate-cache` and `--use-cache` flags now include optimization config handling alongside the existing filter source caching. `@adguard/filters-compiler` is set to `AdguardTeam/FiltersCompiler#local_optimization_config` in `package.json`. This requires `dist/` to be committed to the branch, as GitHub shorthand installation does not trigger a build step. Upd https://github.com/AdguardTeam/FiltersCompiler/issues/216 --- package.json | 2 +- scripts/build/build.js | 10 ++++++++-- yarn.lock | 13 ++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 28ec0337f1d35..f3fa12fdfa800 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@adguard/agtree": "^4.0.4", "@adguard/dead-domains-linter": "^1.0.22", "@adguard/diff-builder": "1.1.2", - "@adguard/filters-compiler": "3.2.8", + "@adguard/filters-compiler": "AdguardTeam/FiltersCompiler#local_optimization_config", "add": "^2.0.6", "crypto-js": "^4.2.0", "zod": "3" diff --git a/scripts/build/build.js b/scripts/build/build.js index 3c7f1ab7e38ff..a6a8a1d42c6cb 100755 --- a/scripts/build/build.js +++ b/scripts/build/build.js @@ -1,7 +1,7 @@ import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; -import { compile } from '@adguard/filters-compiler'; +import { compile, optimizationConfigLocal } from '@adguard/filters-compiler'; import { CUSTOM_PLATFORMS_CONFIG } from './custom_platforms.js'; import { formatDate } from '../utils/strings.js'; import { @@ -78,7 +78,9 @@ const filtersDir = path.join(__dirname, '../../filters'); const logPath = path.join(__dirname, '../../log.txt'); const platformsPath = path.join(__dirname, '../..', FOLDER_WITH_NEW_FILTERS); const copyPlatformsPath = path.join(__dirname, '../..', FOLDER_WITH_OLD_FILTERS); -const cachedFiltersDir = path.join(__dirname, '../../temp/filters_cached'); +const tempDir = path.join(__dirname, '../../temp'); +const cachedFiltersDir = path.join(tempDir, 'filters_cached'); +const optimizationConfigCachePath = path.join(tempDir, 'optimization_config', 'percent.json'); const reportPath = rawReportPath !== '' // report-adguard.txt OR report-third-party.txt @@ -134,6 +136,9 @@ const buildFilters = async () => { // When --generate-cache we only need to compile filters (which updates filter.txt), // skip platform generation, patches preparation, and temp/platforms copying. if (generateCache) { + await optimizationConfigLocal.generate(optimizationConfigCachePath); + optimizationConfigLocal.setPath(optimizationConfigCachePath); + await compile( filtersDir, logPath, @@ -166,6 +171,7 @@ const buildFilters = async () => { if (useCache) { await prepareCachedFiltersDir(); + optimizationConfigLocal.setPath(optimizationConfigCachePath); } try { diff --git a/yarn.lock b/yarn.lock index 1eb7cbb5b7aa0..8bb03759aee7d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -95,19 +95,18 @@ resolved "https://registry.yarnpkg.com/@adguard/extended-css/-/extended-css-2.1.1.tgz#53677a310cf39259f54dfce79b692b0a327a8bb7" integrity sha512-TsHZ20oUWhbtrzQ4w70B96oHkGBIUZg2FdMfkq4StGfLmXQb+kI7fQb6BtXP2D0bvraIHMq6/mtKExglDJ9vsg== -"@adguard/filters-compiler@3.2.8": - version "3.2.8" - resolved "https://registry.yarnpkg.com/@adguard/filters-compiler/-/filters-compiler-3.2.8.tgz#b3b77419ab062d218a5dd7d8bf161493920f1147" - integrity sha512-5BnIQgawIWb6+sOt1RKZwR76G1a8QjkZOw0JtLK53VInSTppEY+XeVanUOmZtzaiifbpu5Ddz8cTgc70tW7ERA== +"@adguard/filters-compiler@AdguardTeam/FiltersCompiler#local_optimization_config": + version "3.2.7" + resolved "https://codeload.github.com/AdguardTeam/FiltersCompiler/tar.gz/85cbca0aeba7e3b3410e6dd0fd60bedfeb2e45b6" dependencies: - "@adguard/agtree" "^4.0.4" + "@adguard/agtree" "^4.0.3" "@adguard/css-tokenizer" "^1.2.0" "@adguard/ecss-tree" "^2.0.1" "@adguard/extended-css" "^2.1.1" "@adguard/filters-downloader" "^2.4.0" "@adguard/logger" "^2.0.0" "@adguard/scriptlets" "^2.3.1" - "@adguard/tsurlfilter" "^4.0.5" + "@adguard/tsurlfilter" "^4.0.4" "@eslint/css-tree" "3.6.6" ajv "^8.17.1" child_process ">=1.0.2" @@ -148,7 +147,7 @@ "@types/trusted-types" "^2.0.7" js-yaml "^3.14.1" -"@adguard/tsurlfilter@^4.0.5": +"@adguard/tsurlfilter@^4.0.4": version "4.0.5" resolved "https://registry.yarnpkg.com/@adguard/tsurlfilter/-/tsurlfilter-4.0.5.tgz#2a1438d3da7c0c4b0a98c255c4386ce631eb99ae" integrity sha512-s/Iv86M9KUXXAfeyps/hmEbX5tismn19lAVqIkFptBujnrV6uEY2bxthzRsBWxY39Y8ZFwrjhe9nyZ3HILbU3g== From 38b9349cf83ed45a0d0019f6dc2c79c4f591e1ec Mon Sep 17 00:00:00 2001 From: Mu-Hun Date: Fri, 24 Apr 2026 14:25:31 +0900 Subject: [PATCH 2/8] fix: not file path --- scripts/build/build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/build.js b/scripts/build/build.js index a6a8a1d42c6cb..711fbafce9947 100755 --- a/scripts/build/build.js +++ b/scripts/build/build.js @@ -80,7 +80,7 @@ const platformsPath = path.join(__dirname, '../..', FOLDER_WITH_NEW_FILTERS); const copyPlatformsPath = path.join(__dirname, '../..', FOLDER_WITH_OLD_FILTERS); const tempDir = path.join(__dirname, '../../temp'); const cachedFiltersDir = path.join(tempDir, 'filters_cached'); -const optimizationConfigCachePath = path.join(tempDir, 'optimization_config', 'percent.json'); +const optimizationConfigCachePath = path.join(tempDir, 'optimization_config'); const reportPath = rawReportPath !== '' // report-adguard.txt OR report-third-party.txt From a8eb38127480bb2534647f94ed51e402bc4982cc Mon Sep 17 00:00:00 2001 From: Mu-Hun Date: Mon, 27 Apr 2026 11:01:33 +0900 Subject: [PATCH 3/8] Update the FiltersCompiler dependency --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 8bb03759aee7d..945120a1cd448 100644 --- a/yarn.lock +++ b/yarn.lock @@ -96,8 +96,8 @@ integrity sha512-TsHZ20oUWhbtrzQ4w70B96oHkGBIUZg2FdMfkq4StGfLmXQb+kI7fQb6BtXP2D0bvraIHMq6/mtKExglDJ9vsg== "@adguard/filters-compiler@AdguardTeam/FiltersCompiler#local_optimization_config": - version "3.2.7" - resolved "https://codeload.github.com/AdguardTeam/FiltersCompiler/tar.gz/85cbca0aeba7e3b3410e6dd0fd60bedfeb2e45b6" + version "3.2.6" + resolved "https://codeload.github.com/AdguardTeam/FiltersCompiler/tar.gz/615d6e0880bc46aa81758d4a7b0f334a87a204bc" dependencies: "@adguard/agtree" "^4.0.3" "@adguard/css-tokenizer" "^1.2.0" From 867ab8821e5b4f4e5225b3ace31d9e1122c39984 Mon Sep 17 00:00:00 2001 From: Mu-Hun Date: Mon, 27 Apr 2026 17:18:30 +0900 Subject: [PATCH 4/8] test(build): add integration tests for optimizationConfigLocal Verifies --use-cache calls setPath() and --generate-cache calls generate() + setPath() with the correct cache path. Dynamically imports build.js per test after vi.resetModules() to re-execute its module-level side effects with controlled process.argv. Mocks fs, @adguard/filters-compiler, and find_files to stay isolated. --- .../optimization-integration.test.js | 68 +++++++++++++++++++ vitest.config.ts | 5 +- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 scripts/build/__tests__/optimization-integration.test.js diff --git a/scripts/build/__tests__/optimization-integration.test.js b/scripts/build/__tests__/optimization-integration.test.js new file mode 100644 index 0000000000000..dc326e00478d9 --- /dev/null +++ b/scripts/build/__tests__/optimization-integration.test.js @@ -0,0 +1,68 @@ +import { + describe, it, vi, expect, beforeEach, afterEach, +} from 'vitest'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const expectedOptimizationConfigCachePath = path.resolve( + path.dirname(fileURLToPath(import.meta.url)), + '../../../temp/optimization_config', +); + +vi.mock('@adguard/filters-compiler', () => ({ + compile: vi.fn().mockResolvedValue(undefined), + optimizationConfigLocal: { + setPath: vi.fn(), + generate: vi.fn().mockResolvedValue(undefined), + }, +})); + +vi.mock('fs', () => ({ + default: { + existsSync: vi.fn().mockReturnValue(false), + promises: { + cp: vi.fn().mockResolvedValue(undefined), + rm: vi.fn().mockResolvedValue(undefined), + writeFile: vi.fn().mockResolvedValue(undefined), + }, + }, +})); + +vi.mock('../../utils/find_files.js', () => ({ + findFiles: vi.fn().mockResolvedValue([]), +})); + +describe('build.js optimization config integration', () => { + const originalArgv = process.argv; + + beforeEach(() => { + vi.resetModules(); + }); + + afterEach(() => { + process.argv = originalArgv; + vi.clearAllMocks(); + }); + + it('setPath is called with optimizationConfigCacheDir when --use-cache', async () => { + process.argv = ['node', 'build.js', '--use-cache']; + await import('../build.js'); + + const { optimizationConfigLocal } = await import('@adguard/filters-compiler'); + await vi.waitFor(() => { + expect(optimizationConfigLocal.setPath).toHaveBeenCalledWith(expectedOptimizationConfigCachePath); + }); + }); + + it('generate and setPath are called in sequence with optimizationConfigCacheDir ' + + 'when --generate-cache', async () => { + process.argv = ['node', 'build.js', '--generate-cache']; + await import('../build.js'); + + const { optimizationConfigLocal } = await import('@adguard/filters-compiler'); + await vi.waitFor(() => { + expect(optimizationConfigLocal.generate).toHaveBeenCalledWith(expectedOptimizationConfigCachePath); + expect(optimizationConfigLocal.setPath).toHaveBeenCalledWith(expectedOptimizationConfigCachePath); + }); + }); +}); diff --git a/vitest.config.ts b/vitest.config.ts index 49fa6dfd524cc..00de9d41adb39 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -7,7 +7,10 @@ export default defineConfig({ enabled: true, tsconfig: './tsconfig.json', }, - include: ['scripts/wildcard-domain-processor/__tests__/*.test.ts'], + include: [ + 'scripts/wildcard-domain-processor/__tests__/*.test.ts', + 'scripts/build/__tests__/*.test.{js,ts}', + ], watch: false, silent: true, }, From 34878cf4c703a24cddbb5bc49906683603b5d526 Mon Sep 17 00:00:00 2001 From: Mu-Hun Date: Mon, 27 Apr 2026 17:26:27 +0900 Subject: [PATCH 5/8] feat(build): log active local optimization config path No output when setPath() activates local config, making it non-obvious whether the feature is in use. Co-authored-by: Copilot --- scripts/build/build.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/build/build.js b/scripts/build/build.js index 711fbafce9947..f70a31a5b0d81 100755 --- a/scripts/build/build.js +++ b/scripts/build/build.js @@ -138,6 +138,8 @@ const buildFilters = async () => { if (generateCache) { await optimizationConfigLocal.generate(optimizationConfigCachePath); optimizationConfigLocal.setPath(optimizationConfigCachePath); + // eslint-disable-next-line no-console + console.log(`Using local optimization config from: ${optimizationConfigCachePath}`); await compile( filtersDir, @@ -172,6 +174,8 @@ const buildFilters = async () => { if (useCache) { await prepareCachedFiltersDir(); optimizationConfigLocal.setPath(optimizationConfigCachePath); + // eslint-disable-next-line no-console + console.log(`Using local optimization config from: ${optimizationConfigCachePath}`); } try { From 7691c68bc61be7981a51e53f9436248097a83fc6 Mon Sep 17 00:00:00 2001 From: Mu-Hun Date: Mon, 27 Apr 2026 17:28:06 +0900 Subject: [PATCH 6/8] fix(build): reset the optimization cache before generate --- scripts/build/build.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build/build.js b/scripts/build/build.js index f70a31a5b0d81..7301c8cc35d68 100755 --- a/scripts/build/build.js +++ b/scripts/build/build.js @@ -136,6 +136,7 @@ const buildFilters = async () => { // When --generate-cache we only need to compile filters (which updates filter.txt), // skip platform generation, patches preparation, and temp/platforms copying. if (generateCache) { + await fs.promises.rm(optimizationConfigCachePath, { recursive: true, force: true }); await optimizationConfigLocal.generate(optimizationConfigCachePath); optimizationConfigLocal.setPath(optimizationConfigCachePath); // eslint-disable-next-line no-console From 531d85588fb0425fed6056026c20769c37b54eab Mon Sep 17 00:00:00 2001 From: Mu-Hun Date: Mon, 27 Apr 2026 17:40:53 +0900 Subject: [PATCH 7/8] ci: add test workflow on pull_request --- .github/workflows/test.yaml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/test.yaml diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000000000..581f020a6d31d --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,26 @@ +name: Test + +on: + workflow_dispatch: + pull_request: + +jobs: + test: + runs-on: ubuntu-slim + steps: + - name: Checkout repo + uses: actions/checkout@v6 + with: + fetch-depth: 1 + + - name: Use Node.js + uses: actions/setup-node@v6 + with: + node-version: 24 + cache: 'yarn' + + - name: Install dependencies + run: yarn + + - name: Test + run: yarn test From 3e2d9bd60390844a9565cfaca4e0109449fe6af6 Mon Sep 17 00:00:00 2001 From: Mu-Hun Date: Mon, 27 Apr 2026 17:43:51 +0900 Subject: [PATCH 8/8] fix(ci): enable corepack so yarn is available on ubuntu-slim --- .github/workflows/test.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 581f020a6d31d..c80ab7d18fe3f 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -17,7 +17,9 @@ jobs: uses: actions/setup-node@v6 with: node-version: 24 - cache: 'yarn' + + - name: Enable corepack + run: corepack enable - name: Install dependencies run: yarn