-
Notifications
You must be signed in to change notification settings - Fork 98
feat: support block sync packages #929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThe pull request introduces package blocking controls to prevent syncing of specific scopes and packages via new whitelist fields in PackageVersionFileService. It renames Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary of ChangesHello @fengmk2, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a critical feature for managing package synchronization by allowing the explicit blocking of packages or scopes. This provides greater control over the content being mirrored, preventing unwanted or problematic packages from being synced. Additionally, it refines the existing large package version handling to be more robust, ensuring that oversized packages that are not whitelisted immediately fail their sync tasks, improving the reliability and predictability of the synchronization process. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces support for blocking package synchronization based on a configurable blocklist. The changes include adding a check for blocked packages at the start of the sync task, and modifying the behavior for large packages to fail the entire sync task instead of just skipping a version. The implementation is logical and includes corresponding test updates. My main feedback is regarding code duplication for handling task failures, which could be refactored to improve maintainability.
| if (await this.packageVersionFileService.isPackageBlockedToSync(scope, name)) { | ||
| task.error = `stop sync by block list, see ${UNPKG_WHITE_LIST_URL}`; | ||
| logs.push(`[${isoNow()}] ❌ ${task.error}, log: ${logUrl}`); | ||
| logs.push(`[${isoNow()}] ❌❌❌❌❌ ${fullname} ❌❌❌❌❌`); | ||
| await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); | ||
| this.logger.info( | ||
| '[PackageSyncerService.executeTask:fail-package-blocked-to-sync] taskId: %s, targetName: %s, %s', | ||
| task.taskId, | ||
| task.targetName, | ||
| task.error, | ||
| ); | ||
| return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block of code for failing a task is very similar to the logic in other parts of this file (e.g., lines 511-521, 892-902, and 1396-1406). To improve maintainability and reduce redundancy, consider extracting this logic into a private helper method. This would make the code cleaner and easier to manage in the future.
| if (!isAllowLargePackageVersion) { | ||
| lastErrorMessage = `large package version size: ${size}, allow size: ${this.config.cnpmcore.largePackageVersionSize}, see ${UNPKG_WHITE_LIST_URL}`; | ||
| logs.push(`[${isoNow()}] ❌ [${syncIndex}] Synced version ${version} fail, ${lastErrorMessage}`); | ||
| await this.taskService.appendTaskLog(task, logs.join('\n')); | ||
| logs = []; | ||
| continue; | ||
| task.error = `Synced version ${version} fail, large package version size: ${size}, allow size: ${this.config.cnpmcore.largePackageVersionSize}, see ${UNPKG_WHITE_LIST_URL}`; | ||
| logs.push(`[${isoNow()}] ❌ ${task.error}, log: ${logUrl}`); | ||
| logs.push(`[${isoNow()}] ❌❌❌❌❌ ${fullname} ❌❌❌❌❌`); | ||
| await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); | ||
| this.logger.info( | ||
| '[PackageSyncerService.executeTask:fail-large-package-version-size] taskId: %s, targetName: %s, %s', | ||
| task.taskId, | ||
| task.targetName, | ||
| task.error, | ||
| ); | ||
| return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if (!isAllowLargePackageVersion) { | ||
| lastErrorMessage = `large package version size: ${size}, allow size: ${this.config.cnpmcore.largePackageVersionSize}, see ${UNPKG_WHITE_LIST_URL}`; | ||
| logs.push(`[${isoNow()}] ❌ [${syncIndex}] Synced version ${version} fail, ${lastErrorMessage}`); | ||
| await this.taskService.appendTaskLog(task, logs.join('\n')); | ||
| logs = []; | ||
| continue; | ||
| task.error = `Synced version ${version} fail, large package version size: ${size}, allow size: ${this.config.cnpmcore.largePackageVersionSize}, see ${UNPKG_WHITE_LIST_URL}`; | ||
| logs.push(`[${isoNow()}] ❌ ${task.error}, log: ${logUrl}`); | ||
| logs.push(`[${isoNow()}] ❌❌❌❌❌ ${fullname} ❌❌❌❌❌`); | ||
| await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); | ||
| this.logger.info( | ||
| '[PackageSyncerService.executeTask:fail-large-package-version-size] taskId: %s, targetName: %s, %s', | ||
| task.taskId, | ||
| task.targetName, | ||
| task.error, | ||
| ); | ||
| return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #929 +/- ##
==========================================
- Coverage 95.38% 95.27% -0.11%
==========================================
Files 197 197
Lines 22211 22263 +52
Branches 2614 2072 -542
==========================================
+ Hits 21185 21212 +27
- Misses 1026 1051 +25 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
app/core/service/PackageSyncerService.ts (2)
524-536: Consider gatingisPackageBlockedToSync()behind the feature flag to avoid unnecessary work.
IfisPackageBlockedToSync()isn’t already a cheap no-op whenenableSyncUnpkgFilesWhiteList=false, this adds avoidable overhead on every sync task.Suggested diff:
- if (await this.packageVersionFileService.isPackageBlockedToSync(scope, name)) { + if ( + this.config.cnpmcore.enableSyncUnpkgFilesWhiteList && + (await this.packageVersionFileService.isPackageBlockedToSync(scope, name)) + ) { task.error = `stop sync by block list, see ${UNPKG_WHITE_LIST_URL}`; logs.push(`[${isoNow()}] ❌ ${task.error}, log: ${logUrl}`); logs.push(`[${isoNow()}] ❌❌❌❌❌ ${fullname} ❌❌❌❌❌`); await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); this.logger.info( '[PackageSyncerService.executeTask:fail-package-blocked-to-sync] taskId: %s, targetName: %s, %s', task.taskId, task.targetName, task.error, ); return; }
885-907: Rename localisAllowLargePackageVersionto match new API + keep fail-fast consistent.
Small clarity improvement; the new fail-fast behavior aligns with the added tests.Suggested diff:
- const isAllowLargePackageVersion = await this.packageVersionFileService.isLargePackageVersionAllowed( + const isLargePackageVersionAllowed = await this.packageVersionFileService.isLargePackageVersionAllowed( scope, name, version, ); - if (!isAllowLargePackageVersion) { + if (!isLargePackageVersionAllowed) { task.error = `Synced version ${version} fail, large package version size: ${size}, allow size: ${this.config.cnpmcore.largePackageVersionSize}, see ${UNPKG_WHITE_LIST_URL}`; logs.push(`[${isoNow()}] ❌ ${task.error}, log: ${logUrl}`); logs.push(`[${isoNow()}] ❌❌❌❌❌ ${fullname} ❌❌❌❌❌`); await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); this.logger.info( '[PackageSyncerService.executeTask:fail-large-package-version-size] taskId: %s, targetName: %s, %s', task.taskId, task.targetName, task.error, ); return; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/core/service/PackageSyncerService.ts(3 hunks)app/core/service/PackageVersionFileService.ts(3 hunks)test/core/service/PackageSyncerService/executeTask.test.ts(2 hunks)test/core/service/PackageSyncerService/executeTaskWithPackument.test.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{js,ts,tsx,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{js,ts,tsx,jsx}: Use single quotes in JavaScript/TypeScript code (from Prettier configuration)
Use 2-space indentation (from Prettier configuration)
Maintain 120 character line width maximum (from Prettier configuration)
Use trailing commas in ES5 syntax (from Prettier configuration)
Avoid parentheses in arrow functions when possible (from Prettier configuration)
Maximum of 6 function parameters (from Oxlint configuration)
Warn on console usage (from Oxlint configuration)
Disallow anonymous default exports (from Oxlint configuration)
Use ES modules (import/export) syntax throughout
Files:
app/core/service/PackageVersionFileService.tsapp/core/service/PackageSyncerService.tstest/core/service/PackageSyncerService/executeTaskWithPackument.test.tstest/core/service/PackageSyncerService/executeTask.test.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}: Use strict TypeScript with comprehensive type definitions - avoidanytypes, use proper typing orunknown
Export types and interfaces for reusability in TypeScript
Files:
app/core/service/PackageVersionFileService.tsapp/core/service/PackageSyncerService.tstest/core/service/PackageSyncerService/executeTaskWithPackument.test.tstest/core/service/PackageSyncerService/executeTask.test.ts
app/core/service/**/*.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
app/core/service/**/*.ts: Services must implement core business logic without HTTP concerns or direct database access
Services must use@SingletonProto()for service lifecycle management
Services must orchestrate multiple repositories and entities, managing transactions and events
Files:
app/core/service/PackageVersionFileService.tsapp/core/service/PackageSyncerService.ts
**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.ts: Use strict TypeScript with proper typing - avoidanytypes, use proper typing orunknowninstead
Use ES modules withimport/exportsyntax throughout the codebase
Use single quotes (') for strings
Use 2-space indentation
Enforce 120 character line width
Use ES5 trailing commas
Limit functions to a maximum of 6 parameters
Do not use console statements - use logger instead
Files:
app/core/service/PackageVersionFileService.tsapp/core/service/PackageSyncerService.tstest/core/service/PackageSyncerService/executeTaskWithPackument.test.tstest/core/service/PackageSyncerService/executeTask.test.ts
test/**/*.test.ts
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
test/**/*.test.ts: Test files must use.test.tssuffix
Tests must use@eggjs/mockfor mocking and testing
Tests must useassertfromnode:assert/strictfor assertions
Test files should be organized intest/directory mirroring source structure
Mock external dependencies usingmock()from@eggjs/mockin tests
Use realistic test data created throughTestUtilhelper methods
Clean up after tests - database is reset between test files
Test both success and failure cases - error paths are equally important
Test files should follow naming pattern: describe('[HTTP_METHOD /api/path] functionName()', ...)
test/**/*.test.ts: Test files must use.test.tssuffix
Use@eggjs/mockfor mocking in test files
Useassertfromnode:assert/strictin test files
Test files must mirror source structure intest/directory and test both success and error cases
Files:
test/core/service/PackageSyncerService/executeTaskWithPackument.test.tstest/core/service/PackageSyncerService/executeTask.test.ts
🧠 Learnings (1)
📚 Learning: 2025-11-29T15:42:37.586Z
Learnt from: CR
Repo: cnpm/cnpmcore PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-29T15:42:37.586Z
Learning: Applies to test/**/*.test.ts : Mock external dependencies using `mock()` from `eggjs/mock` in tests
Applied to files:
test/core/service/PackageSyncerService/executeTaskWithPackument.test.tstest/core/service/PackageSyncerService/executeTask.test.ts
🧬 Code graph analysis (2)
app/core/service/PackageVersionFileService.ts (2)
app/core/entity/Package.ts (1)
fullname(63-65)app/common/PackageUtil.ts (1)
getFullname(25-27)
app/core/service/PackageSyncerService.ts (3)
app/core/service/PackageVersionFileService.ts (1)
UNPKG_WHITE_LIST_URL(24-24)app/common/LogUtil.ts (1)
isoNow(1-3)app/core/entity/Package.ts (1)
fullname(63-65)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
- GitHub Check: test on mysql (node@20, shard@1/3, enableJSONBuilder@false)
- GitHub Check: test on mysql (node@22, shard@0/3, enableJSONBuilder@true)
- GitHub Check: test on mysql (node@22, shard@2/3, enableJSONBuilder@true)
- GitHub Check: test on mysql (node@20, shard@2/3, enableJSONBuilder@true)
- GitHub Check: test on mysql (node@20, shard@1/3, enableJSONBuilder@true)
- GitHub Check: test on mysql (node@24, shard@0/3, enableJSONBuilder@true)
- GitHub Check: test on mysql (node@20, shard@2/3, enableJSONBuilder@false)
- GitHub Check: test on mysql (node@24, shard@2/3, enableJSONBuilder@false)
- GitHub Check: test on postgresql (node@20, shard@0/3)
- GitHub Check: test on postgresql (node@24, shard@0/3)
- GitHub Check: test on postgresql (node@20, shard@1/3)
- GitHub Check: test on postgresql (node@22, shard@0/3)
- GitHub Check: test on postgresql (node@20, shard@2/3)
- GitHub Check: test on postgresql (node@22, shard@1/3)
- GitHub Check: test on postgresql (node@24, shard@1/3)
- GitHub Check: test on postgresql (node@22, shard@2/3)
- GitHub Check: test on postgresql (node@24, shard@2/3)
- GitHub Check: test-deployment
- GitHub Check: build-and-push-image
🔇 Additional comments (7)
app/core/service/PackageVersionFileService.ts (4)
63-66: LGTM! Clean addition of block sync fields.The new private fields for blocking scopes and packages follow the established naming conventions and are properly typed as string arrays, consistent with the existing whitelist fields.
126-136: LGTM! Whitelist update correctly populates block sync data.The new block sync fields are populated from the manifest using the same pattern as existing whitelist fields, with appropriate fallback to empty arrays. The log output enhancement provides useful visibility into the block list counts.
139-152: LGTM! Method rename improves API naming.The rename from
isAllowLargePackageVersiontoisLargePackageVersionAllowedis more grammatically correct and follows better naming conventions (adjective form). The implementation remains unchanged, preserving existing behavior.
154-170: LGTM! New block check method is well-implemented.The
isPackageBlockedToSyncmethod follows the same pattern asisLargePackageVersionAllowed, with proper config checks, whitelist updates, and scope/package-level blocking logic. The use ofgetFullnamehelper is correct for constructing the full package identifier.test/core/service/PackageSyncerService/executeTaskWithPackument.test.ts (1)
2251-2251: LGTM! Test mock correctly updated.The mock is properly updated to reflect the API rename from
isAllowLargePackageVersiontoisLargePackageVersionAllowed, ensuring test compatibility with the service changes.test/core/service/PackageSyncerService/executeTask.test.ts (1)
2292-2292: Good update for renamed API (isLargePackageVersionAllowed).
Keeps the test aligned with the newPackageVersionFileServicemethod name.app/core/service/PackageSyncerService.ts (1)
1388-1411: Packument path matches the same large-version fail-fast policy (good).
Nice to see the same policy mirrored insyncPackageWithPackument()so behavior doesn’t diverge by code path.
| it('should stop sync by block list, see https://github.com/cnpm/unpkg-white-list', async () => { | ||
| const name = 'cnpmcore-test-sync-blocklist'; | ||
| mock(app.config.cnpmcore, 'enableSyncUnpkgFilesWhiteList', true); | ||
| mock(PackageVersionFileService.prototype, 'isPackageBlockedToSync', async () => true); | ||
| await packageSyncerService.createTask(name); | ||
| const task = await packageSyncerService.findExecuteTask(); | ||
| assert.ok(task); | ||
| assert.equal(task.targetName, name); | ||
| await packageSyncerService.executeTask(task); | ||
| const stream = await packageSyncerService.findTaskLog(task); | ||
| assert.ok(stream); | ||
| const log = await TestUtil.readStreamToLog(stream); | ||
| // console.log(log); | ||
| assert.ok(log.includes(`❌❌❌❌❌ ${name} ❌❌❌❌❌`)); | ||
| assert.ok(log.includes('❌ stop sync by block list, see https://github.com/cnpm/unpkg-white-list')); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Check the package.json to understand which mock library is used
cat package.json | grep -A2 -B2 mockRepository: cnpm/cnpmcore
Length of output: 332
🏁 Script executed:
# Look for mock restore patterns in the test file
cd test/core/service/PackageSyncerService && wc -l executeTask.test.tsRepository: cnpm/cnpmcore
Length of output: 81
🏁 Script executed:
# Search for existing mock restore patterns in the test suite
rg "mock\(.+\)" test/core/service/PackageSyncerService/executeTask.test.ts -A 3 | head -50Repository: cnpm/cnpmcore
Length of output: 8291
🏁 Script executed:
# Check if there are afterEach hooks that restore mocks
rg "afterEach|restore" test/core/service/PackageSyncerService/executeTask.test.tsRepository: cnpm/cnpmcore
Length of output: 197
🏁 Script executed:
# Look for the mock library import and how it's used
head -50 test/core/service/PackageSyncerService/executeTask.test.tsRepository: cnpm/cnpmcore
Length of output: 2992
🏁 Script executed:
# Get the test at lines 2046-2061 and surrounding context to check for cleanup
sed -n '2046,2070p' test/core/service/PackageSyncerService/executeTask.test.tsRepository: cnpm/cnpmcore
Length of output: 4687
🏁 Script executed:
# Search for afterEach hooks in the entire test file
rg "afterEach|afterAll" test/core/service/PackageSyncerService/executeTask.test.ts -A 5Repository: cnpm/cnpmcore
Length of output: 39
🏁 Script executed:
# Check for other prototype mocking patterns in the file
rg "mock\(\w+\.prototype" test/core/service/PackageSyncerService/executeTask.test.tsRepository: cnpm/cnpmcore
Length of output: 311
🏁 Script executed:
# Verify @eggjs/mock documentation by checking if there's a README or guide
find . -name "*.md" -type f | xargs grep -l "@eggjs/mock" 2>/dev/null | head -5Repository: cnpm/cnpmcore
Length of output: 102
🏁 Script executed:
# Check one more test that uses prototype mocking to see if it has restore
rg -B5 -A10 "NPMRegistry\.prototype.*getSyncTask" test/core/service/PackageSyncerService/executeTask.test.ts | head -30Repository: cnpm/cnpmcore
Length of output: 773
🏁 Script executed:
# Check if there's an afterEach or test cleanup at the describe block level
sed -n '1,100p' test/core/service/PackageSyncerService/executeTask.test.ts | grep -A 10 "describe"Repository: cnpm/cnpmcore
Length of output: 1039
🏁 Script executed:
# Look for any test runner configuration or setup files
find . -maxdepth 2 -name "*.config.*" -o -name "test.setup.*" -o -name "mocha.opts" | head -10Repository: cnpm/cnpmcore
Length of output: 39
🏁 Script executed:
# Check if @eggjs/mock has auto-restore behavior by looking at package docs or comments
cat package.json | grep -A 5 "@eggjs/mock"Repository: cnpm/cnpmcore
Length of output: 283
Add explicit mock restoration to prevent prototype-mock leakage across tests.
The mock(PackageVersionFileService.prototype, 'isPackageBlockedToSync', ...) call should be restored after the test completes. @eggjs/mock does not automatically restore prototype mocks between test cases, so subsequent tests in the same describe block may inherit this mock and trigger unexpected behavior. Add await mock.restore(); before the test closes.
it('should stop sync by block list, see https://github.com/cnpm/unpkg-white-list', async () => {
const name = 'cnpmcore-test-sync-blocklist';
mock(app.config.cnpmcore, 'enableSyncUnpkgFilesWhiteList', true);
mock(PackageVersionFileService.prototype, 'isPackageBlockedToSync', async () => true);
await packageSyncerService.createTask(name);
const task = await packageSyncerService.findExecuteTask();
assert.ok(task);
assert.equal(task.targetName, name);
await packageSyncerService.executeTask(task);
const stream = await packageSyncerService.findTaskLog(task);
assert.ok(stream);
const log = await TestUtil.readStreamToLog(stream);
// console.log(log);
assert.ok(log.includes(`❌❌❌❌❌ ${name} ❌❌❌❌❌`));
assert.ok(log.includes('❌ stop sync by block list, see https://github.com/cnpm/unpkg-white-list'));
+ await mock.restore();
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| it('should stop sync by block list, see https://github.com/cnpm/unpkg-white-list', async () => { | |
| const name = 'cnpmcore-test-sync-blocklist'; | |
| mock(app.config.cnpmcore, 'enableSyncUnpkgFilesWhiteList', true); | |
| mock(PackageVersionFileService.prototype, 'isPackageBlockedToSync', async () => true); | |
| await packageSyncerService.createTask(name); | |
| const task = await packageSyncerService.findExecuteTask(); | |
| assert.ok(task); | |
| assert.equal(task.targetName, name); | |
| await packageSyncerService.executeTask(task); | |
| const stream = await packageSyncerService.findTaskLog(task); | |
| assert.ok(stream); | |
| const log = await TestUtil.readStreamToLog(stream); | |
| // console.log(log); | |
| assert.ok(log.includes(`❌❌❌❌❌ ${name} ❌❌❌❌❌`)); | |
| assert.ok(log.includes('❌ stop sync by block list, see https://github.com/cnpm/unpkg-white-list')); | |
| }); | |
| it('should stop sync by block list, see https://github.com/cnpm/unpkg-white-list', async () => { | |
| const name = 'cnpmcore-test-sync-blocklist'; | |
| mock(app.config.cnpmcore, 'enableSyncUnpkgFilesWhiteList', true); | |
| mock(PackageVersionFileService.prototype, 'isPackageBlockedToSync', async () => true); | |
| await packageSyncerService.createTask(name); | |
| const task = await packageSyncerService.findExecuteTask(); | |
| assert.ok(task); | |
| assert.equal(task.targetName, name); | |
| await packageSyncerService.executeTask(task); | |
| const stream = await packageSyncerService.findTaskLog(task); | |
| assert.ok(stream); | |
| const log = await TestUtil.readStreamToLog(stream); | |
| // console.log(log); | |
| assert.ok(log.includes(`❌❌❌❌❌ ${name} ❌❌❌❌❌`)); | |
| assert.ok(log.includes('❌ stop sync by block list, see https://github.com/cnpm/unpkg-white-list')); | |
| await mock.restore(); | |
| }); |
🤖 Prompt for AI Agents
In test/core/service/PackageSyncerService/executeTask.test.ts around lines 2046
to 2061, the prototype mock for PackageVersionFileService.isPackageBlockedToSync
is not restored, which can leak into subsequent tests; add a call to await
mock.restore() at the end of this test (after the assertions) or wrap the test
body in try/finally and call await mock.restore() in finally to ensure the
prototype mock is always restored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for blocking package synchronization through the unpkg-white-list manifest. It introduces a new mechanism to prevent specific packages or scopes from being synced, complementing the existing allow-list and large package version controls.
Key changes:
- Added
isPackageBlockedToSyncmethod to check if packages are in block lists - Renamed
isAllowLargePackageVersiontoisLargePackageVersionAllowedfor naming consistency - Changed large package version handling behavior from skipping to failing the entire sync task
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| app/core/service/PackageVersionFileService.ts | Added block sync support with new private fields for blocked scopes/packages, implemented isPackageBlockedToSync method, and renamed isAllowLargePackageVersion to isLargePackageVersionAllowed |
| app/core/service/PackageSyncerService.ts | Added early check for blocked packages, changed large package version handling from continuing to failing the task, and updated method calls to use renamed method |
| test/core/service/PackageSyncerService/executeTask.test.ts | Added integration test for block list functionality and updated mock calls to use renamed method |
| test/core/service/PackageSyncerService/executeTaskWithPackument.test.ts | Updated mock calls to use renamed method isLargePackageVersionAllowed |
| task.error = `Synced version ${version} fail, large package version size: ${size}, allow size: ${this.config.cnpmcore.largePackageVersionSize}, see ${UNPKG_WHITE_LIST_URL}`; | ||
| logs.push(`[${isoNow()}] ❌ ${task.error}, log: ${logUrl}`); | ||
| logs.push(`[${isoNow()}] ❌❌❌❌❌ ${fullname} ❌❌❌❌❌`); | ||
| await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); | ||
| this.logger.info( | ||
| '[PackageSyncerService.executeTask:fail-large-package-version-size] taskId: %s, targetName: %s, %s', | ||
| task.taskId, | ||
| task.targetName, | ||
| task.error, | ||
| ); | ||
| return; |
Copilot
AI
Dec 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changes the behavior from skipping large versions and continuing with other versions to failing the entire sync task when a large version is encountered that is not allowed. This is a breaking behavior change that could impact users who were previously able to partially sync packages with mixed version sizes. Consider documenting this breaking change in the PR description or changelog.
| task.error = `Synced version ${version} fail, large package version size: ${size}, allow size: ${this.config.cnpmcore.largePackageVersionSize}, see ${UNPKG_WHITE_LIST_URL}`; | |
| logs.push(`[${isoNow()}] ❌ ${task.error}, log: ${logUrl}`); | |
| logs.push(`[${isoNow()}] ❌❌❌❌❌ ${fullname} ❌❌❌❌❌`); | |
| await this.taskService.finishTask(task, TaskState.Fail, logs.join('\n')); | |
| this.logger.info( | |
| '[PackageSyncerService.executeTask:fail-large-package-version-size] taskId: %s, targetName: %s, %s', | |
| task.taskId, | |
| task.targetName, | |
| task.error, | |
| ); | |
| return; | |
| const errorMsg = `Synced version ${version} fail, large package version size: ${size}, allow size: ${this.config.cnpmcore.largePackageVersionSize}, see ${UNPKG_WHITE_LIST_URL}`; | |
| logs.push(`[${isoNow()}] ❌ ${errorMsg}, log: ${logUrl}`); | |
| logs.push(`[${isoNow()}] ❌❌❌❌❌ ${fullname} ❌❌❌❌❌`); | |
| await this.taskService.appendTaskLog(task, logs.join('\n')); | |
| logs = []; | |
| this.logger.info( | |
| '[PackageSyncerService.executeTask:skip-large-package-version-size] taskId: %s, targetName: %s, %s', | |
| task.taskId, | |
| task.targetName, | |
| errorMsg, | |
| ); | |
| continue; |
| async isPackageBlockedToSync(pkgScope: string, pkgName: string) { | ||
| if (!this.config.cnpmcore.enableSyncUnpkgFilesWhiteList) return false; | ||
| await this.#updateUnpkgWhiteList(); | ||
|
|
||
| // check block scopes | ||
| if (this.#unpkgWhiteListBlockSyncScopes.includes(pkgScope)) return true; | ||
|
|
||
| // check block packages | ||
| const fullname = getFullname(pkgScope, pkgName); | ||
| return this.#unpkgWhiteListBlockSyncPackages.includes(fullname); | ||
| } |
Copilot
AI
Dec 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new isPackageBlockedToSync method lacks direct unit tests. While there is an integration test that mocks this method, there are no tests that verify the actual logic of checking block sync scopes and packages against the unpkg whitelist manifest. Consider adding unit tests to verify the behavior when packages/scopes are in blockSyncScopes and blockSyncPackages arrays, similar to how isLargePackageVersionAllowed is tested.
|
🎉 This PR is included in version 4.17.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary by CodeRabbit
New Features
Bug Fixes
✏️ Tip: You can customize this high-level summary in your review settings.