diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index da357db..794ddf2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,7 +32,7 @@ repos: - id: dart-check name: dart format (autofix) + check-fast (parallel) language: system - entry: bash -c 'cd "$(git rev-parse --show-toplevel)" && nix develop --command scripts/pre_commit_check.sh' + entry: bash -c 'cd "$(git rev-parse --show-toplevel)" && nix develop --command dagger call --progress=plain -q -m ci --source=. check-fast' pass_filenames: false always_run: true - id: ci-no-direct-dagger diff --git a/Taskfile.yml b/Taskfile.yml index 5a901e8..e4d7fe6 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -96,34 +96,19 @@ tasks: - scripts/silent_on_success.sh fvm flutter pub run build_runner build --delete-conflicting-outputs codegen: - desc: Generate Drift DB code (run after any schema change) - deps: [_preflight, _pub-get] - sources: - - lib/**/*.dart - - pubspec.yaml - generates: - - lib/**/*.g.dart + desc: Generate Drift DB code via Dagger (exports generated files back to host) cmds: - - fvm flutter pub run build_runner build --delete-conflicting-outputs + - dagger call --progress=plain -q -m ci --source=. codegen -o . analyze: - desc: Static analysis (flutter analyze) - deps: [_preflight, _codegen] - sources: - - lib/**/*.dart - - test/**/*.dart - - pubspec.yaml - - analysis_options.yaml + desc: Static analysis via Dagger (dart analyze --fatal-infos) cmds: - - scripts/run_analyze.sh + - dagger call --progress=plain -q -m ci --source=. analyze format: - desc: Format all Dart source files - deps: [_preflight] - sources: - - "**/*.dart" + desc: Format all Dart source files via Dagger (writes back to host) cmds: - - fvm dart format lib test + - dagger call --progress=plain -q -m ci --source=. format-write -o . check-mocks: desc: Fail if any *.mocks.dart file is out of date (re-runs build_runner) @@ -136,13 +121,9 @@ tasks: - scripts/check_mocks_fresh.sh analyze-fix: - desc: Auto-fix lint issues with dart fix --apply - deps: [_preflight] - sources: - - lib/**/*.dart - - test/**/*.dart + desc: Auto-fix lint issues via Dagger (dart fix --apply, writes back to host) cmds: - - fvm dart fix --apply + - dagger call --progress=plain -q -m ci --source=. analyze-fix -o . test: desc: Unit tests + coverage gate (fails if any non-excluded lib/ file is missing) @@ -690,8 +671,9 @@ tasks: ${SSH_USER}@${SSH_HOST}:public_html/ check-fast: - desc: Pre-commit checks — analyze + unit+widget tests + coverage gate (no build, no integration) - deps: [analyze, check-coverage, check-hygiene, check-layers, check-mocks] + desc: Pre-commit checks via Dagger (format, analyze, mocks, coverage — no integration or backend) + cmds: + - dagger call --progress=plain -q -m ci --source=. check-fast check-layers: desc: Enforce architecture — ui/ must not import data/ (only core/ interfaces allowed) diff --git a/ci/main.go b/ci/main.go index 920cc44..b508d80 100644 --- a/ci/main.go +++ b/ci/main.go @@ -440,6 +440,68 @@ func (m *Ci) Format(ctx context.Context) (string, error) { Stdout(ctx) } +// FormatWrite formats Dart files and exports the modified /src directory. +func (m *Ci) FormatWrite() *dagger.Directory { + return m.setup(m.checkSrc()). + WithExec([]string{"dart", "format", "lib", "test"}). + Directory("/src") +} + +// Analyze runs static analysis with dart analyze --fatal-infos. +func (m *Ci) Analyze(ctx context.Context) (string, error) { + return m.setup(m.checkSrc()). + WithExec([]string{"dart", "analyze", "--fatal-infos"}). + Stdout(ctx) +} + +// Codegen runs build_runner and exports the modified /src directory. +func (m *Ci) Codegen() *dagger.Directory { + return m.codegenBase().Directory("/src") +} + +// AnalyzeFix runs dart fix --apply and exports the modified /src directory. +func (m *Ci) AnalyzeFix() *dagger.Directory { + return m.setup(m.checkSrc()). + WithExec([]string{"dart", "fix", "--apply"}). + Directory("/src") +} + +// CheckFast runs fast checks (hygiene, layers, format, analyze, mocks, coverage) in parallel. +func (m *Ci) CheckFast(ctx context.Context) (string, error) { + ctx, cancel := context.WithTimeout(ctx, 15*time.Minute) + defer cancel() + + var eg errgroup.Group + eg.Go(func() error { + _, err := m.CheckHygiene(ctx) + return err + }) + eg.Go(func() error { + _, err := m.CheckLayers(ctx) + return err + }) + eg.Go(func() error { + _, err := m.Format(ctx) + return err + }) + eg.Go(func() error { + _, err := m.Analyze(ctx) + return err + }) + eg.Go(func() error { + _, err := m.CheckGenerated(ctx) + return err + }) + eg.Go(func() error { + _, err := m.Coverage(ctx) + return err + }) + if err := eg.Wait(); err != nil { + return "", err + } + return "All fast checks passed!", nil +} + // CheckGenerated verifies that all generated files (*.g.dart, *.mocks.dart) are up to date. // It snapshots the committed source (including any stale generated files) before // running build_runner, so git diff detects real staleness instead of always