Skip to content

Commit

Permalink
feat: link to referenced issues/PRs in changelog (#292)
Browse files Browse the repository at this point in the history
  • Loading branch information
blaugold authored May 12, 2022
1 parent cd23798 commit 1883020
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 36 deletions.
29 changes: 24 additions & 5 deletions packages/melos/lib/src/common/changelog.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import 'package:pub_semver/pub_semver.dart';

import '../package.dart';
import 'git_commit.dart';
import 'git_repository.dart';
import 'pending_package_update.dart';

class Changelog {
Expand Down Expand Up @@ -142,6 +143,13 @@ extension ChangelogStringBufferExtension on StringBuffer {
}

void writePackageUpdateChanges(MelosPendingPackageUpdate update) {
final config = update.workspace.config;
final repository = config.repository;
final linkToCommits = config.commands.version.linkToCommits ?? false;

String processCommitHeader(String header) =>
repository != null ? header.withIssueLinks(repository) : header;

// User provided changelog entry message.
if (update.userChangelogMessage != null) {
writeln(' - ${update.userChangelogMessage}');
Expand All @@ -162,17 +170,16 @@ extension ChangelogStringBufferExtension on StringBuffer {
}

if (parsedMessage.isMergeCommit) {
writePunctuated(parsedMessage.header);
writePunctuated(processCommitHeader(parsedMessage.header));
} else {
writeBold(parsedMessage.type!.toUpperCase());
write(': ');
writePunctuated(parsedMessage.description!);
writePunctuated(processCommitHeader(parsedMessage.description!));
}

if (update.workspace.config.commands.version.linkToCommits ?? false) {
if (linkToCommits) {
final shortCommitId = commit.id.substring(0, 8);
final commitUrl =
update.workspace.config.repository!.commitUrl(commit.id);
final commitUrl = repository!.commitUrl(commit.id);
write(' (');
writeLink(shortCommitId, uri: commitUrl.toString());
write(')');
Expand Down Expand Up @@ -207,3 +214,15 @@ List<RichGitCommit> _filteredAndSortedCommits(

return commits;
}

// https://regex101.com/r/Q1IV9n/1
final _issueLinkRegexp = RegExp(r'#(\d+)');

extension on String {
String withIssueLinks(HostedGitRepository repository) {
return replaceAllMapped(_issueLinkRegexp, (match) {
final issueUrl = repository.issueUrl(match.group(1)!);
return '[${match.group(0)}]($issueUrl)';
});
}
}
9 changes: 9 additions & 0 deletions packages/melos/lib/src/common/git_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ abstract class HostedGitRepository {

/// The URL of the commit with the given [id] on the host's web site.
Uri commitUrl(String id);

/// The URL of the issue/PR with the given [id] on the host's web site.
Uri issueUrl(String id);
}

/// A git repository, hosted by GitHub.
Expand Down Expand Up @@ -62,6 +65,9 @@ class GitHubRepository extends HostedGitRepository {
@override
Uri commitUrl(String id) => url.resolve('commit/$id');

@override
Uri issueUrl(String id) => url.resolve('issues/$id');

@override
String toString() {
return '''
Expand Down Expand Up @@ -116,6 +122,9 @@ class GitLabRepository extends HostedGitRepository {
@override
Uri commitUrl(String id) => url.resolve('-/commit/$id');

@override
Uri issueUrl(String id) => url.resolve('-/issues/$id');

@override
String toString() {
return '''
Expand Down
89 changes: 58 additions & 31 deletions packages/melos/test/changelog_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*
*/

import 'package:melos/melos.dart';
import 'package:melos/src/common/changelog.dart';
import 'package:melos/src/common/git_commit.dart';
import 'package:melos/src/common/pending_package_update.dart';
Expand All @@ -25,42 +26,68 @@ import 'utils.dart';
void main() {
group('linkToCommits', () {
test('when enabled, adds link to commit behind each one', () {
final workspaceBuilder = VirtualWorkspaceBuilder(
'''
repository: https://github.com/a/b
command:
version:
linkToCommits: true
''',
)..addPackage(
'''
name: a
''',
);
final workspace = workspaceBuilder.build();
final package = workspace.allPackages['a']!;
final commit = RichGitCommit.tryParse(
GitCommit(
author: 'a',
id: 'b2841394a48cd7d84a4966a788842690e543b2ef',
date: DateTime.now(),
message: 'feat(a): b',
),
)!;
final update = MelosPendingPackageUpdate(
workspace,
package,
[commit],
PackageUpdateReason.commit,
logger: workspace.logger,
);
final changelog = MelosChangelog(update, workspace.logger);
final workspace = buildWorkspaceWithRepository();
final package = workspace.allPackages['test_pkg']!;
final commit = testCommit(message: 'feat(a): b');
final commitUrl = workspace.config.repository!.commitUrl(commit.id);

expect(
changelog.markdown,
renderCommitPackageUpdate(workspace, package, commit),
contains('**FEAT**: b. ([${commit.id.substring(0, 8)}]($commitUrl))'),
);
});
});

test('when repository is specified, adds links to referenced issues/PRs', () {
final workspace = buildWorkspaceWithRepository(linkToCommits: false);
final package = workspace.allPackages['test_pkg']!;
final commit = testCommit(message: 'feat(a): b (#123)');
final issueUrl = workspace.config.repository!.issueUrl('123');

expect(
renderCommitPackageUpdate(workspace, package, commit),
contains('**FEAT**: b ([#123]($issueUrl)).'),
);
});
}

MelosWorkspace buildWorkspaceWithRepository({bool linkToCommits = true}) {
final workspaceBuilder = VirtualWorkspaceBuilder(
'''
repository: https://github.com/a/b
command:
version:
linkToCommits: $linkToCommits
''',
)..addPackage(
'''
name: test_pkg
''',
);
return workspaceBuilder.build();
}

RichGitCommit testCommit({required String message}) => RichGitCommit.tryParse(
GitCommit(
author: 'a',
id: 'b2841394a48cd7d84a4966a788842690e543b2ef',
date: DateTime.now(),
message: message,
),
)!;

String renderCommitPackageUpdate(
MelosWorkspace workspace,
Package package,
RichGitCommit commit,
) {
final update = MelosPendingPackageUpdate(
workspace,
package,
[commit],
PackageUpdateReason.commit,
logger: workspace.logger,
);
final changelog = MelosChangelog(update, workspace.logger);
return changelog.markdown;
}
20 changes: 20 additions & 0 deletions packages/melos/test/git_repository_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,16 @@ void main() {
),
);
});

test('issueUrl returns correct URL', () {
final repo = GitHubRepository(owner: 'a', name: 'b');
const issueId = '123';

expect(
repo.issueUrl(issueId),
Uri.parse('https://github.com/a/b/issues/123'),
);
});
});

group('GitLabRepository', () {
Expand Down Expand Up @@ -113,6 +123,16 @@ void main() {
),
);
});

test('issueUrl returns correct URL', () {
final repo = GitLabRepository(owner: 'a', name: 'b');
const issueId = '123';

expect(
repo.issueUrl(issueId),
Uri.parse('https://gitlab.com/a/b/-/issues/123'),
);
});
});

group('parseHostedGitRepositoryUrl', () {
Expand Down

0 comments on commit 1883020

Please sign in to comment.