From 76ff24b34cb2a7eb50c18ac0f28eb868859d6818 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 02:39:56 +0200 Subject: [PATCH] feat: upgrade to .NET 9 / C# 13, latest packages & actions, add Copilot instructions (#2) --- .github/copilot-instructions.md | 94 ++++ .github/workflows/README.md | 34 +- .github/workflows/build.yml | 42 +- .github/workflows/publish.yml | 44 +- .github/workflows/test.yml | 22 +- .gitignore | 1 + CLAUDE.md | 22 +- README.md | 26 +- src/HihaArvio/App.xaml.cs | 5 +- src/HihaArvio/HihaArvio.csproj | 26 +- tests/HihaArvio.Tests/HihaArvio.Tests.csproj | 14 +- .../coverage.cobertura.xml | 490 ------------------ 12 files changed, 224 insertions(+), 596 deletions(-) create mode 100644 .github/copilot-instructions.md delete mode 100644 tests/HihaArvio.Tests/TestResults/a7530e2d-8631-4bd5-9898-59b8cf8b73ed/coverage.cobertura.xml diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..dc79c05 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,94 @@ +# GitHub Copilot Instructions for HihaArvio + +## Authoritative Reference + +**CLAUDE.md is the single source of truth for this repository.** + +All guidelines, architecture decisions, implementation requirements, and coding standards defined in [`CLAUDE.md`](../CLAUDE.md) at the repository root MUST be followed without exception. CLAUDE.md takes absolute precedence over any other instruction, convention, or assumption. + +Before suggesting, generating, or reviewing any code for this repository, read and internalize CLAUDE.md in its entirety. + +## Non-Negotiable Rules + +The following rules are derived from CLAUDE.md and additional Copilot-specific code quality guidelines. All MUST be enforced in every interaction: + +### Language & Framework + +- **Target framework:** .NET 9, using C# 13 +- **UI framework:** .NET MAUI (multi-platform) +- **Nullable reference types MUST be enabled** across all projects +- **All compiler warnings MUST be treated as errors** (`true`) +- Language version MUST be set to `13` in all project files + +### Architecture (MVVM – Strict Separation) + +- **Models**: Plain data objects only — no business logic +- **ViewModels**: All presentation logic — 100% testable without UI dependencies +- **Views**: Thin layer — data binding only, minimal code-behind +- **Services**: All business logic and infrastructure concerns + +### Dependency Injection + +- All services MUST be injected via constructor — never use the service locator pattern or `new` inside ViewModels +- Register all services in `MauiProgram.cs` +- Platform-specific implementations use `#if IOS`, `#elif WINDOWS || MACCATALYST` + +### Testing Requirements + +- Test coverage MUST be ≥ 95 % (measured by Coverlet; threshold enforcement is a future CI/CD enhancement) +- Testing stack: **xUnit + NSubstitute + FluentAssertions** +- All tests MUST use deterministic, seeded randomness — never `Random.Shared` +- All external dependencies (sensors, database, file system) MUST be mocked +- Use test-data builders for complex objects + +### Security + +- Estimate selection MUST use `System.Security.Cryptography.RandomNumberGenerator` — never `System.Random` +- No external data transmission — all data is stored locally only +- Request the minimum required platform permissions + +### Commit & Code Quality + +- Use **semantic / conventional commit** messages (e.g. `feat:`, `fix:`, `chore:`, `docs:`, `test:`, `refactor:`) +- Make **atomic commits** — one logical change per commit +- Run all linting and build tools; automatically fix all reported issues before committing +- Follow the `.editorconfig` rules present in the repository root + +## Technology Stack (Current Versions) + +| Component | Version | +|---|---| +| .NET SDK | 9.0.x | +| C# Language | 13 | +| Microsoft.Maui.Controls | 9.0.120 | +| Microsoft.Maui.Controls.Compatibility | 9.0.120 | +| CommunityToolkit.Mvvm | 8.4.0 | +| SQLite (sqlite-net-pcl) | 1.9.172 | +| SQLitePCLRaw.bundle_green | 2.1.11 | +| Microsoft.Extensions.Logging.Debug | 9.0.13 | +| xUnit | 2.9.3 | +| xunit.runner.visualstudio | 2.8.2 | +| Microsoft.NET.Test.Sdk | 18.3.0 | +| NSubstitute | 5.3.0 | +| FluentAssertions | 8.8.0 | +| coverlet.collector | 8.0.0 | + +## Key Files + +| File | Purpose | +|---|---| +| `CLAUDE.md` | **Authoritative project guide** — always read first | +| `spec.md` | Formal RFC 2119 requirements (MUST / SHALL / REQUIRED) | +| `docs/plans/2025-11-18-hiha-arvio-design.md` | Validated architecture decisions | +| `src/HihaArvio/HihaArvio.csproj` | Main MAUI project | +| `tests/HihaArvio.Tests/HihaArvio.Tests.csproj` | Unit & integration tests | +| `.editorconfig` | Code style enforcement | + +## Easter Egg — Never Expose + +The hidden humorous mode triggered by shaking for > 15 seconds MUST NOT have any visible UI indication and MUST NOT be mentioned in any UI element, setting, or documentation visible to users. + +## When in Doubt + +If there is any ambiguity, consult **CLAUDE.md** and **spec.md** — in that order. +Do not invent architecture, add dependencies, or change platform targets without explicit justification grounded in those documents. diff --git a/.github/workflows/README.md b/.github/workflows/README.md index a154b06..1cee722 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -12,9 +12,9 @@ This directory contains the CI/CD workflows for HihaArvio. **What it does**: - Runs on Ubuntu (fastest, cheapest for tests) -- Sets up .NET 8.0 -- Builds the solution for `net8.0` target -- Runs all 189 xUnit tests +- Sets up .NET 9.0 +- Restores and builds `tests/HihaArvio.Tests/HihaArvio.Tests.csproj` for the `net9.0` target +- Runs all xUnit tests in `tests/HihaArvio.Tests/HihaArvio.Tests.csproj` - Publishes test results and coverage reports - Uploads test artifacts for review @@ -32,8 +32,8 @@ This directory contains the CI/CD workflows for HihaArvio. **Purpose**: Build the application for all supported platforms. **What it does**: -- **iOS Job**: Builds for iOS 15.0+ on macOS-14 runner -- **macOS Catalyst Job**: Builds for macOS 12.0+ on macOS-14 runner +- **iOS Job**: Builds for iOS 15.0+ on macOS-26 runner +- **macOS Catalyst Job**: Builds for macOS 12.0+ on macOS-26 runner - Installs .NET MAUI workload - Builds without code signing (for CI verification) - Uploads build artifacts (`.app` bundles) @@ -98,16 +98,16 @@ Tags containing `alpha`, `beta`, or `rc` are marked as pre-releases. ### Running Tests Locally ```bash -dotnet test HihaArvio.sln -f net8.0 +dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 ``` ### Building Locally ```bash # iOS -dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-ios -c Release +dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-ios -c Release # macOS Catalyst -dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-maccatalyst -c Release +dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-maccatalyst -c Release ``` ### Creating a Release @@ -146,16 +146,16 @@ For signed releases, add: ### Runner Requirements - **Test**: `ubuntu-latest` (any Linux runner) -- **Build**: `macos-14` (Apple Silicon runner for MAUI workloads) -- **Publish**: `macos-14` (Apple Silicon runner for MAUI workloads) +- **Build**: `macos-26` (Apple Silicon runner with Xcode 26 for MAUI workloads) +- **Publish**: `macos-26` (Apple Silicon runner with Xcode 26 for MAUI workloads) ### External Actions Used -- `actions/checkout@v4` - Checkout repository -- `actions/setup-dotnet@v4` - Setup .NET SDK -- `actions/upload-artifact@v4` - Upload build artifacts -- `actions/create-release@v1` - Create GitHub releases -- `actions/upload-release-asset@v1` - Upload release assets -- `dorny/test-reporter@v1` - Generate test reports +- `actions/checkout@v6.0.2` - Checkout repository +- `actions/setup-dotnet@v5.2.0` - Setup .NET SDK +- `actions/upload-artifact@v7.0.0` - Upload build artifacts +- `softprops/action-gh-release@v2.5.0` - Create GitHub releases +- `actions/download-artifact@v8.0.0` - Download build artifacts for release +- `dorny/test-reporter@v2.6.0` - Generate test reports --- @@ -164,7 +164,7 @@ For signed releases, add: ### Tests Failing Check test output in workflow logs. Run locally with: ```bash -dotnet test HihaArvio.sln -f net8.0 --verbosity detailed +dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 --verbosity detailed ``` ### Build Failing diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 44615eb..f3bb0d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,64 +10,74 @@ on: jobs: build-ios: name: Build iOS - runs-on: macos-latest + runs-on: macos-26 permissions: contents: read actions: write steps: - name: Checkout code - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup .NET - uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: - dotnet-version: '8.0.x' + dotnet-version: '9.0.x' + + - name: Select Xcode version + uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 + with: + xcode-version: '26.0' - name: Restore workloads run: dotnet workload restore src/HihaArvio/HihaArvio.csproj - name: Build iOS - run: dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-ios -c Release /p:ArchiveOnBuild=false /p:EnableCodeSigning=false + run: dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-ios -c Release /p:ArchiveOnBuild=false /p:EnableCodeSigning=false - name: Upload iOS build artifacts - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: ios-build path: | - src/HihaArvio/bin/Release/net8.0-ios/**/*.app - src/HihaArvio/bin/Release/net8.0-ios/**/*.ipa + src/HihaArvio/bin/Release/net9.0-ios/**/*.app + src/HihaArvio/bin/Release/net9.0-ios/**/*.ipa retention-days: 7 build-maccatalyst: name: Build macOS Catalyst - runs-on: macos-latest + runs-on: macos-26 permissions: contents: read actions: write steps: - name: Checkout code - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup .NET - uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: - dotnet-version: '8.0.x' + dotnet-version: '9.0.x' + + - name: Select Xcode version + uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 + with: + xcode-version: '26.0' - name: Restore workloads run: dotnet workload restore src/HihaArvio/HihaArvio.csproj - name: Build macOS Catalyst - run: dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-maccatalyst -c Release /p:ArchiveOnBuild=false /p:EnableCodeSigning=false + run: dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-maccatalyst -c Release /p:ArchiveOnBuild=false /p:EnableCodeSigning=false - name: Upload macOS build artifacts - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: maccatalyst-build path: | - src/HihaArvio/bin/Release/net8.0-maccatalyst/**/*.app - src/HihaArvio/bin/Release/net8.0-maccatalyst/**/*.pkg + src/HihaArvio/bin/Release/net9.0-maccatalyst/**/*.app + src/HihaArvio/bin/Release/net9.0-maccatalyst/**/*.pkg retention-days: 7 build-status: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 43e16f2..3b228ad 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -12,19 +12,19 @@ on: type: string env: - DOTNET_VERSION: '8.0.x' + DOTNET_VERSION: '9.0.x' jobs: build-ios: name: Build iOS - runs-on: macos-latest + runs-on: macos-26 permissions: contents: read actions: write steps: - name: Checkout code - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get version id: get_version @@ -36,17 +36,22 @@ jobs: fi - name: Setup .NET - uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Select Xcode version + uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 + with: + xcode-version: '26.0' + - name: Restore workloads run: dotnet workload restore src/HihaArvio/HihaArvio.csproj - name: Build iOS Release run: | dotnet publish src/HihaArvio/HihaArvio.csproj \ - -f net8.0-ios \ + -f net9.0-ios \ -c Release \ /p:ApplicationDisplayVersion=${{ steps.get_version.outputs.version }} \ /p:ApplicationVersion=${{ github.run_number }} \ @@ -55,7 +60,7 @@ jobs: - name: Create iOS artifact archive run: | - cd src/HihaArvio/bin/Release/net8.0-ios + cd src/HihaArvio/bin/Release/net9.0-ios # Find the .app bundle (it's in a subdirectory like iossimulator-arm64 or ios-arm64) APP_PATH=$(find . -name "*.app" -type d | head -n 1) if [ -z "$APP_PATH" ]; then @@ -66,7 +71,7 @@ jobs: mv HihaArvio-iOS-${{ steps.get_version.outputs.version }}.zip ${{ github.workspace }}/ - name: Upload iOS artifact - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: ios-release path: HihaArvio-iOS-${{ steps.get_version.outputs.version }}.zip @@ -74,14 +79,14 @@ jobs: build-maccatalyst: name: Build macOS - runs-on: macos-latest + runs-on: macos-26 permissions: contents: read actions: write steps: - name: Checkout code - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Get version id: get_version @@ -93,17 +98,22 @@ jobs: fi - name: Setup .NET - uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: dotnet-version: ${{ env.DOTNET_VERSION }} + - name: Select Xcode version + uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0 + with: + xcode-version: '26.0' + - name: Restore workloads run: dotnet workload restore src/HihaArvio/HihaArvio.csproj - name: Build macOS Catalyst Release run: | dotnet publish src/HihaArvio/HihaArvio.csproj \ - -f net8.0-maccatalyst \ + -f net9.0-maccatalyst \ -c Release \ /p:ApplicationDisplayVersion=${{ steps.get_version.outputs.version }} \ /p:ApplicationVersion=${{ github.run_number }} \ @@ -112,7 +122,7 @@ jobs: - name: Create macOS artifact archive run: | - cd src/HihaArvio/bin/Release/net8.0-maccatalyst + cd src/HihaArvio/bin/Release/net9.0-maccatalyst # Find the .app bundle (it's in a subdirectory like maccatalyst-x64 or maccatalyst-arm64) APP_PATH=$(find . -name "*.app" -type d | head -n 1) if [ -z "$APP_PATH" ]; then @@ -123,7 +133,7 @@ jobs: mv HihaArvio-macOS-${{ steps.get_version.outputs.version }}.zip ${{ github.workspace }}/ - name: Upload macOS artifact - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: maccatalyst-release path: HihaArvio-macOS-${{ steps.get_version.outputs.version }}.zip @@ -140,7 +150,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 @@ -172,17 +182,17 @@ jobs: fi - name: Download iOS artifact - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: ios-release - name: Download macOS artifact - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: maccatalyst-release - name: Create Release - uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2 + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: tag_name: ${{ github.event_name == 'workflow_dispatch' && format('v{0}', github.event.inputs.version) || github.ref_name }} name: Release ${{ steps.get_version.outputs.version }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 62aeb9f..3306048 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,21 +17,21 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Setup .NET - uses: actions/setup-dotnet@d4c94342e560b34958eacfc5d055d21461ed1c5d # v5.0.0 + uses: actions/setup-dotnet@c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0 with: - dotnet-version: '8.0.x' + dotnet-version: '9.0.x' - name: Restore dependencies - run: dotnet restore tests/HihaArvio.Tests/HihaArvio.Tests.csproj /p:TargetFrameworks=net8.0 + run: dotnet restore tests/HihaArvio.Tests/HihaArvio.Tests.csproj /p:TargetFrameworks=net9.0 - name: Build test project - run: dotnet build tests/HihaArvio.Tests/HihaArvio.Tests.csproj --configuration Release --no-restore /p:TargetFrameworks=net8.0 + run: dotnet build tests/HihaArvio.Tests/HihaArvio.Tests.csproj --configuration Release --no-restore /p:TargetFrameworks=net9.0 - name: Run tests with coverage - run: dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj --configuration Release --no-build --verbosity normal /p:TargetFrameworks=net8.0 --collect:"XPlat Code Coverage" --logger "trx;LogFileName=test-results.trx" + run: dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj --configuration Release --no-build --verbosity normal /p:TargetFrameworks=net9.0 --collect:"XPlat Code Coverage" --logger "trx;LogFileName=test-results.trx" - name: Install ReportGenerator run: dotnet tool install --global dotnet-reportgenerator-globaltool @@ -43,14 +43,14 @@ jobs: run: | # Extract and display line coverage percentage COVERAGE=$(grep -oP 'Line coverage: \K[\d.]+' coverage/Summary.txt | head -1) - echo "📊 Code coverage for net8.0 target: ${COVERAGE}%" + echo "📊 Code coverage for net9.0 target: ${COVERAGE}%" echo "" echo "Note: Multi-target MAUI projects cannot achieve full coverage on Linux runners." - echo "Platform-specific code (iOS/macOS) is excluded when building net8.0 only." + echo "Platform-specific code (iOS/macOS) is excluded when building net9.0 only." echo "Full coverage measurement requires macOS runners with all target frameworks." - name: Upload coverage report - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 if: always() with: name: coverage-report @@ -58,7 +58,7 @@ jobs: retention-days: 30 - name: Publish test results - uses: dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3 # v2.1.1 + uses: dorny/test-reporter@3d76b34a4535afbd0600d347b09a6ee5deb3ed7f # v2.6.0 if: always() with: name: Test Results @@ -67,7 +67,7 @@ jobs: fail-on-error: true - name: Upload test results - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 if: always() with: name: test-results diff --git a/.gitignore b/.gitignore index 8e03ab3..756f6b8 100644 --- a/.gitignore +++ b/.gitignore @@ -44,6 +44,7 @@ _ReSharper*/ *.trx *.coverage *.coveragexml +**/TestResults/ # NuGet Packages *.nupkg diff --git a/CLAUDE.md b/CLAUDE.md index e333be6..212e1e2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -Hiha-Arvio (Finnish: "Sleeve Estimate") is a .NET 8 MAUI cross-platform application that generates semi-random time estimates based on physical shake input (accelerometer on mobile, mouse movement on desktop). This is a humor app for "pulling an estimate from your sleeve." +Hiha-Arvio (Finnish: "Sleeve Estimate") is a .NET 9 MAUI cross-platform application that generates semi-random time estimates based on physical shake input (accelerometer on mobile, mouse movement on desktop). This is a humor app for "pulling an estimate from your sleeve." **Platforms (in priority order):** iOS (primary) → Web (Blazor) → macOS @@ -41,8 +41,8 @@ Hiha-Arvio (Finnish: "Sleeve Estimate") is a .NET 8 MAUI cross-platform applicat ## Technology Stack -- **Framework:** .NET 8 MAUI (LTS) -- **Language:** C# 12 with nullable reference types +- **Framework:** .NET 9 MAUI +- **Language:** C# 13 with nullable reference types - **Database:** SQLite via `sqlite-net-pcl` - **MVVM:** CommunityToolkit.Mvvm (source generators) - **Testing:** xUnit, NSubstitute, FluentAssertions, Coverlet @@ -139,9 +139,9 @@ HihaArvio.sln ### Build Commands - **Build all platforms:** `dotnet build HihaArvio.sln` -- **Build specific framework:** `dotnet build HihaArvio.sln -f net8.0` -- **Build iOS:** `dotnet build HihaArvio.sln -f net8.0-ios` -- **Build macOS:** `dotnet build HihaArvio.sln -f net8.0-maccatalyst` +- **Build specific framework:** `dotnet build HihaArvio.sln -f net9.0` +- **Build iOS:** `dotnet build HihaArvio.sln -f net9.0-ios` +- **Build macOS:** `dotnet build HihaArvio.sln -f net9.0-maccatalyst` ### Test Commands - **Run all tests:** `dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj` @@ -153,8 +153,8 @@ HihaArvio.sln - **Coverage files:** Located in `tests/HihaArvio.Tests/TestResults/{guid}/coverage.cobertura.xml` ### Run Commands -- **iOS Simulator:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net8.0-ios` -- **macOS:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net8.0-maccatalyst` +- **iOS Simulator:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net9.0-ios` +- **macOS:** `dotnet build src/HihaArvio/HihaArvio.csproj -t:Run -f net9.0-maccatalyst` ### Notes - All commands should be run from the repository root directory @@ -205,7 +205,7 @@ HihaArvio.sln - Solution structure with src/HihaArvio and tests/HihaArvio.Tests - Core models: EstimateMode, EstimateResult, ShakeData, AppSettings - 48 tests, all passing -- Build verification: all platforms (net8.0, iOS, macOS) +- Build verification: all platforms (net9.0, iOS, macOS) **Milestone 2: Services Layer (✅ Complete)** - IEstimateService + EstimateService (25 tests) @@ -280,7 +280,7 @@ HihaArvio.sln - TabBar with 3 tabs: Estimate, History, Settings - Each tab uses ContentTemplate for lazy loading - **Total: 165 tests still passing (no UI tests yet)** -- **Build:** 0 warnings, 0 errors across all platforms (net8.0, iOS, macOS Catalyst) +- **Build:** 0 warnings, 0 errors across all platforms (net9.0, iOS, macOS Catalyst) **Milestone 5: Platform-Specific Implementations (✅ Complete)** - IAccelerometerService interface @@ -314,7 +314,7 @@ HihaArvio.sln - Dispose pattern implemented for cleanup - Final verification - **189 tests passing** across all layers - - **0 warnings, 0 errors** on all platforms (net8.0, iOS, macOS Catalyst) + - **0 warnings, 0 errors** on all platforms (net9.0, iOS, macOS Catalyst) - Models (48 tests) + Services (71 tests) + ViewModels (46 tests) + Accelerometer (24 tests) - Build artifacts verified for all target frameworks diff --git a/README.md b/README.md index 45ce956..69d94ac 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ A playful Finnish take on agile estimation through shake gestures. Instead of po ## 🏗️ Architecture -Built with **.NET 8 MAUI** using modern C# 12 and strict MVVM architecture: +Built with **.NET 9 MAUI** using modern C# 13 and strict MVVM architecture: - **Models**: Core domain models (EstimateResult, ShakeData, AppSettings) - **Services**: Business logic layer @@ -37,7 +37,7 @@ Built with **.NET 8 MAUI** using modern C# 12 and strict MVVM architecture: ### Technology Stack -- **.NET 8.0** with C# 12 +- **.NET 9.0** with C# 13 - **MAUI** for cross-platform UI - **CommunityToolkit.Mvvm** for MVVM patterns - **SQLite** (sqlite-net-pcl) for local storage @@ -53,20 +53,20 @@ Comprehensive test suite covering all layers: ```bash # Run all tests -dotnet test HihaArvio.sln -f net8.0 +dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 # Run with detailed output -dotnet test HihaArvio.sln -f net8.0 --verbosity detailed +dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 --verbosity detailed # Generate coverage report -dotnet test HihaArvio.sln -f net8.0 --collect:"XPlat Code Coverage" +dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 --collect:"XPlat Code Coverage" ``` ## 🚀 Getting Started ### Prerequisites -- **.NET 8 SDK**: [Download here](https://dotnet.microsoft.com/download/dotnet/8.0) +- **.NET 9 SDK**: [Download here](https://dotnet.microsoft.com/download/dotnet/9.0) - **MAUI Workload**: Install via `dotnet workload install maui` - **Xcode 15+**: Required for iOS/macOS builds (macOS only) - **Visual Studio 2022** or **VS Code** with C# extension @@ -85,19 +85,19 @@ dotnet restore HihaArvio.sln dotnet build HihaArvio.sln -c Release # Run tests -dotnet test HihaArvio.sln -f net8.0 +dotnet test tests/HihaArvio.Tests/HihaArvio.Tests.csproj -f net9.0 ``` ### Running the App ```bash # iOS Simulator -dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-ios -c Debug +dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-ios -c Debug # Then deploy via Xcode or Visual Studio # macOS Catalyst -dotnet build src/HihaArvio/HihaArvio.csproj -f net8.0-maccatalyst -c Debug -# Then run the .app bundle from bin/Debug/net8.0-maccatalyst/ +dotnet build src/HihaArvio/HihaArvio.csproj -f net9.0-maccatalyst -c Debug +# Then run the .app bundle from bin/Debug/net9.0-maccatalyst/ ``` ## 📦 CI/CD Workflows @@ -174,20 +174,20 @@ hiha-arvio/ - ✅ **MVVM architecture** strictly followed - ✅ **Dependency injection** throughout - ✅ **Nullable reference types** enabled -- ✅ **C# 12** with modern language features +- ✅ **C# 13** with modern language features ### Building for Release ```bash # iOS dotnet publish src/HihaArvio/HihaArvio.csproj \ - -f net8.0-ios \ + -f net9.0-ios \ -c Release \ /p:ArchiveOnBuild=true # macOS Catalyst dotnet publish src/HihaArvio/HihaArvio.csproj \ - -f net8.0-maccatalyst \ + -f net9.0-maccatalyst \ -c Release \ /p:ArchiveOnBuild=true ``` diff --git a/src/HihaArvio/App.xaml.cs b/src/HihaArvio/App.xaml.cs index d10ce75..93ac48a 100644 --- a/src/HihaArvio/App.xaml.cs +++ b/src/HihaArvio/App.xaml.cs @@ -5,7 +5,10 @@ public partial class App : Application public App() { InitializeComponent(); + } - MainPage = new AppShell(); + protected override Window CreateWindow(IActivationState? activationState) + { + return new Window(new AppShell()); } } diff --git a/src/HihaArvio/HihaArvio.csproj b/src/HihaArvio/HihaArvio.csproj index 0a17e15..9d65465 100644 --- a/src/HihaArvio/HihaArvio.csproj +++ b/src/HihaArvio/HihaArvio.csproj @@ -2,11 +2,11 @@ - + - net8.0;net8.0-ios;net8.0-maccatalyst - - net8.0 + net9.0;net9.0-ios;net9.0-maccatalyst + + net9.0 - Exe - Library + Exe + Library HihaArvio - true + true true enable enable - + true - 12 + 13 HihaArvio @@ -61,11 +61,11 @@ - + - - - + + + diff --git a/tests/HihaArvio.Tests/HihaArvio.Tests.csproj b/tests/HihaArvio.Tests/HihaArvio.Tests.csproj index 322654d..8748278 100644 --- a/tests/HihaArvio.Tests/HihaArvio.Tests.csproj +++ b/tests/HihaArvio.Tests/HihaArvio.Tests.csproj @@ -1,25 +1,25 @@ - net8.0 + net9.0 enable enable false true - + true - 12 + 13 - + - + - - + + diff --git a/tests/HihaArvio.Tests/TestResults/a7530e2d-8631-4bd5-9898-59b8cf8b73ed/coverage.cobertura.xml b/tests/HihaArvio.Tests/TestResults/a7530e2d-8631-4bd5-9898-59b8cf8b73ed/coverage.cobertura.xml deleted file mode 100644 index b98f483..0000000 --- a/tests/HihaArvio.Tests/TestResults/a7530e2d-8631-4bd5-9898-59b8cf8b73ed/coverage.cobertura.xml +++ /dev/null @@ -1,490 +0,0 @@ - - - - /Users/ivuorinen/Code/ivuorinen/hiha-arvio/src/HihaArvio/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file