Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Version 0.16.3
- adds more diff result reporting options (cli, json, markdown)
- fixes broken local packages refs
- Add version check to reported output.

## Version 0.16.2
- fixes relative path handling in package config (leading to unresolvable types)
Expand Down
26 changes: 15 additions & 11 deletions lib/src/cli/commands/diff_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -198,19 +198,23 @@ You may want to do this if you want to make sure
}
})();

VersionCheckResult? versionCheckResult;
if (versionCheckMode != VersionCheckMode.none) {
versionCheckResult = VersionCheck.check(
diffResult: diffResult,
oldPackageApi: oldPackageApi,
newPackageApi: newPackageApi,
ignorePrerelease: ignorePrerelease,
versionCheckMode: versionCheckMode,
);
}

stdout.writeln('-- Generating report using: ${reporter.reporterName} --');
await reporter.generateReport(diffResult);

if (versionCheckMode != VersionCheckMode.none &&
!VersionCheck.versionChangeMatchesChanges(
diffResult: diffResult,
oldPackageApi: oldPackageApi,
newPackageApi: newPackageApi,
ignorePrerelease: ignorePrerelease,
versionCheckMode: versionCheckMode)) {
await reporter.generateReport(diffResult, versionCheckResult);
if (versionCheckResult?.success ?? true) {
return 0;
} else {
return -1;
}

return 0;
}
}
103 changes: 71 additions & 32 deletions lib/src/cli/commands/version_check.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,40 @@ import 'package:pub_semver/pub_semver.dart';

import '../../../api_tool.dart';

class VersionCheckResult {
final bool success;
final Version oldVersion;
final Version newVersion;
final Version? neededVersion;
final String explanation;

VersionCheckResult.success({
required this.oldVersion,
required this.newVersion,
Version? neededVersion,
required this.explanation,
}) : success = true,
neededVersion = neededVersion ?? newVersion;

VersionCheckResult.failure({
required this.oldVersion,
required this.newVersion,
required this.neededVersion,
required this.explanation,
}) : success = false;
}

/// helper class to check if the version change matches the changes
abstract class VersionCheck {
/// checks if the version change between [oldPackageApi] and [newPackageApi] matches the changes in [diffResult]
static bool versionChangeMatchesChanges({
static VersionCheckResult check({
required PackageApiDiffResult diffResult,
required PackageApi oldPackageApi,
required PackageApi newPackageApi,
required bool ignorePrerelease,
required VersionCheckMode versionCheckMode,
}) {
stdout.writeln('');
stdout.writeln('Checking Package version');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what you want to still stdout here.

stdout.writeln('');
if (oldPackageApi.packageVersion == null) {
throw PackageApiDiffError(
message: 'Old package doesn\'t contain a version]');
Expand All @@ -36,14 +57,21 @@ abstract class VersionCheck {
diffResult.apiChanges.any((change) => !change.type.requiresMinorBump);

if (versionCheckMode == VersionCheckMode.none) {
stdout.writeln('Skipping version check completely');
return true;
return VersionCheckResult.success(
oldVersion: oldVersion,
newVersion: newVersion,
explanation:
'Skipping version check completely as the version check mode is $versionCheckMode',
);
}
if (versionCheckMode == VersionCheckMode.onlyBreakingChanges &&
!containsBreakingChanges) {
stdout.writeln(
'Skipping version check because there are no breaking changes');
return true;
return VersionCheckResult.success(
oldVersion: oldVersion,
newVersion: newVersion,
explanation:
'Skipping version check because there are no breaking changes',
);
}

if (ignorePrerelease) {
Expand All @@ -57,28 +85,36 @@ abstract class VersionCheck {
final oldVersionWithoutPreRelease = Version.parse(oldVersion.toString());
oldVersionWithoutPreRelease.preRelease.clear();
if (oldVersionWithoutPreRelease <= newVersion) {
stdout.writeln(
'Skipping version check because the old version is a pre-release and the new version is the same or higher without the pre-release part');
return true;
return VersionCheckResult.success(
oldVersion: oldVersion,
newVersion: newVersion,
explanation:
'Skipping version check because the old version is a pre-release and the new version is the same or higher without the pre-release part',
);
}
}

if (newVersion.isPreRelease) {
// pre-release. We don't look at differentiation between breaking and non-breaking changes
stdout.writeln(
'We got a pre release. We only check if there are any changes');
final prefix =
'We got a pre release. We only check if there are any changes.';
if (containsAnyChanges && oldVersion >= newVersion) {
stdout.writeln(
'Got "${Colorize(newVersion.toString()).bold()}" expected > "${Colorize(oldVersion.toString()).bold()}" (pre-release but changes)');
return false;
return VersionCheckResult.failure(
oldVersion: oldVersion,
newVersion: newVersion,
neededVersion: null,
explanation:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to change the explanations to anything you like better.

'$prefix Got "${Colorize(newVersion.toString()).bold()}" expected > "${Colorize(oldVersion.toString()).bold()}" (pre-release but changes)',
);
}
stdout.writeln(Colorize('New version is OK!').green());
final explaination = containsAnyChanges
final explanation = containsAnyChanges
? 'which is > "${Colorize(oldVersion.toString()).bold()}" (pre-release but changes)'
: 'and no changes';
stdout.writeln(
'Got "${Colorize(newVersion.toString()).bold()}" $explaination');
return true;
return VersionCheckResult.success(
oldVersion: oldVersion,
newVersion: newVersion,
explanation:
'$prefix Got "${Colorize(newVersion.toString()).bold()}" $explanation');
}

Version expectedMinVersion =
Expand All @@ -99,19 +135,22 @@ abstract class VersionCheck {
}
}

stdout.writeln('Old version: "$oldVersion"');
stdout.writeln(
'Expecting minimum version: "$expectedMinVersion" ($versionExplanation)');
if (newVersion < expectedMinVersion) {
stdout.writeln(Colorize('New Version is too low!').red());
stdout.writeln(
'Got "${Colorize(newVersion.toString()).bold()}" expected >= "${Colorize(expectedMinVersion.toString()).bold()}"');
return false;
return VersionCheckResult.failure(
oldVersion: oldVersion,
newVersion: newVersion,
neededVersion: expectedMinVersion,
explanation:
'Got "${Colorize(newVersion.toString()).bold()}" expected >= "${Colorize(expectedMinVersion.toString()).bold()}" ($versionExplanation)',
);
} else {
stdout.writeln(Colorize('New version is OK!').green());
stdout.writeln(
'Got "${Colorize(newVersion.toString()).bold()}" which is >= "${Colorize(expectedMinVersion.toString()).bold()}"');
return true;
return VersionCheckResult.success(
oldVersion: oldVersion,
newVersion: newVersion,
neededVersion: expectedMinVersion,
explanation:
'Got "${Colorize(newVersion.toString()).bold()}" which is >= "${Colorize(expectedMinVersion.toString()).bold()}" ($versionExplanation)',
);
}
}
}
23 changes: 22 additions & 1 deletion lib/src/diff/report/console_diff_reporter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import 'package:colorize/colorize.dart';
import 'package:console/console.dart';

import '../../../api_tool.dart';
import '../../cli/commands/version_check.dart';
import 'diff_reporter.dart';

class ConsoleDiffReporter extends DiffReporter {
@override
final String reporterName = 'Console Reporter';

@override
Future<void> generateReport(PackageApiDiffResult diffResult) async {
Future<void> generateReport(
PackageApiDiffResult diffResult,
VersionCheckResult? versionCheckResult,
) async {
void printChanges(bool breaking) {
final changes = _printApiChangeNode(diffResult.rootNode, breaking);
if (changes == null) {
Expand All @@ -32,6 +36,23 @@ class ConsoleDiffReporter extends DiffReporter {
} else {
stdout.writeln('No changes detected!');
}

if (versionCheckResult != null) {
stdout.writeln('Version Check');
if (versionCheckResult.success) {
stdout.writeln(Colorize('New version is OK!').green());
} else {
stdout.writeln(Colorize('New Version is too low!').red());
}
stdout.writeln();
stdout.writeln('Old version: "${versionCheckResult.oldVersion}"');
stdout.writeln('New version: "${versionCheckResult.newVersion}"');
if (versionCheckResult.neededVersion != null) {
stdout.writeln('Needed version: "${versionCheckResult.neededVersion}"');
}
stdout.writeln();
stdout.writeln(versionCheckResult.explanation);
}
}

String? _printApiChangeNode(ApiChangeTreeNode node, bool breaking) {
Expand Down
7 changes: 6 additions & 1 deletion lib/src/diff/report/diff_reporter.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import 'package:dart_apitool/src/cli/commands/version_check.dart';

import '../../../api_tool.dart';

abstract class DiffReporter {
String get reporterName;

Future<void> generateReport(PackageApiDiffResult diffResult);
Future<void> generateReport(
PackageApiDiffResult diffResult,
VersionCheckResult? versionCheckResult,
);
}
42 changes: 30 additions & 12 deletions lib/src/diff/report/json_diff_reporter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:convert';
import 'dart:io';

import '../../../api_tool_cli.dart';
import '../../cli/commands/version_check.dart';
import 'diff_reporter.dart';

class JsonDiffReporter extends DiffReporter {
Expand All @@ -17,8 +18,11 @@ class JsonDiffReporter extends DiffReporter {
});

@override
Future<void> generateReport(PackageApiDiffResult diffResult) async {
final jsonReport = <String, dynamic>{
Future<void> generateReport(
PackageApiDiffResult diffResult,
VersionCheckResult? versionCheckResult,
) async {
final report = <String, dynamic>{
'reportName': 'API Changes Report',
'apiToolInfo': {
'toolName': 'dart_apitool',
Expand All @@ -27,15 +31,33 @@ class JsonDiffReporter extends DiffReporter {
'generatedAt': DateTime.now().toUtc().toLocal().toString(),
'oldRef': oldPackageRef.ref,
'newRef': newPackageRef.ref
},
'report': {},
}
};

if (versionCheckResult != null) {
report['version'] = {
'success': versionCheckResult.success,
'old': versionCheckResult.oldVersion,
'new': versionCheckResult.newVersion,
'needed': versionCheckResult.neededVersion,
'explanation': versionCheckResult.explanation,
};
}

report['report'] = getChanges(diffResult);
// Write the JSON report to a file
await outputFile.writeAsString(jsonEncode(report));

print('JSON report generated at ${outputFile.path}');
}

Map<String, dynamic> getChanges(PackageApiDiffResult diffResult) {
final changeReport = <String, dynamic>{};
void addChanges(bool breaking) {
final changes = _printApiChangeNode(diffResult.rootNode, breaking);
if (changes != null) {
jsonReport['report']
[breaking ? 'breakingChanges' : 'nonBreakingChanges'] = changes;
changeReport[breaking ? 'breakingChanges' : 'nonBreakingChanges'] =
changes;
}
}

Expand All @@ -44,13 +66,9 @@ class JsonDiffReporter extends DiffReporter {
addChanges(true); // Breaking changes
addChanges(false); // Non-breaking changes
} else {
jsonReport['report']['noChangesDetected'] = true;
changeReport['noChangesDetected'] = true;
}

// Write the JSON report to a file
await outputFile.writeAsString(jsonEncode(jsonReport));

print('JSON report generated at ${outputFile.path}');
return changeReport;
}

Map<String, dynamic>? _printApiChangeNode(
Expand Down
23 changes: 22 additions & 1 deletion lib/src/diff/report/markdown_diff_reporter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:io';

import 'package:dart_apitool/api_tool_cli.dart';

import '../../cli/commands/version_check.dart';
import 'diff_reporter.dart';

const changeCodesReadMe =
Expand All @@ -20,7 +21,10 @@ class MarkdownDiffReporter extends DiffReporter {
});

@override
Future<void> generateReport(PackageApiDiffResult diffResult) async {
Future<void> generateReport(
PackageApiDiffResult diffResult,
VersionCheckResult? versionCheckResult,
) async {
final markdownReport = StringBuffer();
markdownReport
..writeln('# API Changes Report')
Expand Down Expand Up @@ -62,6 +66,23 @@ class MarkdownDiffReporter extends DiffReporter {
..writeln('No changes detected!');
}

if (versionCheckResult != null) {
stdout.writeln('### Version Check');
if (versionCheckResult.success) {
stdout.writeln('New version is OK!');
} else {
stdout.writeln('New Version is too low!');
}
stdout.writeln();
stdout.writeln('Old version: "${versionCheckResult.oldVersion}"');
stdout.writeln('New version: "${versionCheckResult.newVersion}"');
if (versionCheckResult.neededVersion != null) {
stdout.writeln('Needed version: "${versionCheckResult.neededVersion}"');
}
stdout.writeln();
stdout.writeln(versionCheckResult.explanation);
}

// Write the Markdown report to a file
await outputFile.writeAsString(markdownReport.toString());

Expand Down
Loading