From c76c08f3660ae7679a4ab7631d633ba05e36e608 Mon Sep 17 00:00:00 2001 From: Frans Stofberg Date: Wed, 16 Mar 2022 13:03:51 +0200 Subject: [PATCH] feat: support git hosted package dependencies when versioning (#256) Co-authored-by: Mike Diarmid --- docs/configuration/overview.mdx | 10 +++++++ docs/guides/automated-releases.mdx | 30 +++++++++++++++++++ packages/melos/lib/src/commands/version.dart | 28 ++++++++++++++--- packages/melos/lib/src/package.dart | 7 +++++ packages/melos/lib/src/workspace_configs.dart | 15 ++++++++++ 5 files changed, 86 insertions(+), 4 deletions(-) diff --git a/docs/configuration/overview.mdx b/docs/configuration/overview.mdx index 072a4cc9..163a7ec2 100644 --- a/docs/configuration/overview.mdx +++ b/docs/configuration/overview.mdx @@ -131,3 +131,13 @@ command: version: workspaceChangelog: true ``` + +### `command/version/updateGitTagRefs` + +When running `melos version` this option will allow updates to `pubspec.yaml` for locally (git) hosted packages part of this melos workspace, see [here](/guides/automated-releases#git-hosted-packages) + +```yaml +command: + version: + updateGitTagRefs: true +``` diff --git a/docs/guides/automated-releases.mdx b/docs/guides/automated-releases.mdx index 2ad6c999..352179b4 100644 --- a/docs/guides/automated-releases.mdx +++ b/docs/guides/automated-releases.mdx @@ -53,3 +53,33 @@ Once satisfied with your pending releases, release them to [pub.dev](https://pub ```dart melos publish --no-dry-run ``` + +## Git hosted packages + +To use this feature enable it in `melos.yaml` +```yaml +command: + version: + updateGitTagRefs: true # defaults to false +``` + +If your packages are private and don't publish to [pub.dev](https://pub.dev), you can use the tag generated as git reference in your `pubspec.yaml` file and Melos will ensure the versions are updated accordingly. + +Example: +```yaml +dependencies: + internal_dep: + git: + url: git@github.com:org/repo.git + path: packages/internal_dep + ref: internal_dep-v0.0.1 + +# will be updated to: + +dependencies: + internal_dep: + git: + url: git@github.com:org/repo.git + path: packages/internal_dep + ref: internal_dep-v0.0.2 +``` diff --git a/packages/melos/lib/src/commands/version.dart b/packages/melos/lib/src/commands/version.dart index 7043dda5..fa5b4f76 100644 --- a/packages/melos/lib/src/commands/version.dart +++ b/packages/melos/lib/src/commands/version.dart @@ -367,6 +367,7 @@ Hint: try running "melos version --all" to include private packages. Package package, String dependencyName, Version version, + MelosWorkspace workspace, ) { final currentVersionConstraint = (package.pubSpec.dependencies[dependencyName] ?? @@ -381,6 +382,7 @@ Hint: try running "melos version --all" to include private packages. package, dependencyName, version, + workspace, ); } @@ -408,6 +410,7 @@ Hint: try running "melos version --all" to include private packages. package, dependencyName, versionConstraint, + workspace, ); } @@ -415,8 +418,10 @@ Hint: try running "melos version --all" to include private packages. Package package, String dependencyName, VersionConstraint dependencyVersion, + MelosWorkspace workspace, ) async { if (package.pubSpec.dependencies.containsKey(dependencyName) && + package.pubSpec.dependencies[dependencyName] is! GitReference && package.pubSpec.dependencies[dependencyName] is! HostedReference && package.pubSpec.dependencies[dependencyName] is! ExternalHostedReference) { @@ -427,6 +432,7 @@ Hint: try running "melos version --all" to include private packages. return; } if (package.pubSpec.devDependencies.containsKey(dependencyName) && + package.pubSpec.devDependencies[dependencyName] is! GitReference && package.pubSpec.devDependencies[dependencyName] is! HostedReference && package.pubSpec.devDependencies[dependencyName] is! ExternalHostedReference) { @@ -439,10 +445,23 @@ Hint: try running "melos version --all" to include private packages. final pubspec = File(pubspecPathForDirectory(Directory(package.path))); final contents = await pubspec.readAsString(); - final updatedContents = contents.replaceAllMapped( - dependencyVersionReplaceRegex(dependencyName), (Match match) { - return '${match.group(1)}$dependencyVersion'; - }); + String updatedContents; + + final gitReference = + package.pubSpec.dependencies[dependencyName] is GitReference || + package.pubSpec.devDependencies[dependencyName] is GitReference; + + if (gitReference && workspace.config.commands.version.updateGitTagRefs) { + updatedContents = contents.replaceAllMapped( + dependencyTagReplaceRegex(dependencyName), (Match match) { + return '${match.group(1)}$dependencyName-v${dependencyVersion.toString().substring(1)}'; + }); + } else { + updatedContents = contents.replaceAllMapped( + dependencyVersionReplaceRegex(dependencyName), (Match match) { + return '${match.group(1)}$dependencyVersion'; + }); + } // Sanity check that contents actually changed. if (contents == updatedContents) { @@ -558,6 +577,7 @@ Hint: try running "melos version --all" to include private packages. !updateDependentsVersions) ? pendingPackageUpdate.package.version : pendingPackageUpdate.nextVersion, + workspace, ); }); } diff --git a/packages/melos/lib/src/package.dart b/packages/melos/lib/src/package.dart index 5418eb18..7427b5a8 100644 --- a/packages/melos/lib/src/package.dart +++ b/packages/melos/lib/src/package.dart @@ -105,6 +105,13 @@ RegExp dependencyVersionReplaceRegex(String dependencyName) { ); } +RegExp dependencyTagReplaceRegex(String dependencyName) { + return RegExp( + '''(?^\\s+ref\\s?:\\s?)(?["']?)(?$dependencyName-v[\\d]+\\.[\\d]+\\.[\\d]+)(?['"]?)\$''', + multiLine: true, + ); +} + class PackageFilter { PackageFilter({ this.scope = const [], diff --git a/packages/melos/lib/src/workspace_configs.dart b/packages/melos/lib/src/workspace_configs.dart index 4d80b8a7..06af381f 100644 --- a/packages/melos/lib/src/workspace_configs.dart +++ b/packages/melos/lib/src/workspace_configs.dart @@ -167,6 +167,7 @@ class VersionCommandConfigs { this.linkToCommits, this.branch, this.workspaceChangelog = false, + this.updateGitTagRefs = false, }); factory VersionCommandConfigs.fromYaml(Map yaml) { @@ -192,11 +193,18 @@ class VersionCommandConfigs { path: 'command/version', ); + final updateGitTagRefs = assertKeyIsA( + key: 'updateGitTagRefs', + map: yaml, + path: 'command/version', + ); + return VersionCommandConfigs( branch: branch, linkToCommits: linkToCommits, message: message, workspaceChangelog: workspaceChangelog ?? false, + updateGitTagRefs: updateGitTagRefs ?? false, ); } @@ -211,6 +219,9 @@ class VersionCommandConfigs { /// Whether to also generate a CHANGELOG.md for the entire workspace at the root. final bool workspaceChangelog; + /// Whether to also update pubspec with git referenced packages. + final bool updateGitTagRefs; + /// If specified, prevents `melos version` from being used inside branches /// other than the one specified. final String? branch; @@ -221,6 +232,7 @@ class VersionCommandConfigs { if (linkToCommits != null) 'linkToCommits': linkToCommits, if (branch != null) 'branch': branch, 'workspaceChangelog': workspaceChangelog, + 'updateGitTagRefs': updateGitTagRefs, }; } @@ -231,6 +243,7 @@ class VersionCommandConfigs { other.message == message && other.linkToCommits == linkToCommits && other.workspaceChangelog == workspaceChangelog && + other.updateGitTagRefs == updateGitTagRefs && other.branch == branch; @override @@ -239,6 +252,7 @@ class VersionCommandConfigs { message.hashCode ^ linkToCommits.hashCode ^ workspaceChangelog.hashCode ^ + updateGitTagRefs.hashCode ^ branch.hashCode; @override @@ -248,6 +262,7 @@ VersionCommandConfigs( message: $message, linkToCommits: $linkToCommits, workspaceChangelog: $workspaceChangelog, + updateGitTagRefs: $updateGitTagRefs, branch: $branch, )'''; }