How to Incorporate Automated Version Information into A Dart Command Line App
To update version information in your code without having to package a resource file to be parsed during run time, you can have the information hard coded into an automatically generated dart source file which gets compiled into your binary. The following example hard codes the version, name, and description information into the Map object "meta" in a meta.dart
file. The meta.dart
file is recreated and overwritten every time the test suite is run in development. To verify the source code has the correct version information, the app's code verifies the version and other meta information against the attributes in the pubspec.yaml file (but only when run as interpreted code in development). If there is a difference from pubspec.yaml, it throws an exception. Once compiled into a binary, it will skip that check as it won't find the pubspec.yaml file, so no error is thrown from the binary. Even if a pubspec.yaml file happens to be around and is found, it only throws an exception and does not create a "meta.dart" source file.
1. Create a MetaUpdate class and save it as "meta_update.dart":
import 'dart:io';
import 'package:yaml/yaml.dart';
import 'meta.dart';
class MetaUpdate {
String pathToYaml = "";
String metaDartFileContents = "";
MetaUpdate(this.pathToYaml);
void writeMetaDartFile(String metaDartFilePath) {
File metaDartFile = File(metaDartFilePath);
String metaDartFileContents = """
/// DO NOT EDIT THIS FILE EXCEPT TO ENTER INITIAL VERSION AND OTHER META INFO
/// THIS FILE IS AUTOMATICALLY OVER WRITTEN BY MetaUpdate
Map<String, String> meta = <String, String>{
"name": "${getPubSpec('name')}",
"description":
// ignore: lines_longer_than_80_chars
"${getPubSpec('description')}",
"version":"${getPubSpec('version')}",
};
""";
metaDartFile.writeAsStringSync(metaDartFileContents);
}
String getPubSpec(String pubSpecParam) {
File f = File(pathToYaml);
String yamlText = f.readAsStringSync();
// ignore: always_specify_types
Map yaml = loadYaml(yamlText);
return yaml[pubSpecParam];
}
void verifyLatestVersionFromPubSpec() {
try {
File f = File(pathToYaml);
//exit if no pubspec found so no warning in production
if (!f.existsSync()) return;
//compare meta.dart with pubspec meta and give warning if difference
if (meta.keys
.where((dynamic e) => (meta[e] != getPubSpec(e)))
.isNotEmpty) {
throw Exception(
"""Version number and other meta attributes in code are different from pubspec.yaml. Please check pubspec.yaml and then run test so that MetaUpdate can update meta information in code, then recompile""");
}
} on Exception {
rethrow;
}
}
}
2. Create a "meta.dart" file:
/// DO NOT EDIT THIS FILE EXCEPT TO ENTER INITIAL VERSION AND OTHER META INFO
/// THIS FILE IS AUTOMATICALLY OVER WRITTEN BY MetaUpdate
Map<String, String> meta = <String, String>{
"name": "Acme Transmogrifier",
"description":
"The best dart application ever.",
"version":"2021.09.001",
};
When you initially create the meta.dart
file, copy your specific info from pubspec.yaml. This will later be overwritten each time your MetaUpdate.writeMetaDartFile() is run, changing the contents whenever the info in pubspec.yaml is changed.
3. Implement The Version Update In Your Test Code
Add the following in the first line of Main() in your test code (not the source of the main program, we don't want it to be compiled into the binary), changing the path to meta.dart as appropriate:
MetaUpdate("pubspec.yaml").writeMetaDartFile("lib/src/meta.dart");
4. Add A Meta Check To Your Main Code
Put this in your app's code so it is one of the first methods executed when your app is run - it will generate an exception if there is a difference between the attributes shown in the meta.dart and pubspec.yaml:
MetaUpdate("pubspec.yaml").verifyLatestVersionFromPubSpec();
5. Using
- Make sure the Name, Version, and Description information in pubspec.yaml contains the latest information you want reflected in your code.
- Import "meta.dart" and insert meta['name'], meta['version'], etc. where you need them to be shown (e.g., in --help or --version messages to be printed to the console).
- As long as you run your tests before compiling your code the meta information will be accurately reflected in your code.