Skip to content
This repository was archived by the owner on Mar 24, 2026. It is now read-only.

fix: resolve workspace root correctly in parsePackageConfig#378

Open
julienzarka wants to merge 1 commit intoinvertase:mainfrom
julienzarka:fix/custom-lint-workspace-plugin-discovery
Open

fix: resolve workspace root correctly in parsePackageConfig#378
julienzarka wants to merge 1 commit intoinvertase:mainfrom
julienzarka:fix/custom-lint-workspace-plugin-discovery

Conversation

@julienzarka
Copy link
Copy Markdown

Fix: Resolve workspace root correctly in parsePackageConfig

Summary

Fixes plugin discovery failure in Dart workspace setups with path dependencies. The issue was that parsePackageConfig() did not properly resolve workspace root paths when workspace_ref.json contained relative paths like "../../..". Additionally, it lacked validation for workspace_ref.json existence and the resolved workspace root's package_config.json.

Problem

When using Dart workspace resolution (common in Melos monorepos), custom_lint fails to discover plugins that are path dependencies, even when:

  • The plugin is correctly listed in dev_dependencies with a path reference
  • The plugin is present in the workspace root's package_config.json
  • workspace_ref.json exists and correctly points to the workspace root

The plugin discovery fails silently without any error messages.

Solution

  1. Added existence check for workspace_ref.json before reading
  2. Fixed path resolution using absolute() to properly resolve relative paths in workspaceRoot
  3. Added validation that resolved workspace root has package_config.json
  4. Improved error messages with context for better debugging

Changes

  • Modified: packages/custom_lint_core/lib/src/package_utils.dart

    • Added workspace_ref.json existence check
    • Fixed path resolution with absolute() for relative paths
    • Added validation for workspace root package_config.json
    • Improved error messages
  • Added: packages/custom_lint_core/test/package_utils_test.dart

    • Unit tests for workspace resolution scenarios
    • Tests for error cases (missing files)

Testing

  • ✅ All new tests pass (4/4)
  • ✅ All existing tests pass (34/34 in custom_lint_core)
  • ✅ All workspace tests pass (75/75 in custom_lint)
  • flutter analyze passes with no warnings/errors
  • ✅ Code formatted and follows project style

Impact

This fix enables custom_lint to work correctly in monorepo setups that use Dart workspace resolution, allowing plugins to be discovered from the workspace root's package_config.json when they're path dependencies.

Related

Fixes the issue described in: https://github.com/julienzarka/dart_custom_lint/issues (if applicable)

Code Review Notes

  • Minimal changes: Only 1 source file modified (+23 lines, -2 lines)
  • No breaking changes
  • Backward compatible
  • Follows existing code patterns (uses FileSystemException like existing error classes)

Fix plugin discovery failure in Dart workspace setups with path dependencies.

The issue was that parsePackageConfig() did not properly resolve workspace
root paths when workspace_ref.json contained relative paths like '../../..'.
Additionally, it lacked validation for workspace_ref.json existence and
the resolved workspace root's package_config.json.

Changes:
- Add existence check for workspace_ref.json before reading
- Use absolute() to properly resolve relative paths in workspaceRoot
- Add validation that resolved workspace root has package_config.json
- Improve error messages with context for better debugging

Fixes workspace plugin discovery in monorepo setups (e.g., Melos) where
plugins are path dependencies and only exist in workspace root's
package_config.json.

Tests:
- Add unit tests for workspace resolution scenarios
- All existing tests pass (34/34)
- All new tests pass (4/4)
@vercel
Copy link
Copy Markdown

vercel bot commented Jan 15, 2026

Someone is attempting to deploy a commit to the Invertase Team on Vercel.

A member of the Team first needs to authorize it.

@docs-page
Copy link
Copy Markdown

docs-page bot commented Jan 15, 2026

To view this pull requests documentation preview, visit the following URL:

docs.page/invertase/dart_custom_lint~378

Documentation is deployed and generated using docs.page.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


Julien Zarka seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@tsavo-at-pieces
Copy link
Copy Markdown

Code Quality Review

Changes

Fixes parsePackageConfig() in packages/custom_lint_core/lib/src/package_utils.dart to correctly resolve workspace root paths when workspace_ref.json contains relative paths like "../../..". Adds existence checks for workspace_ref.json and the resolved workspace root's package_config.json, with descriptive error messages. Includes a comprehensive new test file (package_utils_test.dart) with 4 well-structured tests covering the happy path and error cases.

Quality Assessment

