Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add version check to reported output #164

Merged
merged 7 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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.17.0
- bump dart SDK requirements to >=3.0.0
- Search downloaded packages in entire .pub-cache hosted directory in case path namining changes
- adds information about the package versions and the version check result to the reports (console, json, markdown)

## Version 0.16.3
- adds more diff result reporting options (cli, json, markdown)
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;
}
}
105 changes: 71 additions & 34 deletions lib/src/cli/commands/version_check.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,43 @@
import 'dart:io';

import 'package:colorize/colorize.dart';
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 +56,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 +84,35 @@ 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 "$newVersion" expected > "$oldVersion" (pre-release but changes)',
);
}
stdout.writeln(Colorize('New version is OK!').green());
final explaination = containsAnyChanges
? 'which is > "${Colorize(oldVersion.toString()).bold()}" (pre-release but changes)'
final explanation = containsAnyChanges
? 'which is > "$oldVersion" (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 "$newVersion" $explanation');
}

Version expectedMinVersion =
Expand All @@ -99,19 +133,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 "$newVersion" expected >= "$expectedMinVersion" ($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 "$newVersion" which is >= "$expectedMinVersion" ($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.toString(),
'new': versionCheckResult.newVersion.toString(),
'needed': versionCheckResult.neededVersion?.toString(),
'explanation': versionCheckResult.explanation.toString(),
};
}

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
2 changes: 0 additions & 2 deletions lib/src/tooling/pub_interaction.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ abstract class PubInteraction {
final packagePath = path.join(hostedUrl, '$packageName-$version');
if (Directory(packagePath).existsSync()) {
return packagePath;
} else {
return null;
}
}
return null;
Expand Down
Loading
Loading