Skip to content

Commit

Permalink
feat: support git hosted package dependencies when versioning (#256)
Browse files Browse the repository at this point in the history
Co-authored-by: Mike Diarmid <[email protected]>
  • Loading branch information
fstof and Salakar authored Mar 16, 2022
1 parent 9a5cb26 commit c76c08f
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 4 deletions.
10 changes: 10 additions & 0 deletions docs/configuration/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
30 changes: 30 additions & 0 deletions docs/guides/automated-releases.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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: [email protected]:org/repo.git
path: packages/internal_dep
ref: internal_dep-v0.0.1
# will be updated to:
dependencies:
internal_dep:
git:
url: [email protected]:org/repo.git
path: packages/internal_dep
ref: internal_dep-v0.0.2
```
28 changes: 24 additions & 4 deletions packages/melos/lib/src/commands/version.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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] ??
Expand All @@ -381,6 +382,7 @@ Hint: try running "melos version --all" to include private packages.
package,
dependencyName,
version,
workspace,
);
}

Expand Down Expand Up @@ -408,15 +410,18 @@ Hint: try running "melos version --all" to include private packages.
package,
dependencyName,
versionConstraint,
workspace,
);
}

Future<void> _setDependencyVersionForPackage(
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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -558,6 +577,7 @@ Hint: try running "melos version --all" to include private packages.
!updateDependentsVersions)
? pendingPackageUpdate.package.version
: pendingPackageUpdate.nextVersion,
workspace,
);
});
}
Expand Down
7 changes: 7 additions & 0 deletions packages/melos/lib/src/package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ RegExp dependencyVersionReplaceRegex(String dependencyName) {
);
}

RegExp dependencyTagReplaceRegex(String dependencyName) {
return RegExp(
'''(?<tag_ref>^\\s+ref\\s?:\\s?)(?<opening_quote>["']?)(?<tag>$dependencyName-v[\\d]+\\.[\\d]+\\.[\\d]+)(?<closing_quote>['"]?)\$''',
multiLine: true,
);
}

class PackageFilter {
PackageFilter({
this.scope = const [],
Expand Down
15 changes: 15 additions & 0 deletions packages/melos/lib/src/workspace_configs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ class VersionCommandConfigs {
this.linkToCommits,
this.branch,
this.workspaceChangelog = false,
this.updateGitTagRefs = false,
});

factory VersionCommandConfigs.fromYaml(Map<Object?, Object?> yaml) {
Expand All @@ -192,11 +193,18 @@ class VersionCommandConfigs {
path: 'command/version',
);

final updateGitTagRefs = assertKeyIsA<bool?>(
key: 'updateGitTagRefs',
map: yaml,
path: 'command/version',
);

return VersionCommandConfigs(
branch: branch,
linkToCommits: linkToCommits,
message: message,
workspaceChangelog: workspaceChangelog ?? false,
updateGitTagRefs: updateGitTagRefs ?? false,
);
}

Expand All @@ -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;
Expand All @@ -221,6 +232,7 @@ class VersionCommandConfigs {
if (linkToCommits != null) 'linkToCommits': linkToCommits,
if (branch != null) 'branch': branch,
'workspaceChangelog': workspaceChangelog,
'updateGitTagRefs': updateGitTagRefs,
};
}

Expand All @@ -231,6 +243,7 @@ class VersionCommandConfigs {
other.message == message &&
other.linkToCommits == linkToCommits &&
other.workspaceChangelog == workspaceChangelog &&
other.updateGitTagRefs == updateGitTagRefs &&
other.branch == branch;

@override
Expand All @@ -239,6 +252,7 @@ class VersionCommandConfigs {
message.hashCode ^
linkToCommits.hashCode ^
workspaceChangelog.hashCode ^
updateGitTagRefs.hashCode ^
branch.hashCode;

@override
Expand All @@ -248,6 +262,7 @@ VersionCommandConfigs(
message: $message,
linkToCommits: $linkToCommits,
workspaceChangelog: $workspaceChangelog,
updateGitTagRefs: $updateGitTagRefs,
branch: $branch,
)''';
}
Expand Down

0 comments on commit c76c08f

Please sign in to comment.