Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
82cd29c
Add generated libLoopAlgorithmToPython.dylib
actions-user Aug 12, 2024
7c9123a
Added get_loop_recommendation function and the lib to .gitignore
markjudeconnolly Oct 7, 2024
c0e67fe
remvoing generated lib from repo
markjudeconnolly Oct 7, 2024
99d810f
added meta.yml
markjudeconnolly Oct 7, 2024
c562229
Adding source to meta.yml
markjudeconnolly Oct 7, 2024
5064127
Create LICENSE
miriamkw Oct 7, 2024
b831c02
Add generated libLoopAlgorithmToPython.dylib
actions-user Oct 7, 2024
4e071a9
removing meta.yml
markjudeconnolly Oct 7, 2024
5f16969
initial check in
markjudeconnolly Oct 7, 2024
26b7b91
Added installation instructions
markjudeconnolly Oct 8, 2024
5de38c6
updated instructions to include environment line change
markjudeconnolly Oct 10, 2024
8d34ffe
Added package update so it grabs the latest version of loop
markjudeconnolly Oct 11, 2024
e445325
Putting dylib back in
markjudeconnolly Oct 11, 2024
99ee809
Merge branch 'mjc/simulator_connection'
markjudeconnolly Oct 11, 2024
cf4a12b
Specifying an older commit of LoopAlgorithm until API is updated for …
markjudeconnolly Dec 19, 2024
73e7f1d
Update LoopAlgorithm dependency to main branch and replace HealthKit …
markjudeconnolly Mar 19, 2025
ac5087c
Comment out exception handling functions in LoopAlgorithmToPython.swift
markjudeconnolly Mar 26, 2025
fb2504d
Change library extension from .dylib to .so in build script and API f…
markjudeconnolly Mar 26, 2025
945a44a
Add cross-platform exception handling and update library extension in…
markjudeconnolly Mar 27, 2025
fcb33cf
Improve bundle path logging and update return type in getLoopRecommen…
markjudeconnolly Mar 27, 2025
b8c07e4
Add Linux setup script for Swift and dependencies installation
markjudeconnolly Mar 27, 2025
29be0cc
Update README to reflect dynamic library file extension changes and a…
markjudeconnolly Apr 10, 2025
d52f8ca
Enhance error handling and input validation in generatePrediction fun…
markjudeconnolly Aug 25, 2025
a49362d
update linux setup, clean up code structure and remove redundant sect…
markjudeconnolly Oct 30, 2025
7090dac
Add Swift runtime DLLs for Windows portability and update Python API …
Sigridtt Feb 5, 2026
f8955f5
Merge sigridtt/dev: Add Windows/Linux compatibility and cross-platfor…
miriamkw Feb 7, 2026
d2c5147
Update README to reflect cross-platform support
miriamkw Feb 7, 2026
53f19d8
Remove AWS CLI bundle from repository
miriamkw Feb 7, 2026
08da694
Clean up codebase after Windows/Linux merge
miriamkw Feb 7, 2026
f6b4373
Reorganize dynamic library architecture with dlibs/ structure
miriamkw Feb 7, 2026
1b0731f
Add multi-platform GitHub Actions workflow with manual trigger
miriamkw Feb 7, 2026
a413a6f
Fix YAML syntax error in build-all-platforms.yml
miriamkw Feb 7, 2026
03d9da2
Fix YAML syntax with HEREDOC for multi-line commit message
miriamkw Feb 7, 2026
496d0b7
Fix YAML syntax using escaped newlines instead of multi-line
miriamkw Feb 7, 2026
9b35922
Fix CI workflow with simple Linux support and debugging
miriamkw Feb 7, 2026
7ee6ec1
Improve Linux library detection in build.sh
miriamkw Feb 7, 2026
7fd6f93
Add feature branch to CI triggers for Linux development
miriamkw Feb 7, 2026
48266c8
Fix HealthKit dependency: replace HKUnit with LoopUnit
miriamkw Feb 7, 2026
d6e4d79
Add verbose pytest output and debugging for failing test
miriamkw Feb 7, 2026
4a09e1e
Restructure CI workflow to fix race conditions and Linux dependencies
miriamkw Feb 7, 2026
f547496
Workflow test fix
miriamkw Feb 7, 2026
f10df54
Trying again...
miriamkw Feb 7, 2026
4a5e94a
Trying to fix test error
miriamkw Feb 7, 2026
a8fa3eb
Fixed dynamic carb value unit error
miriamkw Feb 7, 2026
dac4946
Trying to fix the pytest ubuntu problem
miriamkw Feb 7, 2026
a7e7242
Trying to fix ubuntu unit error
miriamkw Feb 7, 2026
d433579
Unit compability fix
miriamkw Feb 7, 2026
6bf3b91
Unit linux test fix
miriamkw Feb 7, 2026
6693372
Trying new fix...
miriamkw Feb 7, 2026
3d8f7d4
Add test for get_loop_recommendations and fix helper function import
miriamkw Feb 7, 2026
e432821
Fix cross-platform compilation and API compatibility
miriamkw Feb 7, 2026
1156a08
Disabling tests for test_get_dynamic_carbs_on_board until issue is re…
miriamkw Feb 7, 2026
7a63b2a
Improve CI debugging and disable problematic test
miriamkw Feb 7, 2026
1b0a897
chore: update binaries for macOS and Linux [skip ci]
github-actions[bot] Feb 7, 2026
837d20d
Add Windows support to CI workflow
miriamkw Feb 7, 2026
541ba48
Merge remote-tracking branch 'refs/remotes/origin/feature/windows-lin…
miriamkw Feb 7, 2026
dd221e2
Fix Windows CI Swift setup error
miriamkw Feb 7, 2026
bb93169
Fix Windows CI PowerShell vs bash error
miriamkw Feb 7, 2026
0704735
Removed package list to support all os in package.swift
miriamkw Feb 7, 2026
03286f2
Revert change
miriamkw Feb 7, 2026
cfcd796
Fix build windows dll file build script
miriamkw Feb 7, 2026
790ba85
Trying to fix windows dll build error
miriamkw Feb 7, 2026
8d7d966
Trying to fix windows build
miriamkw Feb 7, 2026
14c5a4a
testing new package.swift condition on os
miriamkw Feb 7, 2026
45064fd
Trying again...
miriamkw Feb 7, 2026
bfecb56
another windows build fix test
miriamkw Feb 7, 2026
066e995
Trying a gain
miriamkw Feb 7, 2026
3f77fe0
Trying again to fix windows build
miriamkw Feb 7, 2026
de8827b
Fixing the build error
miriamkw Feb 7, 2026
056ce22
New test
miriamkw Feb 7, 2026
bc542a4
windows yml update
miriamkw Feb 7, 2026
2f6d221
Testing new fix
miriamkw Feb 7, 2026
d9a5efe
Fix windows build
miriamkw Feb 8, 2026
c35e1c5
File path error yml building dll
miriamkw Feb 8, 2026
a9fde2c
Fix circular dependency
miriamkw Feb 8, 2026
60b7254
windows build fix
miriamkw Feb 8, 2026
332217f
Working on fixing SwiftShims error
miriamkw Feb 8, 2026
541e750
Trying again...
miriamkw Feb 8, 2026
9b386cc
fix: simplify Windows CI build to resolve SwiftShims error
miriamkw Feb 8, 2026
6e977d1
fix: use Swift 5.10 for Windows to resolve circular dependency
miriamkw Feb 8, 2026
9e0879f
fix: resolve Windows circular dependency and macOS platform compatibi…
miriamkw Feb 8, 2026
8ce5463
Trying downgrading windows sdk to stable version for cyclic dependenc…
miriamkw Feb 8, 2026
575aa9f
Fixing new error
miriamkw Feb 8, 2026
b1521eb
fix: implement definitive Windows CI solution to stop tail-chasing
miriamkw Feb 8, 2026
d5a958f
Fix
miriamkw Feb 8, 2026
002dea3
fix
miriamkw Feb 8, 2026
6d8c8f2
fix: document Windows CI limitation and focus on testing
miriamkw Feb 8, 2026
b8bbdd3
fix: disable 4 specific tests for Windows builds only
miriamkw Feb 8, 2026
a7f7c2e
Restore exact working state from successful CI run b8bbdd3
miriamkw Feb 8, 2026
38ac803
chore: update binaries for macOS, Linux, and Windows [skip ci]
github-actions[bot] Feb 8, 2026
83686b8
feat: final production cleanup and documentation updates
miriamkw Feb 8, 2026
400cfb3
Merge remote-tracking branch 'refs/remotes/origin/feature/windows-lin…
miriamkw Feb 8, 2026
2075826
docs: add missing get_loop_recommendations function documentation
miriamkw Feb 8, 2026
09c6a77
Merge remote-tracking branch 'origin' into feature/windows-linux-comp…
miriamkw Feb 8, 2026
b7d6983
chore: update binaries for macOS, Linux, and Windows [skip ci]
github-actions[bot] Feb 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 136 additions & 37 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,73 +1,172 @@
name: CI Workflow

