From 2f19770eee9deff097d26202bece72bd6b2127a1 Mon Sep 17 00:00:00 2001 From: Gabriel Terwesten Date: Mon, 16 Oct 2023 22:29:28 +0200 Subject: [PATCH 1/5] refactor: fix analyzer issues (#590) --- packages/melos/lib/src/commands/bootstrap.dart | 4 ++-- packages/melos/lib/src/commands/list.dart | 4 ++-- packages/melos/lib/src/commands/publish.dart | 2 +- packages/melos/lib/src/commands/version.dart | 6 +++--- packages/melos/lib/src/common/utils.dart | 4 ++-- packages/melos/lib/src/package.dart | 2 +- .../melos/test/commands/bootstrap_test.dart | 2 +- packages/melos/test/commands/clean_test.dart | 4 ++-- packages/melos/test/commands/run_test.dart | 6 +++--- packages/melos/test/package_test.dart | 2 +- packages/melos/test/utils.dart | 2 +- packages/melos/test/workspace_config_test.dart | 18 +++++++++--------- packages/melos/test/workspace_test.dart | 6 +++--- 13 files changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/melos/lib/src/commands/bootstrap.dart b/packages/melos/lib/src/commands/bootstrap.dart index 5a3ebb8b..2076eb5c 100644 --- a/packages/melos/lib/src/commands/bootstrap.dart +++ b/packages/melos/lib/src/commands/bootstrap.dart @@ -18,7 +18,7 @@ mixin _BootstrapMixin on _CleanMixin { workspace: workspace, ), 'get', - if (workspace.config.commands.bootstrap.runPubGetOffline) '--offline' + if (workspace.config.commands.bootstrap.runPubGetOffline) '--offline', ].join(' '); logger @@ -163,7 +163,7 @@ mixin _BootstrapMixin on _CleanMixin { workspace: workspace, ), 'get', - if (workspace.config.commands.bootstrap.runPubGetOffline) '--offline' + if (workspace.config.commands.bootstrap.runPubGetOffline) '--offline', ]; final process = await startCommandRaw( diff --git a/packages/melos/lib/src/commands/list.dart b/packages/melos/lib/src/commands/list.dart index cbaa4b13..d2277e7f 100644 --- a/packages/melos/lib/src/commands/list.dart +++ b/packages/melos/lib/src/commands/list.dart @@ -76,7 +76,7 @@ mixin _ListMixin on _Melos { package.name, AnsiStyles.green((package.version).toString()), AnsiStyles.gray(printablePath(package.pathRelativeToWorkspace)), - if (package.isPrivate) AnsiStyles.red('PRIVATE') + if (package.isPrivate) AnsiStyles.red('PRIVATE'), ], ) .cast>() @@ -132,7 +132,7 @@ mixin _ListMixin on _Melos { 'version': package.version.toString(), 'private': package.isPrivate, 'location': packagePath, - 'type': package.type.index + 'type': package.type.index, }; if (long) { diff --git a/packages/melos/lib/src/commands/publish.dart b/packages/melos/lib/src/commands/publish.dart index 6ba8a8c4..6e405c3c 100644 --- a/packages/melos/lib/src/commands/publish.dart +++ b/packages/melos/lib/src/commands/publish.dart @@ -77,7 +77,7 @@ mixin _PublishMixin on _ExecMixin { AnsiStyles.dim(latestPublishedVersionForPackages[package.name]), AnsiStyles.green(package.version.toString()), ]; - }) + }), ], paddingSize: 4, ), diff --git a/packages/melos/lib/src/commands/version.dart b/packages/melos/lib/src/commands/version.dart index 66b6ffe1..35a86310 100644 --- a/packages/melos/lib/src/commands/version.dart +++ b/packages/melos/lib/src/commands/version.dart @@ -143,7 +143,7 @@ mixin _VersionMixin on _RunMixin { for (final package in workspace.filteredPackages.values) if (!packagesToManuallyVersion.contains(package)) if (packagesWithVersionableCommits.contains(package.name)) - if (!asStableRelease || !package.version.isPreRelease) package + if (!asStableRelease || !package.version.isPreRelease) package, }; final packagesToVersion = { ...packagesToManuallyVersion, @@ -662,7 +662,7 @@ mixin _VersionMixin on _RunMixin { if (updateDependentsConstraints) { await Future.forEach([ ...pendingPackageUpdate.package.dependentsInWorkspace.values, - ...pendingPackageUpdate.package.devDependentsInWorkspace.values + ...pendingPackageUpdate.package.devDependentsInWorkspace.values, ], (package) { return _setDependencyVersionForDependentPackage( package, @@ -710,7 +710,7 @@ mixin _VersionMixin on _RunMixin { final dateSlug = [ today.year.toString(), today.month.toString().padLeft(2, '0'), - today.day.toString().padLeft(2, '0') + today.day.toString().padLeft(2, '0'), ].join('-'); final packages = diff --git a/packages/melos/lib/src/common/utils.dart b/packages/melos/lib/src/common/utils.dart index e4845688..2576b36c 100644 --- a/packages/melos/lib/src/common/utils.dart +++ b/packages/melos/lib/src/common/utils.dart @@ -591,10 +591,10 @@ bool isPubSubcommand({required MelosWorkspace workspace}) { void sortPackagesForPublishing(List packages) { final packageNames = packages.map((package) => package.name).toList(); final graph = >{ - for (var package in packages) + for (final package in packages) package.name: [ ...package.dependencies.where(packageNames.contains), - ...package.devDependencies.where(packageNames.contains) + ...package.devDependencies.where(packageNames.contains), ], }; final ordered = diff --git a/packages/melos/lib/src/package.dart b/packages/melos/lib/src/package.dart index 16fcd552..c3d0ac5a 100644 --- a/packages/melos/lib/src/package.dart +++ b/packages/melos/lib/src/package.dart @@ -480,7 +480,7 @@ class PackageMap { ignore: [ ...ignore, for (final pattern in _commonIgnorePatterns) - createGlob(pattern, currentDirectoryPath: workspacePath) + createGlob(pattern, currentDirectoryPath: workspacePath), ], ); diff --git a/packages/melos/test/commands/bootstrap_test.dart b/packages/melos/test/commands/bootstrap_test.dart index 4fc41836..acaeb421 100644 --- a/packages/melos/test/commands/bootstrap_test.dart +++ b/packages/melos/test/commands/bootstrap_test.dart @@ -333,7 +333,7 @@ Generating IntelliJ IDE files... mergeMelosPubspecOverrides( { for (final entry in melosDependencyOverrides.entries) - entry.key: PathReference(entry.value) + entry.key: PathReference(entry.value), }, currentPubspecOverrides, ), diff --git a/packages/melos/test/commands/clean_test.dart b/packages/melos/test/commands/clean_test.dart index 2d955f3f..ba0c2fa2 100644 --- a/packages/melos/test/commands/clean_test.dart +++ b/packages/melos/test/commands/clean_test.dart @@ -41,8 +41,8 @@ void main() { pubspecOverrides, yamlFile({ 'dependency_overrides': { - 'a': {'path': relativePath(packageADir.path, packageBDir.path)} - } + 'a': {'path': relativePath(packageADir.path, packageBDir.path)}, + }, }), ); diff --git a/packages/melos/test/commands/run_test.dart b/packages/melos/test/commands/run_test.dart index b350c3dd..f218d990 100644 --- a/packages/melos/test/commands/run_test.dart +++ b/packages/melos/test/commands/run_test.dart @@ -31,7 +31,7 @@ void main() { packageFilters: PackageFilters( fileExists: const ['log.txt'], ), - ) + ), }), ), ); @@ -155,7 +155,7 @@ melos run hello name: 'hello', run: 'echo', exec: ExecOptions(), - ) + ), }), ), ); @@ -225,7 +225,7 @@ melos run hello exec: ExecOptions( concurrency: 1, ), - ) + ), }), ), ); diff --git a/packages/melos/test/package_test.dart b/packages/melos/test/package_test.dart index 8c472698..62f3ee18 100644 --- a/packages/melos/test/package_test.dart +++ b/packages/melos/test/package_test.dart @@ -72,7 +72,7 @@ void main() { MockPackageFs( name: 'melos', version: Version(0, 0, 0), - ) + ), ], ), ); diff --git a/packages/melos/test/utils.dart b/packages/melos/test/utils.dart index 8b4749ac..e03df46c 100644 --- a/packages/melos/test/utils.dart +++ b/packages/melos/test/utils.dart @@ -171,7 +171,7 @@ Future createProject( else ...[ 'packages', pubSpec.name!, - ] + ], ]), ); diff --git a/packages/melos/test/workspace_config_test.dart b/packages/melos/test/workspace_config_test.dart index 1fa14b9b..9a5d8540 100644 --- a/packages/melos/test/workspace_config_test.dart +++ b/packages/melos/test/workspace_config_test.dart @@ -67,7 +67,7 @@ void main() { runPubGetInParallel: false, runPubGetOffline: true, dependencyOverridePaths: [ - createGlob('a', currentDirectoryPath: '.') + createGlob('a', currentDirectoryPath: '.'), ], ), ); @@ -155,7 +155,7 @@ void main() { 'packageFilters': {'flutter': true}, 'description': 'Changelog for all foo packages.', } - ] + ], }, workspacePath: '.', ), @@ -215,7 +215,7 @@ void main() { const { 'bootstrap': { 'runPubGetInParallel': true, - } + }, }, workspacePath: '.', ), @@ -236,7 +236,7 @@ void main() { const { 'bootstrap': { 'runPubGetOffline': true, - } + }, }, workspacePath: '.', ), @@ -256,7 +256,7 @@ void main() { 'message': 'Hello world', 'branch': 'main', 'linkToCommits': true, - } + }, }, workspacePath: '.', ), @@ -429,7 +429,7 @@ void main() { 'exec': { 'concurrency': 1, 'failFast': true, - 'orderDependents': true + 'orderDependents': true, }, }, }), @@ -520,7 +520,7 @@ void main() { expect( () => MelosWorkspaceConfig.fromYaml( createYamlMap({ - 'packages': ['*'] + 'packages': ['*'], }), path: testWorkspacePath, ), @@ -617,7 +617,7 @@ void main() { () => MelosWorkspaceConfig.fromYaml( createYamlMap( { - 'packages': [42] + 'packages': [42], }, defaults: configMapDefaults, ), @@ -658,7 +658,7 @@ void main() { () => MelosWorkspaceConfig.fromYaml( createYamlMap( { - 'ignore': [42] + 'ignore': [42], }, defaults: configMapDefaults, ), diff --git a/packages/melos/test/workspace_test.dart b/packages/melos/test/workspace_test.dart index 903fd7af..d737c3f5 100644 --- a/packages/melos/test/workspace_test.dart +++ b/packages/melos/test/workspace_test.dart @@ -160,7 +160,7 @@ The packages that caused the problem are: configBuilder: (path) => MelosWorkspaceConfig.fromYaml( const { 'name': 'test', - 'packages': ['.'] + 'packages': ['.'], }, path: path, ), @@ -185,7 +185,7 @@ The packages that caused the problem are: configBuilder: (path) => MelosWorkspaceConfig.fromYaml( const { 'name': 'test', - 'packages': ['packages/a'] + 'packages': ['packages/a'], }, path: path, ), @@ -246,7 +246,7 @@ The packages that caused the problem are: config, packageFilters: PackageFilters( scope: [ - createGlob('b', currentDirectoryPath: workspaceDir.path) + createGlob('b', currentDirectoryPath: workspaceDir.path), ], includeDependencies: true, ), From 39e5e499d71e95cf7794ae724ab2ccd3bb4e9fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20L=C3=B6hnn?= Date: Sun, 22 Oct 2023 22:33:54 +0200 Subject: [PATCH 2/5] feat: support syncing common dependency versions (#526) --- docs/commands/bootstrap.mdx | 37 ++++ melos.yaml | 32 ++++ .../melos/lib/src/commands/bootstrap.dart | 140 ++++++++++++++- packages/melos/lib/src/workspace_configs.dart | 70 ++++++++ .../melos/test/commands/bootstrap_test.dart | 159 ++++++++++++++++++ packages/melos/test/utils.dart | 7 + 6 files changed, 444 insertions(+), 1 deletion(-) diff --git a/docs/commands/bootstrap.mdx b/docs/commands/bootstrap.mdx index 8a0ea443..6301a7c2 100644 --- a/docs/commands/bootstrap.mdx +++ b/docs/commands/bootstrap.mdx @@ -84,6 +84,43 @@ example: melos bootstrap --diff="main" ``` +## Bootstrap flags + +Melos bootstrap command supports a few different flags that can be defined in +your `melos.yaml`. + + +### Shared dependencies + +If you want to share dependency versions between your packages in your Melos +project, just add the dependencies you wish to share between the packages to +your bootstrap config in your `melos.yaml` file. + +If a dependency from `environment`, `dependencies` or `dev_dependencies` in +your `common_packages.yaml` exists in a package, the dependency version in this +package will be updated to match the version defined in your +bootstrap config every time `melos bootstrap` is run. + +```yaml +# melos.yaml +# ... +command: + environment: + sdk: ">=3.0.0 <4.0.0" + flutter: ">=3.0.0 <4.0.0" + bootstrap: + dependencies: + collection: ^1.18.0 + integral_isolates: any + uni_links2: + uni_links_macos: + git: https://github.com/SamJakob/uni_links_macos.git + + dev_dependencies: + build_runner: ^2.3.3 +# ... +``` + ## Adding a post bootstrap lifecycle script Melos supports various command [lifecycle hooks](/configuration/scripts#hooks) diff --git a/melos.yaml b/melos.yaml index 520e72d1..83ba7196 100644 --- a/melos.yaml +++ b/melos.yaml @@ -7,6 +7,38 @@ ignore: - packages/melos_flutter_deps_check command: + bootstrap: + environment: + sdk: '>=2.18.0 <3.0.0' + dependencies: + ansi_styles: ^0.3.1 + args: ^2.0.0 + cli_launcher: ^0.3.0 + cli_util: '>=0.3.0 <0.5.0' + collection: ^1.14.12 + conventional_commit: ^0.6.0+1 + file: ^6.1.0 + glob: ^2.1.0 + graphs: ^2.1.0 + http: ">=0.13.1 <2.0.0" + meta: ^1.1.8 + mustache_template: ^2.0.0 + path: ^1.7.0 + platform: ^3.1.0 + pool: ^1.4.0 + prompts: ^2.0.0 + pub_semver: ^2.0.0 + pub_updater: ^0.3.0 + pubspec: ^2.1.0 + string_scanner: ^1.0.5 + yaml: ^3.1.0 + yaml_edit: ^2.0.2 + dev_dependencies: + collection: ^1.15.0 + mockito: ^5.1.0 + test: ^1.17.5 + path: ^1.7.0 + yaml: ^3.1.0 version: # Generate commit links in package changelogs. linkToCommits: true diff --git a/packages/melos/lib/src/commands/bootstrap.dart b/packages/melos/lib/src/commands/bootstrap.dart index 2076eb5c..33fa7a83 100644 --- a/packages/melos/lib/src/commands/bootstrap.dart +++ b/packages/melos/lib/src/commands/bootstrap.dart @@ -12,13 +12,14 @@ mixin _BootstrapMixin on _CleanMixin { workspace, _CommandWithLifecycle.bootstrap, () async { + final bootstrapCommandConfig = workspace.config.commands.bootstrap; final pubCommandForLogging = [ ...pubCommandExecArgs( useFlutter: workspace.isFlutterWorkspace, workspace: workspace, ), 'get', - if (workspace.config.commands.bootstrap.runPubGetOffline) '--offline', + if (bootstrapCommandConfig.runPubGetOffline) '--offline', ].join(' '); logger @@ -35,6 +36,20 @@ mixin _BootstrapMixin on _CleanMixin { } try { + if (bootstrapCommandConfig.environment != null || + bootstrapCommandConfig.dependencies != null || + bootstrapCommandConfig.devDependencies != null) { + final filteredPackages = workspace.filteredPackages.values; + await Stream.fromIterable(filteredPackages).parallel((package) { + return _setSharedDependenciesForPackage( + package, + environment: bootstrapCommandConfig.environment, + dependencies: bootstrapCommandConfig.dependencies, + devDependencies: bootstrapCommandConfig.devDependencies, + ); + }).drain(); + } + await _linkPackagesWithPubspecOverrides(workspace); } on BootstrapException catch (exception) { _logBootstrapException(exception, workspace); @@ -199,6 +214,129 @@ mixin _BootstrapMixin on _CleanMixin { } } + Future _setSharedDependenciesForPackage( + Package package, { + required Environment? environment, + required Map? dependencies, + required Map? devDependencies, + }) async { + final packagePubspecFile = utils.pubspecPathForDirectory(package.path); + final packagePubspecContents = await readTextFileAsync(packagePubspecFile); + final pubspecEditor = YamlEditor(packagePubspecContents); + + final updatedEnvironment = _updateEnvironment( + pubspecEditor: pubspecEditor, + workspaceEnvironment: environment, + packageEnvironment: package.pubSpec.environment, + ); + + final updatedDependenciesCount = _updateDependencies( + pubspecEditor: pubspecEditor, + workspaceDependencies: dependencies, + packageDependencies: package.pubSpec.dependencies, + pubspecKey: 'dependencies', + ); + + final updatedDevDependenciesCount = _updateDependencies( + pubspecEditor: pubspecEditor, + workspaceDependencies: devDependencies, + packageDependencies: package.pubSpec.devDependencies, + pubspecKey: 'dev_dependencies', + ); + + if (pubspecEditor.edits.isNotEmpty) { + await writeTextFileAsync( + packagePubspecFile, + pubspecEditor.toString(), + ); + + final message = [ + if (updatedEnvironment) 'Updated environment', + if (updatedDependenciesCount > 0) + 'Updated $updatedDependenciesCount dependencies', + if (updatedDevDependenciesCount > 0) + 'Updated $updatedDevDependenciesCount dev_dependencies', + ]; + if (message.isNotEmpty) { + logger + .child(packageNameStyle(package.name), prefix: '') + .child(message.join('\n')); + } + } + } + + bool _updateEnvironment({ + required YamlEditor pubspecEditor, + required Environment? workspaceEnvironment, + required Environment? packageEnvironment, + }) { + if (workspaceEnvironment == null || packageEnvironment == null) { + return false; + } + + var didUpdate = false; + + if (workspaceEnvironment.sdkConstraint != + packageEnvironment.sdkConstraint) { + pubspecEditor.update( + ['environment', 'sdk'], + wrapAsYamlNode( + workspaceEnvironment.sdkConstraint.toString(), + collectionStyle: CollectionStyle.BLOCK, + ), + ); + didUpdate = true; + } + + final workspaceUnParsedYaml = workspaceEnvironment.unParsedYaml; + final packageUnParsedYaml = packageEnvironment.unParsedYaml; + if (workspaceUnParsedYaml != null && packageUnParsedYaml != null) { + for (final entry in workspaceUnParsedYaml.entries) { + if (!packageUnParsedYaml.containsKey(entry.key)) continue; + if (packageUnParsedYaml[entry.key] == entry.value) continue; + + pubspecEditor.update( + ['environment', entry.key], + wrapAsYamlNode( + entry.value.toString(), + collectionStyle: CollectionStyle.BLOCK, + ), + ); + didUpdate = true; + } + } + + return didUpdate; + } + + int _updateDependencies({ + required YamlEditor pubspecEditor, + required Map? workspaceDependencies, + required Map packageDependencies, + required String pubspecKey, + }) { + if (workspaceDependencies == null) return 0; + // Filter out the packages that do not exist in package and only the + // dependencies that have a different version specified in the workspace. + final dependenciesToUpdate = workspaceDependencies.entries.where((entry) { + if (!packageDependencies.containsKey(entry.key)) return false; + if (packageDependencies[entry.key] == entry.value) return false; + return true; + }); + + for (final entry in dependenciesToUpdate) { + pubspecEditor.update( + [pubspecKey, entry.key], + wrapAsYamlNode( + entry.value.toJson(), + collectionStyle: CollectionStyle.BLOCK, + ), + ); + } + + return dependenciesToUpdate.length; + } + void _logBootstrapSuccess(Package package) { logger.child(packageNameStyle(package.name), prefix: '$checkLabel ').child( packagePathStyle(printablePath(package.pathRelativeToWorkspace)), diff --git a/packages/melos/lib/src/workspace_configs.dart b/packages/melos/lib/src/workspace_configs.dart index 8ec981c3..9c7b0afc 100644 --- a/packages/melos/lib/src/workspace_configs.dart +++ b/packages/melos/lib/src/workspace_configs.dart @@ -21,6 +21,7 @@ import 'package:ansi_styles/ansi_styles.dart'; import 'package:collection/collection.dart'; import 'package:glob/glob.dart'; import 'package:meta/meta.dart'; +import 'package:pubspec/pubspec.dart'; import 'package:yaml/yaml.dart'; import '../melos.dart'; @@ -357,6 +358,9 @@ class BootstrapCommandConfigs { const BootstrapCommandConfigs({ this.runPubGetInParallel = true, this.runPubGetOffline = false, + this.environment, + this.dependencies, + this.devDependencies, this.dependencyOverridePaths = const [], this.hooks = LifecycleHooks.empty, }); @@ -379,6 +383,31 @@ class BootstrapCommandConfigs { ) ?? false; + final environment = assertKeyIsA?>( + key: 'environment', + map: yaml, + ).let(Environment.fromJson); + + final dependencies = assertKeyIsA?>( + key: 'dependencies', + map: yaml, + )?.map( + (key, value) => MapEntry( + key.toString(), + DependencyReference.fromJson(value), + ), + ); + + final devDependencies = assertKeyIsA?>( + key: 'dev_dependencies', + map: yaml, + )?.map( + (key, value) => MapEntry( + key.toString(), + DependencyReference.fromJson(value), + ), + ); + final dependencyOverridePaths = assertListIsA( key: 'dependencyOverridePaths', map: yaml, @@ -402,6 +431,9 @@ class BootstrapCommandConfigs { return BootstrapCommandConfigs( runPubGetInParallel: runPubGetInParallel, runPubGetOffline: runPubGetOffline, + environment: environment, + dependencies: dependencies, + devDependencies: devDependencies, dependencyOverridePaths: dependencyOverridePaths .map( (override) => @@ -425,6 +457,15 @@ class BootstrapCommandConfigs { /// The default is `false`. final bool runPubGetOffline; + /// Environment configuration to be synced between all packages. + final Environment? environment; + + /// Dependencies to be synced between all packages. + final Map? dependencies; + + /// Dev dependencies to be synced between all packages. + final Map? devDependencies; + /// A list of [Glob]s for paths that contain packages to be used as dependency /// overrides for all packages managed in the Melos workspace. final List dependencyOverridePaths; @@ -436,6 +477,15 @@ class BootstrapCommandConfigs { return { 'runPubGetInParallel': runPubGetInParallel, 'runPubGetOffline': runPubGetOffline, + if (environment != null) 'environment': environment!.toJson(), + if (dependencies != null) + 'dependencies': dependencies!.map( + (key, value) => MapEntry(key, value.toJson()), + ), + if (devDependencies != null) + 'dev_dependencies': devDependencies!.map( + (key, value) => MapEntry(key, value.toJson()), + ), if (dependencyOverridePaths.isNotEmpty) 'dependencyOverridePaths': dependencyOverridePaths.map((path) => path.toString()).toList(), @@ -449,6 +499,15 @@ class BootstrapCommandConfigs { runtimeType == other.runtimeType && other.runPubGetInParallel == runPubGetInParallel && other.runPubGetOffline == runPubGetOffline && + // Extracting equality from environment here as it does not implement == + other.environment?.sdkConstraint == environment?.sdkConstraint && + const DeepCollectionEquality().equals( + other.environment?.unParsedYaml, + environment?.unParsedYaml, + ) && + const DeepCollectionEquality().equals(other.dependencies, dependencies) && + const DeepCollectionEquality() + .equals(other.devDependencies, devDependencies) && const DeepCollectionEquality(_GlobEquality()) .equals(other.dependencyOverridePaths, dependencyOverridePaths) && other.hooks == hooks; @@ -458,6 +517,14 @@ class BootstrapCommandConfigs { runtimeType.hashCode ^ runPubGetInParallel.hashCode ^ runPubGetOffline.hashCode ^ + // Extracting hashCode from environment here as it does not implement + // hashCode + (environment?.sdkConstraint).hashCode ^ + const DeepCollectionEquality().hash( + environment?.unParsedYaml, + ) ^ + const DeepCollectionEquality().hash(dependencies) ^ + const DeepCollectionEquality().hash(devDependencies) ^ const DeepCollectionEquality(_GlobEquality()) .hash(dependencyOverridePaths) ^ hooks.hashCode; @@ -468,6 +535,9 @@ class BootstrapCommandConfigs { BootstrapCommandConfigs( runPubGetInParallel: $runPubGetInParallel, runPubGetOffline: $runPubGetOffline, + environment: $environment, + dependencies: $dependencies, + devDependencies: $devDependencies, dependencyOverridePaths: $dependencyOverridePaths, hooks: $hooks, )'''; diff --git a/packages/melos/test/commands/bootstrap_test.dart b/packages/melos/test/commands/bootstrap_test.dart index acaeb421..5f380815 100644 --- a/packages/melos/test/commands/bootstrap_test.dart +++ b/packages/melos/test/commands/bootstrap_test.dart @@ -2,6 +2,7 @@ import 'dart:io' as io; import 'package:melos/melos.dart'; import 'package:melos/src/commands/runner.dart'; +import 'package:melos/src/common/glob.dart'; import 'package:melos/src/common/utils.dart'; import 'package:path/path.dart' as p; import 'package:pub_semver/pub_semver.dart'; @@ -587,6 +588,164 @@ Generating IntelliJ IDE files... ), ); }); + + test( + 'applies dependencies from melos config', + () async { + final workspaceDir = await createTemporaryWorkspace( + configBuilder: (path) => MelosWorkspaceConfig( + name: 'Melos', + packages: [ + createGlob('packages/**', currentDirectoryPath: path), + ], + commands: CommandConfigs( + bootstrap: BootstrapCommandConfigs( + environment: Environment( + VersionConstraint.parse('>=2.18.0 <3.0.0'), + {'flutter': '>=2.18.0 <3.0.0'}, + ), + dependencies: { + 'intl': HostedReference( + VersionConstraint.compatibleWith(Version.parse('0.18.1')), + ), + 'integral_isolates': HostedReference( + VersionConstraint.compatibleWith(Version.parse('0.4.1')), + ), + 'path': HostedReference( + VersionConstraint.compatibleWith(Version.parse('1.8.3')), + ), + }, + devDependencies: { + 'build_runner': HostedReference( + VersionConstraint.compatibleWith(Version.parse('2.4.6')), + ), + }, + ), + ), + path: path, + ), + ); + + final pkgA = await createProject( + workspaceDir, + PubSpec( + name: 'a', + environment: Environment( + VersionConstraint.any, + {}, + ), + dependencies: { + 'intl': HostedReference( + VersionConstraint.compatibleWith(Version.parse('0.18.1')), + ), + 'path': HostedReference( + VersionConstraint.compatibleWith(Version.parse('1.7.2')), + ), + }, + devDependencies: { + 'build_runner': HostedReference( + VersionConstraint.compatibleWith(Version.parse('2.4.0')), + ), + }, + ), + ); + + final pkgB = await createProject( + workspaceDir, + PubSpec( + name: 'b', + environment: Environment( + VersionRange( + min: Version.parse('2.12.0'), + max: Version.parse('3.0.0'), + includeMin: true, + ), + { + 'flutter': '>=2.12.0 <3.0.0', + }, + ), + dependencies: { + 'integral_isolates': HostedReference( + VersionConstraint.compatibleWith(Version.parse('0.4.1')), + ), + 'intl': HostedReference( + VersionConstraint.compatibleWith(Version.parse('0.17.0')), + ), + 'path': HostedReference(VersionConstraint.any), + }, + ), + ); + + final logger = TestLogger(); + final config = + await MelosWorkspaceConfig.fromWorkspaceRoot(workspaceDir); + final melos = Melos( + logger: logger, + config: config, + ); + + await runMelosBootstrap(melos, logger); + + final pubspecA = pubSpecFromYamlFile(directory: pkgA.path); + final pubspecB = pubSpecFromYamlFile(directory: pkgB.path); + + expect( + pubspecA.environment?.sdkConstraint, + equals(VersionConstraint.parse('>=2.18.0 <3.0.0')), + ); + expect( + pubspecA.environment?.unParsedYaml, + equals({}), + ); + expect( + pubspecA.dependencies, + equals({ + 'intl': HostedReference( + VersionConstraint.compatibleWith(Version.parse('0.18.1')), + ), + 'path': HostedReference( + VersionConstraint.compatibleWith(Version.parse('1.8.3')), + ), + }), + ); + expect( + pubspecA.devDependencies, + equals({ + 'build_runner': HostedReference( + VersionConstraint.compatibleWith(Version.parse('2.4.6')), + ), + }), + ); + + expect( + pubspecB.environment?.sdkConstraint, + equals(VersionConstraint.parse('>=2.18.0 <3.0.0')), + ); + expect( + pubspecB.environment?.unParsedYaml, + equals({'flutter': '>=2.18.0 <3.0.0'}), + ); + expect( + pubspecB.dependencies, + equals({ + 'integral_isolates': HostedReference( + VersionConstraint.compatibleWith(Version.parse('0.4.1')), + ), + 'intl': HostedReference( + VersionConstraint.compatibleWith(Version.parse('0.18.1')), + ), + 'path': HostedReference( + VersionConstraint.compatibleWith(Version.parse('1.8.3')), + ), + }), + ); + expect( + pubspecB.devDependencies, + equals({}), + ); + }, + timeout: const Timeout(Duration(days: 2)), + ); }); } diff --git a/packages/melos/test/utils.dart b/packages/melos/test/utils.dart index e03df46c..6d15feac 100644 --- a/packages/melos/test/utils.dart +++ b/packages/melos/test/utils.dart @@ -284,6 +284,13 @@ PubSpec pubSpecFromJsonFile({ return PubSpec.fromJson(json.decode(jsonAsString) as Map); } +PubSpec pubSpecFromYamlFile({ + required String directory, +}) { + final filePath = pubspecPathForDirectory(directory); + return PubSpec.fromYamlString(readTextFile(filePath)); +} + /// Builder to build a [MelosWorkspace] that is entirely virtual and only exists /// in memory. class VirtualWorkspaceBuilder { From 09dc1edf8e8ce5c52a9f66fa51fe762d7460a133 Mon Sep 17 00:00:00 2001 From: mike Date: Tue, 24 Oct 2023 11:59:02 -0500 Subject: [PATCH 3/5] chore(release): publish packages - melos@3.2.0 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ packages/melos/CHANGELOG.md | 8 ++++++++ packages/melos/lib/version.g.dart | 2 +- packages/melos/pubspec.yaml | 2 +- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10dd5448..c9781d57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,31 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2023-10-24 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`melos` - `v3.2.0`](#melos---v320) + +--- + +#### `melos` - `v3.2.0` + + - **REFACTOR**: fix analyzer issues ([#590](https://github.com/invertase/melos/issues/590)). ([2f19770e](https://github.com/invertase/melos/commit/2f19770eee9deff097d26202bece72bd6b2127a1)) + - **FEAT**: support syncing common dependency versions ([#526](https://github.com/invertase/melos/issues/526)). ([39e5e499](https://github.com/invertase/melos/commit/39e5e499d71e95cf7794ae724ab2ccd3bb4e9fd5)) + - **FEAT**: Expose `Changelog` and `ManualVersionChange` ([#538](https://github.com/invertase/melos/issues/538)). ([b049ed89](https://github.com/invertase/melos/commit/b049ed897402921a5b0f3b818e49b47e3b3bf4cf)) + - **DOCS**: added link to `atproto.dart` ([#544](https://github.com/invertase/melos/issues/544)). ([aa891d82](https://github.com/invertase/melos/commit/aa891d8268f0aba7335ca274af747a15c9e72848)) + - **DOCS**: growerp also use melos ([#551](https://github.com/invertase/melos/issues/551)). ([c679622f](https://github.com/invertase/melos/commit/c679622f1279107e31ec1d10d2b21c18877f7771)) + + ## 2023-07-14 ### Changes diff --git a/packages/melos/CHANGELOG.md b/packages/melos/CHANGELOG.md index 4c5e0192..d8c36f93 100644 --- a/packages/melos/CHANGELOG.md +++ b/packages/melos/CHANGELOG.md @@ -1,3 +1,11 @@ +## 3.2.0 + + - **REFACTOR**: fix analyzer issues ([#590](https://github.com/invertase/melos/issues/590)). ([2f19770e](https://github.com/invertase/melos/commit/2f19770eee9deff097d26202bece72bd6b2127a1)) + - **FEAT**: support syncing common dependency versions ([#526](https://github.com/invertase/melos/issues/526)). ([39e5e499](https://github.com/invertase/melos/commit/39e5e499d71e95cf7794ae724ab2ccd3bb4e9fd5)) + - **FEAT**: Expose `Changelog` and `ManualVersionChange` ([#538](https://github.com/invertase/melos/issues/538)). ([b049ed89](https://github.com/invertase/melos/commit/b049ed897402921a5b0f3b818e49b47e3b3bf4cf)) + - **DOCS**: added link to `atproto.dart` ([#544](https://github.com/invertase/melos/issues/544)). ([aa891d82](https://github.com/invertase/melos/commit/aa891d8268f0aba7335ca274af747a15c9e72848)) + - **DOCS**: growerp also use melos ([#551](https://github.com/invertase/melos/issues/551)). ([c679622f](https://github.com/invertase/melos/commit/c679622f1279107e31ec1d10d2b21c18877f7771)) + ## 3.1.1 - **FIX**: pass extra args to exec scripts ([#540](https://github.com/invertase/melos/issues/540)). ([27b2275d](https://github.com/invertase/melos/commit/27b2275d5f44cbc3b93e780c88618363afca0b55)) diff --git a/packages/melos/lib/version.g.dart b/packages/melos/lib/version.g.dart index 308d40bb..3be14de5 100644 --- a/packages/melos/lib/version.g.dart +++ b/packages/melos/lib/version.g.dart @@ -1,2 +1,2 @@ // This file is generated. Do not manually edit. -String melosVersion = '3.1.1'; +String melosVersion = '3.2.0'; diff --git a/packages/melos/pubspec.yaml b/packages/melos/pubspec.yaml index 70f52535..1c5c5840 100644 --- a/packages/melos/pubspec.yaml +++ b/packages/melos/pubspec.yaml @@ -3,7 +3,7 @@ description: A tool for managing Dart & Flutter repositories with multiple packages (monorepo). Supports automated versioning via Conventional Commits. Inspired by JavaScripts Lerna package. -version: 3.1.1 +version: 3.2.0 homepage: https://melos.invertase.dev/~melos-latest repository: https://github.com/invertase/melos/tree/main/packages/melos issue_tracker: https://github.com/invertase/melos/issues From b4398c0eda454384d0479c5125cc4cd0d6d7ab91 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 6 Nov 2023 16:22:58 +0100 Subject: [PATCH 4/5] docs: Update to correct file reference in shared dependencies (#596) --- docs/commands/bootstrap.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/commands/bootstrap.mdx b/docs/commands/bootstrap.mdx index 6301a7c2..e2977fb1 100644 --- a/docs/commands/bootstrap.mdx +++ b/docs/commands/bootstrap.mdx @@ -97,7 +97,7 @@ project, just add the dependencies you wish to share between the packages to your bootstrap config in your `melos.yaml` file. If a dependency from `environment`, `dependencies` or `dev_dependencies` in -your `common_packages.yaml` exists in a package, the dependency version in this +your `melos.yaml` exists in a package, the dependency version in this package will be updated to match the version defined in your bootstrap config every time `melos bootstrap` is run. From 6a64b0595d01003145049125226fa2db2c45c918 Mon Sep 17 00:00:00 2001 From: Karlo Verde <42245236+mrverdant13@users.noreply.github.com> Date: Mon, 6 Nov 2023 10:27:56 -0500 Subject: [PATCH 5/5] docs(melos): add `coverde` to projects using Melos (#562) --- docs/index.mdx | 1 + packages/melos/README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/index.mdx b/docs/index.mdx index 32745e7e..e97ef163 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -57,6 +57,7 @@ The following projects are using Melos: - [NetGlade/auto_mappr](https://github.com/netglade/auto_mappr) - [myConsciousness/atproto.dart](https://github.com/myConsciousness/atproto.dart) - [GrowERP Flutter ERP](https://github.com/growerp/growerp) +- [mrverdant13/coverde](https://github.com/mrverdant13/coverde) diff --git a/packages/melos/README.md b/packages/melos/README.md index 276d6a6c..3999c5da 100644 --- a/packages/melos/README.md +++ b/packages/melos/README.md @@ -140,6 +140,7 @@ The following projects are using Melos: - [NetGlade/auto_mappr](https://github.com/netglade/auto_mappr) - [myConsciousness/atproto.dart](https://github.com/myConsciousness/atproto.dart) - [GrowERP Flutter ERP](https://github.com/growerp/growerp) +- [mrverdant13/coverde](https://github.com/mrverdant13/coverde) > Submit a PR if you'd like to add your project to the list. Update the > [README.md](https://github.com/invertase/melos/edit/main/packages/melos/README.md)