Skip to content

feat: add workspace support for packages check licenses#1540

Open
realmeylisdev wants to merge 11 commits intoVeryGoodOpenSource:mainfrom
realmeylisdev:feat/workspace-license-support
Open

feat: add workspace support for packages check licenses#1540
realmeylisdev wants to merge 11 commits intoVeryGoodOpenSource:mainfrom
realmeylisdev:feat/workspace-license-support

Conversation

@realmeylisdev
Copy link
Copy Markdown
Contributor

Summary

This PR adds workspace support to the packages check licenses command, enabling license checking in monorepo projects that use Dart's pub workspace feature.

Reopens #1444 (branch was restored per request).
Closes #1273

Changes

New Files

  • lib/src/pubspec/pubspec.dart - Pubspec parser for detecting workspace configurations
  • test/src/pubspec/pubspec_test.dart - 19 tests for the Pubspec parser

Modified Files

  • lib/src/commands/packages/commands/check/commands/licenses.dart - Added workspace detection and dependency collection
  • test/src/commands/packages/commands/check/commands/licenses_test.dart - Added 3 workspace support tests

How It Works

  1. Auto-detection: When pubspec.yaml contains a workspace property, it's detected as a workspace root
  2. Dependency collection: Dependencies are collected from all workspace members' pubspec.yaml files
  3. Glob pattern support: Workspace paths like packages/* are supported (Dart 3.11+)
  4. Nested workspaces: Recursively handles nested workspaces
  5. Backwards compatible: Non-workspace projects work exactly as before

Test plan

  • All existing license tests pass (42 tests)
  • New workspace support tests pass (3 tests)
  • New Pubspec parser tests pass (19 tests)
  • Static analysis passes with no issues

realmeylisdev and others added 7 commits December 30, 2025 00:24
When a pubspec.yaml declares a workspace property, the command now
recursively collects dependencies from all workspace members and
checks their licenses using the root pubspec.lock.

This enables license checking in monorepo projects that use Dart's
pub workspace feature.

Closes VeryGoodOpenSource#1273
@samitsv
Copy link
Copy Markdown

samitsv commented Mar 18, 2026

@realmeylisdev seems like there are some conflicts that needs to be resolved

Keep both workspace license support functions and ReporterOutputFormat
enum from main.
@realmeylisdev
Copy link
Copy Markdown
Contributor Author

now done.

@samitsv
Copy link
Copy Markdown

samitsv commented Mar 18, 2026

@marcossevilla could we get this PR reviewed which was de-prioritized last time ? #1444 (comment)

@marcossevilla
Copy link
Copy Markdown
Member

@marcossevilla could we get this PR reviewed which was de-prioritized last time ? #1444 (comment)

hi @samitsv, I'll take a look during this week, thanks for pushing this!

also mentioning @brianegan as he was having this issue too, a review or test to check if it's fixing your issue is also appreciated 👍

@samitsv
Copy link
Copy Markdown

samitsv commented Apr 1, 2026

any update on this @marcossevilla

@samitsv
Copy link
Copy Markdown

samitsv commented Apr 8, 2026

any update on this @marcossevilla . Would be great to have this merged soon.

@marcossevilla
Copy link
Copy Markdown
Member

hey @samitsv, we're currently trying the branch against internal repos to verify the changes, I'll leave an update once we finish testing

@brianegan
Copy link
Copy Markdown

brianegan commented Apr 9, 2026

@marcossevilla Functional testing done on my end! PR worked well for a workspace monorepo. Sorry for the delay here -- deadlines.

Comment on lines +36 to +41
@visibleForTesting
const pubspecLockBasename = 'pubspec.lock';

/// The basename of the pubspec file.
@visibleForTesting
const pubspecBasename = 'pubspec.yaml';
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we have a library for pubspecs, maybe it's more natural for these variables to part of it

Comment on lines +576 to +586
/// Attempts to parse a [Pubspec] from a file.
///
/// Returns `null` if the file doesn't exist or cannot be parsed.
Pubspec? _tryParsePubspec(File pubspecFile) {
if (!pubspecFile.existsSync()) return null;
try {
return Pubspec.fromFile(pubspecFile);
} on PubspecParseException catch (_) {
return null;
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, maybe it's better if it's part of pubspec library

Comment on lines +54 to +58
} on TypeError catch (_) {
throw const PubspecParseException('Failed to parse YAML content');
} on YamlException catch (_) {
throw const PubspecParseException('Failed to parse YAML content');
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
} on TypeError catch (_) {
throw const PubspecParseException('Failed to parse YAML content');
} on YamlException catch (_) {
throw const PubspecParseException('Failed to parse YAML content');
}
} on Exception catch (_) {
throw const PubspecParseException('Failed to parse YAML content');
}

since it's the same exception being thrown

import 'package:very_good_cli/src/pubspec/pubspec.dart';

void main() {
group('$Pubspec', () {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
group('$Pubspec', () {
group(Pubspec, () {

});
});

group('$PubspecParseException', () {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
group('$PubspecParseException', () {
group(PubspecParseException, () {

});
});

group('$PubspecResolution', () {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
group('$PubspecResolution', () {
group(PubspecResolution, () {

Address review feedback on PR VeryGoodOpenSource#1540:
- Move `pubspecBasename` constant from licenses.dart to pubspec library
- Replace private `_tryParsePubspec` helper with `Pubspec.tryParse` static
- Simplify `Pubspec.fromString` by replacing the throwing `as` cast with
  an `is!` check, removing the `TypeError` catch and lint suppression
- Pass class types directly to `group()` in pubspec_test.dart
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Support packages check licenses with workspaces

4 participants