chore(#335): pin drift, commit pubspec.lock, guard the web asset version
Owner asked whether the web assets must be re-downloaded on every drift bump. They do not - the version can be pinned - but doing that safely needed three changes, because the failure mode is silent. 1. drift and drift_flutter are pinned EXACTLY (2.34.2 / 0.3.1), no caret. The committed web assets are built for a specific drift release, so a caret would let pub resolve a newer drift than the shipped binaries and break the web build with no signal at compile time. 2. pubspec.lock is now committed (removed from .gitignore). It was ignored, which for an application means resolution can differ between machines and CI. That undermines the pin: the assets are matched against the RESOLVED version, so resolution has to be reproducible. Owner-authorized, and it is a repo-wide change rather than a storage-only one. 3. New test asserting the shipped assets match the resolved drift version, plus that both files exist and the wasm really starts with the WebAssembly magic bytes. Verified in both directions: it passes when matched and fails loudly with re-download instructions when skewed. Without (3) a stale asset compiles, deploys, and only fails in the user's browser - the exact silent-failure class SAFELANE 6 forbids and that produced #333 earlier. Upgrading drift is now a deliberate step: bump the pin, re-download both assets, update web/drift_assets.version. The test fails until you do. flutter analyze clean, tests pass.integration/290-306-335
parent
847a28df3e
commit
c25b7ccbdf
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,74 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
/// Guards the one way the web build can break silently (#335).
|
||||||
|
///
|
||||||
|
/// drift on the web needs two binaries shipped in `web/`, and they must match
|
||||||
|
/// the resolved `drift` package. If someone bumps drift without re-downloading
|
||||||
|
/// them, nothing fails at build time: the app compiles, deploys, and then
|
||||||
|
/// fails in the browser. SAFELANE 6 says that must not be silent, so this
|
||||||
|
/// turns it into a red test with instructions.
|
||||||
|
///
|
||||||
|
/// Update `web/drift_assets.version` whenever the assets are re-downloaded.
|
||||||
|
void main() {
|
||||||
|
test('shipped drift web assets match the pinned drift version', () {
|
||||||
|
final root = Directory.current.path;
|
||||||
|
|
||||||
|
final lock = File('$root/pubspec.lock');
|
||||||
|
expect(
|
||||||
|
lock.existsSync(),
|
||||||
|
isTrue,
|
||||||
|
reason:
|
||||||
|
'pubspec.lock must be committed so dependency resolution is '
|
||||||
|
'reproducible; the drift web assets are matched against it.',
|
||||||
|
);
|
||||||
|
|
||||||
|
final resolved = RegExp(
|
||||||
|
r'^ drift:\n(?:.*\n)*? version: "([^"]+)"',
|
||||||
|
multiLine: true,
|
||||||
|
).firstMatch(lock.readAsStringSync())?.group(1);
|
||||||
|
expect(resolved, isNotNull, reason: 'drift not found in pubspec.lock');
|
||||||
|
|
||||||
|
final stamp = File('$root/web/drift_assets.version');
|
||||||
|
expect(
|
||||||
|
stamp.existsSync(),
|
||||||
|
isTrue,
|
||||||
|
reason:
|
||||||
|
'web/drift_assets.version is missing. It records which drift release '
|
||||||
|
'web/sqlite3.wasm and web/drift_worker.js came from.',
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
stamp.readAsStringSync().trim(),
|
||||||
|
resolved,
|
||||||
|
reason:
|
||||||
|
'\nDrift web assets are STALE.\n'
|
||||||
|
'pubspec.lock resolves drift $resolved, but the shipped assets are '
|
||||||
|
'from ${stamp.readAsStringSync().trim()}.\n'
|
||||||
|
'The web build would compile and then fail in the browser.\n\n'
|
||||||
|
'Fix:\n'
|
||||||
|
' gh release download drift-$resolved --repo simolus3/drift \\\n'
|
||||||
|
' --pattern drift_worker.js --pattern sqlite3.wasm --clobber\n'
|
||||||
|
' (run inside web/, then write $resolved into web/drift_assets.version)\n',
|
||||||
|
);
|
||||||
|
|
||||||
|
for (final name in ['sqlite3.wasm', 'drift_worker.js']) {
|
||||||
|
expect(
|
||||||
|
File('$root/web/$name').existsSync(),
|
||||||
|
isTrue,
|
||||||
|
reason: 'web/$name is missing; the web build would fail at runtime.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cheap integrity check: the wasm must actually be WebAssembly.
|
||||||
|
final magic = File('$root/web/sqlite3.wasm').openSync().readSync(4);
|
||||||
|
expect(
|
||||||
|
magic,
|
||||||
|
orderedEquals([0x00, 0x61, 0x73, 0x6d]),
|
||||||
|
reason:
|
||||||
|
'web/sqlite3.wasm does not start with the WebAssembly magic '
|
||||||
|
'bytes (\\0asm) — the download is corrupt or is not a wasm file.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
2.34.2
|
||||||
Loading…
Reference in new issue