Skip to content

Commit

Permalink
feat!: make run script use melos_packages env variable scope (inverta…
Browse files Browse the repository at this point in the history
…se#640)

* Make run script use melos_packages env variable scope

* Adjust the comments mentioning `packageFilters`

* Refactor `copyWithUpdateScope` into more reusable `copyWith`

* Fix typo in `packageFilters` name

* Refactor packageFilters.copyWith() method

* Adjust copyWith to avoid using ValueProvider

* Update docs for MELOS_PACKAGES env variable
  • Loading branch information
Pavel-Sulimau authored Feb 6, 2024
1 parent 6c42c42 commit e12ff57
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 16 deletions.
3 changes: 2 additions & 1 deletion docs/environment-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ package' name ends with `example`
### `MELOS_PACKAGES`

Define a comma delimited list of package names that Melos should focus on. This
bypasses all filtering flags if defined.
will act as the `scope` global package filter, and it will override the `scope`
for all the filtering options defined in the `packageFilters` section.

### `MELOS_SDK_PATH`

Expand Down
8 changes: 3 additions & 5 deletions packages/melos/lib/src/commands/run.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,12 @@ mixin _RunMixin on _Melos {
bool noSelect = false,
List<String> extraArgs = const [],
}) async {
final workspace = await MelosWorkspace.fromConfig(
config,
final workspace = await createWorkspace(
global: global,
packageFilters: script.packageFilters?.copyWithUpdatedIgnore([
...script.packageFilters!.ignore,
...config.ignore,
]),
logger: logger,
)
..validate();

Expand Down Expand Up @@ -148,8 +146,8 @@ mixin _RunMixin on _Melos {
? packages.map((e) => e.name).toList().join(',')
: packages[selectedPackageIndex - 1].name;
// MELOS_PACKAGES environment is detected by melos itself when through
// a defined script, this comma delimited list of package names is used
// instead of any filters if detected.
// a defined script, this comma delimited list of package names used to
// scope the `packageFilters` if it is present.
environment[envKeyMelosPackages] = packagesEnv;
}

Expand Down
21 changes: 12 additions & 9 deletions packages/melos/lib/src/commands/runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,20 @@ abstract class _Melos {

if (currentPlatform.environment.containsKey(envKeyMelosPackages)) {
// MELOS_PACKAGES environment variable is a comma delimited list of
// package names - used instead of filters if it is present.
// package names - used to scope the `packageFilters` if it is present.
// This can be user defined or can come from package selection in
// `melos run`.
filterWithEnv = PackageFilters(
scope: currentPlatform.environment[envKeyMelosPackages]!
.split(',')
.map(
(e) => createGlob(e, currentDirectoryPath: config.path),
)
.toList(),
);
final filteredPackagesScopeFromEnv =
currentPlatform.environment[envKeyMelosPackages]!
.split(',')
.map(
(e) => createGlob(e, currentDirectoryPath: config.path),
)
.toList();

filterWithEnv = packageFilters == null
? PackageFilters(scope: filteredPackagesScopeFromEnv)
: packageFilters.copyWith(scope: filteredPackagesScopeFromEnv);
}

return (await MelosWorkspace.fromConfig(
Expand Down
2 changes: 1 addition & 1 deletion packages/melos/lib/src/common/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ extension Let<T> on T? {
String multiLine(List<String> lines) => lines.join('\n');

// MELOS_PACKAGES environment variable is a comma delimited list of
// package names - used instead of filters if it is present.
// package names - used to scope the `packageFilters` if it is present.
// This can be user defined or can come from package selection in `melos run`.
const envKeyMelosPackages = 'MELOS_PACKAGES';

Expand Down
31 changes: 31 additions & 0 deletions packages/melos/lib/src/package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,37 @@ class PackageFilters {
);
}

PackageFilters copyWith({
List<String>? dependsOn,
List<String>? dirExists,
List<String>? fileExists,
List<Glob>? ignore,
bool? includePrivatePackages,
List<String>? noDependsOn,
bool? nullSafe,
bool? published,
List<Glob>? scope,
String? diff,
bool? includeDependencies,
bool? includeDependents,
}) {
return PackageFilters._(
dependsOn: dependsOn ?? this.dependsOn,
dirExists: dirExists ?? this.dirExists,
fileExists: fileExists ?? this.fileExists,
ignore: ignore ?? this.ignore,
includePrivatePackages:
includePrivatePackages ?? this.includePrivatePackages,
noDependsOn: noDependsOn ?? this.noDependsOn,
nullSafe: nullSafe ?? this.nullSafe,
published: published ?? this.published,
scope: scope ?? this.scope,
diff: diff ?? this.diff,
includeDependencies: includeDependencies ?? this.includeDependencies,
includeDependents: includeDependents ?? this.includeDependents,
);
}

@override
bool operator ==(Object other) =>
other is PackageFilters &&
Expand Down
87 changes: 87 additions & 0 deletions packages/melos/test/commands/run_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import 'package:melos/src/common/io.dart';
import 'package:melos/src/common/platform.dart';
import 'package:melos/src/common/utils.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:pubspec/pubspec.dart';
import 'package:test/test.dart';

import '../matchers.dart';
import '../mock_env.dart';
import '../utils.dart';

void main() {
Expand Down Expand Up @@ -87,6 +89,91 @@ melos run test_script
},
);

test(
'merges filters from `packageFilters` and `$envKeyMelosPackages`',
withMockPlatform(
() async {
final workspaceDir = await createTemporaryWorkspace(
runPubGet: true,
configBuilder: (path) => MelosWorkspaceConfig(
path: path,
name: 'test_package',
packages: [
createGlob('packages/**', currentDirectoryPath: path),
],
scripts: Scripts({
'test_script': Script(
name: 'test_script',
run: 'melos exec -- "echo hello"',
packageFilters: PackageFilters(
fileExists: const ['log.txt'],
),
),
}),
),
);

final aDir = await createProject(
workspaceDir,
const PubSpec(name: 'a'),
);
writeTextFile(p.join(aDir.path, 'log.txt'), '');

await createProject(
workspaceDir,
const PubSpec(name: 'b'),
);

final cDir = await createProject(
workspaceDir,
const PubSpec(name: 'c'),
);
writeTextFile(p.join(cDir.path, 'log.txt'), '');

final logger = TestLogger();
final config =
await MelosWorkspaceConfig.fromWorkspaceRoot(workspaceDir);
final melos = Melos(
logger: logger,
config: config,
);

await melos.run(scriptName: 'test_script', noSelect: true);

expect(
logger.output.normalizeNewLines(),
ignoringAnsii(
'''
melos run test_script
└> melos exec -- "echo hello"
└> RUNNING
\$ melos exec
└> echo hello
└> RUNNING (in 1 packages)
${'-' * terminalWidth}
c:
hello
c: SUCCESS
${'-' * terminalWidth}
\$ melos exec
└> echo hello
└> SUCCESS
melos run test_script
└> melos exec -- "echo hello"
└> SUCCESS
''',
),
);
},
platform: FakePlatform.fromPlatform(const LocalPlatform())
..environment[envKeyMelosPackages] = 'b,c',
),
);

test('supports passing additional arguments to scripts', () async {
final workspaceDir = await createTemporaryWorkspace(
runPubGet: true,
Expand Down

0 comments on commit e12ff57

Please sign in to comment.