-
Notifications
You must be signed in to change notification settings - Fork 5.8k
fix(publish): honor jsr.json fallback and flag config conflicts #31383
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
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis change adds support for discovering and handling jsr.json configuration files throughout the codebase. The DenoOrPkgJson enum is replaced with a new ConfigFolder struct that aggregates deno.json, jsr.json, and package.json sources. A new ConflictingPublishConfig diagnostic is introduced to detect when both deno.json and jsr.json contain publish configurations. The WorkspaceFactoryOptions now uses a discover_jsr_config flag instead of additional_config_file_names. Workspace discovery logic is extended to load jsr.json when the discovery option is enabled, and the publish flow is updated to process JSR configs alongside Deno configs. An integration test validates publishing with jsr.json as a configuration source. Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 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 |
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: 0
🧹 Nitpick comments (1)
cli/tools/publish/mod.rs (1)
1573-1625: Tests cover core scenarios.The tests verify:
- Reading valid jsr.json successfully
- Strict mode validation (missing name errors)
Consider adding a test for non-strict mode behavior: verify that
maybe_jsr_package_configwithstrict=falsereturnsNone(rather than erroring) when jsr.json exists but lacks required fields.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (3)
cli/Cargo.toml(1 hunks)cli/tools/publish/diagnostics.rs(10 hunks)cli/tools/publish/mod.rs(7 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
cli/tools/publish/diagnostics.rs (1)
cli/lsp/documents.rs (1)
primary_specifier(1437-1449)
cli/tools/publish/mod.rs (5)
libs/config/workspace/mod.rs (6)
workspace(2307-2311)workspace(2312-2312)default(1519-1521)dir_path(1717-1719)diagnostics(992-1185)empty(1549-1564)libs/maybe_sync/lib.rs (1)
new_rc(104-106)cli/factory.rs (2)
sys(517-519)default(251-253)libs/config/deno_json/mod.rs (2)
dir_path(1435-1441)read(1360-1370)cli/tools/publish/diagnostics.rs (2)
message(228-275)hint(430-477)
⏰ 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). (10)
- GitHub Check: test release linux-x86_64
- GitHub Check: test debug linux-aarch64
- GitHub Check: test debug macos-aarch64
- GitHub Check: test debug linux-x86_64
- GitHub Check: test debug windows-x86_64
- GitHub Check: test debug macos-x86_64
- GitHub Check: lint debug windows-x86_64
- GitHub Check: lint debug macos-x86_64
- GitHub Check: lint debug linux-x86_64
- GitHub Check: build libs
🔇 Additional comments (7)
cli/Cargo.toml (1)
80-80: LGTM - Dependency is properly utilized.The
deno_maybe_syncdependency is used incli/tools/publish/mod.rs(line 31) for thenew_rcutility function that wraps config objects.cli/tools/publish/diagnostics.rs (2)
145-148: LGTM - New diagnostic variant added.The
ConflictingPublishConfigvariant is properly structured with both a primary specifier for error location and a full list of conflicting specifiers for the message.
200-200: LGTM - Complete and consistent diagnostic implementation.The new diagnostic is fully integrated across all trait methods (
level,code,message,location,snippet,hint,docs_url) following the existing patterns in this file.Also applies to: 222-224, 266-273, 347-351, 426-426, 473-475, 610-612
cli/tools/publish/mod.rs (4)
19-19: LGTM - Imports are properly used.All three imports are utilized in the new
maybe_jsr_package_configfunction and tests.Also applies to: 31-31, 58-58
92-119: Conflict detection logic is sound, but consider error handling clarity.The two-phase approach is correct:
- When
publish_configsexist (from deno.json), check for jsr.json conflicts without requiring it to be valid (strict=false)- When no publish configs exist, look for jsr.json and require it to be valid (
strict=true)However, note that when
strict=false(line 95), the function will still error on JSON parse errors or I/O errors - it only skips files that are valid JSON but lack required fields. This means if a user has a malformed jsr.json alongside a valid deno.json, publishing will fail. This might be intentional (invalid jsr.json should always be flagged), but consider if this is the desired UX.Verify this behavior is acceptable: Should a malformed jsr.json block publishing when deno.json is the intended config?
379-418: LGTM - Helper function correctly implements fallback logic.The function properly handles both strict and non-strict modes:
- Non-strict mode: Returns
Noneif jsr.json/jsr.jsonc don't exist or lack required fields (name/exports)- Strict mode: Errors if files exist but lack required fields
The iteration over both "jsr.json" and "jsr.jsonc" ensures .jsonc fallback works as expected.
1627-1640: LGTM - Diagnostic test verifies message formatting.The test confirms the diagnostic lists all conflicting specifiers in the message and provides an appropriate hint.
|
@coderabbitai help |
ChatThere are 3 ways to chat with CodeRabbit:
CodeRabbit commands
Other keywords and placeholders
CodeRabbit configuration file (
|
@coderabbitai I added a test as a reference to the nitpick comment, (8a3e817). Review it. |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 1257 @Pinta365, the test looks good! It correctly addresses the nitpick by verifying that ✅ Creates a jsr.json with only a The implementation is clean and the test name clearly describes the expected behavior. This completes the test coverage for the non-strict mode fallback scenario. |
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 doesn't look like it will work when publishing a workspace. For example, someone might publish a workspace with members containing a deno.json and jsr.json -- Maybe we need more of a first class solution in libs/config instead of trying to fix this in the cli.
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.
For example, maybe we can get rid of additional_config_file_names and instead have a more specific discover_jsr_config: true flag that will surface a WorkspaceDiagnostic for this scenario.
Related is my comment here: https://github.com/denoland/deno/pull/31383/files#r2572813359 -- fixing that will help fix this.
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.
Ahh yes, I see what you mean with workspaces. This only works as a solution for the root package basically.
cli/tools/publish/mod.rs
Outdated
| ); | ||
| } | ||
|
|
||
| fn maybe_jsr_package_config( |
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.
maybe_package_config() on WorkspaceDirectory needs to be the source of truth for JsrPackageConfig. That way, someone using workspace_directory.maybe_package_config() will always get the right information (so, in other words, we should remove this function and make this work in WorkspaceDirectory.maybe_package_config())
For example, right now cli/tools/lint/mod.rs calls workspace_directory.maybe_package_config() and right now in this PR it's not getting the right information.
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.
I'll go back to the drawing table and come back with a suggested solution based on this input. Thanks for the review so far.
…conflicts with deno.json
… behavior of maybe_package_config()
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: 0
🧹 Nitpick comments (1)
libs/config/workspace/mod.rs (1)
385-397: jsr.json discovery and package selection path looks soundThe jsr integration path hangs together:
WorkspaceDiscoverOptions::discover_jsr_configandFolderConfigs::from_config_foldercleanly add jsr discovery without changing existing defaults (tests opt in explicitly; CLI turns it on via factory options).WorkspaceDirectorynow tracksjsr_jsonalongsidedeno_json/pkg_json, withresolve_member_dirusing a clear precedence: current folder → ancestors viaresolve_jsr_json_from_str→ root. This mirrors the existing deno/pkg resolution strategy and exits safely once the workspace root is passed.maybe_jsr_jsonandmaybe_package_configpreferdeno.jsonpackages and only fall back tojsr.jsonwhen there is no publishabledeno.json, which matches the PR’s intent while keeping behavior deterministic in conflict cases (and aligned with the new diagnostic).Workspace::jsr_packagesandresolver_jsr_pkgsboth respect that ordering; publish flows see only workspace members (config_folders), while resolver flows also include links and pick whichever config is the first publishable one.Overall this is a coherent extension of the existing model; I don’t see correctness or ordering issues.
It might be worth a small follow‑up to factor out “select the effective jsr package config (deno vs jsr)” into a shared helper to avoid duplicating the preference logic between
maybe_package_configandresolver_jsr_pkgs, but that’s purely cosmetic.Also applies to: 406-420, 735-742, 795-809, 876-887, 920-934, 971-987, 1590-1597, 1795-1797, 1803-1829
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
cli/factory.rs(1 hunks)cli/lsp/config.rs(2 hunks)cli/tools/publish/mod.rs(4 hunks)libs/config/workspace/discovery.rs(5 hunks)libs/config/workspace/mod.rs(13 hunks)libs/resolver/factory.rs(2 hunks)tests/integration/publish_tests.rs(1 hunks)tests/integration/run_tests.rs(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- cli/tools/publish/mod.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: For debugging Rust code, set breakpoints in IDE debuggers (VS Code with rust-analyzer, IntelliJ IDEA) or uselldbdirectly
Useeprintln!()ordbg!()macros for debug prints in Rust code
Files:
libs/resolver/factory.rstests/integration/run_tests.rstests/integration/publish_tests.rscli/lsp/config.rscli/factory.rslibs/config/workspace/mod.rslibs/config/workspace/discovery.rs
🧠 Learnings (1)
📚 Learning: 2025-11-24T16:19:37.808Z
Learnt from: CR
Repo: denoland/deno PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T16:19:37.808Z
Learning: Applies to tests/specs/**/{__test__.jsonc,*.out} : Output assertions in spec tests should use `__test__.jsonc` inline fields or `.out` files with special matching syntax: `[WILDCARD]`, `[WILDLINE]`, `[WILDCHAR]`, `[WILDCHARS(n)]`, `[UNORDERED_START]`/`[UNORDERED_END]`, and `[# comment]`
Applied to files:
tests/integration/run_tests.rs
🧬 Code graph analysis (4)
tests/integration/run_tests.rs (1)
libs/config/workspace/mod.rs (1)
new(443-470)
tests/integration/publish_tests.rs (1)
tests/util/server/src/builders.rs (1)
temp_dir(308-310)
libs/config/workspace/mod.rs (1)
libs/config/workspace/discovery.rs (3)
folder_url(70-86)deno_json(102-104)jsr_json(106-108)
libs/config/workspace/discovery.rs (1)
libs/config/workspace/mod.rs (2)
new(443-470)folder_url(2438-2443)
⏰ 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). (10)
- GitHub Check: test release linux-x86_64
- GitHub Check: test debug windows-x86_64
- GitHub Check: test debug linux-aarch64
- GitHub Check: test debug linux-x86_64
- GitHub Check: test debug macos-aarch64
- GitHub Check: test debug macos-x86_64
- GitHub Check: lint debug windows-x86_64
- GitHub Check: lint debug macos-x86_64
- GitHub Check: build libs
- GitHub Check: lint debug linux-x86_64
🔇 Additional comments (15)
libs/resolver/factory.rs (1)
200-220: JSR config discovery flag is plumbed correctly through workspace discoveryAdding
discover_jsr_config: booltoWorkspaceFactoryOptionsand passing it through toWorkspaceDiscoverOptionskeeps behavior opt‑in and avoids surprising defaults. Callers that care about JSR configs can now control discovery explicitly without changing existing behavior.Also applies to: 569-576
cli/lsp/config.rs (1)
1287-1293: LSP now consistently opts into JSR config discoveryUsing
discover_jsr_config: truein both the top‑levelWorkspaceDirectory::discoverand the LSP’sWorkspaceFactoryOptionsensures JSR configs participate in workspace resolution and npm/lockfile handling the same way as in the CLI. The change is localized and doesn’t alter existing settings behavior.Also applies to: 1427-1447
libs/config/workspace/mod.rs (2)
181-189: ConflictingPublishConfig diagnostic is wired correctlyThe new
ConflictingPublishConfigvariant and the diagnostics loop consistently detect the case where bothdeno.json(c)andjsr.json(c)in the same folder are “publishable” packages. Emitting the diagnostic withconfig_urlset to thejsr.jsonspecifier and including both URLs in the message makes the ambiguity clear and actionable. No functional issues here.Also applies to: 1193-1207
2988-3126: New jsr fallback and conflict tests cover the key scenariosThe four added tests exercise the important behaviors:
- jsr‑only package at the root.
- jsr fallback when
deno.jsonexists but is not a package.- resolver’s jsr package list when metadata comes from
jsr.json.- workspace diagnostics emitting
ConflictingPublishConfigwhen both configs define a package.They use
discover_jsr_config: trueexplicitly and assert against names and config specifiers, which should catch regressions in the resolution rules. No changes needed here.cli/factory.rs (1)
1280-1339: Enabling jsr.json discovery globally via discover_jsr_config is reasonableSetting
discover_jsr_config: trueinnew_workspace_factory_optionsmakes jsr configs part of normal workspace discovery for all subcommands. Given the rest of the resolver/publish logic already guards onis_package()and the new conflict diagnostic, this simplifies behavior without obvious downsides. Looks good.tests/integration/run_tests.rs (1)
3594-3646: LGTM! Test covers the JSR fallback scenario well.The test correctly validates that a workspace can resolve packages where one uses
jsr.jsonfor metadata (pkg1) and another uses the standarddeno.json(pkg2). The setup is clear and the assertions verify both packages are functional.One minor observation: this test mirrors
publish_workspace_with_jsr_json_fallbackinpublish_tests.rs, which is good for coverage of both runtime and publish scenarios.tests/integration/publish_tests.rs (1)
531-581: LGTM! Test validates the publish flow with JSR fallback.The test correctly verifies that
deno publishrecognizes packages configured viajsr.jsonwhendeno.jsondoesn't contain package metadata. The assertions checking for both package identifiers and their respective config file paths (pkg1/jsr.jsonandpkg2/deno.json) are solid.libs/config/workspace/discovery.rs (8)
46-51: Clean struct design for aggregating config sources.The
ConfigFolderstruct clearly encapsulates the three possible configuration sources. TheClonederive is appropriate given theRc-wrapped inner types.
53-68: Constructor properly enforces invariant.The constructor ensures
ConfigFolderalways contains at least one config source, making theunreachable!infolder_url()safe.
70-86: LGTM! Priority order is appropriate.The method correctly prioritizes
deno_jsonoverjsr_jsonoverpkg_jsonfor determining the folder URL. Theunreachable!is protected by the constructor's invariant.
88-100: Correctly excludes jsr_json from workspace member checks.The method appropriately only checks
deno_jsonandpkg_jsonfor workspace members sincejsr.jsonis intended for package metadata only, not workspace configuration.
139-149: Consistent priority withfolder_url().The specifier resolution maintains the same priority order as
folder_url(), ensuring consistent behavior across the codebase.
281-304: JSR config discovery implementation looks correct.The conditional discovery based on
opts.discover_jsr_configis clean. Using the same cache (opts.deno_json_cache) for both deno.json and jsr.json makes sense since they share the same JSON schema and parsing logic.Minor note:
JSR_CONFIG_FILE_NAMEScould be a module-level constant, but keeping it local to the closure is fine for readability.
341-342: Safe unwrap due to non-None argument.The
unwrap()is safe here sinceSome(config_file)guaranteesConfigFolder::newwill returnSome.
252-252: Verify behavior ofresolve_config_file_nameswith empty slice.Passing an empty slice to
ConfigFile::resolve_config_file_namesmay be intentional to obtain default config file names. Confirm this matches the expected method behavior and the intent of this code.
|
Thanks for the review @dsherret, would you mind going through these changes?
Also noticed when I tried this out in a local workspace project that looked like this
Might have to look into other sections also? Like the LSP for like ide extensions? but that's probably outside of this scope for sure. |
|
We don't want to support jsr.json outside of deno publish. It's too many config files to probe for (slow) and if someone wants to use deno with it then they should use a deno.json. Maybe one day we'll add the ability to extend a jsr.json from a deno.json |
Right. Ok, I understand. |
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: 0
🧹 Nitpick comments (1)
libs/config/workspace/mod.rs (1)
1803-1824: Minor code duplication in fallback logic.Lines 1803-1812 and 1814-1824 have very similar structure - both check if a config is a package and create a
JsrPackageConfig. This is acceptable for the small size, but if this logic grows, consider extracting a helper function to reduce duplication.fn create_jsr_package_config( config_file: &ConfigFileRc, member_dir: WorkspaceDirectoryRc, ) -> Option<JsrPackageConfig> { if config_file.is_package() { let pkg_name = config_file.json.name.clone()?; Some(JsrPackageConfig { name: pkg_name, config_file: config_file.clone(), member_dir, license: config_file.to_license(), }) } else { None } }Then use:
pub fn maybe_package_config( self: &WorkspaceDirectoryRc, ) -> Option<JsrPackageConfig> { if let Some(deno_json) = self.maybe_deno_json() { if let Some(config) = create_jsr_package_config(deno_json, self.clone()) { return Some(config); } } if let Some(jsr_json) = self.maybe_jsr_json() { return create_jsr_package_config(jsr_json, self.clone()); } None }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
libs/config/workspace/mod.rs(12 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: For debugging Rust code, set breakpoints in IDE debuggers (VS Code with rust-analyzer, IntelliJ IDEA) or uselldbdirectly
Useeprintln!()ordbg!()macros for debug prints in Rust code
Files:
libs/config/workspace/mod.rs
🧬 Code graph analysis (1)
libs/config/workspace/mod.rs (2)
libs/package_json/lib.rs (1)
specifier(504-506)libs/config/workspace/discovery.rs (3)
folder_url(70-86)deno_json(102-104)jsr_json(106-108)
⏰ 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). (10)
- GitHub Check: test debug linux-aarch64
- GitHub Check: test debug linux-x86_64
- GitHub Check: test release linux-x86_64
- GitHub Check: test debug windows-x86_64
- GitHub Check: test debug macos-x86_64
- GitHub Check: test debug macos-aarch64
- GitHub Check: lint debug macos-x86_64
- GitHub Check: lint debug windows-x86_64
- GitHub Check: lint debug linux-x86_64
- GitHub Check: build libs
🔇 Additional comments (2)
libs/config/workspace/mod.rs (2)
1190-1204: LGTM: Conflict detection correctly identifies ambiguous publish configs.The logic properly checks that both deno.json and jsr.json exist and are packages before emitting the diagnostic. The diagnostic message is clear and actionable.
2985-3082: LGTM: Tests cover the key fallback and conflict scenarios.The three tests correctly verify:
- Fallback to jsr.json when deno.json doesn't exist
- Fallback to jsr.json when deno.json exists but isn't a package
- Conflict detection when both configs define package metadata
|
Alright. Please check this out when you get a chance @dsherret. I reverted the change to the runtime package resolution. |
Summary
deno publishfall back tojsr.json(c)when no publishabledeno.json(c)exists, so packages that keep their metadata injsr.jsonwork as expectedconflicting-publish-configdiagnostic (with a hint and docs link) when both config files define package metadata, so authors resolve the ambiguity before publishingFixes #22651.
Testing
cargo test -p deno -- maybe_jsr_package_config./tools/format.js./tools/lint.js