chore(lint): LeanCode's strict rules and a pre-push check
The workspace root's analysis_options.yaml includes leancode_lint 27 and enables its analyzer plugin (rules for blocs, Equatable and Flutter layout); the server and the app include that file, while the generated client keeps its own options. Plugins can only be enabled at the root of a pub workspace and only reach packages whose options include the root file, which was verified before settling on this layout. Most rules are warnings, casts, inference and raw types are strict, and the check treats infos as fatal too. lints and flutter_lints are no longer needed.
tool/check.sh checks formatting, runs dart analyze --fatal-infos and the server tests; .git/hooks/pre-push links to it, so every push has to pass it. AGENTS.md describes the checklist and how to install the hook in a fresh clone.
Fixes for the new rules: package imports, run() returns Future<void>, the server setup as one cascade, a primary constructor for the app widget, a const and a redundant argument. The workspace root keeps its conventional name `_` with a documented ignore.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-29 23:06:29 +02:00
|
|
|
#!/usr/bin/env bash
|
2026-09-30 08:38:37 +02:00
|
|
|
# The checks every push has to pass: formatting, static analysis (infos are fatal too), and
|
|
|
|
|
# the server's and the app's tests. The pre-push hook runs this script, and a CI runner can
|
|
|
|
|
# run it later.
|
chore(lint): LeanCode's strict rules and a pre-push check
The workspace root's analysis_options.yaml includes leancode_lint 27 and enables its analyzer plugin (rules for blocs, Equatable and Flutter layout); the server and the app include that file, while the generated client keeps its own options. Plugins can only be enabled at the root of a pub workspace and only reach packages whose options include the root file, which was verified before settling on this layout. Most rules are warnings, casts, inference and raw types are strict, and the check treats infos as fatal too. lints and flutter_lints are no longer needed.
tool/check.sh checks formatting, runs dart analyze --fatal-infos and the server tests; .git/hooks/pre-push links to it, so every push has to pass it. AGENTS.md describes the checklist and how to install the hook in a fresh clone.
Fixes for the new rules: package imports, run() returns Future<void>, the server setup as one cascade, a primary constructor for the app widget, a const and a redundant argument. The workspace root keeps its conventional name `_` with a documented ignore.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-29 23:06:29 +02:00
|
|
|
#
|
|
|
|
|
# Install the hook in a fresh clone: ln -s ../../tool/check.sh .git/hooks/pre-push
|
|
|
|
|
# Skip it for one push: git push --no-verify
|
|
|
|
|
#
|
|
|
|
|
# It checks the working tree, so uncommitted changes count as well.
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
cd "$(git rev-parse --show-toplevel)"
|
|
|
|
|
|
|
|
|
|
if ! git diff --quiet HEAD; then
|
|
|
|
|
echo 'Note: the working tree has uncommitted changes; they are checked too.'
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Our own Dart files. Generated code is left out: the client package as a whole, and the
|
|
|
|
|
# server's generated sources and test tools. (A loop instead of mapfile: macOS ships bash 3.)
|
|
|
|
|
own=()
|
|
|
|
|
while IFS= read -r file; do own+=("$file"); done < <(
|
|
|
|
|
git ls-files '*.dart' |
|
|
|
|
|
grep -v -E '^halkyon_learn_client/|/lib/src/generated/|/serverpod_test_tools\.dart$'
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
echo '▸ Formatting'
|
|
|
|
|
if [ ${#own[@]} -gt 0 ]; then
|
|
|
|
|
dart format --output=none --set-exit-if-changed "${own[@]}"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
echo '▸ Analysis'
|
|
|
|
|
dart analyze --fatal-infos
|
|
|
|
|
|
|
|
|
|
echo '▸ Server tests'
|
|
|
|
|
if git ls-files 'halkyon_learn_server/test/*_test.dart' | grep -q .; then
|
|
|
|
|
(cd halkyon_learn_server && dart test)
|
|
|
|
|
else
|
|
|
|
|
echo 'No server tests yet.'
|
|
|
|
|
fi
|
|
|
|
|
|
2026-09-30 08:38:37 +02:00
|
|
|
echo '▸ App tests'
|
test(app): studysets synced against a running server
The first tests that need serverpod start running (ADR 0001, rule 9: the client's and the server's sync engines can't share one process), tagged requires-server: tool/check.sh skips them, flutter test -t requires-server runs them. Every device is its own client and local database with the app's real gateway and repository, and syncs only when a test says so.
They state: two devices of one person end up with the same studysets; a deleted studyset leaves the other devices, and its payload is blank on the server, checked with SQL against the development database because the engine keeps deleted rows; a studyset written into another person's space never reaches them; claiming another person's space shows none of their studysets, since the server sends only the spaces the signed-in person has access to. As written here, the forgery test also expects the server to refuse and log the write, and the SQL checks connect over TCP; the first run against the server corrected both (see the commit "the sync tests pass against the running server").
They live in the app package: the server's Docker build resolves its dependencies with only the server package present, so a dev dependency on the client package would break it. They never initialize a Flutter test binding, which would replace real HTTP with a mock. Without a server they fail at sign-in with "connection refused".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-30 12:15:30 +02:00
|
|
|
# The sync tests need `serverpod start` running; run them by hand with
|
|
|
|
|
# `flutter test -t requires-server` in the app package.
|
|
|
|
|
(cd halkyon_learn_flutter && flutter test -x requires-server)
|
2026-09-30 08:38:37 +02:00
|
|
|
|
chore(lint): LeanCode's strict rules and a pre-push check
The workspace root's analysis_options.yaml includes leancode_lint 27 and enables its analyzer plugin (rules for blocs, Equatable and Flutter layout); the server and the app include that file, while the generated client keeps its own options. Plugins can only be enabled at the root of a pub workspace and only reach packages whose options include the root file, which was verified before settling on this layout. Most rules are warnings, casts, inference and raw types are strict, and the check treats infos as fatal too. lints and flutter_lints are no longer needed.
tool/check.sh checks formatting, runs dart analyze --fatal-infos and the server tests; .git/hooks/pre-push links to it, so every push has to pass it. AGENTS.md describes the checklist and how to install the hook in a fresh clone.
Fixes for the new rules: package imports, run() returns Future<void>, the server setup as one cascade, a primary constructor for the app widget, a const and a redundant argument. The workspace root keeps its conventional name `_` with a documented ignore.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
2026-09-29 23:06:29 +02:00
|
|
|
echo '✓ All checks passed.'
|