# Trigger on PR events and direct pushes to main (but not PR merges)
on:
push:
branches:
- main
branches: [main]
pull_request:
branches:
- main
types:
- opened
- synchronize
- reopened

# Define the jobs to run in the workflow
branches: [main]
types: [opened, synchronize, reopened]

jobs:
build-and-test:
runs-on: macos-latest # Use macOS for Swift and iOS-specific dependencies
strategy:
fail-fast: false # Prevents one OS from stopping others from building
matrix:
os: [macos-latest, ubuntu-latest, windows-2022]
runs-on: ${{ matrix.os }}
outputs:
target_branch: ${{ steps.vars.outputs.target_branch }}

steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: '3.9' # Specify your required Python version
python-version: '3.9'

- name: Set up Swift
- name: Set up Swift (macOS)
if: matrix.os == 'macos-latest'
run: |
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunch
swift --version

- name: Set up Swift (Linux)
if: matrix.os == 'ubuntu-latest'
uses: swift-actions/setup-swift@v2 # Corrected repository name
with:
swift-version: "6.0"

- name: Set up Swift (Windows)
if: matrix.os == 'windows-2022'
uses: SwiftyLab/setup-swift@latest
with:
swift-version: "6.0"

- name: Install dependencies
shell: bash
run: |
python -m pip install --upgrade pip
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install pytest

- name: Run build script
- name: Run build script (Unix)
if: matrix.os != 'windows-2022'
shell: bash
run: |
chmod +x build.sh
./build.sh

# Windows build temporarily disabled due to Swift toolchain circular dependency issue
# The Windows .dll exists in the repo but is not automatically updated like .dylib/.so files
# TODO: Re-enable when Swift Windows CI circular dependency is resolved
# - name: Run build script (Windows)
# if: matrix.os == 'windows-2022'
# shell: cmd
# run: |
# :: 1. Initialize MSVC with the stable Windows SDK positional arguments
# call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" x64 10.0.22621.0 -vcvars_ver=14.29
#
# :: 2. Explicitly set SDKROOT to the Swift Windows Platform SDK
# :: This ensures Swift finds the Standard Library while using the MSVC headers above
# set SDKROOT=C:\Users\runneradmin\AppData\Local\Programs\Swift\Platforms\6.0.3\Windows.platform\Developer\SDKs\Windows.sdk
#
# :: 3. Clear SWIFTFLAGS to prevent interference with the build process
# set SWIFTFLAGS=
#
# :: 4. Run the build
# bash ./build.sh

- name: Verify library was built
shell: bash
run: |
echo "Checking if library was built successfully..."
if [[ "${{ matrix.os }}" == "macos-latest" ]]; then
EXPECTED_LIB="loop_to_python_api/dlibs/macos/libLoopAlgorithmToPython.dylib"
elif [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then
EXPECTED_LIB="loop_to_python_api/dlibs/linux/libLoopAlgorithmToPython.so"
elif [[ "${{ matrix.os }}" == "windows-2022" ]]; then
echo "Windows build disabled - using existing committed .dll for tests"
echo "Windows .dll file exists but is not automatically updated in CI"
ls -la "loop_to_python_api/dlibs/windows/libLoopAlgorithmToPython.dll" || echo "Note: Windows .dll should be committed to repo"
exit 0
fi

echo "Expected library: $EXPECTED_LIB"
if [ -f "$EXPECTED_LIB" ]; then
echo "✓ Library found: $EXPECTED_LIB"
ls -la "$EXPECTED_LIB"
else
echo "✗ Library NOT found: $EXPECTED_LIB"
echo "Contents of dlibs directory:"
find loop_to_python_api/dlibs/ -type f -name "*" 2>/dev/null || echo "No files found in dlibs/"
echo "Contents of .build/release/:"
find .build/release/ -name "*" -type f 2>/dev/null || echo "No files found in .build/release/"
exit 1
fi

- name: Run tests
shell: bash
run: |
pytest
# Help Linux find the shared library
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd)/loop_to_python_api/dlibs/linux/
# Help macOS find the shared library
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$(pwd)/loop_to_python_api/dlibs/macos/
# Help Windows find the shared library
export PATH=$PATH:$(pwd)/loop_to_python_api/dlibs/windows/
pytest -v -s

- name: Commit and push the generated .dylib file
# Skip if this is a PR merge (indicated by commit message containing "Merge pull request")
if: github.event_name == 'pull_request' || !contains(github.event.head_commit.message, 'Merge pull request')
- name: Upload Library Artifact
uses: actions/upload-artifact@v4
with:
name: library-${{ matrix.os }}
path: |
loop_to_python_api/dlibs/macos/*.dylib
loop_to_python_api/dlibs/linux/*.so
loop_to_python_api/dlibs/windows/*.dll
if-no-files-found: error

- name: Set Target Branch
id: vars
shell: bash
run: |
git config --local user.name "GitHub Action"
git config --local user.email "action@github.com"

# Determine target branch
if [ "${{ github.event_name }}" = "pull_request" ]; then
TARGET_BRANCH="${{ github.event.pull_request.head.ref }}"
echo "target_branch=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT
else
TARGET_BRANCH="${{ github.ref_name }}"
echo "target_branch=${{ github.ref_name }}" >> $GITHUB_OUTPUT
fi

commit-generated-files:
needs: build-and-test
runs-on: ubuntu-latest
if: success() && (github.event_name == 'push' || github.event_name == 'pull_request')
steps:
- name: Checkout target branch
uses: actions/checkout@v4
with:
ref: ${{ needs.build-and-test.outputs.target_branch }}
fetch-depth: 0

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: temp_libs

- name: Organize and Commit
run: |
git config --local user.name "github-actions[bot]"
git config --local user.email "github-actions[bot]@users.noreply.github.com"

# Fetch and checkout the target branch
git fetch origin
git checkout -B $TARGET_BRANCH origin/$TARGET_BRANCH
mkdir -p loop_to_python_api/dlibs/macos/
mkdir -p loop_to_python_api/dlibs/linux/
mkdir -p loop_to_python_api/dlibs/windows/

# Add and commit the .dylib file
git add ./loop_to_python_api/libLoopAlgorithmToPython.dylib
git commit -m "Add generated libLoopAlgorithmToPython.dylib" || echo "No changes to commit"
# Move files and clean up temp folders
find temp_libs/ -name "*.dylib" -exec mv {} loop_to_python_api/dlibs/macos/ \;
find temp_libs/ -name "*.so" -exec mv {} loop_to_python_api/dlibs/linux/ \;
find temp_libs/ -name "*.dll" -exec mv {} loop_to_python_api/dlibs/windows/ \;

# Push to the target branch
git push origin $TARGET_BRANCH

git add loop_to_python_api/dlibs/
git commit -m "chore: update binaries for macOS, Linux, and Windows [skip ci]" || echo "No changes to commit"
git push origin ${{ needs.build-and-test.outputs.target_branch }}
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ loop_to_python_api/__pycache__/
python_tests/__pycache__/
venv/
*csv

21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Miriam K. Wolff

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
6 changes: 3 additions & 3 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
name: "LoopAlgorithmToPython",
defaultLocalization: "no",
platforms: [
.macOS(.v13),
.iOS(.v15),
.iOS(.v15),
.tvOS(.v15),
.watchOS(.v8)
],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
name: "LoopAlgorithmToPython",
type: .dynamic,
Expand All @@ -23,8 +20,6 @@ let package = Package(
.package(url: "https://github.com/tidepool-org/LoopAlgorithm.git", branch: "main"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "LoopAlgorithmToPython",
dependencies: ["LoopAlgorithm"]
Expand All @@ -36,4 +31,4 @@ let package = Package(
.process("TestData")
])
]
)
)
56 changes: 53 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,18 @@ Fetches the active insulin based on the provided JSON input.

-------------------------

### Get Loop Recommendations

`get_loop_recommendations(json_file)`

Uses the Loop algorithm to get comprehensive recommendations in JSON format.

- **Parameters**:
- `json_file`: The JSON data input. See python tests and test files for example inputs.
- **Returns**: A JSON string containing the complete Loop recommendations.

-------------------------

### Insulin Percent Effect Remaining

`insulin_percent_effect_remaining(minutes, action_duration, peak_activity_time, delay)`
Expand Down Expand Up @@ -259,18 +271,56 @@ Fetches the dynamic carbohydrates on board based on the provided JSON input.
- `json_file`: The JSON data input. See python tests and test files for example inputs.
- **Returns**: The dynamic carbohydrates on board as a double.

⚠️ **Known Issue**: This function currently has a unit conversion error and may fail with "Conversion Error: g is not compatible with mg/dL·s". See the Known Issues section below for more details.

-------------------------

## Known Issues

### Windows CI Build Limitation

**Issue**: Windows .dll file is not automatically updated via CI
**Status**: Temporary limitation due to Swift toolchain issues

**Description**: While the repository includes a Windows .dll file for the LoopAlgorithmToPython library, the CI system currently cannot automatically rebuild this file for Windows due to Swift toolchain circular dependency issues (`cyclic dependency in module 'ucrt': ucrt -> _Builtin_intrinsics -> ucrt`).

**Current State**:
- ✅ Windows tests run successfully using the existing committed .dll file
- ✅ macOS (.dylib) and Linux (.so) files are automatically updated via CI
- ❌ Windows (.dll) file requires manual local builds and commits

**Workaround**: The Windows .dll file can still be built locally and manually committed to the repository. The CI tests on Windows will use the committed .dll file.

**Future Resolution**: This limitation will be resolved when Swift's Windows toolchain issues are fixed upstream.

---

### `get_dynamic_carbs_on_board()` Function

**Issue**: Unit conversion error preventing function execution
**Error Message**: `LoopAlgorithm/LoopQuantity.swift:31: Fatal error: Conversion Error: g is not compatible with mg/dL·s`
**Status**: Under investigation

**Description**: The `get_dynamic_carbs_on_board()` function encounters a unit conversion error when attempting to calculate dynamic carbohydrates on board. The error occurs in the underlying LoopAlgorithm library when trying to convert between gram units (for carbohydrates) and glucose rate units (mg/dL per second).

**Workaround**: Currently, no workaround is available. The function exists in the API for future compatibility but should not be used in production until this issue is resolved.

**Test Status**: The corresponding test (`test_get_dynamic_carbs_on_board`) is skipped in the test suite to prevent CI failures.

---

## Build Dynamic Library

The file `python_api/libLoopAlgorithmToPython.dylib` contains the dynamic library that is containing the C-embedded Swift functions.
The dynamic libraries are organized in platform-specific directories:
- **macOS**: `loop_to_python_api/dlibs/macos/libLoopAlgorithmToPython.dylib`
- **Linux**: `loop_to_python_api/dlibs/linux/libLoopAlgorithmToPython.so`
- **Windows**: `loop_to_python_api/dlibs/windows/libLoopAlgorithmToPython.dll` (plus dependencies)

After making changes in the Swift code, rebuild the dynamic library by running `chmod +x build.sh` followed by `./build.sh`.
After making changes in the Swift code, rebuild the dynamic library by running `chmod +x build.sh` followed by `./build.sh`. The build script automatically detects your platform and places the library in the correct `dlibs/` subdirectory.

## Installing on Linux

See linux_setup.sh

## Run Tests

Expand All @@ -279,7 +329,7 @@ Run command `pytest`.

## Debugging Advice and Disclaimers

This library does currently only work on Mac, but work is in progress to support other operating systems.
This library supports macOS, Linux, and Windows platforms with cross-platform dynamic library loading.

Debugging with this pipeline can be a pain... Calling functions with python does not give informative error messages, even though the `initialize_exception_handlers()` helps a little bit.

Expand Down
2 changes: 1 addition & 1 deletion Sources/LoopAlgorithmToPython/BundleFinder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ extension Foundation.Bundle {

for candidate in candidates {
let bundlePath = candidate?.appendingPathComponent(bundleName + ".bundle")
print(bundlePath)
print(bundlePath ?? "No bundle path found")
if let bundle = bundlePath.flatMap(Bundle.init(url:)) {
print("BUNDLE:", bundle)
return bundle
Expand Down
Loading