Skip to content
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

feat!: make run script use melos_packages env variable scope #640

Merged
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 packageFilers if it is present.
spydon marked this conversation as resolved.
Show resolved Hide resolved
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 packageFilers if it is present.
spydon marked this conversation as resolved.
Show resolved Hide resolved
// 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.copyWithUpdatedScope(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 packageFilers if it is present.
// This can be user defined or can come from package selection in `melos run`.
const envKeyMelosPackages = 'MELOS_PACKAGES';

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

PackageFilters copyWithUpdatedScope(List<Glob> scope) {
spydon marked this conversation as resolved.
Show resolved Hide resolved
return PackageFilters._(
dependsOn: dependsOn,
dirExists: dirExists,
fileExists: fileExists,
ignore: ignore,
includePrivatePackages: includePrivatePackages,
noDependsOn: noDependsOn,
nullSafe: nullSafe,
published: published,
scope: scope,
diff: diff,
includeDependencies: includeDependencies,
includeDependents: 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
Loading