From 769e9f2882429f4c304ee93a6e86e4d3f0be4686 Mon Sep 17 00:00:00 2001 From: Ellet Date: Sun, 19 May 2024 22:58:31 +0300 Subject: [PATCH] refactor(update-version-script): update the script to generate the markdown files from a json file that contains the data to allow automate the CHANGELOG.md for the packages easier in CI, add a comment that indicate those files are generated. --- scripts/regenerate_versions.dart | 122 ++++++++++++++++++++++++------- 1 file changed, 96 insertions(+), 26 deletions(-) diff --git a/scripts/regenerate_versions.dart b/scripts/regenerate_versions.dart index 357914f4..0cb3c8f2 100644 --- a/scripts/regenerate_versions.dart +++ b/scripts/regenerate_versions.dart @@ -1,11 +1,12 @@ // ignore_for_file: avoid_print +import 'dart:convert' show jsonDecode, jsonEncode; import 'dart:io' show File, exit; -import 'package:yaml_edit/yaml_edit.dart'; +import 'package:yaml_edit/yaml_edit.dart' show YamlEditor; /// The list of the packages that which will be used to update the `CHANGELOG.md` -/// and `README.md` files for all the packages +/// and the version in the `pubspec.yaml` for all the packages final _packages = [ './', './dart_quill_delta', @@ -15,51 +16,120 @@ final _packages = [ './quill_pdf_converter', ]; +const _usage = 'Usage: ./script '; + /// A script that should run in the root folder and not inside any other folder -/// it has one task, which update the version for `pubspec.yaml` and `CHANGELOG.md` for all the packages -/// since we have only one CHANGELOG.md file and version, previously we had different `CHANGELOG.md` and `pubspec.yaml` package version -/// for each package +/// it has one task, which update the version for `pubspec.yaml` and +/// `CHANGELOG.md` for all the packages, the `CHANGELOG.md` files will be +/// generated from a json file which is the source of the data +/// +/// the script can be used with the following args [_usage] +/// it will require a version and the changes for that version (as a [String]) +/// if the version exist then it will modify it with the new changes +/// if not, then will be added at the start /// -/// the new version should be passed in the [args], the script accept only one argument +/// the source file (which used to generate the `CHANGELOG.md` files) will +/// also updated with the new change +/// +/// this script designed to run in CI to automate the process of updating +/// the package Future main(List args) async { - if (args.isEmpty) { - print('Missing required version argument. Usage: ./script '); + if (args.isEmpty || args.length < 2) { + print('Missing required arguments. $_usage'); exit(1); } - if (args.length > 1) { - print('Too many arguments. Usage: ./script '); + if (args.length > 2) { + print('Too many arguments. $_usage'); exit(1); } - final newVersion = args[0]; - if (newVersion.isEmpty) { - print('The new version is empty. Usage: ./script '); + final passedVersion = args[0]; + if (passedVersion.isEmpty) { + print('The version is empty. $_usage'); exit(1); } + final passedVersionContent = args[1]; + if (passedVersionContent.isEmpty) { + print('The version content is empty. $_usage'); + exit(1); + } + + // A file that will be used to build the `CHANGELOG.md` files + // the data format is in Json + final sourceChangeLogFile = File('./CHANGELOG.json'); + await _replaceVersion( + sourceChangeLogFile: sourceChangeLogFile, + version: passedVersion, + versionContent: passedVersionContent, + ); + final sourceChangeLog = jsonDecode(await sourceChangeLogFile.readAsString()) + as Map; + final generatedChangeLogBuffer = StringBuffer() + ..write( + '\n\n', + ) + ..write('# Changelog\n\n') + ..write( + 'All notable changes to this project will be documented in this file.\n\n', + ); + sourceChangeLog.forEach((version, versionContent) { + generatedChangeLogBuffer + ..write('## $version\n\n') + ..write('$versionContent\n\n'); + }); + for (final packagePath in _packages) { - await updatePubspecYamlFile('$packagePath/pubspec.yaml', - newVersion: newVersion); - if (packagePath != _packages.first) { - updateChangelogMD('$packagePath/CHANGELOG.md'); - } + await _updatePubspecYamlFile( + pubspecYamlPath: '$packagePath/pubspec.yaml', + newVersion: passedVersion, + ); + _updateChangelog( + changeLogFilePath: '$packagePath/CHANGELOG.md', + changeLogContent: generatedChangeLogBuffer.toString(), + ); } } +/// Replace the version content by the version if it exist +/// or add the version at the start of the map if it doesn't exist +/// +/// then save the changes to the [sourceChangeLogFile] +Future _replaceVersion({ + required File sourceChangeLogFile, + required String version, + required String versionContent, +}) async { + final sourceChangeLog = jsonDecode(await sourceChangeLogFile.readAsString()) + as Map; + if (sourceChangeLog[version] != null) { + sourceChangeLog[version] = versionContent; + } else { + // A workaround to add the new item at the start, the order matter + // becase later it will generate the markdown files + final newMap = {version: versionContent}; + sourceChangeLog + ..forEach((key, value) => newMap[key] = value) + ..clear() + ..addAll(newMap); + } + await sourceChangeLogFile.writeAsString(jsonEncode(sourceChangeLog)); +} + /// Update the [pubspecYamlPath] file to update the `version` property from [newVersion] -Future updatePubspecYamlFile( - String pubspecYamlPath, { +Future _updatePubspecYamlFile({ + required String pubspecYamlPath, required String newVersion, }) async { final file = File(pubspecYamlPath); final yaml = await file.readAsString(); final yamlEditor = YamlEditor(yaml)..update(['version'], newVersion); await file.writeAsString(yamlEditor.toString()); - print(yamlEditor.toString()); } -/// Read the contents of the root `CHANGELOG.md` file and copy it -/// to the [changeLogFilePath] -Future updateChangelogMD(String changeLogFilePath) async { - final rootChangeLogFileContent = await File('./CHANGELOG.md').readAsString(); +/// Copy [changeLogContent] and overwrite it to the [changeLogFilePath] +Future _updateChangelog({ + required String changeLogFilePath, + required String changeLogContent, +}) async { final changeLogFile = File(changeLogFilePath); - await changeLogFile.writeAsString(rootChangeLogFileContent); + await changeLogFile.writeAsString(changeLogContent); }