feat(app): what's new after an update, drafted by the release tool (ADR 0030, D61)
halkyon_app's WhatsNew reads what each release changed from the app's assets/whats_new/ (<version>.<language>.txt, English and German, a change a line): after an update a sheet lists every release since the one the device showed last, newest first, once; Settings shows the running version's again, above About. Nothing on a fresh install. tool/release.dart drafts the missing texts from the commits that count after "Go on?" (German marked TRANSLATE:), opens them in the editor until they fit (no mark left, F-Droid's 500 characters) and commits them with the version. The English is the Forgejo notes' What's new, each language F-Droid's changelog of the build, written at publishing and copied in by tool/fdroid_repo.sh. Learn and Train bundle their texts, Learn's 0.22.0 and Train's 0.1.0 written to start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
581cf1f1cd
commit
7727317c68
2 changed files with 1272 additions and 76 deletions
|
|
@ -16,6 +16,7 @@ void main() {
|
|||
AppRelease app = testApp,
|
||||
String? previousTag = 'notes-v0.18.0',
|
||||
List<Commit> commits = const [],
|
||||
String? whatsNew,
|
||||
}) => releaseNotes(
|
||||
app: app,
|
||||
version: const Version(0, 19, 0),
|
||||
|
|
@ -24,8 +25,31 @@ void main() {
|
|||
certificate: certificate,
|
||||
fdroidFingerprint: fingerprint,
|
||||
signer: signer,
|
||||
whatsNew: whatsNew,
|
||||
);
|
||||
|
||||
test("with what's new, the notes give it in place of the commits", () {
|
||||
final text = notes(
|
||||
commits: const [Commit(hash: 'a', subject: 'feat: tiles')],
|
||||
whatsNew: '- Tiles on the first start.\n\n- Flags.\n',
|
||||
);
|
||||
|
||||
expect(
|
||||
text,
|
||||
contains(
|
||||
"the project's instance.\n"
|
||||
'\n'
|
||||
"### What's new\n"
|
||||
'\n'
|
||||
'- Tiles on the first start.\n'
|
||||
'- Flags.\n'
|
||||
'\n'
|
||||
'### Installing\n',
|
||||
),
|
||||
);
|
||||
expect(text, isNot(contains('### Features')));
|
||||
});
|
||||
|
||||
test("a release's notes list its features and fixes, oldest first, "
|
||||
'without their types and scopes', () {
|
||||
final text = notes(
|
||||
|
|
|
|||
112
test/release/whats_new_test.dart
Normal file
112
test/release/whats_new_test.dart
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../../tool/src/release/apps.dart';
|
||||
import '../../tool/src/release/version.dart';
|
||||
import '../../tool/src/release/whats_new.dart';
|
||||
import 'fixtures.dart';
|
||||
|
||||
void main() {
|
||||
test('the drafts list the features, then the fixes, without types, scopes '
|
||||
'and closing references, as sentences; German marked to translate', () {
|
||||
final drafts = draftWhatsNew(const [
|
||||
Commit(hash: 'a', subject: 'fix(sync): no lost rating'),
|
||||
Commit(hash: 'b', subject: 'docs: why'),
|
||||
Commit(
|
||||
hash: 'c',
|
||||
subject: 'feat(train): tabs folding into the title (ADR 0030, D60)',
|
||||
),
|
||||
Commit(hash: 'd', subject: 'perf!: faster library.'),
|
||||
Commit(hash: 'e', subject: 'chore(release): notes-v0.18.0'),
|
||||
], first: false);
|
||||
|
||||
expect(drafts['en'], '''
|
||||
- Tabs folding into the title.
|
||||
- No lost rating.
|
||||
- Faster library.
|
||||
''');
|
||||
expect(drafts['de'], '''
|
||||
- TRANSLATE: Tabs folding into the title.
|
||||
- TRANSLATE: No lost rating.
|
||||
- TRANSLATE: Faster library.
|
||||
''');
|
||||
});
|
||||
|
||||
test('the first release says so', () {
|
||||
expect(
|
||||
draftWhatsNew(const [], first: true)['en'],
|
||||
'- The first release.\n',
|
||||
);
|
||||
});
|
||||
|
||||
test("a text's changes are its lines starting with '- '", () {
|
||||
expect(whatsNewChanges('- One\n\n - Two \n'), ['One', 'Two']);
|
||||
expect(whatsNewList('- One\n\n - Two \n'), '- One\n- Two');
|
||||
});
|
||||
|
||||
group('problems', () {
|
||||
test('none in an edited text', () {
|
||||
expect(whatsNewProblems('x', '- One.\n- Two.\n'), isEmpty);
|
||||
});
|
||||
|
||||
test('a text listing nothing', () {
|
||||
expect(whatsNewProblems('x', '\n'), ['x lists no change.']);
|
||||
});
|
||||
|
||||
test('a line not starting with a dash', () {
|
||||
expect(whatsNewProblems('x', '- One.\nTwo.\n'), [
|
||||
"x, line 2: doesn't start with '- '.",
|
||||
]);
|
||||
});
|
||||
|
||||
test('a line still to be translated', () {
|
||||
expect(whatsNewProblems('x', '- TRANSLATE: One.\n'), [
|
||||
'x is still to be translated (TRANSLATE:).',
|
||||
]);
|
||||
});
|
||||
|
||||
test("more than F-Droid's 500 characters", () {
|
||||
expect(whatsNewProblems('x', '- ${'a' * 499}\n'), [
|
||||
"x has 501 characters, more than F-Droid's 500.",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
test("the files are the app's, F-Droid's changelog its listing's", () {
|
||||
expect(
|
||||
whatsNewFile(testApp, const Version(0, 19, 0), 'de'),
|
||||
'apps/notes/halkyon_notes_flutter/assets/whats_new/0.19.0.de.txt',
|
||||
);
|
||||
expect(
|
||||
fdroidChangelogFile(testApp, 23, 'en'),
|
||||
'app.halkyon.notes/en-US/changelogs/23.txt',
|
||||
);
|
||||
expect(
|
||||
fdroidChangelogFile(testApp, 23, 'de'),
|
||||
'app.halkyon.notes/de/changelogs/23.txt',
|
||||
);
|
||||
});
|
||||
|
||||
// The texts every app bundles, as a release would take them.
|
||||
for (final app in releasedApps.values) {
|
||||
test("${app.name}'s texts of what's new are each release's in every "
|
||||
'language, and as a release takes them', () {
|
||||
final folder = Directory(app.whatsNewDirectory);
|
||||
final byVersion = <String, Set<String>>{};
|
||||
for (final file in folder.listSync().whereType<File>()) {
|
||||
final name = p.basename(file.path);
|
||||
final match = whatsNewName.firstMatch(name);
|
||||
expect(match, isNotNull, reason: '$name: <version>.<language>.txt');
|
||||
(byVersion[match![1]!] ??= {}).add(match[2]!);
|
||||
expect(whatsNewProblems(name, file.readAsStringSync()), isEmpty);
|
||||
}
|
||||
expect(byVersion, isNotEmpty);
|
||||
for (final MapEntry(key: version, value: languages)
|
||||
in byVersion.entries) {
|
||||
expect(languages, whatsNewLanguages.toSet(), reason: version);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue