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