Positives:

  • The core bug fix is correct: using absolute() to resolve relative paths from workspace_ref.json is the right approach. The original code used normalize(join(...)) which does not resolve .. segments against the current working directory, causing failures when the path is deeply relative.
  • Excellent error messages -- both FileSystemException throws include the source path and the context of what was being resolved, making debugging straightforward.
  • The guard clause for workspaceRefFile.existsSync() before readAsStringSync() is a real improvement -- the original code would throw a raw FileSystemException with no context.
  • Tests are thorough: covers shallow workspace refs, deep nested workspace refs, missing workspace_ref.json, and missing workspace root package_config.json.
  • Proper cleanup in tests using try/finally with tempDir.delete(recursive: true).

Minor observations:

  • The use of absolute() from package:path resolves relative to Directory.current (the process CWD). This works correctly because workspaceRefFile.parent.path is already an absolute path from Directory.systemTemp, so join() produces an absolute path and absolute() is effectively a no-op in those cases. However, if directory were ever passed as a relative Directory, the behavior could be surprising. This is fine for the current usage but worth noting.
  • The test file is 210 lines for 4 tests -- well-commented and readable, not bloated.
  • The PR description is excellent with clear problem statement, solution, and testing evidence.

Verdict

APPROVE -- This is a clean, well-tested bug fix that addresses a real issue with workspace resolution in Dart monorepo setups. The error handling improvements are a welcome addition. The only note is to ensure the CLA is signed (the CLA bot flagged it as pending).

@tsavo-at-pieces
Copy link
Copy Markdown

Fork Maintainer Review (dart_custom_lint)

Reviewing on behalf of open-runtime/dart_custom_lint fork.

Summary

Fixes plugin discovery failure in Dart workspace setups with path dependencies. The issue was that parsePackageConfig() did not properly resolve workspace root paths when workspace_ref.json contained relative paths like "../../..". The fix:

  1. Adds existence check for workspace_ref.json before reading
  2. Uses absolute() to properly resolve relative paths in workspaceRoot
  3. Adds validation that resolved workspace root has package_config.json
  4. Improves error messages with context for debugging
  5. Adds comprehensive unit tests (4 test cases covering happy path and error cases)

Upstream Status

Open on upstream (invertase/dart_custom_lint), not yet merged. This is a community contribution by @julienzarka.

Assessment

High-quality PR and directly relevant to our fork. This is a real bug fix for monorepo/workspace setups -- exactly the kind of environment we use. The code change in packages/custom_lint_core/lib/src/package_utils.dart is clean and minimal:

  • The absolute() call from package:path correctly resolves relative .. paths that normalize() alone cannot handle when the base path itself is relative
  • Error messages are descriptive and include the source paths for debugging
  • Tests cover: workspace resolution, deeply nested workspace resolution, missing workspace_ref.json, and missing workspace root package_config.json
  • No breaking changes -- only adds validation and fixes path resolution

The only minor observation: the test file creates temp directories and cleans up properly with try/finally, which is good practice.

Recommendation

SYNC_FROM_UPSTREAM (once merged upstream) -- This is a valuable bug fix we want in our fork. If upstream is slow to merge, consider cherry-picking directly. The change is isolated to custom_lint_core and carries low risk.

@tsavo-at-pieces
Copy link
Copy Markdown

Compatibility Review (Monorepo Impact)

Reviewer context: We maintain the open-runtime/dart_custom_lint fork, consumed as a workspace member in our Dart monorepo (aot_monorepo). All custom_lint* packages are listed in the monorepo root pubspec.yaml workspace list with resolution: workspace in each sub-package.

Monorepo Impact

CRITICAL FIX FOR US. This PR directly addresses a bug we are affected by. Our monorepo uses Dart native pub workspaces, which means:

  1. Each sub-package gets a .dart_tool/pub/workspace_ref.json that points back to the workspace root via relative paths like "../../.." or deeper.
  2. The current parsePackageConfig() uses normalize(join(...)) which does not properly resolve .. segments when the resulting path is relative-looking. The absolute() call in this PR fixes that.
  3. Without this fix, custom_lint fails silently to discover plugins that are path dependencies in workspace setups -- which is exactly our setup.

The three improvements are all valuable for us:

  • Guard clause for workspace_ref.json existence: prevents cryptic FileSystemException when the file is missing.
  • absolute() resolution: fixes the core path resolution bug for relative workspace roots.
  • Validation that the resolved workspace root actually has package_config.json: prevents confusing downstream errors.

Dependency Concerns

None. This PR modifies only package_utils.dart in custom_lint_core and adds a test file. No new dependencies introduced. No version constraint changes. No API surface changes (the function signature is unchanged; only error behavior on invalid inputs changes from unstructured exceptions to structured FileSystemException).

Recommendation

MERGE -- This is a high-priority fix for any monorepo using Dart native workspaces with custom_lint. The fix is correct, well-tested, backward-compatible, and directly addresses issues we encounter in our workspace setup. We would pull this into our fork immediately after upstream merge.

Note: The CLA check is currently pending for this contributor. That needs to be resolved before merge.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants