Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
144 commits
Select commit Hold shift + click to select a range
35b5399
Extract dependencies
MilosKozak Aug 5, 2026
67ecb1e
Going KMP
MilosKozak Aug 5, 2026
1aed547
cleanup
MilosKozak Aug 5, 2026
5b3bfe0
Merge branch 'dev' into kmp/core-data-experiment
MilosKozak Aug 5, 2026
e244762
Prepare :core:nssdk
MilosKozak Aug 6, 2026
f6a4e85
:core:nssdk org.json -> kotlinx
MilosKozak Aug 6, 2026
350f486
:core:nssdk Gson -> kotlinx.serialization
MilosKozak Aug 6, 2026
cb7b8fa
:core:nssdk date parsing, eliminate joda
MilosKozak Aug 6, 2026
e92ec08
:core:nssdk tests
MilosKozak Aug 6, 2026
ed9c875
:core:nssdk ktor migration
MilosKozak Aug 6, 2026
37e1468
4.0.0-dev-b-kmp
MilosKozak Aug 6, 2026
e44f2f8
:core:nssdk kmp
MilosKozak Aug 6, 2026
307b1ed
TextRef
MilosKozak Aug 7, 2026
defd131
:core:keys Eliminate dependencies
MilosKozak Aug 7, 2026
95da0fa
more TextRef migration
MilosKozak Aug 8, 2026
6fdb924
:core:keys String migration
MilosKozak Aug 8, 2026
7e735f6
Update progress
MilosKozak Aug 8, 2026
c8c1069
Fix Danish language selection
MilosKozak Aug 9, 2026
29dd6ff
:core:keys TextRef.Named
MilosKozak Aug 9, 2026
eeddd81
:core:keys kmp
MilosKozak Aug 9, 2026
9667f80
Update progress
MilosKozak Aug 9, 2026
a4291a1
:core:data ios target
MilosKozak Aug 9, 2026
01678c4
:core:nssdk ios target
MilosKozak Aug 9, 2026
47798f9
:core:data commonTest
MilosKozak Aug 9, 2026
16b6e90
Update progress
MilosKozak Aug 9, 2026
504de93
Fix kmp modules coverage
MilosKozak Aug 9, 2026
db78c3c
Merge remote-tracking branch 'origin/dev' into kmp
MilosKozak Aug 9, 2026
e115e40
:core:data platform parity tests
MilosKozak Aug 9, 2026
08f5384
ios CI
MilosKozak Aug 9, 2026
c017e46
ios CI run tests in a real timezone
MilosKozak Aug 9, 2026
eb06d8d
Update progress
MilosKozak Aug 9, 2026
007da56
:core:data commonMain assert
MilosKozak Aug 9, 2026
e6d645e
cmp spike
MilosKozak Aug 9, 2026
f400188
:core:ui TextRef.Named
MilosKozak Aug 10, 2026
f2cd4b8
:core:ui element labels
MilosKozak Aug 10, 2026
b64c3e1
:core:ui resource ids
MilosKozak Aug 10, 2026
2e0dcd0
:core:ui java cleanup
MilosKozak Aug 10, 2026
fff1704
:core:ui dead res imports
MilosKozak Aug 10, 2026
1d8dfb4
:core:ui compose paths
MilosKozak Aug 10, 2026
4ad47d7
:core:ui more blockers
MilosKozak Aug 10, 2026
4a34333
:core:nssdk restore examples.json formatting
MilosKozak Aug 10, 2026
f184269
Remove CMP spike
MilosKozak Aug 10, 2026
7ba30dc
:core:interfaces TextRef for data enums
MilosKozak Aug 10, 2026
8e928f3
Shared org.json compat shim with parity tests
MilosKozak Aug 10, 2026
ba3c465
:core:interfaces kotlinx-datetime instead of java.time and joda
MilosKozak Aug 10, 2026
f27e8b5
Update KMP doc
MilosKozak Aug 10, 2026
8bca337
:core:interfaces drop vestigial Parcelable
MilosKozak Aug 10, 2026
8e624a5
Remove dead View based stats code
MilosKozak Aug 10, 2026
b3bf363
:core:interfaces eliminate redundant Context parameters
MilosKozak Aug 10, 2026
ce8d14a
:core:interfaces EventStatus returns TextRef
MilosKozak Aug 11, 2026
b092230
:core:interfaces Clock instead of System.currentTimeMillis
MilosKozak Aug 11, 2026
d54f5c5
:pump:virtual delay instead of blocking sleep
MilosKozak Aug 11, 2026
02c9032
:core:interfaces remove dead pump layer members
MilosKozak Aug 11, 2026
6eb7f8c
:core:utils is multiplatform
MilosKozak Aug 11, 2026
f0142bc
:core:interfaces TextRef for notification and permission text
MilosKozak Aug 11, 2026
d143b22
TimeDiff instead of TimeUnit map
MilosKozak Aug 11, 2026
53c7942
BolusProgressState carries TextRef
MilosKozak Aug 11, 2026
373bac2
BolusProgressData provided instead of annotated
MilosKozak Aug 12, 2026
c88bac5
Mark CustomAction as intentionally kept
MilosKozak Aug 12, 2026
d23b9be
Characterize profile JSON before conversion
MilosKozak Aug 12, 2026
74644c7
Add real Nightscout shapes to profile characterization
MilosKozak Aug 12, 2026
419e949
Write side differences are benign, record why
MilosKozak Aug 12, 2026
fbc5449
Profile schedule parsing moves to kotlinx
MilosKozak Aug 12, 2026
9b215a8
Target range parsing moves to kotlinx
MilosKozak Aug 12, 2026
eb61bef
Block and TargetBlock are immutable
MilosKozak Aug 12, 2026
01f4ddb
Profiles as Kotlin objects, JSON only at the storage and Nightscout e…
MilosKozak Aug 13, 2026
37a9ced
Replace Spanned with AnnotatedString, drop the unused APS result rend…
MilosKozak Aug 13, 2026
a7b79f9
Four core:interfaces files off JVM-only types
MilosKozak Aug 13, 2026
d8b74a5
Alarm sounds as an enum instead of raw resource ids
MilosKozak Aug 13, 2026
f08dda8
ProfileStore and PairProfileStore on kotlinx JSON
MilosKozak Aug 13, 2026
6918193
toPureNsJson on kotlinx JSON, with profile and Autotune coverage
MilosKozak Aug 13, 2026
fff05a5
Command takes a result factory instead of a Dagger Provider
MilosKozak Aug 14, 2026
3128760
Temp target presets, version definition and NS log on kotlinx JSON
MilosKozak Aug 14, 2026
d6c31fa
Pump status JSON on kotlinx, driver returns its extended entries
MilosKozak Aug 14, 2026
986f790
Remove NSSettingsStatus, which never received any data
MilosKozak Aug 14, 2026
aff51ea
Last org.json out of core:interfaces: exportApsResult and APSResult.json
MilosKozak Aug 14, 2026
a1ff557
Declare androidx.collection 1.6.0 instead of resolving it transitively
MilosKozak Aug 14, 2026
9ba7d1a
Round without BigDecimal or InvalidParameterException
MilosKozak Aug 14, 2026
c42bde3
Make :core:interfaces a multiplatform module
MilosKozak Aug 14, 2026
240a0f0
Fix crash on start when a remote config fetch succeeds
MilosKozak Aug 14, 2026
6197dd9
Give :core:interfaces its Apple targets
MilosKozak Aug 14, 2026
96e08ee
Pull the icon-only interfaces back into commonMain
MilosKozak Aug 14, 2026
f14a70d
DetailedBolusInfo to commonMain, missingPermissions to an extension
MilosKozak Aug 14, 2026
bd09777
XdripPlugin listens on Flow instead of Observable
MilosKozak Aug 15, 2026
333ac80
TizenPlugin and TidepoolPlugin listen on Flow
MilosKozak Aug 15, 2026
2fffeea
Close the subscription window when collecting the event bus
MilosKozak Aug 15, 2026
a6d423d
DataHandlerMobile listens on Flow
MilosKozak Aug 15, 2026
84489ce
WearPlugin and DataLayerListenerServiceMobile listen on Flow
MilosKozak Aug 15, 2026
202ad40
plugins/main listens on Flow
MilosKozak Aug 15, 2026
f42e953
plugins/automation and plugins/configuration listen on Flow
MilosKozak Aug 15, 2026
fe80b5c
Wear: listen with Flow instead of Rx Observable
MilosKozak Aug 15, 2026
d32e00f
ui, constraints, sync: listen with Flow instead of Rx Observable
MilosKozak Aug 15, 2026
09667d6
Dana pumps: listen with Flow instead of Rx Observable
MilosKozak Aug 15, 2026
717f918
DanaR pair wizard: listen with Flow instead of Rx Observable
MilosKozak Aug 15, 2026
9c5d721
Diaconn: listen with Flow instead of Rx Observable
MilosKozak Aug 15, 2026
f1ac697
Omnipod Eros: listen with Flow instead of Rx Observable
MilosKozak Aug 15, 2026
dd79366
Remaining pumps: listen with Flow instead of Rx Observable
MilosKozak Aug 15, 2026
d2a9202
RxBus: drop toObservable, the bus is Flow only now
MilosKozak Aug 15, 2026
4d83057
Clean up Rx leftovers from the Flow migration
MilosKozak Aug 15, 2026
48218de
SWItem, NSClientV3Service: drop RxJava
MilosKozak Aug 15, 2026
af715a6
ResourceHelper: drop the members nobody calls
MilosKozak Aug 15, 2026
5ab8f8e
ResourceHelper: move the last non-string members to their call sites
MilosKozak Aug 15, 2026
a9c537a
Add TextResolver, the part of ResourceHelper shared code can use
MilosKozak Aug 15, 2026
949a587
Move to commonMain everything that already compiles there
MilosKozak Aug 15, 2026
fbcbfa2
DateUtil resolves through TextResolver, and moves to commonMain
MilosKozak Aug 15, 2026
2b88e8e
NotificationManager takes a TextRef, and moves to commonMain
MilosKozak Aug 15, 2026
5443bf2
One readableDuration instead of three
MilosKozak Aug 16, 2026
57997e3
Delete the Equil duration strings, dead with their formatter
MilosKozak Aug 16, 2026
978f0ef
Events that carry data are data classes, and Event moves to commonMain
MilosKozak Aug 16, 2026
19d2329
RxBus keys on KClass, and takes 48 files to commonMain with it
MilosKozak Aug 16, 2026
687af15
PersistenceLayer.observeChanges keys on KClass
MilosKozak Aug 16, 2026
cd18389
Delete the SP.Editor resource id overloads, used only by their own test
MilosKozak Aug 16, 2026
60a80c4
Profile, PumpSync and InsulinType resolve through TextResolver
MilosKozak Aug 16, 2026
2bcf8e3
Pump, Profile, PumpSync and PumpProfile move to commonMain
MilosKozak Aug 16, 2026
8e8feb3
PluginBase.pluginId uses KClass, and drops @TestOnly
MilosKozak Aug 16, 2026
450a3e6
PluginDescription names plugins with TextRef
MilosKozak Aug 16, 2026
9d1eb07
ActivePlugin, PluginBase and the command queue reach commonMain
MilosKozak Aug 17, 2026
6b64ba9
:core:ui becomes a multiplatform module
MilosKozak Aug 17, 2026
feddd57
HTML becomes AnnotatedString, and :core:ui reaches 348 commonMain
MilosKozak Aug 17, 2026
e63983a
:core:ui reaches 96% commonMain
MilosKozak Aug 17, 2026
358fa85
Eight :core:interfaces files were in the wrong source set
MilosKozak Aug 17, 2026
6f3493f
Split display out of the TB and EB extensions
MilosKozak Aug 17, 2026
7b4adad
Move 33 shared strings to :core:interfaces, freeing :core:objects fro…
MilosKozak Aug 17, 2026
e83ac24
Delete the dead legacy export path, moving maintenance to commonMain
MilosKozak Aug 17, 2026
b6a0260
:core:graph is fully multiplatform - 11 of 11 files in commonMain
MilosKozak Aug 17, 2026
64d08d8
Optimize imports
MilosKozak Aug 17, 2026
3085e95
Lift DI out of :core:objects so it can become multiplatform
MilosKozak Aug 17, 2026
5d993da
Move CoreObjectsModule to :app
MilosKozak Aug 17, 2026
5b41d26
:core:objects KMP + follow deprecations for Preview and BackHandler
MilosKozak Aug 18, 2026
ec05bdf
Fix lenient JSON reads and start the org.json split in :core:objects
MilosKozak Aug 18, 2026
7d26beb
Finish the org.json split in :core:objects
MilosKozak Aug 18, 2026
cd0b5b2
Remove dead json adapter and start moving the profile boundary outward
MilosKozak Aug 18, 2026
a929ae1
Move the profile path off org.json
MilosKozak Aug 18, 2026
6e5ddef
MidnightTime moves to commonMain
MilosKozak Aug 18, 2026
4661916
:core:ui preference package is fully multiplatform
MilosKozak Aug 18, 2026
e8bb095
:pump:virtual becomes a multiplatform module
MilosKozak Aug 18, 2026
b0dc89a
PumpPluginBase drops the Handler, ResourceHelper and R
MilosKozak Aug 19, 2026
0fcca75
PumpPluginBase moves to commonMain
MilosKozak Aug 19, 2026
0b5b35c
:pump:virtual is fully multiplatform
MilosKozak Aug 19, 2026
981e21a
:plugins:smoothing is fully multiplatform
MilosKozak Aug 19, 2026
3a90019
:plugins:calibration partly multiplatform, and register the new strin…
MilosKozak Aug 19, 2026
74fabe3
:plugins:calibration is multiplatform, chart stubbed off Android
MilosKozak Aug 19, 2026
d1afea4
Calibration chart placeholder says it is missing, and drop qualified …
MilosKozak Aug 19, 2026
84ecd73
:plugins:configuration drops unused parcelize and okhttp
MilosKozak Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 9 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,15 @@ jobs:
command: |
export ANDROID_SDK_ROOT=/usr/lib/android-sdk
export ANDROID_HOME=/usr/lib/android-sdk
$GRADLE_PIN ./gradlew --continue -Dorg.gradle.daemon=true -Dorg.gradle.workers.max=8 testFullDebugUnitTest
# jvmTest and testAndroidHostTest cover the multiplatform modules. They have no build
# variants, so testFullDebugUnitTest does not exist for them and their tests would
# silently not run at all - which is what happened to :core:data and :core:nssdk, and
# showed up as a Codecov drop the moment :core:keys converted too.
# Both task names are unqualified on purpose: Gradle runs them in whichever projects
# have them, so a module converting later is picked up without editing this file.
# Deliberately not `allTests`: that would pull in the Kotlin/Native toolchain for the
# mingw and iOS targets, whose tests cannot run on a Linux box anyway.
$GRADLE_PIN ./gradlew --continue -Dorg.gradle.daemon=true -Dorg.gradle.workers.max=8 testFullDebugUnitTest jvmTest testAndroidHostTest

- run:
name: Non-app module androidTests (Gradle, emu-5554)
Expand Down
137 changes: 137 additions & 0 deletions .github/workflows/ios-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: iOS CI (Kotlin/Native)

# The only place the Apple side can actually be checked.
#
# Klibs for iosArm64 / iosSimulatorArm64 cross compile on any host, so a developer on Windows or
# Linux already knows the shared code COMPILES for iOS. What no other machine can do is RUN it:
# `iosSimulatorArm64Test` is disabled off macOS with "simulator tests require macOS", and it reports
# SKIPPED rather than failing, so a green build elsewhere says nothing about iOS behaviour.
#
# That gap matters most for the four platform actuals under the shared data spine. `utcOffset` is
# written to every record, takes part in contentEqualsTo and is validated by Nightscout, and it comes
# from NSTimeZone on Apple and TimeZone.getOffset on the JVM. NumberFormatParityTest and
# SystemTimeZoneTest in commonTest exist to compare them; this job is where they finally execute.
#
# No secrets: nothing is signed, published or uploaded.

on:
workflow_dispatch:
push:
paths:
- 'core/data/**'
- 'core/nssdk/**'
- 'core/keys/**'
- 'gradle/libs.versions.toml'
- 'buildSrc/**'
- '.github/workflows/ios-ci.yml'
pull_request:
paths:
- 'core/data/**'
- 'core/nssdk/**'
- 'core/keys/**'
- 'gradle/libs.versions.toml'
- 'buildSrc/**'

jobs:
ios:
runs-on: macos-latest
timeout-minutes: 60

steps:
- uses: actions/checkout@v5
with:
fetch-depth: 1

- name: Load jdk version
run: |
JAVA_VERSION=$(jq -r '.default' .github/jdk-map.json)
echo "JAVA_VERSION=$JAVA_VERSION" >> $GITHUB_ENV

- name: Set up JDK
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'temurin'
cache: gradle

# Kotlin/Native downloads its own toolchain on first use; without this every run pays for it.
- name: Cache Kotlin/Native
uses: actions/cache@v4
with:
path: ~/.konan
key: konan-${{ runner.os }}-${{ hashFiles('gradle/libs.versions.toml') }}
restore-keys: konan-${{ runner.os }}-

- name: Compile the Apple targets
run: |
# Actions runs `bash -e` but NOT pipefail, so without this the exit code of the pipeline
# would be tee's and a failed Gradle build would report success.
set -o pipefail
./gradlew --console=plain --no-daemon \
:core:data:compileKotlinIosArm64 :core:data:compileKotlinIosSimulatorArm64 \
:core:nssdk:compileKotlinIosArm64 :core:nssdk:compileKotlinIosSimulatorArm64 \
:core:keys:compileKotlinIosArm64 :core:keys:compileKotlinIosSimulatorArm64 \
| tee compile.log

# A disabled Kotlin/Native task reports SKIPPED and still exits 0, so "BUILD SUCCESSFUL" alone
# would stay green even if the whole Apple side silently stopped building. Cross-compilability
# is also transitive: a single cinterop anywhere in the project dependency graph turns these
# into no-ops. Assert the work happened rather than that nothing complained.
- name: Assert the Apple compiles really ran
run: |
if grep -E "Task :core:(data|nssdk|keys):compileKotlinIos(Arm64|SimulatorArm64) (SKIPPED|NO-SOURCE)" compile.log; then
echo "::error::An iOS compile task was skipped instead of executed."
exit 1
fi
for m in data nssdk keys; do
for t in iosArm64 iosSimulatorArm64; do
MANIFEST=$(find core/$m/build/classes/kotlin/$t/main/klib -name manifest 2>/dev/null | head -1)
if [ -z "$MANIFEST" ]; then
echo "::error::core/$m produced no $t klib"
exit 1
fi
echo "core/$m $t -> $(grep native_targets "$MANIFEST")"
done
done

# The part that only exists here. commonTest runs through Kotlin/Native against the real
# NSNumberFormatter and NSTimeZone, which is what no other host can do.
#
# Only :core:data has commonTest today, so it is the one module asserted below. The other two
# are still run: if either grows shared tests later they start executing here with no change to
# this file, and until then they are simply NO-SOURCE.
- name: Run the shared tests on the iOS simulator
# GitHub's macOS runners are UTC, and at UTC every assertion in SystemTimeZoneTest passes
# trivially - the offset is zero whatever unit it is in, so a seconds-instead-of-milliseconds
# bug in the NSTimeZone actual would sail straight through. Pin a zone that has both a
# non-zero offset and daylight saving, so the whole-minutes, range and whole-hour-DST
# assertions actually mean something. Foundation honours TZ on macOS, as does the JVM.
env:
TZ: Europe/Prague
run: |
set -o pipefail
echo "Running with TZ=$TZ"
./gradlew --console=plain --no-daemon \
:core:data:iosSimulatorArm64Test :core:nssdk:iosSimulatorArm64Test :core:keys:iosSimulatorArm64Test \
| tee test.log

- name: Assert the iOS tests really ran
run: |
if grep -E "Task :core:data:iosSimulatorArm64Test (SKIPPED|NO-SOURCE)" test.log; then
echo "::error::Module core:data had its iOS tests skipped instead of executed. On macOS they must run."
exit 1
fi
FOUND=$(find core/data/build/test-results/iosSimulatorArm64Test -name "TEST-*.xml" 2>/dev/null | wc -l)
echo "iOS test result files for :core:data: $FOUND"
[ "$FOUND" -gt 0 ] || { echo "::error::No iOS test results were produced."; exit 1; }
# Surface the counts, so a run that executed zero assertions is visible in the log.
grep -ho 'tests="[0-9]*" skipped="[0-9]*" failures="[0-9]*" errors="[0-9]*"' \
core/data/build/test-results/iosSimulatorArm64Test/TEST-*.xml || true

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: ios-test-results
path: core/*/build/test-results/iosSimulatorArm64Test/**
if-no-files-found: warn
Loading
Loading